云
12 小时以前 bef3d94968fc70667f3123cb23ee69550e08a5ca
feat(crm): 优化合同管理及待办功能

- 移除安灯报警提醒项
- 优化合同审核和提醒列表,修复详情跳转逻辑错误
- 添加合同编号和订单号链接跳转功能
- 显示合同审核状态标签和订单信息
- 优化客户相关待办列表,添加合同数量和金额统计
- 重构待办数量获取逻辑,支持独立加载避免单个接口失败影响其他待办
- 添加合同文档下载功能,支持Word格式导出
- 优化回款审核和计划提醒功能,修复数据关联错误
- 从车间管理中移除面积字段相关显示和配置
- 添加操作权限控制和流程实例验证
已修改15个文件
已添加1个文件
270 ■■■■■ 文件已修改
src/api/crm/contract/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/contract-document.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/contract-audit-list.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/contract-remind-list.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/customer-follow-list.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/customer-put-pool-remind-list.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/customer-today-contact-list.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/receivable-audit-list.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/backlog/modules/receivable-plan-remind-list.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/detail/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/contract/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/crm/saleQuotation/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/home/modules/alert-panel.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/workstation/components/workshop-select.vue 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/workstation/workshop/data.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/crm/contract/index.ts
@@ -93,6 +93,11 @@
  );
}
/** æŒ‰è´­é”€åˆåŒæ¨¡æ¿ä¸‹è½½ Word æ–‡ä»¶ */
export function downloadContractDocument(id: number) {
  return requestClient.download('/crm/contract/download-document', { params: { id } });
}
/** æŸ¥è¯¢åˆåŒè¯¦æƒ… */
export function getContract(id: number) {
  return requestClient.get<CrmContractApi.Contract>(
src/utils/contract-document.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
import { downloadFileFromBlobPart } from '@vben/utils';
import { downloadContractDocument } from '#/api/crm/contract';
export async function downloadContractWord(id: number, no?: string) {
  const source = await downloadContractDocument(id);
  const suffix = (no || String(id)).replaceAll(/[\\/:*?"<>|]/g, '_');
  downloadFileFromBlobPart({ fileName: `购销合同-${suffix}.docx`, source });
}
src/views/crm/backlog/index.vue
@@ -1,4 +1,6 @@
<script lang="ts" setup>
import type { Ref } from 'vue';
import { computed, onActivated, onMounted, ref, watch } from 'vue';
import { Page } from '@vben/common-ui';
@@ -78,16 +80,32 @@
  leftMenu.value = item.menu;
}
/** èŽ·å–æ•°é‡ */
async function getCount() {
  customerTodayContactCount.value = await getTodayContactCustomerCount();
  customerPutPoolRemindCount.value = await getPutPoolRemindCustomerCount();
  customerFollowCount.value = await getFollowCustomerCount();
  clueFollowCount.value = await getFollowClueCount();
  if (!automaticApproval.value) contractAuditCount.value = await getAuditContractCount();
  contractRemindCount.value = await getRemindContractCount();
  if (!automaticApproval.value) receivableAuditCount.value = await getAuditReceivableCount();
  receivablePlanRemindCount.value = await getReceivablePlanRemindCount();
/** ç‹¬ç«‹åŠ è½½å„ç±»æ•°é‡ï¼Œå•ä¸ªæŽ¥å£å¤±è´¥ä¸é˜»æ–­å…¶ä»–å¾…åŠžã€‚ */
let countRequest: Promise<void> | undefined;
function getCount() {
  if (countRequest) return countRequest;
  const requests: [Ref<number>, () => Promise<number>][] = [
    [customerTodayContactCount, getTodayContactCustomerCount],
    [customerPutPoolRemindCount, getPutPoolRemindCustomerCount],
    [customerFollowCount, getFollowCustomerCount],
    [clueFollowCount, getFollowClueCount],
    [contractRemindCount, getRemindContractCount],
    [receivablePlanRemindCount, getReceivablePlanRemindCount],
  ];
  if (!automaticApproval.value) {
    requests.push(
      [contractAuditCount, getAuditContractCount],
      [receivableAuditCount, getAuditReceivableCount],
    );
  }
  countRequest = Promise.allSettled(
    requests.map(async ([count, request]) => {
      count.value = await request();
    }),
  ).then(() => undefined).finally(() => {
    countRequest = undefined;
  });
  return countRequest;
}
/** æ¿€æ´»æ—¶ */
@@ -126,7 +144,7 @@
          </template>
        </List>
      </Card>
      <component class="ml-4 w-4/5" :is="currentComponent" />
      <component class="ml-4 w-4/5" :is="currentComponent" @refresh="getCount" />
    </div>
  </Page>
</template>
src/views/crm/backlog/modules/contract-audit-list.vue
@@ -5,7 +5,7 @@
import { useRouter } from 'vue-router';
import { Button } from 'ant-design-vue';
import { Button, Tag } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getContractPage } from '#/api/crm/contract';
@@ -29,17 +29,21 @@
}
/** æ‰“开客户详情 */
function handleCustomerDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
  if (row.customerId) push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
}
/** æ‰“开联系人详情 */
function handleContactDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmContactDetail', params: { id: row.id } });
  if (row.signContactId) push({ name: 'CrmContactDetail', params: { id: row.signContactId } });
}
/** æ‰“开商机详情 */
function handleBusinessDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmBusinessDetail', params: { id: row.id } });
  if (row.businessId) push({ name: 'CrmBusinessDetail', params: { id: row.businessId } });
}
function handleViewOrder(row: CrmContractApi.Contract) {
  if (row.orderId) push({ name: 'ErpSaleOrder', query: { id: row.orderId } });
}
const [Grid] = useVbenVxeGrid({
@@ -87,6 +91,11 @@
<template>
  <Grid>
    <template #no="{ row }">
      <Button type="link" @click="handleContractDetail(row)">
        {{ row.no }}
      </Button>
    </template>
    <template #name="{ row }">
      <Button type="link" @click="handleContractDetail(row)">
        {{ row.name }}
@@ -102,10 +111,23 @@
        {{ row.businessName }}
      </Button>
    </template>
    <template #contactName="{ row }">
    <template #signContactName="{ row }">
      <Button type="link" @click="handleContactDetail(row)">
        {{ row.contactName }}
        {{ row.signContactName }}
      </Button>
    </template>
    <template #auditStatus="{ row }">
      <Tag v-if="row.auditStatus === 0">未提交</Tag>
      <Tag v-else-if="row.auditStatus === 10" color="warning">审批中</Tag>
      <Tag v-else-if="row.auditStatus === 20" color="success">审核通过</Tag>
      <Tag v-else-if="row.auditStatus === 30" color="error">审核不通过</Tag>
      <Tag v-else-if="row.auditStatus === 40">已取消</Tag>
      <Tag v-else-if="row.auditStatus === 50" color="error">已作废</Tag>
      <span v-else>—</span>
    </template>
    <template #orderNo="{ row }">
      <Button v-if="row.orderId" type="link" @click="handleViewOrder(row)">{{ row.orderNo }}</Button>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <TableAction
@@ -114,6 +136,8 @@
            label: '查看审批',
            type: 'link',
            icon: ACTION_ICON.VIEW,
            auth: ['crm:contract:update'],
            ifShow: !!row.processInstanceId,
            onClick: handleProcessDetail.bind(null, row),
          },
        ]"
