Commit 69a0700ef1f800d820814d21686d1e10559bde7f
Merge branch 'sqy_dev' into 'main'
feat:"转换脚本开发完成",fix:“菜单显示不正确修复”,feat:所属网关字段,图片样式调整 See merge request huang/yun-teng-iot-front!131
Showing
10 changed files
with
48 additions
and
77 deletions
| ... | ... | @@ -289,10 +289,8 @@ |
| 289 | 289 | } |
| 290 | 290 | const content = editor?.getContent() ?? ''; |
| 291 | 291 | const val = |
| 292 | - content?.replace( | |
| 293 | - getUploadingImgName(name), | |
| 294 | - `<img src="${url}" style="height:6rem;width:6rem"/>` | |
| 295 | - ) ?? ''; | |
| 292 | + content?.replace(getUploadingImgName(name), `<img src="${url}" style="width:8rem"/>`) ?? | |
| 293 | + ''; | |
| 296 | 294 | setValue(editor, val); |
| 297 | 295 | } |
| 298 | 296 | ... | ... |
| ... | ... | @@ -64,14 +64,14 @@ export const step1Schemas: FormSchema[] = [ |
| 64 | 64 | |
| 65 | 65 | onChange() { |
| 66 | 66 | setFieldsValue({ |
| 67 | - gateWayDeviceId: null, | |
| 67 | + gateWayId: null, | |
| 68 | 68 | }); |
| 69 | 69 | }, |
| 70 | 70 | }; |
| 71 | 71 | }, |
| 72 | 72 | }, |
| 73 | 73 | { |
| 74 | - field: 'gateWayDeviceId', | |
| 74 | + field: 'gateWayId', | |
| 75 | 75 | label: '网关设备', |
| 76 | 76 | required: true, |
| 77 | 77 | component: 'ApiSelect', | ... | ... |
| ... | ... | @@ -24,6 +24,11 @@ export const descSchema: DescItem[] = [ |
| 24 | 24 | label: '设备配置', |
| 25 | 25 | }, |
| 26 | 26 | { |
| 27 | + field: 'gatewayName', | |
| 28 | + label: '所属网关', | |
| 29 | + show: (data) => !!data.gatewayName, | |
| 30 | + }, | |
| 31 | + { | |
| 27 | 32 | field: 'deviceType', |
| 28 | 33 | label: '设备类型', |
| 29 | 34 | render: (text) => { |
| ... | ... | @@ -37,6 +42,7 @@ export const descSchema: DescItem[] = [ |
| 37 | 42 | { |
| 38 | 43 | field: 'description', |
| 39 | 44 | label: '描述', |
| 45 | + span: 2, | |
| 40 | 46 | }, |
| 41 | 47 | ]; |
| 42 | 48 | ... | ... |
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | <div class="tabs-detail"> |
| 3 | 3 | <div v-if="deviceDetail?.deviceInfo?.avatar"> |
| 4 | 4 | <p>设备图片</p> |
| 5 | - <Image :src="deviceDetail.deviceInfo.avatar" :width="100" /> | |
| 5 | + <Image :src="deviceDetail.deviceInfo.avatar" :width="200" /> | |
| 6 | 6 | </div> |
| 7 | 7 | <div> |
| 8 | 8 | <div class="flex" style="align-items: center"> | ... | ... |
| ... | ... | @@ -210,7 +210,7 @@ |
| 210 | 210 | async function handleEdit(record: Recordable) { |
| 211 | 211 | if (record.deviceType === 'SENSOR') { |
| 212 | 212 | const res = await getGATEWAY(record.tbDeviceId); |
| 213 | - Reflect.set(record, 'gateWayDeviceId', res.id); | |
| 213 | + Reflect.set(record, 'gateWayId', res.id); | |
| 214 | 214 | } |
| 215 | 215 | openModal(true, { |
| 216 | 216 | isUpdate: true, | ... | ... |
| ... | ... | @@ -38,6 +38,7 @@ |
| 38 | 38 | import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 |
| 39 | 39 | import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 |
| 40 | 40 | import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; |
| 41 | + | |
| 41 | 42 | const emit = defineEmits(['register', 'isStatus', 'success']); |
| 42 | 43 | const isUpdate = ref(false); |
| 43 | 44 | const aceEditor = ref(); |
| ... | ... | @@ -66,9 +67,9 @@ |
| 66 | 67 | mode: 'ace/mode/javascript', // 默认设置的语言模式 |
| 67 | 68 | tabSize: 2, // 制表符设置为 4 个空格大小 |
| 68 | 69 | }); |
| 70 | + | |
| 69 | 71 | aceEditor.value.setOptions({ |
| 70 | 72 | enableBasicAutocompletion: true, |
| 71 | - enableSnippets: true, | |
| 72 | 73 | enableLiveAutocompletion: true, |
| 73 | 74 | }); |
| 74 | 75 | aceEditor.value.setValue(jsScript ?? 'return {msg: msg, metadata: metadata};'); | ... | ... |
| ... | ... | @@ -98,8 +98,10 @@ |
| 98 | 98 | import ace from 'ace-builds'; |
| 99 | 99 | import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 |
| 100 | 100 | import 'ace-builds/src-noconflict/mode-javascript'; // 默认设置的语言模式 |
| 101 | - import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; | |
| 102 | - | |
| 101 | + import 'ace-builds/src-noconflict/ext-language_tools.js'; //语言提示 | |
| 102 | + import { beautify } from 'ace-builds/src-noconflict/ext-beautify.js'; //格式化 | |
| 103 | + // !!!important 重要,配置ace编辑器的错误提示,基础路径。否则会加载不到相关web Worker,就没有syntax validation提示 | |
| 104 | + ace.config.set('basePath', 'https://cdn.jsdelivr.net/npm/ace-builds@1.4.14/src-noconflict/'); | |
| 103 | 105 | defineComponent({ |
| 104 | 106 | Tooltip, |
| 105 | 107 | }); |
| ... | ... | @@ -141,11 +143,8 @@ |
| 141 | 143 | theme: 'ace/theme/chrome', // 默认设置的主题 |
| 142 | 144 | mode: 'ace/mode/javascript', // 默认设置的语言模式 |
| 143 | 145 | tabSize: 2, // 制表符设置为 2 个空格大小 |
| 144 | - }); | |
| 145 | - aceEditor.value.setOptions({ | |
| 146 | - enableBasicAutocompletion: true, | |
| 147 | - enableSnippets: true, | |
| 148 | - enableLiveAutocompletion: true, | |
| 146 | + enableBasicAutocompletion: true, //补全 | |
| 147 | + enableLiveAutocompletion: true, // | |
| 149 | 148 | }); |
| 150 | 149 | } |
| 151 | 150 | const mataData: any = { |
| ... | ... | @@ -194,12 +193,12 @@ |
| 194 | 193 | }; |
| 195 | 194 | |
| 196 | 195 | // 测试 |
| 197 | - const handleTestFunc = () => { | |
| 196 | + const handleTestFunc = async () => { | |
| 198 | 197 | // 收集3方数据 |
| 199 | - const msg = JsonEditor.value.get(); | |
| 200 | - const metadata = mataData; | |
| 201 | - const jsCode = aceEditor.value.getValue(); | |
| 202 | 198 | try { |
| 199 | + const msg = JsonEditor.value.get(); | |
| 200 | + const metadata = mataData; | |
| 201 | + const jsCode = aceEditor.value.getValue(); | |
| 203 | 202 | // 执行动态Javascript脚本 |
| 204 | 203 | let result = Function('msg', 'metadata', jsCode)(msg, metadata); |
| 205 | 204 | // 设置输出值 | ... | ... |
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | <template #menu="{ model, field }"> |
| 12 | 12 | <BasicTree |
| 13 | 13 | v-if="treeData.length > 0" |
| 14 | - ref="tree" | |
| 14 | + ref="treeRef" | |
| 15 | 15 | v-model:value="model[field]" |
| 16 | 16 | :treeData="treeData" |
| 17 | 17 | :replaceFields="{ title: 'menuName' }" |
| ... | ... | @@ -19,7 +19,6 @@ |
| 19 | 19 | checkable |
| 20 | 20 | toolbar |
| 21 | 21 | title="菜单分配" |
| 22 | - @check="handleCheckClick" | |
| 23 | 22 | :defaultExpandAll="true" |
| 24 | 23 | /> |
| 25 | 24 | </template> |
| ... | ... | @@ -27,7 +26,7 @@ |
| 27 | 26 | </BasicDrawer> |
| 28 | 27 | </template> |
| 29 | 28 | <script lang="ts"> |
| 30 | - import { defineComponent, ref, computed, unref, getCurrentInstance } from 'vue'; | |
| 29 | + import { defineComponent, ref, computed, unref } from 'vue'; | |
| 31 | 30 | import { BasicForm, useForm } from '/@/components/Form/index'; |
| 32 | 31 | import { formSchema } from './role.data'; |
| 33 | 32 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| ... | ... | @@ -47,20 +46,20 @@ |
| 47 | 46 | components: { BasicDrawer, BasicForm, BasicTree }, |
| 48 | 47 | emits: ['success', 'register'], |
| 49 | 48 | setup(_, { emit }) { |
| 50 | - const { proxy } = getCurrentInstance(); | |
| 51 | 49 | const isUpdate = ref<boolean>(true); |
| 52 | 50 | const treeData = ref<TreeItem[]>([]); |
| 53 | 51 | const roleMenus = ref<string[]>([]); |
| 54 | - const allCheckedKeys = ref<string[]>([]); | |
| 55 | 52 | const roleId = ref<string>(''); |
| 53 | + const treeRef = ref(); | |
| 56 | 54 | const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ |
| 57 | - labelWidth: 90, | |
| 55 | + labelWidth: 100, | |
| 58 | 56 | schemas: formSchema, |
| 59 | 57 | showActionButtonGroup: false, |
| 60 | 58 | }); |
| 61 | 59 | |
| 60 | + // 递归函数,将RouteItem里面的字段换名称 | |
| 62 | 61 | function processChildren(items: RouteItem[]) { |
| 63 | - items.map((item) => { | |
| 62 | + items.forEach((item) => { | |
| 64 | 63 | item.menuName = t(item.meta.title); |
| 65 | 64 | item.icon = item.meta.icon; |
| 66 | 65 | item.key = item.id; |
| ... | ... | @@ -83,43 +82,31 @@ |
| 83 | 82 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { |
| 84 | 83 | resetFields(); |
| 85 | 84 | roleId.value = ''; |
| 86 | - setDrawerProps({ confirmLoading: false }); | |
| 87 | 85 | isUpdate.value = data.isUpdate; |
| 88 | 86 | // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 |
| 89 | - if (unref(treeData).length === 0) { | |
| 87 | + if (!unref(treeData).length) { | |
| 90 | 88 | // 获取全部的菜单 |
| 91 | 89 | const menuListModel = await getMenuList(); |
| 92 | 90 | processChildren(menuListModel); |
| 93 | - let treeValues: TreeItem[] = []; | |
| 94 | - menuListModel.map((item) => { | |
| 95 | - const data = { | |
| 96 | - menuName: t(item.meta.title), | |
| 97 | - icon: item.meta.icon, | |
| 98 | - key: item.id, | |
| 99 | - children: item.children as any as TreeItem[], | |
| 100 | - }; | |
| 101 | - treeValues.push(data); | |
| 102 | - }); | |
| 103 | - treeData.value = treeValues; | |
| 91 | + treeData.value = menuListModel; | |
| 92 | + // console.log(treeData.value); | |
| 104 | 93 | } |
| 105 | 94 | |
| 95 | + // 更新 | |
| 106 | 96 | if (unref(isUpdate)) { |
| 107 | - if (data.record) { | |
| 108 | - //通过角色id去获取角色对应的菜单的ids | |
| 109 | - roleMenus.value = await getMenusIdsByRoleId(data.record.id); | |
| 110 | - treeData.value.map((m) => { | |
| 111 | - roleMenus.value.map((m1) => { | |
| 112 | - if (m.key === m1 && m.children.length !== 0) { | |
| 113 | - proxy.useChildrenIdsRemoveParentId(m1, roleMenus.value); | |
| 114 | - } | |
| 115 | - }); | |
| 97 | + //通过角色id去获取角色对应的菜单的ids | |
| 98 | + roleMenus.value = await getMenusIdsByRoleId(data.record.id); | |
| 99 | + // TODO: 此处算法还可以优化一下。 循环跑了200+次 | |
| 100 | + treeData.value.map((m) => { | |
| 101 | + roleMenus.value.map((m1) => { | |
| 102 | + if (m.key === m1 && m.children.length) { | |
| 103 | + useChildrenIdsRemoveParentId(m1, roleMenus.value); | |
| 104 | + } | |
| 116 | 105 | }); |
| 117 | - proxy.$refs.tree.setCheckedKeys(roleMenus.value); | |
| 118 | - roleId.value = data.record.id; | |
| 119 | - } | |
| 120 | - setFieldsValue({ | |
| 121 | - ...data.record, | |
| 122 | 106 | }); |
| 107 | + treeRef.value.setCheckedKeys(roleMenus.value); | |
| 108 | + roleId.value = data.record.id; | |
| 109 | + setFieldsValue(data.record); | |
| 123 | 110 | } |
| 124 | 111 | }); |
| 125 | 112 | |
| ... | ... | @@ -134,7 +121,7 @@ |
| 134 | 121 | name: values.name, |
| 135 | 122 | remark: values.remark, |
| 136 | 123 | status: values.status, |
| 137 | - menu: allCheckedKeys.value as string[], | |
| 124 | + menu: treeRef.value.getCheckedKeys(), | |
| 138 | 125 | }; |
| 139 | 126 | saveOrUpdateRoleInfoWithMenu(req).then(() => { |
| 140 | 127 | closeDrawer(); |
| ... | ... | @@ -144,30 +131,15 @@ |
| 144 | 131 | setDrawerProps({ confirmLoading: false }); |
| 145 | 132 | } |
| 146 | 133 | } |
| 147 | - // Tree check事件 | |
| 148 | - const handleCheckClick = (_, e) => { | |
| 149 | - allCheckedKeys.value = []; | |
| 150 | - let nodes = e.checkedNodes; | |
| 151 | - let halfKeys = e.halfCheckedKeys; | |
| 152 | - nodes.map((node) => { | |
| 153 | - if (node.key != halfKeys[0] && halfKeys.length == []) { | |
| 154 | - allCheckedKeys.value.push(node.key); | |
| 155 | - } else { | |
| 156 | - allCheckedKeys.value.push(node.key); | |
| 157 | - } | |
| 158 | - }); | |
| 159 | - allCheckedKeys.value.push(...halfKeys); | |
| 160 | - }; | |
| 161 | 134 | return { |
| 162 | - allCheckedKeys, | |
| 163 | 135 | registerDrawer, |
| 164 | 136 | registerForm, |
| 165 | 137 | getTitle, |
| 166 | 138 | handleSubmit, |
| 167 | 139 | treeData, |
| 168 | 140 | roleMenus, |
| 169 | - handleCheckClick, | |
| 170 | 141 | useChildrenIdsRemoveParentId, |
| 142 | + treeRef, | |
| 171 | 143 | }; |
| 172 | 144 | }, |
| 173 | 145 | }); | ... | ... |
| ... | ... | @@ -34,10 +34,8 @@ |
| 34 | 34 | </template> |
| 35 | 35 | <script lang="ts"> |
| 36 | 36 | import { defineComponent } from 'vue'; |
| 37 | - | |
| 38 | 37 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 39 | 38 | import { delRole, getRoleListByPage } from '/@/api/system/system'; |
| 40 | - | |
| 41 | 39 | import { useDrawer } from '/@/components/Drawer'; |
| 42 | 40 | import RoleDrawer from './RoleDrawer.vue'; |
| 43 | 41 | import { columns, searchFormSchema } from './role.data'; | ... | ... |