From 90845519117abbd21955d589366280d77c9b6fc1 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 02 七月 2026 16:57:21 +0800
Subject: [PATCH] 银川 1.销售订单页面开发、联调 2.合同管理页面开发联调 3.项目代码相关配置修改
---
vite.config.ts | 3
src/api/erp/sale/order/index.ts | 14 +++
src/views/erp/sale/order/index.vue | 96 +++++++++++++++++++++--
src/views/erp/sale/order/modules/item-form.vue | 2
src/components/table-action/table-action.vue | 8 ++
src/components/table-action/typing.ts | 2
src/views/crm/contract/detail/data.ts | 5 +
src/views/crm/contract/detail/modules/info.vue | 27 ++++++
src/views/crm/contract/index.vue | 14 +++
src/views/erp/sale/order/data.ts | 17 ++--
src/views/crm/contract/data.ts | 27 ++++++
11 files changed, 194 insertions(+), 21 deletions(-)
diff --git a/src/api/erp/sale/order/index.ts b/src/api/erp/sale/order/index.ts
index 077ca9a..acc7a2c 100644
--- a/src/api/erp/sale/order/index.ts
+++ b/src/api/erp/sale/order/index.ts
@@ -100,3 +100,17 @@
export function exportSaleOrder(params: any) {
return requestClient.download('/erp/sale-order/export-excel', { params });
}
+
+/** 浣滃簾閿�鍞鍗� */
+export function cancelSaleOrder(id: number) {
+ return requestClient.put('/erp/sale-order/cancel', null, {
+ params: { id },
+ });
+}
+
+/** 鍚敤閿�鍞鍗曪紙鎭㈠宸蹭綔搴熻鍗曪級 */
+export function enableSaleOrder(id: number) {
+ return requestClient.put('/erp/sale-order/enable', null, {
+ params: { id },
+ });
+}
diff --git a/src/components/table-action/table-action.vue b/src/components/table-action/table-action.vue
index a265463..cdf81a0 100644
--- a/src/components/table-action/table-action.vue
+++ b/src/components/table-action/table-action.vue
@@ -97,6 +97,8 @@
attrs.onCancel = popConfirm.cancel;
}
+ // 涓嶈缃� getPopupContainer锛岃瀹冮粯璁ゆ寕杞藉埌 body锛岄伩鍏嶈閬尅
+
return attrs;
}
@@ -269,6 +271,12 @@
}
.ant-popconfirm {
+ width: 210px;
+
+ //.ant-popconfirm-message {
+ // white-space: nowrap;
+ //}
+
.ant-popconfirm-buttons {
.ant-btn {
margin-inline-start: 4px !important;
diff --git a/src/components/table-action/typing.ts b/src/components/table-action/typing.ts
index 1e44fb2..91814c5 100644
--- a/src/components/table-action/typing.ts
+++ b/src/components/table-action/typing.ts
@@ -12,6 +12,8 @@
cancel?: () => void;
icon?: string;
disabled?: boolean;
+ placement?: string;
+ getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
}
export interface ActionItem extends ButtonProps {
diff --git a/src/views/crm/contract/data.ts b/src/views/crm/contract/data.ts
index e9ac060..0f99e0a 100644
--- a/src/views/crm/contract/data.ts
+++ b/src/views/crm/contract/data.ts
@@ -277,6 +277,32 @@
allowClear: true,
},
},
+ {
+ fieldName: 'auditStatus',
+ label: '鍚堝悓鐘舵��',
+ component: 'Select',
+ componentProps: {
+ options: [
+ { label: '鏈彁浜�', value: 0 },
+ { label: '瀹℃壒涓�', value: 10 },
+ { label: '瀹℃牳閫氳繃', value: 20 },
+ { label: '瀹℃牳涓嶉�氳繃', value: 30 },
+ { label: '宸插彇娑�', value: 40 },
+ { label: '宸蹭綔搴�', value: 50 },
+ ],
+ placeholder: '璇烽�夋嫨鍚堝悓鐘舵��',
+ allowClear: true,
+ },
+ },
+ {
+ fieldName: 'orderNo',
+ label: '鍏宠仈璁㈠崟',
+ component: 'Input',
+ componentProps: {
+ placeholder: '璇疯緭鍏ヨ鍗曞彿',
+ allowClear: true,
+ },
+ },
];
}
@@ -287,6 +313,7 @@
field: 'no',
minWidth: 180,
fixed: 'left',
+ slots: { default: 'no' },
},
{
title: '鍚堝悓鍚嶇О',
diff --git a/src/views/crm/contract/detail/data.ts b/src/views/crm/contract/detail/data.ts
index 1602256..f0602ca 100644
--- a/src/views/crm/contract/detail/data.ts
+++ b/src/views/crm/contract/detail/data.ts
@@ -84,6 +84,11 @@
label: '鍏徃绛剧害浜�',
},
{
+ field: 'orderNo',
+ label: '閿�鍞鍗�',
+ slot: 'orderNo', // 浣跨敤 slot 鑷畾涔夋覆鏌�
+ },
+ {
field: 'remark',
label: '澶囨敞',
},
diff --git a/src/views/crm/contract/detail/modules/info.vue b/src/views/crm/contract/detail/modules/info.vue
index da23e23..df757d3 100644
--- a/src/views/crm/contract/detail/modules/info.vue
+++ b/src/views/crm/contract/detail/modules/info.vue
@@ -1,16 +1,20 @@
<script lang="ts" setup>
import type { CrmContractApi } from '#/api/crm/contract';
-import { Divider } from 'ant-design-vue';
+import { useRouter } from 'vue-router';
+
+import { Button, Divider } from 'ant-design-vue';
import { useDescription } from '#/components/description';
import { useFollowUpDetailSchema } from '#/views/crm/followup/data';
import { useDetailBaseSchema } from '../data';
-defineProps<{
+const props = defineProps<{
contract: CrmContractApi.Contract; // 鍚堝悓淇℃伅
}>();
+
+const router = useRouter();
const [BaseDescriptions] = useDescription({
title: '鍩烘湰淇℃伅',
@@ -27,11 +31,28 @@
class: 'mx-4',
schema: useFollowUpDetailSchema(),
});
+
+/** 鏌ョ湅閿�鍞鍗� */
+function handleViewOrder() {
+ if (props.contract.orderId) {
+ router.push({
+ path: '/erp/sale/order',
+ query: { orderId: props.contract.orderId },
+ });
+ }
+}
</script>
<template>
<div>
- <BaseDescriptions :data="contract" />
+ <BaseDescriptions :data="contract">
+ <template #orderNo="{ data }">
+ <Button v-if="data.orderId" type="link" @click="handleViewOrder">
+ {{ data.orderNo }}
+ </Button>
+ <span v-else>-</span>
+ </template>
+ </BaseDescriptions>
<Divider />
<SystemDescriptions :data="contract" />
</div>
diff --git a/src/views/crm/contract/index.vue b/src/views/crm/contract/index.vue
index 94b2b2a..99e19fa 100644
--- a/src/views/crm/contract/index.vue
+++ b/src/views/crm/contract/index.vue
@@ -8,7 +8,7 @@
import { Page, useVbenModal } from '../../../packages/effects/common-ui/src';
import { downloadFileFromBlobPart } from '../../../packages/utils/src';
-import { Button, message, Modal, Select, Tabs, Tag } from 'ant-design-vue';
+import { Button, message, Modal, Select, Tabs, Tag, Tooltip } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
@@ -238,6 +238,16 @@
{{ row.name }}
</Button>
</template>
+ <template #no="{ row }">
+ <Tooltip v-if="row.auditStatus === 50" title="璇ュ悎鍚屽凡浣滃簾锛岃鍗曞凡澶辨晥">
+ <span class="text-red-500 cursor-pointer" @click="handleDetail(row)">
+ {{ row.no }}
+ </span>
+ </Tooltip>
+ <Button v-else type="link" @click="handleDetail(row)">
+ {{ row.no }}
+ </Button>
+ </template>
<template #customerName="{ row }">
<Button type="link" @click="handleCustomerDetail(row)">
{{ row.customerName }}
@@ -258,6 +268,8 @@
<Tag v-if="row.auditStatus === 10" color="warning">瀹℃壒涓�</Tag>
<Tag v-if="row.auditStatus === 20" color="success">瀹℃牳閫氳繃</Tag>
<Tag v-if="row.auditStatus === 30" color="error">瀹℃牳涓嶉�氳繃</Tag>
+ <Tag v-if="row.auditStatus === 40" color="default">宸插彇娑�</Tag>
+ <Tag v-if="row.auditStatus === 50" color="error">宸蹭綔搴�</Tag>
</template>
<template #orderNo="{ row }">
<Button v-if="row.orderId" type="link" @click="handleViewOrder(row)">
diff --git a/src/views/erp/sale/order/data.ts b/src/views/erp/sale/order/data.ts
index 3d654e2..24cd0b3 100644
--- a/src/views/erp/sale/order/data.ts
+++ b/src/views/erp/sale/order/data.ts
@@ -1,8 +1,6 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
-import { DICT_TYPE } from '../../../../packages/constants/src';
-import { getDictOptions } from '../../../../packages/effects/hooks/src';
import { erpPriceInputFormatter } from '../../../../packages/utils/src';
import { z } from '#/adapter/form';
@@ -348,7 +346,11 @@
label: '鐘舵��',
component: 'Select',
componentProps: {
- options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'),
+ options: [
+ { label: '鏈鏍�', value: 10 },
+ { label: '宸插鏍�', value: 20 },
+ { label: '宸蹭綔搴�', value: 30 },
+ ],
placeholder: '璇烽�夋嫨鐘舵��',
allowClear: true,
},
@@ -406,6 +408,7 @@
title: '璁㈠崟鍗曞彿',
width: 200,
fixed: 'left',
+ slots: { default: 'no' },
},
{
field: 'productNames',
@@ -474,11 +477,9 @@
{
field: 'status',
title: '鐘舵��',
- minWidth: 120,
- cellRender: {
- name: 'CellDict',
- props: { type: DICT_TYPE.ERP_AUDIT_STATUS },
- },
+ minWidth: 100,
+ fixed: 'right',
+ slots: { default: 'status' },
},
{
title: '鎿嶄綔',
diff --git a/src/views/erp/sale/order/index.vue b/src/views/erp/sale/order/index.vue
index d72d704..abccc6d 100644
--- a/src/views/erp/sale/order/index.vue
+++ b/src/views/erp/sale/order/index.vue
@@ -8,11 +8,13 @@
import { Page, useVbenModal } from '../../../../packages/effects/common-ui/src';
import { downloadFileFromBlobPart, isEmpty } from '../../../../packages/utils/src';
-import { message } from 'ant-design-vue';
+import { message, Tag, Tooltip } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
+ cancelSaleOrder,
deleteSaleOrder,
+ enableSaleOrder,
exportSaleOrder,
getSaleOrderPage,
updateSaleOrderStatus,
@@ -80,6 +82,36 @@
try {
await updateSaleOrderStatus(row.id!, status);
message.success(`${status === 20 ? '瀹℃壒' : '鍙嶅鎵�'}鎴愬姛`);
+ handleRefresh();
+ } finally {
+ hideLoading();
+ }
+}
+
+/** 浣滃簾閿�鍞鍗� */
+async function handleCancel(row: ErpSaleOrderApi.SaleOrder) {
+ const hideLoading = message.loading({
+ content: '姝e湪浣滃簾璇ヨ鍗�...',
+ duration: 0,
+ });
+ try {
+ await cancelSaleOrder(row.id!);
+ message.success('浣滃簾鎴愬姛');
+ handleRefresh();
+ } finally {
+ hideLoading();
+ }
+}
+
+/** 鍚敤閿�鍞鍗曪紙鎭㈠宸蹭綔搴熻鍗曪級 */
+async function handleEnable(row: ErpSaleOrderApi.SaleOrder) {
+ const hideLoading = message.loading({
+ content: '姝e湪鍚敤璇ヨ鍗�...',
+ duration: 0,
+ });
+ try {
+ await enableSaleOrder(row.id!);
+ message.success('鍚敤鎴愬姛');
handleRefresh();
} finally {
hideLoading();
@@ -180,11 +212,26 @@
]"
/>
</template>
+ <template #no="{ row }">
+ <Tooltip v-if="row.status === 30" title="璇ヨ鍗曞凡浣滃簾锛岃鍗曞凡澶辨晥">
+ <span class="text-red-500 cursor-pointer" @click="handleDetail(row)">
+ {{ row.no }}
+ </span>
+ </Tooltip>
+ <a v-else class="text-primary cursor-pointer" @click="handleDetail(row)">
+ {{ row.no }}
+ </a>
+ </template>
<template #contractNo="{ row }">
<a v-if="row.contractId" class="text-primary cursor-pointer" @click="handleViewContract(row)">
{{ row.contractNo }}
</a>
<span v-else>-</span>
+ </template>
+ <template #status="{ row }">
+ <Tag v-if="row.status === 10" color="warning">鏈鏍�</Tag>
+ <Tag v-if="row.status === 20" color="success">宸插鏍�</Tag>
+ <Tag v-if="row.status === 30" color="error">宸蹭綔搴�</Tag>
</template>
<template #actions="{ row }">
<TableAction
@@ -201,21 +248,51 @@
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['erp:sale-order:update'],
- ifShow: () => row.status !== 20,
+ ifShow: () => row.status === 10,
onClick: handleEdit.bind(null, row),
},
{
- label: row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�',
+ label: '瀹℃壒',
type: 'link',
icon: ACTION_ICON.AUDIT,
auth: ['erp:sale-order:update-status'],
+ ifShow: () => row.status === 10,
popConfirm: {
- title: `纭${row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�'}${row.no}鍚楋紵`,
- confirm: handleUpdateStatus.bind(
- null,
- row,
- row.status === 10 ? 20 : 10,
- ),
+ title: `纭瀹℃壒${row.no}鍚楋紵`,
+ confirm: handleUpdateStatus.bind(null, row, 20),
+ },
+ },
+ {
+ label: '鍙嶅鎵�',
+ type: 'link',
+ icon: ACTION_ICON.AUDIT,
+ auth: ['erp:sale-order:update-status'],
+ ifShow: () => row.status === 20,
+ popConfirm: {
+ title: `纭鍙嶅鎵�${row.no}鍚楋紵`,
+ confirm: handleUpdateStatus.bind(null, row, 10),
+ },
+ },
+ {
+ label: '浣滃簾',
+ type: 'link',
+ icon: 'ant-design:stop-outlined',
+ auth: ['erp:sale-order:cancel'],
+ ifShow: () => row.status === 20,
+ popConfirm: {
+ title: `纭浣滃簾${row.no}鍚楋紵浣滃簾鍚庝笉鍙仮澶嶏紒`,
+ confirm: handleCancel.bind(null, row),
+ },
+ },
+ {
+ label: '鍚敤',
+ type: 'link',
+ icon: 'ant-design:check-circle-outlined',
+ auth: ['erp:sale-order:enable'],
+ ifShow: () => row.status === 30,
+ popConfirm: {
+ title: `纭鍚敤${row.no}鍚楋紵`,
+ confirm: handleEnable.bind(null, row),
},
},
{
@@ -224,6 +301,7 @@
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['erp:sale-order:delete'],
+ ifShow: () => row.status === 10,
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
confirm: handleDelete.bind(null, [row.id!]),
diff --git a/src/views/erp/sale/order/modules/item-form.vue b/src/views/erp/sale/order/modules/item-form.vue
index 20389e6..8dc45b3 100644
--- a/src/views/erp/sale/order/modules/item-form.vue
+++ b/src/views/erp/sale/order/modules/item-form.vue
@@ -229,6 +229,7 @@
<Grid class="w-full">
<template #productId="{ row }">
<Select
+ v-if="!disabled"
v-model:value="row.productId"
:options="productOptions"
:field-names="{ label: 'name', value: 'id' }"
@@ -237,6 +238,7 @@
show-search
@change="handleProductChange($event, row)"
/>
+ <span v-else>{{ row.productName || '-' }}</span>
</template>
<template #count="{ row }">
<InputNumber
diff --git a/vite.config.ts b/vite.config.ts
index 44d7717..fc97bd3 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -9,6 +9,9 @@
},
server: {
allowedHosts: true,
+ watch: {
+ ignored: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
+ },
proxy: {
'/admin-api': {
changeOrigin: true,
--
Gitblit v1.9.3