|
|
|
|
@@ -7,7 +7,7 @@ import { computed, onMounted, ref } from 'vue';
|
|
|
|
|
import { confirm, Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
|
|
|
|
|
import { formatDateTime } from '@vben/utils';
|
|
|
|
|
|
|
|
|
|
import { Card, message, TabPane, Tabs, Tag } from 'antdv-next';
|
|
|
|
|
import { Card, InputNumber, message, TabPane, Tabs, Tag } from 'antdv-next';
|
|
|
|
|
|
|
|
|
|
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
|
|
|
import {
|
|
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
|
|
getDailyPlanWorkPage,
|
|
|
|
|
startDailyPlanSleeving,
|
|
|
|
|
startDailyPlanStocking,
|
|
|
|
|
updateDailyPlanWeight,
|
|
|
|
|
} from '#/api/lms/dailyplan';
|
|
|
|
|
|
|
|
|
|
import Detail from '../management/modules/detail.vue';
|
|
|
|
|
@@ -32,8 +33,10 @@ const WORK_CANCELED = 3;
|
|
|
|
|
const STRATEGY_WEIGHT = 2;
|
|
|
|
|
|
|
|
|
|
const activeOrderStatus = ref(String(ORDER_IN_PROGRESS));
|
|
|
|
|
const activeWorkType = ref('1');
|
|
|
|
|
const strategies = ref<LmsDailyPlanApi.Strategy[]>([]);
|
|
|
|
|
const showWeight = computed(() => strategies.value.some((item) => item.strategyMode === STRATEGY_WEIGHT));
|
|
|
|
|
const showWeight = computed(() => strategyOf(Number(activeWorkType.value))?.strategyMode === STRATEGY_WEIGHT);
|
|
|
|
|
const weightDrafts = ref<Record<string, number>>({});
|
|
|
|
|
|
|
|
|
|
const [DetailDrawer, detailDrawerApi] = useVbenDrawer({ connectedComponent: Detail, destroyOnClose: true });
|
|
|
|
|
const [OperationModal, operationModalApi] = useVbenModal({ connectedComponent: Operation, destroyOnClose: true });
|
|
|
|
|
@@ -49,7 +52,7 @@ function strategyName(mode?: number) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateColumns() {
|
|
|
|
|
gridApi.setGridOptions({ columns: useGridColumns(showWeight.value) });
|
|
|
|
|
gridApi.setGridOptions({ columns: useGridColumns(Number(activeWorkType.value), showWeight.value) });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loadStrategies() {
|
|
|
|
|
@@ -74,6 +77,11 @@ function handleTabChange() {
|
|
|
|
|
handleRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleWorkTypeChange() {
|
|
|
|
|
weightDrafts.value = {};
|
|
|
|
|
updateColumns();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleDetail(row: LmsDailyPlanApi.DailyPlan) {
|
|
|
|
|
detailDrawerApi.setData(row).open();
|
|
|
|
|
}
|
|
|
|
|
@@ -82,20 +90,59 @@ function handleOperation(row: LmsDailyPlanApi.DailyPlan, type: string) {
|
|
|
|
|
operationModalApi.setData({ row, type }).open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isCancelableWorkStatus(status: number) {
|
|
|
|
|
return status === WORK_NOT_STARTED || status === WORK_IN_PROGRESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleStrategy(type: number) {
|
|
|
|
|
const strategy = strategyOf(type);
|
|
|
|
|
if (strategy) strategyModalApi.setData(strategy).open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSort() {
|
|
|
|
|
const rows = gridApi.grid?.getData() as LmsDailyPlanApi.DailyPlan[];
|
|
|
|
|
if (!rows?.length) {
|
|
|
|
|
message.warning('当前页没有可调整的日计划');
|
|
|
|
|
async function handleSort() {
|
|
|
|
|
const filters = await gridApi.formApi.getValues();
|
|
|
|
|
const pageSize = 100;
|
|
|
|
|
let pageNo = 1;
|
|
|
|
|
const rows: LmsDailyPlanApi.DailyPlan[] = [];
|
|
|
|
|
while (true) {
|
|
|
|
|
const page = await getDailyPlanWorkPage({
|
|
|
|
|
...filters,
|
|
|
|
|
orderStatus: Number(activeOrderStatus.value),
|
|
|
|
|
pageNo,
|
|
|
|
|
pageSize,
|
|
|
|
|
});
|
|
|
|
|
rows.push(...page.list);
|
|
|
|
|
if (page.list.length === 0 || rows.length >= page.total) break;
|
|
|
|
|
pageNo += 1;
|
|
|
|
|
}
|
|
|
|
|
if (rows.length === 0) {
|
|
|
|
|
message.warning('当前状态没有可调整的日计划');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sortModalApi.setData(rows).open();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getWeightDraft(row: LmsDailyPlanApi.DailyPlan) {
|
|
|
|
|
return weightDrafts.value[String(row.dailyPlanId)] ?? row.weight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setWeightDraft(row: LmsDailyPlanApi.DailyPlan, value: null | number) {
|
|
|
|
|
weightDrafts.value[String(row.dailyPlanId)] = value ?? row.weight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleWeightSave(row: LmsDailyPlanApi.DailyPlan) {
|
|
|
|
|
const weight = getWeightDraft(row);
|
|
|
|
|
if (!Number.isInteger(weight) || weight <= 0) {
|
|
|
|
|
message.warning('权重必须为正整数');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await confirm(`确认将 ${row.planCode} 的权重调整为 ${weight} 吗?`);
|
|
|
|
|
await updateDailyPlanWeight({ id: row.dailyPlanId, version: row.version, weight });
|
|
|
|
|
message.success('权重修改成功');
|
|
|
|
|
delete weightDrafts.value[String(row.dailyPlanId)];
|
|
|
|
|
handleRefresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleStartWork(row: LmsDailyPlanApi.DailyPlan, target: 'sleeving' | 'stocking') {
|
|
|
|
|
const label = target === 'stocking' ? '备货' : '套管';
|
|
|
|
|
await confirm(`确认开始${label}吗?本操作只改变日计划状态,实际任务由定时器后续生成。`);
|
|
|
|
|
@@ -118,7 +165,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|
|
|
|
wrapperClass: 'grid grid-cols-1 gap-x-3 md:grid-cols-2 xl:grid-cols-4',
|
|
|
|
|
},
|
|
|
|
|
gridOptions: {
|
|
|
|
|
columns: useGridColumns(false),
|
|
|
|
|
columns: useGridColumns(1, false),
|
|
|
|
|
height: 'auto',
|
|
|
|
|
keepSource: true,
|
|
|
|
|
proxyConfig: {
|
|
|
|
|
@@ -148,7 +195,12 @@ onMounted(loadStrategies);
|
|
|
|
|
<SortModal @success="handleSuccess" />
|
|
|
|
|
|
|
|
|
|
<div class="mb-4 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
|
|
|
|
<Card v-for="type in [1, 2]" :key="type" size="small">
|
|
|
|
|
<Card
|
|
|
|
|
v-for="type in [1, 2]"
|
|
|
|
|
:key="type"
|
|
|
|
|
:class="{ 'ring-2 ring-primary': Number(activeWorkType) === type }"
|
|
|
|
|
size="small"
|
|
|
|
|
>
|
|
|
|
|
<div class="flex items-center justify-between gap-4">
|
|
|
|
|
<div>
|
|
|
|
|
<div class="mb-2 font-medium">{{ type === 1 ? '备货策略' : '套管策略' }}</div>
|
|
|
|
|
@@ -166,6 +218,11 @@ onMounted(loadStrategies);
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Tabs v-model:active-key="activeWorkType" class="mb-2" @change="handleWorkTypeChange">
|
|
|
|
|
<TabPane key="1" tab="备货作业" />
|
|
|
|
|
<TabPane key="2" tab="套管作业" />
|
|
|
|
|
</Tabs>
|
|
|
|
|
|
|
|
|
|
<Tabs v-model:active-key="activeOrderStatus" class="mb-2" @change="handleTabChange">
|
|
|
|
|
<TabPane :key="String(ORDER_IN_PROGRESS)" tab="进行中" />
|
|
|
|
|
<TabPane :key="String(ORDER_CANCELED)" tab="已取消" />
|
|
|
|
|
@@ -180,18 +237,31 @@ onMounted(loadStrategies);
|
|
|
|
|
<template #orderCode="{ row }">{{ row.erpOrderCode || row.manualOrderCode || '-' }}</template>
|
|
|
|
|
<template #stockingProgress="{ row }">{{ row.stockedQty }} / {{ row.totalQty }}</template>
|
|
|
|
|
<template #sleevingProgress="{ row }">{{ row.sleevedQty }} / {{ row.totalQty }}</template>
|
|
|
|
|
<template #weight="{ row }">
|
|
|
|
|
<div class="flex items-center gap-1">
|
|
|
|
|
<InputNumber
|
|
|
|
|
:min="1"
|
|
|
|
|
:precision="0"
|
|
|
|
|
:value="getWeightDraft(row)"
|
|
|
|
|
class="w-20"
|
|
|
|
|
@update:value="setWeightDraft(row, $event)"
|
|
|
|
|
/>
|
|
|
|
|
<TableAction
|
|
|
|
|
:actions="[{ label: '保存', type: 'link', auth: ['lms:daily-plan:schedule'], onClick: handleWeightSave.bind(null, row) }]"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<template #actions="{ row }">
|
|
|
|
|
<TableAction
|
|
|
|
|
:actions="[
|
|
|
|
|
{ label: '详情', type: 'link', auth: ['lms:daily-plan:query'], onClick: handleDetail.bind(null, row) },
|
|
|
|
|
{ label: '追加', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS, onClick: handleOperation.bind(null, row, 'append') },
|
|
|
|
|
{ label: '调权重', type: 'link', auth: ['lms:daily-plan:schedule'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && showWeight, onClick: handleOperation.bind(null, row, 'weight') },
|
|
|
|
|
{ label: '开始备货', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && row.stockingStatus === WORK_NOT_STARTED, onClick: handleStartWork.bind(null, row, 'stocking') },
|
|
|
|
|
{ label: '取消备货', type: 'link', danger: true, auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && [WORK_NOT_STARTED, WORK_IN_PROGRESS].includes(row.stockingStatus), onClick: handleOperation.bind(null, row, 'cancelStocking') },
|
|
|
|
|
{ label: '恢复备货', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && row.stockingStatus === WORK_CANCELED, onClick: handleOperation.bind(null, row, 'restoreStocking') },
|
|
|
|
|
{ label: '开始套管', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && row.sleevingStatus === WORK_NOT_STARTED, onClick: handleStartWork.bind(null, row, 'sleeving') },
|
|
|
|
|
{ label: '取消套管', type: 'link', danger: true, auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && [WORK_NOT_STARTED, WORK_IN_PROGRESS].includes(row.sleevingStatus), onClick: handleOperation.bind(null, row, 'cancelSleeving') },
|
|
|
|
|
{ label: '恢复套管', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS && row.sleevingStatus === WORK_CANCELED, onClick: handleOperation.bind(null, row, 'restoreSleeving') },
|
|
|
|
|
{ label: '追加', type: 'link', auth: ['lms:daily-plan:start'], ifShow: row.orderStatus === ORDER_IN_PROGRESS, onClick: handleOperation.bind(null, row, 'append') },
|
|
|
|
|
{ label: '开始备货', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '1' && row.orderStatus === ORDER_IN_PROGRESS && row.stockingStatus === WORK_NOT_STARTED, onClick: handleStartWork.bind(null, row, 'stocking') },
|
|
|
|
|
{ label: '取消备货', type: 'link', danger: true, auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '1' && row.orderStatus === ORDER_IN_PROGRESS && isCancelableWorkStatus(row.stockingStatus), onClick: handleOperation.bind(null, row, 'cancelStocking') },
|
|
|
|
|
{ label: '恢复备货', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '1' && row.orderStatus === ORDER_IN_PROGRESS && row.stockingStatus === WORK_CANCELED, onClick: handleOperation.bind(null, row, 'restoreStocking') },
|
|
|
|
|
{ label: '开始套管', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '2' && row.orderStatus === ORDER_IN_PROGRESS && row.sleevingStatus === WORK_NOT_STARTED, onClick: handleStartWork.bind(null, row, 'sleeving') },
|
|
|
|
|
{ label: '取消套管', type: 'link', danger: true, auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '2' && row.orderStatus === ORDER_IN_PROGRESS && isCancelableWorkStatus(row.sleevingStatus), onClick: handleOperation.bind(null, row, 'cancelSleeving') },
|
|
|
|
|
{ label: '恢复套管', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: activeWorkType === '2' && row.orderStatus === ORDER_IN_PROGRESS && row.sleevingStatus === WORK_CANCELED, onClick: handleOperation.bind(null, row, 'restoreSleeving') },
|
|
|
|
|
{ label: '结束订单', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS, onClick: handleFinish.bind(null, row) },
|
|
|
|
|
{ label: '取消订单', type: 'link', danger: true, auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_IN_PROGRESS, onClick: handleOperation.bind(null, row, 'cancelOrder') },
|
|
|
|
|
{ label: '恢复订单', type: 'link', auth: ['lms:daily-plan:operate'], ifShow: row.orderStatus === ORDER_CANCELED, onClick: handleOperation.bind(null, row, 'restoreOrder') },
|
|
|
|
|
|