|
|
@@ -0,0 +1,396 @@
|
|
|
+<route lang="yaml">
|
|
|
+meta:
|
|
|
+ enabled: false
|
|
|
+</route>
|
|
|
+
|
|
|
+<script lang="ts" setup name="bizObjectEdit">
|
|
|
+import Sortable from 'sortablejs'
|
|
|
+import type { FormInstance, FormRules } from 'element-plus'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import { createObject, getObjectById, updateObject } from '@/api/biz/bizObjectApi'
|
|
|
+import useSettingsStore from '@/store/modules/settings'
|
|
|
+
|
|
|
+const settingsStore = useSettingsStore()
|
|
|
+const route = useRoute()
|
|
|
+const bizId = parseInt(route.params.bizId.toString())
|
|
|
+const objectId = parseInt(route.params.objectId.toString())
|
|
|
+const router = useRouter()
|
|
|
+const tabbar = useTabbar()
|
|
|
+
|
|
|
+interface ObjectAttr {
|
|
|
+ attrId: number
|
|
|
+ attrTitle: string
|
|
|
+ attrCode: string
|
|
|
+ attrType: number
|
|
|
+ attrLength: number
|
|
|
+ attrDecimals: number
|
|
|
+ isNotNull: number
|
|
|
+ comment: string
|
|
|
+ sortNo: number
|
|
|
+}
|
|
|
+
|
|
|
+const dataType = [
|
|
|
+ { dataType: 1, dataName: '整数' },
|
|
|
+ { dataType: 2, dataName: '字符串' },
|
|
|
+ { dataType: 3, dataName: '小数' }]
|
|
|
+
|
|
|
+// 数据
|
|
|
+const state = reactive({
|
|
|
+ title: '',
|
|
|
+ dialogVisible: false,
|
|
|
+ loading: false,
|
|
|
+ search: {
|
|
|
+ keywords: '',
|
|
|
+ },
|
|
|
+ formData: {
|
|
|
+ bizId,
|
|
|
+ objectId,
|
|
|
+ objectType: 1,
|
|
|
+ objectCode: '',
|
|
|
+ objectTitle: '',
|
|
|
+ comment: '',
|
|
|
+ attrs: [] as ObjectAttr[],
|
|
|
+ },
|
|
|
+ actionType: 1,
|
|
|
+})
|
|
|
+
|
|
|
+const formRef = ref<FormInstance>()
|
|
|
+const formRules = reactive<FormRules>({
|
|
|
+ objectTitle: [
|
|
|
+ { required: true, message: '请输入对象标题', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ objectType: [
|
|
|
+ { required: true, message: '请输入对象类型', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ objectCode: [
|
|
|
+ { required: true, message: '请输入对像代码', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ comment: [
|
|
|
+ { required: false, message: '请输入简要描述', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+})
|
|
|
+
|
|
|
+// 查询数据
|
|
|
+const getData = async () => {
|
|
|
+ state.loading = true
|
|
|
+ const { data } = await getObjectById(bizId, objectId)
|
|
|
+ state.loading = false
|
|
|
+ state.formData = data
|
|
|
+}
|
|
|
+
|
|
|
+const attrsTableRef = ref()
|
|
|
+const attrsTableKey = ref(0)
|
|
|
+function onAttrAdd() {
|
|
|
+ state.formData.attrs.push({
|
|
|
+ attrId: 0,
|
|
|
+ attrTitle: '', // 名称
|
|
|
+ attrCode: '', // 代码
|
|
|
+ attrType: 0, // 类型
|
|
|
+ attrLength: 0, // 长度
|
|
|
+ attrDecimals: 0, // 小数位数
|
|
|
+ isNotNull: 0, // 是否为空
|
|
|
+ comment: '', // 注释
|
|
|
+ sortNo: 0,
|
|
|
+ })
|
|
|
+ nextTick(() => {
|
|
|
+ attrsTableRef.value.setScrollTop(state.formData.attrs.length * 50)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 删除属性
|
|
|
+function onAttrDelete(index: number) {
|
|
|
+ state.formData.attrs.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+function onAttrDrag() {
|
|
|
+ const tbody = attrsTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
|
|
|
+ Sortable.create(tbody, {
|
|
|
+ handle: '.sortable',
|
|
|
+ animation: 300,
|
|
|
+ ghostClass: 'ghost',
|
|
|
+ onEnd: ({ newIndex, oldIndex }) => {
|
|
|
+ if (newIndex === undefined || oldIndex === undefined) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const currRow = state.formData.attrs.splice(oldIndex, 1)[0]
|
|
|
+ state.formData.attrs.splice(newIndex, 0, currRow)
|
|
|
+ attrsTableKey.value += 1
|
|
|
+ nextTick(() => onAttrDrag())
|
|
|
+ },
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ if (objectId <= 0) {
|
|
|
+ state.title = '新增对象'
|
|
|
+ state.actionType = 1
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ state.title = '编辑对象'
|
|
|
+ state.actionType = 2
|
|
|
+ getData()
|
|
|
+ }
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ onAttrDrag()
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+// 保存
|
|
|
+function onSubmit() {
|
|
|
+ formRef.value && formRef.value.validate(async (valid) => {
|
|
|
+ if (valid) {
|
|
|
+ state.formData.attrs.forEach((item, index) => item.sortNo = index)
|
|
|
+ if (state.actionType === 1) {
|
|
|
+ await createObject(state.formData)
|
|
|
+ state.dialogVisible = false
|
|
|
+ ElMessage.success('新增成功')
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ await updateObject(state.formData)
|
|
|
+ state.dialogVisible = false
|
|
|
+ ElMessage.success('修改成功')
|
|
|
+ }
|
|
|
+ goBack()
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function onCancel() {
|
|
|
+ goBack()
|
|
|
+}
|
|
|
+
|
|
|
+// 返回列表页
|
|
|
+function goBack() {
|
|
|
+ if (settingsStore.settings.tabbar.enable && settingsStore.settings.tabbar.mergeTabsBy !== 'activeMenu') {
|
|
|
+ tabbar.close({ name: 'model' })
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ router.push({ name: 'model' })
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="absolute-container">
|
|
|
+ <page-header title="对象" content="创建元数据对象。">
|
|
|
+ <el-button size="default" round @click="goBack">
|
|
|
+ <template #icon>
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:arrow-left" />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ 返回
|
|
|
+ </el-button>
|
|
|
+ </page-header>
|
|
|
+
|
|
|
+ <div class="page-main">
|
|
|
+ <LayoutContainer hide-left-side-toggle>
|
|
|
+ <template #leftSide>
|
|
|
+ <h2>基本信息</h2>
|
|
|
+ <el-scrollbar class="form-el-scrollbar">
|
|
|
+ <div class="form-content">
|
|
|
+ <el-form ref="formRef" :model="state.formData" :rules="formRules" label-position="top">
|
|
|
+ <el-form-item label="对象名称" prop="objectTitle">
|
|
|
+ <el-input v-model="state.formData.objectTitle" placeholder="请输入标题" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="类型" prop="objectType">
|
|
|
+ <el-radio-group v-model="state.formData.objectType">
|
|
|
+ <el-radio :label="1">
|
|
|
+ 实体对象
|
|
|
+ </el-radio>
|
|
|
+ <el-radio :label="2">
|
|
|
+ 视图对象
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="对象代码" prop="objectCode">
|
|
|
+ <el-input v-model="state.formData.objectCode" placeholder="请输入代码" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="简要说明" prop="comment">
|
|
|
+ <el-input v-model="state.formData.comment" type="textarea" rows="10" placeholder="请输入标题" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="container">
|
|
|
+ <tool-bar>
|
|
|
+ <template #left>
|
|
|
+ <h2>属性</h2>
|
|
|
+ </template>
|
|
|
+ <template #right>
|
|
|
+ <el-input v-model="state.search.keywords" placeholder="请输入关键词筛选字典项" clearable style="width: 200px;" />
|
|
|
+ <el-button style="margin-left:10px" @click="getData">
|
|
|
+ <template #icon>
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:search" />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+
|
|
|
+ <el-button type="primary" @click="onAttrAdd">
|
|
|
+ <template #icon>
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:plus" />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </tool-bar>
|
|
|
+
|
|
|
+ <el-table ref="attrsTableRef" :key="attrsTableKey" :data="state.formData.attrs" class="list-table" border stripe highlight-current-row>
|
|
|
+ <el-table-column width="60" align="center" fixed>
|
|
|
+ <template #header>
|
|
|
+ <el-button type="primary" size="small" plain circle @click="onAttrAdd">
|
|
|
+ <template #icon>
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:plus" />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #default="scope">
|
|
|
+ <span class="index">{{ scope.$index + 1 }}</span>
|
|
|
+ <el-button type="danger" size="small" plain circle class="delete" @click="onAttrDelete(scope.$index)">
|
|
|
+ <template #icon>
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:delete" />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="名称" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input v-model="scope.row.attrTitle" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="代码" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input v-model="scope.row.attrCode" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="类型" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-select v-model="scope.row.attrType">
|
|
|
+ <el-option
|
|
|
+ v-for="item in dataType"
|
|
|
+ :key="item.dataType"
|
|
|
+ :value="item.dataType"
|
|
|
+ :label="item.dataName"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="长度" width="90">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input v-model="scope.row.attrLength" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="小数位数" width="90">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input v-model="scope.row.attrDecimals" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="是否为空" width="90">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-checkbox v-model="scope.row.isNotNull" :true-label="1" :false-label="0">
|
|
|
+ {{ scope.row.isNotNull === 1 ? '是' : '否' }}
|
|
|
+ </el-checkbox>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="注释">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-input v-model="scope.row.comment" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
+ <template #header>
|
|
|
+ 排序
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <el-tag type="info" class="sortable">
|
|
|
+ <el-icon>
|
|
|
+ <svg-icon name="i-ep:d-caret" />
|
|
|
+ </el-icon>
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </LayoutContainer>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <fixed-action-bar>
|
|
|
+ <el-button type="primary" size="large" @click="onSubmit">
|
|
|
+ 保存
|
|
|
+ </el-button>
|
|
|
+ <el-button size="large" @click="onCancel">
|
|
|
+ 取消
|
|
|
+ </el-button>
|
|
|
+ </fixed-action-bar>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.page-header {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.page-main {
|
|
|
+ :deep(.left-side) {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
+ .form-el-scrollbar{
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ :deep(.el-table) {
|
|
|
+ height: 100%;
|
|
|
+
|
|
|
+ .el-table__row {
|
|
|
+ .index {
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .delete {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ .index {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .delete {
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tag.sortable,
|
|
|
+ .el-tag.sortable .el-icon {
|
|
|
+ cursor: s-resize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ h2{
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|