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

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