猫妈狗爸伴宠师小程序前端代码
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.

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