敢为人鲜小程序前端代码仓库
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.

441 lines
10 KiB

5 months ago
5 months ago
5 months ago
1 month ago
1 month ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
1 month ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
3 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. <template>
  2. <view class="page">
  3. <!-- 导航栏 -->
  4. <navbar title=" " bgColor="#019245" color="#fff" />
  5. <!-- 搜索框 -->
  6. <view class="search-box" style="background-color: #fff; padding: 12rpx 20rpx 0rpx; ">
  7. <uv-search placeholder="搜索商品名" v-model="keyword" :showAction="false" actionText="" height="80rpx" animation
  8. bgColor="#F5F5F5" inputAlign="center" color="#000" placeholderColor="#979797"
  9. searchIconSize="50rpx"></uv-search>
  10. </view>
  11. <!-- 订单筛选 -->
  12. <view class="tabs">
  13. <uv-tabs :list="tabs" :activeStyle="{ color: '#019245'}" lineColor="#019245" :scrollable="false"
  14. :inactiveStyle="{color: 'black'}" lineHeight="6rpx" lineWidth="55rpx" :current="current"
  15. @tap="clickTabs" />
  16. </view>
  17. <!-- 团餐列表 -->
  18. <view class="group-meal-list" v-if="identity">
  19. <view class="meal-item" v-for="(meal, index) in groupMeals" :key="index+meal.id">
  20. <view class="meal-name">{{ meal.name }}</view>
  21. <view class="meal-price">本单佣金合计: <text class="price-value">¥{{meal.price}}</text></view>
  22. <view class="meal-action">
  23. <button class="order-btn" @tap="viewOrder(meal)">查看订单</button>
  24. </view>
  25. </view>
  26. </view>
  27. <!-- 订单列表 -->
  28. <view class="order-list" v-else>
  29. <OrderItem v-for="(order, index) in orderList" :key="order.id" :order="order" @cancel="handleCancelOrder"
  30. @pay="handlePayOrder" @tap="goToOrderDetail(order)" />
  31. <view style="margin-top: 200rpx; min-width: 700rpx;">
  32. <uv-empty mode="order" v-if="orderList.length == 0"></uv-empty>
  33. </view>
  34. </view>
  35. <!-- <view class="list">
  36. <view class="item" v-for="(item, index) in list" @tap="toOrderDetail(item.id)" :key="index">
  37. <view class="content" :key="index" v-for="(good, index) in item.commonOrderSkuList">
  38. <view class="top">
  39. <view class="service">
  40. {{ good.title }}
  41. </view>
  42. <view class="status">
  43. <text> {{ tabs[Number(item.state) + 1].name }}</text>
  44. </view>
  45. </view>
  46. <view class="main">
  47. <view class="left">
  48. <image mode="aspectFill" :src="good.image && good.image.split(',')[0]"></image>
  49. </view>
  50. <view class="right">
  51. <view class="text-hidden-1">
  52. 客户姓名{{item.name}}
  53. </view>
  54. <view class="text-hidden-1">
  55. 下单时间{{item.createTime}}
  56. </view>
  57. <view class="text-hidden-1">
  58. 联系电话{{item.phone}}
  59. </view>
  60. </view>
  61. </view>
  62. </view>
  63. <view class="bottom">
  64. <view class="price">
  65. <text class="total-title">总价格</text>
  66. <text class="unit"></text>
  67. <text class="num">{{item.price}}</text>
  68. <text class="c-unit"></text>
  69. </view>
  70. <view @tap.stop="toPayOrder(item)" class="btn" v-if="item.state == 0">
  71. 立即付款
  72. </view>
  73. <view @tap.stop="cancelOrder(item)" class="btn" v-if="item.state == 0">
  74. 取消订单
  75. </view>
  76. <view class="btn" @tap.stop="confirmOrder(item)" v-if="item.state == 2">
  77. 确认收货
  78. </view>
  79. <view @tap.stop="$refs.customerServicePopup.open()" class="btn" v-if="item.state > 0">
  80. 联系客服
  81. </view>
  82. </view>
  83. </view>
  84. <view style="
  85. margin-top: 20rpx;
  86. min-width: 700rpx;">
  87. <uv-empty mode="list" v-if="list.length == 0"></uv-empty>
  88. </view>
  89. </view> -->
  90. <customerServicePopup ref="customerServicePopup" />
  91. <tabber select="order" />
  92. </view>
  93. </template>
  94. <script>
  95. import {
  96. mapGetters
  97. } from 'vuex'
  98. import mixinsList from '@/mixins/list.js'
  99. import mixinsOrder from '@/mixins/order.js'
  100. import tabber from '@/components/base/tabbar.vue'
  101. import customerServicePopup from '@/components/config/customerServicePopup.vue'
  102. import OrderItem from '@/components/order/OrderItem.vue'
  103. import { mockOrders, mockGroupMeals} from '@/static/js/mockOrders.js'
  104. export default {
  105. mixins: [mixinsList, mixinsOrder],
  106. components: {
  107. tabber,
  108. customerServicePopup,
  109. OrderItem
  110. },
  111. computed: {},
  112. data() {
  113. return {
  114. keyword: '',
  115. tabs: [{
  116. name: '待支付'
  117. },
  118. {
  119. name: '待出餐'
  120. },
  121. {
  122. name: '送餐中'
  123. },
  124. {
  125. name: '待取餐'
  126. },
  127. {
  128. name: '已完成'
  129. }
  130. ],
  131. statusMap: {
  132. 0: 'pending', // 待支付
  133. 1: 'processing', // 待出餐
  134. 2: 'shipping', // 送餐中
  135. 3: 'delivered', // 待取餐
  136. 4: 'completed' // 已完成
  137. },
  138. current: 0,
  139. mixinsListApi: 'getOrderPageList',
  140. orderList: [],
  141. groupMeals: [],
  142. identity: uni.getStorageSync('identity')
  143. }
  144. },
  145. onLoad(args) {
  146. if (args.status) {
  147. // 因为传过来的是状态 所以需要 遍历Map找到下标
  148. for (const key in this.statusMap) {
  149. if (this.statusMap[key] === args.status) {
  150. this.current = Number(key)
  151. break
  152. }
  153. }
  154. this.clickTabs({
  155. index: this.current
  156. })
  157. }
  158. // 加载模拟订单数据
  159. this.loadMockOrders()
  160. this.filterOrdersByStatus(this.current)
  161. },
  162. methods: {
  163. //点击tab栏
  164. clickTabs({
  165. index
  166. }) {
  167. if (index == 0) {
  168. delete this.queryParams.state
  169. } else {
  170. this.queryParams.state = index - 1
  171. }
  172. // 关闭请求
  173. // this.getData()
  174. // 模拟根据状态筛选订单
  175. this.filterOrdersByStatus(index)
  176. },
  177. // 跳转到新订单详情页
  178. goToOrderDetail(order) {
  179. if (order.status === 'completed') {
  180. this.$utils.navigateTo({
  181. url: '/pages_order/order/newOrderDetail?id=' + order.id + '&status=' + order.status
  182. })
  183. } else {
  184. this.$utils.navigateTo({
  185. url: '/pages_order/order/newOrderDetail?id=' + order.id + '&status=' + order.status
  186. })
  187. }
  188. },
  189. // 查看团餐订单
  190. viewOrder(meal) {
  191. this.$utils.navigateTo({
  192. url: '/pages_order/order/groupMealDetail?id=' + meal.id + '&status=' + meal.status
  193. })
  194. },
  195. // 加载模拟订单数据
  196. loadMockOrders() {
  197. this.orderList = mockOrders
  198. this.groupMeals = mockGroupMeals
  199. },
  200. // 根据状态筛选订单
  201. filterOrdersByStatus(index) {
  202. this.loadMockOrders() // 先重置数据
  203. // if (index === 0) return // 全部订单不需要筛选
  204. const targetStatus = this.statusMap[index]
  205. if (targetStatus) {
  206. this.orderList = this.orderList.filter(order => order.status === targetStatus)
  207. this.groupMeals = this.groupMeals.filter(meal => meal.status === targetStatus)
  208. }
  209. },
  210. // 处理取消订单
  211. handleCancelOrder(orderId) {
  212. uni.showModal({
  213. title: '提示',
  214. content: '确定要取消订单吗?',
  215. success: (res) => {
  216. if (res.confirm) {
  217. // 模拟取消订单API调用
  218. uni.showToast({
  219. title: '订单已取消',
  220. icon: 'success'
  221. })
  222. // 更新订单状态
  223. const orderIndex = this.orderList.findIndex(item => item.id === orderId)
  224. if (orderIndex !== -1) {
  225. this.orderList[orderIndex].status = 'canceled'
  226. // 如果当前标签页不是全部或已取消,则移除该订单
  227. if (this.current !== 0 && this.current !== 5) {
  228. this.orderList.splice(orderIndex, 1)
  229. }
  230. }
  231. }
  232. }
  233. })
  234. },
  235. // 处理支付订单
  236. handlePayOrder(orderId) {
  237. uni.showToast({
  238. title: '正在跳转支付...',
  239. icon: 'loading'
  240. })
  241. // 模拟支付操作,实际项目中应调用支付API
  242. setTimeout(() => {
  243. uni.hideToast()
  244. uni.showToast({
  245. title: '支付成功',
  246. icon: 'success'
  247. })
  248. // 更新订单状态
  249. const orderIndex = this.orderList.findIndex(item => item.id === orderId)
  250. if (orderIndex !== -1) {
  251. this.orderList[orderIndex].status = 'processing'
  252. // 如果当前标签页不是全部或待发货,则移除该订单
  253. if (this.current !== 0 && this.current !== 2) {
  254. this.orderList.splice(orderIndex, 1)
  255. }
  256. }
  257. }, 1500)
  258. }
  259. }
  260. }
  261. </script>
  262. <style scoped lang="scss">
  263. .page {}
  264. .tabs {
  265. background: #fff;
  266. padding-bottom: 4rpx;
  267. }
  268. .order-list {
  269. padding: 0 20rpx;
  270. // position: relative;
  271. }
  272. /* 团餐列表样式 */
  273. .group-meal-list {
  274. padding: 20rpx;
  275. }
  276. .meal-item {
  277. display: flex;
  278. justify-content: space-between;
  279. align-items: center;
  280. padding: 30rpx 20rpx;
  281. background-color: #fff;
  282. margin-bottom: 20rpx;
  283. border-radius: 10rpx;
  284. }
  285. .meal-info {
  286. flex: 1;
  287. }
  288. .meal-name {
  289. font-size: 32rpx;
  290. font-weight: 500;
  291. margin-bottom: 10rpx;
  292. }
  293. .meal-price {
  294. font-size: 28rpx;
  295. color: $uni-color;
  296. background-color: #ECFEF4;
  297. padding: 10rpx 20rpx;
  298. border-radius: 10rpx;
  299. }
  300. .price-value {
  301. margin-left: 10rpx;
  302. font-weight: 500;
  303. }
  304. .meal-action {
  305. margin-left: 20rpx;
  306. }
  307. .order-btn {
  308. background-color: $uni-color;
  309. color: #fff;
  310. font-size: 28rpx;
  311. padding: 10rpx 30rpx;
  312. border-radius: 30rpx;
  313. line-height: 1.5;
  314. min-width: 160rpx;
  315. }
  316. .list {
  317. .item {
  318. width: calc(100% - 40rpx);
  319. background-color: #fff;
  320. margin: 20rpx;
  321. box-sizing: border-box;
  322. border-radius: 16rpx;
  323. padding: 30rpx;
  324. .content {
  325. .top {
  326. display: flex;
  327. justify-content: space-between;
  328. align-items: center;
  329. font-size: 34rpx;
  330. .status {
  331. font-weight: 600;
  332. color: #FFAC2F;
  333. flex-shrink: 0;
  334. margin-left: 20rpx;
  335. }
  336. }
  337. .main {
  338. display: flex;
  339. margin: 20rpx 0rpx;
  340. .left {
  341. display: flex;
  342. align-items: center;
  343. justify-content: center;
  344. width: 180rpx;
  345. height: 180rpx;
  346. image {
  347. width: 95%;
  348. height: 95%;
  349. border-radius: 10rpx;
  350. }
  351. }
  352. .right {
  353. display: flex;
  354. flex-direction: column;
  355. justify-content: space-between;
  356. width: calc(100% - 200rpx);
  357. color: #777;
  358. font-size: 26rpx;
  359. padding: 30rpx 20rpx;
  360. box-sizing: border-box;
  361. margin-left: 20rpx;
  362. border-radius: 10rpx;
  363. background-color: #F8F8F8;
  364. }
  365. }
  366. }
  367. .bottom {
  368. display: flex;
  369. justify-content: space-between;
  370. font-size: 25rpx;
  371. .price {
  372. .total-title {}
  373. .num {
  374. font-size: 36rpx;
  375. }
  376. .num,
  377. .unit,
  378. .c-unit {
  379. color: $uni-color;
  380. }
  381. }
  382. .btn {
  383. border: 1px solid #C7C7C7;
  384. padding: 10rpx 20rpx;
  385. border-radius: 40rpx;
  386. color: #575757;
  387. }
  388. }
  389. }
  390. }
  391. </style>