|
| 1 | +<template> |
| 2 | + <plugin-setting |
| 3 | + v-if="isShow" |
| 4 | + :fixed-name="PLUGIN_NAME.ModelManager" |
| 5 | + :align="align" |
| 6 | + title="模型设置" |
| 7 | + class="modelmanager-plugin-setting" |
| 8 | + > |
| 9 | + <template #header> |
| 10 | + <button-group> |
| 11 | + <tiny-button @click="$emit('exportModel', selectedModel?.id)">导出SQL</tiny-button> |
| 12 | + <tiny-button type="primary" @click="saveModel">保存</tiny-button> |
| 13 | + <svg-button name="close" @click="closeModelSettingPanel"></svg-button> |
| 14 | + </button-group> |
| 15 | + </template> |
| 16 | + |
| 17 | + <template #content> |
| 18 | + <tiny-collapse v-model="activeName" class="page-setting-collapse"> |
| 19 | + <tiny-collapse-item title="基本设置" name="general"> |
| 20 | + <model-basic-form ref="modelBasicFormRef" :model="selectedModel"></model-basic-form> |
| 21 | + </tiny-collapse-item> |
| 22 | + |
| 23 | + <tiny-collapse-item class="base-setting" title="字段管理" name="fields"> |
| 24 | + <field-manager |
| 25 | + ref="fieldManagerRef" |
| 26 | + :model="selectedModel" |
| 27 | + :expand-config="expandConfig" |
| 28 | + :available-models="models" |
| 29 | + @add-field="handleAddField" |
| 30 | + @insert-enum-after="insertEnumValueAfter" |
| 31 | + @remove-enum="removeEnumValue" |
| 32 | + > |
| 33 | + </field-manager> |
| 34 | + </tiny-collapse-item> |
| 35 | + </tiny-collapse> |
| 36 | + </template> |
| 37 | + </plugin-setting> |
| 38 | +</template> |
| 39 | +<script> |
| 40 | +import { ref, watch, nextTick } from 'vue' |
| 41 | +import { Button, Collapse, CollapseItem } from '@opentiny/vue' |
| 42 | +import { PluginSetting, ButtonGroup, SvgButton } from '@opentiny/tiny-engine-common' |
| 43 | +import { useLayout } from '@opentiny/tiny-engine-meta-register' |
| 44 | +import ModelBasicForm from './ModelBasicForm.vue' |
| 45 | +import FieldManager from './FieldManager.vue' |
| 46 | +import { createModel, updateModel } from '../composable/useModelManager' |
| 47 | +
|
| 48 | +const isShow = ref(false) |
| 49 | +
|
| 50 | +export const openModelSettingPanel = () => { |
| 51 | + isShow.value = true |
| 52 | +} |
| 53 | +
|
| 54 | +export const closeModelSettingPanel = () => { |
| 55 | + isShow.value = false |
| 56 | +} |
| 57 | +
|
| 58 | +export default { |
| 59 | + components: { |
| 60 | + PluginSetting, |
| 61 | + SvgButton, |
| 62 | + ButtonGroup, |
| 63 | + ModelBasicForm, |
| 64 | + FieldManager, |
| 65 | + TinyButton: Button, |
| 66 | + TinyCollapse: Collapse, |
| 67 | + TinyCollapseItem: CollapseItem |
| 68 | + }, |
| 69 | + props: { |
| 70 | + model: { |
| 71 | + type: Object, |
| 72 | + default: () => ({}) |
| 73 | + }, |
| 74 | + models: { |
| 75 | + type: Array, |
| 76 | + default: () => [] |
| 77 | + } |
| 78 | + }, |
| 79 | + emits: ['editCallback', 'exportModel'], |
| 80 | + setup(props, { emit }) { |
| 81 | + const { PLUGIN_NAME } = useLayout() |
| 82 | + const activeName = ref(['general', 'fields']) |
| 83 | + const selectedModel = ref() |
| 84 | + const modelBasicFormRef = ref() |
| 85 | + // 展开行配置 |
| 86 | + const expandConfig = ref({ |
| 87 | + expandAll: false, |
| 88 | + trigger: 'row', |
| 89 | + expandRowKeys: [], |
| 90 | + accordion: false, |
| 91 | + activeMethod: (row) => row.type === 'Enum' || row.type === 'ModelRef', // 枚举类型和模型引用类型都显示展开箭头 |
| 92 | + showIcon: (row) => row.type === 'Enum' || row.type === 'ModelRef' // 枚举类型和模型引用类型都显示展开箭头 |
| 93 | + }) |
| 94 | +
|
| 95 | + // 添加字段,自动进入编辑状态 |
| 96 | + const handleAddField = () => { |
| 97 | + if (!selectedModel.value) return |
| 98 | + const newField = { |
| 99 | + prop: '', |
| 100 | + type: 'String', |
| 101 | + required: false, |
| 102 | + description: '', |
| 103 | + isEditing: true, |
| 104 | + isNew: true // 新增字段标记 |
| 105 | + } |
| 106 | + selectedModel.value.parameters.push(newField) |
| 107 | + nextTick(() => { |
| 108 | + const nameInputs = document.querySelectorAll('.editing-cell .tiny-input') |
| 109 | + if (nameInputs.length > 0) nameInputs[nameInputs.length - 1].focus() |
| 110 | + }) |
| 111 | + } |
| 112 | +
|
| 113 | + // 在当前行后插入一条枚举值 |
| 114 | + const insertEnumValueAfter = (field, index) => { |
| 115 | + if (!field.options) { |
| 116 | + field.options = [] |
| 117 | + } |
| 118 | + field.options.splice(index + 1, 0, { value: '', label: '' }) |
| 119 | + } |
| 120 | +
|
| 121 | + // 删除枚举值 |
| 122 | + const removeEnumValue = (field, index) => { |
| 123 | + if (!Array.isArray(field.options)) return |
| 124 | + if (field.options.length <= 1) { |
| 125 | + // 只剩一条时,不删除,清空内容 |
| 126 | + field.options[0] = { value: '', label: '' } |
| 127 | + return |
| 128 | + } |
| 129 | + field.options.splice(index, 1) |
| 130 | + } |
| 131 | +
|
| 132 | + // 保存模型时一并保存version字段 |
| 133 | + const saveModel = async () => { |
| 134 | + // 从子组件获取最新的数据 |
| 135 | + const latestModelData = modelBasicFormRef.value?.getLocalValue() |
| 136 | + modelBasicFormRef.value.validate().then(async (valid) => { |
| 137 | + if (valid) { |
| 138 | + const newModel = { |
| 139 | + description: latestModelData.description, |
| 140 | + modelUrl: latestModelData.modelUrl, |
| 141 | + nameCn: latestModelData.nameCn, |
| 142 | + nameEn: latestModelData.nameEn, |
| 143 | + version: latestModelData.version, |
| 144 | + id: latestModelData.id, |
| 145 | + parameters: latestModelData.parameters.filter((item) => !!item.prop) |
| 146 | + } |
| 147 | + let isModelRefRelative = true |
| 148 | + let propertyName = '' |
| 149 | + if (newModel.parameters?.length > 0) { |
| 150 | + newModel.parameters.forEach((item) => { |
| 151 | + if (item.type === 'Enum') { |
| 152 | + item.options = JSON.stringify(item.options) |
| 153 | + } |
| 154 | + if (item.type === 'ModelRef') { |
| 155 | + item.isModel = true |
| 156 | + delete item.options |
| 157 | + item.defaultValue = item.defaultValue || null |
| 158 | + isModelRefRelative = !!item.defaultValue |
| 159 | + propertyName = item.prop |
| 160 | + } |
| 161 | + }) |
| 162 | + } |
| 163 | + if (!isModelRefRelative) { |
| 164 | + Notify({ |
| 165 | + type: 'error', |
| 166 | + message: `字段${propertyName}未关联模型引用` |
| 167 | + }) |
| 168 | + return |
| 169 | + } |
| 170 | + if (latestModelData.id === null) { |
| 171 | + delete newModel.id |
| 172 | + await createModel(newModel) |
| 173 | + } else { |
| 174 | + await updateModel(newModel.id, newModel) |
| 175 | + } |
| 176 | + emit('editCallback') |
| 177 | + Notify({ |
| 178 | + type: 'success', |
| 179 | + message: '保存成功' |
| 180 | + }) |
| 181 | + selectedModel.value = null |
| 182 | + } |
| 183 | + }) |
| 184 | + } |
| 185 | + // 监听 props 变化,同步到本地(当选择不同模型时) |
| 186 | + watch( |
| 187 | + () => props.model, |
| 188 | + (newModel) => { |
| 189 | + selectedModel.value = newModel |
| 190 | + }, |
| 191 | + { deep: true } |
| 192 | + ) |
| 193 | + return { |
| 194 | + isShow, |
| 195 | + PLUGIN_NAME, |
| 196 | + activeName, |
| 197 | + modelBasicFormRef, |
| 198 | + expandConfig, |
| 199 | + selectedModel, |
| 200 | + closeModelSettingPanel, |
| 201 | + handleAddField, |
| 202 | + insertEnumValueAfter, |
| 203 | + removeEnumValue, |
| 204 | + saveModel |
| 205 | + } |
| 206 | + } |
| 207 | +} |
| 208 | +</script> |
| 209 | +<style lang="less" scoped> |
| 210 | +:deep(.plugin-setting) { |
| 211 | + width: fit-content !important; |
| 212 | +} |
| 213 | +</style> |
0 commit comments