猫妈狗爸伴宠师小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
9.1 KiB

  1. <template>
  2. <up-list @scrolltolower="scrolltolower">
  3. <template v-for="(item, index) in orderList" :key="index">
  4. <view class="date-label">
  5. <view class="date-box">{{ item.date }}</view>
  6. <view class="order-tag">
  7. <template v-if="item.orders[0].status === 'completed'">已完成{{ item.orders.length }}</template>
  8. <template v-else>待上门{{ item.orders.length }}</template>
  9. </view>
  10. </view>
  11. <view class="timeline-container">
  12. <view class="timeline-line" :class="{'timeline-line-completed': item.orders[0].status === 'completed'}">
  13. </view>
  14. <up-list-item v-for="(order, orderIndex) in item.orders" :key="orderIndex">
  15. <view class="timeline-item" :class="{'item-completed': order.status === 'completed'}">
  16. <view class="timeline-dot"></view>
  17. <view class="mb28 container-list-item">
  18. <view class="order-time-tag"
  19. :class="{'order-time-tag-completed' : order.status === 'completed'}">
  20. <view class="time-box">{{ order.time }}</view>
  21. <view class="order-status">
  22. <view class="status-icon"></view>
  23. <view>
  24. <template v-if="order.status === 'completed'">已完成{{ order.count }}</template>
  25. <template v-else>待上门{{ order.count }}</template>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="container-list">
  30. <view class="flex-between flex">
  31. <view class="address-info flex">
  32. <view class="address-icon"></view>
  33. <view class="address-text">{{ order.address }}</view>
  34. </view>
  35. <view class="expand-btn" @click="toggleExpand(index, orderIndex)">
  36. {{ order.isExpanded ? '收起' : '展开' }} <text
  37. class="expand-icon">{{ order.isExpanded ? '∧' : '∨' }}</text>
  38. </view>
  39. </view>
  40. <view v-if="order.isExpanded" class="pet-info">
  41. <view class="pet-title">陪伴对象</view>
  42. <view class="pet-list">
  43. <view v-for="(pet, petIndex) in order.pets" :key="petIndex" class="pet-item">
  44. <view class="pet-avatar">
  45. <up-image width="70px" height="70px" :src="pet.avatar"
  46. shape="circle"></up-image>
  47. </view>
  48. <view class="pet-detail">
  49. <view class="pet-name">{{ pet.name }} <text
  50. class="pet-tag">{{ pet.tag }}</text></view>
  51. <view class="pet-desc">{{ pet.desc }}</view>
  52. </view>
  53. </view>
  54. </view>
  55. <view class="address-detail mb28">{{ order.fullAddress }}</view>
  56. <view class="action-buttons flex flex-between">
  57. <up-button type="primary" text="打卡" v-if="false" @click="toClock" shape="circle"
  58. class="mr20" color="var(--status-color)"></up-button>
  59. <up-button type="primary" text="查看订单详情" @click="toDetail" shape="circle"
  60. class="mr20" color="var(--status-color)"></up-button>
  61. <up-button type="primary" text="查看宠物档案" @click="toPet" shape="circle"
  62. class="mr20" color="var(--status-color)"></up-button>
  63. <up-button type="primary" text="服务档案" @click="toService" shape="circle"
  64. color="var(--status-color)"></up-button>
  65. </view>
  66. </view>
  67. </view>
  68. </view>
  69. </view>
  70. </up-list-item>
  71. </view>
  72. </template>
  73. </up-list>
  74. </template>
  75. <script setup>
  76. import {
  77. ref,
  78. reactive,
  79. defineProps
  80. } from 'vue';
  81. const {
  82. list
  83. } = defineProps({
  84. list: {
  85. type: Array,
  86. required: true
  87. },
  88. });
  89. // 模拟订单数据
  90. const orderList = reactive([{
  91. date: '12-04',
  92. orders: [{
  93. time: '12-04',
  94. count: 2,
  95. status: 'completed', // 已完成状态
  96. address: '湖南省长沙市雨花区人民东路',
  97. fullAddress: '湖南省长沙市雨花区人民东路88号',
  98. isExpanded: true,
  99. pets: [{
  100. avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png',
  101. name: '小咪',
  102. tag: '猫',
  103. desc: '中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩'
  104. },
  105. {
  106. avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png',
  107. name: 'Billion',
  108. tag: '狗',
  109. desc: '狗狗(小型狗) | 上门喂养+陪玩'
  110. }
  111. ]
  112. }]
  113. },
  114. {
  115. date: '12-05',
  116. orders: [{
  117. time: '12-05',
  118. count: 1,
  119. status: 'completed', // 已完成状态
  120. address: '湖南省长沙市雨花区人民东路',
  121. fullAddress: '湖南省长沙市雨花区人民东路88号',
  122. isExpanded: false,
  123. pets: [{
  124. avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png',
  125. name: '小黑',
  126. tag: '狗',
  127. desc: '中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩'
  128. }]
  129. }]
  130. },
  131. {
  132. date: '12-08',
  133. orders: [{
  134. time: '12-08',
  135. count: 1,
  136. status: 'pending', // 待上门状态
  137. address: '湖南省长沙市雨花区人民东路',
  138. fullAddress: '湖南省长沙市雨花区人民东路88号',
  139. isExpanded: false,
  140. pets: [{
  141. avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png',
  142. name: '小白',
  143. tag: '猫',
  144. desc: '中华田园猫 | 专业喂养+提前熟悉+陪玩'
  145. }]
  146. }]
  147. }
  148. ]);
  149. // 展开/收起订单详情
  150. function toggleExpand(dateIndex, orderIndex) {
  151. orderList[dateIndex].orders[orderIndex].isExpanded = !orderList[dateIndex].orders[orderIndex].isExpanded;
  152. }
  153. // 滚动到底部加载更多
  154. const scrolltolower = () => {
  155. // 实际项目中这里应该调用API加载更多数据
  156. console.log('加载更多数据');
  157. }
  158. // 页面跳转函数
  159. function toClock() {
  160. uni.navigateTo({
  161. url: "/otherPages/myOrdersManage/clock/index"
  162. })
  163. }
  164. function toDetail() {
  165. uni.navigateTo({
  166. url: "/otherPages/orderTakingManage/detail/index"
  167. })
  168. }
  169. function toPet() {
  170. uni.navigateTo({
  171. url: "/otherPages/orderTakingManage/pet/index"
  172. })
  173. }
  174. function toService() {
  175. uni.navigateTo({
  176. url: "/otherPages/myOrdersManage/service/index"
  177. })
  178. }
  179. </script>
  180. <style scoped lang="scss">
  181. @import "../index";
  182. .date-label {
  183. display: flex;
  184. align-items: center;
  185. margin: 20rpx 0;
  186. position: relative;
  187. z-index: 3;
  188. .date-box {
  189. background: #333333;
  190. color: #FFFFFF;
  191. padding: 8rpx 16rpx;
  192. border-radius: 8rpx;
  193. font-size: 24rpx;
  194. margin-right: 20rpx;
  195. }
  196. .order-tag {
  197. color: #7D8196;
  198. font-size: 24rpx;
  199. }
  200. }
  201. .order-time-tag {
  202. display: flex;
  203. align-items: center;
  204. background: rgba(#FFAA48, 0.2);
  205. padding: 22rpx 42rpx;
  206. .time-box {
  207. background: var(--status-color);
  208. color: #FFFFFF;
  209. padding: 4rpx 12rpx;
  210. border-radius: 8rpx;
  211. font-size: 24rpx;
  212. margin-right: 20rpx;
  213. }
  214. .order-status {
  215. display: flex;
  216. align-items: center;
  217. font-size: 24rpx;
  218. .status-icon {
  219. width: 24rpx;
  220. height: 24rpx;
  221. background: var(--status-color);
  222. border-radius: 50%;
  223. margin-right: 10rpx;
  224. }
  225. .status-icon-completed {
  226. background: #4CD964;
  227. }
  228. }
  229. }
  230. .order-time-tag-completed {
  231. background: rgba(#4CD964, 0.2);
  232. }
  233. .time-box-completed {
  234. background: #4CD964;
  235. }
  236. .address-info {
  237. display: flex;
  238. align-items: center;
  239. margin: 20rpx 0;
  240. .address-icon {
  241. width: 36rpx;
  242. height: 36rpx;
  243. background: var(--status-color);
  244. border-radius: 50%;
  245. margin-right: 12rpx;
  246. }
  247. .address-icon-completed {
  248. background: #4CD964;
  249. }
  250. .address-text {
  251. font-size: 28rpx;
  252. color: #333333;
  253. font-weight: 500;
  254. }
  255. }
  256. .expand-btn {
  257. font-size: 26rpx;
  258. color: #FFAA48;
  259. font-weight: 500;
  260. .expand-icon {
  261. margin-left: 8rpx;
  262. }
  263. }
  264. .expand-btn-completed {
  265. color: #4CD964;
  266. }
  267. .pet-info {
  268. margin-top: 20rpx;
  269. .pet-title {
  270. font-size: 28rpx;
  271. color: #333333;
  272. margin-bottom: 16rpx;
  273. }
  274. .pet-list {
  275. .pet-item {
  276. display: flex;
  277. margin-bottom: 20rpx;
  278. .pet-avatar {
  279. margin-right: 20rpx;
  280. flex-shrink: 0;
  281. }
  282. .pet-detail {
  283. .pet-name {
  284. font-size: 28rpx;
  285. color: #333333;
  286. margin-bottom: 10rpx;
  287. .pet-tag {
  288. background: var(--status-color);
  289. color: #FFFFFF;
  290. padding: 2rpx 10rpx;
  291. border-radius: 20rpx;
  292. font-size: 20rpx;
  293. margin-left: 10rpx;
  294. }
  295. }
  296. .pet-desc {
  297. font-size: 24rpx;
  298. color: #7D8196;
  299. }
  300. }
  301. }
  302. }
  303. }
  304. .address-detail {
  305. background: #F6FAFC;
  306. border-radius: 8rpx;
  307. padding: 14rpx 20rpx;
  308. font-size: 24rpx;
  309. color: #7D8196;
  310. margin: 20rpx 0;
  311. }
  312. .action-buttons {
  313. display: flex;
  314. justify-content: space-between;
  315. margin-top: 20rpx;
  316. }
  317. \t
  318. /* 时间线样式 */
  319. .timeline-container {
  320. position: relative;
  321. padding-left: 40rpx;
  322. margin-bottom: 30rpx;
  323. z-index: 1;
  324. }
  325. .timeline-line {
  326. position: absolute;
  327. left: 20rpx;
  328. top: 0;
  329. height: 100%;
  330. width: 2rpx;
  331. background-color: #FFAA48;
  332. z-index: 0;
  333. }
  334. .timeline-line-completed {
  335. background-color: #4CD964;
  336. }
  337. .timeline-item {
  338. position: relative;
  339. padding-left: 30rpx;
  340. margin-bottom: 20rpx;
  341. }
  342. .timeline-dot {
  343. position: absolute;
  344. left: -10rpx;
  345. top: 30rpx;
  346. width: 20rpx;
  347. height: 20rpx;
  348. border-radius: 50%;
  349. background-color: #FFAA48;
  350. z-index: 2;
  351. border: 4rpx solid #FFF;
  352. }
  353. .timeline-dot-completed {
  354. background-color: #4CD964;
  355. }
  356. /* 默认状态颜色变量 */
  357. .timeline-item {
  358. --status-color: #FFAA48;
  359. }
  360. /* 添加状态类,集中控制样式 */
  361. .item-completed {
  362. --status-color: #4CD964;
  363. }
  364. </style>