customer_list/yw/static/config/globalConfig.spump.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
customer_list/yw/static/config/globalConfig.test.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/dimension/index.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/dimensionMgr/DimensionMgr.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/dimensionMgr/components/OptDlg.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/dimensionMgr/components/TagInput.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/dimensionMgr/components/constants.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
customer_list/yw/static/config/globalConfig.spump.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ window.globalConfig = { // 项ç®åç§° Name: 'WIæ°´å¡æºè½', // 项ç®çæ¬å· Version: '1.0.0242', // ç½ç«å¤æ¡å· ICPLicense: '沪ICPå¤14049296å·-2', WebApiUrl: { MainUrl: 'http://47.100.245.85:8802/', AuthUrl: 'http://47.100.245.85:8190/', }, SoftWareInfo: { // ç½ç«ä¸»æ é¢ï¼èå导èªãæµè§å¨å½åç½é¡µæ é¢ï¼ globalTitle: 'WIæ°´å¡æºè½', // ç½ç«å¯æ é¢ï¼ç»å½é¡µé¡¶é¨æåï¼ globalViceTitle: 'WIæ°´å¡æºè½', // ç½ç«å¯æ é¢ï¼ç»å½é¡µé¡¶é¨æåï¼ globalViceTitleMsg: 'æç¦é¡å¡ææºè½ç§ææéå ¬å¸', // tab 页 icon favicon: './favicon.ico', // ç»å½å·¦ä¾§ logo logoMini: './static/images/logo/logoWithNoName.png', // ç»å½å·¦ä¾§å¾ç loginMain: './static/images/login/login-main.svg', // ç»å½èæ¯ loginBg: './static/images/login/login-bg.svg', // 主页é¢å·¦ä¸ logo logoTopMenu: './static/images/logo/logo-mini-white.png', }, // å¯¹æ¥æéç³»ç»ç¸å ³ Auth: { // ç»å½è½¯ä»¶ç¼ç SoftWareCode: 'Istation_web_demo', // ç»å½ä¿¡æ¯ Message: '', }, }; customer_list/yw/static/config/globalConfig.test.js
@@ -7,9 +7,9 @@ ICPLicense: '沪ICPå¤14049296å·-2', WebApiUrl: { MainUrl: 'https://widev.cpolar.top/ai_dev/', // MainUrl: 'https://widev.cpolar.top/ai_dev/', // MainUrl: 'http://192.168.1.58:8080/', // MainUrl: 'http://192.168.1.41:8080/', MainUrl: 'http://192.168.1.41:8080/', AuthUrl: 'http://47.100.245.85:8190/', src/api/dimension/index.ts
@@ -1,4 +1,5 @@ import request, { ExtraConfig } from '/@/utils/request'; import type { ExtraConfig } from '/@/utils/request'; import request from '/@/utils/request'; /** * @description è·å维度åç§°å表 @@ -11,3 +12,27 @@ data: {}, ...extraData, }); /** * @description æ°å¢ç»´åº¦ * @param {FormData} params **/ export const addDimensionByPost = (params) => request({ url: `/admin/dimension/add_dimension`, method: 'post', params: {}, data: params, }); /** * @description ä¿®æ¹ç»´åº¦ * @param {FormData} params **/ export const updateDimensionByPost = (params) => request({ url: `/admin/dimension/update_dimension`, method: 'post', params: {}, data: params, }); src/views/project/yw/systemManage/dimensionMgr/DimensionMgr.vue
@@ -29,7 +29,7 @@ <el-form-item> <!-- <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> æ¥è¯¢ </el-button> --> <el-button icon="ele-Refresh" @click="resetQuery">éç½® </el-button> <!-- <el-button icon="ele-Plus" @click="openOptDlg()"> æ·»å </el-button> --> <el-button type="primary" icon="ele-Plus" @click="openOptDlg()"> æ·»å </el-button> </el-form-item> </el-form> </template> @@ -71,7 +71,11 @@ </el-table-column> <el-table-column label="åä½" prop="unit" width="100" show-overflow-tooltip> </el-table-column> <el-table-column label="ç±»å" prop="type" width="100" show-overflow-tooltip> </el-table-column> <el-table-column label="ç±»å" prop="type" width="100" show-overflow-tooltip> <template #default="scope"> {{ DimensionTypeMap[scope.row.type] }} </template> </el-table-column> <el-table-column label="æä½" width="150" fixed="right" show-overflow-tooltip> <template #default="scope"> @@ -82,6 +86,9 @@ @click="openAliasDisplayDlg(scope.row)" ></i> </el-tooltip> <el-tooltip effect="dark" content="ç¼è¾" placement="top"> <i class="ywifont ywicon-bianji !text-[15px] text-blue-400 cursor-pointer" @click="openOptDlg(scope.row)"></i> </el-tooltip> </div> </template> </el-table-column> @@ -89,28 +96,43 @@ </div> </template> <AliasDisplayDlg v-model="aliasDisplayDlgIsShow" :item="aliasDisplayDlgMapRow"></AliasDisplayDlg> <!-- <OptDlg v-model="optDlgIsShow" :item="optDlgMapRow" @insert="insertOpt" @update="updateOpt" :groupId="currentListID"></OptDlg> --> <OptDlg :groupId="queryParams.group" v-model="optDlgIsShow" :listTreeData="listTreeData" :item="optDlgMapRow" @insert="insertOpt" @update="updateOpt" :tableData="tableData" :dataSources="dataSources" ></OptDlg> <!-- <MetricPrompt v-model="infoDlgIsShow" :metricItem="infoDlgMapRow"></MetricPrompt> <MetricName v-model="metricNameIsShow" :metricItem="metricNameMapRow"></MetricName> --> </HMContainer> </template> <script setup lang="ts"> import { convertListToTree, debounce, getItemMap } from '/@/utils/util'; import { convertListToTree, debounce, getItemMap, travelTree } from '/@/utils/util'; import { computed, onMounted, ref } from 'vue'; import { usePageDisplay } from '/@/hooks/usePageDisplay'; import { useQueryTable } from '/@/hooks/useQueryTable'; // import { useTableSort } from '/@/hooks/useTableSort'; // import { useValidateUniqueness } from '/@/hooks/useValidateUniqueness'; import { SupervisorPublished } from '../../lowCode/sqlAmis/types'; import type { SupervisorPublished } from '../../lowCode/sqlAmis/types'; import AliasDisplayDlg from './components/AliasDisplayDlg.vue'; import { DimensionTypeMap } from './components/constants'; import OptDlg from './components/OptDlg.vue'; import { getDataSourceList } from '/@/api/dataSource'; import * as dimensionApi from '/@/api/dimension'; import { getSceneGroupTreeByPost } from '/@/api/scene'; import HMContainer from '/@/components/layout/HMContainer.vue'; import { OptClassificationMap, classificationEnum } from '/@/views/types/metrics'; import { ElMessage } from 'element-plus'; const dataSources = ref([]); const initDataSources = async () => { const res = await getDataSourceList(); dataSources.value = res.values; }; const themeDomainData = ref([]); const initThemeDomainData = async () => { const res = await getSceneGroupTreeByPost(); @@ -188,18 +210,62 @@ optDlgIsShow.value = true; }; const updateOpt = (formValue) => { const foundIndex = tableData.value.findIndex((item) => item.id === formValue.id); const updateOptData = (optData, formValue) => { const foundIndex = optData.findIndex((item) => item.id === formValue.id); if (foundIndex > -1) { tableData.value[foundIndex] = { ...tableData.value[foundIndex], optData[foundIndex] = { ...optData[foundIndex], ...formValue, }; } }; const updateOpt = (formValue) => { if (formValue.group === queryParams.value.group || queryParams.value.group === '') { updateOptData(displayTableData.value, formValue); updateOptData(tableData.value, formValue); } else { displayTableData.value = displayTableData.value.filter((item) => item.group !== formValue.group); updateOptData(tableData.value, formValue); } }; const insertOptData = (optData, newData) => { optData.unshift({ ...newData }); }; // 夿æ¯å¦å±äºå½å主é¢åï¼æå½æä¸»é¢åä¸å±ä¸»é¢å const isIncludeGroup = (group, currentGroup) => { if (!currentGroup) return true; if (group === currentGroup) return true; let curGroupItem; travelTree(listTreeData.value, (item) => { if (item.group_id === currentGroup) { curGroupItem = item; return true; } }); if (!curGroupItem) return false; let isFind = false; travelTree(curGroupItem.Children as any[], (item) => { if (item.group_id === group) { isFind = true; return true; } }); return isFind; }; const insertOpt = (newData) => { tableData.value.unshift({ ...newData, published: SupervisorPublished.N }); if (newData.group === queryParams.value.group || queryParams.value.group === '') { insertOptData(displayTableData.value, newData); insertOptData(tableData.value, newData); } else { insertOptData(tableData.value, newData); } }; //#endregion @@ -250,8 +316,6 @@ return isExist; }; const openAliasDisplayDlg = (row) => { aliasDisplayDlgMapRow.value = row; aliasDisplayDlgIsShow.value = true; }; @@ -260,6 +324,7 @@ onMounted(() => { getTableData(); initThemeDomainData(); initDataSources(); }); </script> <style scoped lang="scss"></style> src/views/project/yw/systemManage/dimensionMgr/components/OptDlg.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,341 @@ <template> <ywDialog v-model="dialogIsShow" :headerIcon="dialogHeaderIcon" :title="dialogTitle" width="470" @dlgClosed="closeDialog" @submit="submitFormValue" > <el-form :model="dialogFormValue" ref="dialogFormRef" :rules="dialogFormRules" label-width="96"> <el-form-item label="维度ID" prop="dim_id" v-if="!isEditDialog"> <el-input v-model="dialogFormValue.dim_id"></el-input> </el-form-item> <el-form-item label="å®ä¹" prop="dim_title"> <el-input type="textarea" :rows="3" v-model="dialogFormValue.dim_title"></el-input> </el-form-item> <el-form-item label="ç±»å" prop="dim_type"> <el-select v-model="dialogFormValue.dim_type"> <el-option v-for="item in Object.keys(DimensionTypeMap)" :key="item" :value="item" :label="DimensionTypeMap[item]" ></el-option> </el-select> </el-form-item> <el-form-item label="å«å" prop="dim_alias"> <div class="flex flex-col gap-2"> <div class="flex flex-col gap-3"> <div class="flex items-center gap-2" v-for="(item, index) in editAlias" :key="index"> <el-input v-model="item.key" class="w-[60px] flex-0 mb-auto font-bold"></el-input> <TagInput class="flex-auto mt-1" v-model="item.value" /> <el-button size="small" type="danger" circle @click="deleteAlias(index)"> <el-icon><Delete /></el-icon> </el-button> </div> </div> <el-button size="small" type="primary" @click="addAlias">æ·»å å«å</el-button> </div> </el-form-item> <el-form-item label="åç§°" prop="dim_name"> <el-input v-model="dialogFormValue.dim_name"></el-input> </el-form-item> <el-form-item label="主é¢å" prop="dim_group"> <el-tree-select filterable :props="{ id: 'group_id', label: 'group_name', children: 'Children', }" v-model="dialogFormValue.dim_group" node-key="group_id" clearable defaultExpandAll :data="listTreeData" placeholder="è¯·éæ©ä¸»é¢å" check-strictly > </el-tree-select> </el-form-item> <el-form-item label="åä½" prop="dim_unit"> <el-input v-model="dialogFormValue.dim_unit"></el-input> </el-form-item> <el-form-item label="å¼å表" prop="dim_value_list"> <div class="flex flex-col gap-2 w-full"> <el-select v-model="activeValueListType" @change="changeValueListType"> <el-option v-for="item in Object.keys(ValueListTypeMap)" :key="item" :value="item" :label="ValueListTypeMap[item]" ></el-option> </el-select> <!-- <el-input v-model="dialogFormValue.dim_value_list" type="textarea" :rows="3"></el-input> --> <TagInput v-if="activeValueListType === ValueListType.Value" class="flex-auto mt-1" v-model="dialogFormValue.dim_value_list.values" /> <el-input placeholder="请è¾å ¥SQLè¯å¥" v-if="activeValueListType === ValueListType.Sql" v-model="dialogFormValue.dim_value_list.sql.sql" type="textarea" :rows="3" ></el-input> <el-select placeholder="è¯·éæ©æ°æ®åº" v-if="activeValueListType === ValueListType.Sql" v-model="dialogFormValue.dim_value_list.sql.ds_id"> <el-option v-for="item in dataSources" :key="item.id" :label="item.title" :value="item.id"></el-option> </el-select> </div> </el-form-item> </el-form> </ywDialog> </template> <script setup lang="ts"> import type { FormInstance, FormRules } from 'element-plus'; import { ElMessage } from 'element-plus'; import { storeToRefs } from 'pinia'; import { computed, ref, watch } from 'vue'; import * as dimensionApi from '/@/api/dimension'; import ywDialog from '/@/components/dialog/yw-dialog.vue'; import { useUserInfo } from '/@/stores/userInfo'; import { formatDate } from '/@/utils/formatTime'; import { deepClone } from '/@/utils/other'; import TagInput from './TagInput.vue'; import { DimensionTypeMap } from './constants'; import { getDataSourceList } from '/@/api/dataSource'; const enum ValueListType { Sql = 'sql', Value = 'value', } const activeValueListType = ref(ValueListType.Value); const ValueListTypeMap = { [ValueListType.Sql]: 'SQLæ¥è¯¢', [ValueListType.Value]: 'å¼è¾å ¥', }; const getEmptyValueList = (type = activeValueListType.value) => { return type === ValueListType.Sql ? { sql: { ds_id: '', sql: '', }, } : { values: [], }; }; const changeValueListType = (val) => { dialogFormValue.value.dim_value_list = getEmptyValueList(val); }; const checkIsSql = (valueList) => { return valueList && valueList.hasOwnProperty('sql'); }; const checkIsEmptyValueList = (valueList) => { if (!checkIsSql(valueList)) { return valueList.values.length === 0; } return valueList.sql.ds_id === '' && valueList.sql.sql === ''; }; const props = defineProps(['item', 'groupId', 'listTreeData', 'tableData', 'dataSources']); const emit = defineEmits(['update', 'insert']); const addAlias = () => { editAlias.value.push({ key: '', value: [], }); }; const deleteAlias = (index) => { editAlias.value.splice(index, 1); }; //#region ====================== å¢å ãä¿®æ¹è®°å½æä½, dialog init====================== const isEditDialog = ref(false); const dialogTitle = computed(() => { return isEditDialog.value ? 'ä¿®æ¹ç»´åº¦' : 'æ·»å 维度'; }); const dialogHeaderIcon = computed(() => { return isEditDialog.value ? 'ele-Edit' : 'ele-Plus'; }); const dialogFormValue = ref(null); const dialogIsShow = defineModel({ type: Boolean, }); const dialogFormRef = ref<FormInstance>(null); const dialogFormRules = ref<FormRules>({ dim_id: [ { required: true, message: '请è¾å ¥ç»´åº¦ID', trigger: 'blur' }, { validator: (rule, value, callback) => { if (!value) { callback(); return; } const existItem = props.tableData.find((item) => item.id === value); if (existItem) { callback(new Error('维度IDå·²åå¨')); return; } callback(); }, trigger: 'blur', }, ], dim_title: [{ required: true, message: '请è¾å ¥ç»´åº¦å®ä¹', trigger: 'blur' }], dim_type: [{ required: true, message: 'è¯·éæ©ç»´åº¦ç±»å', trigger: 'change' }], dim_name: [{ required: true, message: '请è¾å ¥ç»´åº¦åç§°', trigger: 'blur' }], }); const editAlias = ref([]); const openOperateDialog = (row?) => { if (row) { isEditDialog.value = true; const { id: dim_id, prompt: dim_title, type: dim_type, alias: dim_alias, title: dim_name, group: dim_group, unit: dim_unit, dimValueList: dim_value_list, } = row; dialogFormValue.value = deepClone({ dim_id, dim_title, dim_type, dim_alias, dim_name, dim_group, dim_unit, dim_value_list, }); } else { isEditDialog.value = false; dialogFormValue.value = { dim_id: null, dim_title: null, dim_type: null, dim_alias: {}, dim_name: null, dim_group: props.groupId, dim_unit: null, dim_value_list: null, }; } editAlias.value = Object.keys(dialogFormValue.value.dim_alias ?? {}).map((item) => { return { key: item, value: dialogFormValue.value.dim_alias[item], }; }); dialogFormValue.value.dim_value_list = dialogFormValue.value.dim_value_list ?? getEmptyValueList(); activeValueListType.value = checkIsSql(dialogFormValue.value.dim_value_list) ? ValueListType.Sql : ValueListType.Value; console.log("ð ~ dialogFormValue.value.dim_value_list:", dialogFormValue.value.dim_value_list) }; const closeDialog = () => { dialogIsShow.value = false; dialogFormRef.value?.clearValidate(); }; const stores = useUserInfo(); const { userInfos } = storeToRefs(stores); const checkAlias = () => { for (const item of editAlias.value) { if (!item.key) { ElMessage.error('å«åçé®ä¸è½ä¸ºç©º'); return false; } } const keyCount = editAlias.value.reduce((acc, item) => { acc[item.key] = (acc[item.key] || 0) + 1; return acc; }, {}); for (const key in keyCount) { if (keyCount[key] > 1) { ElMessage.error(`å«åçé® "${key}" éå¤åºç°`); return false; } } return true; }; const submitFormValue = async () => { const valid = await dialogFormRef.value?.validate().catch(() => {}); if (!valid) return; if (!checkAlias()) return; dialogFormValue.value.dim_alias = editAlias.value.reduce((acc, item) => { acc[item.key] = item.value; return acc; }, {}); const sendForm = { ...dialogFormValue.value, dim_alias: JSON.stringify(dialogFormValue.value.dim_alias), dim_value_list: checkIsEmptyValueList(dialogFormValue.value.dim_value_list) ? null : JSON.stringify(dialogFormValue.value.dim_value_list), }; if (isEditDialog.value) { const res = await dimensionApi.updateDimensionByPost(sendForm); emit('update', { id: dialogFormValue.value.dim_id, prompt: dialogFormValue.value.dim_title, type: dialogFormValue.value.dim_type, alias: dialogFormValue.value.dim_alias, title: dialogFormValue.value.dim_name, group: dialogFormValue.value.dim_group, unit: dialogFormValue.value.dim_unit, dimValueList: dialogFormValue.value.dim_value_list, }); closeDialog(); ElMessage.success('ä¿®æ¹ç»´åº¦æå'); } else { const res = await dimensionApi.addDimensionByPost(sendForm); const newData = { id: dialogFormValue.value.dim_id, prompt: dialogFormValue.value.dim_title, type: dialogFormValue.value.dim_type, alias: dialogFormValue.value.dim_alias, title: dialogFormValue.value.dim_name, group: dialogFormValue.value.dim_group, unit: dialogFormValue.value.dim_unit, dimValueList: dialogFormValue.value.dim_value_list, }; emit('insert', newData); closeDialog(); ElMessage.success('æ·»å 维度æå'); } }; //#endregion watch( () => dialogIsShow.value, (val) => { if (!val) return; openOperateDialog(props.item); } ); </script> <style scoped lang="scss"></style> src/views/project/yw/systemManage/dimensionMgr/components/TagInput.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,61 @@ <template> <div class="flex gap-2 flex-wrap"> <el-tag v-for="tag in dynamicTags" :key="tag" closable :disable-transitions="false" @close="handleClose(tag)"> {{ tag }} </el-tag> <el-input v-if="inputVisible" ref="InputRef" v-model="inputValue" class="w-32" size="small" @keyup.enter="handleInputConfirm" @blur="handleInputConfirm" /> <el-button v-else class="button-new-tag" size="small" @click="showInput"> + {{ newLabel }} </el-button> </div> </template> <script lang="ts" setup> import { nextTick, ref } from 'vue'; import { ElInput } from 'element-plus'; import type { InputInstance } from 'element-plus'; const props = defineProps({ newLabel: { type: String, default: 'æ·»å ', }, }); const inputValue = ref(''); const dynamicTags = defineModel({ type: Array<string>, }); const inputVisible = ref(false); const InputRef = ref<InputInstance>(); const handleClose = (tag: string) => { dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); }; const showInput = () => { inputVisible.value = true; nextTick(() => { InputRef.value!.input!.focus(); }); }; const handleInputConfirm = () => { if (inputValue.value) { if (!dynamicTags.value) { dynamicTags.value = [inputValue.value]; } else { dynamicTags.value.push(inputValue.value); } } inputVisible.value = false; inputValue.value = ''; }; </script> src/views/project/yw/systemManage/dimensionMgr/components/constants.ts
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,15 @@ export const enum DimensionType { String = 'S', Double = 'D', Integer = 'I', Long = 'L', Time = 'T', } export const DimensionTypeMap = { [DimensionType.String]: 'å符串', [DimensionType.Double]: 'æµ®ç¹æ°', [DimensionType.Integer]: 'æ´æ°', [DimensionType.Long]: 'é¿æ´æ°', [DimensionType.Time]: 'æ¶é´', };