src/views/crm/backlog/modules/contract-remind-list.vue
@@ -5,7 +5,7 @@
import { useRouter } from 'vue-router';
import { Button } from 'ant-design-vue';
import { Button, Tag } from 'ant-design-vue';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getContractPage } from '#/api/crm/contract';
@@ -30,17 +30,21 @@
/** æ‰“开客户详情 */
function handleCustomerDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
  if (row.customerId) push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
}
/** æ‰“开联系人详情 */
function handleContactDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmContactDetail', params: { id: row.id } });
  if (row.signContactId) push({ name: 'CrmContactDetail', params: { id: row.signContactId } });
}
/** æ‰“开商机详情 */
function handleBusinessDetail(row: CrmContractApi.Contract) {
  push({ name: 'CrmBusinessDetail', params: { id: row.id } });
  if (row.businessId) push({ name: 'CrmBusinessDetail', params: { id: row.businessId } });
}
function handleViewOrder(row: CrmContractApi.Contract) {
  if (row.orderId) push({ name: 'ErpSaleOrder', query: { id: row.orderId } });
}
const [Grid] = useVbenVxeGrid({
@@ -88,6 +92,11 @@
<template>
  <Grid>
    <template #no="{ row }">
      <Button type="link" @click="handleContractDetail(row)">
        {{ row.no }}
      </Button>
    </template>
    <template #name="{ row }">
      <Button type="link" @click="handleContractDetail(row)">
        {{ row.name }}
@@ -108,6 +117,19 @@
        {{ row.signContactName }}
      </Button>
    </template>
    <template #auditStatus="{ row }">
      <Tag v-if="row.auditStatus === 0">未提交</Tag>
      <Tag v-else-if="row.auditStatus === 10" color="warning">审批中</Tag>
      <Tag v-else-if="row.auditStatus === 20" color="success">审核通过</Tag>
      <Tag v-else-if="row.auditStatus === 30" color="error">审核不通过</Tag>
      <Tag v-else-if="row.auditStatus === 40">已取消</Tag>
      <Tag v-else-if="row.auditStatus === 50" color="error">已作废</Tag>
      <span v-else>—</span>
    </template>
    <template #orderNo="{ row }">
      <Button v-if="row.orderId" type="link" @click="handleViewOrder(row)">{{ row.orderNo }}</Button>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <TableAction
        :actions="[
@@ -115,6 +137,7 @@
            label: '查看审批',
            type: 'link',
            auth: ['crm:contract:update'],
            ifShow: !!row.processInstanceId,
            onClick: handleProcessDetail.bind(null, row),
          },
        ]"
