Skip to content

Commit b29c2a8

Browse files
Create ModelSetting.vue
1 parent 98be8a2 commit b29c2a8

1 file changed

Lines changed: 213 additions & 0 deletions

File tree

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
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

Comments
 (0)