update:分级标准tab完成
Showing
11 changed files
with
1110 additions
and
692 deletions
| ... | @@ -3,7 +3,8 @@ VITE_APP_TITLE = 数据资产管理系统 | ... | @@ -3,7 +3,8 @@ VITE_APP_TITLE = 数据资产管理系统 |
| 3 | # 接口域名 | 3 | # 接口域名 |
| 4 | # VITE_API_BASEURL = https://www.zgsjzc.com/api | 4 | # VITE_API_BASEURL = https://www.zgsjzc.com/api |
| 5 | # VITE_API_BASEURL = https://swzl-test.csbr.cn/api | 5 | # VITE_API_BASEURL = https://swzl-test.csbr.cn/api |
| 6 | VITE_API_BASEURL = http://10.4.82.30:8052/ | 6 | # VITE_API_BASEURL = http://10.4.82.30:8052/ |
| 7 | VITE_API_BASEURL = http://10.4.82.1:28052/ | ||
| 7 | # 平台用户 接口请地址 | 8 | # 平台用户 接口请地址 |
| 8 | VITE_APP_USER_API_BASEURL = gateway-server/user | 9 | VITE_APP_USER_API_BASEURL = gateway-server/user |
| 9 | # 系统管理 接口地址 | 10 | # 系统管理 接口地址 | ... | ... |
| ... | @@ -54,6 +54,7 @@ declare module '@vue/runtime-core' { | ... | @@ -54,6 +54,7 @@ declare module '@vue/runtime-core' { |
| 54 | Table_tools: typeof import('./src/components/Tools/table_tools.vue')['default'] | 54 | Table_tools: typeof import('./src/components/Tools/table_tools.vue')['default'] |
| 55 | Table_v2: typeof import('./src/components/Table/table_v2.vue')['default'] | 55 | Table_v2: typeof import('./src/components/Table/table_v2.vue')['default'] |
| 56 | Tabs: typeof import('./src/components/Tabs/index.vue')['default'] | 56 | Tabs: typeof import('./src/components/Tabs/index.vue')['default'] |
| 57 | TemplateItem: typeof import('./src/components/TemplateItem/index.vue')['default'] | ||
| 57 | Toolbar: typeof import('./src/components/LineageGraph/toolbar.vue')['default'] | 58 | Toolbar: typeof import('./src/components/LineageGraph/toolbar.vue')['default'] |
| 58 | Topbar: typeof import('./src/components/LineageGraph/topbar.vue')['default'] | 59 | Topbar: typeof import('./src/components/LineageGraph/topbar.vue')['default'] |
| 59 | Transfer: typeof import('./src/components/Transfer/index.vue')['default'] | 60 | Transfer: typeof import('./src/components/Transfer/index.vue')['default'] | ... | ... |
| 1 | import request from "@/utils/request"; | 1 | import request from "@/utils/request"; |
| 2 | 2 | ||
| 3 | |||
| 4 | /** | ||
| 5 | * 获取数据级别 | ||
| 6 | * @param {Object} | ||
| 7 | * { paramCode: "DATA-CLASSIFY" } | ||
| 8 | * DATA-CLASSIFY 数据类别 | ||
| 9 | * DATA-GRADE 数据级别 | ||
| 10 | */ | ||
| 11 | export const getLargeCategoryList = (data) => request({ | ||
| 12 | url:`${import.meta.env.VITE_APP_API_BASEURL}/data-dict/get-data-list`, | ||
| 13 | method: 'post', | ||
| 14 | data | ||
| 15 | }) | ||
| 16 | |||
| 17 | |||
| 3 | /** 分类分级模板数据 */ | 18 | /** 分类分级模板数据 */ |
| 4 | export const getTempleteClassifyData = (data) => request({ | 19 | export const getTempleteClassifyData = (data) => request({ |
| 5 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/cg-template/page-list`, | 20 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/cg-template/page-list`, |
| 6 | method: 'post', | 21 | method: 'post', |
| 7 | data | 22 | data |
| 8 | }) | 23 | }) |
| 24 | |||
| 25 | |||
| 26 | /** 新增分级 | ||
| 27 | * | ||
| 28 | * @param {Object} | ||
| 29 | * @path /classify-grade/save | ||
| 30 | */ | ||
| 31 | |||
| 32 | export const saveClassifyGrad = (data) => request({ | ||
| 33 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/classify-grade/save`, | ||
| 34 | method: 'post', | ||
| 35 | data | ||
| 36 | }) | ||
| 37 | |||
| 38 | /** 删除分级 | ||
| 39 | * @param {Object} | ||
| 40 | * @path /classify-grade/delete | ||
| 41 | * */ | ||
| 42 | |||
| 43 | export const deleteClassifyGrad = (data) => request({ | ||
| 44 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/classify-grade/delete`, | ||
| 45 | method: 'delete', | ||
| 46 | headers: { | ||
| 47 | 'Content-Type': 'multipart/form-data', | ||
| 48 | }, | ||
| 49 | data | ||
| 50 | }) | ||
| 51 | /** 修改分级 | ||
| 52 | * @param {Object} | ||
| 53 | * @path /classify-grade/update | ||
| 54 | * */ | ||
| 55 | |||
| 56 | export const updateClassifyGrad = (data) => request({ | ||
| 57 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/classify-grade/update`, | ||
| 58 | method: 'post', | ||
| 59 | data | ||
| 60 | }) | ||
| 61 | |||
| 62 | |||
| 63 | /** | ||
| 64 | * 分级列表 | ||
| 65 | * @param {Object} | ||
| 66 | * @path /classify-grade/page-list | ||
| 67 | */ | ||
| 68 | |||
| 69 | export const getClassifyGradList = (data) => request({ | ||
| 70 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/classify-grade/page-list`, | ||
| 71 | method: 'post', | ||
| 72 | data | ||
| 73 | }) | ||
| 74 | |||
| 75 | |||
| 76 | /** | ||
| 77 | * 分级新增 | ||
| 78 | * @param {Object} | ||
| 79 | * @path /grade/save | ||
| 80 | */ | ||
| 81 | export const saveGrade = (data) => request({ | ||
| 82 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/grade/save`, | ||
| 83 | method: 'post', | ||
| 84 | data | ||
| 85 | }) | ||
| 86 | |||
| 87 | /** | ||
| 88 | * 分级更新 | ||
| 89 | * @param {Object} | ||
| 90 | * @path /grade/update | ||
| 91 | * */ | ||
| 92 | export const updateGrade = (data) => request({ | ||
| 93 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/grade/update`, | ||
| 94 | method: 'post', | ||
| 95 | data | ||
| 96 | }) | ||
| 97 | |||
| 98 | /** | ||
| 99 | * 分级列表 | ||
| 100 | * @param {Object} | ||
| 101 | * @path /grade/page-list | ||
| 102 | */ | ||
| 103 | export const getGradeList = (data) => request({ | ||
| 104 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/grade/page-list`, | ||
| 105 | method: 'post', | ||
| 106 | data | ||
| 107 | }) | ||
| 108 | |||
| 109 | /** | ||
| 110 | * 批量删除分级 | ||
| 111 | * @param {Array} | ||
| 112 | * @path /grade/delete | ||
| 113 | * */ | ||
| 114 | export const deleteGrade = (data) => request({ | ||
| 115 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/grade/delete`, | ||
| 116 | method: 'delete', | ||
| 117 | data | ||
| 118 | }) | ||
| 119 | |||
| 120 | |||
| 121 | /*---------------------------------分类标准 tab -----------------------------*/ | ||
| 122 | |||
| 123 | /** | ||
| 124 | * 分级树形结构 | ||
| 125 | * @param no params | ||
| 126 | * @path /grade/tree-list | ||
| 127 | */ | ||
| 128 | export const getGradeTreeList = () => request({ | ||
| 129 | url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/grade/tree-list`, | ||
| 130 | method: 'post', | ||
| 131 | }) | ... | ... |
| ... | @@ -46,8 +46,13 @@ export const getImageUrl = (params) => request({ | ... | @@ -46,8 +46,13 @@ export const getImageUrl = (params) => request({ |
| 46 | }) | 46 | }) |
| 47 | 47 | ||
| 48 | /** 查看图片 */ | 48 | /** 查看图片 */ |
| 49 | // export const getImageContent = (params) => request({ | ||
| 50 | // url: `${import.meta.env.VITE_APP_API_BASEURL}/obs/view-pic?filePath=${params}`, | ||
| 51 | // method: 'get', | ||
| 52 | // responseType: 'blob' | ||
| 53 | // }); | ||
| 49 | export const getImageContent = (params) => request({ | 54 | export const getImageContent = (params) => request({ |
| 50 | url: `${import.meta.env.VITE_APP_API_BASEURL}/obs/view-pic?filePath=${params}`, | 55 | url: `${import.meta.env.VITE_APP_API_BASEURL}/obs/view-pic`, |
| 51 | method: 'get', | 56 | method: 'get', |
| 52 | responseType: 'blob' | 57 | responseType: 'blob' |
| 53 | }); | 58 | }); | ... | ... |
| 1 | <script lang="ts" setup name="DialogForm"> | 1 | /** |
| 2 | import { computed, reactive } from "vue"; | 2 | * 封装内容显示为form的对话框,外部只需传入form相关的配置,以及对话框尺寸标题等即可。 |
| 3 | import type { FormInstance, FormRules, CascaderProps } from "element-plus"; | 3 | */ |
| 4 | import { | 4 | <script lang="ts" setup name="Dialog_form"> |
| 5 | Plus, | 5 | import { ref } from 'vue'; |
| 6 | CirclePlus, | 6 | |
| 7 | Check, | 7 | const emits = defineEmits(["formDialogBtnClick", "formDialogSelectChange", "formDialogRadioGroupChange"]); |
| 8 | Download, | 8 | |
| 9 | Upload, | 9 | /** { visible: false, size: number, title: string, submitBtnLoading: false, formInfo: { id: xx, items: xx, rules:xx }, btns: { 'cancel': xx, } } */ |
| 10 | Search, | ||
| 11 | } from "@element-plus/icons-vue"; | ||
| 12 | import Table from "../Table/index.vue"; | ||
| 13 | const emits = defineEmits(["radioGroupChange", "selectChange"]); | ||
| 14 | const props = defineProps({ | 10 | const props = defineProps({ |
| 15 | itemList: { | 11 | dialogConfigInfo: { |
| 16 | type: Array<any>, | ||
| 17 | default: [], | ||
| 18 | }, | ||
| 19 | formId: { | ||
| 20 | type: String, | ||
| 21 | default: "", | ||
| 22 | }, | ||
| 23 | rules: { | ||
| 24 | type: Object, | 12 | type: Object, |
| 25 | default: {}, | 13 | default: {}, |
| 26 | }, | 14 | }, |
| 27 | col: { | ||
| 28 | type: String, | ||
| 29 | default: "", | ||
| 30 | }, | ||
| 31 | }); | ||
| 32 | const setFormFields = (list) => { | ||
| 33 | let obj = {}; | ||
| 34 | list.map((item) => { | ||
| 35 | if (item.field) { | ||
| 36 | obj[item.field] = item.default ?? ""; | ||
| 37 | } | ||
| 38 | if (item.children) { | ||
| 39 | obj = { ...obj, ...setFormFields(item.children) }; | ||
| 40 | } | ||
| 41 | }); | ||
| 42 | return obj; | ||
| 43 | }; | ||
| 44 | const ruleFormRef = ref<FormInstance>(); | ||
| 45 | const formInline: any = computed(() => { | ||
| 46 | return reactive(setFormFields(props.itemList)); | ||
| 47 | }); | 15 | }); |
| 48 | const formRules = computed(() => { | ||
| 49 | return reactive<FormRules>(props.rules); | ||
| 50 | }); | ||
| 51 | const formItemList: any = computed(() => { | ||
| 52 | return props.itemList ?? []; | ||
| 53 | }); | ||
| 54 | const selectAll = ref(false); | ||
| 55 | const resetForm = (formEl: FormInstance | undefined) => { | ||
| 56 | if (!formEl) return; | ||
| 57 | formEl.resetFields(); | ||
| 58 | formEl.clearValidate(); | ||
| 59 | }; | ||
| 60 | defineExpose({ | ||
| 61 | ruleFormRef, | ||
| 62 | formInline, | ||
| 63 | selectAll, | ||
| 64 | resetForm, | ||
| 65 | }); | ||
| 66 | const selectChange = (val, row) => { | ||
| 67 | emits("selectChange", val, row); | ||
| 68 | }; | ||
| 69 | const radioGroupChange = (val) => { | ||
| 70 | emits("radioGroupChange", val); | ||
| 71 | }; | ||
| 72 | const selectAllChange = (val, row, formModel) => { | ||
| 73 | const list = formItemList.value; | ||
| 74 | list.map((item) => (item.default = formModel[item.field])); | ||
| 75 | if (val) { | ||
| 76 | row.default = row.children.map((item) => item.label); | ||
| 77 | } else { | ||
| 78 | row.default = []; | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | const checkboxGroupChange = (val, row) => { | ||
| 82 | selectAll.value = val.length == row.children.length; | ||
| 83 | }; | ||
| 84 | const inputBlur = (evt, row) => { | ||
| 85 | if (row.field == "contactTel") { | ||
| 86 | formInline.value.adminAccount = formInline.value.contactTel; | ||
| 87 | } | ||
| 88 | }; | ||
| 89 | </script> | ||
| 90 | <template> | ||
| 91 | <el-form ref="ruleFormRef" class="dialog-form-inline" :class="['col' + props.col]" :inline="true" :model="formInline" | ||
| 92 | :rules="formRules"> | ||
| 93 | <el-form-item v-for="(item, index) in formItemList" :key="'form_item_' + index" :prop="item.field" | ||
| 94 | :class="{ 'is-block': item.block }"> | ||
| 95 | <span slot="label"> | ||
| 96 | <span :class="{ required_mark: item.required }">{{ item.label }}</span> | ||
| 97 | </span> | ||
| 98 | <div class="upload_wrap" v-if="item.type == 'image-upload'"> | ||
| 99 | <el-upload action="#" list-type="picture-card" :auto-upload="false"> | ||
| 100 | <el-icon> | ||
| 101 | <Plus /> | ||
| 102 | </el-icon> | ||
| 103 | <template #file="{ file }"> | ||
| 104 | <div> | ||
| 105 | <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" /> | ||
| 106 | </div> | ||
| 107 | </template> | ||
| 108 | </el-upload> | ||
| 109 | </div> | ||
| 110 | <div class="checkbox_panel" v-else-if="item.type == 'checkbox-panel'"> | ||
| 111 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled">{{ item.placeholder }}</el-checkbox> | ||
| 112 | <div class="panel_wrap"> | ||
| 113 | <div class="item_panel" v-for="panel in item.children"> | ||
| 114 | <label :class="{ required_mark: panel.required }">{{ | ||
| 115 | panel.label | ||
| 116 | }}</label> | ||
| 117 | <el-input v-if="panel.type == 'file-upload'" v-model.trim="formInline[panel.field]" | ||
| 118 | :placeholder="panel.placeholder" :disabled="panel.disabled" class="input-with-upload"> | ||
| 119 | <template #append> | ||
| 120 | <el-button class="upload_btn"> | ||
| 121 | <el-icon> | ||
| 122 | <svg-icon name="upload-file" /> | ||
| 123 | </el-icon> | ||
| 124 | </el-button> | ||
| 125 | </template> | ||
| 126 | </el-input> | ||
| 127 | <el-input v-else v-model.trim="formInline[panel.field]" :placeholder="panel.placeholder" | ||
| 128 | :disabled="panel.disabled" /> | ||
| 129 | </div> | ||
| 130 | </div> | ||
| 131 | </div> | ||
| 132 | <div class="checkbox_input" v-else-if="item.type == 'checkbox-input'"> | ||
| 133 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled">{{ item.placeholder }}</el-checkbox> | ||
| 134 | <div class="input_panel" v-for="child in item.children"> | ||
| 135 | <span>{{ child.prepend }}</span> | ||
| 136 | <el-input v-model.trim="formInline[child.field]" :disabled="child.disabled" :placeholder="child.placeholder" /> | ||
| 137 | <span>{{ child.append }}</span> | ||
| 138 | </div> | ||
| 139 | </div> | ||
| 140 | <div class="checkbox_textarea" v-else-if="item.type == 'checkbox-textarea'"> | ||
| 141 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled">{{ item.placeholder }}</el-checkbox> | ||
| 142 | <div class="textarea_panel" v-for="child in item.children"> | ||
| 143 | <el-input v-model.trim="formInline[child.field]" :rows="6" type="textarea" :placeholder="child.placeholder" | ||
| 144 | :disabled="child.disabled" resize="none" /> | ||
| 145 | </div> | ||
| 146 | </div> | ||
| 147 | <div class="checkbox_select" v-else-if="item.type == 'checkbox-select'" :class="{ is_block: item.block }"> | ||
| 148 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled">{{ item.placeholder }}</el-checkbox> | ||
| 149 | <div v-for="child in item.children"> | ||
| 150 | <el-select v-model="formInline[child.field]" :placeholder="child.placeholder"> | ||
| 151 | <el-option v-for="opts in child.options" :label="opts.label" :value="opts.value" /> | ||
| 152 | </el-select> | ||
| 153 | </div> | ||
| 154 | </div> | ||
| 155 | <div class="checkbox_group_panel" v-else-if="item.type == 'checkbox-group'" :class="{ is_block: item.block }"> | ||
| 156 | <div class="panel_tool"> | ||
| 157 | <span class="tips_txt">应用产品的菜单变化,产品组合会同步变化</span> | ||
| 158 | <el-checkbox v-model="selectAll" @change="(val) => selectAllChange(val, item, formInline)">全选</el-checkbox> | ||
| 159 | </div> | ||
| 160 | <el-checkbox-group v-model="formInline[item.field]" @change="(val) => checkboxGroupChange(val, item)"> | ||
| 161 | <el-checkbox v-for="child in item.children" :label="child.label" /> | ||
| 162 | </el-checkbox-group> | ||
| 163 | </div> | ||
| 164 | <div class="select_group" v-else-if="item.type == 'select-group'"> | ||
| 165 | <el-form-item v-for="(child, c) in item.children" :key="'child_item_' + c" :prop="child.field" | ||
| 166 | :class="{ 'is-block': child.block }"> | ||
| 167 | <span slot="label"> | ||
| 168 | <span :class="{ required_mark: child.required }">{{ | ||
| 169 | child.label | ||
| 170 | }}</span> | ||
| 171 | </span> | ||
| 172 | <el-cascader v-if="child.type == 'cascader'" v-model="formInline[child.field]" :props="child.props" clearable /> | ||
| 173 | <el-select v-else-if="child.type == 'select'" v-model="formInline[child.field]" :placeholder="child.placeholder" | ||
| 174 | :clearable="child.clearable"> | ||
| 175 | <el-option v-for="opts in child.options" :label="opts.label" :value="opts.value" /> | ||
| 176 | </el-select> | ||
| 177 | <el-input v-else v-model.trim="formInline[child.field]" :placeholder="child.placeholder" :clearable="child.clearable" | ||
| 178 | :disabled="child.disabled" /> | ||
| 179 | </el-form-item> | ||
| 180 | </div> | ||
| 181 | <div class="select_panel" v-else-if="item.type == 'select-panel'"> | ||
| 182 | <template v-for="child in item.children"> | ||
| 183 | <el-select v-if="child.type == 'select'" v-model="formInline[child.field]" :class="{ is_block: child.block }" | ||
| 184 | :placeholder="child.placeholder"> | ||
| 185 | <el-option v-for="opts in child.options" :label="opts.label" :value="opts.value" /> | ||
| 186 | </el-select> | ||
| 187 | <el-input v-else-if="child.type == 'textarea'" v-model.trim="formInline[child.field]" :rows="12" type="textarea" | ||
| 188 | :placeholder="child.placeholder" :disabled="child.disabled" resize="none" | ||
| 189 | :class="{ is_block: child.block }" /> | ||
| 190 | <el-input v-else v-model.trim="formInline[child.field]" :placeholder="child.placeholder" :clearable="child.clearable" | ||
| 191 | :disabled="child.disabled" /> | ||
| 192 | </template> | ||
| 193 | </div> | ||
| 194 | <!-- <div class="table_upload_panel" v-else-if="item.type == 'table-upload'"> | ||
| 195 | <div class="panel_title">添加表数据</div> | ||
| 196 | <div class="upload_tool"> | ||
| 197 | <div> | ||
| 198 | <el-button :icon="Upload">上传报表</el-button> | ||
| 199 | <el-button :icon="Download">下载报表</el-button> | ||
| 200 | </div> | ||
| 201 | <div> | ||
| 202 | <el-button plain type="primary">树形显示</el-button> | ||
| 203 | <el-button plain type="primary">新增行</el-button> | ||
| 204 | <el-button plain>刷新</el-button> | ||
| 205 | <el-button plain>删除</el-button> | ||
| 206 | </div> | ||
| 207 | </div> | ||
| 208 | <el-upload | ||
| 209 | ref="uploadRef" | ||
| 210 | class="upload-demo" | ||
| 211 | drag | ||
| 212 | action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" | ||
| 213 | :auto-upload="false" | ||
| 214 | > | ||
| 215 | <el-icon class="el-icon--upload"> | ||
| 216 | <Plus /> | ||
| 217 | </el-icon> | ||
| 218 | <div class="el-upload__text">点击或拖拽上传</div> | ||
| 219 | </el-upload> | ||
| 220 | </div> | ||
| 221 | <div class="table_panel" v-else-if="item.type == 'table-panel'"> | ||
| 222 | <Table :tableInfo="item.tableInfo" /> | ||
| 223 | <el-button | ||
| 224 | v-for="tool in item.tableTool" | ||
| 225 | link | ||
| 226 | type="primary" | ||
| 227 | :icon="CirclePlus" | ||
| 228 | >{{ tool.label }}</el-button | ||
| 229 | > | ||
| 230 | </div> | ||
| 231 | <div class="table_panel" v-else-if="item.type == 'tool-table-panel'"> | ||
| 232 | <div class="table_tools start"> | ||
| 233 | <el-button v-for="tool in item.tableTool" :type="tool.type">{{ | ||
| 234 | tool.label | ||
| 235 | }}</el-button> | ||
| 236 | </div> | ||
| 237 | <Table :tableInfo="item.tableInfo" /> | ||
| 238 | </div> | ||
| 239 | <div class="table_panel" v-else-if="item.type == 'edit-table-panel'"> | ||
| 240 | <div class="table_tools"> | ||
| 241 | <span>定义表结构</span> | ||
| 242 | <div class="tool_bars"> | ||
| 243 | <el-button v-for="tool in item.tableTool" :type="tool.type" plain>{{ | ||
| 244 | tool.label | ||
| 245 | }}</el-button> | ||
| 246 | </div> | ||
| 247 | </div> | ||
| 248 | <Table :tableInfo="item.tableInfo" /> | ||
| 249 | </div> --> | ||
| 250 | <div class="radio_panel" v-else-if="item.type == 'radio-panel'"> | ||
| 251 | <el-radio-group v-model="formInline[item.field]" @change="radioGroupChange"> | ||
| 252 | <el-radio v-for="opt in item.options" :label="opt.value" border> | ||
| 253 | <template #default> | ||
| 254 | <span>{{ opt.label }}</span> | ||
| 255 | <el-icon class="corner_mark" :class="{ active: formInline[item.field] == opt.value }"> | ||
| 256 | <Check /> | ||
| 257 | </el-icon> | ||
| 258 | </template> | ||
| 259 | </el-radio> | ||
| 260 | </el-radio-group> | ||
| 261 | <div class="panel_content"> | ||
| 262 | <el-form-item v-for="(child, c) in item.children" :key="'child_item_' + c" :prop="child.field" | ||
| 263 | :class="{ 'is-block': child.block }"> | ||
| 264 | <span slot="label"> | ||
| 265 | <span :class="{ required_mark: child.required }">{{ | ||
| 266 | child.label | ||
| 267 | }}</span> | ||
| 268 | </span> | ||
| 269 | <el-select v-if="child.type == 'select'" v-model="formInline[child.field]" :placeholder="child.placeholder" | ||
| 270 | :clearable="child.clearable"> | ||
| 271 | <el-option v-for="opts in child.options" :label="opts.label" :value="opts.value" /> | ||
| 272 | </el-select> | ||
| 273 | <el-input v-else v-model.trim="formInline[child.field]" :placeholder="child.placeholder" | ||
| 274 | :clearable="child.clearable" /> | ||
| 275 | </el-form-item> | ||
| 276 | </div> | ||
| 277 | </div> | ||
| 278 | <div class="switch" v-else-if="item.type == 'switch'"> | ||
| 279 | <el-switch inline-prompt v-model="formInline[item.field]" :width="item.switchWidth" | ||
| 280 | :active-value="item.activeValue" :inactive-value="item.inactiveValue" :active-text="item.activeText" | ||
| 281 | :inactive-text="item.inactiveText" /> | ||
| 282 | </div> | ||
| 283 | <div class="textarea_panel" v-else-if="item.type == 'textarea-panel'"> | ||
| 284 | <div class="panel_header"> | ||
| 285 | <span class="required_mark">{{ item.title }}</span> | ||
| 286 | <div class="tool_bars"> | ||
| 287 | <span v-for="btn in item.btns" class="text_btn"> | ||
| 288 | <span>{{ btn.label }}</span> | ||
| 289 | </span> | ||
| 290 | </div> | ||
| 291 | </div> | ||
| 292 | <el-input v-model.trim="formInline[item.field]" :rows="12" type="textarea" :placeholder="item.placeholder" | ||
| 293 | :disabled="item.disabled" resize="none" :class="{ is_block: item.block }" /> | ||
| 294 | </div> | ||
| 295 | <el-select v-else-if="item.type == 'select'" v-model="formInline[item.field]" :placeholder="item.placeholder" | ||
| 296 | :clearable="item.clearable" @change="(val) => selectChange(val, item)"> | ||
| 297 | <el-option v-for="opt in item.options" :label="opt.label" :value="opt.value" /> | ||
| 298 | </el-select> | ||
| 299 | <el-checkbox v-else-if="item.type == 'checkbox'" v-model="formInline[item.field]" :disabled="item.disabled">{{ | ||
| 300 | item.placeholder }}</el-checkbox> | ||
| 301 | <el-radio-group v-else-if="item.type == 'radio-group'" v-model="formInline[item.field]"> | ||
| 302 | <el-radio v-for="radio in item.options" :label="radio.value">{{ | ||
| 303 | radio.label | ||
| 304 | }}</el-radio> | ||
| 305 | </el-radio-group> | ||
| 306 | <el-input v-else-if="item.type == 'textarea'" v-model.trim="formInline[item.field]" :rows="4" type="textarea" | ||
| 307 | :placeholder="item.placeholder" :disabled="item.disabled" resize="none" /> | ||
| 308 | <el-input v-else-if="item.type == 'password'" v-model.trim="formInline[item.field]" type="password" | ||
| 309 | :placeholder="item.placeholder" :clearable="item.clearable" show-password /> | ||
| 310 | <el-input v-else-if="item.type == 'input-select'" v-model.trim="formInline[item.field]" :placeholder="item.placeholder" | ||
| 311 | class="input-with-select" :clearable="item.clearable" :suffix-icon="Search"> | ||
| 312 | <template #prepend> | ||
| 313 | <div v-for="child in item.children"> | ||
| 314 | <el-select v-model="formInline[child.field]" :placeholder="child.placeholder" :clearable="child.clearable" | ||
| 315 | style="width: 96px"> | ||
| 316 | <el-option v-for="opts in child.options" :label="opts.label" :value="opts.value" /> | ||
| 317 | </el-select> | ||
| 318 | </div> | ||
| 319 | </template> | ||
| 320 | </el-input> | ||
| 321 | <el-cascader v-else-if="item.type == 'cascader'" v-model="formInline[item.field]" :options="item.options" | ||
| 322 | :props="item.props" :show-all-levels="item.showAllLevels ?? true" :clearable="item.clearable" | ||
| 323 | :disabled="item.disabled" /> | ||
| 324 | <el-date-picker v-else-if="item.type == 'date-picker'" v-model="formInline[item.field]" type="daterange" | ||
| 325 | range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :format="item.format ?? 'YYYY-MM-DD'" | ||
| 326 | :value-format="item.formatValue ?? 'YYYY-MM-DD'" :unlink-panels="item.unlink ?? false" | ||
| 327 | :shortcuts="item.shortcuts ?? []" :default-value="item.defaultDate ?? []" /> | ||
| 328 | <el-input v-else v-model.trim="formInline[item.field]" :placeholder="item.placeholder" :clearable="item.clearable" | ||
| 329 | :disabled="item.disabled" @blur="(evt) => inputBlur(evt, item)" /> | ||
| 330 | </el-form-item> | ||
| 331 | </el-form> | ||
| 332 | </template> | ||
| 333 | <style lang="scss" scoped> | ||
| 334 | .dialog-form-inline { | ||
| 335 | display: flex; | ||
| 336 | justify-content: space-between; | ||
| 337 | align-items: center; | ||
| 338 | flex-wrap: wrap; | ||
| 339 | text-align: left; | ||
| 340 | |||
| 341 | &.col3 { | ||
| 342 | justify-content: flex-start; | ||
| 343 | |||
| 344 | :deep(.el-form-item) { | ||
| 345 | width: calc(33.33% - 6.67px); | ||
| 346 | margin-right: 10px; | ||
| 347 | |||
| 348 | &:nth-child(3n) { | ||
| 349 | margin-right: 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | &.is-block { | ||
| 353 | width: 100%; | ||
| 354 | margin-right: 0; | ||
| 355 | } | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | :deep(.el-form-item) { | ||
| 360 | width: calc(50% - 5px); | ||
| 361 | margin-right: 0; | ||
| 362 | flex-direction: column; | ||
| 363 | margin-bottom: 12px; | ||
| 364 | |||
| 365 | .el-form-item__content { | ||
| 366 | line-height: 21px; | ||
| 367 | |||
| 368 | // margin-bottom: 2px; | ||
| 369 | >div { | ||
| 370 | width: 100%; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | .el-form-item__label { | ||
| 375 | justify-content: flex-start; | ||
| 376 | } | ||
| 377 | |||
| 378 | .el-select, | ||
| 379 | .el-radio-group { | ||
| 380 | width: 100%; | ||
| 381 | |||
| 382 | .el-radio { | ||
| 383 | margin-right: 8px; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | &.is-block { | ||
| 388 | width: 100%; | ||
| 389 | |||
| 390 | .el-form-item__content { | ||
| 391 | width: 100%; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | &.required_mark { | ||
| 396 | .el-form-item__label { | ||
| 397 | position: relative; | ||
| 398 | |||
| 399 | &::after { | ||
| 400 | content: "*"; | ||
| 401 | color: #fb2323; | ||
| 402 | position: absolute; | ||
| 403 | margin-left: 2px; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | .required_mark { | ||
| 409 | position: relative; | ||
| 410 | |||
| 411 | &::after { | ||
| 412 | content: "*"; | ||
| 413 | color: #fb2323; | ||
| 414 | position: absolute; | ||
| 415 | margin-left: 2px; | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | .el-radio { | ||
| 420 | .el-radio__inner::after { | ||
| 421 | width: 10px; | ||
| 422 | height: 10px; | ||
| 423 | } | ||
| 424 | |||
| 425 | .el-radio__input.is-checked .el-radio__inner { | ||
| 426 | background-color: inherit; | ||
| 427 | |||
| 428 | &::after { | ||
| 429 | background-color: var(--el-color-primary); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 433 | |||
| 434 | .table_tools { | ||
| 435 | margin-bottom: 10px; | ||
| 436 | display: flex; | ||
| 437 | justify-content: space-between; | ||
| 438 | align-items: center; | ||
| 439 | |||
| 440 | >span { | ||
| 441 | font-size: 16px; | ||
| 442 | color: var(--el-color-regular); | ||
| 443 | font-weight: 600; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | |||
| 447 | .upload_wrap { | ||
| 448 | width: 100%; | ||
| 449 | padding: 0 12px; | ||
| 450 | border: 1px solid #d9d9d9; | ||
| 451 | border-radius: 2px; | ||
| 452 | |||
| 453 | .el-upload-list { | ||
| 454 | .el-upload--picture-card { | ||
| 455 | width: 64px; | ||
| 456 | height: 64px; | ||
| 457 | margin: 12px 0; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | .el-upload-list--picture-card .el-upload-list__item { | ||
| 462 | width: 64px; | ||
| 463 | height: 64px; | ||
| 464 | margin: 12px 12px 12px 0; | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | .checkbox_panel { | ||
| 469 | .panel_wrap { | ||
| 470 | width: 100%; | ||
| 471 | padding: 5px 12px 20px 12px; | ||
| 472 | border: 1px solid #d9d9d9; | ||
| 473 | border-radius: 2px; | ||
| 474 | |||
| 475 | .item_panel { | ||
| 476 | margin-bottom: 10px; | ||
| 477 | |||
| 478 | .el-input-group__append { | ||
| 479 | box-shadow: none; | ||
| 480 | } | ||
| 481 | |||
| 482 | .upload_btn { | ||
| 483 | padding: 0; | ||
| 484 | padding-left: 12px; | ||
| 485 | |||
| 486 | .el-icon { | ||
| 487 | width: 24px; | ||
| 488 | height: 24px; | ||
| 489 | color: var(--el-text-color-regular); | ||
| 490 | |||
| 491 | svg { | ||
| 492 | width: 24px; | ||
| 493 | height: 24px; | ||
| 494 | } | ||
| 495 | } | ||
| 496 | } | ||
| 497 | } | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | .checkbox_input { | ||
| 502 | display: flex; | ||
| 503 | |||
| 504 | .input_panel { | ||
| 505 | margin: 0 20px; | ||
| 506 | display: flex; | ||
| 507 | align-items: center; | ||
| 508 | |||
| 509 | >span { | ||
| 510 | margin: 0 4px; | ||
| 511 | white-space: nowrap; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | .checkbox_group_panel { | ||
| 517 | padding: 12px 24px; | ||
| 518 | border: 1px solid #d9d9d9; | ||
| 519 | border-radius: 2px; | ||
| 520 | position: relative; | ||
| 521 | |||
| 522 | .panel_tool { | ||
| 523 | width: calc(100% - 80px); | ||
| 524 | height: 21px; | ||
| 525 | display: flex; | ||
| 526 | justify-content: space-between; | ||
| 527 | align-items: center; | ||
| 528 | position: absolute; | ||
| 529 | top: -21px; | ||
| 530 | right: 0; | ||
| 531 | |||
| 532 | .tips_txt { | ||
| 533 | font-size: 12px; | ||
| 534 | color: #b2b2b2; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | .select_panel { | ||
| 540 | display: flex; | ||
| 541 | justify-content: space-between; | ||
| 542 | flex-wrap: wrap; | ||
| 543 | |||
| 544 | >div { | ||
| 545 | width: calc(33.33% - 5px); | ||
| 546 | margin-bottom: 10px; | ||
| 547 | |||
| 548 | &:last-child { | ||
| 549 | margin-bottom: 0; | ||
| 550 | } | ||
| 551 | |||
| 552 | &.is_block { | ||
| 553 | width: 100%; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | } | ||
| 557 | } | ||
| 558 | 16 | ||
| 559 | .select_group { | 17 | const dialogInfo = computed(() => { |
| 560 | display: flex; | 18 | return { |
| 561 | justify-content: space-between; | 19 | visible: props.dialogConfigInfo.visible, |
| 562 | } | 20 | size: props.dialogConfigInfo.size, |
| 563 | 21 | direction: "column", | |
| 564 | .radio_panel { | 22 | header: { |
| 565 | .panel_content { | 23 | title: props.dialogConfigInfo.title, |
| 566 | padding: 5px 0; | 24 | }, |
| 567 | background: #fafafa; | 25 | contents: [ |
| 568 | border: 1px solid #e5e5e5; | 26 | { |
| 569 | margin: 10px 0; | 27 | type: 'form', |
| 570 | padding: 0 10px; | 28 | title: '', |
| 571 | display: flex; | 29 | formInfo: props.dialogConfigInfo.formInfo |
| 572 | flex-wrap: wrap; | 30 | } |
| 573 | } | 31 | ], |
| 574 | 32 | footer: { | |
| 575 | :deep(.el-radio) { | 33 | btns: [ |
| 576 | &.is-bordered { | 34 | { type: "default", label: "取消", value: "cancel" }, |
| 577 | padding: 0; | 35 | { type: "primary", label: "确定", value: "submit", loading: props.dialogConfigInfo.submitBtnLoading ?? false }, |
| 578 | position: relative; | 36 | ], |
| 579 | 37 | }, | |
| 580 | .el-radio__input { | ||
| 581 | position: absolute; | ||
| 582 | opacity: 0; | ||
| 583 | } | ||
| 584 | |||
| 585 | .el-radio__label { | ||
| 586 | padding: 0 15px; | ||
| 587 | font-size: 12px; | ||
| 588 | position: relative; | ||
| 589 | |||
| 590 | .corner_mark { | ||
| 591 | position: absolute; | ||
| 592 | right: 0; | ||
| 593 | bottom: 0; | ||
| 594 | width: 18px; | ||
| 595 | height: 18px; | ||
| 596 | color: #fff; | ||
| 597 | |||
| 598 | svg { | ||
| 599 | width: 9px; | ||
| 600 | height: 9px; | ||
| 601 | position: absolute; | ||
| 602 | right: 0; | ||
| 603 | bottom: 2px; | ||
| 604 | z-index: 1; | ||
| 605 | } | ||
| 606 | |||
| 607 | &.active { | ||
| 608 | &::after { | ||
| 609 | content: ""; | ||
| 610 | position: absolute; | ||
| 611 | border: 9px solid var(--el-color-primary); | ||
| 612 | border-top-color: transparent; | ||
| 613 | border-left-color: transparent; | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | } | 38 | } |
| 39 | }) | ||
| 618 | 40 | ||
| 619 | .el-radio__input.is-checked+.el-radio__label { | 41 | const formDialogBtnClick = (btn, info) => { |
| 620 | color: var(--el-color-primary); | 42 | props.dialogConfigInfo.btns[btn.value]?.(btn, info); |
| 621 | } | 43 | }; |
| 622 | } | ||
| 623 | } | ||
| 624 | } | ||
| 625 | 44 | ||
| 626 | .table_panel { | 45 | const formDialogRadioGroupChange = (val, row, item) => { |
| 627 | .table_tools { | 46 | emits('formDialogRadioGroupChange', val, row, item); |
| 628 | &.start { | 47 | } |
| 629 | justify-content: flex-start; | ||
| 630 | } | ||
| 631 | } | ||
| 632 | } | ||
| 633 | 48 | ||
| 634 | .table_upload_panel { | 49 | const formDialogSelectChange = (val, item, row) => { |
| 635 | .panel_title { | 50 | emits('formDialogSelectChange', val, row, item); |
| 636 | color: var(--el-color-regular); | 51 | } |
| 637 | font-size: 16px; | ||
| 638 | font-weight: 600; | ||
| 639 | } | ||
| 640 | 52 | ||
| 641 | .upload_tool { | 53 | </script> |
| 642 | margin-bottom: 10px; | ||
| 643 | display: flex; | ||
| 644 | justify-content: space-between; | ||
| 645 | } | ||
| 646 | } | ||
| 647 | 54 | ||
| 648 | .textarea_panel { | 55 | <template> |
| 649 | .panel_header { | 56 | <Dialog :dialogInfo="dialogInfo" @btnClick="formDialogBtnClick" @radioGroupChange="formDialogRadioGroupChange" |
| 650 | display: flex; | 57 | @select-change="formDialogSelectChange" /> |
| 651 | justify-content: space-between; | 58 | </template> |
| 652 | align-items: center; | ||
| 653 | line-height: 21px; | ||
| 654 | } | ||
| 655 | } | ||
| 656 | } | ||
| 657 | </style> | ... | ... |
| ... | @@ -71,6 +71,39 @@ const routes: RouteRecordRaw[] = [ | ... | @@ -71,6 +71,39 @@ const routes: RouteRecordRaw[] = [ |
| 71 | } | 71 | } |
| 72 | } | 72 | } |
| 73 | }, | 73 | }, |
| 74 | { | ||
| 75 | path: 'newCreate-class', | ||
| 76 | name: 'newCreateClass', | ||
| 77 | component: () => import('@/views/data_inventory/newCreateClass.vue'), | ||
| 78 | meta: { | ||
| 79 | title: '新增分类', | ||
| 80 | sidebar: false, | ||
| 81 | breadcrumb: false, | ||
| 82 | cache: true, | ||
| 83 | reuse: true, | ||
| 84 | editPage: true, | ||
| 85 | activeMenu: '/data-inventory/classify-grade-manage/template-config' | ||
| 86 | }, | ||
| 87 | }, | ||
| 88 | { | ||
| 89 | path: 'classifyGrad-edit', | ||
| 90 | name: 'classifyGradEdit', | ||
| 91 | component: () => import('@/views/data_inventory/classifyGradEdit.vue'), | ||
| 92 | meta: { | ||
| 93 | title: '编辑-', | ||
| 94 | sidebar: false, | ||
| 95 | breadcrumb: false, | ||
| 96 | cache: true, | ||
| 97 | reuse: true, | ||
| 98 | editPage: true, | ||
| 99 | activeMenu: '/data-inventory/classify-grade-manage/template-config' | ||
| 100 | }, | ||
| 101 | beforeEnter: (to, from) => { | ||
| 102 | if (to.query.classClassifyGradName) { | ||
| 103 | to.meta.title = `编辑-${to.query.classClassifyGradName}`; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | }, | ||
| 74 | ], | 107 | ], |
| 75 | } | 108 | } |
| 76 | ] | 109 | ] | ... | ... |
| ... | @@ -405,6 +405,10 @@ onMounted(() => { | ... | @@ -405,6 +405,10 @@ onMounted(() => { |
| 405 | name: '装备制造' | 405 | name: '装备制造' |
| 406 | }] | 406 | }] |
| 407 | }); | 407 | }); |
| 408 | graph.value.on('node:mouseenter', (e) => { | ||
| 409 | const nodeItem = e.item // 获取鼠标进入的节点元素对象 | ||
| 410 | console.log('鼠标移入', nodeItem._cfg) | ||
| 411 | }) | ||
| 408 | graph.value.render(); | 412 | graph.value.render(); |
| 409 | graph.value.fitView(); | 413 | graph.value.fitView(); |
| 410 | graph.value.on('node:click', (evt: any) => { | 414 | graph.value.on('node:click', (evt: any) => { | ... | ... |
| 1 | <route lang="yaml"> | ||
| 2 | name: classifyGradEdit //新增分级分类模板 | ||
| 3 | </route> | ||
| 4 | |||
| 5 | <script lang="ts" setup name="classifyGradEdit"> | ||
| 6 | |||
| 7 | import router from "@/router"; | ||
| 8 | import { ref } from "vue"; | ||
| 9 | import { saveGrade, getGradeList, deleteGrade, getLargeCategoryList, updateGrade } from '@/api/modules/dataInventory'; | ||
| 10 | |||
| 11 | onMounted(() => { | ||
| 12 | getGradeListData(); | ||
| 13 | Promise.all([getDataGrade(), getDataClassify()]); | ||
| 14 | }); | ||
| 15 | |||
| 16 | // 获取分级列表 | ||
| 17 | const getGradeListData = async () => { | ||
| 18 | const params = { | ||
| 19 | pageIndex: 1, | ||
| 20 | pageSize: -1, | ||
| 21 | classifyGradeGuid: guid | ||
| 22 | } | ||
| 23 | const res: any = await getGradeList(params); | ||
| 24 | if (res.code == proxy.$passCode) { | ||
| 25 | tableInfo.value.data = res.data.records; | ||
| 26 | } else { | ||
| 27 | proxy.$ElMessage.error(res.msg); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | // 获取数据类别 | ||
| 32 | const getDataGrade = async () => { | ||
| 33 | const params = { | ||
| 34 | paramCode: "DATA-CLASSIFY" | ||
| 35 | } | ||
| 36 | const res: any = await getLargeCategoryList(params); | ||
| 37 | if (res.code == proxy.$passCode) { | ||
| 38 | // 提出value和label 作为select的options | ||
| 39 | const options = res.data.map((item: any) => ({ | ||
| 40 | label: item.paramName, | ||
| 41 | value: item.paramValue | ||
| 42 | })); | ||
| 43 | newCreateGradeFormItems.value[1].options = options; | ||
| 44 | classDataRef.value = options; | ||
| 45 | } else { | ||
| 46 | proxy.$ElMessage.error(res.msg); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | // 获取数据级别 | ||
| 51 | const getDataClassify = async () => { | ||
| 52 | const params = { | ||
| 53 | paramCode: "DATA-GRADE" | ||
| 54 | } | ||
| 55 | const res: any = await getLargeCategoryList(params); | ||
| 56 | if (res.code == proxy.$passCode) { | ||
| 57 | // 提出value和label 作为select的options | ||
| 58 | const options = res.data.map((item: any) => ({ | ||
| 59 | label: item.paramName, | ||
| 60 | value: item.paramValue | ||
| 61 | })); | ||
| 62 | newCreateGradeFormItems.value[0].options = options; | ||
| 63 | // 这里需要过滤已经在表格中数据级别 | ||
| 64 | gradeDataRef.value = options; | ||
| 65 | } else { | ||
| 66 | proxy.$ElMessage.error(res.msg); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | // 新增过滤数据级别 | ||
| 71 | const filterDataGrade = () => { | ||
| 72 | const selectedDataGrade = new Set(); | ||
| 73 | tableInfo.value.data.forEach((item: any) => { | ||
| 74 | if (item.dataGrade) { | ||
| 75 | selectedDataGrade.add(item.dataGrade); | ||
| 76 | } | ||
| 77 | }); | ||
| 78 | const filteredOptions = gradeDataRef.value.filter(option => !selectedDataGrade.has(option.value)); | ||
| 79 | (newCreateGradeFormItems.value[0].options as any[]) = filteredOptions; | ||
| 80 | }; | ||
| 81 | |||
| 82 | // 编辑过滤数据级别,需包含当前数据级别,不排除自己 | ||
| 83 | const filterDataGradeEdit = (dataGrade: string) => { | ||
| 84 | const selectedDataGrade = new Set(); | ||
| 85 | tableInfo.value.data.forEach((item: any) => { | ||
| 86 | if (item.dataGrade) { | ||
| 87 | selectedDataGrade.add(item.dataGrade); | ||
| 88 | } | ||
| 89 | }); | ||
| 90 | // 移除当前数据级别dataGrade | ||
| 91 | selectedDataGrade.delete(dataGrade); | ||
| 92 | console.log(selectedDataGrade,); | ||
| 93 | const filteredOptions = gradeDataRef.value.filter(option => !selectedDataGrade.has(option.value)); | ||
| 94 | (newCreateGradeFormItems.value[0].options as any[]) = filteredOptions; | ||
| 95 | }; | ||
| 96 | |||
| 97 | const tableRef = ref(); | ||
| 98 | const classDataRef = ref(); | ||
| 99 | const gradeDataRef = ref(); | ||
| 100 | const fullscreenLoading = ref(false); | ||
| 101 | const editClassifyGradeGuid = ref(''); | ||
| 102 | const { proxy } = getCurrentInstance() as any; | ||
| 103 | const guidArray = ref<any[]>([]); | ||
| 104 | // 获取query参数 中的guid | ||
| 105 | const guid = router.currentRoute.value.query.guid; | ||
| 106 | const tableInfo = ref({ | ||
| 107 | id: "data-class-standard-table", | ||
| 108 | multiple: true, | ||
| 109 | fields: [ | ||
| 110 | { label: "序号", field: 'orderNum', width: 56, align: "center" }, | ||
| 111 | { | ||
| 112 | label: "数据级别", field: "dataGrade", width: 120, getName: (scope) => { | ||
| 113 | let dataGrade = scope.row.dataGrade; | ||
| 114 | return dataGrade + '级'; | ||
| 115 | } | ||
| 116 | }, | ||
| 117 | { | ||
| 118 | label: "数据类别", field: "dataClassify", width: 120, getName: (scope) => { | ||
| 119 | let dataClassify = scope.row.dataClassify; | ||
| 120 | return classDataRef.value.find((item: any) => item.value === dataClassify)?.label; | ||
| 121 | } | ||
| 122 | }, | ||
| 123 | { label: "分级描述", field: "gradeDesc", align: "left", }, | ||
| 124 | |||
| 125 | ], | ||
| 126 | actionInfo: { | ||
| 127 | label: "操作", | ||
| 128 | type: "btn", | ||
| 129 | width: 120, | ||
| 130 | btns: [ | ||
| 131 | { | ||
| 132 | label: "编辑", value: "edit", click: (scope) => { | ||
| 133 | console.log(scope); | ||
| 134 | filterDataGradeEdit(scope.row.dataGrade); | ||
| 135 | newCreateGradeStandardDialogInfo.value.visible = true; | ||
| 136 | newCreateGradeStandardDialogInfo.value.title = '编辑分类'; | ||
| 137 | newCreateGradeFormItems.value.forEach(item => { | ||
| 138 | item.default = scope.row[item.field]; | ||
| 139 | }) | ||
| 140 | editClassifyGradeGuid.value = scope.row.guid; | ||
| 141 | } | ||
| 142 | }, | ||
| 143 | { | ||
| 144 | label: "删除", value: "delete", click: (scope) => { | ||
| 145 | guidArray.value = []; // 重置数组 | ||
| 146 | guidArray.value.push(scope.row.guid); | ||
| 147 | batchRemobe(); | ||
| 148 | } | ||
| 149 | }, | ||
| 150 | ], | ||
| 151 | }, | ||
| 152 | data: [], | ||
| 153 | showPage: false, | ||
| 154 | loading: false, | ||
| 155 | }); | ||
| 156 | |||
| 157 | // 选择勾选的数据 | ||
| 158 | const onTableSelectChange = async (selection: any[]) => { | ||
| 159 | guidArray.value = []; // 重置数组 | ||
| 160 | selection.forEach((item: any) => { | ||
| 161 | guidArray.value.push(item.guid); | ||
| 162 | }); | ||
| 163 | }; | ||
| 164 | |||
| 165 | // 批量删除 | ||
| 166 | const batchRemobe = async () => { | ||
| 167 | // 批量删除,增加confirm确认弹窗 | ||
| 168 | if (guidArray.value.length == 0) { | ||
| 169 | proxy.$ElMessage({ | ||
| 170 | type: 'warning', | ||
| 171 | message: '请选择要删除的数据' | ||
| 172 | }) | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | // confirm弹窗 | ||
| 177 | proxy.$confirm('是否删除选中数据?', '提示', { | ||
| 178 | confirmButtonText: '确定', | ||
| 179 | cancelButtonText: '取消', | ||
| 180 | type: 'warning' | ||
| 181 | }).then(async () => { | ||
| 182 | const res: any = await deleteGrade(guidArray.value); | ||
| 183 | if (res.code == proxy.$passCode) { | ||
| 184 | proxy.$ElMessage({ | ||
| 185 | type: 'success', | ||
| 186 | message: '删除成功' | ||
| 187 | }) | ||
| 188 | getGradeListData(); | ||
| 189 | } else { | ||
| 190 | proxy.$ElMessage.error(res.msg); | ||
| 191 | } | ||
| 192 | }).catch(() => { | ||
| 193 | proxy.$ElMessage({ | ||
| 194 | type: 'info', | ||
| 195 | message: '已取消删除' | ||
| 196 | }); | ||
| 197 | }); | ||
| 198 | |||
| 199 | }; | ||
| 200 | |||
| 201 | /**弹窗配置 */ | ||
| 202 | const newCreateGradeFormItems = ref([{ | ||
| 203 | label: '数据级别', | ||
| 204 | type: 'select', | ||
| 205 | placeholder: '请选择', | ||
| 206 | field: 'dataGrade', | ||
| 207 | default: '', | ||
| 208 | options: gradeDataRef.value, | ||
| 209 | required: true, | ||
| 210 | filterable: true, | ||
| 211 | clearable: true, | ||
| 212 | visible: true, | ||
| 213 | }, | ||
| 214 | { | ||
| 215 | label: '数据类别', | ||
| 216 | type: 'select', | ||
| 217 | placeholder: '请选择', | ||
| 218 | field: 'dataClassify', | ||
| 219 | default: '', | ||
| 220 | options: [], | ||
| 221 | required: true, | ||
| 222 | filterable: true, | ||
| 223 | clearable: true, | ||
| 224 | visible: true, | ||
| 225 | }, | ||
| 226 | { | ||
| 227 | label: '序号', | ||
| 228 | type: 'input', | ||
| 229 | maxlength: 19, | ||
| 230 | placeholder: '请输入', | ||
| 231 | field: 'orderNum', | ||
| 232 | default: '', | ||
| 233 | clearable: true, | ||
| 234 | required: true, | ||
| 235 | regexp: /\D/g | ||
| 236 | }, | ||
| 237 | { | ||
| 238 | label: '分级描述', | ||
| 239 | type: 'textarea', | ||
| 240 | maxlength: 50, | ||
| 241 | placeholder: '分类分级的描述说明', | ||
| 242 | field: 'gradeDesc', | ||
| 243 | default: '', | ||
| 244 | clearable: true, | ||
| 245 | required: false, | ||
| 246 | block: true, | ||
| 247 | }]); | ||
| 248 | |||
| 249 | const newCreateGradeFormRules = ref({ | ||
| 250 | dataGrade: [ | ||
| 251 | { required: true, message: '请选择数据级别', trigger: 'change' } | ||
| 252 | ], | ||
| 253 | orderNum: [ | ||
| 254 | { required: true, message: '请输入序号', trigger: 'blur' } | ||
| 255 | ], | ||
| 256 | dataClassify: [ | ||
| 257 | { required: true, message: '请选择数据类别', trigger: 'change' } | ||
| 258 | ] | ||
| 259 | }); | ||
| 260 | |||
| 261 | const newCreateGradeStandardDialogInfo = ref({ | ||
| 262 | visible: false, | ||
| 263 | size: 860, | ||
| 264 | title: "添加分类", | ||
| 265 | type: "", | ||
| 266 | formInfo: { | ||
| 267 | id: "grade-form", | ||
| 268 | items: newCreateGradeFormItems.value, | ||
| 269 | rules: newCreateGradeFormRules.value, | ||
| 270 | }, | ||
| 271 | submitBtnLoading: false, | ||
| 272 | btns: { | ||
| 273 | cancel: () => { | ||
| 274 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 275 | }, | ||
| 276 | submit: async (btn, info) => { | ||
| 277 | console.log(info, guid); | ||
| 278 | newCreateGradeStandardDialogInfo.value.submitBtnLoading = true; | ||
| 279 | if (newCreateGradeStandardDialogInfo.value.title === '编辑分类') { | ||
| 280 | const params = { | ||
| 281 | ...info, | ||
| 282 | guid: editClassifyGradeGuid.value, | ||
| 283 | classifyGradeGuid: guid | ||
| 284 | } | ||
| 285 | |||
| 286 | const res: any = await updateGrade(params); | ||
| 287 | if (res.code == proxy.$passCode) { | ||
| 288 | proxy.$ElMessage({ | ||
| 289 | type: 'success', | ||
| 290 | message: '修改分类成功' | ||
| 291 | }) | ||
| 292 | getGradeListData(); | ||
| 293 | newCreateGradeStandardDialogInfo.value.submitBtnLoading = false; | ||
| 294 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 295 | } else { | ||
| 296 | proxy.$ElMessage.error(res.msg); | ||
| 297 | } | ||
| 298 | return; | ||
| 299 | } else { | ||
| 300 | const params = { | ||
| 301 | ...info, | ||
| 302 | classifyGradeGuid: guid | ||
| 303 | } | ||
| 304 | const res: any = await saveGrade(params); | ||
| 305 | if (res.code == proxy.$passCode) { | ||
| 306 | proxy.$ElMessage({ | ||
| 307 | type: 'success', | ||
| 308 | message: '新增分类成功' | ||
| 309 | }) | ||
| 310 | getGradeListData(); | ||
| 311 | newCreateGradeStandardDialogInfo.value.submitBtnLoading = false; | ||
| 312 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 313 | } else { | ||
| 314 | proxy.$ElMessage.error(res.msg); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | }) | ||
| 320 | |||
| 321 | const newStandard = () => { | ||
| 322 | filterDataGrade(); | ||
| 323 | newCreateGradeStandardDialogInfo.value.visible = true; | ||
| 324 | newCreateGradeFormItems.value.forEach(item => item.default = ''); | ||
| 325 | } | ||
| 326 | |||
| 327 | |||
| 328 | |||
| 329 | </script> | ||
| 330 | |||
| 331 | <template> | ||
| 332 | <div class="container_wrap" v-loading="fullscreenLoading"> | ||
| 333 | <div class="content_main"> | ||
| 334 | <div class="table-top-btns"> | ||
| 335 | <el-button type="primary" @click="newStandard">新增标准</el-button> | ||
| 336 | <el-button @click="batchRemobe">批量删除</el-button> | ||
| 337 | </div> | ||
| 338 | <Table ref="tableRef" :tableInfo="tableInfo" @tableSelectionChange="onTableSelectChange" /> | ||
| 339 | </div> | ||
| 340 | <Dialog_form :dialogConfigInfo="newCreateGradeStandardDialogInfo" /> | ||
| 341 | </div> | ||
| 342 | </template> | ||
| 343 | <style lang="scss" scoped> | ||
| 344 | .container_wrap { | ||
| 345 | padding: 0px; | ||
| 346 | } | ||
| 347 | |||
| 348 | .content_main { | ||
| 349 | height: calc(100% - 44px); | ||
| 350 | padding: 17px 16px 10px 16px; | ||
| 351 | |||
| 352 | .table-top-btns { | ||
| 353 | display: flex; | ||
| 354 | margin-bottom: 12px; | ||
| 355 | } | ||
| 356 | } | ||
| 357 | </style> |
src/views/data_inventory/newCreateClass.vue
0 → 100644
| 1 | <route lang="yaml"> | ||
| 2 | name: newCreateClass //新增分级分类模板 | ||
| 3 | </route> | ||
| 4 | |||
| 5 | <script lang="ts" setup name="newCreateClass"> | ||
| 6 | import router from "@/router"; | ||
| 7 | import { getMetaDataBase } from '@/api/modules/dataMetaService'; | ||
| 8 | import { ref } from "vue"; | ||
| 9 | |||
| 10 | |||
| 11 | onMounted(async () => { | ||
| 12 | const params = { | ||
| 13 | pageIndex: 1, | ||
| 14 | pageSize: -1, | ||
| 15 | } | ||
| 16 | const res = await getMetaDataBase(params) | ||
| 17 | console.log(res); | ||
| 18 | }); | ||
| 19 | |||
| 20 | // 表单引用 | ||
| 21 | const formRef = ref(); | ||
| 22 | const tableRef = ref(); | ||
| 23 | const fullscreenLoading = ref(false); | ||
| 24 | const isExpand = ref(true); | ||
| 25 | const newCreateClassFormItems = ref([{ | ||
| 26 | label: '分类名称', | ||
| 27 | type: 'input', | ||
| 28 | maxlength: 50, | ||
| 29 | placeholder: '请输入', | ||
| 30 | field: 'categoryName', | ||
| 31 | default: '', | ||
| 32 | clearable: true, | ||
| 33 | required: true | ||
| 34 | }, { | ||
| 35 | label: '引用分级标准', | ||
| 36 | type: 'select', | ||
| 37 | placeholder: '请选择', | ||
| 38 | field: 'ReferenceGradingStandard', | ||
| 39 | default: '', | ||
| 40 | options: [], //TODO | ||
| 41 | required: true, | ||
| 42 | filterable: true, | ||
| 43 | clearable: true, | ||
| 44 | visible: true, | ||
| 45 | }]); | ||
| 46 | |||
| 47 | const formRules = ref({ | ||
| 48 | templeteName: [ | ||
| 49 | { required: true, message: '请输入模板名称', trigger: 'blur' }, | ||
| 50 | { max: 50, message: '长度在 50 个字符以内', trigger: 'blur' } | ||
| 51 | ], | ||
| 52 | industryCategory: [ | ||
| 53 | { required: true, message: '请选择行业分类', trigger: 'change' } | ||
| 54 | ], | ||
| 55 | gradingStandard: [ | ||
| 56 | { required: true, message: '请选择分级标准', trigger: 'change' } | ||
| 57 | ] | ||
| 58 | }); | ||
| 59 | |||
| 60 | const tableInfo = ref({ | ||
| 61 | id: "data-class-standard-table", | ||
| 62 | fields: [ | ||
| 63 | { label: "序号", type: "index", width: 56, align: "center" }, | ||
| 64 | { label: "层级", field: "databaseNameZh", width: 160, }, | ||
| 65 | { label: "状态", field: "databaseName", width: 120, }, | ||
| 66 | { label: "定义说明", field: "tableCount", width: 120, align: "right", }, | ||
| 67 | { label: "最低安全级别", field: "storageCapacities", align: "right", width: 220, }, | ||
| 68 | { label: "创建时间", field: "columns", width: 140, align: "right", }, | ||
| 69 | ], | ||
| 70 | actionInfo: { | ||
| 71 | show: false, | ||
| 72 | }, | ||
| 73 | data: [ | ||
| 74 | { | ||
| 75 | index: 1, | ||
| 76 | databaseNameZh: "数据库名称", | ||
| 77 | databaseName: "数据库名", | ||
| 78 | tableCount: 0, | ||
| 79 | storageCapacities: 0, | ||
| 80 | columns: 0, | ||
| 81 | }, | ||
| 82 | { | ||
| 83 | index: 2, | ||
| 84 | databaseNameZh: "数据库名称", | ||
| 85 | databaseName: "数据库名", | ||
| 86 | tableCount: 0, | ||
| 87 | storageCapacities: 0, | ||
| 88 | columns: 0, | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | index: 3, | ||
| 92 | databaseNameZh: "数据库名称", | ||
| 93 | databaseName: "数据库名", | ||
| 94 | tableCount: 0, | ||
| 95 | storageCapacities: 0, | ||
| 96 | columns: 0, | ||
| 97 | }, | ||
| 98 | { | ||
| 99 | index: 4, | ||
| 100 | databaseNameZh: "数据库名称", | ||
| 101 | databaseName: "数据库名", | ||
| 102 | tableCount: 0, | ||
| 103 | storageCapacities: 0, | ||
| 104 | columns: 0, | ||
| 105 | }, | ||
| 106 | { | ||
| 107 | index: 5, | ||
| 108 | databaseNameZh: "数据库名称", | ||
| 109 | databaseName: "数据库名", | ||
| 110 | tableCount: 0, | ||
| 111 | storageCapacities: 0, | ||
| 112 | columns: 0, | ||
| 113 | }, | ||
| 114 | { | ||
| 115 | index: 6, | ||
| 116 | databaseNameZh: "数据库名称", | ||
| 117 | databaseName: "数据库名", | ||
| 118 | tableCount: 0, | ||
| 119 | storageCapacities: 0, | ||
| 120 | columns: 0, | ||
| 121 | }, | ||
| 122 | |||
| 123 | ], | ||
| 124 | showPage: false, | ||
| 125 | loading: false, | ||
| 126 | }); | ||
| 127 | |||
| 128 | const onTableSelectChange = (selection: any[]) => { | ||
| 129 | console.log(selection); | ||
| 130 | }; | ||
| 131 | |||
| 132 | const cancel = () => { | ||
| 133 | // 返回上一页路由 | ||
| 134 | router.back(); | ||
| 135 | }; | ||
| 136 | |||
| 137 | const save = async () => { | ||
| 138 | console.log('save'); | ||
| 139 | // 校验表单 | ||
| 140 | const res = formRef.value; | ||
| 141 | res.ruleFormRef.validate((valid: any) => { | ||
| 142 | if (valid) { | ||
| 143 | // 表单校验通过 | ||
| 144 | console.log('表单校验通过'); | ||
| 145 | } else { | ||
| 146 | console.log('表单校验不通过'); | ||
| 147 | return false; | ||
| 148 | } | ||
| 149 | }); | ||
| 150 | |||
| 151 | |||
| 152 | }; | ||
| 153 | </script> | ||
| 154 | |||
| 155 | <template> | ||
| 156 | <div class="container_wrap" v-loading="fullscreenLoading"> | ||
| 157 | <div class="content_main"> | ||
| 158 | <ContentWrap id="id-baseInfo" title="基础信息" description="" style="margin-top: 8px;" :expandSwicth=isExpand> | ||
| 159 | <Form ref="formRef" :itemList="newCreateClassFormItems" formId="main-model-edit" col="col3" :rules=formRules /> | ||
| 160 | </ContentWrap> | ||
| 161 | <ContentWrap id="id-classStandard" class="detail-content" title="分类标准" description="" style="margin-top:16px;" | ||
| 162 | :expandSwicth=isExpand> | ||
| 163 | <div class="table-content_wrap"> | ||
| 164 | <Table ref="tableRef" :tableInfo="tableInfo" /> | ||
| 165 | </div> | ||
| 166 | </ContentWrap> | ||
| 167 | </div> | ||
| 168 | <div class="bottom_tool_wrap"> | ||
| 169 | <el-button @click="cancel">取消</el-button> | ||
| 170 | <el-button type="primary" @click="save">后台运行</el-button> | ||
| 171 | </div> | ||
| 172 | </div> | ||
| 173 | </template> | ||
| 174 | |||
| 175 | <style lang="scss" scoped> | ||
| 176 | .container_wrap { | ||
| 177 | padding: 0px; | ||
| 178 | } | ||
| 179 | |||
| 180 | .content_main { | ||
| 181 | height: calc(100% - 44px); | ||
| 182 | padding: 10px 16px; | ||
| 183 | |||
| 184 | .table-content_wrap { | ||
| 185 | width: 100%; | ||
| 186 | height: 213px; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | .bottom_tool_wrap { | ||
| 191 | display: flex; | ||
| 192 | justify-content: center; | ||
| 193 | border-top: 1px solid #D9D9D9; | ||
| 194 | padding-top: 8px; | ||
| 195 | |||
| 196 | } | ||
| 197 | </style> |
| ... | @@ -3,10 +3,26 @@ | ... | @@ -3,10 +3,26 @@ |
| 3 | </route> | 3 | </route> |
| 4 | 4 | ||
| 5 | <script lang="ts" setup name="newCreateTemplate"> | 5 | <script lang="ts" setup name="newCreateTemplate"> |
| 6 | import router from "@/router"; | ||
| 7 | import { getMetaDataBase } from '@/api/modules/dataMetaService'; | ||
| 6 | import { ref } from "vue"; | 8 | import { ref } from "vue"; |
| 9 | |||
| 10 | |||
| 11 | onMounted(async () => { | ||
| 12 | const params = { | ||
| 13 | pageIndex: 1, | ||
| 14 | pageSize: -1, | ||
| 15 | } | ||
| 16 | const res = await getMetaDataBase(params) | ||
| 17 | console.log(res); | ||
| 18 | }); | ||
| 19 | |||
| 20 | // 表单引用 | ||
| 21 | const formRef = ref(); | ||
| 22 | const tableRef = ref(); | ||
| 7 | const fullscreenLoading = ref(false); | 23 | const fullscreenLoading = ref(false); |
| 8 | const isExpand = ref(true); | 24 | const isExpand = ref(true); |
| 9 | const classStandardFormItems = ref([{ | 25 | const newCreateTemplateFormItems = ref([{ |
| 10 | label: '模板名称', | 26 | label: '模板名称', |
| 11 | type: 'input', | 27 | type: 'input', |
| 12 | maxlength: 50, | 28 | maxlength: 50, |
| ... | @@ -38,34 +54,113 @@ const classStandardFormItems = ref([{ | ... | @@ -38,34 +54,113 @@ const classStandardFormItems = ref([{ |
| 38 | clearable: true, | 54 | clearable: true, |
| 39 | visible: true, | 55 | visible: true, |
| 40 | }]); | 56 | }]); |
| 41 | const dataShowMethod = ref('shape'); | 57 | |
| 58 | const formRules = ref({ | ||
| 59 | templeteName: [ | ||
| 60 | { required: true, message: '请输入模板名称', trigger: 'blur' }, | ||
| 61 | { max: 50, message: '长度在 50 个字符以内', trigger: 'blur' } | ||
| 62 | ], | ||
| 63 | industryCategory: [ | ||
| 64 | { required: true, message: '请选择行业分类', trigger: 'change' } | ||
| 65 | ], | ||
| 66 | gradingStandard: [ | ||
| 67 | { required: true, message: '请选择分级标准', trigger: 'change' } | ||
| 68 | ] | ||
| 69 | }); | ||
| 70 | |||
| 42 | const tableInfo = ref({ | 71 | const tableInfo = ref({ |
| 43 | id: "data-class-standard-table", | 72 | id: "data-class-standard-table", |
| 44 | multiple: false, | 73 | multiple: true, |
| 45 | fields: [ | 74 | fields: [ |
| 46 | { label: "序号", type: "index", width: 56, align: "center" }, | 75 | { label: "序号", type: "index", width: 56, align: "center" }, |
| 47 | { label: "数据库名称", field: "className", width: 160, }, | 76 | { label: "数据库名称", field: "databaseNameZh", width: 160, }, |
| 48 | { label: "数据库名", field: "levelName", width: 120 }, | 77 | { label: "数据库名", field: "databaseName", width: 120, }, |
| 49 | { label: "总表数", field: "state", type: "tag", width: 120, align: "center" }, | 78 | { label: "总表数", field: "tableCount", width: 120, align: "right", }, |
| 50 | { label: "存储量(约/MB)", field: "description", }, | 79 | { label: "存储量(约/MB)", field: "storageCapacities", align: "right", width: 220, }, |
| 51 | { label: "总字段数", field: "minLevel", width: 140 }, | 80 | { label: "总字段数", field: "columns", width: 140, align: "right", }, |
| 81 | ], | ||
| 82 | actionInfo: { | ||
| 83 | show: false, | ||
| 84 | }, | ||
| 85 | data: [ | ||
| 86 | { | ||
| 87 | index: 1, | ||
| 88 | databaseNameZh: "数据库名称", | ||
| 89 | databaseName: "数据库名", | ||
| 90 | tableCount: 0, | ||
| 91 | storageCapacities: 0, | ||
| 92 | columns: 0, | ||
| 93 | }, | ||
| 94 | { | ||
| 95 | index: 2, | ||
| 96 | databaseNameZh: "数据库名称", | ||
| 97 | databaseName: "数据库名", | ||
| 98 | tableCount: 0, | ||
| 99 | storageCapacities: 0, | ||
| 100 | columns: 0, | ||
| 101 | }, | ||
| 102 | { | ||
| 103 | index: 3, | ||
| 104 | databaseNameZh: "数据库名称", | ||
| 105 | databaseName: "数据库名", | ||
| 106 | tableCount: 0, | ||
| 107 | storageCapacities: 0, | ||
| 108 | columns: 0, | ||
| 109 | }, | ||
| 110 | { | ||
| 111 | index: 4, | ||
| 112 | databaseNameZh: "数据库名称", | ||
| 113 | databaseName: "数据库名", | ||
| 114 | tableCount: 0, | ||
| 115 | storageCapacities: 0, | ||
| 116 | columns: 0, | ||
| 117 | }, | ||
| 118 | { | ||
| 119 | index: 5, | ||
| 120 | databaseNameZh: "数据库名称", | ||
| 121 | databaseName: "数据库名", | ||
| 122 | tableCount: 0, | ||
| 123 | storageCapacities: 0, | ||
| 124 | columns: 0, | ||
| 125 | }, | ||
| 126 | { | ||
| 127 | index: 6, | ||
| 128 | databaseNameZh: "数据库名称", | ||
| 129 | databaseName: "数据库名", | ||
| 130 | tableCount: 0, | ||
| 131 | storageCapacities: 0, | ||
| 132 | columns: 0, | ||
| 133 | }, | ||
| 134 | |||
| 52 | ], | 135 | ], |
| 53 | data: [{ | ||
| 54 | guid: '1', | ||
| 55 | children: [{ | ||
| 56 | guid: '1-1' | ||
| 57 | }] | ||
| 58 | }], | ||
| 59 | showPage: false, | 136 | showPage: false, |
| 60 | loading: false, | 137 | loading: false, |
| 61 | }); | 138 | }); |
| 62 | 139 | ||
| 140 | const onTableSelectChange = (selection: any[]) => { | ||
| 141 | console.log(selection); | ||
| 142 | }; | ||
| 143 | |||
| 63 | const cancel = () => { | 144 | const cancel = () => { |
| 64 | console.log('cancel'); | 145 | // 返回上一页路由 |
| 146 | router.back(); | ||
| 65 | }; | 147 | }; |
| 66 | 148 | ||
| 67 | const save = () => { | 149 | const save = async () => { |
| 68 | console.log('save'); | 150 | console.log('save'); |
| 151 | // 校验表单 | ||
| 152 | const res = formRef.value; | ||
| 153 | res.ruleFormRef.validate((valid: any) => { | ||
| 154 | if (valid) { | ||
| 155 | // 表单校验通过 | ||
| 156 | console.log('表单校验通过'); | ||
| 157 | } else { | ||
| 158 | console.log('表单校验不通过'); | ||
| 159 | return false; | ||
| 160 | } | ||
| 161 | }); | ||
| 162 | |||
| 163 | |||
| 69 | }; | 164 | }; |
| 70 | </script> | 165 | </script> |
| 71 | 166 | ||
| ... | @@ -73,18 +168,20 @@ const save = () => { | ... | @@ -73,18 +168,20 @@ const save = () => { |
| 73 | <div class="container_wrap" v-loading="fullscreenLoading"> | 168 | <div class="container_wrap" v-loading="fullscreenLoading"> |
| 74 | <div class="content_main"> | 169 | <div class="content_main"> |
| 75 | <ContentWrap id="id-baseInfo" title="模板信息" description="" style="margin-top: 8px;" :expandSwicth=isExpand> | 170 | <ContentWrap id="id-baseInfo" title="模板信息" description="" style="margin-top: 8px;" :expandSwicth=isExpand> |
| 76 | <Form ref="formRef" :itemList="classStandardFormItems" formId="main-model-edit" col="col3" /> | 171 | <Form ref="formRef" :itemList="newCreateTemplateFormItems" formId="main-model-edit" col="col3" |
| 172 | :rules=formRules /> | ||
| 77 | </ContentWrap> | 173 | </ContentWrap> |
| 78 | <ContentWrap id="id-classStandard" class="detail-content" title="选择元数据" description="" style="margin-top:16px;" | 174 | <ContentWrap id="id-classStandard" class="detail-content" title="选择元数据" description="" style="margin-top:16px;" |
| 79 | :expandSwicth=isExpand> | 175 | :expandSwicth=isExpand> |
| 80 | 176 | <div class="table-content_wrap"> | |
| 177 | <Table ref="tableRef" :tableInfo="tableInfo" @tableSelectionChange="onTableSelectChange" /> | ||
| 178 | </div> | ||
| 81 | </ContentWrap> | 179 | </ContentWrap> |
| 82 | </div> | 180 | </div> |
| 83 | <div class=" bottom_tool_wrap"> | 181 | <div class="bottom_tool_wrap"> |
| 84 | <el-button @click="cancel">取消</el-button> | 182 | <el-button @click="cancel">取消</el-button> |
| 85 | <el-button type="primary" @click="save">保存</el-button> | 183 | <el-button type="primary" @click="save">后台运行</el-button> |
| 86 | </div> | 184 | </div> |
| 87 | |||
| 88 | </div> | 185 | </div> |
| 89 | </template> | 186 | </template> |
| 90 | 187 | ||
| ... | @@ -96,5 +193,18 @@ const save = () => { | ... | @@ -96,5 +193,18 @@ const save = () => { |
| 96 | .content_main { | 193 | .content_main { |
| 97 | height: calc(100% - 44px); | 194 | height: calc(100% - 44px); |
| 98 | padding: 10px 16px; | 195 | padding: 10px 16px; |
| 196 | |||
| 197 | .table-content_wrap { | ||
| 198 | width: 100%; | ||
| 199 | height: 213px; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | .bottom_tool_wrap { | ||
| 204 | display: flex; | ||
| 205 | justify-content: center; | ||
| 206 | border-top: 1px solid #D9D9D9; | ||
| 207 | padding-top: 8px; | ||
| 208 | |||
| 99 | } | 209 | } |
| 100 | </style> | 210 | </style> | ... | ... |
| ... | @@ -10,12 +10,51 @@ import { MoreFilled } from "@element-plus/icons-vue"; | ... | @@ -10,12 +10,51 @@ import { MoreFilled } from "@element-plus/icons-vue"; |
| 10 | import { commonPageConfig } from '@/components/PageNav/index'; | 10 | import { commonPageConfig } from '@/components/PageNav/index'; |
| 11 | import { useValidator } from '@/hooks/useValidator'; | 11 | import { useValidator } from '@/hooks/useValidator'; |
| 12 | import TemplateItem from '@/components/TemplateItem/index.vue' | 12 | import TemplateItem from '@/components/TemplateItem/index.vue' |
| 13 | import { getTempleteClassifyData } from "@/api/modules/dataInventory"; | 13 | import { getTempleteClassifyData, saveClassifyGrad, getClassifyGradList, deleteClassifyGrad, updateClassifyGrad, getGradeTreeList } from "@/api/modules/dataInventory"; |
| 14 | |||
| 15 | |||
| 14 | 16 | ||
| 15 | const router = useRouter(); | 17 | const router = useRouter(); |
| 16 | const { required } = useValidator(); | 18 | const { required } = useValidator(); |
| 17 | const { proxy } = getCurrentInstance() as any; | 19 | const { proxy } = getCurrentInstance() as any; |
| 18 | 20 | ||
| 21 | const refClassifyPageParams = ref({ | ||
| 22 | pageIndex: 1, | ||
| 23 | pageSize: 10, | ||
| 24 | type: "G" | ||
| 25 | }); | ||
| 26 | const classifyGradListData = ref(); | ||
| 27 | |||
| 28 | const getClassifyGradListData = async () => { | ||
| 29 | const res: any = await getClassifyGradList(refClassifyPageParams.value); | ||
| 30 | if (res.code == proxy.$passCode) { | ||
| 31 | classifyGradListData.value = res.data.records || []; | ||
| 32 | } else { | ||
| 33 | proxy.$ElMessage.error(res.msg); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | // 获取分级树形列表 | ||
| 38 | const getGradeTreeListData = async () => { | ||
| 39 | const res: any = await getGradeTreeList(); | ||
| 40 | if (res.code == proxy.$passCode) { | ||
| 41 | gradeTreeData.value = res.data || []; | ||
| 42 | } else { | ||
| 43 | proxy.$ElMessage.error(res.msg); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | //记录分级guid | ||
| 48 | const classifyGradGuid = ref(''); | ||
| 49 | // 分级列表 | ||
| 50 | const gradeTreeData = ref(''); | ||
| 51 | |||
| 52 | onMounted(() => { | ||
| 53 | getClassifyGradListData(); | ||
| 54 | getGradeTreeListData(); | ||
| 55 | }) | ||
| 56 | |||
| 57 | |||
| 19 | const tabsInfo = ref({ | 58 | const tabsInfo = ref({ |
| 20 | activeName: 'classStandard', | 59 | activeName: 'classStandard', |
| 21 | tabs: [ | 60 | tabs: [ |
| ... | @@ -115,10 +154,7 @@ const searchClass = (val: any, clear: boolean = false) => { | ... | @@ -115,10 +154,7 @@ const searchClass = (val: any, clear: boolean = false) => { |
| 115 | getClassListData(); | 154 | getClassListData(); |
| 116 | }; | 155 | }; |
| 117 | 156 | ||
| 118 | const newCreateClass = () => { | 157 | |
| 119 | newCreateClassStandardDialogInfo.value.visible = true; | ||
| 120 | classStandardFormItems.value.forEach(item => item.default = ''); | ||
| 121 | } | ||
| 122 | 158 | ||
| 123 | const getClassListData = () => { | 159 | const getClassListData = () => { |
| 124 | // classListDataLoading.value = true; | 160 | // classListDataLoading.value = true; |
| ... | @@ -141,15 +177,15 @@ const getClassListData = () => { | ... | @@ -141,15 +177,15 @@ const getClassListData = () => { |
| 141 | } | 177 | } |
| 142 | 178 | ||
| 143 | /** 编辑分类 */ | 179 | /** 编辑分类 */ |
| 144 | const handleClassDataEdit = (item) => { | 180 | const handleClassDataEdit = (item, des = '') => { |
| 145 | 181 | ||
| 146 | } | 182 | } |
| 147 | 183 | ||
| 148 | const handleClassDataClick = (item) => { | 184 | const handleClassDataClick = (item, des = '') => { |
| 149 | router.push({ | 185 | router.push({ |
| 150 | name: 'classStandardEdit', | 186 | name: 'classStandardEdit', |
| 151 | query: { | 187 | query: { |
| 152 | guid: item.guid, | 188 | type: des === '' ? '配置' : des, |
| 153 | classStandardName: '工业分类' | 189 | classStandardName: '工业分类' |
| 154 | } | 190 | } |
| 155 | }); | 191 | }); |
| ... | @@ -158,6 +194,7 @@ const handleClassDataClick = (item) => { | ... | @@ -158,6 +194,7 @@ const handleClassDataClick = (item) => { |
| 158 | const handleClassDataDel = (item) => { | 194 | const handleClassDataDel = (item) => { |
| 159 | 195 | ||
| 160 | } | 196 | } |
| 197 | /** ------------------------------- 分类标准相关 ------------------------------------- */ | ||
| 161 | 198 | ||
| 162 | const classStandardFormItems = ref([{ | 199 | const classStandardFormItems = ref([{ |
| 163 | label: '分类名称', | 200 | label: '分类名称', |
| ... | @@ -171,7 +208,7 @@ const classStandardFormItems = ref([{ | ... | @@ -171,7 +208,7 @@ const classStandardFormItems = ref([{ |
| 171 | required: true | 208 | required: true |
| 172 | }, { | 209 | }, { |
| 173 | label: '分级标准', | 210 | label: '分级标准', |
| 174 | type: 'select', | 211 | type: 'tree-select', |
| 175 | placeholder: '请选择', | 212 | placeholder: '请选择', |
| 176 | field: 'gradeStandard', | 213 | field: 'gradeStandard', |
| 177 | default: 1, | 214 | default: 1, |
| ... | @@ -219,24 +256,161 @@ const newCreateClassStandardDialogInfo = ref({ | ... | @@ -219,24 +256,161 @@ const newCreateClassStandardDialogInfo = ref({ |
| 219 | } | 256 | } |
| 220 | }) | 257 | }) |
| 221 | 258 | ||
| 222 | const newCreateTemplate = () => { | 259 | const newCreateClass = () => { |
| 260 | newCreateClassStandardDialogInfo.value.visible = true; | ||
| 261 | classStandardFormItems.value.forEach(item => item.default = ''); | ||
| 262 | } | ||
| 263 | |||
| 264 | /** ------------------------------- 分级标准相关 ------------------------------------- */ | ||
| 265 | |||
| 266 | const newCreateGradeFormItems = ref([{ | ||
| 267 | label: '分级名称', | ||
| 268 | type: 'input', | ||
| 269 | maxlength: 50, | ||
| 270 | placeholder: '请输入', | ||
| 271 | field: 'name', | ||
| 272 | default: '', | ||
| 273 | block: true, | ||
| 274 | clearable: true, | ||
| 275 | required: true | ||
| 276 | }]); | ||
| 277 | |||
| 278 | const newCreateGradeFormRules = ref({ | ||
| 279 | name: [required('请填写分级名称')], | ||
| 280 | }); | ||
| 281 | |||
| 282 | const newCreateGradeStandardDialogInfo = ref({ | ||
| 283 | visible: false, | ||
| 284 | size: 460, | ||
| 285 | title: "新增分级", | ||
| 286 | type: "", | ||
| 287 | formInfo: { | ||
| 288 | id: "grade-form", | ||
| 289 | items: newCreateGradeFormItems.value, | ||
| 290 | rules: newCreateGradeFormRules.value, | ||
| 291 | }, | ||
| 292 | submitBtnLoading: false, | ||
| 293 | btns: { | ||
| 294 | cancel: () => { | ||
| 295 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 296 | }, | ||
| 297 | submit: async (btn, info) => { | ||
| 298 | newCreateGradeStandardDialogInfo.value.submitBtnLoading = true; | ||
| 299 | console.log(info, newCreateGradeStandardDialogInfo.value.title); | ||
| 300 | if (newCreateGradeStandardDialogInfo.value.title === '新增分级') { | ||
| 301 | const params = { | ||
| 302 | name: info.name, | ||
| 303 | type: 'G' | ||
| 304 | } | ||
| 305 | const res: any = await saveClassifyGrad(params); | ||
| 306 | if (res.code == proxy.$passCode) { | ||
| 307 | await getClassifyGradListData(); | ||
| 308 | proxy.$ElMessage({ | ||
| 309 | type: 'success', | ||
| 310 | message: '新增分类成功' | ||
| 311 | }) | ||
| 312 | |||
| 313 | // 拿到新增的分级数据,跳转到配置页面 | ||
| 314 | const item = classifyGradListData.value.find(item => item.name === info.name); | ||
| 315 | |||
| 316 | if (item) { | ||
| 317 | const params = { | ||
| 318 | name: item.name, | ||
| 319 | guid: item.guid, | ||
| 320 | } | ||
| 321 | handleClassifyGradDataClick(params); | ||
| 322 | } | ||
| 323 | newCreateGradeStandardDialogInfo.value.submitBtnLoading = false; | ||
| 324 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 325 | } else { | ||
| 326 | proxy.$ElMessage.error(res.msg); | ||
| 327 | } | ||
| 328 | } else { | ||
| 329 | const params = { | ||
| 330 | name: info.name, | ||
| 331 | guid: classifyGradGuid.value, | ||
| 332 | type: 'G' | ||
| 333 | } | ||
| 334 | const res: any = await updateClassifyGrad(params); | ||
| 335 | if (res.code == proxy.$passCode) { | ||
| 336 | getClassifyGradListData(); | ||
| 337 | proxy.$ElMessage({ | ||
| 338 | type: 'success', | ||
| 339 | message: '修改分类成功' | ||
| 340 | }) | ||
| 341 | newCreateGradeStandardDialogInfo.value.visible = false; | ||
| 342 | } else { | ||
| 343 | proxy.$ElMessage.error(res.msg); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | } | ||
| 348 | } | ||
| 349 | }) | ||
| 350 | |||
| 351 | // 删除分级 | ||
| 352 | const handleClassifyGradDataDel = async (item) => { | ||
| 353 | try { | ||
| 354 | // 弹出确认框 | ||
| 355 | await proxy.$confirm('此操作将永久删除该分级, 是否继续?', '提示', { | ||
| 356 | confirmButtonText: '确定', | ||
| 357 | cancelButtonText: '取消', | ||
| 358 | type: 'warning' | ||
| 359 | }); | ||
| 360 | const res: any = await deleteClassifyGrad({ guid: item.guid }); | ||
| 361 | if (res.code === proxy.$passCode) { | ||
| 362 | await getClassifyGradListData(); // 获取更新后的列表数据 | ||
| 363 | proxy.$ElMessage({ | ||
| 364 | type: 'success', | ||
| 365 | message: '删除成功!' | ||
| 366 | }); | ||
| 367 | } else { | ||
| 368 | proxy.$ElMessage.error(res.msg); // 显示错误信息 | ||
| 369 | } | ||
| 370 | } catch (error) { | ||
| 371 | if (error !== 'cancel') { | ||
| 372 | proxy.$ElMessage({ | ||
| 373 | type: 'info', | ||
| 374 | message: '已取消删除' | ||
| 375 | }); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | }; | ||
| 379 | |||
| 380 | // 编辑分级 | ||
| 381 | const handleClassifyGradDataEdit = (itemGradeName) => { | ||
| 382 | classifyGradGuid.value = itemGradeName.guid; | ||
| 383 | newCreateGradeStandardDialogInfo.value.visible = true; | ||
| 384 | newCreateGradeStandardDialogInfo.value.title = '编辑分级'; | ||
| 385 | newCreateGradeFormItems.value.forEach(item => { | ||
| 386 | item.default = itemGradeName.name | ||
| 387 | }) | ||
| 388 | } | ||
| 389 | |||
| 390 | // 配置分级 | ||
| 391 | const handleClassifyGradDataClick = (item) => { | ||
| 392 | console.log(item); | ||
| 223 | router.push({ | 393 | router.push({ |
| 224 | name: 'newCreateTemplate', | 394 | name: 'classifyGradEdit', |
| 225 | query: { | 395 | query: { |
| 226 | classStandardName: '分类分级模板' | 396 | guid: item.guid, |
| 397 | classClassifyGradName: item.name | ||
| 227 | } | 398 | } |
| 228 | }); | 399 | }); |
| 229 | |||
| 230 | } | 400 | } |
| 231 | 401 | ||
| 232 | const newCreateGrade = () => { | 402 | const newCreateGrade = () => { |
| 233 | 403 | newCreateGradeStandardDialogInfo.value.visible = true; | |
| 404 | newCreateGradeFormItems.value.forEach(item => item.default = ''); | ||
| 234 | } | 405 | } |
| 235 | 406 | ||
| 236 | /** | 407 | |
| 237 | * 分类分级模板 | 408 | |
| 238 | * | 409 | |
| 239 | */ | 410 | |
| 411 | |||
| 412 | /** ------------------------------- 分类分级模板 ------------------------------------- */ | ||
| 413 | |||
| 240 | const pageInfo = ref({ | 414 | const pageInfo = ref({ |
| 241 | limit: 50, | 415 | limit: 50, |
| 242 | curr: 1, | 416 | curr: 1, |
| ... | @@ -251,6 +425,16 @@ const pageInfo = ref({ | ... | @@ -251,6 +425,16 @@ const pageInfo = ref({ |
| 251 | rows: 0, | 425 | rows: 0, |
| 252 | }) | 426 | }) |
| 253 | 427 | ||
| 428 | const newCreateTemplate = () => { | ||
| 429 | router.push({ | ||
| 430 | name: 'newCreateTemplate', | ||
| 431 | query: { | ||
| 432 | classStandardName: '分类分级模板' | ||
| 433 | } | ||
| 434 | }); | ||
| 435 | } | ||
| 436 | |||
| 437 | |||
| 254 | const pageChange = (info) => { | 438 | const pageChange = (info) => { |
| 255 | pageInfo.value.curr = Number(info.curr); | 439 | pageInfo.value.curr = Number(info.curr); |
| 256 | pageInfo.value.limit = Number(info.limit); | 440 | pageInfo.value.limit = Number(info.limit); |
| ... | @@ -334,7 +518,8 @@ onBeforeMount(() => { | ... | @@ -334,7 +518,8 @@ onBeforeMount(() => { |
| 334 | <el-button type="primary" @click="newCreateGrade">新增分级</el-button> | 518 | <el-button type="primary" @click="newCreateGrade">新增分级</el-button> |
| 335 | </div> | 519 | </div> |
| 336 | <div class="data-content" v-loading="classListDataLoading"> | 520 | <div class="data-content" v-loading="classListDataLoading"> |
| 337 | <div class="card-content" v-for="item in classListData" :key="item.guid" @click="handleClassDataClick(item)"> | 521 | <div class="card-content" v-for="item in classifyGradListData" :key="item.guid" |
| 522 | @click="handleClassifyGradDataClick(item)"> | ||
| 338 | <div class="type-btn"> | 523 | <div class="type-btn"> |
| 339 | <el-popover v-model="cardBtnVisible" placement="bottom" width="96" trigger="click" | 524 | <el-popover v-model="cardBtnVisible" placement="bottom" width="96" trigger="click" |
| 340 | popper-class="tree-item-edit-menu" :show-arrow="false" :hide-after="0"> | 525 | popper-class="tree-item-edit-menu" :show-arrow="false" :hide-after="0"> |
| ... | @@ -344,9 +529,9 @@ onBeforeMount(() => { | ... | @@ -344,9 +529,9 @@ onBeforeMount(() => { |
| 344 | </el-icon> | 529 | </el-icon> |
| 345 | </template> | 530 | </template> |
| 346 | <div class="levitation-ul"> | 531 | <div class="levitation-ul"> |
| 347 | <span class="levitation-li" @click="handleClassDataClick(item)">配置</span> | 532 | <span class="levitation-li" @click="handleClassifyGradDataClick(item)">配置</span> |
| 348 | <span class="levitation-li" @click="handleClassDataEdit(item)">编辑</span> | 533 | <span class="levitation-li" @click="handleClassifyGradDataEdit(item)">编辑</span> |
| 349 | <span class="levitation-li" @click="handleClassDataDel(item)">删除</span> | 534 | <span class="levitation-li" @click="handleClassifyGradDataDel(item)">删除</span> |
| 350 | </div> | 535 | </div> |
| 351 | </el-popover> | 536 | </el-popover> |
| 352 | </div> | 537 | </div> |
| ... | @@ -354,10 +539,10 @@ onBeforeMount(() => { | ... | @@ -354,10 +539,10 @@ onBeforeMount(() => { |
| 354 | <svg-icon name="folder" /> | 539 | <svg-icon name="folder" /> |
| 355 | </el-icon> | 540 | </el-icon> |
| 356 | <div class="title">{{ item.name }}</div> | 541 | <div class="title">{{ item.name }}</div> |
| 357 | <div class="desc-row"> | 542 | <!-- <div class="desc-row"> |
| 358 | <div class="desc">{{ '分级标准' }}</div> | 543 | <div class="desc">{{ '分级标准' }}</div> |
| 359 | <div class="desc">{{ item.updateTime }}</div> | 544 | <div class="desc">{{ item.updateTime }}</div> |
| 360 | </div> | 545 | </div> --> |
| 361 | </div> | 546 | </div> |
| 362 | <div v-if="!classListData.length" class="card-noData"> | 547 | <div v-if="!classListData.length" class="card-noData"> |
| 363 | <img src="../../assets/images/no-data.png" :style="{ width: '96px', height: '96px' }" /> | 548 | <img src="../../assets/images/no-data.png" :style="{ width: '96px', height: '96px' }" /> |
| ... | @@ -366,6 +551,7 @@ onBeforeMount(() => { | ... | @@ -366,6 +551,7 @@ onBeforeMount(() => { |
| 366 | </div> | 551 | </div> |
| 367 | </div> | 552 | </div> |
| 368 | <Dialog_form :dialogConfigInfo="newCreateClassStandardDialogInfo" /> | 553 | <Dialog_form :dialogConfigInfo="newCreateClassStandardDialogInfo" /> |
| 554 | <Dialog_form :dialogConfigInfo="newCreateGradeStandardDialogInfo" /> | ||
| 369 | </div> | 555 | </div> |
| 370 | </template> | 556 | </template> |
| 371 | 557 | ... | ... |
-
Please register or sign in to post a comment