src/views/crm/backlog/modules/customer-follow-list.vue
@@ -4,6 +4,7 @@
import type { CrmCustomerApi } from '#/api/crm/customer';
import { useRouter } from 'vue-router';
import { erpNumberFormatter } from '@vben/utils';
import { Button } from 'ant-design-vue';
@@ -68,6 +69,10 @@
    <template #name="{ row }">
      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
    </template>
    <template #contracts="{ row }">
      <span v-if="row.contractCount">{{ row.contractCount }} ä»½ Â· Â¥{{ erpNumberFormatter(row.contractTotalPrice, 2) }}</span>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <Button type="link" @click="handleDetail(row)">查看详情</Button>
    </template>
src/views/crm/backlog/modules/customer-put-pool-remind-list.vue
@@ -4,11 +4,12 @@
import type { CrmCustomerApi } from '#/api/crm/customer';
import { useRouter } from 'vue-router';
import { erpNumberFormatter } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getCustomerPage } from '#/api/crm/customer';
import { getPutPoolRemindCustomerPage } from '#/api/crm/customer';
import { useGridColumns } from '#/views/crm/customer/data';
import { SCENE_TYPES } from '../data';
@@ -42,10 +43,9 @@
    proxyConfig: {
      ajax: {
        query: async ({ page }, formValues) => {
          return await getCustomerPage({
          return await getPutPoolRemindCustomerPage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            pool: true, // å›ºå®š å…¬æµ·å‚数为 true
            ...formValues,
          });
        },
@@ -68,6 +68,10 @@
    <template #name="{ row }">
      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
    </template>
    <template #contracts="{ row }">
      <span v-if="row.contractCount">{{ row.contractCount }} ä»½ Â· Â¥{{ erpNumberFormatter(row.contractTotalPrice, 2) }}</span>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <Button type="link" @click="handleDetail(row)">查看详情</Button>
    </template>
src/views/crm/backlog/modules/customer-today-contact-list.vue
@@ -4,6 +4,7 @@
import type { CrmCustomerApi } from '#/api/crm/customer';
import { useRouter } from 'vue-router';
import { erpNumberFormatter } from '@vben/utils';
import { Button } from 'ant-design-vue';
@@ -78,6 +79,10 @@
    <template #name="{ row }">
      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
    </template>
    <template #contracts="{ row }">
      <span v-if="row.contractCount">{{ row.contractCount }} ä»½ Â· Â¥{{ erpNumberFormatter(row.contractTotalPrice, 2) }}</span>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <Button type="link" @click="handleDetail(row)">查看详情</Button>
    </template>
src/views/crm/backlog/modules/receivable-audit-list.vue
@@ -7,13 +7,14 @@
import { Button, message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getReceivablePage, updateReceivableStatus } from '#/api/crm/receivable';
import { useGridColumns } from '#/views/crm/receivable/data';
import { AUDIT_STATUS } from '../data';
const { push } = useRouter();
const emit = defineEmits<{ refresh: [] }>();
/** å®¡æ ¸ */
async function handleAudit(row: CrmReceivableApi.Receivable) {
@@ -24,7 +25,8 @@
  try {
    await updateReceivableStatus(row.id!, 20);
    message.success('审核成功');
    gridApi.query();
    await gridApi.query();
    emit('refresh');
  } finally {
    hideLoading();
  }
@@ -42,7 +44,11 @@
/** æ‰“开合同详情 */
function handleContractDetail(row: CrmReceivableApi.Receivable) {
  push({ name: 'CrmContractDetail', params: { id: row.contractId } });
  if (row.contractId) push({ name: 'CrmContractDetail', params: { id: row.contractId } });
}
function handleInvoiceDetail(row: CrmReceivableApi.Receivable) {
  if (row.invoiceId) push({ name: 'CrmInvoiceDetail', params: { id: row.invoiceId } });
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -50,7 +56,7 @@
    schema: [
      {
        fieldName: 'auditStatus',
        label: '合同状态',
        label: '审核状态',
        component: 'Select',
        componentProps: {
          allowClear: true,
@@ -70,6 +76,7 @@
          return await getReceivablePage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            sceneType: 1,
            ...formValues,
          });
        },
@@ -100,18 +107,26 @@
      </Button>
    </template>
    <template #contractNo="{ row }">
      <Button type="link" @click="handleContractDetail(row)">
        {{ row.contractNo }}
      <Button v-if="row.contractId" type="link" @click="handleContractDetail(row)">
        {{ row.contract?.no ?? row.contractNo ?? '—' }}
      </Button>
      <span v-else>—</span>
    </template>
    <template #invoiceNo="{ row }">
      <template v-if="row.invoice">
        <Button type="link" @click="handleInvoiceDetail(row)">{{ row.invoice.no }}</Button>
        <span> / {{ row.invoice.invoiceNo ?? '—' }} / Â¥{{ row.invoice.price ?? 0 }}</span>
      </template>
      <span v-else>—</span>
    </template>
    <template #actions="{ row }">
      <Button
        v-if="row.auditStatus === 10"
        type="link"
        @click="handleAudit(row)"
      >
        å®¡æ ¸
      </Button>
      <TableAction :actions="[{
        label: '审核',
        type: 'link',
        auth: ['crm:receivable:update'],
        ifShow: row.auditStatus === 10,
        onClick: handleAudit.bind(null, row),
      }]" />
    </template>
  </Grid>
</template>
src/views/crm/backlog/modules/receivable-plan-remind-list.vue
@@ -9,7 +9,7 @@
import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getReceivablePlanPage } from '#/api/crm/receivable/plan';
import Form from '#/views/crm/receivable/modules/form.vue';
import { useGridColumns } from '#/views/crm/receivable/plan/data';
@@ -17,15 +17,21 @@
import { RECEIVABLE_REMIND_TYPE } from '../data';
const { push } = useRouter();
const emit = defineEmits<{ refresh: [] }>();
function handleRefresh() {
  gridApi.query();
  emit('refresh');
}
const [FormModal, formModalApi] = useVbenModal({
  connectedComponent: Form,
  destroyOnClose: true,
});
/** æ‰“开回款详情 */
/** æ‰“开回款计划详情 */
function handleDetail(row: CrmReceivablePlanApi.Plan) {
  push({ name: 'CrmReceivableDetail', params: { id: row.id } });
  push({ name: 'CrmReceivablePlanDetail', params: { id: row.id } });
}
/** æ‰“开客户详情 */
@@ -35,15 +41,16 @@
/** åˆ›å»ºå›žæ¬¾ */
function handleCreateReceivable(row: CrmReceivablePlanApi.Plan) {
  if (row.receivableId) return;
  formModalApi.setData({ plan: row }).open();
}
const [Grid] = useVbenVxeGrid({
const [Grid, gridApi] = useVbenVxeGrid({
  formOptions: {
    schema: [
      {
        fieldName: 'remindType',
        label: '合同状态',
        label: '回款状态',
        component: 'Select',
        componentProps: {
          allowClear: true,
@@ -63,6 +70,7 @@
          return await getReceivablePlanPage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            sceneType: 1,
            ...formValues,
          });
        },
@@ -82,7 +90,7 @@
<template>
  <div>
    <FormModal />
    <FormModal @success="handleRefresh" />
    <Grid>
      <template #customerName="{ row }">
        <Button type="link" @click="handleCustomerDetail(row)">
@@ -93,9 +101,13 @@
        <Button type="link" @click="handleDetail(row)">{{ row.period }}</Button>
      </template>
      <template #actions="{ row }">
        <Button type="link" @click="handleCreateReceivable(row)">
          åˆ›å»ºå›žæ¬¾
        </Button>
        <TableAction :actions="[{
          label: '创建回款',
          type: 'link',
          auth: ['crm:receivable:create'],
          ifShow: !row.receivableId,
          onClick: handleCreateReceivable.bind(null, row),
        }]" />
      </template>
    </Grid>
  </div>
src/views/crm/contract/detail/index.vue
@@ -17,6 +17,7 @@
import { OperateLog } from '#/components/operate-log';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import { downloadContractWord } from '#/utils/contract-document';
import { FollowUp } from '#/views/crm/followup';
import { PermissionList, TransferForm } from '#/views/crm/permission';
import { ProductDetailsList } from '#/views/crm/product/components';
@@ -119,6 +120,13 @@
            onClick: handleEdit,
          },
          {
            label: '下载合同',
            type: 'primary',
            icon: 'lucide:download',
            auth: ['crm:contract:query'],
            onClick: () => downloadContractWord(contractId, contract.no),
          },
          {
            label: '转移',
            type: 'primary',
            ifShow: permissionListRef?.validateOwnerUser,
src/views/crm/contract/index.vue
@@ -21,6 +21,7 @@
} from '#/api/crm/contract';
import { $t } from '#/locales';
import { automaticApproval } from '#/store/audit-policy';
import { downloadContractWord } from '#/utils/contract-document';
import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
@@ -332,6 +333,13 @@
        <TableAction
          :actions="[
            {
              label: '下载合同',
              type: 'link',
              icon: 'lucide:download',
              auth: ['crm:contract:query'],
              onClick: () => downloadContractWord(row.id, row.no),
            },
            {
              label: $t('common.edit'),
              type: 'link',
              icon: ACTION_ICON.EDIT,
src/views/crm/saleQuotation/index.vue
@@ -15,6 +15,7 @@
  getSaleQuotationPage,
} from '#/api/crm/saleQuotation';
import { $t } from '#/locales';
import { downloadContractWord } from '#/utils/contract-document';
import type { CrmSaleQuotationAiApi } from '#/api/crm/saleQuotation/ai';
@@ -107,6 +108,12 @@
    async onOk() {
      const contractId = await convertSaleQuotationToContract(row.id!);
      message.success('转合同成功');
      gridApi.query();
      try {
        await downloadContractWord(contractId);
      } catch {
        message.warning('合同已创建,文件下载失败,可在合同详情中重新下载');
      }
      push({ name: 'CrmContractDetail', params: { id: contractId } });
    },
  });
@@ -218,6 +225,13 @@
              ifShow: !!row.contractId,
            },
            {
              label: '下载合同',
              type: 'link',
              auth: ['crm:contract:query'],
              onClick: () => downloadContractWord(row.contractId!, row.contractNo),
              ifShow: !!row.contractId,
            },
            {
              label: $t('common.delete'),
              type: 'link',
              danger: true,
@@ -233,4 +247,4 @@
      </template>
    </Grid>
  </Page>
</template>
</template>
src/views/mes/home/modules/alert-panel.vue
@@ -20,14 +20,6 @@
/** å¾…办提醒列表:标签、描述、图标、目标路由名称、数量 */
const alertItems = computed(() => [
  {
    count: props.summary.andonActiveCount,
    desc: '未处置的安灯呼叫',
    icon: 'lucide:bell-ring',
    iconClass: 'bg-red-50 text-red-500',
    label: '安灯报警',
    routeName: 'MesProAndonRecord',
  },
  {
    count: props.summary.repairActiveCount,
    desc: '待处理的维修订单',
    icon: 'lucide:wrench',
src/views/mes/md/workstation/components/workshop-select.vue
@@ -82,10 +82,6 @@
      <div v-if="selectedItem" class="leading-6">
        <div>编码:{{ selectedItem.code || '-' }}</div>
        <div>名称:{{ selectedItem.name || '-' }}</div>
        <div>
          é¢ç§¯ï¼š
          {{ selectedItem.area !== null ? `${selectedItem.area} ãŽ¡` : '-' }}
        </div>
        <div>负责人:{{ selectedItem.chargeUserName || '-' }}</div>
      </div>
    </template>
src/views/mes/md/workstation/workshop/data.ts
@@ -76,16 +76,6 @@
      rules: 'required',
    },
    {
      fieldName: 'area',
      label: '面积',
      component: 'InputNumber',
      componentProps: {
        class: '!w-full',
        min: 0,
        precision: 2,
      },
    },
    {
      fieldName: 'chargeUserId',
      label: '负责人',
      component: 'ApiSelect',
@@ -168,11 +158,6 @@
      field: 'name',
      title: '车间名称',
      minWidth: 150,
    },
    {
      field: 'area',
      title: '面积',
      width: 120,
    },
    {
      field: 'chargeUserName',