|
|
@@ -1,615 +0,0 @@
|
|
|
-import dayjs from "dayjs";
|
|
|
-import type { PaginationProps } from "@pureadmin/table";
|
|
|
-import { deviceDetection } from "@pureadmin/utils";
|
|
|
-import { message } from "@/utils/message";
|
|
|
-import { addDialog } from "@/components/ReDialog";
|
|
|
-import {
|
|
|
- getOrderList,
|
|
|
- getOrderDetail,
|
|
|
- getOrderItems,
|
|
|
- createOrder,
|
|
|
- deleteOrder,
|
|
|
- submitOrder,
|
|
|
- syncToErp,
|
|
|
- completeOrder,
|
|
|
- cancelOrder,
|
|
|
- getReplenishmentSuggestions
|
|
|
-} from "@/api/replenishmentOrder";
|
|
|
-import { getDeviceList } from "@/api/device";
|
|
|
-import { reactive, ref, onMounted } from "vue";
|
|
|
-import {
|
|
|
- ElMessageBox,
|
|
|
- ElTag,
|
|
|
- ElInput,
|
|
|
- ElInputNumber,
|
|
|
- ElDatePicker,
|
|
|
- ElDescriptions,
|
|
|
- ElDescriptionsItem,
|
|
|
- ElTable,
|
|
|
- ElTableColumn,
|
|
|
- ElButton,
|
|
|
- ElDivider,
|
|
|
- ElCard
|
|
|
-} from "element-plus";
|
|
|
-import type {
|
|
|
- ReplenishmentSearchForm,
|
|
|
- ReplenishmentOrderRow,
|
|
|
- ReplenishmentSuggestion,
|
|
|
- SuggestionItem
|
|
|
-} from "./types";
|
|
|
-
|
|
|
-export function useReplenishment() {
|
|
|
- const form = reactive<ReplenishmentSearchForm>({
|
|
|
- orderNo: "",
|
|
|
- deviceId: "",
|
|
|
- status: undefined,
|
|
|
- timeRange: []
|
|
|
- });
|
|
|
- const formRef = ref();
|
|
|
- const dataList = ref<ReplenishmentOrderRow[]>([]);
|
|
|
- const loading = ref(true);
|
|
|
- const deviceOptions = ref<any[]>([]);
|
|
|
- const pagination = reactive<PaginationProps>({
|
|
|
- total: 0,
|
|
|
- pageSize: 10,
|
|
|
- currentPage: 1,
|
|
|
- background: true
|
|
|
- });
|
|
|
-
|
|
|
- const statusMap: Record<number, { text: string; type: string }> = {
|
|
|
- 0: { text: "草稿", type: "info" },
|
|
|
- 1: { text: "已提交", type: "warning" },
|
|
|
- 2: { text: "已同步ERP", type: "primary" },
|
|
|
- 3: { text: "已完成", type: "success" },
|
|
|
- 4: { text: "已取消", type: "danger" }
|
|
|
- };
|
|
|
-
|
|
|
- const columns: TableColumnList = [
|
|
|
- { label: "补货单号", prop: "orderNo", minWidth: 180 },
|
|
|
- { label: "门店名称", prop: "shopName", minWidth: 130 },
|
|
|
- { label: "设备ID", prop: "deviceId", minWidth: 130 },
|
|
|
- { label: "设备名称", prop: "deviceName", minWidth: 130 },
|
|
|
- { label: "补货数量", prop: "totalQuantity", width: 100 },
|
|
|
- {
|
|
|
- label: "补货金额",
|
|
|
- prop: "totalAmount",
|
|
|
- width: 110,
|
|
|
- formatter: ({ totalAmount }: any) =>
|
|
|
- totalAmount != null ? `¥${Number(totalAmount).toFixed(2)}` : "-"
|
|
|
- },
|
|
|
- { label: "供应商", prop: "supplierName", minWidth: 120 },
|
|
|
- {
|
|
|
- label: "状态",
|
|
|
- prop: "status",
|
|
|
- width: 100,
|
|
|
- cellRenderer: ({ row }: any) => {
|
|
|
- const s = statusMap[row.status];
|
|
|
- return s ? <ElTag type={s.type as any}>{s.text}</ElTag> : "-";
|
|
|
- }
|
|
|
- },
|
|
|
- { label: "创建人", prop: "creatorName", width: 100 },
|
|
|
- { label: "明细数", prop: "itemCount", width: 80 },
|
|
|
- {
|
|
|
- label: "创建时间",
|
|
|
- prop: "createTime",
|
|
|
- minWidth: 160,
|
|
|
- formatter: ({ createTime }: any) =>
|
|
|
- createTime ? dayjs(createTime).format("YYYY-MM-DD HH:mm:ss") : "-"
|
|
|
- },
|
|
|
- { label: "操作", fixed: "right", width: 280, slot: "operation" }
|
|
|
- ];
|
|
|
-
|
|
|
- // ==================== 搜索 / 分页 ====================
|
|
|
-
|
|
|
- async function onSearch() {
|
|
|
- loading.value = true;
|
|
|
- try {
|
|
|
- const params: any = {
|
|
|
- page: pagination.currentPage,
|
|
|
- pageSize: pagination.pageSize
|
|
|
- };
|
|
|
- if (form.orderNo) params.orderNo = form.orderNo;
|
|
|
- if (form.deviceId) params.deviceId = form.deviceId;
|
|
|
- if (form.status !== undefined && form.status !== null && form.status !== "")
|
|
|
- params.status = form.status;
|
|
|
- if (form.timeRange?.length === 2) {
|
|
|
- params.startTime = form.timeRange[0];
|
|
|
- params.endTime = form.timeRange[1];
|
|
|
- }
|
|
|
- const { data } = await getOrderList(params);
|
|
|
- if (data) {
|
|
|
- dataList.value = (data.list || []) as ReplenishmentOrderRow[];
|
|
|
- pagination.total = Number(data.total) || 0;
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.error("获取补货单列表失败:", e);
|
|
|
- } finally {
|
|
|
- setTimeout(() => { loading.value = false; }, 300);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function resetForm(formEl: any) {
|
|
|
- if (!formEl) return;
|
|
|
- formEl.resetFields();
|
|
|
- (form as any).timeRange = [];
|
|
|
- pagination.currentPage = 1;
|
|
|
- onSearch();
|
|
|
- }
|
|
|
-
|
|
|
- function handleSizeChange(val: number) {
|
|
|
- pagination.pageSize = val;
|
|
|
- onSearch();
|
|
|
- }
|
|
|
-
|
|
|
- function handleCurrentChange(val: number) {
|
|
|
- pagination.currentPage = val;
|
|
|
- onSearch();
|
|
|
- }
|
|
|
-
|
|
|
- async function fetchDeviceOptions() {
|
|
|
- try {
|
|
|
- const { data } = await getDeviceList({ page: 1, pageSize: 1000 });
|
|
|
- deviceOptions.value = data?.list || [];
|
|
|
- } catch (e) {
|
|
|
- console.error("获取设备列表失败:", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 创建补货单弹窗 ====================
|
|
|
-
|
|
|
- function handleCreate() {
|
|
|
- const selectedDevices = ref<any[]>([]);
|
|
|
- const suggestions = ref<ReplenishmentSuggestion[]>([]);
|
|
|
- const suggestionsLoading = ref(false);
|
|
|
- const commonForm = reactive({
|
|
|
- supplierName: "",
|
|
|
- warehouseName: "",
|
|
|
- expectedArrivalTime: ""
|
|
|
- });
|
|
|
- const innerDeviceOptions = ref<any[]>([]);
|
|
|
-
|
|
|
- async function loadDevices() {
|
|
|
- try {
|
|
|
- const { data } = await getDeviceList({ page: 1, pageSize: 1000 });
|
|
|
- innerDeviceOptions.value = data?.list || [];
|
|
|
- } catch (e) {
|
|
|
- console.error("加载设备失败:", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function handleSelectionChange(selection: any[]) {
|
|
|
- selectedDevices.value = selection;
|
|
|
- }
|
|
|
-
|
|
|
- async function fetchSuggestions() {
|
|
|
- if (selectedDevices.value.length === 0) {
|
|
|
- message("请先勾选设备", { type: "warning" });
|
|
|
- return;
|
|
|
- }
|
|
|
- suggestionsLoading.value = true;
|
|
|
- try {
|
|
|
- const ids = selectedDevices.value.map((d: any) => d.deviceId as string);
|
|
|
- const { data } = await getReplenishmentSuggestions(ids);
|
|
|
- const list: ReplenishmentSuggestion[] = Array.isArray(data) ? data : [];
|
|
|
- if (list.length === 0) {
|
|
|
- message("所选设备当前均无需补货", { type: "info" });
|
|
|
- }
|
|
|
- suggestions.value = list;
|
|
|
- } catch (e) {
|
|
|
- console.error("获取补货建议失败:", e);
|
|
|
- message("获取补货建议失败", { type: "error" });
|
|
|
- } finally {
|
|
|
- suggestionsLoading.value = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- async function doSubmit(done: () => void) {
|
|
|
- const validSuggestions = suggestions.value.filter(
|
|
|
- s => s.items.some(i => i.suggestedQuantity > 0)
|
|
|
- );
|
|
|
- if (validSuggestions.length === 0) {
|
|
|
- message("没有有效的补货项,请检查补货数量", { type: "warning" });
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const payloads = validSuggestions.map(s => ({
|
|
|
- deviceId: s.deviceId,
|
|
|
- shopId: s.shopId ? Number(s.shopId) : undefined,
|
|
|
- supplierName: commonForm.supplierName || undefined,
|
|
|
- warehouseName: commonForm.warehouseName || undefined,
|
|
|
- expectedArrivalTime: commonForm.expectedArrivalTime
|
|
|
- ? dayjs(commonForm.expectedArrivalTime).format("YYYY-MM-DD HH:mm:ss")
|
|
|
- : undefined,
|
|
|
- items: s.items
|
|
|
- .filter(i => i.suggestedQuantity > 0)
|
|
|
- .map(i => ({
|
|
|
- productId: Number(i.productId),
|
|
|
- productCode: i.productCode,
|
|
|
- productName: i.productName,
|
|
|
- plannedQuantity: i.suggestedQuantity,
|
|
|
- unitPrice: i.unitPrice != null ? i.unitPrice : undefined,
|
|
|
- shelfNum: i.shelfNum,
|
|
|
- position: i.position
|
|
|
- }))
|
|
|
- }));
|
|
|
-
|
|
|
- const results = await Promise.allSettled(
|
|
|
- payloads.map(p => createOrder(p))
|
|
|
- );
|
|
|
-
|
|
|
- const successCount = results.filter(r => r.status === "fulfilled").length;
|
|
|
- const failCount = results.filter(r => r.status === "rejected").length;
|
|
|
-
|
|
|
- if (failCount === 0) {
|
|
|
- message(`成功创建 ${successCount} 个补货单`, { type: "success" });
|
|
|
- } else {
|
|
|
- message(`创建完成:${successCount} 成功, ${failCount} 失败`, { type: "warning" });
|
|
|
- }
|
|
|
- done();
|
|
|
- onSearch();
|
|
|
- }
|
|
|
-
|
|
|
- const createContentRenderer = () => {
|
|
|
- const hasSuggestions = suggestions.value.length > 0;
|
|
|
-
|
|
|
- return (
|
|
|
- <div style="max-height: 65vh; overflow-y: auto;">
|
|
|
- {/* ===== 第一步:设备列表 ===== */}
|
|
|
- <div style="margin-bottom:8px;font-size:14px;font-weight:600;color:#303133;">
|
|
|
- 第一步:勾选需要补货的设备
|
|
|
- </div>
|
|
|
- <ElTable
|
|
|
- data={innerDeviceOptions.value}
|
|
|
- max-height={220}
|
|
|
- onSelectionChange={handleSelectionChange}
|
|
|
- >
|
|
|
- <ElTableColumn type="selection" width="55" />
|
|
|
- <ElTableColumn prop="deviceId" label="设备ID" minWidth={140} />
|
|
|
- <ElTableColumn prop="name" label="设备名称" minWidth={140} />
|
|
|
- <ElTableColumn prop="shopName" label="所属门店" minWidth={140} />
|
|
|
- </ElTable>
|
|
|
-
|
|
|
- <div style="margin-top:12px;display:flex;align-items:center;gap:12px;">
|
|
|
- <ElButton
|
|
|
- type="primary"
|
|
|
- loading={suggestionsLoading.value}
|
|
|
- onClick={fetchSuggestions}
|
|
|
- disabled={selectedDevices.value.length === 0}
|
|
|
- >
|
|
|
- 补货建议
|
|
|
- </ElButton>
|
|
|
- <span style="color:#909399;font-size:13px;">
|
|
|
- 已勾选 {selectedDevices.value.length} 台设备
|
|
|
- {hasSuggestions
|
|
|
- ? `,共 ${suggestions.value.reduce((s: number, sug) => s + sug.items.length, 0)} 项待补商品`
|
|
|
- : ""}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* ===== 第二步:补货明细 ===== */}
|
|
|
- {hasSuggestions && (
|
|
|
- <div style="margin-top:24px;">
|
|
|
- <div style="margin-bottom:12px;font-size:14px;font-weight:600;color:#303133;">
|
|
|
- 第二步:确认补货明细,填写供应商等信息
|
|
|
- </div>
|
|
|
-
|
|
|
- <div style="display:flex;gap:16px;flex-wrap:wrap;margin-bottom:16px;padding:12px;background:#fafafa;border-radius:6px;">
|
|
|
- <div style="display:flex;align-items:center;gap:6px;">
|
|
|
- <span style="font-size:13px;color:#606266;white-space:nowrap;">供应商</span>
|
|
|
- <ElInput v-model={commonForm.supplierName} placeholder="选填" clearable size="small" style="width:150px;" />
|
|
|
- </div>
|
|
|
- <div style="display:flex;align-items:center;gap:6px;">
|
|
|
- <span style="font-size:13px;color:#606266;white-space:nowrap;">仓库</span>
|
|
|
- <ElInput v-model={commonForm.warehouseName} placeholder="选填" clearable size="small" style="width:150px;" />
|
|
|
- </div>
|
|
|
- <div style="display:flex;align-items:center;gap:6px;">
|
|
|
- <span style="font-size:13px;color:#606266;white-space:nowrap;">预计到货</span>
|
|
|
- <ElDatePicker v-model={commonForm.expectedArrivalTime} type="datetime" placeholder="选填"
|
|
|
- value-format="YYYY-MM-DD HH:mm:ss" size="small" style="width:190px;" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {suggestions.value.map((sug: ReplenishmentSuggestion) => {
|
|
|
- const deviceTotalQty = sug.items.reduce(
|
|
|
- (sum: number, i) => sum + (i.suggestedQuantity || 0), 0
|
|
|
- );
|
|
|
- const deviceTotalAmt = sug.items.reduce(
|
|
|
- (sum: number, i) => sum + (i.suggestedQuantity || 0) * (i.unitPrice || 0), 0
|
|
|
- );
|
|
|
-
|
|
|
- const itemRows = sug.items.map((item: SuggestionItem, idx: number) => (
|
|
|
- <tr key={idx}>
|
|
|
- <td style="padding:6px 10px;border:1px solid #ebeef5;font-size:13px;">{item.productCode}</td>
|
|
|
- <td style="padding:6px 10px;border:1px solid #ebeef5;font-size:13px;">{item.productName || "-"}</td>
|
|
|
- <td style="padding:6px 10px;border:1px solid #ebeef5;text-align:center;font-size:13px;">{item.templateStock}</td>
|
|
|
- <td style="padding:6px 10px;border:1px solid #ebeef5;text-align:center;font-size:13px;">
|
|
|
- <span style={`font-weight:500;color:${item.currentStock <= 0 ? '#f56c6c' : '#67c23a'}`}>{item.currentStock}</span>
|
|
|
- </td>
|
|
|
- <td style="padding:4px 6px;border:1px solid #ebeef5;">
|
|
|
- <ElInputNumber v-model={item.suggestedQuantity} min={1} max={9999} size="small" controls-position="right" style="width:100px;" />
|
|
|
- </td>
|
|
|
- <td style="padding:4px 6px;border:1px solid #ebeef5;">
|
|
|
- <ElInput v-model={item.unitPrice} placeholder="单价" size="small" style="width:90px;" />
|
|
|
- </td>
|
|
|
- <td style="padding:6px 10px;border:1px solid #ebeef5;text-align:right;font-size:13px;font-weight:500;">
|
|
|
- ¥{((item.suggestedQuantity || 0) * (item.unitPrice || 0)).toFixed(2)}
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- ));
|
|
|
-
|
|
|
- return (
|
|
|
- <ElCard key={sug.deviceId} style="margin-bottom:12px;" shadow="hover">
|
|
|
- {{
|
|
|
- header: () => (
|
|
|
- <div style="display:flex;justify-content:space-between;align-items:center;">
|
|
|
- <span style="font-size:14px;font-weight:600;">
|
|
|
- {sug.deviceId}{sug.deviceName ? ` (${sug.deviceName})` : ""}
|
|
|
- <span style="margin:0 8px;color:#dcdfe6;">|</span>
|
|
|
- {sug.shopName || "未绑定门店"}
|
|
|
- </span>
|
|
|
- <span style="color:#409eff;font-size:13px;">{deviceTotalQty} 件 / ¥{deviceTotalAmt.toFixed(2)}</span>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- default: () => (
|
|
|
- <table style="width:100%;border-collapse:collapse;">
|
|
|
- <thead>
|
|
|
- <tr style="background:#f5f7fa;">
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">商品编码</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">商品名称</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">标准库存</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">当前库存</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">补货数量</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">单价</th>
|
|
|
- <th style="padding:8px 10px;border:1px solid #ebeef5;font-size:13px;font-weight:500;color:#606266;">小计</th>
|
|
|
- </tr>
|
|
|
- </thead>
|
|
|
- <tbody>{itemRows}</tbody>
|
|
|
- </table>
|
|
|
- )
|
|
|
- }}
|
|
|
- </ElCard>
|
|
|
- );
|
|
|
- })}
|
|
|
-
|
|
|
- {/* 提示 */}
|
|
|
- <div style="margin-top:16px;padding:10px 16px;background:#ecf5ff;border-radius:6px;color:#409eff;font-size:13px;">
|
|
|
- 确认补货明细无误后,点击「确认」按钮即可创建补货单
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- loadDevices();
|
|
|
- addDialog({
|
|
|
- title: "创建补货单",
|
|
|
- width: "80%",
|
|
|
- draggable: true,
|
|
|
- closeOnClickModal: false,
|
|
|
- fullscreen: deviceDetection(),
|
|
|
- contentRenderer: createContentRenderer,
|
|
|
- beforeSure: async (done: () => void) => {
|
|
|
- // 确保用户已获取补货建议
|
|
|
- if (suggestions.value.length === 0) {
|
|
|
- message("请先勾选设备并点击「补货建议」生成补货明细", { type: "warning" });
|
|
|
- return;
|
|
|
- }
|
|
|
- await doSubmit(done);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 查看详情弹窗 ====================
|
|
|
-
|
|
|
- function handleViewDetail(row: ReplenishmentOrderRow) {
|
|
|
- const orderDetail = ref<any>(null);
|
|
|
- const items = ref<any[]>([]);
|
|
|
- const detailLoading = ref(true);
|
|
|
-
|
|
|
- async function loadDetail() {
|
|
|
- detailLoading.value = true;
|
|
|
- try {
|
|
|
- const [orderRes, itemsRes] = await Promise.all([
|
|
|
- getOrderDetail(row.id),
|
|
|
- getOrderItems(row.id)
|
|
|
- ]);
|
|
|
- orderDetail.value = orderRes.data || (orderRes as any);
|
|
|
- items.value = Array.isArray(itemsRes.data) ? itemsRes.data : [];
|
|
|
- } catch (e) {
|
|
|
- console.error("获取补货单详情失败:", e);
|
|
|
- } finally {
|
|
|
- detailLoading.value = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const detailRenderer = () => {
|
|
|
- if (detailLoading.value) {
|
|
|
- return <div style="text-align:center;padding:40px;">加载中...</div>;
|
|
|
- }
|
|
|
- const o = orderDetail.value || {};
|
|
|
- const s = statusMap[o.status as number];
|
|
|
- return (
|
|
|
- <div style="max-height:60vh;overflow-y:auto;">
|
|
|
- <ElDescriptions column={2} border size="small">
|
|
|
- <ElDescriptionsItem label="补货单号" span={2}>
|
|
|
- {o.orderNo || "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="设备ID">{o.deviceId || "-"}</ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="设备名称">{o.deviceName || "-"}</ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="门店">{o.shopName || "-"}</ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="状态">
|
|
|
- {s ? <ElTag type={s.type as any} size="small">{s.text}</ElTag> : "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="总数量">{o.totalQuantity ?? "-"}</ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="总金额">
|
|
|
- {o.totalAmount != null ? `¥${Number(o.totalAmount).toFixed(2)}` : "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="供应商">
|
|
|
- {o.supplierName || "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="仓库">
|
|
|
- {o.warehouseName || "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="预计到货">
|
|
|
- {o.expectedArrivalTime
|
|
|
- ? dayjs(o.expectedArrivalTime).format("YYYY-MM-DD HH:mm:ss")
|
|
|
- : "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="创建人">{o.creatorName || "-"}</ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="创建时间">
|
|
|
- {o.createTime
|
|
|
- ? dayjs(o.createTime).format("YYYY-MM-DD HH:mm:ss")
|
|
|
- : "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- <ElDescriptionsItem label="备注" span={2}>
|
|
|
- {o.remark || "-"}
|
|
|
- </ElDescriptionsItem>
|
|
|
- </ElDescriptions>
|
|
|
-
|
|
|
- <ElDivider contentPosition="left">补货明细</ElDivider>
|
|
|
- <ElTable data={items.value} size="small" max-height={300}>
|
|
|
- <ElTableColumn prop="productCode" label="商品编码" minWidth={120} />
|
|
|
- <ElTableColumn prop="productName" label="商品名称" minWidth={130} />
|
|
|
- <ElTableColumn prop="plannedQuantity" label="计划数量" width={90} />
|
|
|
- <ElTableColumn prop="actualQuantity" label="实际数量" width={90} />
|
|
|
- <ElTableColumn prop="beforeStock" label="补货前库存" width={110} />
|
|
|
- <ElTableColumn prop="afterStock" label="补货后库存" width={110} />
|
|
|
- <ElTableColumn
|
|
|
- prop="unitPrice"
|
|
|
- label="单价"
|
|
|
- width={90}
|
|
|
- formatter={(r: any) =>
|
|
|
- r.unitPrice != null ? `¥${Number(r.unitPrice).toFixed(2)}` : "-"
|
|
|
- }
|
|
|
- />
|
|
|
- <ElTableColumn
|
|
|
- prop="totalPrice"
|
|
|
- label="小计"
|
|
|
- width={90}
|
|
|
- formatter={(r: any) =>
|
|
|
- r.totalPrice != null
|
|
|
- ? `¥${Number(r.totalPrice).toFixed(2)}`
|
|
|
- : "-"
|
|
|
- }
|
|
|
- />
|
|
|
- <ElTableColumn prop="shelfNum" label="层号" width={70} />
|
|
|
- <ElTableColumn prop="position" label="货道" width={80} />
|
|
|
- </ElTable>
|
|
|
- </div>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- loadDetail();
|
|
|
- addDialog({
|
|
|
- title: `补货单详情 - ${row.orderNo}`,
|
|
|
- width: "70%",
|
|
|
- draggable: true,
|
|
|
- closeOnClickModal: false,
|
|
|
- fullscreen: deviceDetection(),
|
|
|
- contentRenderer: detailRenderer,
|
|
|
- hideFooter: true
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 生命周期操作 ====================
|
|
|
-
|
|
|
- async function handleSubmit(row: ReplenishmentOrderRow) {
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm(`确认提交补货单 ${row.orderNo}?`, "提示", {
|
|
|
- confirmButtonText: "确定",
|
|
|
- cancelButtonText: "取消",
|
|
|
- type: "warning"
|
|
|
- });
|
|
|
- await submitOrder(row.id);
|
|
|
- message("提交成功", { type: "success" });
|
|
|
- onSearch();
|
|
|
- } catch {
|
|
|
- // cancelled
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- async function handleDelete(row: ReplenishmentOrderRow) {
|
|
|
- try {
|
|
|
- await deleteOrder(row.id);
|
|
|
- message("删除成功", { type: "success" });
|
|
|
- onSearch();
|
|
|
- } catch (e) {
|
|
|
- console.error("删除补货单失败:", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- async function handleSyncErp(row: ReplenishmentOrderRow) {
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm(
|
|
|
- `确认将补货单 ${row.orderNo} 同步到ERP?`,
|
|
|
- "提示",
|
|
|
- { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }
|
|
|
- );
|
|
|
- await syncToErp(row.id);
|
|
|
- message("同步成功", { type: "success" });
|
|
|
- onSearch();
|
|
|
- } catch {
|
|
|
- // cancelled
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- async function handleComplete(row: ReplenishmentOrderRow) {
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm(
|
|
|
- `确认完成补货单 ${row.orderNo}?`,
|
|
|
- "提示",
|
|
|
- { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }
|
|
|
- );
|
|
|
- await completeOrder(row.id);
|
|
|
- message("完成", { type: "success" });
|
|
|
- onSearch();
|
|
|
- } catch {
|
|
|
- // cancelled
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- async function handleCancel(row: ReplenishmentOrderRow) {
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm(
|
|
|
- `确认取消补货单 ${row.orderNo}?取消后不可恢复。`,
|
|
|
- "提示",
|
|
|
- { confirmButtonText: "确定", cancelButtonText: "取消", type: "error" }
|
|
|
- );
|
|
|
- await cancelOrder(row.id);
|
|
|
- message("已取消", { type: "success" });
|
|
|
- onSearch();
|
|
|
- } catch {
|
|
|
- // cancelled
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 初始化 ====================
|
|
|
-
|
|
|
- onMounted(async () => {
|
|
|
- await fetchDeviceOptions();
|
|
|
- onSearch();
|
|
|
- });
|
|
|
-
|
|
|
- return {
|
|
|
- form,
|
|
|
- formRef,
|
|
|
- loading,
|
|
|
- columns,
|
|
|
- dataList,
|
|
|
- pagination,
|
|
|
- deviceOptions,
|
|
|
- statusMap,
|
|
|
- onSearch,
|
|
|
- resetForm,
|
|
|
- handleSizeChange,
|
|
|
- handleCurrentChange,
|
|
|
- handleCreate,
|
|
|
- handleViewDetail,
|
|
|
- handleDelete,
|
|
|
- handleSubmit,
|
|
|
- handleSyncErp,
|
|
|
- handleComplete,
|
|
|
- handleCancel
|
|
|
- };
|
|
|
-}
|