Merge remote-tracking branch 'origin/dev_pro2.0' into dev_pro2.0
| | |
| | | name="viewport" |
| | | content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" |
| | | /> |
| | | <!-- ç± vite 注å
¥ VITE_APP_TITLE åéï¼å¨ .env æä»¶å
é
ç½® --> |
| | | <title>%VITE_APP_TITLE%</title> |
| | | <!-- é¦å±æ é¢åºå®ä¸ºä¸æ§ææ¡ï¼ä¸è¦æå®¢æ·åçç¼è¯è¿äº§ç©ï¼å¦åæ¢ä¸ªç¯å¢é¨ç½²å°±ä¼"串åç"ï¼ã |
| | | çå®åçç±è¿è¡æ¶ä¸åï¼ç³»ç»ç®¡ç â å好设置 â å
¬å¸ä¿¡æ¯ï¼å端 system_company_configï¼ï¼ |
| | | å¯å¨åè¦ç document.titleï¼è§ src/utils/company-config.ts --> |
| | | <title>å·¥ä¸AIæºé å¹³å°</title> |
| | | <link rel="icon" href="/favicon.ico" /> |
| | | <script> |
| | | var HM_ID = '%VITE_APP_BAIDU_CODE%'; |
| | |
| | | </style> |
| | | <div class="loading" id="__app-loading__"> |
| | | <span class="dot"><i></i><i></i><i></i><i></i></span> |
| | | <div class="title">%VITE_APP_TITLE%</div> |
| | | <!-- 䏿§ææ¡ï¼å 载页æ©äº JS æ§è¡ï¼æ¿ä¸å°è¿è¡æ¶çå
¬å¸ä¿¡æ¯ï¼ä¸è½åæ»å®¢æ·åç --> |
| | | <div class="title">æ£å¨å è½½ï¼è¯·ç¨åâ¦</div> |
| | | </div> |
| | |
| | | </style> |
| | | <div class="loading" id="__app-loading__"> |
| | | <div class="loader"></div> |
| | | <div class="title">%VITE_APP_TITLE%</div> |
| | | <!-- 䏿§ææ¡ï¼å 载页æ©äº JS æ§è¡ï¼æ¿ä¸å°è¿è¡æ¶çå
¬å¸ä¿¡æ¯ï¼ä¸è½åæ»å®¢æ·åç --> |
| | | <div class="title">æ£å¨å è½½ï¼è¯·ç¨åâ¦</div> |
| | | </div> |
| | |
| | | file: File; |
| | | updateSupport: boolean; |
| | | } |
| | | |
| | | /** 客æ·å¯¼å
¥ç»æ */ |
| | | export interface CustomerImportRespVO { |
| | | createCustomerNames?: string[]; // æ°å¢æåç客æ·å |
| | | updateCustomerNames?: string[]; // æ´æ°æåç客æ·å |
| | | failureCustomerNames?: Record<string, string>; // 导å
¥å¤±è´¥ç客æ·åååå |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢å®¢æ·å表 */ |
| | |
| | | |
| | | /** 导å
¥å®¢æ· */ |
| | | export function importCustomer(data: CrmCustomerApi.CustomerImportReqVO) { |
| | | return requestClient.upload('/crm/customer/import', data); |
| | | return requestClient.upload<CrmCustomerApi.CustomerImportRespVO>( |
| | | '/crm/customer/import', |
| | | data, |
| | | ); |
| | | } |
| | | |
| | | /** è·å客æ·ç²¾ç®ä¿¡æ¯å表 */ |
| | |
| | | remark: string; |
| | | createTime?: Date; |
| | | } |
| | | |
| | | /** å²ä½å¯¼å
¥ç»æ */ |
| | | export interface PostImportRespVO { |
| | | createPostNames?: string[]; // æ°å¢æåçå²ä½å |
| | | updatePostNames?: string[]; // æ´æ°æåçå²ä½å |
| | | failurePostNames?: Record<string, string>; // 导å
¥å¤±è´¥çå²ä½åååå |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢å²ä½å表 */ |
| | |
| | | |
| | | /** 导å
¥å²ä½ */ |
| | | export function importPost(file: File, updateSupport: boolean) { |
| | | return requestClient.upload('/system/post/import', { |
| | | return requestClient.upload<SystemPostApi.PostImportRespVO>( |
| | | '/system/post/import', |
| | | { |
| | | file, |
| | | updateSupport, |
| | | }); |
| | | }, |
| | | ); |
| | | } |
| | |
| | | export interface UserSimple extends User { |
| | | id: number; |
| | | } |
| | | |
| | | /** ç¨æ·å¯¼å
¥ç»æ */ |
| | | export interface UserImportRespVO { |
| | | createUsernames?: string[]; // æ°å¢æåçç¨æ·å |
| | | updateUsernames?: string[]; // æ´æ°æåçç¨æ·å |
| | | failureUsernames?: Record<string, string>; // 导å
¥å¤±è´¥çç¨æ·åååå |
| | | } |
| | | } |
| | | |
| | | /** æ¥è¯¢ç¨æ·ç®¡çå表 */ |
| | |
| | | |
| | | /** 导å
¥ç¨æ· */ |
| | | export function importUser(file: File, updateSupport: boolean) { |
| | | return requestClient.upload('/system/user/import', { |
| | | return requestClient.upload<SystemUserApi.UserImportRespVO>( |
| | | '/system/user/import', |
| | | { |
| | | file, |
| | | updateSupport, |
| | | }); |
| | | }, |
| | | ); |
| | | } |
| | | |
| | | /** ç¨æ·å¯ç éç½® */ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VNodeChild } from 'vue'; |
| | | |
| | | import { h } from 'vue'; |
| | | |
| | | import { message, notification } from 'ant-design-vue'; |
| | | |
| | | export interface ImportResultNotifyOptions { |
| | | /** ä¸å¡ä¸»ä½ï¼ç¨äºæ¼æ é¢ä¸å»ºè®®ï¼å¦ã设å¤ãã客æ·ã */ |
| | | subject: string; |
| | | /** æ°å¢æåçæ¡æ° */ |
| | | createCount?: number; |
| | | /** æ´æ°æåçæ¡æ° */ |
| | | updateCount?: number; |
| | | /** 失败æç»ï¼key 为ç¼ç /åç§°ï¼value 为å端失败åå */ |
| | | failures?: null | Record<string, string>; |
| | | /** ãä¸åå¨ã类失败çè½ç¹æç¤ºï¼å¦ãã设å¤ç±»åãã车é´ããå·¥ä½ç«ãä¸ç对åºç¼ç ã */ |
| | | masterDataHint?: string; |
| | | } |
| | | |
| | | /** |
| | | * ç»ä¸å±ç¤º Excel 导å
¥ç»æã |
| | | * |
| | | * åªè¦å端è¿åäºå¤±è´¥æç»ï¼å°±ç»ä¸è½åæç¤ºãæä½æåãââæ¹ä¸ºå¸¸é©»éç¥éè¡ååºå¤±è´¥åå ï¼ |
| | | * å¹¶æå¤±è´¥åå ç»åºä¸ä¸æ¥å¨ä½ï¼å
¨é¨æåæ¶ææç¤ºæåã |
| | | * |
| | | * @returns å®é
åå
¥çæ¡æ°ï¼æ°å¢ + æ´æ°ï¼ï¼ä¾è°ç¨æ¹å³å®æ¯å¦éè¦å·æ°å表 |
| | | */ |
| | | export function notifyImportResult( |
| | | options: ImportResultNotifyOptions, |
| | | ): number { |
| | | const { |
| | | subject, |
| | | createCount = 0, |
| | | updateCount = 0, |
| | | failures, |
| | | masterDataHint, |
| | | } = options; |
| | | const failureEntries = Object.entries(failures ?? {}); |
| | | const importedCount = createCount + updateCount; |
| | | |
| | | if (failureEntries.length === 0) { |
| | | message.success(`导å
¥æåï¼æ°å¢ ${createCount} æ¡ï¼æ´æ° ${updateCount} æ¡`); |
| | | return importedCount; |
| | | } |
| | | |
| | | const nodes: VNodeChild[] = [ |
| | | h( |
| | | 'div', |
| | | `æ°å¢æå ${createCount} æ¡ï¼æ´æ°æå ${updateCount} æ¡ï¼å¤±è´¥ ${failureEntries.length} æ¡ï¼`, |
| | | ), |
| | | ...failureEntries.map(([name, reason]) => h('div', `${name}ï¼${reason}`)), |
| | | ...buildFailureHints(failureEntries.map(([, reason]) => reason), { |
| | | subject, |
| | | masterDataHint, |
| | | }).map((hint) => h('div', { class: 'mt-2 text-red-500' }, hint)), |
| | | ]; |
| | | |
| | | const notify = importedCount === 0 ? notification.error : notification.warning; |
| | | notify({ |
| | | message: |
| | | importedCount === 0 |
| | | ? `${subject}导å
¥å¤±è´¥ï¼${failureEntries.length} è¡å
¨é¨æªå¯¼å
¥` |
| | | : `导å
¥å®æï¼é¨å${subject}导å
¥å¤±è´¥ï¼æå ${importedCount} æ¡ / 失败 ${failureEntries.length} æ¡ï¼`, |
| | | description: () => h('div', nodes), |
| | | duration: null, |
| | | }); |
| | | return importedCount; |
| | | } |
| | | |
| | | /** æå¤±è´¥åå å½çº³ä¸ä¸æ¥å¨ä½ï¼é¿å
ç¨æ·åªçå°ã失败ãå´ä¸ç¥éæ¹åªé */ |
| | | function buildFailureHints( |
| | | reasons: string[], |
| | | { subject, masterDataHint }: Pick<ImportResultNotifyOptions, 'masterDataHint' | 'subject'>, |
| | | ): string[] { |
| | | const hints = new Set<string>(); |
| | | for (const reason of reasons) { |
| | | if (reason.includes('ä¸åå¨')) { |
| | | hints.add( |
| | | `æç¤ºãä¸åå¨ãçï¼è¯·å
ç»´æ¤å¥½${masterDataHint ?? '对åºä¸»æ°æ®'}ï¼ææ Excel ä¸ç弿¹æå·²åå¨çï¼å鿰坼å
¥ã`, |
| | | ); |
| | | } else if (reason.includes('å·²ç»åå¨') || reason.includes('å·²åå¨')) { |
| | | hints.add( |
| | | `æç¤ºãå·²åå¨ãçï¼è¯·ä¿®æ¹ Excel ä¸ç${subject}åç§°æç¼ç ï¼æå¾éãæ¯ææ´æ°ãå鿰坼å
¥ä»¥è¦çå·²ææ°æ®ã`, |
| | | ); |
| | | } else if (reason.includes('ä¸è½ä¸ºç©º') || reason.includes('为空')) { |
| | | hints.add('æç¤ºãä¸è½ä¸ºç©ºãçï¼è¯·è¡¥é½ Excel ä¸å¯¹åºåçå
容å鿰坼å
¥ã'); |
| | | } |
| | | } |
| | | return [...hints]; |
| | | } |
| | |
| | | import type { Recordable } from '@vben/types'; |
| | | |
| | | export * from './import-result'; |
| | | export * from './rangePickerProps'; |
| | | export * from './routerHelper'; |
| | | |
| | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Upload } from 'ant-design-vue'; |
| | | import { Button, Upload } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { importCustomer, importCustomerTemplate } from '#/api/crm/customer'; |
| | | import { $t } from '#/locales'; |
| | | import { notifyImportResult } from '#/utils'; |
| | | |
| | | import { useImportFormSchema } from '../data'; |
| | | |
| | |
| | | // æäº¤è¡¨å |
| | | const data = await formApi.getValues(); |
| | | try { |
| | | await importCustomer({ |
| | | const importData = await importCustomer({ |
| | | ownerUserId: data.ownerUserId, |
| | | file: data.file, |
| | | updateSupport: data.updateSupport, |
| | | }); |
| | | // å
³éå¹¶æç¤º |
| | | const createCount = importData.createCustomerNames?.length || 0; |
| | | const updateCount = importData.updateCustomerNames?.length || 0; |
| | | |
| | | // å
³éå¹¶æå¯¼å
¥ç»ææç¤ºï¼ä»
å¨ç¡®ææ°æ®åå
¥æ¶éç¥åè¡¨å·æ° |
| | | await modalApi.close(); |
| | | if (createCount + updateCount > 0) { |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } |
| | | notifyImportResult({ |
| | | subject: '客æ·', |
| | | createCount, |
| | | updateCount, |
| | | failures: importData.failureCustomerNames, |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | emit('success'); |
| | | // å端è¿å导å
¥ç»æï¼å«å¤±è´¥åå ï¼ä¾å¦â以ä¸åå·¥ä¸åå¨...ï¼éè¡¥å
ææºå·...âï¼ |
| | | if (res && res.length > 0) { |
| | | message[res.includes('æª') || res.includes('ä¸å®æ´') ? 'warning' : 'success'](res); |
| | | // 失败æ¶åç«¯ä¼æ¼ä¸ãæªè½å¯¼å
¥ï¼ãæç»æ®µï¼ç¨å®å¤å®ï¼é¿å
æåææ¡éåºç°ãæªã就误æ¥è¦å |
| | | message[res.includes('æªè½å¯¼å
¥') ? 'warning' : 'success'](res); |
| | | } else { |
| | | message.success('导å
¥æå'); |
| | | } |
| | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Upload } from 'ant-design-vue'; |
| | | import { Button, Upload } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { |
| | |
| | | importMachineryTemplate, |
| | | } from '#/api/mes/dv/machinery'; |
| | | import { $t } from '#/locales'; |
| | | import { notifyImportResult } from '#/utils'; |
| | | |
| | | import { useImportFormSchema } from '../data'; |
| | | |
| | |
| | | try { |
| | | const result = await importMachinery(data.file, data.updateSupport); |
| | | const importData = result as MesDvMachineryApi.MachineryImportRespVO; |
| | | let text = `ä¸ä¼ æåæ°éï¼${importData.createCodes?.length || 0}ï¼`; |
| | | text += `æ´æ°æåæ°éï¼${importData.updateCodes?.length || 0}ï¼`; |
| | | text += `æ´æ°å¤±è´¥æ°éï¼${Object.keys(importData.failureCodes || {}).length}ï¼`; |
| | | message.info(text); |
| | | // å
³éå¹¶æç¤º |
| | | const createCount = importData.createCodes?.length || 0; |
| | | const updateCount = importData.updateCodes?.length || 0; |
| | | |
| | | // å
³éå¹¶æå¯¼å
¥ç»ææç¤ºï¼ä»
å¨ç¡®ææ°æ®åå
¥æ¶éç¥åè¡¨å·æ° |
| | | await modalApi.close(); |
| | | if (createCount + updateCount > 0) { |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } |
| | | notifyImportResult({ |
| | | subject: '设å¤', |
| | | createCount, |
| | | updateCount, |
| | | failures: importData.failureCodes, |
| | | masterDataHint: 'ã设å¤ç±»åãã车é´ããå·¥ä½ç«ãä¸ç对åºç¼ç ', |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Upload } from 'ant-design-vue'; |
| | | import { Button, Upload } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { importItem, importItemTemplate } from '#/api/mes/md/item'; |
| | | import { $t } from '#/locales'; |
| | | import { notifyImportResult } from '#/utils'; |
| | | |
| | | import { useImportFormSchema } from '../data'; |
| | | |
| | |
| | | try { |
| | | const result = await importItem(data.file, data.updateSupport); |
| | | const importData = result as MesMdItemApi.ItemImportRespVO; |
| | | let text = `ä¸ä¼ æåæ°éï¼${importData.createCodes?.length || 0};`; |
| | | for (const code of importData.createCodes || []) { |
| | | text += `< ${code} >`; |
| | | } |
| | | text += `æ´æ°æåæ°éï¼${importData.updateCodes?.length || 0};`; |
| | | for (const code of importData.updateCodes || []) { |
| | | text += `< ${code} >`; |
| | | } |
| | | text += `æ´æ°å¤±è´¥æ°éï¼${Object.keys(importData.failureCodes || {}).length};`; |
| | | for (const code in importData.failureCodes || {}) { |
| | | text += `< ${code}: ${importData.failureCodes?.[code]} >`; |
| | | } |
| | | message.info(text); |
| | | // å
³éå¹¶æç¤º |
| | | const createCount = importData.createCodes?.length || 0; |
| | | const updateCount = importData.updateCodes?.length || 0; |
| | | |
| | | // å
³éå¹¶æå¯¼å
¥ç»ææç¤ºï¼ä»
å¨ç¡®ææ°æ®åå
¥æ¶éç¥åè¡¨å·æ° |
| | | await modalApi.close(); |
| | | if (createCount + updateCount > 0) { |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } |
| | | notifyImportResult({ |
| | | subject: 'ç©æ', |
| | | createCount, |
| | | updateCount, |
| | | failures: importData.failureCodes, |
| | | masterDataHint: 'ãç©æåç±»ãä¸ç对åºç¼ç ', |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Upload } from 'ant-design-vue'; |
| | | import { Button, Upload } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { importPost, importPostTemplate } from '#/api/system/post'; |
| | | import { $t } from '#/locales'; |
| | | import { notifyImportResult } from '#/utils'; |
| | | |
| | | import { useImportFormSchema } from '../data'; |
| | | |
| | |
| | | // æäº¤è¡¨å |
| | | const data = await formApi.getValues(); |
| | | try { |
| | | await importPost(data.file, data.updateSupport); |
| | | // å
³éå¹¶æç¤º |
| | | const importData = await importPost(data.file, data.updateSupport); |
| | | const createCount = importData.createPostNames?.length || 0; |
| | | const updateCount = importData.updatePostNames?.length || 0; |
| | | |
| | | // å
³éå¹¶æå¯¼å
¥ç»ææç¤ºï¼ä»
å¨ç¡®ææ°æ®åå
¥æ¶éç¥åè¡¨å·æ° |
| | | await modalApi.close(); |
| | | if (createCount + updateCount > 0) { |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } |
| | | notifyImportResult({ |
| | | subject: 'å²ä½', |
| | | createCount, |
| | | updateCount, |
| | | failures: importData.failurePostNames, |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { Button, message, Upload } from 'ant-design-vue'; |
| | | import { Button, Upload } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { importUser, importUserTemplate } from '#/api/system/user'; |
| | | import { $t } from '#/locales'; |
| | | import { notifyImportResult } from '#/utils'; |
| | | |
| | | import { useImportFormSchema } from '../data'; |
| | | |
| | |
| | | // æäº¤è¡¨å |
| | | const data = await formApi.getValues(); |
| | | try { |
| | | await importUser(data.file, data.updateSupport); |
| | | // å
³éå¹¶æç¤º |
| | | const importData = await importUser(data.file, data.updateSupport); |
| | | const createCount = importData.createUsernames?.length || 0; |
| | | const updateCount = importData.updateUsernames?.length || 0; |
| | | |
| | | // å
³éå¹¶æå¯¼å
¥ç»ææç¤ºï¼ä»
å¨ç¡®ææ°æ®åå
¥æ¶éç¥åè¡¨å·æ° |
| | | await modalApi.close(); |
| | | if (createCount + updateCount > 0) { |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } |
| | | notifyImportResult({ |
| | | subject: 'ç¨æ·', |
| | | createCount, |
| | | updateCount, |
| | | failures: importData.failureUsernames, |
| | | }); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | const appApiUrl = company?.apiUrl ?? ''; |
| | | const appName = company?.name ?? ''; |
| | | const isDev = mode === 'development'; |
| | | if (appName) { |
| | | // è¦çæµè§å¨æ ç¾é¡µæ é¢ï¼Vite ç resolveEnv ä¼å
读 process.envï¼ä»èæ¿æ¢ index.html éç %VITE_APP_TITLE% |
| | | process.env.VITE_APP_TITLE = appName; |
| | | } |
| | | // è¿éä¸è¦åæ appName åè¿ VITE_APP_TITLEã |
| | | // é¦å±æ é¢ãå è½½é¡µææ¡å·²åºå®ä¸ºä¸æ§ææ¡ï¼åçç»ä¸ç±è¿è¡æ¶ãå
¬å¸ä¿¡æ¯ãä¸åï¼ |
| | | // 䏿¦å¨è¿éè¦çï¼æä¸ªå®¢æ·çåç§°å°±ä¼è¢«ç¼è¯è¿ index.html / å è½½é¡µï¼æ¢ä¸ªç¯å¢é¨ç½²å°±"串åç"ã |
| | | console.log('[company]', companyKey, '-> name:', appName, 'logo:', appLogo, 'api:', appApiUrl || '(from env)'); |
| | | |
| | | const defineVars: Record<string, string> = { |