diff --git a/.workbuddy/memory/2026-08-25.md b/.workbuddy/memory/2026-08-25.md index 915344d..dcc15c6 100644 --- a/.workbuddy/memory/2026-08-25.md +++ b/.workbuddy/memory/2026-08-25.md @@ -82,3 +82,71 @@ - 实现:复用已有组件 `src/views/settlement/components/formal-settlement-table-panel.vue`(工具栏+表格+分页一体,通过 emit 事件与父通信),分别挂入"应付""应收"两个 `el-tab-pane` 内,共享父级 `rows/columns/loading/page/hasPermissionFn`,事件回连:@create→openCreate、@payment→openPaymentDialog、@sync→handleSync、@export→handleExport、@refresh→loadTable、@page-change→onPageChange、@action→onAction(分发 view/edit/delete/submit/approve/return/void/print)、@update:selection→selection 同步。切 tab 仍走 `handleSettlementTypeChange` 重载数据。 - 配套改动:父页 `:has-permission` 传 `hasPermissionFn`(computed 返回箭头函数,避免方法作 prop 时 this 丢失导致权限恒为 true);`handlePrint(row)` 增加可选 row 入参;移除父页内联表格及对应 scoped 样式(.formal-page__toolbar/links/pagination);组件操作列 width 120→320(符合 AGENTS.md >3 按钮规范)。 - 校验:@vue/compiler-sfc parse/compileTemplate 0 错误、esbuild 脚本语法 OK;`pnpm build` 因沙箱保护 dist/ 被拦截(非代码问题)。仅改 formal-settlement.vue 一个页面文件 + 组件 width。 + +## 临时额度管理附件上传按钮移至表格左下角 +- 需求:用户截图反馈 `business/temporary-credit-limit` 新增弹窗中「上传附件」按钮在表格上方,要求统一放到附件表格左下角,与 project-apply 的项目材料交互一致。 +- 改动文件:`src/views/business/temporary-credit-limit.vue`: + - 模板:将 `vehicle-attachment-upload` 从 `temporary-credit-limit-page__attachment-head` 移除,放到 `el-table` 之后的新增 `temporary-credit-limit-page__attachment-upload` 容器内;head 内只保留「批量下载」按钮。 + - 样式:`&__attachment-head` 的 `justify-content` 由 `space-between` 改为 `flex-end`;新增 `&__attachment-upload` 样式,左对齐并控制上传组件宽度自适应。 +- 结论:临时额度管理附件区域现与合同管理、项目材料保持一致:批量下载在表格上方右侧,上传附件在表格下方左侧。 + +## 项目材料上传提示文字移到按钮右侧 +- 需求:用户要求 project-apply/form「上传附件」按钮支持指定格式(pdf/bmp/jpeg/png/jpg/doc/docx/ppt/pptx/xlsx/xls/eml/msg/zip)、单文件 50M,并把提示文字放到按钮后面(右侧同一行)。 +- 现状:project-apply.vue 第 537-540 行早已配置 `:file-types`、`:max-size="50"` 与完整 `tip` 文案,但 vehicle-attachment-upload 组件默认把提示渲染在按钮下方。 +- 修复:仅改 `&__upload` 样式,用 `:deep` 把 `.vehicle-attachment-upload` 设为 `display:flex; align-items:center`,并把 `.el-upload__tip` 由默认块级(下方)改为 `display:inline-block; margin-left:12px`,使格式/大小提示与按钮同一行、位于按钮右侧。 +- 结论:project-apply 附件提示现为"上传附件按钮 + 右侧灰色提示文字",未改动组件逻辑与其它页面。 + +## 附件格式说明三页统一(按钮右侧 30px / 500M) +- 需求:用户要求「支持pdf、bmp、…、zip,单个文件不超过500M」这段说明在 project-apply / temporary-credit-limit / contract-manage 三处附件上传区统一摆放:放到「上传附件」按钮右侧、间距 30px、文字左对齐;文件限制上限由 50M 改为 500M(说明与校验一致)。 +- 实现(三页一致): + - 统一 `tip` 文案:`支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过500M`。 + - `:max-size`(contract-manage 为 `maxSize`)统一 500;project-apply / temporary-credit-limit 由 50→500。 + - 样式:用 `:deep` 把 `.vehicle-attachment-upload` 设为 `display:flex;align-items:center`,`.el-upload__tip` 改 `display:inline-block;margin-left:30px;color:#909399;font-size:13px;text-align:left`,使说明在按钮右侧 30px、左对齐。 + - contract-manage 的 AttachmentSection render 把上传按钮从表格上方 head 移到表格下方左侧(`.contract-manage-form__attachment-upload`),head 仅保留「批量下载」;同步删除失效的 `__attachment-actions` 死样式,新增 `__attachment-upload` 样式。至此三页上传按钮均位于附件表格左下角、说明在按钮右侧。 +- 校验:@vue/compiler-sfc 对三文件 parse/compileScript/compileTemplate 均 OK;dev localhost:2889 HMR 已生效。 + +## 全站附件上传统一(vehicle-attachment-upload 组件级单一事实来源) +- 需求:把"上传附件按钮在附件表格左下角 + 按钮右侧 30px 左对齐统一说明 + 单文件 500M"方案应用到整个站点,统一风格。 +- 核心做法(改 1 个组件即全站生效):`src/components/vehicle-attachment-upload/main.vue` + - 新增常量 `UNIFIED_ATTACHMENT_TIP = '支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过500M'`;`tipText` 改为 `this.tip || UNIFIED_ATTACHMENT_TIP`(不再按 acceptText 拼装)。 + - `maxSize` 默认值 `0` → `500`(说明与校验一致)。 + - 模板 `v-if="showTip && ..."` 去掉 `showTip` 门控 → `v-if="tipText && !readonly"`,全站始终显示统一说明(原 `:show-tip="false"` 变为无害 no-op,未逐一清理)。 + - SCSS 新增 `.vehicle-attachment-upload :deep(.el-upload){display:flex;align-items:center}` 与 `:deep(.el-upload__tip){display:inline-block;margin:0 0 0 30px;color:#909399;font-size:13px;text-align:left}`,按钮与说明内联、说明在按钮右侧 30px 左对齐。 +- 表格型附件区布局对齐(上传移表格下方左侧,批量下载留表头右侧):business-crud-page.vue(2 处 attachmentsJson-form / 派车明细附件)、contract-manage-change.vue、pre-settlement-editor.vue、master-order-editor.vue、payment-application-form.vue、invoice-application-form.vue;各页新增 `__attachment-upload` 左对齐样式、`__attachment-head` 改 `justify-content:flex-end`。 +- 大小异常值修正:bill-ledger-form / bill-payment-form 的 `:max-size="10"` → 500;invoice-application-form `:max-size="50"` → 500(同时把上传从表格上方移到下方)。 +- 已是下方布局无需移动(仅随组件生效):invoice-receipt / receipt-claim-record / receipt-flow / bill-ledger / bill-payment / formal-settlement-editor(独立上传无表格)/ 各 vehicle 页(独立上传无表格)。 +- 校验:@vue/compiler-sfc 对 12 个改动文件(组件 + 上述各页 + 此前已改的 project-apply/temporary-credit-limit/contract-manage)全部编译通过;grep 确认全站无残留非 500M 的附件 max-size。 + +## master-order 附件上传"按钮 + 描述"由两行改一行 +- 需求:用户截图 `/business/master-order?mode=editor` 详情附件区,"上传附件"按钮与"支持pdf…"描述文字分别居中、各占一行,要求并到同一行(与 vehicle-attachment-upload 组件默认样式一致)。 +- 根因:`master-order-editor.vue` 第 1814-1824 行 scoped CSS 把 `.master-editor__attachment-upload .el-upload` 强制 `display: inline-flex` 但未显式 `flex-wrap/align-items/text-align`;而 Element Plus 全局 `.el-upload` 默认 `text-align: center`,加 inline-flex 子元素被 EP 默认行为按各自一行居中显示。 +- 修复:在 `.master-editor__attachment-upload` 内用 `:deep(.el-upload)` 显式声明 `display: inline-flex; align-items: center; flex-wrap: nowrap; text-align: left`,并 `:deep(.el-upload__tip)` 改 `display: inline-block; margin: 0 0 0 8px; color:#909399; font-size:13px; line-height:1.4; white-space:normal; text-align:left`,让按钮与说明内联排成一行。 +- 结论:master-order 附件区与 project-apply/temporary-credit-limit/contract-manage 风格一致(按钮左 + 描述贴右侧)。 + +## vehicle-attachment-upload 恢复 showTip 门控 +- 根因:用户截图 feedback `customer-archive/form` 的「OCR上传识别」按钮下方仍显示统一附件说明,要求「OCR上传识别这里不用加描述」。该组件虽有 `showTip` prop,但此前「全站附件上传统一」时把模板门控 `v-if="showTip && tipText && !readonly"` 简化成了 `v-if="tipText && !readonly"`,导致 `:show-tip="false"` 失效。 +- 修复:恢复 `src/components/vehicle-attachment-upload/main.vue` 第 24 行的 `showTip &&` 条件,使 `:show-tip="false"` 可正常隐藏按钮旁说明;`customer-archive.vue` 中 OCR 上传实例已配置 `:show-tip="false"`,无需额外改动。 +- 影响:所有 `:show-tip="false"` 的调用点(annual-inspection/maintenance/accident/violation/tire/customer-archive 等)现在会按预期隐藏提示;未配置 `show-tip` 或 `:show-tip="true"` 的实例继续显示 `UNIFIED_ATTACHMENT_TIP`。 + +## customer-archive 客商材料上传按钮左、描述右、间距 30px +- 需求:用户第三轮明确「客商材料」表格下"上传附件"按钮与「支持pdf…」描述需并排、按钮左、描述右、间距严格 30px。 +- 定位:`src/views/vehicle/customer-archive.vue` 第 4637-4666 行 `.qualification-upload-bar`(grid 1fr auto 1fr 改 flex 的二次修正)。 +- 修复:保留 flex 容器,按钮区 `.vehicle-attachment-upload > :deep(.el-upload)` `flex: 0 0 auto` 贴左固定;描述 `:deep(.el-upload__tip)` `margin-left: 30px + white-space: nowrap + overflow:hidden + text-overflow:ellipsis + text-align:left`,与按钮同行紧贴、间距固定 30px、超长文案省略号。 +- 结论:布局"「上传附件」按钮 ←30px→ 「支持pdf…」描述",单行两端对齐。 + +## sidebar 子路由高亮回退(方案B) +- 需求:用户反馈点「客商档案」菜单后,再点新增/编辑/查看(跳子路由 /vehicle/customer-archive/form),左侧菜单选中灰底消失。 +- 根因:sidebar `activeMenu` getter 在无 `meta.activeMenu` 时退到 `route.path`(即子路由 /vehicle/customer-archive/form),与菜单 path /vehicle/customer-archive 不匹配,`` 找不到项 → 高亮丢失。同因还影响 /business/contract-manage/change 等独立子路由。 +- 修复(方案B,通用兜底,改 1 文件):`src/page/index/sidebar/index.vue` + - 新增 `menuPaths` computed:递归收集全站菜单 `website.menu` 的 `path` 字段进 Set。 + - `activeMenu` 在 `return path` 前加分支:当 `path` 不在 menuPaths 时,过滤出所有 `path.startsWith(p + '/')` 的菜单路径,按长度降序取最长前缀匹配者作为高亮项(即 /vehicle/customer-archive/form → /vehicle/customer-archive)。 + - 原有 `meta.activeMenu` 与 `menuIndexes`(带参菜单精确匹配)分支保持不变;路径完全相同的路由仍精确匹配,不受影响。 +- 结论:一次改动全站受益,所有"父菜单 + 独立子表单页"场景(customer-archive/form、contract-manage/change 等)自动保持父菜单高亮,无需逐路由配 activeMenu。HMR 已生效。 + +## master-order-dispatch 运费单位 select 撑爆 append 槽 +- 需求:用户截图 dispatch 页"任务信息"块下"数量 → 吨"与"单价 → 元/吨"两个 select 宽度比左侧 input 还宽,红框标记要求改小。 +- 根因:`src/views/business/components/master-order-dispatch.vue` 第 702 行 `.dispatch-form` 全局规则 `:deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; }` 把整个 dispatch 表单内**所有** el-select 强制 100% 宽;这两个 select 处于 `el-input` 的 `#append` slot 内,被强制撑开 append 容器,append 又把整个 `el-col :span="6"` 列占满。第 707 行 `.freight-form { :deep(.freight-unit-select) { width: 92px; } }` 想兜底 92px,但因 specificity 与覆盖时机问题未生效。 +- 修复(最小改动,2 处): + - 行 702 末尾追加 `:deep(.el-input-group__append .el-select) { width: auto; }`,使 append 内的 select 退回内容自适应宽度(避免被 100% 拉伸)。 + - 行 707 强化兜底:`.freight-unit-select` 加 `flex: 0 0 92px; min-width: 0;`,固定 92px 防止 append flex 拉伸。 +- 结论:单位 select(吨/元/吨)宽度由内容决定(≈92px),不再撑爆 append 与列;其它顶层 select(承运商/币种等)仍维持 100% 宽,行为不变。 diff --git a/src/components/vehicle-attachment-upload/main.vue b/src/components/vehicle-attachment-upload/main.vue index c4988ec..692197c 100644 --- a/src/components/vehicle-attachment-upload/main.vue +++ b/src/components/vehicle-attachment-upload/main.vue @@ -75,6 +75,9 @@ import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url'; import { baseUrl } from '@/config/env'; import { getUploadHeaders } from '@/utils/upload'; +const UNIFIED_ATTACHMENT_TIP = + '支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过500M'; + const MIME_MAP = { jpg: 'image/jpeg', jpeg: 'image/jpeg', @@ -143,7 +146,7 @@ export default { }, maxSize: { type: Number, - default: 0, + default: 500, }, readonly: { type: Boolean, @@ -212,10 +215,7 @@ export default { return this.acceptedList.join(','); }, tipText() { - if (this.tip) return this.tip; - const typeText = this.acceptText || '所有类型'; - const sizeText = this.maxSize > 0 ? `,单文件不超过 ${this.maxSize}MB` : ''; - return `支持上传 ${typeText}${sizeText}`; + return this.tip || UNIFIED_ATTACHMENT_TIP; }, uploadingCount() { return this.fileList.filter(file => ['ready', 'uploading'].includes(file.status)).length; @@ -372,6 +372,27 @@ export default { diff --git a/src/views/business/components/master-order-dispatch.vue b/src/views/business/components/master-order-dispatch.vue index f257d31..a27800a 100644 --- a/src/views/business/components/master-order-dispatch.vue +++ b/src/views/business/components/master-order-dispatch.vue @@ -697,12 +697,12 @@ export default { .route-overview__line { flex: 0 1 56px; min-width: 24px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; } .segment-header { min-height: 46px; padding: 0 20px; border-bottom: 1px solid #eff1f7; font-weight: 600; em { color: #409eff; font-style: normal; } } .segment-content { padding: 16px 24px; } -.dispatch-form { :deep(.el-form-item) { margin-bottom: 16px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } } +.dispatch-form { :deep(.el-form-item) { margin-bottom: 16px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } :deep(.el-input-group__append .el-select) { width: auto; } } .transport-type-field :deep(.el-input) { width: 240px; } .goods-heading { display: flex; align-items: center; justify-content: space-between; margin: 0 -24px 12px; padding: 14px 24px; border-top: 1px solid #eff1f7; border-bottom: 1px solid #eff1f7; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } span { color: #909399; font-size: 13px; } } .freight-heading { margin: 16px 0 12px; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } } .goods-table { :deep(th.el-table__cell), :deep(td.el-table__cell) { border-color: #eff1f7; } :deep(.el-table__row--striped td.el-table__cell) { background: #fafafa; } :deep(.goods-table__remaining .cell) { white-space: nowrap; } :deep(.goods-table__dispatch .el-input) { width: 100%; min-width: 0; } :deep(.goods-table__cargo-type .el-input__inner), :deep(.goods-table__cargo-name .el-select__selected-item) { color: #303133; } } -.freight-form { :deep(.freight-unit-select) { width: 92px; } } +.freight-form { :deep(.freight-unit-select) { width: 92px; flex: 0 0 92px; min-width: 0; } } .carrier-type-form { margin-top: 16px; } .carrier-form { padding-top: 8px; } .segment-actions { display: flex; justify-content: flex-end; gap: 12px; padding-top: 4px; } diff --git a/src/views/business/components/master-order-editor.vue b/src/views/business/components/master-order-editor.vue index b60e852..0205ef7 100644 --- a/src/views/business/components/master-order-editor.vue +++ b/src/views/business/components/master-order-editor.vue @@ -63,7 +63,7 @@
@@ -104,7 +104,7 @@
@@ -217,15 +217,6 @@

