Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
XieYongHong 2023-07-13 17:04:34 +08:00
commit da7ec5332c
16 changed files with 242 additions and 104 deletions

View File

@ -30,9 +30,21 @@
</j-space>
<div style="margin-top: 20px" v-if="importLoading">
<j-badge v-if="flag" status="processing" text="进行中" />
<j-badge v-else status="success" text="已完成" />
<span>总数量{{ count }}</span>
<p style="color: red">{{ errMessage }}</p>
<div v-else>
<div>
<j-space size="large">
<j-badge status="success" text="已完成" />
<span>总数量{{ count }}</span>
</j-space>
</div>
<div>
<j-space size="large">
<j-badge status="error" text="失败&emsp;" />
<span>总数量{{ failCount }}</span>
<a :href="detailFile" v-if="failCount">下载</a>
</j-space>
</div>
</div>
</div>
</template>
@ -85,7 +97,9 @@ const props = defineProps({
const importLoading = ref<boolean>(false);
const flag = ref<boolean>(false);
const count = ref<number>(0);
const failCount = ref(0);
const errMessage = ref<string>('');
const detailFile = ref('');
const downFile = async (type: string) => {
const res: any = await templateDownload(props.product, type);
@ -112,6 +126,7 @@ const beforeUpload = (_file: any) => {
const submitData = async (fileUrl: string) => {
if (!!fileUrl) {
count.value = 0;
failCount.value = 0;
errMessage.value = '';
flag.value = true;
const autoDeploy = !!props?.file?.autoDeploy || false;
@ -126,8 +141,11 @@ const submitData = async (fileUrl: string) => {
const temp = res.result.total;
dt += temp;
count.value = dt;
} else {
} else if(!res.success && !res.detailFile) {
failCount.value++;
errMessage.value = res.message || '失败';
} else if(res.detailFile) {
detailFile.value = res.detailFile;
}
};
source.onerror = (e: { status: number }) => {

View File

@ -197,6 +197,7 @@ import { FormValidate, FormState } from '../data';
import type { FormInstance } from 'ant-design-vue';
import type { FormDataType } from '../type.d';
import { cloneDeep, isArray } from 'lodash-es';
import { protocolList } from '@/utils/consts';
const props = defineProps({
data: {
@ -281,17 +282,13 @@ const getCertificateList = async () => {
const getProvidersList = async () => {
const resp: any = await getProviders();
if (resp.status === 200) {
const list = [
{ label: 'OPC UA', value: 'OPC_UA' },
{ label: 'Modbus TCP', value: 'MODBUS_TCP' },
];
const arr = resp.result
.filter(
(item: any) => item.id === 'modbus-tcp' || item.id === 'opc-ua',
)
.map((it: any) => (it?.id === 'opc-ua' ? 'OPC_UA' : 'MODBUS_TCP'));
const providers: any = list.filter((item: any) =>
arr.includes(item.value),
.map((it: any) => it.id);
const providers: any = protocolList.filter((item: any) =>
arr.includes(item.alias),
);
providersList.value = providers;
if (arr.includes('OPC_UA')) {

View File

@ -14,6 +14,8 @@
import { getImage } from '@/utils/comm';
import BaseMenu, { USER_CENTER_MENU_DATA } from '../data/baseMenu'
import { getSystemPermission, updateMenus } from '@/api/initHome';
import { protocolList } from '@/utils/consts';
import { getProviders } from '@/api/data-collect/channel';
/**
* 获取菜单数据
*/
@ -36,6 +38,18 @@ const getSystemPermissionData = async () => {
menuDatas.count = _count;
}
};
/**
* 查询支持的协议
*/
let filterProtocolList: any[] = [];
const getProvidersFn = async () => {
const res: any = await getProviders();
filterProtocolList = protocolList.filter((item) => {
return res.result?.find((val: any) => item.alias == val.id);
})
}
getProvidersFn();
/**
* 过滤菜单
*/
@ -50,6 +64,9 @@ const filterMenu = (permissions: string[], menus: any[]) => {
if (item.children) {
item.children = filterMenu(permissions, item.children);
}
if (!filterProtocolList.length && item.code == 'link/DataCollect') {
return false;
}
return isShow || !!item.children?.length;
});
};
@ -71,6 +88,7 @@ const menuCount = (menus: any[]) => {
const initMenu = async () => {
return new Promise(async (resolve) => {
//
console.log([...menuDatas.current!, USER_CENTER_MENU_DATA]);
const res = await updateMenus([...menuDatas.current!, USER_CENTER_MENU_DATA]);
if (res.status === 200) {
resolve(true);

View File

@ -244,4 +244,10 @@ watch(
</script>
<style lang="less" scoped>
@import './index.less';
:deep(.live-player-stretch-btn){
display: none;
}
:deep(.vjs-icon-spinner){
display: none;
}
</style>

View File

@ -323,7 +323,7 @@ const handleAdd = () => {
);
tab.onTabSaveSuccess = async (value: any) => {
await getGatewayList();
handleClick(value?.result);
handleClick(gatewayList.value?.[0]);
};
};
</script>

View File

@ -187,6 +187,7 @@ const columns = [
options: [
{ label: '在线', value: 'online' },
{ label: '离线', value: 'offline' },
{ label: '禁用', value: 'notActive'}
],
handleValue: (v: any) => {
return v;

View File

@ -8,6 +8,7 @@
:loadData="onLoadData"
:fieldNames="{ title: 'name', key: 'id' }"
@select="onSelect"
v-model:expandedKeys="expandedKeys"
>
<template #title="{id, name}">
<div class="name"><AIcon
@ -28,6 +29,12 @@ type Emits = {
(e: 'onSelect', data: { dId: string; cId: string }): void;
};
/**
* 默认展开第一个
*/
const expandedKeys = ref<any[]>([]); // key
// const selectedKeys = ref<any[]>([]); // key
const emit = defineEmits<Emits>();
interface DataNode {
@ -80,6 +87,16 @@ const getDeviceList = async () => {
...extra,
};
});
getChildren(treeData.value[0].id,{
pageIndex: 0,
pageSize: 100,
terms: [
{
column: 'deviceId',
value: treeData.value[0].id,
},
],
},true)
}
};
getDeviceList();
@ -120,7 +137,7 @@ const updateTreeData = (
* @param key
* @param params
*/
const getChildren = (key: any, params: any): Promise<any> => {
const getChildren = (key: any, params: any, first?:any): Promise<any> => {
return new Promise(async (resolve) => {
const res = await cascadeApi.queryChannelList(params);
if (res.status === 200) {
@ -143,6 +160,11 @@ const getChildren = (key: any, params: any): Promise<any> => {
});
}, 50);
}
if(first){
expandedKeys.value.push(treeData.value[0].id)
// selectedKeys.value.push(treeData.value[0].children[0].id)
// emit('onSelect', { dId: treeData.value[0].children[0].deviceId, cId: treeData.value[0].children[0].channelId });
}
resolve(res.result);
}
});
@ -171,6 +193,7 @@ const onLoadData = ({ key, children }: any): Promise<void> => {
resolve();
});
};
</script>
<style lang="less" scoped>

View File

@ -51,6 +51,8 @@ const props = defineProps({
},
});
const data = ref();
const tableRef = ref();
const columns = [
@ -69,14 +71,15 @@ const columns = [
fixed: 'right',
},
];
const dataSource = reactive({
table:props.headers
});
const handleHeader= (data:any) =>{
return data.map((item:any)=>{
return {...item,_key: randomString()}
})
}
const dataSource = reactive({
table:props.headers.length > 0 ? handleHeader(props.headers) : ''
});
watch(()=>JSON.stringify(props.headers),()=>{
dataSource.table = handleHeader(props.headers)
})
@ -85,7 +88,7 @@ const handleDelete = (id: number) => {
dataSource.table.splice(idx, 1);
};
const valueChange = () =>{
return dataSource.table.map((item:any)=>{
data.value = dataSource.table.map((item:any)=>{
const {_key,...extra}=item;
return extra
})
@ -98,14 +101,17 @@ const handleAdd = () => {
});
};
const validate = () =>{
return new Promise((resolve:any,reject:any)=>{
tableRef.value.validate().then(()=>{
return valueChange()
valueChange()
resolve(data.value)
}).catch((err:any)=>{
return false
reject(false)
})
})
}
defineExpose({
validate
validate,
})
</script>

View File

@ -546,7 +546,34 @@ const resetPublicFiles = () => {
*/
const btnLoading = ref<boolean>(false);
const handleSubmit = () => {
if(editTable.value.validate()){
if(formData.value.type === 'webhook') {
Promise.all([editTable.value.validate(),validate()]).then(async (result:any) => {
formData.value.configuration.headers = result[0]
btnLoading.value = true;
let res;
if (!formData.value.id) {
res = await configApi.save(formData.value);
} else {
res = await configApi.update(formData.value);
}
if (res?.success) {
onlyMessage('保存成功');
if (route.query?.notifyType) {
// @ts-ignore
window?.onTabSaveSuccess(res.result);
setTimeout(() => window.close(), 300);
} else {
router.back();
}
}
})
.catch((err:any) => {
console.log('err: ', err);
})
.finally(() => {
btnLoading.value = false;
});
}else{
validate()
.then(async () => {
btnLoading.value = true;
@ -567,65 +594,13 @@ const handleSubmit = () => {
}
}
})
.catch((err) => {
.catch((err:any) => {
console.log('err: ', err);
})
.finally(() => {
btnLoading.value = false;
});
}
// Promise.all([validate(),editTable.value.validate()]).then(async()=>{
// btnLoading.value = true;
// let res;
// if (!formData.value.id) {
// res = await configApi.save(formData.value);
// } else {
// res = await configApi.update(formData.value);
// }
// if (res?.success) {
// onlyMessage('');
// if (route.query?.notifyType) {
// // @ts-ignore
// window?.onTabSaveSuccess(res.result);
// setTimeout(() => window.close(), 300);
// } else {
// router.back();
// }
// }
// }) .catch((err) => {
// console.log('err: ', err);
// })
// .finally(() => {
// btnLoading.value = false;
// });
// validate()
// .then(async () => {
// const a = editTable.value.validate();
// console.log(a);
// btnLoading.value = true;
// let res;
// if (!formData.value.id) {
// res = await configApi.save(formData.value);
// } else {
// res = await configApi.update(formData.value);
// }
// if (res?.success) {
// onlyMessage('');
// if (route.query?.notifyType) {
// // @ts-ignore
// window?.onTabSaveSuccess(res.result);
// setTimeout(() => window.close(), 300);
// } else {
// router.back();
// }
// }
// })
// .catch((err) => {
// console.log('err: ', err);
// })
// .finally(() => {
// btnLoading.value = false;
// });
}
};
watchEffect(() => {

View File

@ -38,8 +38,8 @@
<template #action="slotProps">
<AIcon
type="ExclamationCircleOutlined"
style="color: #1d39c4; cursor: pointer"
@click="handleDetail(slotProps.context)"
:class="Object.keys(slotProps.context).length == 0 ? 'disableIcon' : 'Icon'"
@click="handleDetail(slotProps)"
/>
</template>
</JProTable>
@ -51,6 +51,7 @@ import configApi from '@/api/notice/config';
import { PropType } from 'vue';
import moment from 'moment';
import { Modal } from 'ant-design-vue';
import Record from '../../Template/Log/components/Record.vue'
type Emits = {
(e: 'update:visible', data: boolean): void;
@ -152,19 +153,46 @@ const handleError = (e: any) => {
/**
* 查看详情
*/
const handleDetail = (e: any) => {
Modal.info({
const handleDetail = (data: any) => {
if(Object.keys(data.context).length == 0){
Modal.info({
title: '详情信息',
content: h(
'p',
"p",
{
style: {
maxHeight: '300px',
overflowY: 'auto',
},
},
JSON.stringify(e),
'模板中不存在变量'
),
});
}else{
Modal.info({
title: '详情信息',
content: h(
Record,
{
data:data,
style: {
maxHeight: '300px',
overflowY: 'auto',
},
},
),
});
}
};
</script>
<style lang="less" scoped>
.disableIcon{
color:darkgrey ;
cursor:pointer;
}
.Icon{
color:#1d39c4;
cursor:pointer;
}
</style>

View File

@ -27,7 +27,6 @@ const replaceData = async (data: any) => {
context.value = data.context
if (context.value.detailJson) {
context.value.detailJson = context.value.detailJson.replace(/\\\"/g, '\"')
}
if (context.value.hasOwnProperty('userIdList') || context.value.hasOwnProperty('toUser')) {
templateApi.getUser(

View File

@ -34,7 +34,7 @@
<template #action="slotProps">
<AIcon
type="ExclamationCircleOutlined"
style="color: #1d39c4; cursor: pointer"
:class="Object.keys(slotProps.context).length == 0 ? 'disableIcon' : 'Icon'"
@click="handleDetail(slotProps)"
/>
</template>
@ -148,8 +148,24 @@ const handleError = (e: any) => {
/**
* 查看详情
*/
const handleDetail = (data:any) => {
Modal.info({
const handleDetail = (data: any) => {
if(Object.keys(data.context).length == 0){
Modal.info({
title: '详情信息',
content: h(
"p",
{
style: {
maxHeight: '300px',
overflowY: 'auto',
},
},
'模板中不存在变量'
),
});
}else{
Modal.info({
title: '详情信息',
content: h(
Record,
@ -162,5 +178,16 @@ const handleDetail = (data:any) => {
},
),
});
}
};
</script>
<style lang="less" scoped>
.disableIcon{
color:darkgrey ;
cursor:pointer;
}
.Icon{
color:#1d39c4;
cursor:pointer;
}
</style>

View File

@ -141,15 +141,18 @@ const confirm = () => {
}));
// ,
departmentStore.setProductId(table.selectedRows.map((item: any) => item.id));
// departmentStore.setProductId(table.selectedRows.map((item: any) => item.id));
loading.value = true;
bindDeviceOrProductList_api(props.assetType, params)
.then(() => {
onlyMessage('操作成功');
emits('confirm');
emits('update:visible', false);
emits('next',table.selectedRows.map((item: any) => item.id))
if(props.assetType === 'device'){
departmentStore.setProductId(undefined)
}
emits('update:visible', false);
})
.finally(() => {
loading.value = false;
@ -172,7 +175,7 @@ const columns = props.queryColumns.filter(
const searchColumns = computed(() => {
return props.queryColumns.map(item => {
if (departmentStore.productId) {
if (departmentStore.productId) {
if (item.dataIndex === 'productName') {
item.search.first = true
item.search.componentProps = {
@ -185,6 +188,11 @@ const searchColumns = computed(() => {
} else if (item.search && 'first' in item.search) {
delete item.search.first
}
}
else{
if (item.dataIndex === 'productName'){
item.search.defaultOnceValue = ''
}
}
return item
})
@ -342,7 +350,7 @@ const table: any = {
code: 200,
result: {
data: data.sort(
(a, b) => a.createTime - b.createTime,
(a, b) => b.createTime - a.createTime
),
pageIndex,
pageSize,
@ -459,18 +467,18 @@ const selectAll = (selected: Boolean, selectedRows: any,changeRows:any) => {
}
const cancel = () => {
departmentStore.setProductId(undefined)
console.log(departmentStore.productId)
emits('update:visible', false)
}
const search = (query: any) => {
queryParams.value = query
}
onUnmounted(()=>{
if(props.assetType ==='device'){
departmentStore.setProductId(undefined)
}
console.log(departmentStore.productId)
})
// onUnmounted(()=>{
// if(props.assetType ==='device'){
// departmentStore.setProductId(undefined)
// }
// })
</script>
<style lang="less" scoped>

View File

@ -27,7 +27,7 @@ const handleOk = () => {
};
const cancel = () => {
departmentStore.setProductId()
// departmentStore.setProductId()
emits('update:visible',false)
}

View File

@ -219,6 +219,7 @@
:all-permission="tableData.permissionList"
asset-type="product"
@confirm="table.addConfirm"
@next="nextAction"
/>
<EditPermissionDialog
v-if="dialogs.editShow"
@ -230,12 +231,11 @@
asset-type="product"
:defaultPermission="tableData.defaultPermission"
@confirm="table.refresh"
@next="next"
/>
<NextDialog
v-if="dialogs.nextShow"
v-model:visible="dialogs.nextShow"
@confirm="emits('openDeviceBind')"
@confirm="nextConfirm"
/>
</div>
</div>
@ -256,9 +256,10 @@ import {
getBindingsPermission,
} from '@/api/system/department';
import { intersection } from 'lodash-es';
import { useDepartmentStore } from '@/store/department';
const permission = 'system/Department';
const departmentStore = useDepartmentStore();
const emits = defineEmits(['openDeviceBind']);
const props = defineProps<{
parentId: string;
@ -614,8 +615,14 @@ watch(
if (!val) tableData.selectedRows = [];
},
);
const next = (data:any) =>{
let Temporary:any = '';
const nextAction = (data:any) =>{
Temporary = data
}
const nextConfirm = () =>{
departmentStore.setProductId(Temporary);
emits('openDeviceBind')
}
</script>

View File

@ -81,6 +81,8 @@ import { onlyMessage } from '@/utils/comm';
import {
USER_CENTER_MENU_CODE,
} from '@/utils/consts';
import { protocolList } from '@/utils/consts';
import { getProviders } from '@/api/data-collect/channel';
const selectedKeys: any = ref([]);
const treeData = ref<any>([]);
@ -111,6 +113,17 @@ const params = {
],
};
/**
* 查询支持的协议
*/
let filterProtocolList: any[] = [];
const getProvidersFn = async () => {
const res: any = await getProviders();
filterProtocolList = protocolList.filter((item) => {
return res.result?.find((val: any) => item.alias == val.id);
})
}
getProvidersFn();
function filterTree(nodes: Array<any>, selectedKeys: Array<any>) {
const filtered = [];
for (let i = 0; i < nodes.length; i++) {
@ -206,17 +219,29 @@ onMounted(() => {
const systemMenuData = initData(systemMenu.value);
selectedKeys.value = systemMenuData.checkedKeys;
const AllMenu = mergeArr(
const AllMenu = filterMenus(mergeArr(
cloneDeep(filterBaseMenu),
cloneDeep(systemMenu.value),
);
))
console.log(AllMenu);
//
treeData.value = handleSortsArr(AllMenu);
}
});
});
});
const filterMenus = (menus: any[]) => {
return menus.filter((item) => {
if (item.children) {
item.children = filterMenus(item.children);
}
if (!filterProtocolList.length && item.code == 'link/DataCollect') {
debugger
return false;
}
return item
});
};
</script>
<style lang="less" scoped>