<script lang="ts" setup>
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import type {
|
FormulaDetail,
|
FormulaFunction,
|
FormulaRule,
|
FormulaStatus,
|
FormulaType,
|
FormulaValidation,
|
FormulaVersion,
|
ParameterSlot,
|
RoundMode,
|
TemplateReferencePageQuery,
|
} from '#/api/x/eln/formulas';
|
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicDrawer, useDrawerInner } from '@jnpf/ui/drawer';
|
import { BasicModal, useModal } from '@jnpf/ui/modal';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue';
|
|
import {
|
cancelFormulaVersion,
|
createFormulaVersion,
|
getFormulaDetail,
|
getFormulaFunctions,
|
getFormulaTemplateReferences,
|
preReleaseFormulaVersion,
|
publishFormulaVersion,
|
switchCurrentFormulaVersion,
|
updateFormulaVersion,
|
} from '#/api/x/eln/formulas';
|
|
import FormulaEditor from './FormulaEditor.vue';
|
import FormulaPreview from './FormulaPreview.vue';
|
import { formulaVersionActions } from './formulaRules';
|
import ParameterTable from './ParameterTable.vue';
|
import TrialPanel from './TrialPanel.vue';
|
|
defineOptions({ name: 'ElnFormulaVersionDrawer' });
|
|
const emit = defineEmits(['register', 'reload']);
|
|
type ReasonAction = 'cancel' | 'setCurrent';
|
|
const { createMessage } = useMessage();
|
const formula = ref<FormulaDetail>();
|
const editingVersion = ref<FormulaVersion>();
|
type EditableParameterSlot = ParameterSlot & { _clientKey?: string };
|
|
const editingParameters = ref<EditableParameterSlot[]>([]);
|
const formulaEditor = ref<{ validate?: () => Promise<void> }>();
|
const formulaFunctions = ref<FormulaFunction[]>([]);
|
const formulaFunctionsError = ref('');
|
const editingValidation = ref<FormulaValidation>();
|
const parametersExpanded = ref(false);
|
const versionModalHeight = ref<number>();
|
const savingDraft = ref(false);
|
const trialResetKey = ref(0);
|
const reason = ref('');
|
const reasonAction = ref<ReasonAction>();
|
const reasonVersion = ref<FormulaVersion>();
|
const referenceKeyword = ref('');
|
let detailRequestSequence = 0;
|
|
const FORMULA_TYPE_LABELS: Record<FormulaType, string> = {
|
BOOLEAN: '布尔值',
|
DECIMAL: '数值',
|
DECIMAL_LIST: '数值列表',
|
TEXT: '文本',
|
};
|
const FORMULA_RESULT_TYPE_OPTIONS: { fullName: string; id: FormulaType }[] = (['DECIMAL', 'BOOLEAN', 'TEXT'] as const).map((id) => ({
|
fullName: FORMULA_TYPE_LABELS[id],
|
id,
|
}));
|
const versions = computed(() => formula.value?.versions || []);
|
const currentVersion = computed(() => versions.value.find((version) => version.id === formula.value?.dangqianGongshiBanbenId));
|
const isEditingDraft = computed(() => editingVersion.value?.bizStatus === 'DRAFT');
|
const editingRule = computed<FormulaRule | undefined>(() => {
|
const version = editingVersion.value;
|
if (!version) return undefined;
|
return {
|
biaodashi: version.biaodashi || '',
|
jieguoLeixing: version.jieguoLeixing,
|
parameters: editingParameters.value.map(({ _clientKey, ...slot }) => slot),
|
xiuyueMoshi: version.xiuyueMoshi,
|
xiuyueXiaoshuWei: version.xiuyueXiaoshuWei,
|
};
|
});
|
const drawerTitle = computed(() => (formula.value ? `公式版本 - ${formula.value.gongshiBianma}` : '公式版本'));
|
const versionModalTitle = computed(() => {
|
const actionTitle = isEditingDraft.value ? '编辑公式版本' : '预览公式版本';
|
return editingVersion.value ? `${actionTitle} - V${editingVersion.value.banbenHao}` : actionTitle;
|
});
|
const reasonModalTitle = computed(() => {
|
const actionTitle = reasonAction.value === 'cancel' ? '作废公式版本' : '切换当前版本';
|
return reasonVersion.value ? `${actionTitle} - V${reasonVersion.value.banbenHao}` : actionTitle;
|
});
|
const referenceTotal = computed(() => formula.value?.mubanYinyongShu ?? formula.value?.templateReferences?.length ?? 0);
|
const hasMoreReferences = computed(() => referenceTotal.value > (formula.value?.templateReferences?.length ?? 0));
|
const columns: BasicColumn[] = [
|
{ dataIndex: 'banbenHao', title: '版本', width: 80, slots: { default: 'banbenHao' } },
|
{ dataIndex: 'jieguoLeixing', slots: { default: 'jieguoLeixing' }, title: '结果类型', width: 110 },
|
{ dataIndex: 'bizStatus', title: '状态', width: 110, slots: { default: 'bizStatus' } },
|
{ dataIndex: 'current', title: '当前使用', width: 90, slots: { default: 'current' } },
|
{ dataIndex: 'chuangjianShijian', format: 'date|YYYY-MM-DD HH:mm:ss', minWidth: 165, title: '创建时间' },
|
{ dataIndex: 'gengxinShijian', format: 'date|YYYY-MM-DD HH:mm:ss', title: '最后修改时间', width: 165 },
|
];
|
const [registerTable] = useVxeTable({
|
actionColumn: { dataIndex: 'action', fixed: 'right', title: '操作', width: 260 },
|
columns,
|
dataSource: versions,
|
immediate: false,
|
pagination: false,
|
rowKey: 'id',
|
showIndexColumn: false,
|
showTableSetting: false,
|
});
|
const referenceColumns: BasicColumn[] = [
|
{ dataIndex: 'templateName', minWidth: 200, slots: { default: 'templateName' }, title: '模板名称' },
|
{ dataIndex: 'templateId', minWidth: 180, title: '模板 ID' },
|
{ dataIndex: 'templateStatus', slots: { default: 'templateStatus' }, title: '模板状态', width: 110 },
|
{ dataIndex: 'bindingStatus', slots: { default: 'bindingStatus' }, title: '绑定状态', width: 110 },
|
{ dataIndex: 'formulaVersionId', minWidth: 180, title: '公式版本 ID' },
|
];
|
const [registerReferenceTable, { reload: reloadReferenceTable }] = useVxeTable({
|
api: fetchTemplateReferences,
|
beforeFetch: normalizeReferenceQuery,
|
columns: referenceColumns,
|
immediate: false,
|
pagination: {
|
pageSize: 20,
|
pageSizeOptions: ['20', '50', '100'],
|
showQuickJumper: true,
|
showSizeChanger: true,
|
showTotal: (total) => `共 ${total} 个模板引用`,
|
},
|
rowKey: 'bindingId',
|
showIndexColumn: false,
|
showTableSetting: false,
|
});
|
const [registerEditModal, { closeModal: closeEditModal, openModal: openEditModal }] = useModal();
|
const [registerReasonModal, { closeModal: closeReasonModal, openModal: openReasonModal }] = useModal();
|
const [registerReferenceModal, { openModal: openReferenceModal }] = useModal();
|
const [registerDrawer, { changeLoading }] = useDrawerInner(init);
|
|
watch(
|
() => editingVersion.value?.jieguoLeixing,
|
(resultType) => {
|
if (!editingVersion.value || !isEditingDraft.value) return;
|
if (resultType === 'DECIMAL') {
|
editingVersion.value.xiuyueMoshi ??= 'HALF_UP';
|
editingVersion.value.xiuyueXiaoshuWei ??= 2;
|
return;
|
}
|
editingVersion.value.xiuyueMoshi = undefined;
|
editingVersion.value.xiuyueXiaoshuWei = undefined;
|
},
|
);
|
|
async function init(data: { formulaId: string; openDraft?: boolean }) {
|
const loaded = await loadFormula(data.formulaId, true);
|
if (!loaded || !data.openDraft) return;
|
const draft = formula.value?.versions.filter((version) => version.bizStatus === 'DRAFT').sort((left, right) => left.banbenHao - right.banbenHao)[0];
|
if (!draft) {
|
createMessage.warning('未找到可编辑的草稿版本');
|
return;
|
}
|
await openDraft(draft);
|
}
|
|
async function loadFormula(formulaId: string, clearBeforeLoad: boolean): Promise<boolean> {
|
const requestSequence = ++detailRequestSequence;
|
if (clearBeforeLoad) formula.value = undefined;
|
changeLoading(true);
|
try {
|
const response = await getFormulaDetail(formulaId);
|
if (requestSequence !== detailRequestSequence) return false;
|
formula.value = response.data;
|
return true;
|
} finally {
|
if (requestSequence === detailRequestSequence) changeLoading(false);
|
}
|
}
|
|
function normalizeReferenceQuery(raw: Record<string, unknown>): TemplateReferencePageQuery {
|
const query: Record<string, unknown> = { ...raw };
|
if (typeof query.keyword === 'string') query.keyword = query.keyword.trim();
|
if (!query.keyword) delete query.keyword;
|
query.currentPage = Math.max(1, Number(query.currentPage) || 1);
|
query.pageSize = Math.max(1, Number(query.pageSize) || 20);
|
return query as unknown as TemplateReferencePageQuery;
|
}
|
|
async function fetchTemplateReferences(query: TemplateReferencePageQuery) {
|
const formulaId = formula.value?.id;
|
if (!formulaId) throw new Error('公式信息尚未加载');
|
const response = await getFormulaTemplateReferences(formulaId, query);
|
return { data: response.data };
|
}
|
|
async function showAllReferences() {
|
if (!formula.value) return;
|
referenceKeyword.value = '';
|
openReferenceModal(true);
|
await nextTick();
|
reloadReferenceTable({ page: 1, searchInfo: {} });
|
}
|
|
function searchTemplateReferences() {
|
const keyword = referenceKeyword.value.trim();
|
referenceKeyword.value = keyword;
|
reloadReferenceTable({ page: 1, searchInfo: keyword ? { keyword } : {} });
|
}
|
|
onBeforeUnmount(() => {
|
detailRequestSequence++;
|
});
|
|
function getTableActions(version: FormulaVersion): ActionItem[] {
|
return formulaVersionActions({
|
current: version.id === formula.value?.dangqianGongshiBanbenId,
|
enabled: formula.value?.bizEnabled === 'enabled',
|
status: version.bizStatus,
|
}).map((action): ActionItem => {
|
if (action === 'preview') return { label: '预览', onClick: () => openVersion(version) };
|
if (action === 'edit') return { label: '编辑', onClick: () => openDraft(version) };
|
if (action === 'preRelease')
|
return {
|
label: '提交预发布',
|
modelConfirm: { content: `确认将 V${version.banbenHao} 提交为预发布版本?`, onOk: () => preRelease(version) },
|
};
|
if (action === 'publish')
|
return {
|
color: 'success',
|
label: '发布',
|
modelConfirm: { content: `确认发布 V${version.banbenHao}?发布后不可修改。`, onOk: () => publish(version) },
|
};
|
if (action === 'cancel') return { color: 'error', label: '作废', onClick: () => openReason(version, 'cancel') };
|
if (action === 'setCurrent') return { label: '设为当前', onClick: () => openReason(version, 'setCurrent') };
|
return {
|
label: '复制新版本',
|
modelConfirm: { content: `基于 V${version.banbenHao} 创建新的草稿版本?`, onOk: () => copyVersion(version) },
|
};
|
});
|
}
|
|
async function openDraft(version: FormulaVersion) {
|
if (version.bizStatus !== 'DRAFT') return;
|
await openVersion(version);
|
}
|
|
async function openVersion(version: FormulaVersion) {
|
const editable = version.bizStatus === 'DRAFT';
|
if (!editable && version.bizStatus !== 'PRE_RELEASE' && version.bizStatus !== 'PUBLISHED') return;
|
versionModalHeight.value = undefined;
|
parametersExpanded.value = false;
|
editingVersion.value = {
|
...version,
|
xiuyueMoshi: editable && version.jieguoLeixing === 'DECIMAL' ? (version.xiuyueMoshi ?? 'HALF_UP') : version.xiuyueMoshi,
|
xiuyueXiaoshuWei: editable && version.jieguoLeixing === 'DECIMAL' ? (version.xiuyueXiaoshuWei ?? 2) : version.xiuyueXiaoshuWei,
|
};
|
editingParameters.value = version.parameters.map((slot) => ({ ...slot }));
|
editingValidation.value = undefined;
|
formulaFunctionsError.value = '';
|
openEditModal(true);
|
await nextTick();
|
void formulaEditor.value?.validate?.();
|
try {
|
formulaFunctions.value = await getFormulaFunctions();
|
} catch {
|
formulaFunctionsError.value = '公式函数加载失败,仍可继续编辑表达式';
|
}
|
}
|
|
async function resetDraftModalState() {
|
versionModalHeight.value = undefined;
|
parametersExpanded.value = false;
|
editingValidation.value = undefined;
|
trialResetKey.value++;
|
}
|
|
function clearEditingValidation() {
|
editingValidation.value = undefined;
|
}
|
|
function handleValidation(validation: FormulaValidation) {
|
editingValidation.value = validation;
|
}
|
|
function lockVersionModalHeight(height: number | string) {
|
if (versionModalHeight.value !== undefined || parametersExpanded.value) return;
|
const measuredHeight = Number(height);
|
if (!Number.isFinite(measuredHeight) || measuredHeight <= 0) return;
|
versionModalHeight.value = measuredHeight;
|
}
|
|
async function saveDraft() {
|
const version = editingVersion.value;
|
if (!version || version.bizStatus !== 'DRAFT' || savingDraft.value) return;
|
savingDraft.value = true;
|
try {
|
await updateFormulaVersion(version.id, {
|
biaodashi: version.biaodashi,
|
jieguoLeixing: version.jieguoLeixing as FormulaType,
|
parameters: editingParameters.value.map(({ _clientKey, ...slot }) => slot),
|
xiuyueMoshi: version.xiuyueMoshi as RoundMode | undefined,
|
xiuyueXiaoshuWei: version.xiuyueXiaoshuWei,
|
});
|
createMessage.success('草稿版本已保存');
|
closeEditModal();
|
await reloadFormula();
|
} finally {
|
savingDraft.value = false;
|
}
|
}
|
|
async function preRelease(version: FormulaVersion) {
|
await preReleaseFormulaVersion(version.id);
|
createMessage.success(`V${version.banbenHao} 已提交预发布`);
|
await reloadFormula();
|
}
|
|
async function publish(version: FormulaVersion) {
|
await publishFormulaVersion(version.id);
|
createMessage.success(`V${version.banbenHao} 已发布`);
|
await reloadFormula();
|
}
|
|
async function copyVersion(version: FormulaVersion) {
|
if (!formula.value) return;
|
await createFormulaVersion(formula.value.id, { sourceVersionId: version.id });
|
createMessage.success('新的草稿版本已创建');
|
await reloadFormula();
|
}
|
|
function openReason(version: FormulaVersion, action: ReasonAction) {
|
reason.value = '';
|
reasonVersion.value = version;
|
reasonAction.value = action;
|
openReasonModal(true);
|
}
|
|
async function confirmReasonAction() {
|
const version = reasonVersion.value;
|
const actualReason = reason.value.trim();
|
if (!version || !reasonAction.value || !actualReason) {
|
createMessage.warning('请输入操作原因');
|
return;
|
}
|
if (reasonAction.value === 'cancel') {
|
await cancelFormulaVersion(version.id, actualReason);
|
createMessage.success(`V${version.banbenHao} 已作废`);
|
} else if (formula.value) {
|
await switchCurrentFormulaVersion(formula.value.id, { reason: actualReason, versionId: version.id });
|
createMessage.success(`当前版本已切换为 V${version.banbenHao}`);
|
}
|
closeReasonModal();
|
await reloadFormula();
|
}
|
|
async function reloadFormula() {
|
const formulaId = formula.value?.id;
|
if (!formulaId) return;
|
if (await loadFormula(formulaId, false)) emit('reload');
|
}
|
|
function versionStatusLabel(status: FormulaStatus) {
|
return { CANCELLED: '已作废', DRAFT: '草稿', PRE_RELEASE: '预发布', PUBLISHED: '已发布' }[status];
|
}
|
|
function versionStatusColor(status: FormulaStatus) {
|
return { CANCELLED: 'default', DRAFT: 'processing', PRE_RELEASE: 'warning', PUBLISHED: 'success' }[status];
|
}
|
|
function formulaTypeLabel(type: FormulaType) {
|
return FORMULA_TYPE_LABELS[type] || type;
|
}
|
|
function templateStatusLabel(status?: string) {
|
return { CANCELLED: '已作废', DRAFT: '草稿', PRE_RELEASE: '预发布', PUBLISHED: '已发布' }[status || ''] || status || '模板已不存在';
|
}
|
|
function bindingStatusLabel(status?: string) {
|
return { ACTIVE: '已生效', PENDING: '待生效' }[status || ''] || status || '-';
|
}
|
</script>
|
|
<template>
|
<BasicDrawer v-bind="$attrs" @register="registerDrawer" class="full-drawer" keyboard :show-footer="false" :title="drawerTitle" width="960px">
|
<div v-if="formula" class="formula-version-content">
|
<div class="formula-summary">
|
<a-descriptions :column="2" size="small">
|
<a-descriptions-item label="公式编码">{{ formula.gongshiBianma }}</a-descriptions-item>
|
<a-descriptions-item label="启用状态">{{ formula.bizEnabled === 'enabled' ? '启用' : '停用' }}</a-descriptions-item>
|
<a-descriptions-item label="当前版本">{{ currentVersion ? `V${currentVersion.banbenHao}` : '未设置' }}</a-descriptions-item>
|
<a-descriptions-item label="模板引用数">{{ referenceTotal }}</a-descriptions-item>
|
</a-descriptions>
|
<a-alert v-if="currentVersion?.bizStatus === 'PRE_RELEASE'" class="pre-release-warning" message="预发布,仅供模板验证" show-icon type="warning" />
|
</div>
|
<div v-if="formula.templateReferences?.length" class="formula-references">
|
<a-descriptions :column="1" size="small" title="模板引用">
|
<template #extra>
|
<a-button v-if="hasMoreReferences" data-test="view-all-references" type="link" @click="showAllReferences">查看全部</a-button>
|
</template>
|
<a-descriptions-item
|
v-for="reference in formula.templateReferences"
|
:key="`${reference.templateId}-${reference.formulaVersionId}-${reference.bindingStatus}`"
|
label="模板">
|
{{ reference.templateName || reference.templateId }} · {{ templateStatusLabel(reference.templateStatus) }} ·
|
{{ bindingStatusLabel(reference.bindingStatus) }}
|
</a-descriptions-item>
|
</a-descriptions>
|
</div>
|
<div class="version-table">
|
<BasicVxeTable @register="registerTable" :data-source="versions">
|
<template #banbenHao="{ record }">V{{ record.banbenHao }}</template>
|
<template #jieguoLeixing="{ record }">{{ formulaTypeLabel(record.jieguoLeixing) }}</template>
|
<template #bizStatus="{ record }">
|
<a-tag :color="versionStatusColor(record.bizStatus)">{{ versionStatusLabel(record.bizStatus) }}</a-tag>
|
</template>
|
<template #current="{ record }"><a-tag v-if="record.id === formula.dangqianGongshiBanbenId" color="blue">当前</a-tag><span v-else>-</span></template>
|
<template #action="{ record }"><TableAction :actions="getTableActions(record)" /></template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
<BasicModal
|
@register="registerEditModal"
|
:after-close="resetDraftModalState"
|
:confirm-loading="savingDraft"
|
force-render
|
:height="versionModalHeight"
|
:min-height="versionModalHeight"
|
:show-ok-btn="isEditingDraft"
|
:title="versionModalTitle"
|
width="min(1200px, calc(100vw - 48px))"
|
@height-change="lockVersionModalHeight"
|
@ok="saveDraft">
|
<template v-if="editingVersion">
|
<div class="draft-version-content">
|
<div v-if="!parametersExpanded" class="draft-version-workspace">
|
<section class="draft-version-editor">
|
<a-form class="draft-version-form" layout="vertical">
|
<div class="draft-version-rule-grid">
|
<a-form-item label="结果类型">
|
<a-select
|
v-model:value="editingVersion.jieguoLeixing"
|
:disabled="!isEditingDraft"
|
:field-names="{ label: 'fullName', value: 'id' }"
|
:options="FORMULA_RESULT_TYPE_OPTIONS"
|
placeholder="请选择结果类型" />
|
</a-form-item>
|
<template v-if="editingVersion.jieguoLeixing === 'DECIMAL'">
|
<a-form-item label="修约小数位">
|
<a-input-number
|
v-model:value="editingVersion.xiuyueXiaoshuWei"
|
:disabled="!isEditingDraft"
|
:max="12"
|
:min="0"
|
placeholder="请输入修约小数位"
|
:precision="0" />
|
</a-form-item>
|
<a-form-item label="修约方式">
|
<a-select
|
v-model:value="editingVersion.xiuyueMoshi"
|
allow-clear
|
:disabled="!isEditingDraft"
|
:field-names="{ label: 'fullName', value: 'id' }"
|
:options="[
|
{ fullName: '四舍五入', id: 'HALF_UP' },
|
{ fullName: '四舍六入五成双', id: 'HALF_EVEN' },
|
{ fullName: '向下', id: 'DOWN' },
|
{ fullName: '向上', id: 'UP' },
|
]"
|
placeholder="请选择修约方式" />
|
</a-form-item>
|
</template>
|
</div>
|
<a-form-item class="draft-version-expression" label="表达式">
|
<FormulaEditor
|
ref="formulaEditor"
|
:key="`${editingVersion.id}-${editingVersion.bizStatus}`"
|
v-model="editingVersion.biaodashi"
|
:functions="formulaFunctions"
|
:parameters="editingParameters"
|
:readonly="!isEditingDraft"
|
:rule="editingRule!"
|
@update:model-value="clearEditingValidation"
|
@validation="handleValidation" />
|
<a-alert v-if="formulaFunctionsError" class="formula-functions-error" :message="formulaFunctionsError" show-icon type="warning" />
|
</a-form-item>
|
<section class="draft-version-preview">
|
<div class="draft-version-preview-title">公式预览</div>
|
<div class="draft-version-preview__content">
|
<FormulaPreview :validation="editingValidation" />
|
</div>
|
</section>
|
</a-form>
|
</section>
|
<section class="draft-version-validation">
|
<div class="draft-version-trial-title">临时试算</div>
|
<div class="draft-version-trial">
|
<TrialPanel v-if="editingRule" :key="trialResetKey" :rule="editingRule" />
|
</div>
|
</section>
|
</div>
|
<section class="draft-version-parameters" :class="{ 'is-expanded': parametersExpanded }">
|
<div class="draft-version-parameters__header">
|
<span>参数槽({{ editingParameters.length }})</span>
|
<a-button data-test="toggle-parameters" type="link" @click="parametersExpanded = !parametersExpanded">
|
<span>{{ parametersExpanded ? '收起配置' : '展开配置' }}</span>
|
<DownOutlined v-if="parametersExpanded" class="parameter-toggle-icon" />
|
<UpOutlined v-else class="parameter-toggle-icon" />
|
</a-button>
|
</div>
|
<ParameterTable
|
v-if="parametersExpanded"
|
v-model="editingParameters"
|
full-height
|
:readonly="editingVersion.bizStatus !== 'DRAFT'"
|
:status="editingVersion.bizStatus" />
|
</section>
|
</div>
|
</template>
|
</BasicModal>
|
<BasicModal @register="registerReasonModal" :title="reasonModalTitle" destroy-on-close @ok="confirmReasonAction">
|
<a-alert
|
:message="reasonAction === 'cancel' ? '作废后不能恢复,也不会复用该版本号。' : `当前版本将切换为 V${reasonVersion?.banbenHao}。`"
|
show-icon
|
type="warning" />
|
<a-form-item class="reason-input" label="操作原因" required>
|
<a-textarea v-model:value="reason" :maxlength="500" :rows="4" placeholder="请输入操作原因" show-count />
|
</a-form-item>
|
</BasicModal>
|
<BasicModal @register="registerReferenceModal" force-render :show-ok-btn="false" title="全部模板引用" width="min(920px, calc(100vw - 48px))">
|
<div class="reference-modal-content">
|
<div class="reference-toolbar">
|
<a-input-search
|
v-model:value="referenceKeyword"
|
allow-clear
|
enter-button="查询"
|
placeholder="请输入模板名称或 ID"
|
@search="searchTemplateReferences" />
|
</div>
|
<div class="reference-table">
|
<BasicVxeTable @register="registerReferenceTable">
|
<template #templateName="{ record }">{{ record.templateName || '模板已不存在' }}</template>
|
<template #templateStatus="{ record }">{{ templateStatusLabel(record.templateStatus) }}</template>
|
<template #bindingStatus="{ record }">{{ bindingStatusLabel(record.bindingStatus) }}</template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
</BasicModal>
|
</BasicDrawer>
|
</template>
|
|
<style lang="scss" scoped>
|
.formula-version-content {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
min-width: 0;
|
}
|
.formula-summary {
|
flex: none;
|
padding: 16px 24px;
|
border-bottom: 1px solid var(--border-color-base);
|
}
|
.pre-release-warning {
|
margin-top: 12px;
|
}
|
.formula-references {
|
padding: 12px 24px;
|
border-bottom: 1px solid var(--border-color-base);
|
}
|
.version-table {
|
flex: 1;
|
min-height: 240px;
|
padding: 12px 24px 0;
|
}
|
.reason-input {
|
margin-top: 16px;
|
}
|
.reference-modal-content {
|
padding: 16px 24px 24px;
|
}
|
.reference-toolbar {
|
width: min(360px, 100%);
|
margin-bottom: 12px;
|
}
|
.reference-table {
|
min-height: 420px;
|
}
|
.formula-functions-error {
|
margin-top: 8px;
|
}
|
.draft-version-content {
|
display: flex;
|
flex-direction: column;
|
padding-bottom: 24px;
|
}
|
|
.draft-version-workspace {
|
display: grid;
|
flex: 1;
|
grid-template-columns: minmax(0, 13fr) minmax(320px, 7fr);
|
gap: 16px;
|
min-height: 0;
|
}
|
|
.draft-version-editor,
|
.draft-version-validation {
|
min-width: 0;
|
min-height: 0;
|
}
|
|
.draft-version-validation {
|
display: flex;
|
flex-direction: column;
|
overflow: hidden;
|
border-left: 1px solid var(--border-color-base);
|
padding-left: 16px;
|
}
|
|
.draft-version-form {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
}
|
|
.draft-version-rule-grid {
|
display: grid;
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
gap: 12px;
|
}
|
|
.draft-version-expression {
|
flex: none;
|
margin-bottom: 0;
|
}
|
|
.draft-version-preview {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
min-height: 160px;
|
margin-top: 12px;
|
}
|
|
.draft-version-preview-title {
|
flex: none;
|
min-height: 40px;
|
padding: 8px 0;
|
font-weight: 500;
|
}
|
|
.draft-version-trial-title {
|
flex: none;
|
min-height: 40px;
|
padding: 8px 0;
|
font-weight: 500;
|
}
|
|
.draft-version-preview__content,
|
.draft-version-trial {
|
flex: 1;
|
min-height: 0;
|
overflow: auto;
|
}
|
|
.draft-version-trial {
|
padding-top: 8px;
|
}
|
|
.draft-version-parameters {
|
flex: none;
|
margin-top: 12px;
|
border-top: 1px solid var(--border-color-base);
|
}
|
|
.draft-version-parameters.is-expanded {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
min-height: 0;
|
margin-top: 0;
|
border-top: 0;
|
}
|
|
.draft-version-parameters__header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
min-height: 40px;
|
font-weight: 500;
|
}
|
|
.parameter-toggle-icon {
|
margin-left: 4px;
|
}
|
|
@media (max-width: 1100px) {
|
.draft-version-content {
|
overflow: auto;
|
}
|
|
.draft-version-workspace {
|
display: block;
|
}
|
|
.draft-version-validation {
|
min-height: 360px;
|
margin-top: 16px;
|
padding-top: 12px;
|
padding-left: 0;
|
border-top: 1px solid var(--border-color-base);
|
border-left: 0;
|
}
|
|
.draft-version-preview {
|
min-height: 180px;
|
}
|
|
.draft-version-rule-grid {
|
grid-template-columns: 1fr;
|
}
|
}
|
</style>
|