| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- <template>
- <!-- 订单分配详情抽屉 -->
- <el-drawer v-model="drawer.visible" size="65%" direction="rtl" :close-on-click-modal="true" :before-close="handleDrawerClose">
- <template #header>
- <div class="drawer-header">
- <!-- <el-icon color="#f56c6c" :size="24"><WarningFilled /></el-icon> -->
- <span class="order-title">订单分配 {{ orderInfo.orderNo }}</span>
- </div>
- </template>
- <div class="drawer-content">
- <div class="detail-header">
- <el-row :gutter="20">
- <el-col :span="6">
- <div class="info-item">
- <span class="label">客户</span>
- <span class="value">{{ orderInfo.customerName }}</span>
- </div>
- </el-col>
- <el-col :span="6">
- <div class="info-item">
- <span class="label">负责人</span>
- <span class="value">{{ orderInfo.businessStaff }}</span>
- </div>
- </el-col>
- <el-col :span="4">
- <div class="info-item">
- <span class="label">商品总数</span>
- <span class="value">{{ orderInfo.productTotal }}</span>
- </div>
- </el-col>
- <el-col :span="4">
- <div class="info-item">
- <span class="label">待分配</span>
- <span class="value">{{ orderInfo.unassigned }}</span>
- </div>
- </el-col>
- <el-col :span="4">
- <div class="info-item">
- <span class="label">已分配</span>
- <span class="value">{{ orderInfo.assigned }}</span>
- </div>
- </el-col>
- </el-row>
- </div>
- <el-tabs v-model="activeTab" class="detail-tabs">
- <el-tab-pane label="待分配" name="pending" v-if="assignmentStatus != '1'">
- <div class="tab-actions">
- <el-button type="primary" @click="handleBatchAssign">+ 批量分配</el-button>
- </div>
- <el-table
- ref="pendingTableRef"
- :data="pendingProducts"
- border
- style="width: 100%"
- max-height="800"
- @selection-change="handlePendingSelectionChange"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="序号" width="80" align="center">
- <template #default="scope">{{ scope.$index + 1 }}</template>
- </el-table-column>
- <el-table-column label="商品图片" width="100" align="center">
- <template #default="scope">
- <el-image
- v-if="scope.row.productImage"
- :src="scope.row.productImage"
- style="width: 60px; height: 60px"
- fit="cover"
- :preview-src-list="[scope.row.productImage]"
- />
- </template>
- </el-table-column>
- <el-table-column label="商品编号" prop="productNo" align="center" />
- <el-table-column label="商品名称" prop="productName" min-width="200" show-overflow-tooltip align="left" />
- <el-table-column label="数量" prop="orderQuantity" align="center" />
- <el-table-column label="单价" prop="orderPrice" align="center" />
- <el-table-column label="小计" align="center">
- <template #default="scope">{{ (scope.row.orderPrice * scope.row.orderQuantity).toFixed(2) }}</template>
- </el-table-column>
- <el-table-column label="状态" width="100" align="center">
- <template #default="scope">
- <dict-tag :options="order_assignment_status" :value="scope.row.assignmentStatus" />
- </template>
- </el-table-column>
- <el-table-column label="操作" width="120" align="center" fixed="right">
- <template #default="scope">
- <el-button link type="primary" size="small" @click="handleAssignProduct(scope.row)">分配</el-button>
- </template>
- </el-table-column>
- </el-table>
- </el-tab-pane>
- <el-tab-pane label="已分配" name="assigned">
- <el-table :data="assignedProducts" border style="width: 100%" max-height="800">
- <el-table-column label="序号" width="80" align="center">
- <template #default="scope">{{ scope.$index + 1 }}</template>
- </el-table-column>
- <el-table-column label="商品图片" width="100" align="center">
- <template #default="scope">
- <el-image
- v-if="scope.row.productImage"
- :src="scope.row.productImage"
- style="width: 60px; height: 60px"
- fit="cover"
- :preview-src-list="[scope.row.productImage]"
- />
- </template>
- </el-table-column>
- <el-table-column label="商品编号" prop="productNo" align="center" />
- <el-table-column label="商品名称" prop="productName" min-width="200" show-overflow-tooltip align="left" />
- <el-table-column label="数量" prop="orderQuantity" align="center" />
- <el-table-column label="单价" prop="orderPrice" align="center" />
- <el-table-column label="小计" align="center">
- <template #default="scope">{{ (scope.row.orderPrice * scope.row.orderQuantity).toFixed(2) }}</template>
- </el-table-column>
- <el-table-column label="状态" width="100" align="center">
- <template #default="scope">
- <dict-tag :options="order_assignment_status" :value="scope.row.assignmentStatus" />
- </template>
- </el-table-column>
- <el-table-column label="分配人" prop="assigneeName" min-width="200" align="left" />
- </el-table>
- </el-tab-pane>
- <el-tab-pane label="记录" name="record">
- <el-table :data="assignRecords" border style="width: 100%" max-height="400">
- <el-table-column label="序号" type="index" width="80" align="center" />
- <el-table-column label="分配时间" prop="createTime" align="center" />
- <el-table-column label="分配人" prop="createName" align="center" />
- <el-table-column label="分配目标" prop="assigneeName" align="center" />
- </el-table>
- </el-tab-pane>
- </el-tabs>
- </div>
- </el-drawer>
- <!-- 分配抽屉 -->
- <el-drawer v-model="assignDialog.visible" title="分配" size="50%" direction="rtl" :close-on-click-modal="true">
- <div class="assign-drawer-content">
- <!-- 分配目标选择 -->
- <div class="assign-target-section">
- <el-row :gutter="20">
- <el-col :span="12">
- <div class="target-input-wrapper">
- <span class="required-mark">*</span>
- <span class="label">分配对象类型:</span>
- <el-select v-model="assignForm.targetType" placeholder="请选择分配对象类型" clearable style="flex: 1" @change="handleTargetTypeChange">
- <el-option label="自营客户" value="zy" />
- <el-option label="供应商" value="srm" />
- </el-select>
- </div>
- </el-col>
- <el-col :span="12" v-show="assignForm.targetType === 'zy'">
- <div class="target-input-wrapper">
- <span class="required-mark">*</span>
- <span class="label">自营客户: </span>
- <el-select v-model="assignForm.targetId" :placeholder="'请选择自营客户'" clearable filterable style="flex: 1">
- <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
- </div>
- </el-col>
- <el-col :span="12" v-show="assignForm.targetType === 'srm'">
- <div class="target-input-wrapper">
- <span class="required-mark">*</span>
- <span class="label">供应商: </span>
- <el-select v-model="assignForm.targetId" :placeholder="'请选择供应商'" clearable filterable style="flex: 1">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
- </div>
- </el-col>
- </el-row>
- </div>
- <!-- 商品列表 -->
- <div class="product-list-section">
- <el-table
- ref="assignProductTableRef"
- :data="assignForm.productList"
- border
- style="width: 100%"
- max-height="800"
- @selection-change="handleAssignProductSelectionChange"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="序号" width="80" align="center">
- <template #default="scope">{{ scope.$index + 1 }}</template>
- </el-table-column>
- <el-table-column label="商品图片" width="100" align="center">
- <template #default="scope">
- <el-image
- v-if="scope.row.productImage"
- :src="scope.row.productImage"
- style="width: 60px; height: 60px"
- fit="cover"
- :preview-src-list="[scope.row.productImage]"
- />
- <span v-else style="color: #999">暂无图片</span>
- </template>
- </el-table-column>
- <el-table-column label="商品编号" prop="productNo" width="140" align="center" />
- <el-table-column label="商品名称" prop="productName" min-width="200" show-overflow-tooltip />
- <el-table-column label="分配数量" width="150" align="center" prop="orderQuantity">
- <!-- <template #default="scope">
- <el-input-number v-model="scope.row.assignQuantity" :min="1" :max="scope.row.orderQuantity" :controls="false" style="width: 100%" />
- </template> -->
- </el-table-column>
- <el-table-column label="单价" prop="orderPrice" width="120" align="center" />
- <el-table-column label="小计" width="120" align="center">
- <template #default="scope">{{ (scope.row.orderPrice * scope.row.orderQuantity).toFixed(2) }}</template>
- </el-table-column>
- </el-table>
- </div>
- </div>
- <template #footer>
- <div class="drawer-footer">
- <el-button @click="assignDialog.visible = false">取 消</el-button>
- <el-button :loading="buttonLoading" type="primary" @click="submitAssign">确定分配</el-button>
- </div>
- </template>
- </el-drawer>
- </template>
- <script setup name="SplitAssignDialog" lang="ts">
- import { getOrderMain } from '@/api/order/orderMain';
- import { listOrderAssignment } from '@/api/order/orderAssignmentLog';
- import { listInfo } from '@/api/supplier/info';
- import { addOrderSplitAssign, addOrderAssignment } from '@/api/order/orderAssignmentLog';
- import { OrderSplitAssignForm, OrderProductAssignRule, OrderAssignmentForm } from '@/api/order/orderAssignmentLog/types';
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const { sys_platform_code, order_assignment_status } = toRefs<any>(proxy?.useDict('sys_platform_code', 'order_assignment_status'));
- import { listCustomerInfo } from '@/api/customer/customerFile/customerInfo';
- const emit = defineEmits(['success']);
- const buttonLoading = ref(false);
- const pendingTableRef = ref();
- const assignProductTableRef = ref();
- const selectedPendingProducts = ref<any[]>([]);
- const selectedAssignProducts = ref<any[]>([]); // 分配对话框中选中的商品
- // 订单分配详情抽屉
- const drawer = reactive<DialogOption>({
- visible: false,
- title: '订单分配'
- });
- // 分配对话框
- const assignDialog = reactive({
- visible: false
- });
- const orderInfo = ref<any>({
- orderNo: '',
- id: undefined,
- platformCode: '',
- customerName: '',
- businessStaff: '',
- productQuantity: 0,
- pendingCount: 0,
- assignedCount: 0,
- productTotal: 0,
- assigned: 0,
- unassigned: 0
- });
- // 分配表单
- const assignForm = reactive({
- targetType: 'srm', // 分配对象类型:srm-供应商
- targetId: '', // 分配目标ID
- productList: [] as any[]
- });
- // 供应商列表
- const supplierList = ref<any[]>([]);
- // 缓存的供应商列表(打开抽屉时预先加载)
- const cachedSupplierList = ref<any[]>([]);
- // 自营客户列表
- const customerList = ref<any[]>([]);
- const cachedCustomerList = ref<any[]>([]);
- // 标签页
- const activeTab = ref('pending');
- // 待分配商品列表
- const pendingProducts = ref<any[]>([]);
- // 已分配商品列表
- const assignedProducts = ref<any[]>([]);
- // 分配记录
- const assignRecords = ref<any[]>([]);
- const assignmentStatus = ref('0');
- /** 打开订单分配详情抽屉 */
- const open = async (orderId: string | number, status: string) => {
- reset();
- drawer.visible = true;
- assignmentStatus.value = status;
- if (status == '1') {
- activeTab.value = 'assigned';
- }
- try {
- // 获取订单详情
- const res = await getOrderMain(orderId);
- orderInfo.value = {
- orderNo: res.data.orderNo,
- id: res.data.id,
- platformCode: res.data.platformCode,
- customerName: res.data.customerName || '--',
- businessStaff: res.data.businessStaff || '--',
- productQuantity: res.data.productQuantity || 0,
- productTotal: res.data.productTotal || 0,
- assigned: res.data.assigned || 0,
- unassigned: res.data.unassigned || 0
- };
- // 加载订单商品列表
- if (res.data.orderProductList && res.data.orderProductList.length > 0) {
- const productList = res.data.orderProductList.map((item: any) => ({
- ...item,
- itemId: item.id,
- assignQuantity: item.orderQuantity
- }));
- // 待分配/已分配商品(按 assignmentStatus 过滤:0-待分配,1-已分配)
- pendingProducts.value = productList.filter((item: any) => item.assignmentStatus === '0');
- assignedProducts.value = productList.filter((item: any) => item.assignmentStatus === '1');
- }
- // 加载分配记录
- await loadAssignRecords(orderId);
- // 预加载供应商数据以加快后续操作响应
- loadSupplierData();
- } catch (error) {
- proxy?.$modal.msgError('获取订单信息失败');
- drawer.visible = false;
- }
- };
- /** 分配对象类型变化 */
- const handleTargetTypeChange = () => {
- // 切换类型时清空已选择的目标
- assignForm.targetId = '';
- if (assignForm.targetType === 'zy') {
- loadCustomerData();
- } else if (assignForm.targetType === 'srm') {
- supplierList.value = cachedSupplierList.value;
- }
- };
- /** 加载自营客户数据 */
- const loadCustomerData = async () => {
- if (cachedCustomerList.value.length > 0) {
- customerList.value = cachedCustomerList.value;
- return;
- }
- try {
- const res: any = await listCustomerInfo({ status: '0', pageNum: 1, pageSize: 1000 });
- const list = res.rows || res.data || [];
- cachedCustomerList.value = list.map((item: any) => ({
- ...item,
- id: item.id,
- name: item.customerName
- }));
- customerList.value = cachedCustomerList.value;
- } catch (error) {
- console.error('获取自营客户列表失败', error);
- }
- };
- /** 预加载供应商数据 */
- const loadSupplierData = async () => {
- if (cachedSupplierList.value.length > 0) return;
- try {
- const res: any = await listInfo({ supplyStatus: 1, pageNum: 1, pageSize: 9999 });
- const list = res.rows || res.data || [];
- cachedSupplierList.value = list.map((item: any) => ({
- ...item,
- id: item.id,
- name: item.enterpriseName || item.supplierName
- }));
- supplierList.value = cachedSupplierList.value;
- } catch (error) {
- console.error('获取供应商列表失败', error);
- }
- };
- /** 加载分配记录 */
- const loadAssignRecords = async (orderId: string | number) => {
- try {
- const res = await listOrderAssignment({
- orderId: orderId,
- pageNum: 1,
- pageSize: 100
- });
- assignRecords.value = res.rows || [];
- } catch (error) {
- console.error('获取分配记录失败:', error);
- assignRecords.value = [];
- }
- };
- /** 表单重置 */
- const reset = () => {
- assignForm.targetType = 'srm';
- assignForm.targetId = '';
- assignForm.productList = [];
- selectedPendingProducts.value = [];
- selectedAssignProducts.value = [];
- pendingProducts.value = [];
- assignedProducts.value = [];
- assignRecords.value = [];
- activeTab.value = 'pending';
- orderInfo.value = {
- orderNo: '',
- id: undefined,
- platformCode: '',
- customerName: '',
- businessStaff: '',
- productQuantity: 0,
- pendingCount: 0,
- assignedCount: 0,
- productTotal: 0,
- assigned: 0,
- unassigned: 0
- };
- };
- /** 关闭抽屉前的回调 */
- const handleDrawerClose = (done: () => void) => {
- if (buttonLoading.value) {
- return;
- }
- done();
- reset();
- };
- /** 待分配商品选择变化 */
- const handlePendingSelectionChange = (selection: any[]) => {
- selectedPendingProducts.value = selection;
- };
- /** 分配对话框中商品选择变化 */
- const handleAssignProductSelectionChange = (selection: any[]) => {
- selectedAssignProducts.value = selection;
- };
- /** 批量分配 */
- const handleBatchAssign = () => {
- // 验证是否选择了商品
- if (selectedPendingProducts.value.length === 0) {
- proxy?.$modal.msgWarning('请至少选择一个商品进行分配');
- return;
- }
- // 打开分配对话框
- assignForm.productList = [...selectedPendingProducts.value];
- assignDialog.visible = true;
- // 等待对话框渲染后,默认全选所有商品
- nextTick(() => {
- assignForm.productList.forEach((row) => {
- assignProductTableRef.value?.toggleRowSelection(row, true);
- });
- });
- };
- /** 分配单个商品 */
- const handleAssignProduct = (row: any) => {
- // 打开分配对话框,只包含当前商品
- assignForm.productList = [row];
- assignDialog.visible = true;
- // 等待对话框渲染后,默认选中该商品
- nextTick(() => {
- assignProductTableRef.value?.toggleRowSelection(row, true);
- });
- };
- /** 转分配 */
- const handleReassign = (row: any) => {
- proxy?.$modal.confirm('确认要转分配该商品吗?').then(() => {
- // 打开分配对话框
- assignForm.productList = [row];
- assignDialog.visible = true;
- // 等待对话框渲染后,默认选中该商品
- nextTick(() => {
- assignProductTableRef.value?.toggleRowSelection(row, true);
- });
- });
- };
- /** 提交分配 */
- const submitAssign = async () => {
- // 验证是否选择了商品
- if (selectedAssignProducts.value.length === 0) {
- proxy?.$modal.msgWarning('请至少勾选一个商品进行分配');
- return;
- }
- // 验证分配对象类型
- if (!assignForm.targetType) {
- proxy?.$modal.msgWarning('请选择分配对象类型');
- return;
- }
- // 验证分配目标
- if (!assignForm.targetId) {
- proxy?.$modal.msgWarning(`请选择${assignForm.targetType === 'srm' ? '供应商' : '伙伴商'}`);
- return;
- }
- buttonLoading.value = true;
- try {
- // 组装提交数据,只提交勾选的商品
- const submitData: OrderSplitAssignForm = {
- orderId: orderInfo.value.id, // 父订单ID
- itemRules: selectedAssignProducts.value.map(
- (product): OrderProductAssignRule => ({
- itemId: product.itemId, // 商品行ID
- assigneeId: assignForm.targetId, // 供应商ID 或 伙伴商ID
- assigneeType: assignForm.targetType // "srm" 或 "bp"
- })
- ),
- remark: '' // 分配备注(可选)
- };
- // 调用拆单分配接口
- await addOrderSplitAssign(submitData);
- proxy?.$modal.msgSuccess('分配成功');
- assignDialog.visible = false;
- // 清空选中状态
- selectedAssignProducts.value = [];
- // 刷新抽屉数据
- await open(orderInfo.value.id, '0');
- emit('success');
- } catch (error) {
- console.error('分配失败:', error);
- proxy?.$modal.msgError('分配失败');
- } finally {
- buttonLoading.value = false;
- }
- };
- // /** 分配对象类型变化 */
- // const handleTargetTypeChange = () => {
- // // 切换类型时清空已选择的目标
- // assignForm.targetId = '';
- // if (assignForm.targetType === 'srm') {
- // supplierList.value = cachedSupplierList.value;
- // } else {
- // // 处理伙伴商等其他情况(目前留空或使用别的缓存)
- // }
- // };
- defineExpose({
- open
- });
- </script>
- <style scoped lang="scss">
- .drawer-header {
- display: flex;
- align-items: center;
- gap: 10px;
- .order-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- }
- }
- .drawer-content {
- padding: 0 20px 20px;
- height: calc(100% - 60px);
- overflow-y: auto;
- }
- .assign-drawer-content {
- padding: 0 20px 20px;
- height: calc(100% - 80px);
- overflow-y: auto;
- }
- .assign-target-section {
- margin-bottom: 20px;
- .target-input-wrapper {
- display: flex;
- align-items: center;
- gap: 8px;
- .required-mark {
- color: #f56c6c;
- font-size: 14px;
- }
- .label {
- font-size: 14px;
- color: #606266;
- white-space: nowrap;
- }
- }
- .or-divider {
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 14px;
- color: #909399;
- }
- }
- .product-list-section {
- margin-top: 20px;
- }
- .drawer-footer {
- display: flex;
- justify-content: flex-end;
- gap: 10px;
- padding: 10px 20px;
- border-top: 1px solid #e4e7ed;
- }
- .detail-header {
- padding: 15px 20px;
- background-color: #f5f7fa;
- border-radius: 4px;
- margin-bottom: 20px;
- .info-item {
- display: flex;
- flex-direction: column;
- gap: 5px;
- .label {
- font-size: 12px;
- color: #909399;
- }
- .value {
- font-size: 14px;
- color: #303133;
- font-weight: 500;
- }
- }
- }
- .detail-tabs {
- .tab-actions {
- margin-bottom: 15px;
- }
- }
- :deep(.el-alert__title) {
- font-size: 13px;
- }
- </style>
|