|
|
@@ -47,26 +47,45 @@
|
|
|
|
|
|
<!-- 列表头部:仅在有数据时显示 -->
|
|
|
<view class="list-header" v-if="selectedModels.length > 0">
|
|
|
- <text class="header-text">已选型号列表:</text>
|
|
|
+ <view class="header-left">
|
|
|
+ <text class="header-text" v-if="!batchMode">已选型号列表:</text>
|
|
|
+ <text class="header-text" v-else>批量修改({{ selectedIds.length }}/{{ selectedModels.length
|
|
|
+ }})</text>
|
|
|
+ <view class="select-all-toggle" v-if="batchMode" @click="toggleSelectAll">
|
|
|
+ <text class="select-all-icon" :class="{ checked: isAllSelected }">☐</text>
|
|
|
+ <text class="select-all-text">{{ isAllSelected ? '取消全选' : '全选' }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="batch-toggle" :class="{ active: batchMode }" @click="toggleBatchMode">
|
|
|
+ <text>{{ batchMode ? '退出' : '批量修改' }}</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 1. 列表渲染 (精品化设计) -->
|
|
|
<view class="model-item-card" v-for="(item, index) in selectedModels" :key="index"
|
|
|
- v-if="selectedModels.length > 0" @click="editItem(index, item)">
|
|
|
- <view class="remove-icon" @click.stop="removeItem(index)">
|
|
|
- <text class="x-icon">×</text>
|
|
|
+ v-if="selectedModels.length > 0"
|
|
|
+ :class="{ 'batch-mode-card': batchMode, 'batch-selected': batchMode && isSelected(item.rowId) }">
|
|
|
+ <view class="batch-checkbox" v-if="batchMode" @click.stop="toggleSelect(item.rowId)">
|
|
|
+ <view class="checkbox-circle" :class="{ checked: isSelected(item.rowId) }">
|
|
|
+ <text class="check-icon" v-if="isSelected(item.rowId)">✓</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
- <view class="card-line">
|
|
|
- <view class="model-info">
|
|
|
- <text class="model-value">{{ item.modelNum }}</text>
|
|
|
+ <view class="card-body" @click="batchMode ? toggleSelect(item.rowId) : editItem(index, item)">
|
|
|
+ <view class="remove-icon" @click.stop="removeItem(index)">
|
|
|
+ <text class="x-icon">×</text>
|
|
|
</view>
|
|
|
- <view class="count-tag">
|
|
|
- 支数<text class="count-num">{{ item.count }}</text>
|
|
|
+ <view class="card-line">
|
|
|
+ <view class="model-info">
|
|
|
+ <text class="model-value">{{ item.modelNum }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="count-tag">
|
|
|
+ 支数<text class="count-num">{{ item.count }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="card-line secondary">
|
|
|
+ <text class="surface-label">表面名称:</text>
|
|
|
+ <text class="surface-text">{{ item.surfaceName }}</text>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- <view class="card-line secondary">
|
|
|
- <text class="surface-label">表面名称:</text>
|
|
|
- <text class="surface-text">{{ item.surfaceName }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -85,13 +104,25 @@
|
|
|
</view>
|
|
|
</scroll-view>
|
|
|
|
|
|
- <!-- 悬浮添加按钮 (仅在有数据时显示) -->
|
|
|
- <view class="floating-add-btn" @click="goToAddModel" v-if="selectedModels.length > 0">
|
|
|
+ <!-- 悬浮添加按钮 (仅在有数据时且非批量模式显示) -->
|
|
|
+ <view class="floating-add-btn" @click="goToAddModel" v-if="selectedModels.length > 0 && !batchMode">
|
|
|
<view class="plus-icon"></view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 底部支付/下单汇总栏 (仅在有数据时显示) -->
|
|
|
- <view class="footer-summary-bar" v-if="selectedModels.length > 0">
|
|
|
+ <!-- 批量操作栏(批量模式下常驻) -->
|
|
|
+ <view class="batch-action-bar" v-if="batchMode">
|
|
|
+ <view class="batch-count" v-if="selectedIds.length > 0">已选 {{ selectedIds.length }} 项</view>
|
|
|
+ <view class="batch-count placeholder" v-else>请勾选型号</view>
|
|
|
+ <view class="batch-btns">
|
|
|
+ <button class="batch-btn surface-btn" :disabled="selectedIds.length === 0"
|
|
|
+ @click="openBatchSurfacePicker">批量修改表面</button>
|
|
|
+ <button class="batch-btn pack-btn" :disabled="selectedIds.length === 0"
|
|
|
+ @click="openBatchPackPicker">批量修改包装</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 底部支付/下单汇总栏 (仅在有数据时且非批量模式显示) -->
|
|
|
+ <view class="footer-summary-bar" v-if="selectedModels.length > 0 && !batchMode">
|
|
|
<view class="summary-info">
|
|
|
<text class="count-label">共计:</text>
|
|
|
<text class="num-highlight">{{ selectedModels.length }}</text>
|
|
|
@@ -107,17 +138,90 @@
|
|
|
|
|
|
<!-- 底部菜单栏 -->
|
|
|
<erp-tab-bar active="order"></erp-tab-bar>
|
|
|
+
|
|
|
+ <!-- 批量修改 - 表面处理选择弹层 -->
|
|
|
+ <view class="custom-picker-mask" v-if="showBatchSurfacePicker" @click="showBatchSurfacePicker = false"
|
|
|
+ @touchmove.stop.prevent>
|
|
|
+ <view class="picker-popup" @click.stop>
|
|
|
+ <view class="popup-header">
|
|
|
+ <text class="cancel-text" @click="showBatchSurfacePicker = false">取消</text>
|
|
|
+ <text class="popup-title">选择表面处理</text>
|
|
|
+ <text class="confirm-text" @click="confirmBatchSurface">确定</text>
|
|
|
+ </view>
|
|
|
+ <!-- 搜索栏 -->
|
|
|
+ <view class="search-bar">
|
|
|
+ <view class="search-input-wrap">
|
|
|
+ <text class="search-icon">🔍</text>
|
|
|
+ <input class="search-input" type="text" v-model="batchSurfaceSearchKey" placeholder="输入名称检索"
|
|
|
+ @input="onBatchSurfaceSearch" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 层级面包屑 -->
|
|
|
+ <view class="breadcrumb-bar" v-if="batchSurfaceLevel > 1">
|
|
|
+ <text class="back-btn" @click="goBackBatchSurfaceLevel">← 返回</text>
|
|
|
+ <text class="breadcrumb-path">{{batchSurfaceBreadcrumbs.map(b => b.label).join(' / ')}}</text>
|
|
|
+ </view>
|
|
|
+ <!-- 列表区 -->
|
|
|
+ <scroll-view scroll-y class="item-list">
|
|
|
+ <view class="option-item kind-item" v-for="(item, index) in batchSurfaceKindList" :key="'bsk'+index"
|
|
|
+ @click="drillDownBatchSurface(item)">
|
|
|
+ <text class="option-text kind-text">{{ item.num }} - {{ item.name }}</text>
|
|
|
+ <text class="arrow-right">›</text>
|
|
|
+ </view>
|
|
|
+ <view class="option-item" v-for="item in batchSurfaceItemList" :key="'bsi'+item.rowId"
|
|
|
+ :class="{ active: batchSurfaceId === item.rowId }">
|
|
|
+ <text class="option-text" @click="selectBatchSurfaceItem(item)">{{ item.num }} - {{ item.name
|
|
|
+ }}</text>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 批量修改 - 包装方式选择弹层 -->
|
|
|
+ <view class="custom-picker-mask" v-if="showBatchPackPicker" @click="showBatchPackPicker = false"
|
|
|
+ @touchmove.stop.prevent>
|
|
|
+ <view class="picker-popup" @click.stop>
|
|
|
+ <view class="popup-header">
|
|
|
+ <text class="cancel-text" @click="showBatchPackPicker = false">取消</text>
|
|
|
+ <text class="popup-title">选择包装方式</text>
|
|
|
+ <text class="confirm-text" @click="confirmBatchPack">确定</text>
|
|
|
+ </view>
|
|
|
+ <view class="search-bar">
|
|
|
+ <view class="search-input-wrap">
|
|
|
+ <text class="search-icon">🔍</text>
|
|
|
+ <input class="search-input" type="text" v-model="batchPackSearchKey" placeholder="输入名称检索"
|
|
|
+ @input="onBatchPackSearch" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <scroll-view scroll-y class="item-list" @scrolltolower="loadMorePackBatch">
|
|
|
+ <view class="option-item" v-for="item in batchPackList" :key="item.rowId"
|
|
|
+ :class="{ active: batchPackId === item.rowId }"
|
|
|
+ @click="batchPackId = item.rowId; batchPackName = item.name">
|
|
|
+ <text>{{ item.num }} - {{ item.name }}</text>
|
|
|
+ <icon type="success_no_circle" size="16" color="#C1001C" v-if="batchPackId === item.rowId">
|
|
|
+ </icon>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <order-confirm-popup :visible="showConfirmPopup" :models="selectedModels" :clientName="confirmClientName"
|
|
|
+ :submitting="confirmSubmitting" @confirm="handleConfirmOrder" @close="showConfirmPopup = false" />
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import ErpTabBar from '@/components/erp-tab-bar.vue';
|
|
|
import ErpNavBar from '@/components/erp-nav-bar.vue';
|
|
|
+import OrderConfirmPopup from './components/order-confirm-popup.vue';
|
|
|
import { getMyInfo } from '@/api/system/customer.js';
|
|
|
-import { listOrderDetail } from '@/api/erp/orderDetail.js';
|
|
|
+import { listOrderDetail, batchUpdateOrderDetail } from '@/api/erp/orderDetail.js';
|
|
|
+import { listColor } from '@/api/erp/color.js';
|
|
|
+import { listColorKind } from '@/api/erp/colorKind.js';
|
|
|
+import { listPagePack } from '@/api/erp/pack.js';
|
|
|
import { addOrder } from '@/api/erp/order.js';
|
|
|
export default {
|
|
|
- components: { ErpNavBar, ErpTabBar },
|
|
|
+ components: { ErpNavBar, ErpTabBar, OrderConfirmPopup },
|
|
|
data() {
|
|
|
return {
|
|
|
isLoggedIn: false,
|
|
|
@@ -125,12 +229,41 @@ export default {
|
|
|
myInfo: {},
|
|
|
selectedModels: [],
|
|
|
selectedClientId: '',
|
|
|
- selectedClientName: ''
|
|
|
+ selectedClientName: '',
|
|
|
+ // 批量修改相关
|
|
|
+ batchMode: false,
|
|
|
+ selectedIds: [],
|
|
|
+ // 表面处理选择器
|
|
|
+ showBatchSurfacePicker: false,
|
|
|
+ batchSurfaceId: '',
|
|
|
+ batchSurfaceName: '',
|
|
|
+ batchSurfaceSearchKey: '',
|
|
|
+ batchSurfaceBreadcrumbs: [],
|
|
|
+ batchSurfaceLevel: 1,
|
|
|
+ batchSurfaceKindList: [],
|
|
|
+ batchSurfaceItemList: [],
|
|
|
+ // 包装方式选择器
|
|
|
+ showBatchPackPicker: false,
|
|
|
+ batchPackList: [],
|
|
|
+ batchPackPageNum: 1,
|
|
|
+ batchPackHasMore: true,
|
|
|
+ batchPackLoading: false,
|
|
|
+ batchPackId: '',
|
|
|
+ batchPackName: '',
|
|
|
+ batchPackSearchKey: '',
|
|
|
+ batchPackSearchTimer: null,
|
|
|
+ showConfirmPopup: false,
|
|
|
+ confirmClientId: '',
|
|
|
+ confirmClientName: '',
|
|
|
+ confirmSubmitting: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
totalCount() {
|
|
|
return this.selectedModels.reduce((sum, item) => sum + parseInt(item.count || 0), 0);
|
|
|
+ },
|
|
|
+ isAllSelected() {
|
|
|
+ return this.selectedModels.length > 0 && this.selectedIds.length === this.selectedModels.length;
|
|
|
}
|
|
|
},
|
|
|
onLoad() {
|
|
|
@@ -181,7 +314,6 @@ export default {
|
|
|
const res = await getMyInfo();
|
|
|
this.isLoggedIn = true;
|
|
|
this.myInfo = res.data || {};
|
|
|
- // 登录成功后加载列表
|
|
|
this.loadOrderItems();
|
|
|
} catch (e) {
|
|
|
uni.showToast({ title: e || '登录状态校验失败', icon: 'none' });
|
|
|
@@ -220,6 +352,240 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 切换全选 / 取消全选
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ toggleSelectAll() {
|
|
|
+ if (this.isAllSelected) {
|
|
|
+ this.selectedIds = [];
|
|
|
+ } else {
|
|
|
+ this.selectedIds = this.selectedModels.map(item => item.rowId);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 切换批量修改模式
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ toggleBatchMode() {
|
|
|
+ this.batchMode = !this.batchMode;
|
|
|
+ if (!this.batchMode) {
|
|
|
+ this.selectedIds = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 切换选中状态
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ toggleSelect(rowId) {
|
|
|
+ const idx = this.selectedIds.indexOf(rowId);
|
|
|
+ if (idx > -1) {
|
|
|
+ this.selectedIds.splice(idx, 1);
|
|
|
+ } else {
|
|
|
+ this.selectedIds.push(rowId);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 判断是否已选中
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ isSelected(rowId) {
|
|
|
+ return this.selectedIds.indexOf(rowId) > -1;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开批量修改表面处理选择器(二级级联)
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ openBatchSurfacePicker() {
|
|
|
+ if (this.selectedIds.length === 0) {
|
|
|
+ uni.showToast({ title: '请先选择型号', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.showBatchSurfacePicker = true;
|
|
|
+ this.batchSurfaceId = '';
|
|
|
+ this.batchSurfaceName = '';
|
|
|
+ this.batchSurfaceSearchKey = '';
|
|
|
+ this.batchSurfaceLevel = 1;
|
|
|
+ this.batchSurfaceBreadcrumbs = [];
|
|
|
+ this.loadBatchSurfaceList('');
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 加载表面处理系列,点击系列后同时加载子系列和具体颜色(批量选择器)
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ async loadBatchSurfaceList(parentRowId) {
|
|
|
+ try {
|
|
|
+ const keyword = (this.batchSurfaceSearchKey || '').trim();
|
|
|
+ const kindParams = { name: keyword || undefined };
|
|
|
+ if (parentRowId) {
|
|
|
+ kindParams.parentRowId = parentRowId;
|
|
|
+ }
|
|
|
+ const kindRes = await listColorKind(kindParams);
|
|
|
+ this.batchSurfaceKindList = kindRes.data || [];
|
|
|
+ if (parentRowId) {
|
|
|
+ const colorParams = { name: keyword || undefined, parentRowId };
|
|
|
+ const colorRes = await listColor(colorParams);
|
|
|
+ this.batchSurfaceItemList = colorRes.data || [];
|
|
|
+ } else {
|
|
|
+ this.batchSurfaceItemList = [];
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: e || '加载表面处理失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 表面处理搜索
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ onBatchSurfaceSearch() {
|
|
|
+ const parentRowId = this.batchSurfaceBreadcrumbs.length > 0
|
|
|
+ ? this.batchSurfaceBreadcrumbs[this.batchSurfaceBreadcrumbs.length - 1].rowId : '';
|
|
|
+ this.loadBatchSurfaceList(parentRowId);
|
|
|
+ },
|
|
|
+ selectBatchSurfaceItem(item) {
|
|
|
+ this.batchSurfaceId = item.rowId;
|
|
|
+ this.batchSurfaceName = item.name;
|
|
|
+ },
|
|
|
+ drillDownBatchSurface(item) {
|
|
|
+ this.batchSurfaceBreadcrumbs.push({ rowId: item.rowId, label: item.num });
|
|
|
+ this.batchSurfaceId = '';
|
|
|
+ this.batchSurfaceName = '';
|
|
|
+ this.batchSurfaceLevel++;
|
|
|
+ this.loadBatchSurfaceList(item.rowId);
|
|
|
+ },
|
|
|
+ goBackBatchSurfaceLevel() {
|
|
|
+ this.batchSurfaceBreadcrumbs.pop();
|
|
|
+ this.batchSurfaceLevel--;
|
|
|
+ this.batchSurfaceId = '';
|
|
|
+ this.batchSurfaceName = '';
|
|
|
+ const parentRowId = this.batchSurfaceBreadcrumbs.length > 0
|
|
|
+ ? this.batchSurfaceBreadcrumbs[this.batchSurfaceBreadcrumbs.length - 1].rowId : '';
|
|
|
+ this.loadBatchSurfaceList(parentRowId);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 确认批量修改表面处理
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ async confirmBatchSurface() {
|
|
|
+ if (!this.batchSurfaceId) {
|
|
|
+ uni.showToast({ title: '请选择表面处理', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.showBatchSurfacePicker = false;
|
|
|
+ uni.showLoading({ title: '修改中...', mask: true });
|
|
|
+ try {
|
|
|
+ await batchUpdateOrderDetail({
|
|
|
+ rowIds: this.selectedIds,
|
|
|
+ surfaceId: this.batchSurfaceId,
|
|
|
+ surfaceName: this.batchSurfaceName
|
|
|
+ });
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({ title: '修改成功', icon: 'success' });
|
|
|
+ this.selectedIds = [];
|
|
|
+ this.loadOrderItems(false);
|
|
|
+ } catch (e) {
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({ title: e || '修改失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ this.batchSurfaceLevel = 1;
|
|
|
+ this.batchSurfaceBreadcrumbs = [];
|
|
|
+ this.batchSurfaceId = '';
|
|
|
+ this.batchSurfaceName = '';
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开批量修改包装方式选择器
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ openBatchPackPicker() {
|
|
|
+ if (this.selectedIds.length === 0) {
|
|
|
+ uni.showToast({ title: '请先选择型号', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.showBatchPackPicker = true;
|
|
|
+ this.batchPackId = '';
|
|
|
+ this.batchPackName = '';
|
|
|
+ this.batchPackSearchKey = '';
|
|
|
+ this.batchPackPageNum = 1;
|
|
|
+ if (this.batchPackList.length === 0) {
|
|
|
+ this.loadBatchPackList();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 加载包装方式列表(批量选择器)
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ async loadBatchPackList(pageNum = 1, keyword = '') {
|
|
|
+ if (this.batchPackLoading) return;
|
|
|
+ this.batchPackLoading = true;
|
|
|
+ try {
|
|
|
+ const res = await listPagePack({
|
|
|
+ pageNum,
|
|
|
+ pageSize: 10,
|
|
|
+ name: keyword || undefined
|
|
|
+ });
|
|
|
+ const rows = res.rows || [];
|
|
|
+ if (pageNum === 1) {
|
|
|
+ this.batchPackList = rows;
|
|
|
+ } else {
|
|
|
+ this.batchPackList = [...this.batchPackList, ...rows];
|
|
|
+ }
|
|
|
+ this.batchPackHasMore = rows.length >= 20;
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: e || '加载包装方式失败', icon: 'none' });
|
|
|
+ } finally {
|
|
|
+ this.batchPackLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 加载更多包装方式列表
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ loadMorePackBatch() {
|
|
|
+ if (!this.batchPackHasMore || this.batchPackLoading) return;
|
|
|
+ this.batchPackPageNum++;
|
|
|
+ this.loadBatchPackList(this.batchPackPageNum, this.batchPackSearchKey);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 包装方式搜索(防抖)
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ onBatchPackSearch() {
|
|
|
+ if (this.batchPackSearchTimer) clearTimeout(this.batchPackSearchTimer);
|
|
|
+ this.batchPackSearchTimer = setTimeout(() => {
|
|
|
+ this.batchPackPageNum = 1;
|
|
|
+ this.loadBatchPackList(1, this.batchPackSearchKey);
|
|
|
+ }, 300);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 确认批量修改包装方式
|
|
|
+ * @Author: Trae
|
|
|
+ */
|
|
|
+ async confirmBatchPack() {
|
|
|
+ if (!this.batchPackId) {
|
|
|
+ uni.showToast({ title: '请选择包装方式', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.showBatchPackPicker = false;
|
|
|
+ uni.showLoading({ title: '修改中...', mask: true });
|
|
|
+ try {
|
|
|
+ await batchUpdateOrderDetail({
|
|
|
+ rowIds: this.selectedIds,
|
|
|
+ packId: this.batchPackId,
|
|
|
+ packName: this.batchPackName
|
|
|
+ });
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({ title: '修改成功', icon: 'success' });
|
|
|
+ this.selectedIds = [];
|
|
|
+ this.loadOrderItems(false);
|
|
|
+ } catch (e) {
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({ title: e || '修改失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 提交最终订单 - 选择客户后弹出确认弹窗
|
|
|
+ * @Author: Antigravity
|
|
|
+ */
|
|
|
async submitFinalOrder() {
|
|
|
if (this.selectedModels.length === 0) return;
|
|
|
|
|
|
@@ -229,15 +595,15 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 单个授权客户:直接用
|
|
|
+ // 单个授权客户:直接弹出
|
|
|
if (clientList.length === 1) {
|
|
|
- this.selectedClientId = clientList[0].rowId;
|
|
|
- this.selectedClientName = clientList[0].name;
|
|
|
- this.doSubmitOrder();
|
|
|
+ this.confirmClientId = clientList[0].rowId;
|
|
|
+ this.confirmClientName = clientList[0].name;
|
|
|
+ this.showConfirmPopup = true;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 多个授权客户:弹出选择器
|
|
|
+ // 多个授权客户:先选择再弹出
|
|
|
const clientNames = clientList.map(c => c.name);
|
|
|
const res = await new Promise((resolve) => {
|
|
|
uni.showActionSheet({
|
|
|
@@ -248,25 +614,28 @@ export default {
|
|
|
});
|
|
|
if (res && res.tapIndex !== undefined) {
|
|
|
const chosen = clientList[res.tapIndex];
|
|
|
- this.selectedClientId = chosen.rowId;
|
|
|
- this.selectedClientName = chosen.name;
|
|
|
- this.doSubmitOrder();
|
|
|
+ this.confirmClientId = chosen.rowId;
|
|
|
+ this.confirmClientName = chosen.name;
|
|
|
+ this.showConfirmPopup = true;
|
|
|
}
|
|
|
},
|
|
|
/**
|
|
|
- * 执行下单请求
|
|
|
- * @Author: Antigravity
|
|
|
+ * 确认弹窗回调 - 正式执行下单
|
|
|
+ * @Author: Trae
|
|
|
*/
|
|
|
- async doSubmitOrder() {
|
|
|
+ async handleConfirmOrder() {
|
|
|
+ this.confirmSubmitting = true;
|
|
|
uni.showLoading({ title: '正在提交订单', mask: true });
|
|
|
try {
|
|
|
const detailIds = this.selectedModels.map(item => item.rowId);
|
|
|
const submitRes = await addOrder({
|
|
|
detailIds,
|
|
|
- clientId: this.selectedClientId,
|
|
|
- clientName: this.selectedClientName
|
|
|
+ clientId: this.confirmClientId,
|
|
|
+ clientName: this.confirmClientName
|
|
|
});
|
|
|
uni.hideLoading();
|
|
|
+ this.confirmSubmitting = false;
|
|
|
+ this.showConfirmPopup = false;
|
|
|
const orderId = submitRes.data;
|
|
|
uni.showToast({ title: '下单成功', icon: 'success' });
|
|
|
setTimeout(() => {
|
|
|
@@ -276,6 +645,7 @@ export default {
|
|
|
}, 1500);
|
|
|
} catch (e) {
|
|
|
uni.hideLoading();
|
|
|
+ this.confirmSubmitting = false;
|
|
|
uni.showToast({ title: e || '下单失败', icon: 'none' });
|
|
|
}
|
|
|
}
|
|
|
@@ -391,6 +761,17 @@ export default {
|
|
|
|
|
|
.list-header {
|
|
|
padding: 10rpx 0 20rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.header-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 16rpx;
|
|
|
}
|
|
|
|
|
|
.header-text {
|
|
|
@@ -412,6 +793,29 @@ export default {
|
|
|
border-radius: 4rpx;
|
|
|
}
|
|
|
|
|
|
+.select-all-toggle {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6rpx;
|
|
|
+ padding: 6rpx 16rpx;
|
|
|
+ background: #f5f5f5;
|
|
|
+ border-radius: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.select-all-icon {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+
|
|
|
+.select-all-icon.checked {
|
|
|
+ color: #C1001C;
|
|
|
+}
|
|
|
+
|
|
|
+.select-all-text {
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
/* 型号卡片:大幅升级美化 */
|
|
|
.model-item-card {
|
|
|
background: #fff;
|
|
|
@@ -421,12 +825,57 @@ export default {
|
|
|
position: relative;
|
|
|
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.04);
|
|
|
border: 1rpx solid rgba(0, 0, 0, 0.02);
|
|
|
+ display: flex;
|
|
|
+ align-items: stretch;
|
|
|
+ transition: border 0.25s, background 0.25s, transform 0.15s;
|
|
|
+}
|
|
|
+
|
|
|
+.model-item-card.batch-mode-card {
|
|
|
+ padding-left: 20rpx;
|
|
|
+ gap: 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-checkbox {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding-top: 6rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-circle {
|
|
|
+ width: 44rpx;
|
|
|
+ height: 44rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 2rpx solid #ddd;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: #fff;
|
|
|
+ transition: all 0.2s;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-circle.checked {
|
|
|
+ background: #C1001C;
|
|
|
+ border-color: #C1001C;
|
|
|
+}
|
|
|
+
|
|
|
+.check-icon {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #fff;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.card-body {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
|
|
|
.remove-icon {
|
|
|
position: absolute;
|
|
|
- right: 0;
|
|
|
- top: 0;
|
|
|
+ right: -36rpx;
|
|
|
+ top: -36rpx;
|
|
|
width: 50rpx;
|
|
|
height: 50rpx;
|
|
|
background: rgba(255, 77, 79, 0.1);
|
|
|
@@ -755,4 +1204,224 @@ export default {
|
|
|
font-weight: bold;
|
|
|
color: #C1001C;
|
|
|
}
|
|
|
+
|
|
|
+/* 批量修改按钮 */
|
|
|
+.batch-toggle {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding: 8rpx 24rpx;
|
|
|
+ background: #C1001C;
|
|
|
+ border-radius: 40rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-selected {
|
|
|
+ border-color: #C1001C !important;
|
|
|
+ background: #FFF1F2 !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 批量操作栏 */
|
|
|
+.batch-action-bar {
|
|
|
+ position: fixed;
|
|
|
+ bottom: calc(110rpx + env(safe-area-inset-bottom));
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 110rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-top: 1rpx solid #f0f0f0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 0 30rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ z-index: 100;
|
|
|
+ box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
|
|
|
+}
|
|
|
+
|
|
|
+.batch-count {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-count.placeholder {
|
|
|
+ color: #ccc;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-btns {
|
|
|
+ display: flex;
|
|
|
+ gap: 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-btn {
|
|
|
+ width: auto;
|
|
|
+ height: 64rpx;
|
|
|
+ padding: 0 28rpx;
|
|
|
+ border-radius: 32rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ border: none;
|
|
|
+ line-height: 64rpx;
|
|
|
+ transition: opacity 0.2s;
|
|
|
+}
|
|
|
+
|
|
|
+.batch-btn[disabled] {
|
|
|
+ opacity: 0.4;
|
|
|
+}
|
|
|
+
|
|
|
+.surface-btn {
|
|
|
+ background: linear-gradient(135deg, #1890FF, #096DD9);
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.pack-btn {
|
|
|
+ background: linear-gradient(135deg, #52C41A, #389E0D);
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+/* 选择器弹层(参照 edit-model 模式) */
|
|
|
+.custom-picker-mask {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background: rgba(0, 0, 0, 0.4);
|
|
|
+ z-index: 1000;
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-end;
|
|
|
+}
|
|
|
+
|
|
|
+.picker-popup {
|
|
|
+ width: 100%;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 32rpx 32rpx 0 0;
|
|
|
+ padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
|
|
|
+ animation: slideUp 0.15s ease-out;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes slideUp {
|
|
|
+ from {
|
|
|
+ transform: translateY(100%);
|
|
|
+ }
|
|
|
+
|
|
|
+ to {
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.popup-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 30rpx 40rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+}
|
|
|
+
|
|
|
+.popup-title {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.cancel-text,
|
|
|
+.confirm-text {
|
|
|
+ font-size: 30rpx;
|
|
|
+ padding: 10rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.confirm-text {
|
|
|
+ color: #C1001C;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.item-list {
|
|
|
+ max-height: 50vh;
|
|
|
+ padding: 0 40rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item {
|
|
|
+ height: 110rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ border-bottom: 1rpx solid #f8f8f8;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item.active {
|
|
|
+ color: #C1001C;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.kind-item {
|
|
|
+ background: #fafbfc;
|
|
|
+}
|
|
|
+
|
|
|
+.kind-text {
|
|
|
+ color: #556;
|
|
|
+}
|
|
|
+
|
|
|
+.option-text {
|
|
|
+ flex: 1;
|
|
|
+ padding: 10rpx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.arrow-right {
|
|
|
+ font-size: 56rpx;
|
|
|
+ color: #bbb;
|
|
|
+ padding: 10rpx 0 10rpx 20rpx;
|
|
|
+ font-weight: 300;
|
|
|
+}
|
|
|
+
|
|
|
+/* 级联面包屑 */
|
|
|
+.breadcrumb-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 16rpx 40rpx;
|
|
|
+ background: #fafafa;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+}
|
|
|
+
|
|
|
+.back-btn {
|
|
|
+ color: #C1001C;
|
|
|
+ font-size: 28rpx;
|
|
|
+ margin-right: 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.breadcrumb-path {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+/* 搜索栏样式 */
|
|
|
+.search-bar {
|
|
|
+ padding: 16rpx 40rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input-wrap {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: #f5f6f8;
|
|
|
+ border-radius: 32rpx;
|
|
|
+ padding: 12rpx 24rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.search-icon {
|
|
|
+ font-size: 28rpx;
|
|
|
+ margin-right: 12rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #333;
|
|
|
+ height: 56rpx;
|
|
|
+}
|
|
|
</style>
|