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

378 lines
13 KiB

1 week ago
  1. <template>
  2. <view class="page">
  3. <!-- 导航栏 -->
  4. <navbar title="订单管理" bgColor="#019245" color="#fff" />
  5. <!-- 搜索框 -->
  6. <view 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" searchIconSize="50rpx"
  9. @search="handleSearch" @clickIcon="handleSearch" />
  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="status"
  15. @click="clickTabs" />
  16. </view>
  17. <!-- 批量操作区域 -->
  18. <view class="batch-actions" v-if="leaderOrderList.length > 0">
  19. <checkbox-group @change="handleCheckAllChange">
  20. <label class="checkbox-all">
  21. <checkbox :checked="isAllChecked" color="#019245" />
  22. <text>全选</text>
  23. </label>
  24. </checkbox-group>
  25. <view class="batch-btns">
  26. <button class="batch-btn" @tap="handleBatchAction('出餐')" v-if="status === 0">批量出餐</button>
  27. <button class="batch-btn" @tap="handleBatchAction('取餐')" v-if="status === 1">批量待取餐</button>
  28. <button class="batch-btn" @tap="handleBatchAction('完成')" v-if="status === 2">批量完成</button>
  29. </view>
  30. </view>
  31. <!-- 团餐列表 -->
  32. <view class="group-meal-list">
  33. <view class="meal-item" v-for="(meal, index) in leaderOrderList" :key="meal.id">
  34. <view class="meal-checkbox">
  35. <checkbox :checked="checkedOrders.includes(meal.id)" :value="meal.id" color="#019245" @tap.stop="toggleCheckOrder(meal.id)" />
  36. </view>
  37. <view class="meal-content" @tap="viewOrder(meal)">
  38. <view class="meal-name">{{ meal.title }}</view>
  39. <view class="meal-price">本单佣金合计: <text class="price-value">¥{{ (meal.commission || 0).toFixed(2) || 0.00 }}</text>
  40. </view>
  41. </view>
  42. <view class="meal-action">
  43. <button class="action-btn" @tap.stop="handleSingleAction(meal, '出餐')" v-if="status === 0">出餐</button>
  44. <button class="action-btn" @tap.stop="handleSingleAction(meal, '取餐')" v-if="status === 2">取餐</button>
  45. <button class="action-btn" @tap.stop="handleSingleAction(meal, '完成')" v-if="status === 2">完成</button>
  46. <button class="order-btn" @tap.stop="viewOrder(meal)">查看</button>
  47. </view>
  48. </view>
  49. <view style="margin-top: 200rpx; min-width: 700rpx;">
  50. <uv-empty mode="order" v-if="leaderOrderList.length == 0" />
  51. </view>
  52. </view>
  53. <tabber select="order" />
  54. </view>
  55. </template>
  56. <script>
  57. import mixinsList from '@/mixins/list.js'
  58. import tabber from '@/components/base/tabbar.vue'
  59. export default {
  60. mixins: [mixinsList],
  61. components: {
  62. tabber
  63. },
  64. data() {
  65. return {
  66. keyword: '',
  67. title: '',
  68. tabs: [
  69. { name: '待出餐' },
  70. { name: '已出餐' },
  71. { name: '待取餐' },
  72. { name: '已完成' }
  73. ],
  74. status: 0,
  75. leaderOrderList: [],
  76. mixinsListApi: 'managerOrderList',
  77. mixinsListKey: 'leaderOrderList',
  78. checkedOrders: [], // 已选择的订单ID
  79. isAllChecked: false
  80. }
  81. },
  82. onLoad(args) {
  83. // 检查是否有tabIndex参数,如果有则自动切换到对应tab
  84. if (args.tabIndex !== undefined) {
  85. const index = parseInt(args.tabIndex)
  86. if (!isNaN(index) && index >= 0 && index < this.tabs.length) {
  87. this.status = index
  88. }
  89. }
  90. },
  91. methods: {
  92. handleSearch() {
  93. this.title = this.keyword
  94. this.getData()
  95. this.keyword = ''
  96. this.title = ''
  97. },
  98. beforeGetData() {
  99. const params = {
  100. status: this.status,
  101. title: this.title || ''
  102. }
  103. return params
  104. },
  105. //点击tab栏
  106. clickTabs({ index }) {
  107. this.status = index
  108. this.getData()
  109. this.checkedOrders = [] // 切换标签时清空选择
  110. this.isAllChecked = false
  111. },
  112. // 查看团餐订单
  113. viewOrder(meal) {
  114. this.$utils.navigateTo({
  115. url: '/pages_order/order/groupMealDetail?id=' + meal.id
  116. })
  117. },
  118. // 切换选择订单
  119. toggleCheckOrder(id) {
  120. const index = this.checkedOrders.indexOf(id)
  121. if (index === -1) {
  122. this.checkedOrders.push(id)
  123. } else {
  124. this.checkedOrders.splice(index, 1)
  125. }
  126. // 更新全选状态
  127. this.isAllChecked = this.checkedOrders.length === this.leaderOrderList.length
  128. },
  129. // 处理全选/取消全选
  130. handleCheckAllChange(e) {
  131. this.isAllChecked = !this.isAllChecked
  132. if (this.isAllChecked) {
  133. this.checkedOrders = this.leaderOrderList.map(item => item.id)
  134. } else {
  135. this.checkedOrders = []
  136. }
  137. },
  138. // 处理单个订单操作
  139. handleSingleAction(meal, action) {
  140. const actionMap = {
  141. '出餐': {
  142. status: 1,
  143. confirmText: '确定将该订单标记为已出餐吗?',
  144. successText: '已出餐'
  145. },
  146. '取餐': {
  147. status: 2,
  148. confirmText: '确定将该订单标记为待取餐吗?',
  149. successText: '待取餐'
  150. },
  151. '完成': {
  152. status: 3,
  153. confirmText: '确定将该订单标记为已完成吗?',
  154. successText: '已完成'
  155. }
  156. }
  157. const currentAction = actionMap[action]
  158. uni.showModal({
  159. title: '提示',
  160. content: currentAction.confirmText,
  161. confirmColor: '#019245',
  162. success: (res) => {
  163. if (res.confirm) {
  164. // 使用统一的updateOrders接口处理单个订单
  165. uni.showLoading({
  166. title: '处理中...'
  167. })
  168. this.$api('updateOrders', {
  169. orderIds: meal.id, // 单个订单直接传ID
  170. status: currentAction.status
  171. }, res => {
  172. uni.hideLoading()
  173. if (res.code === 200) {
  174. uni.showToast({
  175. title: currentAction.successText,
  176. icon: 'success'
  177. })
  178. this.getData()
  179. } else {
  180. uni.showToast({
  181. title: '操作失败',
  182. icon: 'none'
  183. })
  184. }
  185. })
  186. }
  187. }
  188. })
  189. },
  190. // 处理批量操作
  191. handleBatchAction(action) {
  192. if (this.checkedOrders.length === 0) {
  193. uni.showToast({
  194. title: '请先选择订单',
  195. icon: 'none'
  196. })
  197. return
  198. }
  199. const actionMap = {
  200. '出餐': {
  201. status: 1,
  202. confirmText: `确定将选中的${this.checkedOrders.length}个订单标记为已出餐吗?`,
  203. successText: '批量操作成功'
  204. },
  205. '取餐': {
  206. status: 2,
  207. confirmText: `确定将选中的${this.checkedOrders.length}个订单标记为待取餐餐吗?`,
  208. successText: '批量操作成功'
  209. },
  210. '完成': {
  211. status: 3,
  212. confirmText: `确定将选中的${this.checkedOrders.length}个订单标记为已完成吗?`,
  213. successText: '批量操作成功'
  214. }
  215. }
  216. const currentAction = actionMap[action]
  217. uni.showModal({
  218. title: '批量操作',
  219. content: currentAction.confirmText,
  220. confirmColor: '#019245',
  221. success: (res) => {
  222. if (res.confirm) {
  223. // 显示加载中
  224. uni.showLoading({
  225. title: '处理中...'
  226. })
  227. // 使用分号分隔多个订单ID
  228. const orderIds = this.checkedOrders.join(';')
  229. this.$api('updateOrders', {
  230. orderIds: orderIds,
  231. status: currentAction.status
  232. }, res => {
  233. uni.hideLoading()
  234. if (res.code === 200) {
  235. uni.showToast({
  236. title: currentAction.successText,
  237. icon: 'success'
  238. })
  239. this.checkedOrders = []
  240. this.isAllChecked = false
  241. this.getData()
  242. } else {
  243. uni.showToast({
  244. title: '操作失败',
  245. icon: 'none'
  246. })
  247. }
  248. })
  249. }
  250. }
  251. })
  252. }
  253. }
  254. }
  255. </script>
  256. <style scoped lang="scss">
  257. .page {}
  258. .tabs {
  259. background: #fff;
  260. padding-bottom: 4rpx;
  261. }
  262. /* 批量操作区域 */
  263. .batch-actions {
  264. display: flex;
  265. justify-content: space-between;
  266. align-items: center;
  267. background-color: #fff;
  268. padding: 20rpx;
  269. margin-bottom: 10rpx;
  270. border-bottom: 1px solid #f5f5f5;
  271. }
  272. .checkbox-all {
  273. display: flex;
  274. align-items: center;
  275. font-size: 28rpx;
  276. }
  277. .batch-btns {
  278. display: flex;
  279. gap: 20rpx;
  280. }
  281. .batch-btn {
  282. background-color: $uni-color;
  283. color: #fff;
  284. font-size: 26rpx;
  285. padding: 10rpx 30rpx;
  286. border-radius: 30rpx;
  287. line-height: 1.5;
  288. margin: 0;
  289. }
  290. /* 团餐列表样式 */
  291. .group-meal-list {
  292. padding: 20rpx;
  293. }
  294. .meal-item {
  295. display: flex;
  296. align-items: center;
  297. padding: 30rpx 20rpx;
  298. background-color: #fff;
  299. margin-bottom: 20rpx;
  300. border-radius: 10rpx;
  301. }
  302. .meal-checkbox {
  303. margin-right: 20rpx;
  304. }
  305. .meal-content {
  306. flex: 1;
  307. }
  308. .meal-name {
  309. font-size: 32rpx;
  310. font-weight: 500;
  311. margin-bottom: 10rpx;
  312. }
  313. .meal-price {
  314. font-size: 28rpx;
  315. color: $uni-color;
  316. background-color: #ECFEF4;
  317. padding: 10rpx 20rpx;
  318. border-radius: 10rpx;
  319. display: inline-block;
  320. }
  321. .price-value {
  322. margin-left: 10rpx;
  323. font-weight: 500;
  324. }
  325. .meal-action {
  326. display: flex;
  327. gap: 15rpx;
  328. margin-left: 20rpx;
  329. }
  330. .action-btn {
  331. background-color: #f0f0f0;
  332. color: #333;
  333. font-size: 26rpx;
  334. padding: 10rpx 25rpx;
  335. border-radius: 30rpx;
  336. line-height: 1.5;
  337. margin: 0;
  338. }
  339. .order-btn {
  340. background-color: $uni-color;
  341. color: #fff;
  342. font-size: 26rpx;
  343. padding: 10rpx 25rpx;
  344. border-radius: 30rpx;
  345. line-height: 1.5;
  346. margin: 0;
  347. }
  348. </style>