新增业务实体字段配置功能,包含主表和明细表的数据库结构定义,支持业务打印绑定的字段映射。实现字段配置的增删改查操作,优化打印数据生成逻辑,提升系统的可维护性和扩展性。同时,新增异步同步功能以支持打印模板与业务数据的实时更新。
This commit is contained in:
@@ -22,8 +22,9 @@ export const deleteOne = (params, handleSuccess?) =>
|
||||
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => handleSuccess?.());
|
||||
|
||||
export const bizTypes = () => defHttp.get({ url: Api.bizTypes });
|
||||
/** 新增/编辑绑定时可选业务(受打印业务白名单过滤) */
|
||||
export const bizTypesForBinding = () => defHttp.get({ url: Api.bizTypesForBinding });
|
||||
/** 新增/编辑绑定时可选业务(受打印业务白名单过滤);后端批量查缓存与菜单,数据多时延长超时 */
|
||||
export const bizTypesForBinding = () =>
|
||||
defHttp.get({ url: Api.bizTypesForBinding, timeout: 120000 });
|
||||
/** 白名单:已勾选菜单 id + 完整业务目录 */
|
||||
export const getPermWhitelist = () => defHttp.get({ url: Api.permWhitelist });
|
||||
/** 勾选菜单多时后端需批量 upsert,默认 10s 易超时 */
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
show-icon
|
||||
class="bind-alert"
|
||||
message="配置说明"
|
||||
description="按卡片顺序操作:先选业务与模板 → 若模板含明细占位,在「明细数据来源」中选择主实体上的集合/嵌套对象 → 点击「解析模板占位字段」→ 在下方「主表参数」「明细与表格」中分别为每个占位选择业务字段。主表参数一般映射主实体字段;明细占位可选带「明细前缀」的路径(如 lines.qty)。支持 lines.qty(首行)或 lines.0.qty。"
|
||||
description="按卡片顺序操作:先选业务与模板 → 若模板含明细占位,在「明细数据来源」中选择主实体上的集合/嵌套对象 → 点击「解析模板占位字段」→ 在下方「主表参数」「明细与表格」中分别为每个占位选择业务字段;业务字段下拉第一项为「空占位符」,表示不参与业务 JSON 取值(等同输出空)。主表参数一般映射主实体字段;明细占位可选带「明细前缀」的路径(如 lines.qty)。支持 lines.qty(首行)或 lines.0.qty。"
|
||||
/>
|
||||
|
||||
<a-card title="基础信息" size="small" :bordered="true" class="bind-card">
|
||||
@@ -57,7 +57,7 @@
|
||||
<a-form-item
|
||||
label="业务"
|
||||
required
|
||||
extra="业务编码为菜单 id;后端按 print_biz_perm_entity 或菜单 component 推断主实体并反射主表字段。"
|
||||
extra="业务编码为菜单 id;业务字段优先从缓存表读取(启动任务根据 print_biz_perm_entity 异步写入 mes_xsl_biz_entity_field_*),无缓存时再反射实体类。"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="form.bizCode"
|
||||
@@ -129,7 +129,6 @@
|
||||
>
|
||||
同名自动匹配
|
||||
</a-button>
|
||||
<a-button size="small" @click="addPlaceholderParamRow">添加空占位</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -285,6 +284,9 @@
|
||||
const { createMessage } = useMessage();
|
||||
const { t } = useI18n();
|
||||
|
||||
/** 下拉「空占位符」选项值(落库 fieldMappingJson 的 bizField 转为 '') */
|
||||
const EMPTY_BIZ_FIELD_SENTINEL = '__PRINT_BIND_EMPTY_BIZ__';
|
||||
|
||||
interface BizTypeItem {
|
||||
bizCode: string;
|
||||
bizName: string;
|
||||
@@ -361,15 +363,18 @@
|
||||
})),
|
||||
);
|
||||
|
||||
const bizFieldOptionsMain = computed(() =>
|
||||
unref(bizFields).map((f) => ({
|
||||
const bizFieldOptionsMain = computed(() => {
|
||||
const head = [{ label: '— 空占位符(不参与业务 JSON)—', value: EMPTY_BIZ_FIELD_SENTINEL }];
|
||||
const rest = unref(bizFields).map((f) => ({
|
||||
label: f.label ? `${f.label}(${f.fieldKey})` : f.fieldKey,
|
||||
value: f.fieldKey,
|
||||
})),
|
||||
);
|
||||
}));
|
||||
return [...head, ...rest];
|
||||
});
|
||||
|
||||
/** 主表 + 明细前缀字段(用于明细/表格占位) */
|
||||
const bizFieldOptions = computed(() => {
|
||||
const head = [{ label: '— 空占位符(不参与业务 JSON)—', value: EMPTY_BIZ_FIELD_SENTINEL }];
|
||||
const main = unref(bizFields).map((f) => ({
|
||||
label: f.label ? `${f.label}(${f.fieldKey})` : f.fieldKey,
|
||||
value: f.fieldKey,
|
||||
@@ -378,9 +383,25 @@
|
||||
label: f.label ? `${f.label}(${f.fieldKey})` : f.fieldKey,
|
||||
value: f.fieldKey,
|
||||
}));
|
||||
return [...main, ...detail];
|
||||
return [...head, ...main, ...detail];
|
||||
});
|
||||
|
||||
/** 已保存的空字符串映射为下拉哨兵,便于展示「空占位符」项 */
|
||||
function normalizeBizFieldForUi(raw?: string) {
|
||||
if (raw === undefined || raw === null || raw === '') {
|
||||
return EMPTY_BIZ_FIELD_SENTINEL;
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/** 提交前哨兵还原为空字符串 */
|
||||
function denormalizeBizFieldForSave(v?: string) {
|
||||
if (v === EMPTY_BIZ_FIELD_SENTINEL || v === undefined || v === null || v === '') {
|
||||
return '';
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/** 主表参数行:模板 elementType 为 param */
|
||||
const mappingRowsParam = computed(() =>
|
||||
unref(mappingRows).filter((r) => (r.elementType || '') === 'param'),
|
||||
@@ -615,7 +636,7 @@
|
||||
const hit = saved.find((x) => x.templateField === templateField);
|
||||
return {
|
||||
templateField,
|
||||
bizField: hit?.bizField ?? '',
|
||||
bizField: hit !== undefined ? normalizeBizFieldForUi(hit.bizField) : undefined,
|
||||
elementType: t?.elementType || 'param',
|
||||
titleHint:
|
||||
t?.titleHint ||
|
||||
@@ -637,26 +658,13 @@
|
||||
mappingRows.value = [...unref(mappingRows)];
|
||||
}
|
||||
|
||||
/** 手动增加仅输出空值的模板占位(写入 savedMappingRef 并重建行,避免再次「解析模板」时丢失) */
|
||||
function addPlaceholderParamRow() {
|
||||
const raw = window.prompt(
|
||||
'请输入模板参数 bindField(如 Parameter3)。业务字段将固定为空字符串,不参与业务 JSON 取值。',
|
||||
'Parameter3',
|
||||
);
|
||||
const k = (raw || '').trim();
|
||||
if (!k) return;
|
||||
if (unref(savedMappingRef).some((x) => x.templateField === k) || unref(mappingRows).some((r) => r.templateField === k)) {
|
||||
createMessage.warning('该占位已存在');
|
||||
return;
|
||||
}
|
||||
savedMappingRef.value = [...unref(savedMappingRef), { templateField: k, bizField: '' }];
|
||||
rebuildMappingRows();
|
||||
}
|
||||
|
||||
function buildFieldMappingJson() {
|
||||
const arr = unref(mappingRows)
|
||||
.filter((r) => r.templateField)
|
||||
.map((r) => ({ templateField: r.templateField, bizField: r.bizField ?? '' }));
|
||||
.map((r) => ({
|
||||
templateField: r.templateField,
|
||||
bizField: denormalizeBizFieldForSave(r.bizField),
|
||||
}));
|
||||
return JSON.stringify(arr);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user