附件

- +
+ +
基本信息
- - - - - - - - - - - - - -
-
- - + + + + + + + + + + + + + +
+ +
合同文件
- 批量下载 + 批量下载 +
+ +
+
-
-
-
计费信息
- 添加 -
- 系统生成手动生成 - +
计费信息
添加
+ 系统生成手动生成 +
@@ -182,66 +46,13 @@ -
- 自动生成结算单开启关闭 -
- - - - - - +
自动生成结算单开启关闭
+ + + + + +
@@ -250,135 +61,29 @@ - - - + + + 添加 - +
-
-
其它附件
- 批量下载 -
- - 上传附件 +
其它附件
批量下载
+ + 上传附件
-
-
变更原因
- -
变更材料
- 上传变更材料 -
- +
变更原因
变更材料
上传变更材料
+ - - + + - + @@ -387,13 +92,7 @@ import * as api from '@/api/business/contract-manage'; import BillingPlanEditor from './components/billing-plan-editor.vue'; import { ElImageViewer } from 'element-plus'; import { OpenFileViewer } from '@open-file-viewer/vue'; -import { - fallbackPlugin, - imagePlugin, - officePlugin, - pdfPlugin, - textPlugin, -} from '@open-file-viewer/core'; +import { fallbackPlugin, imagePlugin, officePlugin, pdfPlugin, textPlugin } from '@open-file-viewer/core'; import '@open-file-viewer/core/style.css'; import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url'; @@ -407,396 +106,55 @@ const viewerPlugins = [ export default { components: { BillingPlanEditor, ElImageViewer, OpenFileViewer }, - data() { - return { - form: {}, - period: [], - plans: [], - attachments: [], - contractFiles: [], - contractFileRows: [], - selectedContractFiles: [], - paymentRatioRows: [], - settlementConfigTab: 'pre', - changeMaterials: [], - imagePreviewVisible: false, - imagePreviewUrls: [], - imagePreviewIndex: 0, - documentPreviewVisible: false, - previewFile: {}, - viewerPlugins, - viewerToolbar: { zoom: true, rotate: true, download: true, fullscreen: true }, - feeGenerationMode: 'system', - settlementRule: { - autoGenerate: 1, - settlementType: '月结', - billCycleType: '固定截单日', - billCutoffDay: 25, - cycleDays: '', - }, - preSettlementConfig: {}, - formalSettlementConfig: {}, - settlementTypeOptions: ['月结', '日结', '周结', '半月结', '固定天数周期结算'], - billCycleTypeOptions: ['固定截单日', '自然月'], - billCutoffDayOptions: Array.from({ length: 31 }, (_, index) => ({ - label: `${index + 1}日`, - value: index + 1, - })), - cycleDayOptions: [7, 15, 30, 60].map(value => ({ label: `${value}天`, value })), - planDialogVisible: false, - planEditor: { planName: '', defaultPlan: false, remark: '', rules: [] }, - planEditorIndex: -1, - billingElements: [ - '按重量', - '按体积', - '按车辆', - '按里程', - '按吨·公里', - '固定金额(整单一口价)', - '按数量', - ], - attachmentFileTypes: [ - 'pdf', - 'bmp', - 'jpeg', - 'png', - 'jpg', - 'doc', - 'docx', - 'ppt', - 'pptx', - 'xlsx', - 'xls', - 'eml', - 'msg', - 'zip', - ], - rules: { - contractName: [{ required: true, message: '请输入合同名称', trigger: 'blur' }], - changeReason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }], - }, - }; - }, - computed: { - showSettlementBillCycleType() { - return this.settlementRule.settlementType === '月结'; - }, - showSettlementBillCutoffDay() { - return this.showSettlementBillCycleType && this.settlementRule.billCycleType === '固定截单日'; - }, - showSettlementCycleDays() { - return this.settlementRule.settlementType === '固定天数周期结算'; - }, - }, - mounted() { - this.load(); - }, - watch: { - settlementConfigTab(tab, oldTab) { - if (tab === oldTab) return; - if (oldTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; - else this.formalSettlementConfig = { ...this.settlementRule }; - this.settlementRule = { - ...(tab === 'pre' ? this.preSettlementConfig : this.formalSettlementConfig), - }; - }, - }, + data() { return { form: {}, period: [], plans: [], attachments: [], contractFiles: [], contractFileRows: [], selectedContractFiles: [], paymentRatioRows: [], settlementConfigTab: 'pre', changeMaterials: [], imagePreviewVisible: false, imagePreviewUrls: [], imagePreviewIndex: 0, documentPreviewVisible: false, previewFile: {}, viewerPlugins, viewerToolbar: { zoom: true, rotate: true, download: true, fullscreen: true }, feeGenerationMode: 'system', settlementRule: { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: '' }, preSettlementConfig: {}, formalSettlementConfig: {}, settlementTypeOptions: ['月结','日结','周结','半月结','固定天数周期结算'], billCycleTypeOptions: ['固定截单日','自然月'], billCutoffDayOptions: Array.from({ length: 31 }, (_, index) => ({ label: `${index + 1}日`, value: index + 1 })), cycleDayOptions: [7,15,30,60].map(value => ({ label: `${value}天`, value })), planDialogVisible: false, planEditor: { planName: '', defaultPlan: false, remark: '', rules: [] }, planEditorIndex: -1, billingElements: ['按重量','按体积','按车辆','按里程','按吨·公里','固定金额(整单一口价)','按数量'], attachmentFileTypes: ['pdf','bmp','jpeg','png','jpg','doc','docx','ppt','pptx','xlsx','xls','eml','msg','zip'], rules: { contractName: [{ required: true, message: '请输入合同名称', trigger: 'blur' }], changeReason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }] } }; }, + computed: { showSettlementBillCycleType() { return this.settlementRule.settlementType === '月结'; }, showSettlementBillCutoffDay() { return this.showSettlementBillCycleType && this.settlementRule.billCycleType === '固定截单日'; }, showSettlementCycleDays() { return this.settlementRule.settlementType === '固定天数周期结算'; } }, + mounted() { this.load(); }, + watch: { settlementConfigTab(tab, oldTab) { if (tab === oldTab) return; if (oldTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; this.settlementRule = { ...(tab === 'pre' ? this.preSettlementConfig : this.formalSettlementConfig) }; } }, methods: { - async load() { - const id = this.$route.query.id; - if (!id) return; - const res = await api.getDetail(id); - const data = res.data?.data || res.data || {}; - this.form = { ...data, changeType: '合同信息变更' }; - this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; - this.plans = this.parse(data.billingPlanJson); - this.attachments = this.parse(data.attachmentsJson); - this.contractFileRows = this.parse(data.contractFileJson); - const rules = this.parseObject(data.settlementRuleJson); - const pre = this.parseObject(data.preSettlementConfigJson); - const formal = this.parseObject(data.formalSettlementConfigJson); - const legacy = Object.keys(rules).some( - key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key) - ) - ? rules - : {}; - this.preSettlementConfig = - rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); - this.formalSettlementConfig = - rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); - this.settlementRule = { ...this.preSettlementConfig }; - this.feeGenerationMode = - data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); - this.paymentRatioRows = this.parse(data.paymentRatioJson); - }, - parse(value) { - try { - const result = JSON.parse(value || '[]'); - return Array.isArray(result) ? result : []; - } catch { - return []; - } - }, - parseObject(value) { - try { - return { - autoGenerate: 1, - settlementType: '月结', - billCycleType: '固定截单日', - billCutoffDay: 25, - cycleDays: 15, - ...(JSON.parse(value || '{}') || {}), - }; - } catch { - return { - autoGenerate: 1, - settlementType: '月结', - billCycleType: '固定截单日', - billCutoffDay: 25, - cycleDays: 15, - }; - } - }, - addPlan() { - this.planEditorIndex = -1; - this.planEditor = { - planName: `计费方案${this.plans.length + 1}`, - defaultPlan: !this.plans.length, - remark: '', - rules: [{}], - }; - this.planDialogVisible = true; - }, - editPlan(row, index) { - this.planEditorIndex = index; - this.planEditor = JSON.parse(JSON.stringify(row)); - this.planDialogVisible = true; - }, - toggleDefaultPlan(value) { - if (value) - this.plans.forEach(item => { - item.defaultPlan = false; - }); - }, - savePlan(value, index) { - if (index < 0) this.plans.push(value); - else this.plans.splice(index, 1, value); - if (value.defaultPlan) - this.plans.forEach((item, current) => { - if (current !== (index < 0 ? this.plans.length - 1 : index)) item.defaultPlan = false; - }); - }, - handleSettlementTypeChange(value) { - if (value !== '月结') { - this.settlementRule.billCycleType = ''; - this.settlementRule.billCutoffDay = ''; - } else if (!this.settlementRule.billCycleType) - this.settlementRule.billCycleType = '固定截单日'; - if (value !== '固定天数周期结算') this.settlementRule.cycleDays = ''; - }, - handleCycleTypeChange(value) { - if (value === '固定截单日' && !this.settlementRule.billCutoffDay) - this.settlementRule.billCutoffDay = 25; - if (value !== '固定截单日') this.settlementRule.billCutoffDay = ''; - }, - handleAttachment(event) { - const raw = event.raw; - if (raw) - this.attachments.push({ - name: raw.name, - size: `${Math.ceil(raw.size / 1024)}KB`, - uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'), - }); - }, - handleContractFileChange(list) { - this.contractFileRows = (list || []).map(item => ({ - ...item, - uploadTime: item.uploadTime || this.$dayjs().format('YYYY-MM-DD HH:mm:ss'), - })); - }, - attachmentUrl(row = {}) { - return row.url || row.link || row.fileUrl || row.downloadUrl || row.domain || ''; - }, - attachmentName(row = {}) { - return row.originalName || row.name || row.fileName || '附件'; - }, - attachmentExtension(row = {}) { - const source = String(this.attachmentName(row) || this.attachmentUrl(row)).split('?')[0]; - const index = source.lastIndexOf('.'); - return index > -1 ? source.slice(index + 1).toLowerCase() : ''; - }, - isAttachmentImage(row) { - return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(this.attachmentExtension(row)); - }, - previewAttachment(row, rows = this.attachments) { - const url = this.attachmentUrl(row); - if (!url) { - this.$message.warning('附件地址为空,无法预览'); - return; - } - if (this.isAttachmentImage(row)) { - this.imagePreviewUrls = (rows || []) - .filter(item => this.isAttachmentImage(item) && this.attachmentUrl(item)) - .map(item => this.attachmentUrl(item)); - this.imagePreviewIndex = Math.max(this.imagePreviewUrls.indexOf(url), 0); - this.imagePreviewVisible = true; - return; - } - this.previewFile = { - name: this.attachmentName(row), - url, - mimeType: row.mimeType || row.contentType || '', - }; - this.documentPreviewVisible = true; - }, - handlePreviewUnsupported() { - this.$message.warning('当前文件暂不支持在线预览'); - }, - handlePreviewError() { - this.$message.error('附件预览失败'); - }, - removeContractFile(index) { - this.contractFileRows.splice(index, 1); - }, - handleContractFileBatchDownload() { - (this.selectedContractFiles.length - ? this.selectedContractFiles - : this.contractFileRows - ).forEach(row => { - if (row.url) window.open(row.url, '_blank'); - }); - }, - formatFileSize(value) { - const size = Number(value || 0); - return size > 1024 * 1024 - ? `${(size / 1024 / 1024).toFixed(2)}MB` - : `${Math.max(1, Math.ceil(size / 1024))}KB`; - }, - handleChangeMaterial(event) { - if (event.raw) this.changeMaterials.push(event.raw); - }, - addPaymentRatioRow() { - this.paymentRatioRows.push({ - paymentTerm: `第${this.paymentRatioRows.length + 1}笔`, - ratioLimit: '', - remark: '', - }); - }, - ratioInput(row, value) { - let nextValue = String(value ?? '').replace(/[^\d.]/g, ''); - const parts = nextValue.split('.'); - if (parts.length > 2) nextValue = `${parts.shift()}.${parts.join('')}`; - const [integerPart, decimalPart] = nextValue.split('.'); - nextValue = - decimalPart === undefined ? integerPart : `${integerPart}.${decimalPart.slice(0, 2)}`; - if (Number(nextValue) > 100) nextValue = '100'; - row.ratioLimit = nextValue; - }, - async submit() { - await this.$refs.formRef.validate(); - const total = this.paymentRatioRows.reduce( - (sum, row) => sum + Number(row.ratioLimit || 0), - 0 - ); - if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { - this.$message.warning('付款比例上限合计必须等于100%'); - return; - } - const settlementRule = { - preSettlementConfig: this.preSettlementConfig, - formalSettlementConfig: this.formalSettlementConfig, - }; - await api.submitChange({ - ...this.form, - startDate: this.period[0], - endDate: this.period[1], - feeGenerationMode: this.feeGenerationMode, - billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, - billingPlanJson: JSON.stringify(this.plans), - settlementRuleJson: JSON.stringify(settlementRule), - preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), - formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), - paymentRatioJson: JSON.stringify(this.paymentRatioRows), - contractFileJson: JSON.stringify(this.contractFileRows), - attachmentsJson: JSON.stringify(this.attachments), - changeContent: this.form.changeReason, - changeReason: this.form.changeReason, - }); - this.$message.success('变更已提交'); - this.$router.back(); - }, + async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, changeType: '合同信息变更' }; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); }, + parse(value) { try { const result = JSON.parse(value || '[]'); return Array.isArray(result) ? result : []; } catch { return []; } }, + parseObject(value) { try { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15, ...(JSON.parse(value || '{}') || {}) }; } catch { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15 }; } }, + addPlan() { this.planEditorIndex = -1; this.planEditor = { planName: `计费方案${this.plans.length + 1}`, defaultPlan: !this.plans.length, remark: '', rules: [{}] }; this.planDialogVisible = true; }, + editPlan(row, index) { this.planEditorIndex = index; this.planEditor = JSON.parse(JSON.stringify(row)); this.planDialogVisible = true; }, + toggleDefaultPlan(value) { if (value) this.plans.forEach(item => { item.defaultPlan = false; }); }, + savePlan(value, index) { if (index < 0) this.plans.push(value); else this.plans.splice(index, 1, value); if (value.defaultPlan) this.plans.forEach((item, current) => { if (current !== (index < 0 ? this.plans.length - 1 : index)) item.defaultPlan = false; }); }, + handleSettlementTypeChange(value) { if (value !== '月结') { this.settlementRule.billCycleType = ''; this.settlementRule.billCutoffDay = ''; } else if (!this.settlementRule.billCycleType) this.settlementRule.billCycleType = '固定截单日'; if (value !== '固定天数周期结算') this.settlementRule.cycleDays = ''; }, + handleCycleTypeChange(value) { if (value === '固定截单日' && !this.settlementRule.billCutoffDay) this.settlementRule.billCutoffDay = 25; if (value !== '固定截单日') this.settlementRule.billCutoffDay = ''; }, + handleAttachment(event) { const raw = event.raw; if (raw) this.attachments.push({ name: raw.name, size: `${Math.ceil(raw.size / 1024)}KB`, uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss') }); }, + handleContractFileChange(list) { this.contractFileRows = (list || []).map(item => ({ ...item, uploadTime: item.uploadTime || this.$dayjs().format('YYYY-MM-DD HH:mm:ss') })); }, + attachmentUrl(row = {}) { return row.url || row.link || row.fileUrl || row.downloadUrl || row.domain || ''; }, + attachmentName(row = {}) { return row.originalName || row.name || row.fileName || '附件'; }, + attachmentExtension(row = {}) { const source = String(this.attachmentName(row) || this.attachmentUrl(row)).split('?')[0]; const index = source.lastIndexOf('.'); return index > -1 ? source.slice(index + 1).toLowerCase() : ''; }, + isAttachmentImage(row) { return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(this.attachmentExtension(row)); }, + previewAttachment(row, rows = this.attachments) { const url = this.attachmentUrl(row); if (!url) { this.$message.warning('附件地址为空,无法预览'); return; } if (this.isAttachmentImage(row)) { this.imagePreviewUrls = (rows || []).filter(item => this.isAttachmentImage(item) && this.attachmentUrl(item)).map(item => this.attachmentUrl(item)); this.imagePreviewIndex = Math.max(this.imagePreviewUrls.indexOf(url), 0); this.imagePreviewVisible = true; return; } this.previewFile = { name: this.attachmentName(row), url, mimeType: row.mimeType || row.contentType || '' }; this.documentPreviewVisible = true; }, + handlePreviewUnsupported() { this.$message.warning('当前文件暂不支持在线预览'); }, + handlePreviewError() { this.$message.error('附件预览失败'); }, + removeContractFile(index) { this.contractFileRows.splice(index, 1); }, + handleContractFileBatchDownload() { (this.selectedContractFiles.length ? this.selectedContractFiles : this.contractFileRows).forEach(row => { if (row.url) window.open(row.url, '_blank'); }); }, + formatFileSize(value) { const size = Number(value || 0); return size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(2)}MB` : `${Math.max(1, Math.ceil(size / 1024))}KB`; }, + handleChangeMaterial(event) { if (event.raw) this.changeMaterials.push(event.raw); }, + addPaymentRatioRow() { this.paymentRatioRows.push({ paymentTerm: `第${this.paymentRatioRows.length + 1}笔`, ratioLimit: '', remark: '' }); }, + async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeReason, changeReason: this.form.changeReason }); this.$message.success('变更已提交'); this.$router.back(); }, }, }; diff --git a/src/views/business/contract-manage.vue b/src/views/business/contract-manage.vue index 90eaff0..00afa1a 100644 --- a/src/views/business/contract-manage.vue +++ b/src/views/business/contract-manage.vue @@ -275,32 +275,26 @@ - -
- - -
+ + - -
- - -
+ +
'批量下载' - ), - ]), + h( + ElButton, + { type: 'primary', disabled: !this.rows.length, onClick: this.batchDownload }, + () => '批量下载' + ), ]), h( ElTable, @@ -1081,6 +1059,23 @@ const AttachmentSection = defineComponent({ }, () => columns ), + ...(!this.readonly + ? [ + h('div', { class: 'contract-manage-form__attachment-upload' }, [ + h(VehicleAttachmentUpload, { + modelValue: this.rows, + fileTypes: this.attachmentFileTypes, + maxSize: 500, + showTip: true, + tip: '支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件不超过500M', + showFileList: false, + buttonText: '上传附件', + 'onUpdate:modelValue': this.handleChange, + onChange: this.handleChange, + }), + ]), + ] + : []), ] ); }, @@ -2197,25 +2192,6 @@ export default { } } - &__inline-number { - display: flex; - align-items: center; - gap: 8px; - width: 360px; - max-width: 100%; - - :deep(.el-input) { - flex: 1; - width: auto; - min-width: 0; - } - - span { - flex: none; - color: #606266; - } - } - &__billing-head, &__attachment-head { display: flex; @@ -2318,22 +2294,29 @@ export default { margin-bottom: 16px; } -:deep(.contract-manage-form__attachment-actions) { - display: inline-flex; - align-items: center; - justify-content: flex-end; - flex-wrap: nowrap; - gap: 8px; - white-space: nowrap; -} +:deep(.contract-manage-form__attachment-upload) { + display: flex; + justify-content: flex-start; + margin-top: 12px; -:deep(.contract-manage-form__attachment-actions .vehicle-attachment-upload) { - flex: 0 0 auto; - width: auto !important; -} + :deep(.vehicle-attachment-upload) { + display: flex; + align-items: center; + width: auto; + } -:deep(.contract-manage-form__attachment-actions .el-upload) { - display: inline-flex; + :deep(.el-upload) { + display: inline-flex; + } + + :deep(.el-upload__tip) { + display: inline-block; + margin: 0 0 0 30px; + color: #909399; + font-size: 13px; + line-height: 1.4; + text-align: left; + } } .contract-manage-detail { @@ -2383,4 +2366,8 @@ export default { white-space: normal; line-height: 1.2; } +.contract-manage-form__tip { + color: #ff0000 !important; + font-size: 12px; +} diff --git a/src/views/business/loading-manage.vue b/src/views/business/loading-manage.vue index f3a5b2e..a85e52b 100644 --- a/src/views/business/loading-manage.vue +++ b/src/views/business/loading-manage.vue @@ -901,7 +901,7 @@
{{ routeChangeTypeText(index) }}{{ node.address }}{{ tag }}
- + @@ -2631,6 +2631,9 @@ export default { gap: 16px; align-items: start; //margin-bottom: 12px; + .section-card { + min-height: 257px; + } } .loading-manage-dialog__candidate-actions, diff --git a/src/views/business/process-config.vue b/src/views/business/process-config.vue index 1e824ed..e06458c 100644 --- a/src/views/business/process-config.vue +++ b/src/views/business/process-config.vue @@ -105,7 +105,7 @@ :title="dialogReadonly ? '查看过程配置' : form.id ? '编辑过程配置' : '新建过程配置'" append-to-body v-model="configBox" - width="96%" + width="90%" top="4vh" class="process-config-dialog" :close-on-click-modal="false" @@ -170,7 +170,7 @@ @@ -585,7 +585,7 @@
- 批量下载 @@ -121,6 +112,18 @@ +
+ +
@@ -639,10 +642,35 @@ export default { &__attachment-head { display: flex; align-items: center; - justify-content: space-between; + justify-content: flex-end; margin-bottom: 12px; } + &__attachment-upload { + display: flex; + justify-content: flex-start; + margin-top: 12px; + + :deep(.vehicle-attachment-upload) { + display: flex; + align-items: center; + width: auto; + } + + :deep(.el-upload) { + display: inline-flex; + } + + :deep(.el-upload__tip) { + display: inline-block; + margin: 0 0 0 30px; + color: #909399; + font-size: 13px; + line-height: 1.4; + text-align: left; + } + } + &__flow { width: 100%; height: calc(100vh - 150px); @@ -670,4 +698,8 @@ export default { .temporary-credit-limit-dialog .business-crud-page__detail-content .el-descriptions__label { width: 180px !important; } +.el-form-item--default .el-form-item__label { + min-height: 30px; + height: auto !important; +} diff --git a/src/views/payment/bill-ledger-form.vue b/src/views/payment/bill-ledger-form.vue index 87daa14..7c80652 100644 --- a/src/views/payment/bill-ledger-form.vue +++ b/src/views/payment/bill-ledger-form.vue @@ -231,7 +231,7 @@ class="bill-ledger-form-page__uploader" :multiple="true" :limit="20" - :max-size="10" + :max-size="500" :file-types="attachmentFileTypes" :show-file-list="false" button-text="上传" @@ -244,7 +244,7 @@ - @@ -399,6 +388,19 @@ +
+ +
@@ -407,7 +409,7 @@ v-model="form.remark" :disabled="readonly" type="textarea" - :rows="3" + :rows="2" maxlength="200" show-word-limit /> @@ -970,6 +972,17 @@ export default { gap: 8px; padding: 16px 0 8px; } +.invoice-form-page__attachment-upload { + display: flex; + justify-content: flex-start; + margin-top: 12px; +} +.invoice-form-page__attachment-upload .vehicle-attachment-upload { + width: auto; +} +.invoice-form-page__attachment-upload .el-upload { + display: inline-flex; +} .invoice-form-page__dialog-search { display: flex; justify-content: flex-end; diff --git a/src/views/payment/invoice-receipt-form.vue b/src/views/payment/invoice-receipt-form.vue index 45925ce..d783b48 100644 --- a/src/views/payment/invoice-receipt-form.vue +++ b/src/views/payment/invoice-receipt-form.vue @@ -232,7 +232,7 @@ v-model="form.remark" :disabled="readonly" type="textarea" - :rows="3" + :rows="2" maxlength="200" show-word-limit /> diff --git a/src/views/payment/payment-application-form.vue b/src/views/payment/payment-application-form.vue index f0cdb00..4a1d369 100644 --- a/src/views/payment/payment-application-form.vue +++ b/src/views/payment/payment-application-form.vue @@ -245,17 +245,7 @@ /> - +
+ +
返回 - +
diff --git a/src/views/payment/receipt-flow-form.vue b/src/views/payment/receipt-flow-form.vue index 32dd9b9..c6fb752 100644 --- a/src/views/payment/receipt-flow-form.vue +++ b/src/views/payment/receipt-flow-form.vue @@ -159,7 +159,7 @@ > diff --git a/src/views/settlement/components/pre-settlement-editor.vue b/src/views/settlement/components/pre-settlement-editor.vue index ecaa8bb..9de53b3 100644 --- a/src/views/settlement/components/pre-settlement-editor.vue +++ b/src/views/settlement/components/pre-settlement-editor.vue @@ -292,19 +292,6 @@
- 批量下载 @@ -341,6 +328,20 @@ +
+ +
@@ -1559,10 +1560,25 @@ export default { &__attachment-actions { display: flex; align-items: center; + justify-content: flex-end; gap: 8px; margin-bottom: 12px; } + &__attachment-upload { + display: flex; + justify-content: flex-start; + margin-top: 12px; + + :deep(.vehicle-attachment-upload) { + width: auto; + } + + :deep(.el-upload) { + display: inline-flex; + } + } + &__summary-total { padding: 12px 16px 0; text-align: right; diff --git a/src/views/system/authlock.vue b/src/views/system/authlock.vue index 883c783..f45f8d9 100644 --- a/src/views/system/authlock.vue +++ b/src/views/system/authlock.vue @@ -88,7 +88,7 @@ @@ -144,7 +144,7 @@ diff --git a/src/views/system/user.vue b/src/views/system/user.vue index 1442bbe..4a93510 100644 --- a/src/views/system/user.vue +++ b/src/views/system/user.vue @@ -200,7 +200,7 @@ 仅所属组织全部组织自定义 包含下级仅本级 - + diff --git a/src/views/transit/exception-disposal.vue b/src/views/transit/exception-disposal.vue index de4bad0..a202a86 100644 --- a/src/views/transit/exception-disposal.vue +++ b/src/views/transit/exception-disposal.vue @@ -200,7 +200,7 @@ type="textarea" maxlength="500" show-word-limit - :rows="4" + :rows="2" placeholder="请输入" /> diff --git a/src/views/transit/risk-disposal.vue b/src/views/transit/risk-disposal.vue index fa49742..36c5118 100644 --- a/src/views/transit/risk-disposal.vue +++ b/src/views/transit/risk-disposal.vue @@ -158,7 +158,7 @@ v-model="disposeForm.disposalRemark" type="textarea" maxlength="500" - :rows="4" + :rows="2" :disabled="dialog.readonly" /> diff --git a/src/views/vehicle/credit-score-quantification.vue b/src/views/vehicle/credit-score-quantification.vue index 06f6a07..4d2427c 100644 --- a/src/views/vehicle/credit-score-quantification.vue +++ b/src/views/vehicle/credit-score-quantification.vue @@ -105,7 +105,7 @@ diff --git a/src/views/vehicle/customer-archive.vue b/src/views/vehicle/customer-archive.vue index f647030..8adc03d 100644 --- a/src/views/vehicle/customer-archive.vue +++ b/src/views/vehicle/customer-archive.vue @@ -606,7 +606,6 @@ v-model="ocrQualificationUploadFiles" :multiple="true" :limit="20" - accept=".pdf,.bmp,.jpeg,.png,.jpg,.doc,.docx,.ppt,.pptx,.xlsx,.xls,.eml,.msg,.zip" :max-size="500" button-text="OCR上传识别" :show-tip="false" @@ -689,14 +688,10 @@ accept=".pdf,.bmp,.jpeg,.png,.jpg,.doc,.docx,.ppt,.pptx,.xlsx,.xls,.eml,.msg,.zip" :max-size="500" button-text="上传附件" - :show-tip="false" :show-file-list="false" :show-uploading="true" @success="handleQualificationUploadSuccess" /> - - 支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip,单个文件不超过500M -
@@ -859,7 +854,13 @@
- + @@ -951,7 +952,13 @@ - + @@ -4559,7 +4566,7 @@ export default { display: flex; align-items: center; gap: 10px; - width: 97%; + width: 100%; } .business-term-field { @@ -4650,21 +4657,33 @@ export default { } .qualification-upload-bar { - display: grid; - grid-template-columns: 1fr auto 1fr; + display: flex; align-items: center; margin-top: 12px; margin-bottom: 6px; :deep(.vehicle-attachment-upload) { - width: auto; - } + flex: 1; + display: flex; + align-items: center; + min-width: 0; - &__tip { - grid-column: 2; - color: #909399; - font-size: 13px; - text-align: center; + :deep(.el-upload) { + flex: 0 0 auto; + display: inline-flex; + align-items: center; + } + + :deep(.el-upload__tip) { + margin-left: 30px; + color: #909399; + font-size: 13px; + line-height: 1.4; + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } } diff --git a/vite.config.mjs.timestamp-1787653210304-5b6c221708201.mjs b/vite.config.mjs.timestamp-1787653210304-5b6c221708201.mjs new file mode 100644 index 0000000..30fcf0c --- /dev/null +++ b/vite.config.mjs.timestamp-1787653210304-5b6c221708201.mjs @@ -0,0 +1,158 @@ +// vite.config.mjs +import { + defineConfig, + loadEnv +} from "file:///Users/gxwebsoft/VUE/tms-erp-web-ws/node_modules/.pnpm/vite@5.4.21_sass@1.99.0_terser@5.46.2/node_modules/vite/dist/node/index.js"; +import { resolve } from "path"; + +// vite/plugins/index.js +import vue from "file:///Users/gxwebsoft/VUE/tms-erp-web-ws/node_modules/.pnpm/@vitejs+plugin-vue@5.2.4_vite@5.4.21_sass@1.99.0_terser@5.46.2__vue@3.5.34/node_modules/@vitejs/plugin-vue/dist/index.mjs"; + +// vite/plugins/auto-import.js +import autoImport from "file:///Users/gxwebsoft/VUE/tms-erp-web-ws/node_modules/.pnpm/unplugin-auto-import@0.11.5_@vueuse+core@14.3.0_vue@3.5.34__rollup@4.60.3/node_modules/unplugin-auto-import/dist/vite.js"; +function createAutoImport() { + return autoImport({ + imports: ["vue", "vue-router", "vuex"], + dts: false + }); +} + +// vite/plugins/compression.js +import compression from "file:///Users/gxwebsoft/VUE/tms-erp-web-ws/node_modules/.pnpm/vite-plugin-compression@0.5.1_vite@5.4.21_sass@1.99.0_terser@5.46.2_/node_modules/vite-plugin-compression/dist/index.mjs"; +function createCompression(env) { + const { VITE_BUILD_COMPRESS } = env; + const plugin = []; + if (VITE_BUILD_COMPRESS) { + const compressList = VITE_BUILD_COMPRESS.split(","); + if (compressList.includes("gzip")) { + plugin.push( + compression({ + ext: ".gz", + deleteOriginFile: false + }) + ); + } + if (compressList.includes("brotli")) { + plugin.push( + compression({ + ext: ".br", + algorithm: "brotliCompress", + deleteOriginFile: false + }) + ); + } + } + return plugin; +} + +// vite/plugins/setup-extend.js +import setupExtend from "file:///Users/gxwebsoft/VUE/tms-erp-web-ws/node_modules/.pnpm/vite-plugin-vue-setup-extend@0.4.0_vite@5.4.21_sass@1.99.0_terser@5.46.2_/node_modules/vite-plugin-vue-setup-extend/dist/index.mjs"; +function createSetupExtend() { + return setupExtend(); +} + +// vite/plugins/index.js +function createVitePlugins(viteEnv, isBuild = false) { + const vitePlugins = [vue()]; + vitePlugins.push(createAutoImport()); + vitePlugins.push(createSetupExtend()); + isBuild && vitePlugins.push(...createCompression(viteEnv)); + return vitePlugins; +} + +// vite.config.mjs +var __vite_injected_original_dirname = "/Users/gxwebsoft/VUE/tms-erp-web-ws"; +var vite_config_default = ({ + mode, + command +}) => { + const env = loadEnv(mode, process.cwd()); + const { + VITE_APP_ENV, + VITE_APP_BASE + } = env; + const isProd = VITE_APP_ENV === "production"; + const buildConfig = { + target: "esnext", + minify: isProd ? "terser" : "esbuild" + // 根据环境选择压缩工具 + }; + if (isProd) { + buildConfig.terserOptions = { + compress: { + drop_console: true, + // 删除 console + drop_debugger: true + // 删除 debugger + }, + format: { + comments: false + // 删除所有注释 + } + }; + buildConfig.rollupOptions = { + output: { + manualChunks: { + "element-plus": ["element-plus"], + "@smallwei/avue": ["@smallwei/avue"] + } + } + }; + } + return defineConfig({ + base: VITE_APP_BASE, + define: { + __VUE_I18N_FULL_INSTALL__: true, + __VUE_I18N_LEGACY_API__: true, + __INTLIFY_PROD_DEVTOOLS__: false + }, + // server: { + // port: 2888, + // proxy: { + // '/api': { + // target: 'http://localhost', + // //target: 'https://saber3.bladex.cn/api', + // changeOrigin: true, + // rewrite: path => path.replace(/^\/api/, ''), + // }, + // }, + // }, + server: { + port: 2889, + proxy: { + "/api": { + target: "http://172.16.203.228:8000", + changeOrigin: true + } + } + }, + resolve: { + alias: { + "~": resolve(__vite_injected_original_dirname, "./"), + "@": resolve(__vite_injected_original_dirname, "./src"), + components: resolve(__vite_injected_original_dirname, "./src/components"), + styles: resolve(__vite_injected_original_dirname, "./src/styles"), + utils: resolve(__vite_injected_original_dirname, "./src/utils") + } + }, + css: { + preprocessorOptions: { + scss: { + api: "modern-compiler", + additionalData: `@use "@/styles/variables.scss" as *;` + } + } + }, + plugins: createVitePlugins(env, command === "build"), + build: buildConfig, + optimizeDeps: { + esbuildOptions: { + target: "esnext" + } + } + }); +}; +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcubWpzIiwgInZpdGUvcGx1Z2lucy9pbmRleC5qcyIsICJ2aXRlL3BsdWdpbnMvYXV0by1pbXBvcnQuanMiLCAidml0ZS9wbHVnaW5zL2NvbXByZXNzaW9uLmpzIiwgInZpdGUvcGx1Z2lucy9zZXR1cC1leHRlbmQuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL2d4d2Vic29mdC9WVUUvdG1zLWVycC13ZWItd3Mvdml0ZS5jb25maWcubWpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9neHdlYnNvZnQvVlVFL3Rtcy1lcnAtd2ViLXdzL3ZpdGUuY29uZmlnLm1qc1wiO2ltcG9ydCB7XG4gIGRlZmluZUNvbmZpZyxcbiAgbG9hZEVudlxufSBmcm9tICd2aXRlJztcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdwYXRoJ1xuaW1wb3J0IGNyZWF0ZVZpdGVQbHVnaW5zIGZyb20gJy4vdml0ZS9wbHVnaW5zJztcbi8vIGh0dHBzOi8vdml0ZWpzLmRldi9jb25maWcvXG5leHBvcnQgZGVmYXVsdCAoe1xuICBtb2RlLFxuICBjb21tYW5kXG59KSA9PiB7XG4gIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSlcbiAgY29uc3Qge1xuICAgIFZJVEVfQVBQX0VOVixcbiAgICBWSVRFX0FQUF9CQVNFXG4gIH0gPSBlbnZcbiAgLy8gXHU1MjI0XHU2NUFEXHU2NjJGXHU2MjUzXHU3NTFGXHU0RUE3XHU3M0FGXHU1ODgzXHU1MzA1XG4gIGNvbnN0IGlzUHJvZCA9IFZJVEVfQVBQX0VOViA9PT0gJ3Byb2R1Y3Rpb24nXG5cbiAgLy8gXHU2ODM5XHU2MzZFXHU2NjJGXHU1NDI2XHU3NTFGXHU0RUE3XHU3M0FGXHU1ODgzXHVGRjBDXHU1MkE4XHU2MDAxXHU4QkJFXHU3RjZFXHU1MzhCXHU3RjI5XHU5MTREXHU3RjZFXG4gIGNvbnN0IGJ1aWxkQ29uZmlnID0ge1xuICAgIHRhcmdldDogJ2VzbmV4dCcsXG4gICAgbWluaWZ5OiBpc1Byb2QgPyAndGVyc2VyJyA6ICdlc2J1aWxkJywgLy8gXHU2ODM5XHU2MzZFXHU3M0FGXHU1ODgzXHU5MDA5XHU2MkU5XHU1MzhCXHU3RjI5XHU1REU1XHU1MTc3XG4gIH07XG5cbiAgLy8gXHU1OTgyXHU2NzlDXHU2NjJGXHU3NTFGXHU0RUE3XHU3M0FGXHU1ODgzXHVGRjBDXHU2REZCXHU1MkEwVGVyc2VyXHU3Njg0XHU5MTREXHU3RjZFXG4gIGlmIChpc1Byb2QpIHtcbiAgICBidWlsZENvbmZpZy50ZXJzZXJPcHRpb25zID0ge1xuICAgICAgY29tcHJlc3M6IHtcbiAgICAgICAgZHJvcF9jb25zb2xlOiB0cnVlLCAvLyBcdTUyMjBcdTk2NjQgY29uc29sZVxuICAgICAgICBkcm9wX2RlYnVnZ2VyOiB0cnVlLCAvLyBcdTUyMjBcdTk2NjQgZGVidWdnZXJcbiAgICAgIH0sXG4gICAgICBmb3JtYXQ6IHtcbiAgICAgICAgY29tbWVudHM6IGZhbHNlIC8vIFx1NTIyMFx1OTY2NFx1NjI0MFx1NjcwOVx1NkNFOFx1OTFDQVxuICAgICAgfVxuICAgIH07XG4gICAgYnVpbGRDb25maWcucm9sbHVwT3B0aW9ucyA9IHtcbiAgICAgIG91dHB1dDoge1xuICAgICAgICBtYW51YWxDaHVua3M6IHtcbiAgICAgICAgICAnZWxlbWVudC1wbHVzJzogWydlbGVtZW50LXBsdXMnXSxcbiAgICAgICAgICAnQHNtYWxsd2VpL2F2dWUnOiBbJ0BzbWFsbHdlaS9hdnVlJ11cbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlZmluZUNvbmZpZyh7XG4gICAgYmFzZTogVklURV9BUFBfQkFTRSxcbiAgICBkZWZpbmU6IHtcbiAgICAgIF9fVlVFX0kxOE5fRlVMTF9JTlNUQUxMX186IHRydWUsXG4gICAgICBfX1ZVRV9JMThOX0xFR0FDWV9BUElfXzogdHJ1ZSxcbiAgICAgIF9fSU5UTElGWV9QUk9EX0RFVlRPT0xTX186IGZhbHNlLFxuICAgIH0sXG4gICAgLy8gc2VydmVyOiB7XG4gICAgLy8gICBwb3J0OiAyODg4LFxuICAgIC8vICAgcHJveHk6IHtcbiAgICAvLyAgICAgJy9hcGknOiB7XG4gICAgLy8gICAgICAgdGFyZ2V0OiAnaHR0cDovL2xvY2FsaG9zdCcsXG4gICAgLy8gICAgICAgLy90YXJnZXQ6ICdodHRwczovL3NhYmVyMy5ibGFkZXguY24vYXBpJyxcbiAgICAvLyAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXG4gICAgLy8gICAgICAgcmV3cml0ZTogcGF0aCA9PiBwYXRoLnJlcGxhY2UoL15cXC9hcGkvLCAnJyksXG4gICAgLy8gICAgIH0sXG4gICAgLy8gICB9LFxuICAgIC8vIH0sXG4gICAgc2VydmVyOiB7XG4gICAgICBwb3J0OiAyODg5LFxuICAgICAgcHJveHk6IHtcbiAgICAgICAgJy9hcGknOiB7XG4gICAgICAgICAgdGFyZ2V0OiAnaHR0cDovLzE3Mi4xNi4yMDMuMjI4OjgwMDAnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczoge1xuICAgICAgICAnfic6IHJlc29sdmUoX19kaXJuYW1lLCAnLi8nKSxcbiAgICAgICAgJ0AnOiByZXNvbHZlKF9fZGlybmFtZSwgJy4vc3JjJyksXG4gICAgICAgIGNvbXBvbmVudHM6IHJlc29sdmUoX19kaXJuYW1lLCAnLi9zcmMvY29tcG9uZW50cycpLFxuICAgICAgICBzdHlsZXM6IHJlc29sdmUoX19kaXJuYW1lLCAnLi9zcmMvc3R5bGVzJyksXG4gICAgICAgIHV0aWxzOiByZXNvbHZlKF9fZGlybmFtZSwgJy4vc3JjL3V0aWxzJyksXG4gICAgICB9LFxuICAgIH0sXG4gICAgY3NzOiB7XG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XG4gICAgICAgIHNjc3M6IHtcbiAgICAgICAgICBhcGk6ICdtb2Rlcm4tY29tcGlsZXInLFxuICAgICAgICAgIGFkZGl0aW9uYWxEYXRhOiBgQHVzZSBcIkAvc3R5bGVzL3ZhcmlhYmxlcy5zY3NzXCIgYXMgKjtgLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHBsdWdpbnM6IGNyZWF0ZVZpdGVQbHVnaW5zKGVudiwgY29tbWFuZCA9PT0gJ2J1aWxkJyksXG4gICAgYnVpbGQ6IGJ1aWxkQ29uZmlnLFxuICAgIG9wdGltaXplRGVwczoge1xuICAgICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgICAgdGFyZ2V0OiAnZXNuZXh0JyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG59O1xuIiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9neHdlYnNvZnQvVlVFL3Rtcy1lcnAtd2ViLXdzL3ZpdGUvcGx1Z2lucy9pbmRleC5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnMvaW5kZXguanNcIjtpbXBvcnQgdnVlIGZyb20gJ0B2aXRlanMvcGx1Z2luLXZ1ZSc7XG5cbmltcG9ydCBjcmVhdGVBdXRvSW1wb3J0IGZyb20gJy4vYXV0by1pbXBvcnQnO1xuaW1wb3J0IGNyZWF0ZUNvbXByZXNzaW9uIGZyb20gJy4vY29tcHJlc3Npb24nO1xuaW1wb3J0IGNyZWF0ZVNldHVwRXh0ZW5kIGZyb20gJy4vc2V0dXAtZXh0ZW5kJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY3JlYXRlVml0ZVBsdWdpbnModml0ZUVudiwgaXNCdWlsZCA9IGZhbHNlKSB7XG4gIGNvbnN0IHZpdGVQbHVnaW5zID0gW3Z1ZSgpXTtcbiAgdml0ZVBsdWdpbnMucHVzaChjcmVhdGVBdXRvSW1wb3J0KCkpO1xuICB2aXRlUGx1Z2lucy5wdXNoKGNyZWF0ZVNldHVwRXh0ZW5kKCkpO1xuICBpc0J1aWxkICYmIHZpdGVQbHVnaW5zLnB1c2goLi4uY3JlYXRlQ29tcHJlc3Npb24odml0ZUVudikpO1xuICByZXR1cm4gdml0ZVBsdWdpbnM7XG59IiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9neHdlYnNvZnQvVlVFL3Rtcy1lcnAtd2ViLXdzL3ZpdGUvcGx1Z2lucy9hdXRvLWltcG9ydC5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnMvYXV0by1pbXBvcnQuanNcIjtpbXBvcnQgYXV0b0ltcG9ydCBmcm9tICd1bnBsdWdpbi1hdXRvLWltcG9ydC92aXRlJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY3JlYXRlQXV0b0ltcG9ydCgpIHtcbiAgcmV0dXJuIGF1dG9JbXBvcnQoe1xuICAgIGltcG9ydHM6IFsndnVlJywgJ3Z1ZS1yb3V0ZXInLCAndnVleCddLFxuICAgIGR0czogZmFsc2UsXG4gIH0pO1xufVxuIiwgImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9neHdlYnNvZnQvVlVFL3Rtcy1lcnAtd2ViLXdzL3ZpdGUvcGx1Z2lucy9jb21wcmVzc2lvbi5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnMvY29tcHJlc3Npb24uanNcIjtpbXBvcnQgY29tcHJlc3Npb24gZnJvbSAndml0ZS1wbHVnaW4tY29tcHJlc3Npb24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVDb21wcmVzc2lvbihlbnYpIHtcbiAgY29uc3QgeyBWSVRFX0JVSUxEX0NPTVBSRVNTIH0gPSBlbnY7XG4gIGNvbnN0IHBsdWdpbiA9IFtdO1xuICBpZiAoVklURV9CVUlMRF9DT01QUkVTUykge1xuICAgIGNvbnN0IGNvbXByZXNzTGlzdCA9IFZJVEVfQlVJTERfQ09NUFJFU1Muc3BsaXQoJywnKTtcbiAgICBpZiAoY29tcHJlc3NMaXN0LmluY2x1ZGVzKCdnemlwJykpIHtcbiAgICAgIHBsdWdpbi5wdXNoKFxuICAgICAgICBjb21wcmVzc2lvbih7XG4gICAgICAgICAgZXh0OiAnLmd6JyxcbiAgICAgICAgICBkZWxldGVPcmlnaW5GaWxlOiBmYWxzZSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChjb21wcmVzc0xpc3QuaW5jbHVkZXMoJ2Jyb3RsaScpKSB7XG4gICAgICBwbHVnaW4ucHVzaChcbiAgICAgICAgY29tcHJlc3Npb24oe1xuICAgICAgICAgIGV4dDogJy5icicsXG4gICAgICAgICAgYWxnb3JpdGhtOiAnYnJvdGxpQ29tcHJlc3MnLFxuICAgICAgICAgIGRlbGV0ZU9yaWdpbkZpbGU6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHBsdWdpbjtcbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL2d4d2Vic29mdC9WVUUvdG1zLWVycC13ZWItd3Mvdml0ZS9wbHVnaW5zXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMvZ3h3ZWJzb2Z0L1ZVRS90bXMtZXJwLXdlYi13cy92aXRlL3BsdWdpbnMvc2V0dXAtZXh0ZW5kLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9neHdlYnNvZnQvVlVFL3Rtcy1lcnAtd2ViLXdzL3ZpdGUvcGx1Z2lucy9zZXR1cC1leHRlbmQuanNcIjtpbXBvcnQgc2V0dXBFeHRlbmQgZnJvbSAndml0ZS1wbHVnaW4tdnVlLXNldHVwLWV4dGVuZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVNldHVwRXh0ZW5kKCkge1xuICByZXR1cm4gc2V0dXBFeHRlbmQoKTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBNlI7QUFBQSxFQUMzUjtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxlQUFlOzs7QUNKOFIsT0FBTyxTQUFTOzs7QUNBSixPQUFPLGdCQUFnQjtBQUUxVSxTQUFSLG1CQUFvQztBQUN6QyxTQUFPLFdBQVc7QUFBQSxJQUNoQixTQUFTLENBQUMsT0FBTyxjQUFjLE1BQU07QUFBQSxJQUNyQyxLQUFLO0FBQUEsRUFDUCxDQUFDO0FBQ0g7OztBQ1BrVSxPQUFPLGlCQUFpQjtBQUUzVSxTQUFSLGtCQUFtQyxLQUFLO0FBQzdDLFFBQU0sRUFBRSxvQkFBb0IsSUFBSTtBQUNoQyxRQUFNLFNBQVMsQ0FBQztBQUNoQixNQUFJLHFCQUFxQjtBQUN2QixVQUFNLGVBQWUsb0JBQW9CLE1BQU0sR0FBRztBQUNsRCxRQUFJLGFBQWEsU0FBUyxNQUFNLEdBQUc7QUFDakMs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