diff --git a/src/api/data-collect/collector.ts b/src/api/data-collect/collector.ts index b90fe629..df3d219d 100644 --- a/src/api/data-collect/collector.ts +++ b/src/api/data-collect/collector.ts @@ -68,4 +68,20 @@ export const getSnapTypes = () => server.get('/s7/client/s7codecs/list') export const getArea = () => server.get('/s7/client/s7area/list') -export const exportTemplate = (provider: string, format: string) =>server.get(`/data-collect/point/${provider}/template.${format}`, {}, {responseType: 'blob'}) \ No newline at end of file +export const exportTemplate = (provider: string, format: string) =>server.get(`/data-collect/point/${provider}/template.${format}`, {}, {responseType: 'blob'}) + +/** + * BACNet协议扫描对象 + * @param channelId 通道id + * @param instanceNumber 设备实例号 + */ +export const getBacnetObjectList = (channelId: string, instanceNumber: string) => server.get(`/collect/bacnet/${channelId}/${instanceNumber}/objects`); + +/** + * 查询未使用的属性id + * @param data 采集器Id + */ +export const getBacnetPropertyIdNotUse = (data: any) => server.post(`/collect/bacnet/${data.collectorId}/unused/ids`, data) + +/**查询bacnet值类型*/ +export const getBacnetValueType = () => server.get(`/collect/bacnet/value/types`) \ No newline at end of file diff --git a/src/components/RadioCard/index.vue b/src/components/RadioCard/index.vue index e29c8c76..d66d59fb 100644 --- a/src/components/RadioCard/index.vue +++ b/src/components/RadioCard/index.vue @@ -96,6 +96,7 @@ const handleRadio = (item: any) => { display: flex; flex-wrap: wrap; justify-content: space-between; + gap: 24px; .disabled { >div { color: rgba(0, 0, 0, 0.25); @@ -105,7 +106,7 @@ const handleRadio = (item: any) => { } &-item { - width: 49%; + flex:1; height: 70px; padding: 10px 15px; margin-bottom: 12px; @@ -113,7 +114,7 @@ const handleRadio = (item: any) => { border-radius: 2px; display: flex; align-items: center; - gap: 24px; + cursor: pointer; .img { width: 32px; diff --git a/src/store/menu.ts b/src/store/menu.ts index 2e573be3..bbd6e2c3 100644 --- a/src/store/menu.ts +++ b/src/store/menu.ts @@ -40,7 +40,7 @@ const defaultOwnParams = [ column: "options" } ], - type:'or' + type:'and' } ] } diff --git a/src/utils/consts.ts b/src/utils/consts.ts index ac738daf..7763787c 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -58,5 +58,6 @@ export const protocolList = [ { label: 'MODBUS_TCP', value: 'MODBUS_TCP', alias: 'Modbus/TCP' }, { label: 'COLLECTOR_GATEWAY', value: 'COLLECTOR_GATEWAY', alias: 'GATEWAY' }, { label: 'S7', value: 'snap7', alias: 'snap7' }, - { label: 'IEC104', value: 'iec104', alias: 'IEC104' } + { label: 'IEC104', value: 'iec104', alias: 'IEC104' }, + { label: 'BACNetIp', value: 'BACNetIp', alias: 'BACNet/IP' } ] diff --git a/src/views/DataCollect/Channel/Save/index.vue b/src/views/DataCollect/Channel/Save/index.vue index 69c827fd..b0a11b75 100644 --- a/src/views/DataCollect/Channel/Save/index.vue +++ b/src/views/DataCollect/Channel/Save/index.vue @@ -1,4 +1,4 @@ - + - + + + + + + + + + + + + + + + {{ unSelectKeys }} + + + + + + + {{ name }} + + + + + + + + + + + + + + + + diff --git a/src/views/DataCollect/Collector/Point/ScanBacnet/index.vue b/src/views/DataCollect/Collector/Point/ScanBacnet/index.vue new file mode 100644 index 00000000..43269069 --- /dev/null +++ b/src/views/DataCollect/Collector/Point/ScanBacnet/index.vue @@ -0,0 +1,105 @@ + + + + + + + + 取消 + + 确认 + + + + + + + diff --git a/src/views/DataCollect/Collector/Point/components/BatchUpdate/index.vue b/src/views/DataCollect/Collector/Point/components/BatchUpdate/index.vue index 70066ea3..4bbc9228 100644 --- a/src/views/DataCollect/Collector/Point/components/BatchUpdate/index.vue +++ b/src/views/DataCollect/Collector/Point/components/BatchUpdate/index.vue @@ -8,7 +8,7 @@ > 将批量修改 - {{ data.length }} 条数据的访问类型、采集频率、只推送变化的数据 + {{ data.length }} 条数据的【{{ labelName.join(',') }}】 + + + {{ item }} + + \ No newline at end of file + diff --git a/src/views/device/Instance/Detail/Info/components/Config/index.vue b/src/views/device/Instance/Detail/Info/components/Config/index.vue index f8951390..781d0777 100644 --- a/src/views/device/Instance/Detail/Info/components/Config/index.vue +++ b/src/views/device/Instance/Detail/Info/components/Config/index.vue @@ -143,15 +143,15 @@ const instanceStore = useInstanceStore(); const visible = ref(false); const config = ref([]); -watchEffect(() => { - if (instanceStore.current.id) { - getConfigMetadata(instanceStore.current.id).then((resp) => { +watch(()=>instanceStore.current.id,(val) => { + if (val) { + getConfigMetadata(val).then((resp) => { if (resp.status === 200) { config.value = resp?.result as ConfigMetadata[]; } }); } -}); +},{ immediate: true }); const isExit = (property: string) => { return ( diff --git a/src/views/device/Instance/Detail/Log/index.vue b/src/views/device/Instance/Detail/Log/index.vue index 570078ba..16561171 100644 --- a/src/views/device/Instance/Detail/Log/index.vue +++ b/src/views/device/Instance/Detail/Log/index.vue @@ -3,7 +3,6 @@ :columns="columns" target="device-instance-log" @search="handleSearch" - type="simple" class="device-log-search" /> {{ slotProps?.type?.text }} @@ -144,7 +143,7 @@ const handleSearch = (_params: any) => { }; - \ No newline at end of file + diff --git a/src/views/edge/Device/index.vue b/src/views/edge/Device/index.vue index 0acd4d41..e68b1297 100644 --- a/src/views/edge/Device/index.vue +++ b/src/views/edge/Device/index.vue @@ -154,9 +154,9 @@ {{ - dayjs(slotProps.registryTime).format( + slotProps.registryTime ? dayjs(slotProps.registryTime).format( 'YYYY-MM-DD HH:mm:ss', - ) + ) : '' }} @@ -269,6 +269,7 @@ const columns = [ type: 'string', defaultTermType: 'eq', }, + ellipsis:true }, { title: '设备名称', @@ -278,6 +279,7 @@ const columns = [ type: 'string', first: true, }, + ellipsis:true }, { title: '产品名称', @@ -375,6 +377,7 @@ const columns = [ title: '说明', dataIndex: 'describe', key: 'describe', + ellipsis:true, search: { type: 'string', }, diff --git a/src/views/home/components/PlatformPicCard.vue b/src/views/home/components/PlatformPicCard.vue index 085a764e..ae0590f2 100644 --- a/src/views/home/components/PlatformPicCard.vue +++ b/src/views/home/components/PlatformPicCard.vue @@ -45,7 +45,7 @@ const props = defineProps({ width: 100%; height: calc(100% - 50px); margin-top: 40px; - background-size: 95%; + background-size: 85%; background-position: center; background-repeat: no-repeat; } diff --git a/src/views/link/AccessConfig/Detail/index.vue b/src/views/link/AccessConfig/Detail/index.vue index 4571a3f2..043d5543 100644 --- a/src/views/link/AccessConfig/Detail/index.vue +++ b/src/views/link/AccessConfig/Detail/index.vue @@ -94,6 +94,7 @@ const goProviders = (param: any) => { showType.value = param.type; provider.value = param; type.value = false; + console.log(showType.value,provider.value) }; const goBack = () => { @@ -105,6 +106,7 @@ const goBack = () => { const TypeMap = new Map([ ['fixed-media', 'media'], ['gb28181-2016', 'media'], + ['onvif', 'media'], ['OneNet', 'cloud'], ['Ctwing', 'cloud'], ['modbus-tcp', 'channel'], @@ -117,6 +119,7 @@ const TypeMap = new Map([ const DataMap = new Map(); DataMap.set('fixed-media', { type: 'media', title: '视频类设备接入' }); DataMap.set('gb28181-2016', { type: 'media', title: '视频类设备接入' }); +DataMap.set('onvif',{ type: 'media' , title:'视频类设备接入'}); DataMap.set('OneNet', { type: 'cloud', title: '云平台接入' }); DataMap.set('Ctwing', { type: 'cloud', title: '云平台接入' }); DataMap.set('modbus-tcp', { type: 'channel', title: '通道类设备接入' }); @@ -133,7 +136,7 @@ const getTypeList = (result: Record) => { const channel: any[] = []; const edge: any[] = []; result.map((item: any) => { - if (item.id === 'fixed-media' || item.id === 'gb28181-2016') { + if (item.id === 'fixed-media' || item.id === 'gb28181-2016' || item.id ==='onvif') { item.type = 'media'; media.push(item); } else if (item.id === 'OneNet' || item.id === 'Ctwing') { @@ -190,6 +193,7 @@ const queryProviders = async () => { if (resp.status === 200) { const _data = resp.result || []; dataSource.value = getTypeList(accessConfigTypeFilter(_data as any[])); + console.log(dataSource.value) // dataSource.value = getTypeList(resp.result)[0].list.filter( // (item) => item.name !== '插件设备接入', // ); diff --git a/src/views/link/AccessConfig/components/Media/Onvif.vue b/src/views/link/AccessConfig/components/Media/Onvif.vue new file mode 100644 index 00000000..482d5875 --- /dev/null +++ b/src/views/link/AccessConfig/components/Media/Onvif.vue @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + 保存 + + + + + + + + 接入方式 + + {{ provider.name }} + + + {{ provider.description }} + + 消息协议 + + {{ provider.id === 'fixed-media' ? 'URL' : 'SIP' }} + + + + + + + + + diff --git a/src/views/link/AccessConfig/components/Media/index.vue b/src/views/link/AccessConfig/components/Media/index.vue index df422758..294a29a9 100644 --- a/src/views/link/AccessConfig/components/Media/index.vue +++ b/src/views/link/AccessConfig/components/Media/index.vue @@ -78,12 +78,16 @@ + + + diff --git a/src/views/rule-engine/Scene/Save/components/ParamsDropdown/ArrayItem.vue b/src/views/rule-engine/Scene/Save/components/ParamsDropdown/ArrayItem.vue new file mode 100644 index 00000000..2d4eeab0 --- /dev/null +++ b/src/views/rule-engine/Scene/Save/components/ParamsDropdown/ArrayItem.vue @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + diff --git a/src/views/rule-engine/Scene/Save/components/ParamsDropdown/Double.vue b/src/views/rule-engine/Scene/Save/components/ParamsDropdown/Double.vue index 3d65dd01..6c6b3dac 100644 --- a/src/views/rule-engine/Scene/Save/components/ParamsDropdown/Double.vue +++ b/src/views/rule-engine/Scene/Save/components/ParamsDropdown/Double.vue @@ -1,17 +1,17 @@ - onSelect(v, l, index)' - @tabChange='tabChange' + onSelect(v, l, index)' + @tabChange='tabChange' /> - + - - + - + diff --git a/src/views/rule-engine/Scene/Save/components/Terms/util.ts b/src/views/rule-engine/Scene/Save/components/Terms/util.ts index 191e67ab..cbb210b7 100644 --- a/src/views/rule-engine/Scene/Save/components/Terms/util.ts +++ b/src/views/rule-engine/Scene/Save/components/Terms/util.ts @@ -2,6 +2,7 @@ import { BranchesThen } from '@/views/rule-engine/Scene/typings' export const ContextKey = 'columnOptions' export const arrayParamsKey = ['nbtw', 'btw', 'in', 'nin', 'contains_all', 'contains_any', 'not_contains'] +export const doubleParamsKey= ['nbtw','btw'] export const timeTypeKeys = ['time_gt_now', 'time_lt_now'] diff --git a/src/views/system/Apply/Save/components/EditForm.vue b/src/views/system/Apply/Save/components/EditForm.vue index 2bc45205..fdd3c67a 100644 --- a/src/views/system/Apply/Save/components/EditForm.vue +++ b/src/views/system/Apply/Save/components/EditForm.vue @@ -1274,6 +1274,10 @@ required: true, message: '请输入用户名前缀', }, + { + validator: checkCh, + trigger: 'change' + } ]" > => + new Promise((resolve,reject) => { + if (/[\u4e00-\u9fa5]/.test(value)) return reject('用户名不能包含中文'); + else return resolve('') + }) + +// 请求头和参数必填验 const headerValid = ref(true); const paramsValid = ref(true); const headerValidator = () => { diff --git a/src/views/system/Basis/index.vue b/src/views/system/Basis/index.vue index 7424577b..3dafe4cc 100644 --- a/src/views/system/Basis/index.vue +++ b/src/views/system/Basis/index.vue @@ -271,15 +271,15 @@ 点击修改 @@ -345,7 +345,7 @@ const form = reactive({ 'base-path': `${window.location.origin}/api`, logo: '', ico: '', - backgroud: '', + background: '', }, rulesFrom: { title: [ @@ -387,8 +387,8 @@ const form = reactive({ headerTheme: configInfo.front?.headerTheme, logo: configInfo.front?.logo || '/logo.png', ico: configInfo.front?.ico || '/favicon.ico', - backgroud: - configInfo.front?.backgroud || '/images/login.png', + background: + configInfo.front?.background || '/images/login.png', apiKey: configInfo.amap?.apiKey, 'base-path': configInfo.paths?.['base-path'], }; @@ -497,7 +497,7 @@ const uploader: uploaderType = { } else if (info.file.status === 'done') { info.file.url = info.file.response?.result; form.backLoading = false; - form.formValue.backgroud = info.file.response?.result; + form.formValue.background = info.file.response?.result; } else if (info.file.status === 'error') { form.logoLoading = false; onlyMessage('背景图上传失败,请稍后再试', 'error'); diff --git a/src/views/system/Menu/Detail/BasicInfo.vue b/src/views/system/Menu/Detail/BasicInfo.vue index bb611fd1..04ea30d1 100644 --- a/src/views/system/Menu/Detail/BasicInfo.vue +++ b/src/views/system/Menu/Detail/BasicInfo.vue @@ -4,40 +4,65 @@ 基本信息 - + - - 点击修改 + + 点击修改 - + - + 点击选择图标 - - + + @@ -46,81 +71,140 @@ name="code" :validateFirst="true" :rules="[ - { - required: true, - message: '请输入编码', - trigger: 'change', - }, - { - max: 64, - message: '最多可输入64个字符', - trigger: 'change', - }, - { - validator: form.checkCode, - trigger: 'blur', - }, - ]"> - + { + required: true, + message: '请输入编码', + trigger: 'change', + }, + { + max: 64, + message: '最多可输入64个字符', + trigger: 'change', + }, + { + validator: checkCh, + trigger: ['change', 'blur'], + }, + { + validator: form.checkCode, + trigger: 'blur', + }, + ]" + > + - - + + - - + + - + 权限配置 - + 数据权限控制 - + - + 不支持 支持 间接控制 - - + + - - + + - choseIcon(typeStr)" /> + choseIcon(typeStr)" + /> @@ -175,7 +287,6 @@ import { Rule } from 'ant-design-vue/lib/form'; import { isNoCommunity } from '@/utils/utils'; import { onlyMessage } from '@/utils/comm'; - const permission = 'system/Menu'; // 路由 const route = useRoute(); @@ -191,7 +302,7 @@ const basicFormRef = ref(); const permissFormRef = ref(); const uploadIcon = ref(); //菜单应用选项 -const appOptions = ref([]) +const appOptions = ref([]); const form = reactive({ data: { name: '', @@ -216,7 +327,9 @@ const form = reactive({ getMenuInfo_api(routeParams.id).then((resp: any) => { form.data = { ...(resp.result as formType), - permissions: resp.result?.permissions ? resp.result.permissions : [], + permissions: resp.result?.permissions + ? resp.result.permissions + : [], accessSupport: resp.result?.accessSupport?.value || 'unsupported', }; @@ -224,25 +337,34 @@ const form = reactive({ }); if (isNoCommunity) { - // 获取关联菜单 - getMenuTree_api({ paging: false,terms:[{terms:[{ - terms:[ - { - value:"%show\":true%", - termType:"like", - column:"options" - } - ] - }]}]}).then((resp: any) => { - form.treeData = resp.result; - }); - // 获取资产类型 - getAssetsType_api().then((resp: any) => { - form.assetsType = resp.result.map((item: any) => ({ - label: item.name, - value: item.id, - })); - }); + // 获取关联菜单 + getMenuTree_api({ + paging: false, + terms: [ + { + terms: [ + { + terms: [ + { + value: '%show":true%', + termType: 'like', + column: 'options', + }, + ], + }, + ], + }, + ], + }).then((resp: any) => { + form.treeData = resp.result; + }); + // 获取资产类型 + getAssetsType_api().then((resp: any) => { + form.assetsType = resp.result.map((item: any) => ({ + label: item.name, + value: item.id, + })); + }); } }, checkCode: async (_rule: Rule, value: string): Promise => { @@ -270,7 +392,7 @@ const form = reactive({ const api = routeParams.id ? saveMenuInfo_api : addMenuInfo_api; form.saveLoading = true; const accessSupportValue = form.data.accessSupport; - const params:any = { + const params: any = { ...form.data, owner: 'iot', options: { show: true }, @@ -280,8 +402,8 @@ const form = reactive({ accessSupportValue === 'unsupported' ? '不支持' : accessSupportValue === 'support' - ? '支持' - : '间接控制', + ? '支持' + : '间接控制', }, }; api(params) @@ -302,15 +424,20 @@ const form = reactive({ }) .finally(() => (form.saveLoading = false)); }) - .catch((err) => { }); + .catch((err) => {}); }, }); form.init(); +const checkCh = async (_rule: Rule, value: string) => { + if (/[\u4e00-\u9fa5]/.test(value)) + return Promise.reject('编码不能包含中文'); + else return Promise.resolve(''); +}; const choseIcon = (typeStr: string) => { form.data.icon = typeStr; uploadIcon.value?.clearValidate(); -} +}; // 弹窗 const dialogVisible = ref(false); diff --git a/src/views/system/Menu/Detail/ButtonMange.vue b/src/views/system/Menu/Detail/ButtonMange.vue index 038ef3ea..52b84799 100644 --- a/src/views/system/Menu/Detail/ButtonMange.vue +++ b/src/views/system/Menu/Detail/ButtonMange.vue @@ -55,6 +55,7 @@ :menu-info="menuInfo" :mode="dialogTitle" :data="selectItem" + :menuData="table.tableData" @confirm="table.getList" /> @@ -84,8 +85,6 @@ const openDialog = (mode: '查看' | '新增' | '编辑', row: object) => { if (!routeParams.id && !paramsId.value) { return onlyMessage('请先新增菜单基本信息', 'warning'); } - console.log(3); - selectItem.value = { ...row }; dialogTitle.value = mode; dialogVisible.value = true; diff --git a/src/views/system/Menu/components/ButtonAddDialog.vue b/src/views/system/Menu/components/ButtonAddDialog.vue index bf927177..6b474c5c 100644 --- a/src/views/system/Menu/components/ButtonAddDialog.vue +++ b/src/views/system/Menu/components/ButtonAddDialog.vue @@ -15,6 +15,7 @@ :rules="[ { required: true, message: '请输入编码' }, { max: 64, message: '最多可输入64个字符' }, + { validator: validateIdRepeat, trigger: 'blur' }, ]" > - + ; + default: []; + }; }>(); const loading = ref(false); @@ -126,7 +131,7 @@ const initForm = { name: '', id: '', permissions: [], - describe: '', + description: '', } as formType; const formRef = ref(); const form = reactive({ @@ -141,12 +146,24 @@ const codeOptions = [ { label: 'delete', value: 'delete', message: '删除' }, { label: 'update', value: 'update', message: '更新' }, ]; - +const validateIdRepeat = (rule: any, val: any) => { + if (props.mode === '编辑') { + return Promise.resolve(''); + } + const isRepeat = props.menuData.find((i: any) => { + return i.id === val; + }); + if (isRepeat) { + return Promise.reject('编码重复'); + } else { + return Promise.resolve(''); + } +}; type formType = { name: string; id: string; permissions: any[]; - describe: string; + description: string; }; diff --git a/src/views/system/Menu/components/PermissChoose.vue b/src/views/system/Menu/components/PermissChoose.vue index f62e7e3c..03337ed5 100644 --- a/src/views/system/Menu/components/PermissChoose.vue +++ b/src/views/system/Menu/components/PermissChoose.vue @@ -25,9 +25,9 @@ v-model:checked="rowItem.checkAll" :indeterminate="rowItem.indeterminate" @change="() => permission.selectAllOpions(rowItem)" - :disabled="props.disabled" + :disabled="props.disabled || rowItem.disabled" > - {{ rowItem.name }} + {{ rowItem.name }} @@ -35,7 +35,7 @@ v-model:value="rowItem.checkedList" :options="rowItem.options" @change="((checkValue:string[])=>permission.selectOption(rowItem, checkValue))" - :disabled="props.disabled" + :disabled="props.disabled || rowItem.disabled" /> @@ -177,6 +177,7 @@ const permission = reactive({ checked.actions.length < item.actions.length) || false, options, + disabled: item.status === 0, }; }) as permissionType[]; @@ -192,6 +193,7 @@ type permissionType = { checkAll: boolean; indeterminate: boolean; options: any[]; + disabled: boolean; }; type paramsType = { paging: boolean; diff --git a/src/views/system/Platforms/Api/components/ApiTest.vue b/src/views/system/Platforms/Api/components/ApiTest.vue index 891c4e44..23afd4d0 100644 --- a/src/views/system/Platforms/Api/components/ApiTest.vue +++ b/src/views/system/Platforms/Api/components/ApiTest.vue @@ -108,7 +108,7 @@ (); +const method = ref() const requestBody = reactive({ tableColumns: [ { @@ -199,9 +200,10 @@ let schema: any = {}; const refStr = ref(''); const init = () => { - if (!props.selectApi.requestBody) return; - schema = props.selectApi.requestBody.content['application/json'].schema; - refStr.value = schema.$ref || schema?.items?.$ref; + method.value = props.selectApi.method + // if (!props.selectApi.requestBody) return; + // schema = props.selectApi.requestBody.content['application/json'].schema; + // refStr.value = schema.$ref || schema?.items?.$ref; }; init(); diff --git a/src/views/system/User/components/EditUserDialog.vue b/src/views/system/User/components/EditUserDialog.vue index 2cc59751..1b7a074a 100644 --- a/src/views/system/User/components/EditUserDialog.vue +++ b/src/views/system/User/components/EditUserDialog.vue @@ -142,14 +142,16 @@ @@ -267,15 +269,9 @@ const form = reactive({ data: {} as formType, rules: { - checkCh: (_rule:Rule,value:string): Promise => - new Promise((resolve,reject) => { - if (/[\u4e00-\u9fa5]/.test(value)) return reject('用户名不能包含中文'); - else return resolve('') - }), checkUserName: (_rule: Rule, value: string): Promise => new Promise((resolve, reject) => { if (props.type === 'edit') return resolve(''); - if (!value) return reject('请输入用户名'); else if (value.length > 64) return reject('最多可输入64个字符'); validateField_api('username', value).then((resp: any): any => { resp.result.passed @@ -397,7 +393,10 @@ const form = reactive({ }; }, }); - +const checkCh = async(_rule:Rule,value:string) => { + if (/[\u4e00-\u9fa5]/.test(value)) return Promise.reject('用户名不能包含中文'); + else return Promise.resolve('') + } const dealRoleList = (data:any) =>{ return data.map((item:any)=>{ return { diff --git a/src/views/user/Login/index.vue b/src/views/user/Login/index.vue index 662b3bcf..7b74dc8c 100644 --- a/src/views/user/Login/index.vue +++ b/src/views/user/Login/index.vue @@ -118,7 +118,7 @@ @@ -133,6 +133,9 @@ /> + + 查看更多 + @@ -158,6 +161,31 @@ + (moreVisible = false)" + :footer="null" + :width="800" + > + + + + + {{ item.name }} + + + +
+ {{ provider.name }} +
+ {{ provider.description }} +
+ {{ provider.id === 'fixed-media' ? 'URL' : 'SIP' }} +
点击选择图标