style(contract): 优化合同管理页面表单样式与布局
- 调整合同管理备注输入框行数和最大长度 - 细化合同变更页面表单项间距和对齐方式 - 统一弹窗表单项的底部间距样式,改为注释禁用 - 调整 port-terminal 和 region 组件的表单项底部间距 - 修改 vite 配置中 API 请求代理地址 - 优化凭证执行详情搜索表单列宽布局 - 在运单管理页面更新型号字段为非必填,调整变更记录内容格式化显示 - 引入并使用 formatRouteChangeContent 工具函数 - 统一明细按钮显示逻辑,草稿状态也显示详情按钮 - 新增路由变更相关工具函数与样式支持
This commit is contained in:
@@ -22,6 +22,36 @@
|
||||
|
||||
**坑三:路由表重复定义 → 内容区整页空白(2026-09-18)。** `/business/contract-manage/detail` 在 `router/views/index.js` 定义两次、子路由同名 `合同详情`。重名 `addRoute` 会 `removeRoute(name)` 移除旧子记录,但**不从父记录 children 里摘除**,第一条 Layout 壳记录留在 matcher 且靠前 → `resolve()` 命中它 → `$route.matched.length === 1` → 二级 router-view 无匹配 → 侧栏/标签正常但内容空白。修法:删重复定义。排查:扫「顶层 path + 首个子路由 name」重复项。
|
||||
|
||||
## 列表页右上角按钮组(table-header-tools 标准件)
|
||||
⚠️ **2026-10-14 修正:最终方向是手写列表页改用 `avue-crud`**。用户要求与其它模块"完全一致",而 avue 的列显隐抽屉(`el-drawer`+表格,隐藏/冻结/过滤/排序,行拖拽)是 avue-crud 内部子组件(`inject: ['crud']`),脱离 avue-crud 拿不出来;第 4 键也是 avue 的"表格↔卡片视图"切换。所以 `table-header-tools` 只是过渡仿制件,**新页面不要再接**,直接写 avue-crud。
|
||||
|
||||
手写 `el-table` 列表页若暂时保留,右上角统一用 `src/components/table-header-tools/main.vue`,复刻 avue-crud 默认 4 键:刷新 `el-icon-refresh` / 列设置 `el-icon-operation` / 搜索显隐 `el-icon-search` / 表格尺寸 `el-icon-grid`(default→large→small 循环)。
|
||||
|
||||
- 接入范式:`<table-header-tools :columns="columns" v-model:visible-column-keys="visibleColumnKeys" v-model:table-size="tableSize" v-model:search-visible="searchVisible" @refresh="loadTable" />`;配套:搜索区 `v-if="searchVisible"`、el-table `:size="tableSize"`、列用 computed `visibleColumns = columns.filter(c => visibleColumnKeys.includes(c.prop))`。⚠️ 不能 `v-for` + `v-if` 同元素(Vue3 v-if 优先级更高,取不到 column 变量)。
|
||||
- 表格在子组件时(如 `payment/components/bill-*-table.vue`):子组件加 props `searchVisible` + emits `refresh`/`update:searchVisible`,父页面 `v-model:search-visible` + `@refresh`,搜索子组件加 `v-if="searchVisible"`。
|
||||
- `icon="el-icon-xxx"` 字符串**依赖 Avue 的全局 el-icon 映射**(`main.js` 只注册 EP 的 PascalCase 图标),临时验证页没 `app.use(Avue)` 会渲染成空圆按钮 —— 别误判成组件 bug。
|
||||
- 组件已加 `deactivated()` 关列设置弹窗(防 keep-alive 下 Teleport 弹窗残留)。
|
||||
- 已接入(过渡态,待逐页改 avue):business/{master-order,loading-manage,voucher-manage}、settlement、payment 模块手写页。
|
||||
|
||||
## avue-crud 列表页改造要点(payment 模块样板,2026-10-14)
|
||||
- **列显隐抽屉**:点第 2 键弹出,标题"列显隐"(语言包 `crud.showTitle`),表头 列名/隐藏/冻结/过滤/排序。直接读写 avue crud 的列配置,页面无需实现。
|
||||
- **第 4 键**:`handleGridShow()` = 表格 ↔ 卡片视图(`tableCard` 按列通用渲染),页面无需写卡片模板。
|
||||
- `searchOrder` 是**降序**排序(值越大越靠前):`list.sort((a,b) => (b.searchOrder||0) - (a.searchOrder||0))`。首次改造踩过坑。
|
||||
- `searchIndex: 4` + `searchIcon: true` → 默认只显示前 4 个搜索项 + "展开/收起"(columnLen > searchIndex 时才出现该按钮)。
|
||||
- **搜索项 label 与表格列 label 不同**(列「收款方」/搜索「客户名称」):单独定义 hide 列 + `searchProp` 指向后端字段(avue 在 search-change 里自动改名)。
|
||||
- 搜索专用列加 `hide: true` + `showColumn: false`,否则会混进列显隐抽屉。
|
||||
- ⚠️ **column 数组顺序 = 表格列顺序**:搜索专用列别插在表格列中间(会把表格列顶到前面);deptName 这种"既搜索又展示"的列要放回表格列的正确位置。
|
||||
- 分页:`page: { currentPage, pageSize, pageSizes, total }`;`on-load` 由 avue 内部(table-page)在 created / 翻页 / 改页容量时触发,`current-change`/`size-change` 里**只改 page 不要再调 onLoad**(否则双请求)。
|
||||
- `onLoad(page)` 只用 `this.query`(avue 传的 page 对象含 total/pageSizes 等分页字段,别 spread 进查询参数)。
|
||||
- 搜索参数转换放 `searchChange(params, done)`:日期区间数组拆成 `xxxStartDate/xxxEndDate`;所属组织级联用 `normalizeOrganizationSearch(params, 'deptName')`(见 `mixins/organization-search.js`,option 里该列加 `searchslot: true`)。
|
||||
- 单元格空值统一 `-`:列级 `formatter: (row, value) => ...`;金额 `Number(v||0).toFixed(2)`;状态/链接用 `slot: true` + `#prop` 插槽。
|
||||
- 操作列用 `#menu` 插槽(`menuWidth: 320`),`addBtn/viewBtn/delBtn/editBtn: false` 关掉 avue 自带按钮。
|
||||
|
||||
## 地址/行政区划展示(全站既有规则)
|
||||
「省/市/区县」都要空格分段,但**省与自治区不重复展示**:`上海市浦东新区`→`上海市 浦东新区`,`广西壮族自治区南宁市邕宁区`→`南宁市 邕宁区`(同 `formatRoadLocation` / `formatRouteCityDistrict` / 总单列表 `formatRoadAddress` 一致)。
|
||||
- 统一入口:`src/utils/region-address.js` 的 `formatRegionAddress(value)`(按后缀切分行政区划,`州+市`、`县+区` 连写合并;**只有整串都是行政区划**才重排,站点名「南宁站/广州南站」与含门牌的详细地址原样返回)。v-for 列表里用它做展示时,直接把函数挂进 `methods` 用 ES6 简写(`formatRegionAddress,`)。
|
||||
- ⚠️ 路线节点的名称字段来自后端 `routeJson`:`routes[i].departureName` = 第 i 段**到货地/途经地**(不是本段发货地),末段 = 最终收货地;`master.departureName/arrivalName` 才是总发货/总收货。总单调度/详情都按「上一个节点的 departureName」拼分段起点。
|
||||
|
||||
## 样式硬规则
|
||||
- 底栏 `flex; justify-content:flex-end`,**不写 gap**(靠 EP 默认 `.el-button+.el-button{margin-left:12px}`);浮动底栏必须 `position:fixed`(祖先 overflow:hidden 使 sticky 失效)+ `:global(.avue--collapse .x){left:60px}`、`:global(.avue-layout--horizontal .x){left:0}`,`:global()` 要包整个选择器。
|
||||
- 按钮层级:次要=无 type;中间步骤=`primary plain`;主操作=`primary`(禁绿、禁两个蓝实心)。顺序 `[辅助][取消][保存草稿][提交]`。
|
||||
@@ -33,3 +63,9 @@
|
||||
- `business-crud-page.vue`:option 经 `cloneOption` 克隆,独立表单页走 `PageAvueForm`。
|
||||
- 自检:`curl "localhost:2889/src/xxx.vue"` 与 `"...?vue&type=style&index=0&scoped=true&lang.scss"`(200 / 500)。`vite build` 在 `facelogin.vue` 被沙箱中断,不能作唯一校验。dev `VITE_APP_API=/api` 代理 `172.16.203.228:8000`。
|
||||
- 导出:前端 `exportColumns` 后端未用,以 `XxxExportExcel.java` 为准;BladeX `BeanUtil` 类型不兼容静默跳过(`Date` → `LocalDateTime` 丢值,用 `DateUtil.fromDate`)。
|
||||
|
||||
## Element Plus 图标两种用法的机制差异(易误判)
|
||||
`main.js` 里 `for (...ElementPlusIconsVue) app.component(key, component)` 全局注册了全部图标,因此模板里可以写标签形式 `<Location />`(靠全局注册解析)。
|
||||
但 `:icon="OfficeBuilding"` 是**表达式**,编译成 `_ctx.OfficeBuilding`,只会从 data / props / computed / setup 返回值里取 —— **组件对象必须放进 `data()`**;放进 `components: {}` 注册里模板取不到,会静默渲染不出图标(不报错,只是空白)。
|
||||
项目既有惯例:需要 `:icon` 的图标一律 `import` 后在 `data()` 里 `return { Xxx }`(transport-plan-page、waybill-manage-page、business-crud-page 都是这么写的)。
|
||||
注:标签形式(如 `<Location />`)不依赖 data,放不放 data 都能显示;仅 `:icon` 必须放 data。
|
||||
|
||||
@@ -84,6 +84,10 @@ export default {
|
||||
columnSettingVisible: false,
|
||||
};
|
||||
},
|
||||
deactivated() {
|
||||
// keep-alive 缓存页面时关闭列设置弹窗,避免 Teleport 到 body 的弹窗切页后残留
|
||||
this.columnSettingVisible = false;
|
||||
},
|
||||
methods: {
|
||||
toggleTableSize() {
|
||||
const index = TABLE_SIZE_OPTIONS.indexOf(this.tableSize);
|
||||
|
||||
@@ -1,20 +1,165 @@
|
||||
export const paymentApplicationTableColumns = [
|
||||
{ prop: 'paymentNo', label: '单据号', minWidth: 140, link: true },
|
||||
{ prop: 'paymentTypeName', label: '付款类型', minWidth: 110 },
|
||||
{ prop: 'projectName', label: '所属项目', minWidth: 140 },
|
||||
{ prop: 'deptName', label: '所属组织', minWidth: 120 },
|
||||
{ prop: 'contractNo', label: '合同编号', minWidth: 130 },
|
||||
{ prop: 'contractName', label: '合同名称', minWidth: 140 },
|
||||
{ prop: 'payerName', label: '付款方', minWidth: 130 },
|
||||
{ prop: 'payeeName', label: '收款方', minWidth: 130 },
|
||||
{ prop: 'appliedAmount', label: '申请付款金额', minWidth: 140, money: true },
|
||||
{ prop: 'paidAmount', label: '已付款金额', minWidth: 130, money: true },
|
||||
{ prop: 'matchedInvoiceAmount', label: '匹配发票金额', minWidth: 130, money: true },
|
||||
{ prop: 'applicantName', label: '申请人', minWidth: 100 },
|
||||
{ prop: 'applyDate', label: '申请日期', minWidth: 120 },
|
||||
{ prop: 'approvalStatusName', label: '审核状态', minWidth: 110, status: true },
|
||||
{ prop: 'currentNode', label: '当前节点', minWidth: 120 },
|
||||
{ prop: 'currentProcessor', label: '当前处理人', minWidth: 120 },
|
||||
{ prop: 'kingdeeBillNo', label: '金蝶单据号', minWidth: 130 },
|
||||
{ prop: 'kingdeeStatusName', label: '金蝶单据状态', minWidth: 130 },
|
||||
];
|
||||
/**
|
||||
* 付款申请列表(avue-crud)配置
|
||||
* ------------------------------------------------------------------
|
||||
* 列表页与其它模块统一使用 avue-crud,头部 4 个按钮(刷新 / 列显隐 / 搜索显隐 /
|
||||
* 表格卡片切换)由 avue-crud 自带,不做二次封装。
|
||||
*
|
||||
* 搜索项与表格列 label 不一致的(如表格列「收款方」/ 搜索项「客户名称」),
|
||||
* 单独定义一个 hide 的搜索列,并用 searchProp 映射到后端字段。
|
||||
*
|
||||
* ⚠️ avue 的 searchOrder 为降序排序,值越大越靠前(见 header-search2.js:
|
||||
* `list.sort((a, b) => (b.searchOrder || 0) - (a.searchOrder || 0))`)。
|
||||
*/
|
||||
|
||||
const textFormatter = (row, value) =>
|
||||
value === null || value === undefined || value === '' ? '-' : value;
|
||||
|
||||
const moneyFormatter = (row, value) => Number(value || 0).toFixed(2);
|
||||
|
||||
// 仅用于搜索、不在表格中出现的列
|
||||
const searchOnlyColumn = ({ label, prop, searchOrder, searchProp, dicData }) => {
|
||||
const column = {
|
||||
label,
|
||||
prop,
|
||||
search: true,
|
||||
searchOrder,
|
||||
searchPlaceholder: '请输入',
|
||||
hide: true,
|
||||
showColumn: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
};
|
||||
if (searchProp) column.searchProp = searchProp;
|
||||
if (dicData) {
|
||||
column.type = 'select';
|
||||
column.searchPlaceholder = '请选择';
|
||||
column.dicData = dicData;
|
||||
}
|
||||
return column;
|
||||
};
|
||||
|
||||
export const paymentApplicationOption = ({
|
||||
paymentTypeOptions = [],
|
||||
approvalStatusOptions = [],
|
||||
kingdeeStatusOptions = [],
|
||||
} = {}) => ({
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchBtnText: '查询',
|
||||
emptyBtnText: '重置',
|
||||
searchShow: true,
|
||||
searchIcon: true,
|
||||
searchLabelWidth: 88,
|
||||
searchMenuSpan: 24,
|
||||
searchIndex: 4,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
indexWidth: 70,
|
||||
indexFixed: 'left',
|
||||
selection: true,
|
||||
selectionWidth: 52,
|
||||
selectionFixed: 'left',
|
||||
addBtn: false,
|
||||
viewBtn: false,
|
||||
delBtn: false,
|
||||
editBtn: false,
|
||||
copyBtn: false,
|
||||
menuWidth: 320,
|
||||
menuFixed: 'right',
|
||||
dialogClickModal: false,
|
||||
column: [
|
||||
// ---------- 搜索项(前 4 项默认展示,其余折叠;searchOrder 越大越靠前) ----------
|
||||
{
|
||||
label: '单据号',
|
||||
prop: 'paymentNo',
|
||||
slot: true,
|
||||
search: true,
|
||||
searchOrder: 9,
|
||||
searchPlaceholder: '请输入',
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
label: '日期',
|
||||
prop: 'applyDateRange',
|
||||
type: 'daterange',
|
||||
searchType: 'daterange',
|
||||
search: true,
|
||||
searchOrder: 8,
|
||||
hide: true,
|
||||
showColumn: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
viewDisplay: false,
|
||||
},
|
||||
searchOnlyColumn({
|
||||
label: '客户名称',
|
||||
prop: 'payeeNameSearch',
|
||||
searchOrder: 7,
|
||||
searchProp: 'payeeName',
|
||||
}),
|
||||
searchOnlyColumn({
|
||||
label: '项目名称',
|
||||
prop: 'projectNameSearch',
|
||||
searchOrder: 6,
|
||||
searchProp: 'projectName',
|
||||
}),
|
||||
searchOnlyColumn({
|
||||
label: '关联结算单',
|
||||
prop: 'settlementNo',
|
||||
searchOrder: 4,
|
||||
}),
|
||||
searchOnlyColumn({
|
||||
label: '付款类型',
|
||||
prop: 'paymentType',
|
||||
searchOrder: 3,
|
||||
dicData: paymentTypeOptions,
|
||||
}),
|
||||
searchOnlyColumn({
|
||||
label: '审核状态',
|
||||
prop: 'approvalStatus',
|
||||
searchOrder: 2,
|
||||
dicData: approvalStatusOptions,
|
||||
}),
|
||||
searchOnlyColumn({
|
||||
label: '金蝶单据状态',
|
||||
prop: 'kingdeeStatus',
|
||||
searchOrder: 1,
|
||||
dicData: kingdeeStatusOptions,
|
||||
}),
|
||||
// ---------- 表格列 ----------
|
||||
{ label: '付款类型', prop: 'paymentTypeName', minWidth: 110, formatter: textFormatter },
|
||||
{ label: '所属项目', prop: 'projectName', minWidth: 140, formatter: textFormatter },
|
||||
{
|
||||
label: '所属组织',
|
||||
prop: 'deptName',
|
||||
search: true,
|
||||
searchOrder: 5,
|
||||
searchslot: true,
|
||||
minWidth: 120,
|
||||
formatter: textFormatter,
|
||||
},
|
||||
{ label: '合同编号', prop: 'contractNo', minWidth: 130, formatter: textFormatter },
|
||||
{ label: '合同名称', prop: 'contractName', minWidth: 140, formatter: textFormatter },
|
||||
{ label: '付款方', prop: 'payerName', minWidth: 130, formatter: textFormatter },
|
||||
{ label: '收款方', prop: 'payeeName', minWidth: 130, formatter: textFormatter },
|
||||
{ label: '申请付款金额', prop: 'appliedAmount', minWidth: 140, formatter: moneyFormatter },
|
||||
{ label: '已付款金额', prop: 'paidAmount', minWidth: 130, formatter: moneyFormatter },
|
||||
{
|
||||
label: '匹配发票金额',
|
||||
prop: 'matchedInvoiceAmount',
|
||||
minWidth: 130,
|
||||
formatter: moneyFormatter,
|
||||
},
|
||||
{ label: '申请人', prop: 'applicantName', minWidth: 100, formatter: textFormatter },
|
||||
{ label: '申请日期', prop: 'applyDate', minWidth: 120, formatter: textFormatter },
|
||||
{ label: '审核状态', prop: 'approvalStatusName', slot: true, minWidth: 110 },
|
||||
{ label: '当前节点', prop: 'currentNode', minWidth: 120, formatter: textFormatter },
|
||||
{ label: '当前处理人', prop: 'currentProcessor', minWidth: 120, formatter: textFormatter },
|
||||
{ label: '金蝶单据号', prop: 'kingdeeBillNo', minWidth: 130, formatter: textFormatter },
|
||||
{ label: '金蝶单据状态', prop: 'kingdeeStatusName', minWidth: 130, formatter: textFormatter },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -367,7 +367,7 @@
|
||||
|
||||
// 4) 弹窗内表单项上下间距:预留绝对定位校验提示(约 14~18px)的可视空间
|
||||
.el-dialog .el-form-item {
|
||||
margin-bottom: 24px;
|
||||
//margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// 校验提示浮在控件下方,提高层级避免被下一行输入框背景遮挡
|
||||
|
||||
@@ -1721,7 +1721,7 @@ export default {
|
||||
.el-form-item--small.el-form-item,
|
||||
.el-form-item--large.el-form-item,
|
||||
.el-form-item--medium.el-form-item {
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -787,6 +787,6 @@ export default {
|
||||
margin-bottom: 12px !important;
|
||||
}
|
||||
.el-form-item{
|
||||
margin-bottom: 24px !important;
|
||||
margin-bottom: 22px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2993,9 +2993,10 @@
|
||||
<el-table-column prop="changeUser" label="变更人" min-width="120" />
|
||||
<el-table-column prop="content" label="变更内容" min-width="360">
|
||||
<template #default="{ row }">
|
||||
<div class="business-crud-page__route-change-record-content">
|
||||
{{ row.content || '-' }}
|
||||
</div>
|
||||
<div
|
||||
class="business-crud-page__route-change-record-content"
|
||||
v-text="formatRouteChangeContent(row.content)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip />
|
||||
@@ -5282,6 +5283,7 @@ import { formatContractOptionLabel } from '@/utils/contract';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
||||
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
||||
import { formatRouteChangeContent } from '@/utils/route-change';
|
||||
import { applyTableMenuWidth } from '@/utils/table-menu';
|
||||
import { downloadFileByUrl, downloadXls } from '@/utils/util';
|
||||
import { isMobile } from '@/utils/validate';
|
||||
@@ -6628,6 +6630,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formatContractOptionLabel,
|
||||
formatRouteChangeContent,
|
||||
initStandaloneFormPage() {
|
||||
if (!this.isStandaloneFormPage) return;
|
||||
const mode = this.$route.query.mode === 'edit' ? 'edit' : 'add';
|
||||
@@ -15898,6 +15901,9 @@ export default {
|
||||
|
||||
&__route-change-record-content {
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="route-map"><template v-for="(route, index) in segments" :key="route.segmentNo"><div class="route-map__node"><span :class="['route-badge', index ? 'middle' : 'start']">{{ index ? '经' : '起' }}</span><strong>{{ segmentLocationName(route, 'departure') }}</strong><small>{{ route.departureAddress || '-' }}</small><small class="route-map__progress">{{ index ? `已到达 ${quantity(segments[index - 1].arrivedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(segments[index - 1])}` : `已调度 ${quantity(route.dispatchedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(route)}` }}</small><small v-if="index" class="route-map__progress">已调度 {{ quantity(route.dispatchedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div><div class="route-map__line"></div><div v-if="index === segments.length - 1" class="route-map__node"><span class="route-badge end">终</span><strong>{{ segmentLocationName(route, 'arrival') }}</strong><small>{{ route.arrivalAddress || '-' }}</small><small class="route-map__progress">已到达 {{ quantity(route.arrivedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div></template></div>
|
||||
<div class="route-map"><template v-for="(route, index) in segments" :key="route.segmentNo"><div class="route-map__node"><span :class="['route-badge', index ? 'middle' : 'start']">{{ index ? '经' : '起' }}</span><strong>{{ segmentLocationName(route, 'departure') }}</strong><small>{{ formatRegionAddress(route.departureAddress) || '-' }}</small><small class="route-map__progress">{{ index ? `已到达 ${quantity(segments[index - 1].arrivedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(segments[index - 1])}` : `已调度 ${quantity(route.dispatchedQuantity)}/${quantity(master.totalQuantity)} ${plannedUnit(route)}` }}</small><small v-if="index" class="route-map__progress">已调度 {{ quantity(route.dispatchedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div><div class="route-map__line"></div><div v-if="index === segments.length - 1" class="route-map__node"><span class="route-badge end">终</span><strong>{{ segmentLocationName(route, 'arrival') }}</strong><small>{{ formatRegionAddress(route.arrivalAddress) || '-' }}</small><small class="route-map__progress">已到达 {{ quantity(route.arrivedQuantity) }}/{{ quantity(master.totalQuantity) }} {{ plannedUnit(route) }}</small></div></template></div>
|
||||
</section>
|
||||
|
||||
<el-dialog v-model="documentPreviewVisible" :title="previewFile.name || '附件预览'" append-to-body destroy-on-close width="90%" top="4vh">
|
||||
@@ -110,6 +110,7 @@ import { getList as getCustomerArchiveList } from '@/api/vehicle/customer-archiv
|
||||
import { CaretBottom, CaretTop } from '@element-plus/icons-vue';
|
||||
import { ElImageViewer } from 'element-plus';
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
import { formatRegionAddress } from '@/utils/region-address';
|
||||
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';
|
||||
@@ -164,6 +165,7 @@ export default {
|
||||
} finally { this.loading = false; }
|
||||
},
|
||||
methods: {
|
||||
formatRegionAddress,
|
||||
quantity(value) { const number = Number(value || 0); return Number.isInteger(number) ? number : number.toFixed(3).replace(/\.?0+$/, ''); },
|
||||
segmentNumber(route, index) { return String(route.segmentNo || '').replace(/^段/, '') || index + 1; },
|
||||
isSegmentExpanded(segmentNo) { return Boolean(this.expandedSegments[segmentNo]); },
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
<div class="route-overview__node">
|
||||
<span :class="['route-badge', index === 0 ? 'start' : 'middle']">{{ index === 0 ? '起' : '经' }}</span>
|
||||
<el-tooltip :content="route.departureName || '-'" placement="top" :show-after="120">
|
||||
<strong>{{ route.departureName || '-' }}</strong>
|
||||
<strong>{{ dispatchLocationName(route, 'departure') }}</strong>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="route.departureAddress || '-'" placement="top" :show-after="120">
|
||||
<small>{{ route.departureAddress || '-' }}</small>
|
||||
<small>{{ formatRegionAddress(route.departureAddress) || '-' }}</small>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="contactText(route.departureContact, route.departurePhone)" placement="top" :show-after="120">
|
||||
<small>{{ contactText(route.departureContact, route.departurePhone) }}</small>
|
||||
@@ -34,10 +34,10 @@
|
||||
<div v-if="index === routes.length - 1" class="route-overview__node">
|
||||
<span class="route-badge end">终</span>
|
||||
<el-tooltip :content="route.arrivalName || '-'" placement="top" :show-after="120">
|
||||
<strong>{{ route.arrivalName || '-' }}</strong>
|
||||
<strong>{{ dispatchLocationName(route, 'arrival') }}</strong>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="route.arrivalAddress || '-'" placement="top" :show-after="120">
|
||||
<small>{{ route.arrivalAddress || '-' }}</small>
|
||||
<small>{{ formatRegionAddress(route.arrivalAddress) || '-' }}</small>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="contactText(route.arrivalContact, route.arrivalPhone)" placement="top" :show-after="120">
|
||||
<small>{{ contactText(route.arrivalContact, route.arrivalPhone) }}</small>
|
||||
@@ -324,6 +324,7 @@ import {
|
||||
resolvePriceUnitByQuantityUnit,
|
||||
} from '@/utils/currency';
|
||||
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
||||
import { formatRegionAddress } from '@/utils/region-address';
|
||||
import { isMobile } from '@/utils/validate';
|
||||
|
||||
const unwrapRecords = res => {
|
||||
@@ -851,7 +852,12 @@ export default {
|
||||
const mileage = Number(value);
|
||||
return Number.isFinite(mileage) && mileage >= 0 ? String(Math.trunc(mileage)) : '';
|
||||
},
|
||||
addressText(name, address) { return [name, address].filter(Boolean).join(' / ') || '-'; },
|
||||
formatRegionAddress,
|
||||
addressText(name, address) {
|
||||
// 名称与详细地址都要按「市 区县」展示;两者格式化后相同时只展示一次
|
||||
const values = [this.formatRegionAddress(name), this.formatRegionAddress(address)].filter(Boolean);
|
||||
return [...new Set(values)].join(' / ') || '-';
|
||||
},
|
||||
contactText(name, phone) { return [name, phone].filter(Boolean).join(' - ') || '-'; },
|
||||
dateStartLabel(route) { return route.documentType === '计划单' ? '计划开始日期' : '预计发货日期'; },
|
||||
dateEndLabel(route) { return route.documentType === '计划单' ? '计划结束日期' : '预计完成日期'; },
|
||||
|
||||
@@ -153,11 +153,24 @@
|
||||
@click="handleTransportSecondaryAddressInputClick('departure')"
|
||||
>
|
||||
<template #suffix>
|
||||
<el-icon @click.stop="openTransportMapDialog('departure')">
|
||||
<el-icon
|
||||
class="shipping-template-page__map-suffix"
|
||||
@click.stop="openTransportMapDialog('departure')"
|
||||
>
|
||||
<Location />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
class="shipping-template-page__address-pick-btn"
|
||||
type="primary"
|
||||
:icon="OfficeBuilding"
|
||||
link
|
||||
:disabled="transportAddressSelectDisabled"
|
||||
@click="openTransportAddressPicker('departure')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<span>联系人</span>
|
||||
<el-input
|
||||
v-model="form.departureContact"
|
||||
@@ -166,16 +179,6 @@
|
||||
/>
|
||||
<span>联系方式</span>
|
||||
<el-input v-model="form.departurePhone" placeholder="请输入" :disabled="dialogReadonly" />
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
:disabled="transportAddressSelectDisabled"
|
||||
@click="openTransportAddressPicker('departure')"
|
||||
>
|
||||
选择
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -197,25 +200,28 @@
|
||||
@click="handleTransportSecondaryAddressInputClick('arrival')"
|
||||
>
|
||||
<template #suffix>
|
||||
<el-icon @click.stop="openTransportMapDialog('arrival')">
|
||||
<el-icon
|
||||
class="shipping-template-page__map-suffix"
|
||||
@click.stop="openTransportMapDialog('arrival')"
|
||||
>
|
||||
<Location />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
class="shipping-template-page__address-pick-btn"
|
||||
type="primary"
|
||||
:icon="OfficeBuilding"
|
||||
link
|
||||
:disabled="transportAddressSelectDisabled"
|
||||
@click="openTransportAddressPicker('arrival')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<span>联系人</span>
|
||||
<el-input v-model="form.arrivalContact" placeholder="请输入" :disabled="dialogReadonly" />
|
||||
<span>联系方式</span>
|
||||
<el-input v-model="form.arrivalPhone" placeholder="请输入" :disabled="dialogReadonly" />
|
||||
<el-tooltip content="选择常用地址" placement="top">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
:disabled="transportAddressSelectDisabled"
|
||||
@click="openTransportAddressPicker('arrival')"
|
||||
>
|
||||
选择
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1122,7 +1128,7 @@ import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
||||
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
||||
import { downloadFileByUrl, downloadXls } from '@/utils/util';
|
||||
import { isMobile } from '@/utils/validate';
|
||||
import { Location } from '@element-plus/icons-vue';
|
||||
import { Location, OfficeBuilding } from '@element-plus/icons-vue';
|
||||
import { ElImageViewer } from 'element-plus';
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
import {
|
||||
@@ -1273,6 +1279,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
Location,
|
||||
OfficeBuilding,
|
||||
form: {},
|
||||
query: {},
|
||||
loading: true,
|
||||
@@ -3421,10 +3428,25 @@ export default {
|
||||
.shipping-template-page__route-row {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
minmax(160px, 1fr) minmax(220px, 2fr) auto minmax(140px, 1fr) auto minmax(160px, 1fr)
|
||||
auto;
|
||||
minmax(160px, 1fr) minmax(220px, 2fr) 40px auto minmax(140px, 1fr) auto
|
||||
minmax(160px, 1fr);
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
.shipping-template-page__address-pick-btn {
|
||||
:deep(.el-icon) {
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.shipping-template-page__map-suffix {
|
||||
cursor: pointer;
|
||||
color: #909399;
|
||||
font-size: 18px;
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
.shipping-template-page__address-map-input {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="voucher-folder-page voucher-folder-page--embedded">
|
||||
<section class="voucher-folder-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="160px">
|
||||
<el-form :model="query" label-position="right">
|
||||
<div class="voucher-folder-page__search-grid">
|
||||
<el-form-item label="车牌号">
|
||||
<el-input v-model="query.plateNo" clearable placeholder="请输入" />
|
||||
@@ -196,7 +196,7 @@ watch(
|
||||
}
|
||||
&__search-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 360px 360px 1fr;
|
||||
grid-template-columns: 220px 220px 1fr;
|
||||
gap: 8px 24px;
|
||||
}
|
||||
&__search-actions {
|
||||
|
||||
@@ -1334,7 +1334,7 @@
|
||||
:disabled="dialogReadonly"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="型号" required>
|
||||
<el-form-item label="型号">
|
||||
<el-input
|
||||
v-model="form.model"
|
||||
placeholder="选择货物自动回填"
|
||||
@@ -3022,9 +3022,10 @@
|
||||
<el-table-column prop="changeUser" label="变更人" min-width="120" />
|
||||
<el-table-column prop="content" label="变更内容" min-width="360">
|
||||
<template #default="{ row }">
|
||||
<div class="waybill-manage-page__route-change-record-content">
|
||||
{{ row.content || '-' }}
|
||||
</div>
|
||||
<div
|
||||
class="waybill-manage-page__route-change-record-content"
|
||||
v-text="formatRouteChangeContent(row.content)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip />
|
||||
@@ -3666,6 +3667,7 @@ import { wgs84ToGcj02 } from '@/utils/coordinate';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
||||
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
|
||||
import { formatRouteChangeContent } from '@/utils/route-change';
|
||||
import { applyTableMenuWidth } from '@/utils/table-menu';
|
||||
import { downloadFileByUrl, downloadXls } from '@/utils/util';
|
||||
import { isMobile } from '@/utils/validate';
|
||||
@@ -4753,6 +4755,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formatContractOptionLabel,
|
||||
formatRouteChangeContent,
|
||||
// 页面被 keep-alive 缓存/卸载时调用,关闭本页所有 append-to-body 的弹窗,
|
||||
// 避免 Teleport 出去的 DOM 残留在 body 上盖住后续页面(详见 data 里的说明)。
|
||||
closeInnerDialogs() {
|
||||
@@ -5218,10 +5221,11 @@ export default {
|
||||
return true;
|
||||
},
|
||||
showDetailButton(row) {
|
||||
// 草稿与其它状态统一走「详情」(独立详情页 / 详情弹窗),
|
||||
// 不再对草稿单独降级为 avue 的「查看」表单弹窗,避免同一列出现两种弹窗形态。
|
||||
if (!this.config.detailButton || !this.hasPermission(`${this.config.permission}_view`))
|
||||
return false;
|
||||
const status = this.statusValue(row);
|
||||
return status !== 'draft';
|
||||
return true;
|
||||
},
|
||||
formatDetailValue(row, prop) {
|
||||
if (!row) return '-';
|
||||
@@ -11844,6 +11848,9 @@ export default {
|
||||
|
||||
&__route-change-record-content {
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
&__common-address-toolbar {
|
||||
|
||||
@@ -754,7 +754,7 @@ export default {
|
||||
.contract-basic-section__change-type { grid-column: 1 / -1; }
|
||||
.contract-basic-section__remark {
|
||||
width: 100%;
|
||||
margin-bottom: 24px !important;
|
||||
margin-bottom: 23px !important;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
@@ -763,7 +763,7 @@ export default {
|
||||
.contract-basic-section__date-range { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; width: 360px; max-width: 100%; }
|
||||
.contract-basic-section__date-range span { color: #606266; }
|
||||
.contract-basic-section__date-range :deep(.el-date-editor) { width: auto; min-width: 0; }
|
||||
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 24px; }
|
||||
.contract-basic-section :deep(.el-form-item) { align-items: center; }
|
||||
.contract-basic-section :deep(.el-form-item__label) { flex: 0 0 96px !important; width: 96px !important; height: auto; padding-right: 12px; white-space: normal; word-break: break-all; line-height: 18px; }
|
||||
.contract-basic-section :deep(.el-form-item__content) { min-width: 0; }
|
||||
.contract-basic-section :deep(.el-input),
|
||||
|
||||
@@ -613,8 +613,8 @@
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
maxlength="200"
|
||||
:rows="4"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
placeholder="请输入其他事项说明"
|
||||
/>
|
||||
|
||||
@@ -1685,9 +1685,7 @@
|
||||
label="变更人"
|
||||
min-width="120" /><el-table-column prop="content" label="变更内容" min-width="360"
|
||||
><template #default="{ row }"
|
||||
><div class="loading-route-change-dialog__record-content">
|
||||
{{ row.content || '-' }}
|
||||
</div></template
|
||||
><div class="loading-route-change-dialog__record-content">{{ formatRouteChangeContent(row.content) }}</div></template
|
||||
></el-table-column
|
||||
><el-table-column
|
||||
prop="remark"
|
||||
@@ -1800,6 +1798,7 @@ import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { isMobile } from '@/utils/validate';
|
||||
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
|
||||
import { formatRouteChangeContent } from '@/utils/route-change';
|
||||
|
||||
const defaultTransportType = '';
|
||||
const defaultCandidateTransportType = '';
|
||||
@@ -2278,6 +2277,7 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatRouteChangeContent,
|
||||
formatTaskCarrierContractLabel(item = {}) {
|
||||
const carrierName = item.carrierName || item.partyB || '';
|
||||
const contractLabel = formatContractOptionLabel(item);
|
||||
@@ -5129,8 +5129,9 @@ export default {
|
||||
gap: 4px;
|
||||
}
|
||||
.loading-route-change-dialog__record-content {
|
||||
white-space: normal;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<basic-container class="bill-ledger-page">
|
||||
<bill-ledger-search
|
||||
v-if="searchVisible"
|
||||
:query="query"
|
||||
:loading="loading"
|
||||
@search="handleSearch"
|
||||
@@ -20,10 +21,12 @@
|
||||
:rows="rows"
|
||||
:loading="loading"
|
||||
:page="page"
|
||||
v-model:search-visible="searchVisible"
|
||||
@add="openCreate"
|
||||
@view="openView"
|
||||
@edit="openEdit"
|
||||
@delete="handleDelete"
|
||||
@refresh="loadData"
|
||||
@page-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
@@ -124,6 +127,7 @@ export default {
|
||||
return {
|
||||
query: emptyQuery(),
|
||||
counts: { all: 0, within30: 0, within90: 0, over90: 0 },
|
||||
searchVisible: true,
|
||||
rows: [],
|
||||
loading: false,
|
||||
page: { current: 1, size: 10, total: 0 },
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<basic-container class="bill-payment-page">
|
||||
<bill-payment-search
|
||||
v-if="searchVisible"
|
||||
:query="query"
|
||||
:loading="loading"
|
||||
@search="handleSearch"
|
||||
@@ -11,6 +12,7 @@
|
||||
:loading="loading"
|
||||
:page="page"
|
||||
:mk-enabled="mkEnabled"
|
||||
v-model:search-visible="searchVisible"
|
||||
@add="openCreate"
|
||||
@view="openView"
|
||||
@edit="openEdit"
|
||||
@@ -20,6 +22,7 @@
|
||||
@approve="handleApprove"
|
||||
@return="handleReturn"
|
||||
@void="handleVoid"
|
||||
@refresh="loadTable"
|
||||
@page-change="handlePageChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
@@ -47,6 +50,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
query: emptyQuery(),
|
||||
searchVisible: true,
|
||||
rows: [],
|
||||
loading: false,
|
||||
page: { current: 1, size: 10, total: 0 },
|
||||
|
||||
@@ -4,11 +4,19 @@
|
||||
<el-button v-if="hasPermission('bill_ledger_add')" type="primary" @click="$emit('add')">
|
||||
新增
|
||||
</el-button>
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
:search-visible="searchVisible"
|
||||
@update:search-visible="$emit('update:searchVisible', $event)"
|
||||
@refresh="$emit('refresh')"
|
||||
/>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="rows" border>
|
||||
<el-table v-loading="loading" :data="rows" :size="tableSize" border>
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -60,20 +68,30 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { billLedgerTableColumns } from '@/option/payment/billLedger';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
|
||||
export default {
|
||||
name: 'BillLedgerTable',
|
||||
components: { TableHeaderTools },
|
||||
props: {
|
||||
rows: { type: Array, default: () => [] },
|
||||
loading: { type: Boolean, default: false },
|
||||
page: { type: Object, required: true },
|
||||
searchVisible: { type: Boolean, default: true },
|
||||
},
|
||||
emits: ['add', 'view', 'edit', 'delete', 'page-change', 'size-change'],
|
||||
emits: ['add', 'view', 'edit', 'delete', 'page-change', 'size-change', 'refresh', 'update:searchVisible'],
|
||||
data() {
|
||||
return { columns: billLedgerTableColumns };
|
||||
return {
|
||||
columns: billLedgerTableColumns,
|
||||
visibleColumnKeys: billLedgerTableColumns.map(column => column.prop),
|
||||
tableSize: 'default',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
@@ -96,7 +114,7 @@ export default {
|
||||
.bill-ledger-table__toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.bill-ledger-table__links {
|
||||
|
||||
@@ -4,11 +4,19 @@
|
||||
<el-button v-if="hasPermission('bill_payment_add')" type="primary" @click="$emit('add')">
|
||||
新增
|
||||
</el-button>
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
:search-visible="searchVisible"
|
||||
@update:search-visible="$emit('update:searchVisible', $event)"
|
||||
@refresh="$emit('refresh')"
|
||||
/>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="rows" border>
|
||||
<el-table v-loading="loading" :data="rows" :size="tableSize" border>
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -115,15 +123,18 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { billPaymentTableColumns } from '@/option/payment/billPayment';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import { isAdministrator } from '@/utils/auth';
|
||||
|
||||
export default {
|
||||
name: 'BillPaymentTable',
|
||||
components: { TableHeaderTools },
|
||||
props: {
|
||||
rows: { type: Array, default: () => [] },
|
||||
loading: { type: Boolean, default: false },
|
||||
page: { type: Object, required: true },
|
||||
mkEnabled: { type: Boolean, default: false },
|
||||
searchVisible: { type: Boolean, default: true },
|
||||
},
|
||||
emits: [
|
||||
'add',
|
||||
@@ -137,12 +148,21 @@ export default {
|
||||
'void',
|
||||
'page-change',
|
||||
'size-change',
|
||||
'refresh',
|
||||
'update:searchVisible',
|
||||
],
|
||||
data() {
|
||||
return { columns: billPaymentTableColumns };
|
||||
return {
|
||||
columns: billPaymentTableColumns,
|
||||
visibleColumnKeys: billPaymentTableColumns.map(column => column.prop),
|
||||
tableSize: 'default',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission', 'userInfo']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
isAdmin() {
|
||||
return isAdministrator(this.userInfo);
|
||||
},
|
||||
@@ -173,7 +193,8 @@ export default {
|
||||
}
|
||||
.bill-payment-table__toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.bill-payment-table__links {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container class="invoice-page">
|
||||
<section class="invoice-page__search">
|
||||
<section v-if="searchVisible" class="invoice-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="88px" @submit.prevent>
|
||||
<div class="invoice-page__search-grid">
|
||||
<el-form-item label="单据号">
|
||||
@@ -78,18 +78,26 @@
|
||||
>导出</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="invoice-page__toolbar-right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button text :icon="Refresh" @click="loadTable" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
v-model:search-visible="searchVisible"
|
||||
@refresh="loadTable"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
:size="tableSize"
|
||||
border
|
||||
@selection-change="selection = $event"
|
||||
>
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -209,12 +217,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import * as XLSX from 'xlsx';
|
||||
import * as api from '@/api/payment/invoiceApplication';
|
||||
import * as formalSettlementApi from '@/api/settlement/formalSettlement';
|
||||
import { invoiceApplicationTableColumns } from '@/option/payment/invoiceApplication';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import organizationSearch from '@/mixins/organization-search';
|
||||
import { getMKApprovalUrl } from '@/api/system/business-process';
|
||||
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
|
||||
@@ -230,17 +239,20 @@ const emptyQuery = () => ({
|
||||
|
||||
export default {
|
||||
name: 'InvoiceApplication',
|
||||
components: { TableHeaderTools },
|
||||
mixins: [organizationSearch],
|
||||
data() {
|
||||
return {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
Refresh,
|
||||
query: emptyQuery(),
|
||||
searchExpanded: false,
|
||||
searchVisible: true,
|
||||
tableSize: 'default',
|
||||
approvalStatusOptions: api.approvalStatusOptions,
|
||||
kingdeeStatusOptions: api.kingdeeStatusOptions,
|
||||
columns: invoiceApplicationTableColumns,
|
||||
visibleColumnKeys: invoiceApplicationTableColumns.map(column => column.prop),
|
||||
rows: [],
|
||||
selection: [],
|
||||
loading: false,
|
||||
@@ -250,6 +262,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadOrganizationOptions();
|
||||
@@ -477,7 +492,6 @@ export default {
|
||||
padding: 12px 0;
|
||||
}
|
||||
.invoice-page__toolbar-left,
|
||||
.invoice-page__toolbar-right,
|
||||
.invoice-page__links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container class="receipt-page">
|
||||
<section class="receipt-page__search">
|
||||
<section v-if="searchVisible" class="receipt-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="88px" @submit.prevent>
|
||||
<div class="receipt-page__search-grid">
|
||||
<el-form-item label="发票号码">
|
||||
@@ -84,18 +84,26 @@
|
||||
>导出</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="receipt-page__toolbar-right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button text :icon="Refresh" @click="loadTable" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
v-model:search-visible="searchVisible"
|
||||
@refresh="loadTable"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
:size="tableSize"
|
||||
border
|
||||
@selection-change="selection = $event"
|
||||
>
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -202,11 +210,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import * as XLSX from 'xlsx';
|
||||
import * as api from '@/api/payment/invoiceReceipt';
|
||||
import { invoiceReceiptTableColumns } from '@/option/payment/invoiceReceipt';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import organizationSearch from '@/mixins/organization-search';
|
||||
import { getMKApprovalUrl } from '@/api/system/business-process';
|
||||
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
|
||||
@@ -223,17 +232,20 @@ const emptyQuery = () => ({
|
||||
|
||||
export default {
|
||||
name: 'InvoiceReceipt',
|
||||
components: { TableHeaderTools },
|
||||
mixins: [organizationSearch],
|
||||
data() {
|
||||
return {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
Refresh,
|
||||
query: emptyQuery(),
|
||||
searchExpanded: false,
|
||||
searchVisible: true,
|
||||
tableSize: 'default',
|
||||
approvalStatusOptions: api.approvalStatusOptions,
|
||||
kingdeeStatusOptions: api.kingdeeStatusOptions,
|
||||
columns: invoiceReceiptTableColumns,
|
||||
visibleColumnKeys: invoiceReceiptTableColumns.map(column => column.prop),
|
||||
rows: [],
|
||||
selection: [],
|
||||
loading: false,
|
||||
@@ -243,6 +255,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadOrganizationOptions();
|
||||
@@ -439,7 +454,6 @@ export default {
|
||||
padding: 12px 0;
|
||||
}
|
||||
.receipt-page__toolbar-left,
|
||||
.receipt-page__toolbar-right,
|
||||
.receipt-page__links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,278 +1,177 @@
|
||||
<template>
|
||||
<basic-container class="payment-page">
|
||||
<section class="payment-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="88px">
|
||||
<div class="payment-page__search-grid">
|
||||
<el-form-item label="单据号"
|
||||
><el-input v-model="query.paymentNo" clearable
|
||||
/></el-form-item>
|
||||
<el-form-item label="日期"
|
||||
><el-date-picker
|
||||
v-model="query.applyDateRange"
|
||||
type="daterange"
|
||||
value-format="YYYY-MM-DD"
|
||||
range-separator="~"
|
||||
start-placeholder="年/月/日"
|
||||
end-placeholder="年/月/日"
|
||||
/></el-form-item>
|
||||
<el-form-item label="客户名称"
|
||||
><el-input v-model="query.payeeName" clearable
|
||||
/></el-form-item>
|
||||
<el-form-item label="项目名称"
|
||||
><el-input v-model="query.projectName" clearable
|
||||
/></el-form-item>
|
||||
<template v-if="searchExpanded">
|
||||
<el-form-item label="所属组织"
|
||||
><el-cascader
|
||||
v-model="query.deptPath"
|
||||
:options="organizationTreeOptions"
|
||||
:props="organizationCascaderProps"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%"
|
||||
placeholder="请选择 所属组织"
|
||||
@change="val => { query.deptName = findOrgById(val)?.rawLabel || '' }"
|
||||
/></el-form-item>
|
||||
<el-form-item label="关联结算单"
|
||||
><el-input v-model="query.settlementNo" clearable
|
||||
/></el-form-item>
|
||||
<el-form-item label="付款类型"
|
||||
><el-select v-model="query.paymentType" clearable
|
||||
><el-option
|
||||
v-for="item in paymentTypeOptions"
|
||||
:key="item.value"
|
||||
v-bind="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="审核状态"
|
||||
><el-select v-model="query.approvalStatus" clearable
|
||||
><el-option
|
||||
v-for="item in approvalStatusOptions"
|
||||
:key="item.value"
|
||||
v-bind="item" /></el-select
|
||||
></el-form-item>
|
||||
<el-form-item label="金蝶单据状态"
|
||||
><el-select v-model="query.kingdeeStatus" clearable
|
||||
><el-option
|
||||
v-for="item in kingdeeStatusOptions"
|
||||
:key="item.value"
|
||||
v-bind="item" /></el-select
|
||||
></el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
<div class="payment-page__search-actions">
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="resetSearch">重置</el-button>
|
||||
<el-button text @click="searchExpanded = !searchExpanded"
|
||||
><el-icon><component :is="searchExpanded ? ArrowUp : ArrowDown" /></el-icon
|
||||
></el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</section>
|
||||
<section class="payment-page__table-panel">
|
||||
<div class="payment-page__toolbar">
|
||||
<div class="payment-page__toolbar-left">
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
@click="openCreate"
|
||||
>新增付款申请</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_sync')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="handleSync"
|
||||
>批量同步</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="openSettlementPayment"
|
||||
>申请付尾款</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="openProjectAdvance"
|
||||
>预付申请</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_export')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="handleExport"
|
||||
>导出</el-button
|
||||
>
|
||||
</div>
|
||||
<el-button text :icon="Refresh" @click="loadTable" />
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
<avue-crud
|
||||
ref="crud"
|
||||
:option="option"
|
||||
:table-loading="loading"
|
||||
:data="rows"
|
||||
v-model:page="page"
|
||||
@search-change="searchChange"
|
||||
@search-reset="searchReset"
|
||||
@selection-change="selectionChange"
|
||||
@current-change="currentChange"
|
||||
@size-change="sizeChange"
|
||||
@refresh-change="refreshChange"
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
@click="openCreate"
|
||||
>新增付款申请</el-button
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link v-if="column.link" type="primary" @click="openView(row)">{{
|
||||
row[column.prop]
|
||||
}}</el-link>
|
||||
<el-tag
|
||||
v-else-if="column.status"
|
||||
:type="statusType(row.approvalStatus)"
|
||||
class="status-text"
|
||||
>{{ row[column.prop] || '-' }}</el-tag
|
||||
>
|
||||
<span v-else-if="column.money">{{ formatMoney(row[column.prop]) }}</span>
|
||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="320" fixed="right" align="center">
|
||||
<template #default="{ row }"
|
||||
><div class="payment-page__links">
|
||||
<el-link
|
||||
v-if="hasPermission('payment_application_view')"
|
||||
type="primary"
|
||||
@click="openView(row)"
|
||||
>查看</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
hasPermission('payment_application_edit') &&
|
||||
['draft', 'returned'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="openEdit(row)"
|
||||
>编辑</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
hasPermission('payment_application_submit') &&
|
||||
['draft', 'returned'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="handleSubmit(row)"
|
||||
>提交</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
['reviewing', 'approved'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="handleMkAudit(row)"
|
||||
>流程</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
!mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
row.approvalStatus === 'reviewing'
|
||||
"
|
||||
type="primary"
|
||||
@click="handleApprove(row)"
|
||||
>通过</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
!mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
row.approvalStatus === 'reviewing'
|
||||
"
|
||||
type="danger"
|
||||
@click="handleReturn(row)"
|
||||
>驳回</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
hasPermission('payment_application_void') && row.approvalStatus === 'approved'
|
||||
"
|
||||
type="danger"
|
||||
@click="handleVoid(row)"
|
||||
>作废</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="hasPermission('payment_application_delete') && row.approvalStatus === 'draft'"
|
||||
type="danger"
|
||||
@click="handleDelete(row)"
|
||||
>删除</el-link
|
||||
>
|
||||
</div></template
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="payment-page__pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="page.current"
|
||||
v-model:page-size="page.size"
|
||||
:total="page.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="loadTable"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_sync')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="handleSync"
|
||||
>批量同步</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="openSettlementPayment"
|
||||
>申请付尾款</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_add')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="openProjectAdvance"
|
||||
>预付申请</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('payment_application_export')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="handleExport"
|
||||
>导出</el-button
|
||||
>
|
||||
</template>
|
||||
|
||||
<template #paymentNo="{ row }">
|
||||
<el-link type="primary" @click="openView(row)">{{ row.paymentNo }}</el-link>
|
||||
</template>
|
||||
|
||||
<template #approvalStatusName="{ row }">
|
||||
<el-tag :type="statusType(row.approvalStatus)" class="status-text">{{
|
||||
row.approvalStatusName || '-'
|
||||
}}</el-tag>
|
||||
</template>
|
||||
|
||||
<template #menu="{ row }">
|
||||
<el-link
|
||||
v-if="hasPermission('payment_application_view')"
|
||||
type="primary"
|
||||
@click="openView(row)"
|
||||
>查看</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
hasPermission('payment_application_edit') &&
|
||||
['draft', 'returned'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="openEdit(row)"
|
||||
>编辑</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
hasPermission('payment_application_submit') &&
|
||||
['draft', 'returned'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="handleSubmit(row)"
|
||||
>提交</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
['reviewing', 'approved'].includes(row.approvalStatus)
|
||||
"
|
||||
type="primary"
|
||||
@click="handleMkAudit(row)"
|
||||
>流程</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
!mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
row.approvalStatus === 'reviewing'
|
||||
"
|
||||
type="primary"
|
||||
@click="handleApprove(row)"
|
||||
>通过</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="
|
||||
!mkEnabled &&
|
||||
hasPermission('payment_application_approve') &&
|
||||
row.approvalStatus === 'reviewing'
|
||||
"
|
||||
type="danger"
|
||||
@click="handleReturn(row)"
|
||||
>驳回</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="hasPermission('payment_application_void') && row.approvalStatus === 'approved'"
|
||||
type="danger"
|
||||
@click="handleVoid(row)"
|
||||
>作废</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="hasPermission('payment_application_delete') && row.approvalStatus === 'draft'"
|
||||
type="danger"
|
||||
@click="handleDelete(row)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</avue-crud>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import * as api from '@/api/payment/paymentApplication';
|
||||
import { paymentApplicationTableColumns } from '@/option/payment/paymentApplication';
|
||||
import { paymentApplicationOption } from '@/option/payment/paymentApplication';
|
||||
import organizationSearch from '@/mixins/organization-search';
|
||||
import { getMKApprovalUrl } from '@/api/system/business-process';
|
||||
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
|
||||
|
||||
const emptyQuery = () => ({
|
||||
paymentNo: '',
|
||||
applyDateRange: [],
|
||||
payeeName: '',
|
||||
projectName: '',
|
||||
deptName: '',
|
||||
deptPath: [],
|
||||
settlementNo: '',
|
||||
paymentType: '',
|
||||
approvalStatus: '',
|
||||
kingdeeStatus: '',
|
||||
});
|
||||
export default {
|
||||
name: 'PaymentApplication',
|
||||
mixins: [organizationSearch],
|
||||
data() {
|
||||
return {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
Refresh,
|
||||
query: emptyQuery(),
|
||||
searchExpanded: false,
|
||||
paymentTypeOptions: api.paymentTypeOptions,
|
||||
approvalStatusOptions: api.approvalStatusOptions,
|
||||
kingdeeStatusOptions: api.kingdeeStatusOptions,
|
||||
columns: paymentApplicationTableColumns,
|
||||
rows: [],
|
||||
selection: [],
|
||||
loading: false,
|
||||
page: { current: 1, size: 10, total: 0 },
|
||||
query: {},
|
||||
option: {},
|
||||
page: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
total: 0,
|
||||
},
|
||||
mkEnabled: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
visibleSearchFields() {
|
||||
return this.searchExpanded ? this.columns : this.columns.slice(0, 4);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.option = paymentApplicationOption({
|
||||
paymentTypeOptions: api.paymentTypeOptions,
|
||||
approvalStatusOptions: api.approvalStatusOptions,
|
||||
kingdeeStatusOptions: api.kingdeeStatusOptions,
|
||||
});
|
||||
this.loadOrganizationOptions();
|
||||
},
|
||||
mounted() {
|
||||
this.loadOrganizationOptions();
|
||||
this.loadTable();
|
||||
loadMkEnabled()
|
||||
.then(enabled => {
|
||||
this.mkEnabled = !!enabled;
|
||||
@@ -289,39 +188,52 @@ export default {
|
||||
const body = response?.data || response || {};
|
||||
return body?.data || body;
|
||||
},
|
||||
buildParams() {
|
||||
const params = { ...this.query };
|
||||
onLoad(page) {
|
||||
this.loading = true;
|
||||
api
|
||||
.getList(page.currentPage, page.pageSize, { ...this.query })
|
||||
.then(res => {
|
||||
const data = this.unwrapData(res);
|
||||
this.rows = data.records || [];
|
||||
this.page.total = Number(data.total || 0);
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
this.selection = [];
|
||||
this.$refs.crud?.toggleSelection?.();
|
||||
});
|
||||
},
|
||||
searchChange(params, done) {
|
||||
// 所属组织级联返回 id 路径数组,转成部门名称给后端
|
||||
this.normalizeOrganizationSearch(params, 'deptName');
|
||||
// 日期区间拆成后端需要的起止字段
|
||||
const range = params.applyDateRange || [];
|
||||
delete params.applyDateRange;
|
||||
if (range.length === 2) {
|
||||
params.applyStartDate = range[0];
|
||||
params.applyEndDate = range[1];
|
||||
}
|
||||
return params;
|
||||
this.query = {
|
||||
...params,
|
||||
applyStartDate: range[0] || '',
|
||||
applyEndDate: range[1] || '',
|
||||
};
|
||||
this.page.currentPage = 1;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
},
|
||||
async loadTable() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const data = this.unwrapData(
|
||||
await api.getList(this.page.current, this.page.size, this.buildParams())
|
||||
);
|
||||
this.rows = data.records || [];
|
||||
this.page.total = data.total || 0;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
this.page.currentPage = 1;
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
handleSearch() {
|
||||
this.page.current = 1;
|
||||
this.loadTable();
|
||||
currentChange(currentPage) {
|
||||
this.page.currentPage = currentPage;
|
||||
},
|
||||
resetSearch() {
|
||||
this.query = emptyQuery();
|
||||
this.handleSearch();
|
||||
sizeChange(pageSize) {
|
||||
this.page.pageSize = pageSize;
|
||||
},
|
||||
handleSizeChange() {
|
||||
this.page.current = 1;
|
||||
this.loadTable();
|
||||
refreshChange() {
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
selectionChange(list) {
|
||||
this.selection = list;
|
||||
},
|
||||
openCreate() {
|
||||
this.$router.push({ path: '/payment/payment-application/form', query: { mode: 'add' } });
|
||||
@@ -361,7 +273,7 @@ export default {
|
||||
await this.$confirm('确认删除该付款申请?', '提示', { type: 'warning' });
|
||||
await api.remove(row.id);
|
||||
this.$message.success('删除成功');
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
async handleSubmit(row) {
|
||||
const previousApprovalStatus = row.approvalStatus || '';
|
||||
@@ -373,12 +285,12 @@ export default {
|
||||
approvalStatus: previousApprovalStatus,
|
||||
});
|
||||
this.$message.success('提交成功');
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
async handleApprove(row) {
|
||||
await api.approve({ id: row.id });
|
||||
this.$message.success('审批通过');
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
handleMkAudit(row) {
|
||||
if (!row?.id) {
|
||||
@@ -402,18 +314,18 @@ export default {
|
||||
const { value } = await this.$prompt('请输入驳回原因', '审批驳回');
|
||||
await api.returnBill({ id: row.id, reason: value });
|
||||
this.$message.success('已驳回');
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
async handleVoid(row) {
|
||||
const { value } = await this.$prompt('请输入作废原因', '作废付款申请');
|
||||
await api.voidBill({ id: row.id, reason: value });
|
||||
this.$message.success('作废成功');
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
async handleSyncRow(row) {
|
||||
const data = this.unwrapData(await api.syncKingdee(row.id));
|
||||
this.$message.success(`已生成金蝶付款单:${data}`);
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
async handleSync() {
|
||||
const rows = this.selection.filter(row => row.approvalStatus === 'approved');
|
||||
@@ -423,11 +335,16 @@ export default {
|
||||
}
|
||||
await api.syncKingdeeBatch(rows.map(row => row.id));
|
||||
this.$message.success(`已同步${rows.length}条付款申请`);
|
||||
this.loadTable();
|
||||
this.refreshChange();
|
||||
},
|
||||
handleExport() {
|
||||
const headers = this.columns.map(item => item.label);
|
||||
const rows = this.rows.map(row => this.columns.map(item => row[item.prop] || ''));
|
||||
const columns = this.option.column.filter(column => !column.hide && column.prop);
|
||||
const headers = columns.map(item => item.label);
|
||||
const rows = this.rows.map(row =>
|
||||
columns.map(item =>
|
||||
row[item.prop] === null || row[item.prop] === undefined ? '' : row[item.prop]
|
||||
)
|
||||
);
|
||||
const csv = [headers, ...rows]
|
||||
.map(item => item.map(value => `"${String(value).replaceAll('"', '""')}"`).join(','))
|
||||
.join('\n');
|
||||
@@ -444,65 +361,11 @@ export default {
|
||||
''
|
||||
);
|
||||
},
|
||||
displayValue(value) {
|
||||
return value === null || value === undefined || value === '' ? '-' : value;
|
||||
},
|
||||
formatMoney(value) {
|
||||
return Number(value || 0).toFixed(2);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.payment-page__search {
|
||||
padding: 12px 12px 4px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.payment-page__search-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 8px 24px;
|
||||
}
|
||||
.payment-page__search :deep(.el-form-item) {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.payment-page__search :deep(.el-input),
|
||||
.payment-page__search :deep(.el-select),
|
||||
.payment-page__search :deep(.el-date-editor) {
|
||||
width: 100%;
|
||||
}
|
||||
.payment-page__search-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.payment-page__table-panel {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.payment-page__toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.payment-page__toolbar-left {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.payment-page__links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.payment-page__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.payment-page :deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
}
|
||||
@@ -512,14 +375,4 @@ export default {
|
||||
:deep(.payment-page.basic-container .basic-container__card > .el-card__body) {
|
||||
padding: 0;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.payment-page__search-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.payment-page__search-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container class="claim-record-page">
|
||||
<section-card class="claim-record-page__search">
|
||||
<section-card v-if="searchVisible" class="claim-record-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="88px" @submit.prevent>
|
||||
<div class="claim-record-page__search-grid">
|
||||
<el-form-item label="认领通知单">
|
||||
@@ -80,10 +80,19 @@
|
||||
</section-card>
|
||||
|
||||
<section class="claim-record-page__table-panel">
|
||||
<el-table v-loading="loading" :data="rows" border>
|
||||
<div class="claim-record-page__toolbar">
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
v-model:search-visible="searchVisible"
|
||||
@refresh="loadTable"
|
||||
/>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="rows" :size="tableSize" border>
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -138,6 +147,7 @@ import { mapGetters } from 'vuex';
|
||||
import * as api from '@/api/payment/receiptClaimRecord';
|
||||
import { receiptClaimRecordTableColumns } from '@/option/payment/receiptClaimRecord';
|
||||
import SectionCard from '@/components/section-card/main.vue';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import { isAdministrator } from '@/utils/auth';
|
||||
|
||||
const emptyQuery = () => ({
|
||||
@@ -156,16 +166,19 @@ const emptyQuery = () => ({
|
||||
|
||||
export default {
|
||||
name: 'ReceiptClaimRecord',
|
||||
components: { SectionCard },
|
||||
components: { SectionCard, TableHeaderTools },
|
||||
data() {
|
||||
return {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
query: emptyQuery(),
|
||||
searchExpanded: false,
|
||||
searchVisible: true,
|
||||
tableSize: 'default',
|
||||
claimStatusOptions: api.claimStatusOptions,
|
||||
kingdeeBillStatusOptions: api.kingdeeBillStatusOptions,
|
||||
columns: receiptClaimRecordTableColumns,
|
||||
visibleColumnKeys: receiptClaimRecordTableColumns.map(column => column.prop),
|
||||
rows: [],
|
||||
loading: false,
|
||||
page: { current: 1, size: 10, total: 0 },
|
||||
@@ -173,6 +186,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission', 'userInfo']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
isAdmin() {
|
||||
return isAdministrator(this.userInfo);
|
||||
},
|
||||
@@ -279,6 +295,12 @@ export default {
|
||||
.claim-record-page__table-panel {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.claim-record-page__toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.claim-record-page__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container class="receipt-flow-page">
|
||||
<section class="receipt-flow-page__search">
|
||||
<section v-if="searchVisible" class="receipt-flow-page__search">
|
||||
<el-form :model="query" label-position="right" label-width="88px" @submit.prevent>
|
||||
<div class="receipt-flow-page__search-grid">
|
||||
<el-form-item label="认领通知单">
|
||||
@@ -52,33 +52,43 @@
|
||||
|
||||
<section class="receipt-flow-page__table-panel">
|
||||
<div class="receipt-flow-page__toolbar">
|
||||
<el-button
|
||||
v-if="hasPermission('receipt_flow_sync')"
|
||||
type="primary"
|
||||
:loading="syncing"
|
||||
@click="handleSync"
|
||||
>
|
||||
手动同步流水
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasPermission('receipt_flow_claim')"
|
||||
type="primary"
|
||||
:disabled="!selectedRows.length"
|
||||
@click="openBatchClaim"
|
||||
>
|
||||
批量认领
|
||||
</el-button>
|
||||
<div class="receipt-flow-page__toolbar-left">
|
||||
<el-button
|
||||
v-if="hasPermission('receipt_flow_sync')"
|
||||
type="primary"
|
||||
:loading="syncing"
|
||||
@click="handleSync"
|
||||
>
|
||||
手动同步流水
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasPermission('receipt_flow_claim')"
|
||||
type="primary"
|
||||
:disabled="!selectedRows.length"
|
||||
@click="openBatchClaim"
|
||||
>
|
||||
批量认领
|
||||
</el-button>
|
||||
</div>
|
||||
<table-header-tools
|
||||
:columns="columns"
|
||||
v-model:visible-column-keys="visibleColumnKeys"
|
||||
v-model:table-size="tableSize"
|
||||
v-model:search-visible="searchVisible"
|
||||
@refresh="loadTable"
|
||||
/>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
:size="tableSize"
|
||||
border
|
||||
@selection-change="selectedRows = $event"
|
||||
>
|
||||
<el-table-column type="selection" width="52" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
v-for="column in visibleColumns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
@@ -193,6 +203,7 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
import * as api from '@/api/payment/receiptFlow';
|
||||
import { receiptFlowTableColumns } from '@/option/payment/receiptFlow';
|
||||
import TableHeaderTools from '@/components/table-header-tools/main.vue';
|
||||
import { isAdministrator } from '@/utils/auth';
|
||||
|
||||
const receiptFlowMockTemplates = [
|
||||
@@ -265,11 +276,15 @@ const emptyQuery = () => ({
|
||||
|
||||
export default {
|
||||
name: 'ReceiptFlow',
|
||||
components: { TableHeaderTools },
|
||||
data() {
|
||||
return {
|
||||
query: emptyQuery(),
|
||||
claimStatusOptions: api.claimStatusOptions,
|
||||
columns: receiptFlowTableColumns,
|
||||
visibleColumnKeys: receiptFlowTableColumns.map(column => column.prop),
|
||||
searchVisible: true,
|
||||
tableSize: 'default',
|
||||
rows: [],
|
||||
selectedRows: [],
|
||||
loading: false,
|
||||
@@ -281,6 +296,9 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission', 'userInfo']),
|
||||
visibleColumns() {
|
||||
return this.columns.filter(column => this.visibleColumnKeys.includes(column.prop));
|
||||
},
|
||||
isAdmin() {
|
||||
return isAdministrator(this.userInfo);
|
||||
},
|
||||
@@ -436,11 +454,15 @@ export default {
|
||||
}
|
||||
.receipt-flow-page__toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.receipt-flow-page__toolbar-left {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
.receipt-flow-page__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
@@ -175,6 +175,17 @@
|
||||
<section-card title="结算明细">
|
||||
<template #extra>
|
||||
<div class="formal-editor__actions">
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_export')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="exportDetails"
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
<el-button v-if="editable" type="primary" plain @click="openDetailDialog">
|
||||
选择结算明细
|
||||
</el-button>
|
||||
<el-button type="primary" text @click="detailCollapsed = !detailCollapsed">
|
||||
{{ detailCollapsed ? '展开明细' : '收起明细' }}
|
||||
</el-button>
|
||||
@@ -182,33 +193,46 @@
|
||||
</template>
|
||||
<el-form
|
||||
:model="detailQuery"
|
||||
inline
|
||||
label-position="right"
|
||||
label-width="88px"
|
||||
label-width="auto"
|
||||
class="formal-editor__detail-filter"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="单据号">
|
||||
<el-input v-model="detailQuery.documentNo" clearable @keyup.enter="handleDetailQuery" />
|
||||
<el-input
|
||||
v-model="detailQuery.documentNo"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handleDetailQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="运单号">
|
||||
<el-input v-model="detailQuery.waybillNo" clearable @keyup.enter="handleDetailQuery" />
|
||||
<el-input
|
||||
v-model="detailQuery.waybillNo"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handleDetailQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号">
|
||||
<el-input v-model="detailQuery.batchNo" clearable @keyup.enter="handleDetailQuery" />
|
||||
<el-input
|
||||
v-model="detailQuery.batchNo"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handleDetailQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="货物名称">
|
||||
<el-input v-model="detailQuery.cargoName" clearable @keyup.enter="handleDetailQuery" />
|
||||
<el-input
|
||||
v-model="detailQuery.cargoName"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
@keyup.enter="handleDetailQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="formal-editor__detail-filter-actions">
|
||||
<el-button type="primary" @click="handleDetailQuery">查询</el-button>
|
||||
<el-button @click="resetDetailQuery">重置</el-button>
|
||||
<el-button type="primary" :disabled="!details.length" @click="exportDetails">
|
||||
导出
|
||||
</el-button>
|
||||
<el-button v-if="editable" type="primary" @click="openDetailDialog">
|
||||
选择结算明细
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-show="!detailCollapsed" :data="pagedDetails" border>
|
||||
@@ -991,6 +1015,7 @@ import { mapGetters } from 'vuex';
|
||||
import { formatContractOptionLabel } from '@/utils/contract';
|
||||
import { downloadFileByUrl } from '@/utils/util';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { isAdministrator } from '@/utils/auth';
|
||||
|
||||
export default {
|
||||
name: 'FormalSettlementEditor',
|
||||
@@ -1126,7 +1151,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['userInfo']),
|
||||
...mapGetters(['permission', 'userInfo']),
|
||||
visible: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
@@ -1154,6 +1179,9 @@ export default {
|
||||
editable() {
|
||||
return !this.readonly;
|
||||
},
|
||||
isAdmin() {
|
||||
return isAdministrator(this.userInfo);
|
||||
},
|
||||
title() {
|
||||
return this.readonly ? '查看正式结算单' : this.recordId ? '编辑正式结算单' : '新增正式结算单';
|
||||
},
|
||||
@@ -1225,6 +1253,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formatContractOptionLabel,
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission?.[code], false);
|
||||
},
|
||||
async loadFormalDetail(id) {
|
||||
const response = this.publicMode
|
||||
? await getMkPublicDetail('formal-settlement', id)
|
||||
@@ -2829,20 +2860,24 @@ export default {
|
||||
}
|
||||
.formal-editor__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.formal-editor__detail-filter {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
|
||||
align-items: center;
|
||||
gap: 8px 16px;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px 12px 4px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.formal-editor__detail-filter-actions {
|
||||
grid-column: 1 / -1;
|
||||
width: auto;
|
||||
margin-left: 0;
|
||||
white-space: nowrap;
|
||||
justify-self: end;
|
||||
}
|
||||
.formal-editor__page-actions {
|
||||
@@ -2965,9 +3000,29 @@ export default {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
/* 结算明细筛选区:覆盖全局 el-form-item 24px 行距,保证筛选控件与「查询/重置」同行居中对齐 */
|
||||
.formal-editor__detail-filter :deep(.el-form-item) {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.formal-editor__detail-filter :deep(.el-form-item__content) {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.formal-editor__detail-filter :deep(.el-input) {
|
||||
width: 100%;
|
||||
}
|
||||
.formal-editor__detail-filter-actions :deep(.el-form-item__content) {
|
||||
flex: none;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.formal-editor__detail-filter {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)) auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ export default ({ mode, command }) => {
|
||||
port: 2889,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://172.16.203.228:8000',
|
||||
target: 'http://172.16.203.221:8000',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user