605 lines
21 KiB
Vue
605 lines
21 KiB
Vue
<template>
|
|
<div class="_fd-variable">
|
|
<template v-if="popover">
|
|
<el-popover ref="pop" placement="bottom" :width="330" :hide-after="0" trigger="click" :persistent="false"
|
|
popper-class="_fd-variable-pop">
|
|
<template #reference>
|
|
<i class="fc-icon icon-variable" style="cursor: pointer;"></i>
|
|
</template>
|
|
<el-container style="height: 100%;">
|
|
<el-header height="55px" class="_fd-variable-pop-header">
|
|
<el-input size="small" v-model="variable">
|
|
<template #prefix>
|
|
<span>{{</span>
|
|
</template>
|
|
<template #suffix>
|
|
}}
|
|
</template>
|
|
<template #append>
|
|
<div @click="confirm">{{ t('props.append') }}</div>
|
|
</template>
|
|
</el-input>
|
|
<i class="fc-icon icon-setting" @click="openVariableConfig"></i>
|
|
</el-header>
|
|
<el-main>
|
|
<el-tree
|
|
ref="treeRef"
|
|
:data="treeInfo"
|
|
:default-expanded-keys="expandedKeys"
|
|
:expand-on-click-node="false"
|
|
:indent="10"
|
|
node-key="id"
|
|
@nodeClick="nodeClick"
|
|
>
|
|
<template #default="{ node, data }">
|
|
<div class="_fd-variable-pop-node"
|
|
:class="{disabled: data.disabled}">
|
|
<div>
|
|
<span>{{
|
|
(data.label || '').trim() || (data.rule ? getTitle(data.rule) : data.id)
|
|
}}</span>
|
|
</div>
|
|
<span>
|
|
{{ data.id }}
|
|
</span>
|
|
</div>
|
|
</template>
|
|
</el-tree>
|
|
</el-main>
|
|
</el-container>
|
|
</el-popover>
|
|
</template>
|
|
<template v-else>
|
|
<el-badge :value="eventNum" type="warning" :hidden="eventNum < 1">
|
|
<div class="_fd-variable-btn" @click="open">
|
|
<i class="fc-icon icon-variable"></i>{{ t('computed.variable.bind') }}
|
|
</div>
|
|
</el-badge>
|
|
<el-dialog class="_fd-variable-dialog _fd-config-dialog"
|
|
v-model="visible"
|
|
destroy-on-close
|
|
:close-on-click-modal="false"
|
|
append-to-body
|
|
width="980px">
|
|
<template #header>
|
|
{{ t('computed.variable.bind') }}
|
|
<Warning :tooltip="t('warning.variable')"></Warning>
|
|
</template>
|
|
<el-container class="_fd-variable-con" style="height: 600px">
|
|
<el-main>
|
|
<el-container class="_fd-variable-l">
|
|
<el-header>
|
|
<div style="width: 230px">{{ t('computed.variable.attr') }}</div>
|
|
<div>{{ t('computed.variable.bind') }}</div>
|
|
</el-header>
|
|
<el-main>
|
|
<template v-for="(item, idx) in fields" :key="item.label">
|
|
<div class="_fd-variable-item"
|
|
:class="{active: idx === activeIdx, '_fd-variable-top': item.attach === true}">
|
|
<div class="_fd-variable-item-label">{{ item.label }}</div>
|
|
<div>=</div>
|
|
<el-input v-model="item.value" placeholder="_" @focus="activeIdx = idx"
|
|
clearable>
|
|
<template #prefix>
|
|
<span>{{</span>
|
|
</template>
|
|
<template #suffix>
|
|
}}
|
|
</template>
|
|
</el-input>
|
|
</div>
|
|
</template>
|
|
</el-main>
|
|
</el-container>
|
|
</el-main>
|
|
<el-aside style="width:328px;">
|
|
<el-container class="_fd-variable-r">
|
|
<el-header>
|
|
{{ t('computed.variable.list') }}
|
|
<i class="fc-icon icon-setting" @click="openVariableConfig"></i>
|
|
</el-header>
|
|
<el-main>
|
|
<div class="_fd-variable-info">
|
|
{{ t('warning.variableInfo') }}
|
|
</div>
|
|
<el-tree
|
|
ref="treeRef"
|
|
:data="treeInfo"
|
|
:default-expanded-keys="expandedKeys"
|
|
:expand-on-click-node="false"
|
|
node-key="id"
|
|
:indent="10"
|
|
@nodeClick="nodeClick"
|
|
>
|
|
<template #default="{ node, data }">
|
|
<div class="_fd-variable-node"
|
|
:class="{disabled: data.disabled}">
|
|
<div>
|
|
<span>{{
|
|
(data.label || '').trim() || (data.rule ? getTitle(data.rule) : data.id)
|
|
}}</span>
|
|
</div>
|
|
<span>
|
|
{{ data.id }}
|
|
</span>
|
|
</div>
|
|
</template>
|
|
</el-tree>
|
|
</el-main>
|
|
</el-container>
|
|
</el-aside>
|
|
</el-container>
|
|
<template #footer>
|
|
<div>
|
|
<el-button size="default" @click="visible=false">{{ t('props.cancel') }}</el-button>
|
|
<el-button type="primary" size="default" @click="submit">{{
|
|
t('props.ok')
|
|
}}
|
|
</el-button>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {defineComponent} from 'vue';
|
|
import {lower} from '@form-create/utils/lib/tocase';
|
|
import Warning from '../Warning.vue';
|
|
|
|
export default defineComponent({
|
|
name: 'VariableConfig',
|
|
components: {Warning},
|
|
emits: ['submit', 'confirm'],
|
|
props: {
|
|
popover: Boolean,
|
|
},
|
|
inject: ['designer'],
|
|
data() {
|
|
return {
|
|
visible: false,
|
|
activeIdx: 0,
|
|
variable: '',
|
|
value: {},
|
|
fields: [],
|
|
expandedKeys: [
|
|
'$topForm', '$cookie', '$localStorage', '$sessionStorage', '$globalData', '$var'
|
|
],
|
|
};
|
|
},
|
|
computed: {
|
|
t() {
|
|
return this.designer.setupState.t;
|
|
},
|
|
activeRule() {
|
|
return this.designer.setupState.activeRule;
|
|
},
|
|
eventNum() {
|
|
return ((this.activeRule || {})._loadData || []).length;
|
|
},
|
|
treeInfo() {
|
|
const varObj = this.toObject(this.designer.setupState.varList || []);
|
|
const tree = [
|
|
{
|
|
id: '$topForm',
|
|
label: this.t('computed.form'),
|
|
driver: true,
|
|
children: this.getFormTree(this.designer.setupState.treeInfo)
|
|
},
|
|
{
|
|
id: '$cookie',
|
|
label: 'cookie',
|
|
},
|
|
{
|
|
id: '$localStorage',
|
|
label: 'localStorage',
|
|
},
|
|
{
|
|
id: '$sessionStorage',
|
|
label: 'sessionStorage',
|
|
},
|
|
{
|
|
id: '$globalData',
|
|
label: this.t('props.globalData'),
|
|
driver: true,
|
|
children: Object.keys((this.designer.setupState.formOptions.globalData || {})).map(k => {
|
|
return {
|
|
label: this.designer.setupState.formOptions.globalData[k].label,
|
|
id: k,
|
|
}
|
|
})
|
|
},
|
|
{
|
|
id: '$var',
|
|
label: this.t('computed.variable.title'),
|
|
driver: true,
|
|
children: Object.keys((this.designer.setupState.formOptions.globalVariable || {})).map(k => {
|
|
return {
|
|
label: this.designer.setupState.formOptions.globalVariable[k].label,
|
|
id: k,
|
|
}
|
|
})
|
|
},
|
|
];
|
|
const activePage = this.designer.setupState.activePage;
|
|
if (!activePage.default && activePage.main.field && activePage.main !== this.activeRule) {
|
|
tree[0].id = '$scopeForm';
|
|
if (tree[0].children.length) {
|
|
tree[0].children = tree[0].children[0].children;
|
|
}
|
|
}
|
|
let ctx = this.activeRule?.__fc__.parent;
|
|
while (ctx) {
|
|
if (ctx.rule === activePage.main) {
|
|
ctx = undefined;
|
|
} else if (ctx.rule._menu && ['array', 'object', 'scope'].indexOf(ctx.rule._menu.subForm) > -1) {
|
|
const subTree = this.getFormTree(this.designer.setupState.findTree(ctx.rule._fc_id))
|
|
if (subTree.length) {
|
|
tree.unshift({
|
|
id: '$form',
|
|
driver: true,
|
|
label: ctx.refRule?.__$title?.value || ctx.rule.title || ctx.rule._menu.label,
|
|
children: subTree
|
|
})
|
|
}
|
|
ctx = undefined;
|
|
} else {
|
|
ctx = ctx.parent;
|
|
}
|
|
}
|
|
if (this.designer.setupState.getConfig('showLanguage') !== false) {
|
|
let lang = this.designer.setupState.formOptions?.language || {};
|
|
let language = lang[this.designer.props?.locale?.name || 'zh-cn'] || lang[Object.keys(lang)[0]] || {};
|
|
tree.push({
|
|
id: '$t',
|
|
label: this.t('language.name'),
|
|
driver: true,
|
|
children: Object.keys(language).map(k => {
|
|
return {
|
|
label: language[k],
|
|
id: k,
|
|
}
|
|
})
|
|
});
|
|
}
|
|
if (varObj['$cookie']) {
|
|
tree[1] = {...tree[1], ...varObj['$cookie']};
|
|
}
|
|
if (varObj['$localStorage']) {
|
|
tree[2] = {...tree[2], ...varObj['$localStorage']};
|
|
}
|
|
if (varObj['$sessionStorage']) {
|
|
tree[3] = {...tree[3], ...varObj['$sessionStorage']};
|
|
}
|
|
if (varObj['$globalData'] && varObj['$globalData'].children) {
|
|
tree[4].children = Object.values({...this.toObject(tree[4].children), ...this.toObject(varObj['$globalData'].children || [])});
|
|
}
|
|
if (varObj['$var'] && varObj['$var'].children) {
|
|
tree[5].children = Object.values({...this.toObject(tree[5].children), ...this.toObject(varObj['$var'].children || [])});
|
|
}
|
|
|
|
delete varObj['$cookie'];
|
|
delete varObj['$localStorage'];
|
|
delete varObj['$sessionStorage'];
|
|
delete varObj['$globalData'];
|
|
delete varObj['$var'];
|
|
tree.push(...Object.values(varObj));
|
|
return tree;
|
|
}
|
|
},
|
|
watch: {
|
|
visible(v) {
|
|
if (v) {
|
|
this.updateFields();
|
|
this.activeIdx = 0;
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
openVariableConfig() {
|
|
this.designer.setupState.openGlobalVariableDialog();
|
|
},
|
|
toObject(list) {
|
|
const data = {};
|
|
list && list.forEach(item => {
|
|
data[item.id] = item;
|
|
})
|
|
|
|
return data;
|
|
},
|
|
nodeClick(data, node) {
|
|
if ((this.popover || this.fields[this.activeIdx]) && !data.driver) {
|
|
let val = data.id;
|
|
node = node.parent;
|
|
while (node.level >= 1) {
|
|
val = (node.data.id) + '.' + val;
|
|
node = node.parent;
|
|
}
|
|
if (this.popover) {
|
|
this.variable = val;
|
|
} else {
|
|
this.fields[this.activeIdx].value = val;
|
|
}
|
|
}
|
|
},
|
|
getTitle(rule) {
|
|
return (rule?.__fc__?.refRule?.__$title?.value || rule.title || '').trim() || (rule._menu && rule._menu.label) || rule.field || rule._fc_id;
|
|
},
|
|
getFormTree(children) {
|
|
const fields = [];
|
|
children.forEach(({rule, children}) => {
|
|
const childrenFields = (rule.field && (!rule._menu || rule._menu.subForm !== 'object')) ? [] : this.getFormTree(children || []);
|
|
if (rule.field) {
|
|
const item = {
|
|
id: rule.field,
|
|
label: rule?.__fc__?.refRule?.__$title?.value || rule.title,
|
|
rule,
|
|
};
|
|
if (childrenFields.length) {
|
|
item.children = childrenFields;
|
|
}
|
|
fields.push(item);
|
|
} else {
|
|
fields.push(...childrenFields)
|
|
}
|
|
});
|
|
return fields;
|
|
},
|
|
tranField(str) {
|
|
if (str.indexOf('formCreate') === 0) {
|
|
str = lower(str.replace('formCreate', ''));
|
|
} else {
|
|
str = 'props.' + str;
|
|
}
|
|
return str.replaceAll('>', '.');
|
|
},
|
|
updateFields() {
|
|
const vm = this.designer.setupState;
|
|
const fields = [];
|
|
const loadData = {};
|
|
(vm.activeRule._loadData || []).forEach(item => {
|
|
loadData[item.to] = item.attr;
|
|
});
|
|
const important = [];
|
|
if (vm.activeRule.field) {
|
|
important.push({
|
|
label: this.t('computed.value.name'),
|
|
attach: true,
|
|
modify: true,
|
|
field: 'value'
|
|
});
|
|
}
|
|
const rules = vm.propsForm.api.model();
|
|
Object.keys(rules).forEach(k => {
|
|
if (k && (k[0] !== '_' || rules[k]._fc_important_prop) && rules[k].title && rules[k]._fc_important_prop !== false && !rules[k].hidden && false !== rules[k].display) {
|
|
const prop = typeof rules[k]._fc_important_prop === 'string' ? rules[k]._fc_important_prop : k;
|
|
(rules[k]._fc_important_prop === true ? important : fields).push({
|
|
label: rules[k].title,
|
|
modify: prop === 'formCreateChild',
|
|
field: this.tranField(prop)
|
|
})
|
|
}
|
|
});
|
|
fields.unshift(...important);
|
|
fields.forEach(item => {
|
|
item.value = loadData[item.field] || '';
|
|
});
|
|
|
|
this.fields = fields;
|
|
},
|
|
open() {
|
|
this.visible = true;
|
|
},
|
|
active(idx) {
|
|
if (this.activeIdx !== idx) {
|
|
this.activeIdx = idx;
|
|
}
|
|
},
|
|
submit() {
|
|
const loadData = [];
|
|
this.fields.forEach(item => {
|
|
let val = (item.value || '').trim();
|
|
if (val) {
|
|
const data = {
|
|
attr: val,
|
|
to: item.field
|
|
};
|
|
if (item.modify) {
|
|
data.modify = true;
|
|
}
|
|
loadData.push(data);
|
|
}
|
|
});
|
|
this.designer.setupState.activeRule._loadData = loadData;
|
|
this.visible = false;
|
|
},
|
|
confirm() {
|
|
const val = (this.variable || '').trim();
|
|
if (val) {
|
|
this.$emit('confirm', `{{${val}}}`);
|
|
this.$refs.pop.hide();
|
|
this.variable = '';
|
|
}
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
._fd-variable-btn {
|
|
margin-left: 6px;
|
|
background: var(--fc-style-bg-color-1);
|
|
border-radius: 5px;
|
|
color: var(--fc-style-color-1);
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 12px;
|
|
padding: 2px 6px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
._fd-variable-con .el-main {
|
|
padding: 0;
|
|
}
|
|
|
|
._fd-variable-l, ._fd-variable-r {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
height: 100%;
|
|
border: 1px solid var(--fc-line-color-3);
|
|
}
|
|
|
|
._fd-variable-r {
|
|
margin-left: 10px;
|
|
}
|
|
|
|
._fd-variable-l .el-header, ._fd-variable-r .el-header {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 40px;
|
|
background: var(--fc-bg-color-3);
|
|
color: var(--fc-text-color-1);
|
|
font-size: 13px;
|
|
}
|
|
|
|
._fd-variable-r .el-header .fc-icon {
|
|
font-size: 13px;
|
|
margin-left: 2px;
|
|
color: var(--fc-style-color-1);
|
|
cursor: pointer;
|
|
}
|
|
|
|
._fd-variable-r .el-main {
|
|
padding: 10px;
|
|
}
|
|
|
|
._fd-variable-info {
|
|
display: flex;
|
|
font-size: 12px;
|
|
position: relative;
|
|
margin-bottom: 6px;
|
|
padding: 8px 13px;
|
|
line-height: 18px;
|
|
background: rgba(170, 170, 170, 0.1);
|
|
border-radius: 6px;
|
|
color: var(--fc-text-color-2);
|
|
}
|
|
|
|
._fd-variable-node {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
width: 100%;
|
|
height: 26px;
|
|
line-height: 26px;
|
|
padding-right: 5px;
|
|
font-size: 13px;
|
|
color: var(--fc-text-color-1);
|
|
}
|
|
|
|
._fd-variable-node > span {
|
|
color: var(--fc-text-color-3);
|
|
font-size: 12px;
|
|
}
|
|
|
|
._fd-variable-item {
|
|
display: flex;
|
|
align-items: center;
|
|
min-height: 40px;
|
|
padding: 0 20px;
|
|
border-bottom: 1px solid var(--fc-line-color-3);;
|
|
}
|
|
|
|
._fd-variable-top ._fd-variable-item-label {
|
|
color: #fca130;
|
|
}
|
|
|
|
._fd-variable-item-label {
|
|
width: 198px;
|
|
margin-right: 18px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
._fd-variable-item .el-input {
|
|
display: flex;
|
|
flex: 1;
|
|
margin-top: 4px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
._fd-variable-item.active, ._fd-variable-item.active ._fd-variable-item-label, ._fd-variable-item.active input {
|
|
color: var(--fc-style-color-1);
|
|
}
|
|
|
|
._fd-variable-item.active .el-input {
|
|
--el-input-icon-color: var(--fc-style-color-1);
|
|
}
|
|
|
|
._fd-variable-item input {
|
|
text-align: center;
|
|
}
|
|
|
|
._fd-variable-item .el-input .el-input__wrapper {
|
|
box-shadow: none;
|
|
}
|
|
|
|
._fd-variable-pop.el-popover.el-popper {
|
|
height: 400px;
|
|
padding: 0;
|
|
}
|
|
|
|
._fd-variable-pop-header .fc-icon {
|
|
color: var(--fc-style-color-1);
|
|
margin-left: 4px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
._fd-variable-pop .el-header {
|
|
display: flex;
|
|
align-items: center;
|
|
border-bottom: 1px solid var(--fc-line-color-3);
|
|
padding: 0 10px;
|
|
background-color: var(--fc-bg-color-2)
|
|
}
|
|
|
|
._fd-variable-pop .el-main {
|
|
padding: 10px;
|
|
}
|
|
|
|
._fd-variable-pop .el-tree-node__content > .el-tree-node__expand-icon {
|
|
padding: 3px;
|
|
}
|
|
|
|
._fd-variable-pop .el-input-group__append {
|
|
background: var(--fc-style-color-1);
|
|
color: #FFFFFF;
|
|
cursor: pointer;
|
|
width: 60px;
|
|
padding: 0;
|
|
}
|
|
|
|
._fd-variable-pop .el-input-group__append div {
|
|
width: 100%;
|
|
text-align: center;
|
|
}
|
|
|
|
._fd-variable-pop-node {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
width: 100%;
|
|
height: 26px;
|
|
line-height: 26px;
|
|
padding-right: 5px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
._fd-variable-pop-node > span {
|
|
color: var(--fc-text-color-3);
|
|
font-size: 12px;
|
|
}
|
|
|
|
</style>
|