| | |
| | | apiUrl: 'http://42.63.70.90:9001/admin-api', |
| | | }, |
| | | YZFX: { |
| | | name: '宁夏英泽除锈', |
| | | name: '宁夏英泽防锈', |
| | | logo: '/logos/YZFXLogo.png', |
| | | favicon: '/logos/YZFXLogo.ico', |
| | | apiUrl: 'http://42.63.70.231:9001/admin-api', |
| | |
| | | match = 'VITE_GLOB_', |
| | | confFiles = getConfFiles(), |
| | | ) { |
| | | let envConfig = {}; |
| | | let envConfig: Record<string, string> = {}; |
| | | |
| | | for (const confFile of confFiles) { |
| | | try { |
| | |
| | | Reflect.deleteProperty(envConfig, key); |
| | | } |
| | | }); |
| | | // 合并进程环境变量,使 vite.config.ts 按公司注入的 VITE_GLOB_API_URL 能进入 _app-config 文件 |
| | | Object.keys(process.env).forEach((key) => { |
| | | const value = process.env[key]; |
| | | if (reg.test(key) && value) { |
| | | envConfig[key] = value; |
| | | } |
| | | }); |
| | | return envConfig as T; |
| | | } |
| | | |
| | |
| | | return requestClient.get<any[]>('/erp/purchase-order/approve-process-list'); |
| | | } |
| | | |
| | | /** 反审批(协同办公已办任务中撤回已审核订单,回退为未审核) */ |
| | | export function reverseApprove(processInstanceId: string) { |
| | | return requestClient.post('/erp/purchase-order/reverse-approve', null, { |
| | | params: { processInstanceId }, |
| | | }); |
| | | } |
| | | |
| | | /** 获取采购审核流程列表响应 */ |
| | | export interface ProcessDefinition { |
| | | id: string; // 流程定义ID |
| | |
| | | createTime?: number; |
| | | /** BPM 流程实例编号 */ |
| | | processInstanceId?: string; |
| | | /** 待审核文件数(auditStatus=0 的审核记录数) */ |
| | | pendingAuditCount?: number; |
| | | } |
| | | |
| | | export interface PageParams extends PageParam { |
| | |
| | | }); |
| | | |
| | | const appName = computed(() => preferences.copyright.companyName); |
| | | const logo = computed(() => __APP_LOGO__ || preferences.logo.source); |
| | | // 登录页 logo 优先取数据库配置(preferences.logo.source),未配置时回退编译期默认 __APP_LOGO__ |
| | | const logo = computed(() => preferences.logo.source || __APP_LOGO__); |
| | | const logoDark = computed(() => preferences.logo.sourceDark); |
| | | // 登录页标题/描述优先取后端配置,未配置时回退到 i18n 默认 |
| | | const pageTitle = computed( |
| | |
| | | <template> |
| | | <div class="flex flex-col"> |
| | | <!-- 公司名称 --> |
| | | <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"> |
| | | <span class="flex items-center text-sm"> |
| | | <div class="my-2 flex w-full items-center justify-between gap-4 rounded-md px-2 py-2"> |
| | | <span class="shrink-0 text-sm text-foreground/80"> |
| | | {{ $t('preferences.company.companyName') }} |
| | | </span> |
| | | <Input |
| | |
| | | </div> |
| | | |
| | | <!-- 登录页标题 --> |
| | | <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"> |
| | | <span class="flex items-center text-sm"> |
| | | <div class="my-2 flex w-full items-center justify-between gap-4 rounded-md px-2 py-2"> |
| | | <span class="shrink-0 text-sm text-foreground/80"> |
| | | {{ $t('preferences.company.loginTitle') }} |
| | | </span> |
| | | <Input |
| | |
| | | </div> |
| | | |
| | | <!-- 登录页描述 --> |
| | | <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"> |
| | | <span class="flex items-center text-sm"> |
| | | <div class="my-2 flex w-full items-center justify-between gap-4 rounded-md px-2 py-2"> |
| | | <span class="shrink-0 text-sm text-foreground/80"> |
| | | {{ $t('preferences.company.loginDescription') }} |
| | | </span> |
| | | <Input |
| | |
| | | </div> |
| | | |
| | | <!-- 公司 Logo --> |
| | | <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1"> |
| | | <span class="flex items-center text-sm"> |
| | | <div class="my-2 flex w-full items-center justify-between gap-4 rounded-md px-2 py-2"> |
| | | <span class="shrink-0 text-sm text-foreground/80"> |
| | | {{ $t('preferences.company.logo') }} |
| | | </span> |
| | | <div class="flex items-center gap-2"> |
| | |
| | | }, |
| | | { |
| | | title: '操作', |
| | | width: 120, |
| | | width: 180, |
| | | fixed: 'right', |
| | | slots: { default: 'actions' }, |
| | | }, |
| | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { reverseApprove } from '#/api/erp/purchase/order'; |
| | | import { getTaskDonePage, withdrawTask } from '#/api/bpm/task'; |
| | | import { router } from '#/router'; |
| | | |
| | |
| | | try { |
| | | await withdrawTask(row.id); |
| | | message.success('撤回成功'); |
| | | await gridApi.query(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** 是否采购订单审批任务(用于显示"反审批"、隐藏通用"撤回") */ |
| | | function isPurchaseOrderApprove(row: BpmTaskApi.Task) { |
| | | return (row.processInstance?.processDefinitionId || '').startsWith( |
| | | 'purchase_order_approve', |
| | | ); |
| | | } |
| | | |
| | | /** 反审批采购订单(已审核 -> 未审核,在协同办公已办任务中操作) */ |
| | | async function handleReverseApprove(row: BpmTaskApi.Task) { |
| | | const hideLoading = message.loading({ |
| | | content: '反审批中...', |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await reverseApprove(row.processInstance.id); |
| | | message.success('反审批成功,订单已重新进入待办审批'); |
| | | await gridApi.query(); |
| | | } finally { |
| | | hideLoading(); |
| | |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: '反审批', |
| | | type: 'link', |
| | | danger: true, |
| | | icon: ACTION_ICON.AUDIT, |
| | | ifShow: () => isPurchaseOrderApprove(row), |
| | | popConfirm: { |
| | | title: '确定要反审批该采购订单吗?订单将重新进入待办审批', |
| | | confirm: handleReverseApprove.bind(null, row), |
| | | }, |
| | | }, |
| | | { |
| | | label: '撤回', |
| | | type: 'link', |
| | | danger: true, |
| | | icon: ACTION_ICON.DELETE, |
| | | ifShow: () => !isPurchaseOrderApprove(row), |
| | | popConfirm: { |
| | | title: '确定要撤回该任务吗?', |
| | | confirm: handleWithdraw.bind(null, row), |
| | |
| | | deletePurchaseOrder, |
| | | exportPurchaseOrder, |
| | | getPurchaseOrderPage, |
| | | updatePurchaseOrderStatus, |
| | | } from '#/api/erp/purchase/order'; |
| | | import { $t } from '#/locales'; |
| | | |
| | |
| | | try { |
| | | await deletePurchaseOrder(ids); |
| | | message.success($t('ui.actionMessage.deleteSuccess')); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** 审批/反审批操作 */ |
| | | async function handleUpdateStatus( |
| | | row: ErpPurchaseOrderApi.PurchaseOrder, |
| | | status: number, |
| | | ) { |
| | | const hideLoading = message.loading({ |
| | | content: `确定${status === 20 ? '审批' : '反审批'}该订单吗?`, |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await updatePurchaseOrderStatus(row.id!, status); |
| | | message.success(`${status === 20 ? '审批' : '反审批'}成功`); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | |
| | | </script> |
| | | |
| | | <template> |
| | | <Page auto-content-height><FormModal @success="handleRefresh" /> |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <Grid table-title="采购订单列表"> |
| | | <template #toolbar-tools> |
| | | <TableAction |
| | |
| | | auth: ['erp:purchase-order:update'], |
| | | ifShow: () => row.status !== 20, |
| | | onClick: handleEdit.bind(null, row), |
| | | }, |
| | | { |
| | | label: row.status === 10 ? '审批' : '反审批', |
| | | type: 'link', |
| | | icon: ACTION_ICON.AUDIT, |
| | | auth: ['erp:purchase-order:update-status'], |
| | | popConfirm: { |
| | | title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`, |
| | | confirm: handleUpdateStatus.bind( |
| | | null, |
| | | row, |
| | | row.status === 10 ? 20 : 10, |
| | | ), |
| | | }, |
| | | }, |
| | | { |
| | | label: '确认收货', |
| | |
| | | loading.value = true; |
| | | try { |
| | | project.value = await getPdProject(projectId.value); |
| | | if (isPendingUpload.value) { |
| | | if (route.query.tab === 'audit') { |
| | | // 从列表页「审核文件」按钮进入,直接定位到资料审核 Tab |
| | | activeTab.value = 'audit'; |
| | | } else if (isPendingUpload.value) { |
| | | activeTab.value = 'material'; |
| | | } else if (isPendingAudit.value) { |
| | | activeTab.value = 'audit'; |
| | |
| | | } |
| | | } |
| | | |
| | | /** 审核文件 - 跳转详情页资料审核 Tab */ |
| | | function handleAuditFile(row: MesPdProjectApi.Project) { |
| | | router.push({ |
| | | name: 'MesPdProjectDetail', |
| | | params: { id: row.id }, |
| | | query: { tab: 'audit' }, |
| | | }); |
| | | } |
| | | |
| | | /** 查看审批详情 */ |
| | | function handleProcessDetail(row: MesPdProjectApi.Project) { |
| | | if (!row.processInstanceId) { |
| | |
| | | onClick: () => handleDetail(row), |
| | | }, |
| | | { |
| | | label: '审核文件', |
| | | type: 'link', |
| | | auth: ['mes:pd-project:update'], |
| | | ifShow: |
| | | row.status === MesPdProjectStatusEnum.PENDING_AUDIT && |
| | | (row.pendingAuditCount ?? 0) > 0, |
| | | onClick: handleAuditFile.bind(null, row), |
| | | }, |
| | | { |
| | | label: '提交审批', |
| | | type: 'link', |
| | | auth: ['mes:pd-project:update'], |
| | | ifShow: row.status === MesPdProjectStatusEnum.PENDING_AUDIT, |
| | | ifShow: |
| | | row.status === MesPdProjectStatusEnum.PENDING_AUDIT && |
| | | (row.pendingAuditCount ?? 0) === 0, |
| | | onClick: handleSubmit.bind(null, row), |
| | | }, |
| | | { |
| | |
| | | __APP_NAME__: JSON.stringify(appName), |
| | | }; |
| | | if (!isDev && appApiUrl) { |
| | | process.env.VITE_GLOB_API_URL = appApiUrl; |
| | | defineVars['import.meta.env.VITE_GLOB_API_URL'] = JSON.stringify(appApiUrl); |
| | | defineVars['import.meta.env.VITE_BASE_URL'] = JSON.stringify(new URL(appApiUrl).origin); |
| | | } |
| | |
| | | proxy: { |
| | | "/admin-api": { |
| | | changeOrigin: true, |
| | | target: "http://192.168.0.10:48080", |
| | | target: "http://36.213.90.123:9500", |
| | | ws: true, |
| | | }, |
| | | }, |