Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # vite.config.ts
This commit is contained in:
commit
4258311ed6
|
@ -403,3 +403,59 @@ export const treeMapping = (data?: any) => server.post(`/data-collect/channel/_a
|
|||
* @returns
|
||||
*/
|
||||
export const saveMapping = (thingId: any, provider: string, data?: any) => server.patch(`/things/collector/device/${thingId}/${provider}`, data)
|
||||
|
||||
/**
|
||||
* 查询边缘网关通道
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const edgeChannel = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/data-collector-channel-list/invoke`, data)
|
||||
|
||||
/**
|
||||
* 查询边缘网关采集器
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const edgeCollector = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/data-collector-list/invoke`, data)
|
||||
|
||||
/**
|
||||
* 查询边缘网关点位
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const edgePoint = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/data-collector-point-list/invoke`, data)
|
||||
|
||||
/**
|
||||
*
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const getEdgeMap = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/device-collector-list/invoke`, data)
|
||||
|
||||
/**
|
||||
*
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const removeEdgeMap = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/device-collector-delete/invoke`, data)
|
||||
|
||||
/**
|
||||
*
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const treeEdgeMap = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/data-collector-channel-tree/invoke`, data)
|
||||
|
||||
/**
|
||||
*
|
||||
* @param deviceId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export const saveEdgeMap = (deviceId: string, data?: any) => server.post(`/edge/operations/${deviceId}/device-collector-save/invoke`, data)
|
|
@ -11,8 +11,8 @@ export default {
|
|||
// 修改
|
||||
update: (data: any) => patch(`/notifier/template`, data),
|
||||
del: (id: any) => remove(`/notifier/template/${id}`),
|
||||
getConfig: (data: any) => post<BindConfig>(`/notifier/config/_query/no-paging?paging=false`, data),
|
||||
getTemplateDetail: (id: string) => get(`/notifier/template/${id}/detail`),
|
||||
getConfig: (data: any) => post<BindConfig[]>(`/notifier/config/_query/no-paging?paging=false`, data),
|
||||
getTemplateDetail: (id: string) => get<any>(`/notifier/template/${id}/detail`),
|
||||
debug: (data: any, configId: string, templateId: string) => post(`/notifier/${configId}/${templateId}/_send`, data),
|
||||
getHistory: (data: any, id: string) => post(`/notify/history/template/${id}/_query`, data),
|
||||
// 钉钉/微信, 根据配置获取部门和用户
|
||||
|
|
|
@ -51,7 +51,8 @@ const iconKeys = [
|
|||
'playCircleOutlined',
|
||||
'RightOutlined',
|
||||
'FileTextOutlined',
|
||||
'UploadOutlined'
|
||||
'UploadOutlined',
|
||||
'ArrowLeftOutlined'
|
||||
]
|
||||
|
||||
const Icon = (props: {type: string}) => {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<svg width="58" height="50" viewBox="0 0 58 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M29 49.5794C45.0163 49.5794 58 46.8079 58 43.3891C58 39.9702 45.0163 37.1987 29 37.1987C12.9837 37.1987 0 39.9702 0 43.3891C0 46.8079 12.9837 49.5794 29 49.5794Z" fill="#FAFAFA"/>
|
||||
<path d="M33.2639 9.99902L9.93594 16.3635C9.47351 16.4896 9.43643 17.1312 9.88123 17.3098L26.5406 23.999L49.1273 18.1035C49.5839 17.9843 49.6364 17.3571 49.206 17.1637L33.2639 9.99902Z" fill="#FAFAFA" stroke="#E0E0E0"/>
|
||||
<path d="M24.2975 4.69484C25.7779 5.25264 26.8448 8.08321 25.7779 9.45134L22.4067 10.9999C21.6665 10.2491 20.7123 8.2462 21.0824 6.52395C21.2746 5.62954 21.4884 5.19123 22.1983 4.7653C22.8554 4.37107 23.7889 4.5032 24.2975 4.69484Z" fill="white" stroke="#E0E0E0"/>
|
||||
<path d="M35.2162 3.78468C33.7358 4.34248 32.6689 7.17306 33.7358 8.54119L37.107 10.0897C37.8472 9.33897 38.8014 7.33604 38.4313 5.61379C38.2391 4.71939 38.0253 4.28107 37.3153 3.85514C36.6583 3.46091 35.7248 3.59304 35.2162 3.78468Z" fill="white" stroke="#E0E0E0"/>
|
||||
<mask id="path-5-inside-1_990_11491" fill="white">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.5449 17.5308C42.5432 17.4907 42.5411 17.4504 42.5387 17.4099C42.3461 14.2156 40.8848 9.80379 37.5252 7.09156C35.6005 5.42908 33.0395 4.3785 29.6986 4.65434C26.3456 4.78127 23.9278 6.13333 22.2162 8.01686C19.2086 11.1131 18.2885 15.6671 18.4811 18.8607C18.4835 18.9011 18.4863 18.9414 18.4894 18.9814C18.515 19.5938 18.6444 20.1629 18.8655 20.688C20.262 24.3125 25.1708 25.5541 30.934 25.2065C30.9736 25.2042 31.0131 25.2017 31.0526 25.1991C36.7632 24.8346 41.4308 23.0119 42.3762 19.2717C42.533 18.7234 42.5931 18.1424 42.5449 17.5308Z"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.5449 17.5308C42.5432 17.4907 42.5411 17.4504 42.5387 17.4099C42.3461 14.2156 40.8848 9.80379 37.5252 7.09156C35.6005 5.42908 33.0395 4.3785 29.6986 4.65434C26.3456 4.78127 23.9278 6.13333 22.2162 8.01686C19.2086 11.1131 18.2885 15.6671 18.4811 18.8607C18.4835 18.9011 18.4863 18.9414 18.4894 18.9814C18.515 19.5938 18.6444 20.1629 18.8655 20.688C20.262 24.3125 25.1708 25.5541 30.934 25.2065C30.9736 25.2042 31.0131 25.2017 31.0526 25.1991C36.7632 24.8346 41.4308 23.0119 42.3762 19.2717C42.533 18.7234 42.5931 18.1424 42.5449 17.5308Z" fill="white"/>
|
||||
<path d="M42.5387 17.4099L43.5369 17.3497L43.5369 17.3497L42.5387 17.4099ZM42.5449 17.5308L41.5459 17.5738L41.5466 17.5916L41.548 17.6094L42.5449 17.5308ZM37.5252 7.09156L36.8715 7.84832L36.8841 7.8592L36.897 7.86964L37.5252 7.09156ZM29.6986 4.65434L29.7364 5.65362L29.7587 5.65278L29.7809 5.65095L29.6986 4.65434ZM22.2162 8.01686L22.9335 8.71363L22.9451 8.7017L22.9563 8.68938L22.2162 8.01686ZM18.4811 18.8607L17.4829 18.9209L18.4811 18.8607ZM18.4894 18.9814L19.4885 18.9396L19.4878 18.9217L19.4864 18.904L18.4894 18.9814ZM18.8655 20.688L19.7987 20.3284L19.7931 20.3141L19.7871 20.2999L18.8655 20.688ZM31.0526 25.1991L30.9889 24.2011L30.9878 24.2012L31.0526 25.1991ZM42.3762 19.2717L41.4148 18.9968L41.4105 19.0117L41.4067 19.0266L42.3762 19.2717ZM41.5405 17.4701C41.5426 17.5049 41.5444 17.5394 41.5459 17.5738L43.544 17.4879C43.5421 17.442 43.5397 17.3959 43.5369 17.3497L41.5405 17.4701ZM36.897 7.86964C39.9727 10.3527 41.359 14.4604 41.5405 17.4701L43.5369 17.3497C43.3331 13.9708 41.7968 9.2549 38.1533 6.31347L36.897 7.86964ZM38.1788 6.33479C36.0609 4.50532 33.2375 3.35875 29.6163 3.65773L29.7809 5.65095C32.8416 5.39825 35.1402 6.35285 36.8715 7.84832L38.1788 6.33479ZM22.9563 8.68938C24.496 6.99503 26.6647 5.76991 29.7364 5.65362L29.6608 3.65505C26.0266 3.79264 23.3597 5.27163 21.4761 7.34434L22.9563 8.68938ZM21.4989 7.3201C18.2372 10.6779 17.2792 15.5428 17.4829 18.9209L19.4793 18.8005C19.2978 15.7915 20.18 11.5483 22.9335 8.71363L21.4989 7.3201ZM17.4829 18.9209C17.4857 18.967 17.4888 19.013 17.4924 19.0588L19.4864 18.904C19.4837 18.8697 19.4814 18.8352 19.4793 18.8005L17.4829 18.9209ZM19.7871 20.2999C19.6131 19.8867 19.5093 19.435 19.4885 18.9396L17.4903 19.0232C17.5208 19.7525 17.6756 20.439 17.9439 21.0761L19.7871 20.2999ZM17.9324 21.0475C18.7723 23.2274 20.6451 24.6048 22.941 25.3838C25.2296 26.1603 28.0393 26.3829 30.9942 26.2047L30.8738 24.2084C28.0655 24.3777 25.5393 24.1534 23.5835 23.4898C21.6351 22.8288 20.3553 21.7731 19.7987 20.3284L17.9324 21.0475ZM30.9942 26.2047C31.0353 26.2023 31.0763 26.1997 31.1174 26.197L30.9878 24.2012C30.9499 24.2037 30.9119 24.2061 30.8738 24.2084L30.9942 26.2047ZM41.4067 19.0266C41.0298 20.5176 39.8986 21.7128 38.0652 22.6014C36.2245 23.4935 33.7708 24.0236 30.9889 24.2011L31.1163 26.1971C34.045 26.0101 36.7804 25.4466 38.9375 24.4012C41.1019 23.3522 42.7772 21.766 43.3457 19.5167L41.4067 19.0266ZM43.3377 19.5465C43.5279 18.8813 43.5992 18.1806 43.5419 17.4523L41.548 17.6094C41.587 18.1042 41.5381 18.5654 41.4148 18.9968L43.3377 19.5465Z" fill="#E0E0E0" mask="url(#path-5-inside-1_990_11491)"/>
|
||||
<ellipse cx="21.5982" cy="19.5977" rx="2.27602" ry="1.30058" transform="rotate(-3.45082 21.5982 19.5977)" fill="#F4F4F4"/>
|
||||
<ellipse cx="2.27602" cy="1.30058" rx="2.27602" ry="1.30058" transform="matrix(-0.974459 0.224564 0.224564 0.974459 43.8887 15.7603)" fill="#F4F4F4"/>
|
||||
<circle cx="26.0809" cy="15.0666" r="1.84249" transform="rotate(-3.45082 26.0809 15.0666)" fill="#E0E0E0"/>
|
||||
<circle cx="26.6121" cy="14.6075" r="0.650291" transform="rotate(-3.45082 26.6121 14.6075)" fill="white"/>
|
||||
<circle cx="25.4848" cy="15.971" r="0.325146" transform="rotate(-3.45082 25.4848 15.971)" fill="white"/>
|
||||
<circle cx="37.7645" cy="14.362" r="1.84249" transform="rotate(-3.45082 37.7645 14.362)" fill="#E0E0E0"/>
|
||||
<circle cx="38.2937" cy="13.9029" r="0.650291" transform="rotate(-3.45082 38.2937 13.9029)" fill="white"/>
|
||||
<circle cx="37.1683" cy="15.2669" r="0.325146" transform="rotate(-3.45082 37.1683 15.2669)" fill="white"/>
|
||||
<ellipse cx="32.3087" cy="16.6698" rx="1.51282" ry="1.23036" transform="rotate(-3.45082 32.3087 16.6698)" fill="#E0E0E0"/>
|
||||
<mask id="mask0_990_11491" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="28" y="19" width="8" height="4">
|
||||
<path d="M28.8401 21.0038C29.1929 20.5749 29.549 20.2953 30.0249 20.0923C30.5162 19.8826 31.1577 19.7447 32.1 19.6404C33.021 19.5386 33.5501 19.5974 33.9102 19.7125C34.2573 19.8235 34.4861 19.9957 34.8185 20.246C34.8296 20.2544 34.8408 20.2628 34.8521 20.2713C35.02 20.3977 35.1717 20.6012 35.2384 20.787C35.2708 20.8773 35.274 20.938 35.2703 20.9682C35.2681 20.9866 35.2652 20.9882 35.2637 20.989C35.2635 20.9891 35.2633 20.9892 35.2632 20.9893C34.8844 21.3249 34.6341 21.5424 34.2159 21.7233C33.7851 21.9096 33.148 22.067 32.0018 22.1938C30.8548 22.3207 30.2398 22.3016 29.8387 22.2257C29.513 22.164 29.319 22.0665 29.0343 21.9233C28.9772 21.8947 28.9166 21.8642 28.8504 21.8317C28.7416 21.7784 28.657 21.6792 28.6311 21.5668C28.609 21.4712 28.6107 21.2826 28.8401 21.0038Z" fill="#FD7477" stroke="#666666"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_990_11491)">
|
||||
<path d="M31.2438 19.4706L31.0537 18.6566C31.0373 18.5863 31.1139 18.545 31.1837 18.5631C31.3003 18.5935 31.4791 18.5924 31.6924 18.4731C32.0018 18.3001 32.1775 17.9936 32.2267 17.862L32.3581 20.041L32.0351 20.0605C31.6628 20.083 31.3286 19.8338 31.2438 19.4706Z" fill="white" stroke="#E0E0E0" stroke-width="0.5"/>
|
||||
<path d="M33.4522 19.3375L33.543 18.5065C33.5509 18.4348 33.4699 18.403 33.4028 18.4294C33.2906 18.4735 33.113 18.4939 32.887 18.4012C32.559 18.2666 32.3477 17.9835 32.2831 17.8587L32.4145 20.0378L32.7374 20.0183C33.1097 19.9958 33.4116 19.7083 33.4522 19.3375Z" fill="white" stroke="#E0E0E0" stroke-width="0.5"/>
|
||||
</g>
|
||||
<path d="M31.421 18.7266C30.2561 19.2905 29.7431 20.4957 29.7177 20.5566C29.7081 20.5796 29.7032 20.6044 29.7031 20.6293C29.7031 20.6543 29.708 20.679 29.7175 20.7021C29.727 20.7252 29.741 20.7462 29.7587 20.7639C29.7763 20.7815 29.7972 20.7956 29.8203 20.8052C29.8434 20.8147 29.8681 20.8197 29.893 20.8197C29.918 20.8198 29.9428 20.8149 29.9658 20.8053C29.9889 20.7958 30.0099 20.7818 30.0276 20.7642C30.0453 20.7466 30.0593 20.7256 30.0689 20.7026C30.0756 20.6866 30.6789 19.416 32.19 19.1705C33.6941 18.926 34.9386 20.104 34.9503 20.119C34.9812 20.1584 35.0264 20.184 35.076 20.1903C35.1257 20.1966 35.1758 20.183 35.2155 20.1526C35.2553 20.1222 35.2814 20.0773 35.2882 20.0277C35.2951 19.9781 35.2821 19.9278 35.2522 19.8878C35.0034 19.5814 34.7147 19.3099 34.3937 19.0805C33.6826 18.5696 32.926 18.3613 32.2053 18.4785C31.9332 18.5227 31.669 18.6063 31.421 18.7266Z" fill="#E0E0E0" stroke="#E0E0E0" stroke-width="0.1"/>
|
||||
<line x1="23.7287" y1="18.1659" x2="23.5991" y2="18.5272" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="24.9494" y1="18.31" x2="24.893" y2="18.4672" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="0.35" y1="-0.35" x2="0.733819" y2="-0.35" transform="matrix(0.44853 0.893768 0.893768 -0.44853 40.4297 15.9731)" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<line x1="0.35" y1="-0.35" x2="0.517055" y2="-0.35" transform="matrix(0.448552 0.893757 0.893757 -0.448552 39.2363 16.2622)" stroke="#E0E0E0" stroke-width="0.7" stroke-linecap="round"/>
|
||||
<path d="M9 17.5027C9 17.1455 9.36388 16.9035 9.69336 17.0416L25 23.4605V46.2127L9 38.7176V17.5027Z" fill="#FBFBFB" stroke="#E0E0E0"/>
|
||||
<path d="M8.74631 16.66L24.8561 23.8265L22.245 30.3166L6.15202 22.5625L8.74631 16.66Z" fill="white" stroke="#E0E0E0"/>
|
||||
<path d="M50 18.2859C50 17.9597 49.6926 17.7208 49.3765 17.8014L25.5 23.8878V45.8708C25.5 46.2033 25.8185 46.4432 26.1381 46.3513L50 39.4934V18.2859Z" fill="#F4F4F4" stroke="#E0E0E0"/>
|
||||
<path d="M50.0635 18.0495C49.9823 17.7978 49.719 17.6529 49.4628 17.719L26.1262 23.7393L28.0893 30.3834L51.865 23.6308L50.0635 18.0495Z" fill="white" stroke="#E0E0E0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 9.4 KiB |
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<Empty v-bind="baseProps">
|
||||
<template v-for="item in renderArr" :key="item" #[item]="scope">
|
||||
<slot :name="item" :scope="scope"></slot>
|
||||
</template>
|
||||
</Empty>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="JEmpty">
|
||||
import { Empty } from 'ant-design-vue';
|
||||
import { useSlots } from 'vue';
|
||||
import NoData from './assets/nodata.svg';
|
||||
import { omit } from 'lodash-es';
|
||||
import type { PropType, CSSProperties } from 'vue';
|
||||
const slots = useSlots();
|
||||
const renderArr = Object.keys(slots);
|
||||
console.log(renderArr);
|
||||
|
||||
const props = defineProps({
|
||||
description: {
|
||||
type: String,
|
||||
default: '暂无数据',
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
default: NoData,
|
||||
},
|
||||
imageStyle: {
|
||||
type: Object as PropType<CSSProperties>,
|
||||
default: () => {
|
||||
return { height: '60px' };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const baseProps = omit(props, ...renderArr);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-empty-description) {
|
||||
color: #b3b3b3;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
|
@ -4,7 +4,7 @@
|
|||
<a-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled">
|
||||
<a-tooltip v-if="tooltip" v-bind="tooltip">
|
||||
<slot v-if="noButton"></slot>
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" >
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" :style="props.style">
|
||||
<slot></slot>
|
||||
<template #icon>
|
||||
<slot name="icon"></slot>
|
||||
|
@ -22,7 +22,7 @@
|
|||
<template v-else-if="tooltip">
|
||||
<a-tooltip v-bind="tooltip">
|
||||
<slot v-if="noButton"></slot>
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" >
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" :style="props.style">
|
||||
<slot></slot>
|
||||
<template #icon>
|
||||
<slot name="icon"></slot>
|
||||
|
@ -32,7 +32,7 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<slot v-if="noButton"></slot>
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" >
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" :style="props.style">
|
||||
<slot></slot>
|
||||
<template #icon>
|
||||
<slot name="icon"></slot>
|
||||
|
@ -42,7 +42,7 @@
|
|||
</template>
|
||||
<a-tooltip v-else title="没有权限">
|
||||
<slot v-if="noButton"></slot>
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" >
|
||||
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" :style="props.style">
|
||||
<slot></slot>
|
||||
<template #icon>
|
||||
<slot name="icon"></slot>
|
||||
|
@ -51,7 +51,7 @@
|
|||
</a-tooltip>
|
||||
</template>
|
||||
<script setup lang="ts" name="PermissionButton">
|
||||
import { PropType } from 'vue'
|
||||
import { CSSProperties, PropType } from 'vue'
|
||||
import { TooltipProps, PopconfirmProps } from 'ant-design-vue/es'
|
||||
import { buttonProps } from 'ant-design-vue/es/button/button'
|
||||
import { usePermissionStore } from '@/store/permission';
|
||||
|
@ -85,6 +85,9 @@ const props = defineProps({
|
|||
hasPermission: {
|
||||
type: String || Array,
|
||||
},
|
||||
style: {
|
||||
type: Object as PropType<CSSProperties>
|
||||
},
|
||||
...buttonProps()
|
||||
})
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { UnorderedListOutlined, AppstoreOutlined } from '@ant-design/icons-vue'
|
||||
import styles from './index.module.less'
|
||||
import { Pagination, Table, Empty, Spin, Alert } from 'ant-design-vue'
|
||||
import { Pagination, Table, Spin, Alert } from 'ant-design-vue'
|
||||
import type { TableProps } from 'ant-design-vue/es/table'
|
||||
import type { TooltipProps } from 'ant-design-vue/es/tooltip'
|
||||
import type { PopconfirmProps } from 'ant-design-vue/es/popconfirm'
|
||||
import { CSSProperties, PropType } from 'vue';
|
||||
import type { JColumnsProps } from './types'
|
||||
import JEmpty from '@/components/Empty/index.vue'
|
||||
|
||||
enum ModelEnum {
|
||||
TABLE = 'TABLE',
|
||||
|
@ -146,7 +147,6 @@ const JTable = defineComponent<JTableProps>({
|
|||
}
|
||||
} as any,
|
||||
setup(props: JTableProps, { slots, emit, expose }) {
|
||||
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
|
||||
const _model = ref<keyof typeof ModelEnum>(props.model ? props.model : ModelEnum.CARD); // 模式切换
|
||||
const column = ref<number>(props.gridColumn || 4);
|
||||
const _dataSource = ref<Record<string, any>[]>([])
|
||||
|
@ -154,6 +154,7 @@ const JTable = defineComponent<JTableProps>({
|
|||
const pageSize = ref<number>(6)
|
||||
const total = ref<number>(0)
|
||||
const loading = ref<boolean>(true)
|
||||
const loading1 = ref<boolean>(true)
|
||||
|
||||
const _columns = computed(() => props.columns.filter(i => !(i?.hideInTable)))
|
||||
|
||||
|
@ -244,10 +245,6 @@ const JTable = defineComponent<JTableProps>({
|
|||
window.onresize = null
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
// console.log(props.bodyStyle)
|
||||
})
|
||||
|
||||
/**
|
||||
* 刷新数据
|
||||
* @param _params
|
||||
|
@ -292,91 +289,94 @@ const JTable = defineComponent<JTableProps>({
|
|||
</div>
|
||||
</div>
|
||||
{/* content */}
|
||||
<div class={styles['jtable-content']}>
|
||||
{
|
||||
props.alertRender && props?.rowSelection && props?.rowSelection?.selectedRowKeys && props.rowSelection.selectedRowKeys?.length ?
|
||||
<div class={styles['jtable-alert']}>
|
||||
<Alert
|
||||
message={'已选择' + props?.rowSelection?.selectedRowKeys?.length + '项'}
|
||||
type="info"
|
||||
onClose={() => {
|
||||
emit('cancelSelect')
|
||||
}}
|
||||
closeText={<a-button type="link">取消选择</a-button>}
|
||||
/>
|
||||
</div> : null
|
||||
}
|
||||
{
|
||||
_model.value === ModelEnum.CARD ?
|
||||
<div class={styles['jtable-card']}>
|
||||
{
|
||||
_dataSource.value.length ?
|
||||
<div
|
||||
class={styles['jtable-card-items']}
|
||||
style={{ gridTemplateColumns: `repeat(${column.value}, 1fr)` }}
|
||||
>
|
||||
{
|
||||
_dataSource.value.map(item => slots.card ?
|
||||
<div class={[styles['jtable-card-item'], props.cardBodyClass]}>
|
||||
{slots.card(item)}
|
||||
</div> : null
|
||||
)
|
||||
}
|
||||
</div> :
|
||||
<div><Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /></div>
|
||||
}
|
||||
</div> :
|
||||
<div>
|
||||
<Table
|
||||
dataSource={_dataSource.value}
|
||||
columns={_columns.value}
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
rowSelection={props.rowSelection}
|
||||
scroll={{ x: 1366 }}
|
||||
v-slots={{
|
||||
bodyCell: (dt: Record<string, any>) => {
|
||||
const { column, record } = dt;
|
||||
if ((column?.key || column?.dataIndex) && column?.scopedSlots && (slots?.[column?.dataIndex] || slots?.[column?.key])) {
|
||||
const _key = column?.key || column?.dataIndex
|
||||
return slots?.[_key]!(record)
|
||||
} else {
|
||||
return record?.[column?.dataIndex] || ''
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
!loading.value ? <div class={styles['jtable-content']}>
|
||||
{
|
||||
props.alertRender && props?.rowSelection && props?.rowSelection?.selectedRowKeys && props.rowSelection.selectedRowKeys?.length ?
|
||||
<div class={styles['jtable-alert']}>
|
||||
<Alert
|
||||
message={'已选择' + props?.rowSelection?.selectedRowKeys?.length + '项'}
|
||||
type="info"
|
||||
onClose={() => {
|
||||
emit('cancelSelect')
|
||||
}}
|
||||
closeText={<a-button type="link">取消选择</a-button>}
|
||||
/>
|
||||
</div> : null
|
||||
}
|
||||
{
|
||||
_model.value === ModelEnum.CARD ?
|
||||
<div class={styles['jtable-card']}>
|
||||
{
|
||||
_dataSource.value.length ?
|
||||
<div
|
||||
class={styles['jtable-card-items']}
|
||||
style={{ gridTemplateColumns: `repeat(${column.value}, 1fr)` }}
|
||||
>
|
||||
{
|
||||
_dataSource.value.map(item => slots.card ?
|
||||
<div class={[styles['jtable-card-item'], props.cardBodyClass]}>
|
||||
{slots.card(item)}
|
||||
</div> : null
|
||||
)
|
||||
}
|
||||
</div> :
|
||||
<div><JEmpty style="margin: 10% 0" /></div>
|
||||
}
|
||||
</div> :
|
||||
<div>
|
||||
<Table
|
||||
dataSource={_dataSource.value}
|
||||
columns={_columns.value}
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
rowSelection={props.rowSelection}
|
||||
scroll={{ x: 1366 }}
|
||||
v-slots={{
|
||||
bodyCell: (dt: Record<string, any>) => {
|
||||
const { column, record } = dt;
|
||||
if ((column?.key || column?.dataIndex) && column?.scopedSlots && (slots?.[column?.dataIndex] || slots?.[column?.key])) {
|
||||
const _key = column?.key || column?.dataIndex
|
||||
return slots?.[_key]!(record)
|
||||
} else {
|
||||
return record?.[column?.dataIndex] || ''
|
||||
}
|
||||
},
|
||||
emptyText: () => <JEmpty style="margin: 10% 0" />
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div> : <div style="width: 100%; height: 400px"></div>
|
||||
}
|
||||
{/* 分页 */}
|
||||
{
|
||||
(!!_dataSource.value.length) && !props.noPagination && props.type === 'PAGE' &&
|
||||
<div class={styles['jtable-pagination']}>
|
||||
{
|
||||
slots?.paginationRender ?
|
||||
slots.paginationRender() :
|
||||
<Pagination
|
||||
size="small"
|
||||
total={total.value}
|
||||
showQuickJumper={false}
|
||||
showSizeChanger={true}
|
||||
current={pageIndex.value + 1}
|
||||
pageSize={pageSize.value}
|
||||
pageSizeOptions={['12', '24', '48', '60', '100']}
|
||||
showTotal={(num) => {
|
||||
const minSize = pageIndex.value * pageSize.value + 1;
|
||||
const MaxSize = (pageIndex.value + 1) * pageSize.value;
|
||||
return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
|
||||
}}
|
||||
onChange={(page, size) => {
|
||||
handleSearch({
|
||||
...props.params,
|
||||
pageSize: size,
|
||||
pageIndex: pageSize.value === size ? (page ? page - 1 : 0) : 0
|
||||
})
|
||||
}}
|
||||
/>
|
||||
slots.paginationRender() :
|
||||
<Pagination
|
||||
size="small"
|
||||
total={total.value}
|
||||
showQuickJumper={false}
|
||||
showSizeChanger={true}
|
||||
current={pageIndex.value + 1}
|
||||
pageSize={pageSize.value}
|
||||
pageSizeOptions={['12', '24', '48', '60', '100']}
|
||||
showTotal={(num) => {
|
||||
const minSize = pageIndex.value * pageSize.value + 1;
|
||||
const MaxSize = (pageIndex.value + 1) * pageSize.value;
|
||||
return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
|
||||
}}
|
||||
onChange={(page, size) => {
|
||||
handleSearch({
|
||||
...props.params,
|
||||
pageSize: size,
|
||||
pageIndex: pageSize.value === size ? (page ? page - 1 : 0) : 0
|
||||
})
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import FileFormat from './FileFormat/index.vue'
|
|||
import JUpload from './JUpload/index.vue'
|
||||
import { BasicLayoutPage, BlankLayoutPage, PageContainer } from './Layout'
|
||||
import Ellipsis from './Ellipsis/index.vue'
|
||||
import JEmpty from './Empty/index.vue'
|
||||
|
||||
export default {
|
||||
install(app: App) {
|
||||
|
@ -28,5 +29,6 @@ export default {
|
|||
.component('BlankLayoutPage', BlankLayoutPage)
|
||||
.component('PageContainer', PageContainer)
|
||||
.component('Ellipsis', Ellipsis)
|
||||
.component('JEmpty', JEmpty)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,11 +226,11 @@
|
|||
:key="index"
|
||||
:header="
|
||||
item.productKey
|
||||
? aliyunProductList.find(
|
||||
? (aliyunProductList.find(
|
||||
(i) =>
|
||||
i.productKey ===
|
||||
item.productKey,
|
||||
)?.productName
|
||||
)?.productName || `产品映射${index + 1}`)
|
||||
: `产品映射${index + 1}`
|
||||
"
|
||||
>
|
||||
|
@ -356,12 +356,14 @@
|
|||
</a-row>
|
||||
</a-form>
|
||||
<div v-if="type === 'edit'">
|
||||
<a-button
|
||||
:loading="loading"
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="saveBtn"
|
||||
>保存</a-button
|
||||
:hasPermission="['Northbound/AliCloud:add', 'Northbound/AliCloud:update']"
|
||||
>
|
||||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
|
@ -497,11 +499,11 @@ const saveBtn = () => {
|
|||
.then(async (data: any) => {
|
||||
const product = (aliyunProductList.value || []).find(
|
||||
(item: any) =>
|
||||
item?.bridgeProductKey === data?.bridgeProductKey,
|
||||
item?.productKey === data?.bridgeProductKey,
|
||||
);
|
||||
data.bridgeProductName = product?.productName || '';
|
||||
loading.value = true;
|
||||
const resp = await savePatch(toRaw(modelRef));
|
||||
const resp = await savePatch({...toRaw(modelRef), ...data});
|
||||
loading.value = false;
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<Search :columns="columns" target="northbound-dueros" @search="handleSearch" />
|
||||
<Search :columns="columns" target="northbound-aliyun" @search="handleSearch" />
|
||||
<JTable
|
||||
ref="instanceRef"
|
||||
:columns="columns"
|
||||
|
@ -10,7 +10,14 @@
|
|||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
hasPermission="Northbound/AliCloud:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
|
@ -57,42 +64,22 @@
|
|||
</a-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
<PermissionButton
|
||||
:disabled="item.disabled"
|
||||
:popConfirm="item.popConfirm"
|
||||
:tooltip="item.tooltip"
|
||||
@click="item.onClick"
|
||||
:hasPermission="'Northbound/AliCloud:' + item.key"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="item.popConfirm"
|
||||
v-bind="item.popConfirm"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<a-button :disabled="item.disabled">
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<a-button
|
||||
:disabled="item.disabled"
|
||||
@click="item.onClick"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -103,38 +90,23 @@
|
|||
/>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="i.tooltip"
|
||||
style="padding: 0px"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
:hasPermission="'Northbound/AliCloud:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -240,7 +212,7 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -257,7 +229,7 @@ const getActions = (
|
|||
title: data.state?.value !== 'disabled' ? '禁用' : '启用',
|
||||
},
|
||||
icon:
|
||||
data.state.value !== 'notActive'
|
||||
data.state.value !== 'disabled'
|
||||
? 'StopOutlined'
|
||||
: 'CheckCircleOutlined',
|
||||
popConfirm: {
|
||||
|
|
|
@ -43,7 +43,11 @@
|
|||
]"
|
||||
>
|
||||
<a-select
|
||||
:disabled="type !== 'edit' && modelRef.id && modelRef.id !== ':id'"
|
||||
:disabled="
|
||||
type !== 'edit' &&
|
||||
modelRef.id &&
|
||||
modelRef.id !== ':id'
|
||||
"
|
||||
placeholder="请选择产品"
|
||||
v-model:value="modelRef.id"
|
||||
show-search
|
||||
|
@ -410,12 +414,14 @@
|
|||
</a-row>
|
||||
</a-form>
|
||||
<div v-if="type === 'edit'">
|
||||
<a-button
|
||||
:loading="loading"
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="saveBtn"
|
||||
>保存</a-button
|
||||
:hasPermission="['Northbound/DuerOS:add', 'Northbound/DuerOS:update']"
|
||||
>
|
||||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
|
@ -616,8 +622,8 @@ const getTypesActions = (val: string) => {
|
|||
const saveBtn = async () => {
|
||||
const tasks: any[] = [];
|
||||
for (let i = 0; i < command.value.length; i++) {
|
||||
const res = await (command.value[i] as any)?.saveBtn()
|
||||
if(!res || (res?.errorFields && res.errorFields.length)) {
|
||||
const res = await (command.value[i] as any)?.saveBtn();
|
||||
if (!res || (res?.errorFields && res.errorFields.length)) {
|
||||
actionActiveKey.value.push(String(i));
|
||||
tasks.push(false);
|
||||
} else {
|
||||
|
@ -629,7 +635,7 @@ const saveBtn = async () => {
|
|||
.then(async (data: any) => {
|
||||
if (tasks.every((item) => item) && data) {
|
||||
loading.value = true;
|
||||
const resp = await savePatch(toRaw(modelRef));
|
||||
const resp = await savePatch(data);
|
||||
loading.value = false;
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
|
@ -642,10 +648,16 @@ const saveBtn = async () => {
|
|||
const _arr = err.errorFields.map((item: any) => item.name);
|
||||
_arr.map((item: string | any[]) => {
|
||||
if (item.length >= 3) {
|
||||
if(item[0] === 'propertyMappings' && !propertyActiveKey.value.includes(item[1])){
|
||||
if (
|
||||
item[0] === 'propertyMappings' &&
|
||||
!propertyActiveKey.value.includes(item[1])
|
||||
) {
|
||||
propertyActiveKey.value.push(item[1]);
|
||||
}
|
||||
if(item[0] === 'actionMappings' && !actionActiveKey.value.includes(item[1])){
|
||||
if (
|
||||
item[0] === 'actionMappings' &&
|
||||
!actionActiveKey.value.includes(item[1])
|
||||
) {
|
||||
actionActiveKey.value.push(item[1]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,14 @@
|
|||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
hasPermission="Northbound/DuerOS:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
|
@ -55,42 +62,24 @@
|
|||
</a-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
<PermissionButton
|
||||
:disabled="item.disabled"
|
||||
:popConfirm="item.popConfirm"
|
||||
:tooltip="{
|
||||
...item.tooltip,
|
||||
}"
|
||||
@click="item.onClick"
|
||||
:hasPermission="'Northbound/DuerOS:' + item.key"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="item.popConfirm"
|
||||
v-bind="item.popConfirm"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<a-button :disabled="item.disabled">
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<a-button
|
||||
:disabled="item.disabled"
|
||||
@click="item.onClick"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -104,38 +93,25 @@
|
|||
{{ slotProps.applianceType.text }}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
style="padding: 0px"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
:hasPermission="'Northbound/DuerOS:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -143,17 +119,24 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { query, _undeploy, _deploy, _delete, queryProductList, queryTypes } from '@/api/northbound/dueros';
|
||||
import {
|
||||
query,
|
||||
_undeploy,
|
||||
_deploy,
|
||||
_delete,
|
||||
queryProductList,
|
||||
queryTypes,
|
||||
} from '@/api/northbound/dueros';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useMenuStore } from 'store/menu'
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const router = useRouter();
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
const current = ref<Record<string, any>>({});
|
||||
const menuStory = useMenuStore()
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const statusMap = new Map();
|
||||
statusMap.set('enabled', 'success');
|
||||
|
@ -238,14 +221,14 @@ const columns = [
|
|||
* 新增
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
menuStory.jumpPage('Northbound/DuerOS/Detail', { id: ':id'})
|
||||
menuStory.jumpPage('Northbound/DuerOS/Detail', { id: ':id' });
|
||||
};
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
const handleView = (id: string) => {
|
||||
menuStory.jumpPage('Northbound/DuerOS/Detail', { id }, { type: 'view' })
|
||||
menuStory.jumpPage('Northbound/DuerOS/Detail', { id }, { type: 'view' });
|
||||
};
|
||||
|
||||
const getActions = (
|
||||
|
@ -266,14 +249,18 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
menuStory.jumpPage('Northbound/DuerOS/Detail', { id: data.id }, { type: 'edit' })
|
||||
menuStory.jumpPage(
|
||||
'Northbound/DuerOS/Detail',
|
||||
{ id: data.id },
|
||||
{ type: 'edit' },
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -283,7 +270,7 @@ const getActions = (
|
|||
title: data.state?.value !== 'disabled' ? '禁用' : '启用',
|
||||
},
|
||||
icon:
|
||||
data.state.value !== 'notActive'
|
||||
data.state.value !== 'disabled'
|
||||
? 'StopOutlined'
|
||||
: 'CheckCircleOutlined',
|
||||
popConfirm: {
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<template>
|
||||
<a-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%">
|
||||
<a-select-option
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
:filter-option="filterOption"
|
||||
>{{ item.name }}</a-select-option
|
||||
>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
edgeCollector,
|
||||
edgePoint,
|
||||
} from '@/api/device/instance';
|
||||
|
||||
const _props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'POINT',
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
edgeId: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
});
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: string | undefined): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const list = ref<any[]>([]);
|
||||
const _value = ref<string | undefined>(undefined);
|
||||
|
||||
watchEffect(() => {
|
||||
_value.value = _props.modelValue;
|
||||
});
|
||||
|
||||
const onChange = (_val: string) => {
|
||||
emit('update:modelValue', _val);
|
||||
};
|
||||
|
||||
const getCollector = async (_val: string) => {
|
||||
if (!_val) {
|
||||
return [];
|
||||
} else {
|
||||
const resp = await edgeCollector(_props.edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'channelId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
list.value = (resp.result as any[])?.[0] || []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getPoint = async (_val: string) => {
|
||||
if (!_val) {
|
||||
return [];
|
||||
} else {
|
||||
const resp = await edgePoint(_props.edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'collectorId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
list.value = (resp.result as any[])?.[0] || []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (_props.id) {
|
||||
if (_props.type === 'POINT') {
|
||||
getPoint(_props.id);
|
||||
} else {
|
||||
getCollector(_props.id);
|
||||
}
|
||||
} else {
|
||||
list.value = [];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -0,0 +1,189 @@
|
|||
<template>
|
||||
<a-modal
|
||||
width="900px"
|
||||
title="批量映射"
|
||||
visible
|
||||
@ok="handleClick"
|
||||
@cancel="handleClose"
|
||||
>
|
||||
<div class="map-tree">
|
||||
<div class="map-tree-top">
|
||||
采集器的点位名称与属性名称一致时将自动映射绑定;有多个采集器点位名称与属性名称一致时以第1个采集器的点位数据进行绑定
|
||||
</div>
|
||||
<a-spin :spinning="loading">
|
||||
<div class="map-tree-content">
|
||||
<a-card class="map-tree-content-card" title="源数据">
|
||||
<a-tree
|
||||
checkable
|
||||
:height="300"
|
||||
:tree-data="dataSource"
|
||||
:checkedKeys="checkedKeys"
|
||||
@check="onCheck"
|
||||
/>
|
||||
</a-card>
|
||||
<div style="width: 100px">
|
||||
<a-button
|
||||
:disabled="rightList.length >= leftList.length"
|
||||
@click="onRight"
|
||||
>加入右侧</a-button
|
||||
>
|
||||
</div>
|
||||
<a-card class="map-tree-content-card" title="采集器">
|
||||
<a-list
|
||||
size="small"
|
||||
:data-source="rightList"
|
||||
class="map-tree-content-card-list"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
{{ item.title }}
|
||||
<template #actions>
|
||||
<a-popconfirm
|
||||
title="确定删除?"
|
||||
@confirm="_delete(item.key)"
|
||||
>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-card>
|
||||
</div>
|
||||
</a-spin>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { treeEdgeMap, saveEdgeMap } from '@/api/device/instance';
|
||||
import { message } from 'ant-design-vue/es';
|
||||
const _props = defineProps({
|
||||
metaData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
deviceId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
edgeId: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
});
|
||||
const _emits = defineEmits(['close', 'save']);
|
||||
|
||||
const checkedKeys = ref<string[]>([]);
|
||||
|
||||
const leftList = ref<any[]>([]);
|
||||
const rightList = ref<any[]>([]);
|
||||
|
||||
const dataSource = ref<any[]>([]);
|
||||
const loading = ref<boolean>(false);
|
||||
|
||||
const handleData = (data: any[], type: string) => {
|
||||
data.forEach((item) => {
|
||||
item.key = item.id;
|
||||
item.title = item.name;
|
||||
item.checkable = type === 'collectors';
|
||||
if (
|
||||
item.collectors &&
|
||||
Array.isArray(item.collectors) &&
|
||||
item.collectors.length
|
||||
) {
|
||||
item.children = handleData(item.collectors, 'collectors');
|
||||
}
|
||||
if (item.points && Array.isArray(item.points) && item.points.length) {
|
||||
item.children = handleData(item.points, 'points');
|
||||
}
|
||||
});
|
||||
return data as any[];
|
||||
};
|
||||
|
||||
const handleSearch = async () => {
|
||||
loading.value = true;
|
||||
const resp = await treeEdgeMap(_props.edgeId);
|
||||
loading.value = false;
|
||||
if (resp.status === 200) {
|
||||
dataSource.value = handleData((resp.result as any[])?.[0], 'channel');
|
||||
}
|
||||
};
|
||||
|
||||
const onCheck = (keys: string[], e: any) => {
|
||||
checkedKeys.value = [...keys];
|
||||
leftList.value = e?.checkedNodes || [];
|
||||
};
|
||||
|
||||
const onRight = () => {
|
||||
rightList.value = leftList.value;
|
||||
};
|
||||
|
||||
const _delete = (_key: string) => {
|
||||
const _index = rightList.value.findIndex((i) => i.key === _key);
|
||||
rightList.value.splice(_index, 1);
|
||||
checkedKeys.value = rightList.value.map((i) => i.key);
|
||||
leftList.value = rightList.value;
|
||||
};
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!rightList.value.length) {
|
||||
message.warning('请选择采集器');
|
||||
} else {
|
||||
const params: any[] = [];
|
||||
rightList.value.map((item: any) => {
|
||||
const array = (item.children || []).map((element: any) => ({
|
||||
channelId: item.parentId,
|
||||
collectorId: element.collectorId,
|
||||
pointId: element.id,
|
||||
metadataType: 'property',
|
||||
metadataId: (_props.metaData as any[]).find((i: any) => i.name === element.name)
|
||||
?.metadataId,
|
||||
provider: dataSource.value.find((it: any) => it.id === item.parentId).provider,
|
||||
}));
|
||||
params.push(...array);
|
||||
});
|
||||
const filterParms = params.filter((item) => !!item.metadataId);
|
||||
if (filterParms && filterParms.length !== 0) {
|
||||
const res = await saveEdgeMap(_props.edgeId, {
|
||||
deviceId: _props.deviceId,
|
||||
provider: filterParms[0]?.provider,
|
||||
requestList: filterParms,
|
||||
});
|
||||
if (res.status === 200) {
|
||||
message.success('操作成功');
|
||||
_emits('save');
|
||||
}
|
||||
} else {
|
||||
message.error('暂无对应属性的映射');
|
||||
}
|
||||
}
|
||||
};
|
||||
const handleClose = () => {
|
||||
_emits('close');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (_props.edgeId) {
|
||||
handleSearch();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.map-tree-content {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.map-tree-content-card {
|
||||
width: 350px;
|
||||
height: 400px;
|
||||
|
||||
.map-tree-content-card-list {
|
||||
overflow-y: auto;
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<a-spin :spinning="loading" v-if="metadata.properties.length">
|
||||
<a-card>
|
||||
<template #extra>
|
||||
<a-space>
|
||||
|
@ -53,6 +53,7 @@
|
|||
v-model="record[column.dataIndex]"
|
||||
:id="record.channelId"
|
||||
type="COLLECTOR"
|
||||
:edgeId="instanceStore.current.parentId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
@ -70,6 +71,7 @@
|
|||
v-model="record[column.dataIndex]"
|
||||
:id="record.collectorId"
|
||||
type="POINT"
|
||||
:edgeId="instanceStore.current.parentId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
@ -85,6 +87,7 @@
|
|||
<a-tooltip title="解绑">
|
||||
<a-popconfirm
|
||||
title="确认解绑"
|
||||
:disabled="!record.id"
|
||||
@confirm="unbind(record.id)"
|
||||
>
|
||||
<a-button type="link" :disabled="!record.id"
|
||||
|
@ -97,27 +100,30 @@
|
|||
</a-table>
|
||||
</a-form>
|
||||
</a-card>
|
||||
<!-- <PatchMapping
|
||||
<PatchMapping
|
||||
:deviceId="instanceStore.current.id"
|
||||
v-if="visible"
|
||||
@close="visible = false"
|
||||
@save="onPatchBind"
|
||||
:type="provider"
|
||||
:metaData="modelRef.dataSource"
|
||||
/> -->
|
||||
:edgeId="instanceStore.current.parentId"
|
||||
/>
|
||||
</a-spin>
|
||||
<a-card v-else>
|
||||
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import {
|
||||
queryMapping,
|
||||
saveMapping,
|
||||
removeMapping,
|
||||
queryChannelNoPaging,
|
||||
getEdgeMap,
|
||||
saveEdgeMap,
|
||||
removeEdgeMap,
|
||||
edgeChannel,
|
||||
} from '@/api/device/instance';
|
||||
import MSelect from '../components/MSelect.vue';
|
||||
// import PatchMapping from '../components/PatchMapping.vue';
|
||||
import MSelect from './MSelect.vue';
|
||||
import PatchMapping from './PatchMapping.vue';
|
||||
import { message } from 'ant-design-vue/es';
|
||||
|
||||
const columns = [
|
||||
|
@ -162,13 +168,6 @@ const filterOption = (input: string, option: any) => {
|
|||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
provider: {
|
||||
type: String,
|
||||
default: 'MODBUS_TCP',
|
||||
},
|
||||
});
|
||||
|
||||
const instanceStore = useInstanceStore();
|
||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}');
|
||||
const loading = ref<boolean>(false);
|
||||
|
@ -182,25 +181,15 @@ const formRef = ref();
|
|||
const visible = ref<boolean>(false);
|
||||
|
||||
const getChannel = async () => {
|
||||
const resp: any = await queryChannelNoPaging({
|
||||
paging: false,
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'provider',
|
||||
value: props.provider,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
channelList.value = resp.result?.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
provider: item.provider,
|
||||
}));
|
||||
if (instanceStore.current?.parentId) {
|
||||
const resp: any = await edgeChannel(instanceStore.current.parentId);
|
||||
if (resp.status === 200) {
|
||||
channelList.value = resp.result?.[0]?.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
provider: item.provider,
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -214,12 +203,15 @@ const handleSearch = async () => {
|
|||
name: item.name,
|
||||
}));
|
||||
if (_metadata && _metadata.length) {
|
||||
const resp: any = await queryMapping(
|
||||
'device',
|
||||
instanceStore.current.id,
|
||||
);
|
||||
const resp: any = await getEdgeMap(instanceStore.current?.parentId || '', {
|
||||
deviceId: instanceStore.current.id,
|
||||
query: {},
|
||||
}).catch(() => {
|
||||
modelRef.dataSource = _metadata;
|
||||
loading.value = false;
|
||||
})
|
||||
if (resp.status === 200) {
|
||||
const array = resp.result.reduce((x: any, y: any) => {
|
||||
const array = resp.result?.[0].reduce((x: any, y: any) => {
|
||||
const metadataId = _metadata.find(
|
||||
(item: any) => item.metadataId === y.metadataId,
|
||||
);
|
||||
|
@ -238,9 +230,10 @@ const handleSearch = async () => {
|
|||
|
||||
const unbind = async (id: string) => {
|
||||
if (id) {
|
||||
const resp = await removeMapping('device', instanceStore.current.id, [
|
||||
id,
|
||||
]);
|
||||
const resp = await removeEdgeMap(instanceStore.current?.parentId || '', {
|
||||
deviceId: instanceStore.current.id,
|
||||
idList: [id],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
handleSearch();
|
||||
|
@ -265,11 +258,12 @@ const onSave = () => {
|
|||
(i: any) => i.channelId,
|
||||
);
|
||||
if (arr && arr.length !== 0) {
|
||||
const resp = await saveMapping(
|
||||
instanceStore.current.id,
|
||||
props.provider,
|
||||
arr,
|
||||
);
|
||||
const submitData = {
|
||||
deviceId: instanceStore.current.id,
|
||||
provider: (arr[0] as any)?.provider,
|
||||
requestList: arr,
|
||||
};
|
||||
const resp = await saveEdgeMap(instanceStore.current.parentId || '', submitData);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
handleSearch();
|
||||
|
|
|
@ -14,60 +14,79 @@
|
|||
>
|
||||
<a-row :gutter="30">
|
||||
<a-col :span="15">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="func.table"
|
||||
:pagination="false"
|
||||
rowKey="id"
|
||||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'type'">
|
||||
<span>{{ record.type }}</span>
|
||||
<a-tooltip v-if="record.type === 'object'">
|
||||
<template slot="title">
|
||||
请按照json格式输入
|
||||
</template>
|
||||
<a-form :ref="`${func.id}Ref`" :model="func">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="func.table"
|
||||
:pagination="false"
|
||||
rowKey="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template
|
||||
v-if="column.dataIndex === 'type'"
|
||||
>
|
||||
<span>{{ record.type }}</span>
|
||||
<a-tooltip
|
||||
v-if="record.type === 'object'"
|
||||
>
|
||||
<template slot="title">
|
||||
请按照json格式输入
|
||||
</template>
|
||||
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
:style="{
|
||||
marginLeft: '5px',
|
||||
cursor: 'help',
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
:style="{
|
||||
marginLeft: '5px',
|
||||
cursor: 'help',
|
||||
}"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template
|
||||
v-if="column.dataIndex === 'value'"
|
||||
>
|
||||
<a-form-item
|
||||
:name="['table', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '',
|
||||
}"
|
||||
/>
|
||||
</a-tooltip>
|
||||
has-feedback
|
||||
>
|
||||
<ValueItem
|
||||
:ref="`valueItemRef${record.id}`"
|
||||
v-model:modelValue="
|
||||
record.value
|
||||
"
|
||||
:itemType="record.type"
|
||||
:options="
|
||||
record.type === 'enum'
|
||||
? (
|
||||
record?.options
|
||||
?.elements || []
|
||||
).map((item:any) => ({
|
||||
label: item.text,
|
||||
value: item.value,
|
||||
}))
|
||||
: record.type === 'boolean'
|
||||
? [
|
||||
{
|
||||
label: '是',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: '否',
|
||||
value: false,
|
||||
},
|
||||
]
|
||||
: undefined
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'value'">
|
||||
<ValueItem
|
||||
:ref="`valueItemRef${record.id}`"
|
||||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
:options="
|
||||
record.type === 'enum'
|
||||
? (
|
||||
record?.options
|
||||
?.elements || []
|
||||
).map((item:any) => ({
|
||||
label: item.text,
|
||||
value: item.value,
|
||||
}))
|
||||
: record.type === 'boolean'
|
||||
? [
|
||||
{
|
||||
label: '是',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: '否',
|
||||
value: false,
|
||||
},
|
||||
]
|
||||
: undefined
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-table>
|
||||
</a-form>
|
||||
<div class="editor-btn">
|
||||
<a-space>
|
||||
<a-button
|
||||
|
@ -180,36 +199,46 @@ const newFunctions = computed(() => {
|
|||
* 执行
|
||||
*/
|
||||
const handleExecute = async (func: any) => {
|
||||
const obj = {};
|
||||
func.table.forEach((item: any) => {
|
||||
if (item.type === 'object') {
|
||||
obj[item.id] = JSON.parse(item.value);
|
||||
} else {
|
||||
obj[item.id] = item.value;
|
||||
}
|
||||
});
|
||||
const { success, result } = await execute(
|
||||
route.params.id as string,
|
||||
func.id,
|
||||
obj,
|
||||
);
|
||||
if (!success) return;
|
||||
message.success('操作成功');
|
||||
func.executeResult = result instanceof Array ? result[0] : result;
|
||||
proxy?.$forceUpdate();
|
||||
proxy?.$refs[`${func.id}Ref`][0]
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const obj = {};
|
||||
func.table.forEach((item: any) => {
|
||||
if (item.type === 'object') {
|
||||
obj[item.id] = JSON.parse(item.value);
|
||||
} else {
|
||||
obj[item.id] = item.value;
|
||||
}
|
||||
});
|
||||
const { success, result } = await execute(
|
||||
route.params.id as string,
|
||||
func.id,
|
||||
obj,
|
||||
);
|
||||
if (!success) return;
|
||||
message.success('操作成功');
|
||||
func.executeResult = result instanceof Array ? result[0] : result;
|
||||
proxy?.$forceUpdate();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log('err: ', err);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
const handleClear = (func: any) => {
|
||||
func.table.forEach((item: any) => {
|
||||
item.value = undefined;
|
||||
proxy.$refs[`valueItemRef${item.id}`][0].myValue = undefined;
|
||||
});
|
||||
proxy?.$refs[`${func.id}Ref`][0].resetFields();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-table-cell .ant-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
:deep(.ant-form-item-with-help .ant-form-item-explain) {
|
||||
min-height: 0;
|
||||
}
|
||||
.wrapper {
|
||||
.tips {
|
||||
margin-bottom: 10px;
|
||||
|
|
|
@ -1,90 +1,153 @@
|
|||
<template>
|
||||
<div style="margin-top: 20px" v-if="config.length">
|
||||
<div style="display: flex; margin-bottom: 20px; align-items: center;">
|
||||
<div style="display: flex; margin-bottom: 20px; align-items: center">
|
||||
<div style="font-size: 16px; font-weight: 700">配置</div>
|
||||
<a-space>
|
||||
<a-button type="link" @click="visible = true"><AIcon type="EditOutlined" />编辑</a-button>
|
||||
<a-popconfirm title="确认重新应用该配置?" @confirm="deployBtn">
|
||||
<a-button type="link" v-if="instanceStore.detail.current?.value !== 'notActive'"><AIcon type="CheckOutlined" />应用配置<a-tooltip title="修改配置后需重新应用后才能生效。"><AIcon type="QuestionCircleOutlined" /></a-tooltip></a-button>
|
||||
</a-popconfirm>
|
||||
<a-popconfirm title="确认恢复默认配置?" @confirm="resetBtn">
|
||||
<a-button type="link" v-if="instanceStore.detail.aloneConfiguration"><AIcon type="SyncOutlined" />恢复默认<a-tooltip title="该设备单独编辑过配置信息,点击此将恢复成默认的配置信息,请谨慎操作。"><AIcon type="QuestionCircleOutlined" /></a-tooltip></a-button>
|
||||
</a-popconfirm>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="visible = true"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<template #icon><AIcon type="EditOutlined" /></template>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
v-if="instanceStore.detail.current?.value !== 'notActive'"
|
||||
:popConfirm="{
|
||||
title: '确认重新应用该配置?',
|
||||
onConfirm: deployBtn,
|
||||
}"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<AIcon type="CheckOutlined" />应用配置<a-tooltip
|
||||
title="修改配置后需重新应用后才能生效。"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></a-tooltip>
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
v-if="instanceStore.detail.aloneConfiguration"
|
||||
:popConfirm="{
|
||||
title: '确认恢复默认配置?',
|
||||
onConfirm: resetBtn,
|
||||
}"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<AIcon type="SyncOutlined" />恢复默认<a-tooltip
|
||||
title="该设备单独编辑过配置信息,点击此将恢复成默认的配置信息,请谨慎操作。"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></a-tooltip>
|
||||
</PermissionButton>
|
||||
</a-space>
|
||||
</div>
|
||||
<a-descriptions bordered size="small" v-for="i in config" :key="i.name">
|
||||
<template #title><h4 style="font-size: 15px">{{i.name}}</h4></template>
|
||||
<a-descriptions-item v-for="item in i.properties" :key="item.property">
|
||||
<template #title
|
||||
><h4 style="font-size: 15px">{{ i.name }}</h4></template
|
||||
>
|
||||
<a-descriptions-item
|
||||
v-for="item in i.properties"
|
||||
:key="item.property"
|
||||
>
|
||||
<template #label>
|
||||
<span style="margin-right: 5px">{{item.name}}</span>
|
||||
<a-tooltip v-if="item.description" :title="item.description"><AIcon type="QuestionCircleOutlined" /></a-tooltip>
|
||||
<span style="margin-right: 5px">{{ item.name }}</span>
|
||||
<a-tooltip v-if="item.description" :title="item.description"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></a-tooltip>
|
||||
</template>
|
||||
<span v-if="item.type.type === 'password' && instanceStore.current?.configuration?.[item.property]?.length > 0">******</span>
|
||||
<span
|
||||
v-if="
|
||||
item.type.type === 'password' &&
|
||||
instanceStore.current?.configuration?.[item.property]
|
||||
?.length > 0
|
||||
"
|
||||
>******</span
|
||||
>
|
||||
<span v-else>
|
||||
<span>{{ instanceStore.current?.configuration?.[item.property] || '' }}</span>
|
||||
<a-tooltip v-if="isExit(item.property)" :title="`有效值:${instanceStore.current?.configuration?.[item.property]}`"><AIcon type="QuestionCircleOutlined" /></a-tooltip>
|
||||
<span>{{
|
||||
instanceStore.current?.configuration?.[item.property] ||
|
||||
''
|
||||
}}</span>
|
||||
<a-tooltip
|
||||
v-if="isExit(item.property)"
|
||||
:title="`有效值:${
|
||||
instanceStore.current?.configuration?.[
|
||||
item.property
|
||||
]
|
||||
}`"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></a-tooltip>
|
||||
</span>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<Save v-if="visible" @save="saveBtn" @close="visible = false" :config="config" />
|
||||
<Save
|
||||
v-if="visible"
|
||||
@save="saveBtn"
|
||||
@close="visible = false"
|
||||
:config="config"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useInstanceStore } from "@/store/instance"
|
||||
import { ConfigMetadata } from "@/views/device/Product/typings"
|
||||
import { getConfigMetadata, _deploy, configurationReset } from '@/api/device/instance'
|
||||
import { message } from "ant-design-vue"
|
||||
import Save from './Save.vue'
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import { ConfigMetadata } from '@/views/device/Product/typings';
|
||||
import {
|
||||
getConfigMetadata,
|
||||
_deploy,
|
||||
configurationReset,
|
||||
} from '@/api/device/instance';
|
||||
import { message } from 'ant-design-vue';
|
||||
import Save from './Save.vue';
|
||||
|
||||
const instanceStore = useInstanceStore()
|
||||
const visible = ref<boolean>(false)
|
||||
const config = ref<ConfigMetadata[]>([])
|
||||
const instanceStore = useInstanceStore();
|
||||
const visible = ref<boolean>(false);
|
||||
const config = ref<ConfigMetadata[]>([]);
|
||||
|
||||
watchEffect(() => {
|
||||
if(instanceStore.current.id){
|
||||
getConfigMetadata(instanceStore.current.id).then(resp => {
|
||||
if(resp.status === 200){
|
||||
config.value = resp?.result as ConfigMetadata[]
|
||||
if (instanceStore.current.id) {
|
||||
getConfigMetadata(instanceStore.current.id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
config.value = resp?.result as ConfigMetadata[];
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const isExit = (property: string) => {
|
||||
return (
|
||||
instanceStore.current?.cachedConfiguration &&
|
||||
instanceStore.current?.cachedConfiguration[property] !== undefined &&
|
||||
instanceStore.current?.configuration &&
|
||||
instanceStore.current?.configuration[property] !==
|
||||
instanceStore.current?.cachedConfiguration[property]
|
||||
instanceStore.current?.cachedConfiguration &&
|
||||
instanceStore.current?.cachedConfiguration[property] !== undefined &&
|
||||
instanceStore.current?.configuration &&
|
||||
instanceStore.current?.configuration[property] !==
|
||||
instanceStore.current?.cachedConfiguration[property]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const deployBtn = async () => {
|
||||
if(instanceStore.current.id){
|
||||
const resp = await _deploy(instanceStore.current.id)
|
||||
if (instanceStore.current.id) {
|
||||
const resp = await _deploy(instanceStore.current.id);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功')
|
||||
instanceStore.refresh(instanceStore.current.id)
|
||||
message.success('操作成功');
|
||||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const resetBtn = async () => {
|
||||
if(instanceStore.current.id){
|
||||
const resp = await configurationReset(instanceStore.current.id)
|
||||
if (instanceStore.current.id) {
|
||||
const resp = await configurationReset(instanceStore.current.id);
|
||||
if (resp.status === 200) {
|
||||
message.success('恢复默认配置成功')
|
||||
instanceStore.refresh(instanceStore.current.id)
|
||||
message.success('恢复默认配置成功');
|
||||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const saveBtn = () => {
|
||||
visible.value = false
|
||||
if(instanceStore.current.id){
|
||||
instanceStore.refresh(instanceStore.current.id)
|
||||
visible.value = false;
|
||||
if (instanceStore.current.id) {
|
||||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -3,31 +3,50 @@
|
|||
<a-descriptions bordered>
|
||||
<template #title>
|
||||
关系信息
|
||||
<a-button type="link" @click="visible = true"><AIcon type="EditOutlined" />编辑<a-tooltip title="管理设备与其他业务的关联关系,关系来源于关系配置"><AIcon type="QuestionCircleOutlined" /></a-tooltip></a-button>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="visible = true"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<AIcon type="EditOutlined" />编辑<a-tooltip
|
||||
title="管理设备与其他业务的关联关系,关系来源于关系配置"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></a-tooltip>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<a-descriptions-item :span="1" v-for="item in dataSource" :key="item.objectId" :label="item.relationName">{{ item?.related ? (item?.related || []).map(i => i.name).join(',') : '' }}</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
:span="1"
|
||||
v-for="item in dataSource"
|
||||
:key="item.objectId"
|
||||
:label="item.relationName"
|
||||
>{{
|
||||
item?.related
|
||||
? (item?.related || []).map((i) => i.name).join(',')
|
||||
: ''
|
||||
}}</a-descriptions-item
|
||||
>
|
||||
</a-descriptions>
|
||||
<Save v-if="visible" @save="saveBtn" @close="visible = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useInstanceStore } from "@/store/instance"
|
||||
import Save from './Save.vue'
|
||||
const instanceStore = useInstanceStore()
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import Save from './Save.vue';
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
const dataSource = ref<Record<any, any>[]>([])
|
||||
const dataSource = ref<Record<any, any>[]>([]);
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
watchEffect(() => {
|
||||
const arr = (instanceStore.current?.relations || []).reverse()
|
||||
dataSource.value = arr as Record<any, any>[]
|
||||
})
|
||||
const arr = (instanceStore.current?.relations || []).reverse();
|
||||
dataSource.value = arr as Record<any, any>[];
|
||||
});
|
||||
|
||||
const saveBtn = () => {
|
||||
visible.value = false
|
||||
if(instanceStore.current.id){
|
||||
instanceStore.refresh(instanceStore.current.id)
|
||||
visible.value = false;
|
||||
if (instanceStore.current.id) {
|
||||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,32 +3,44 @@
|
|||
<a-descriptions bordered>
|
||||
<template #title>
|
||||
标签
|
||||
<a-button type="link" @click="visible = true"><AIcon type="EditOutlined" />编辑</a-button>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="visible = true"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<AIcon type="EditOutlined" />编辑
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<a-descriptions-item :span="1" v-for="item in dataSource" :key="item.key" :label="`${item.name}(${item.key})`">{{ item?.value }}</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
:span="1"
|
||||
v-for="item in dataSource"
|
||||
:key="item.key"
|
||||
:label="`${item.name}(${item.key})`"
|
||||
>{{ item?.value }}</a-descriptions-item
|
||||
>
|
||||
</a-descriptions>
|
||||
<Save v-if="visible" @close="visible = false" @save="saveBtn" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useInstanceStore } from "@/store/instance"
|
||||
import Save from './Save.vue'
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import Save from './Save.vue';
|
||||
|
||||
const instanceStore = useInstanceStore()
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
const dataSource = ref<Record<any, any>[]>([])
|
||||
const visible = ref<boolean>(false)
|
||||
const dataSource = ref<Record<any, any>[]>([]);
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
watchEffect(() => {
|
||||
const arr = (instanceStore.current?.tags || [])
|
||||
dataSource.value = arr as Record<any, any>[]
|
||||
})
|
||||
const arr = instanceStore.current?.tags || [];
|
||||
dataSource.value = arr as Record<any, any>[];
|
||||
});
|
||||
|
||||
const saveBtn = () => {
|
||||
visible.value = false
|
||||
if(instanceStore.current.id){
|
||||
instanceStore.refresh(instanceStore.current.id)
|
||||
visible.value = false;
|
||||
if (instanceStore.current.id) {
|
||||
instanceStore.refresh(instanceStore.current.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,43 +3,105 @@
|
|||
<a-descriptions bordered>
|
||||
<template #title>
|
||||
设备信息
|
||||
<a-button type="link" @click="visible = true"><AIcon type="EditOutlined" />编辑</a-button>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="visible = true"
|
||||
hasPermission="device/Instance:update"
|
||||
>
|
||||
<template #icon><AIcon type="EditOutlined" /></template>
|
||||
编辑
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<a-descriptions-item label="设备ID">{{ instanceStore.current.id }}</a-descriptions-item>
|
||||
<a-descriptions-item label="产品名称">{{ instanceStore.current.productName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="产品分类">{{ instanceStore.current.classifiedName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="设备类型">{{ instanceStore.current.deviceType?.text }}</a-descriptions-item>
|
||||
<a-descriptions-item label="固件版本">{{ instanceStore.current.firmwareInfo?.version }}</a-descriptions-item>
|
||||
<a-descriptions-item label="连接协议">{{ instanceStore.current.protocolName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="消息协议">{{ instanceStore.current.transport }}</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">{{ instanceStore.current.createTime ? moment(instanceStore.current.createTime).format('YYYY-MM-DD HH:mm:ss') : '' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="注册时间">{{ instanceStore.current.registerTime ? moment(instanceStore.current.registerTime).format('YYYY-MM-DD HH:mm:ss') : ''}}</a-descriptions-item>
|
||||
<a-descriptions-item label="最后上线时间">{{ instanceStore.current.onlineTime ? moment(instanceStore.current.onlineTime).format('YYYY-MM-DD HH:mm:ss') : '' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="父设备" v-if="instanceStore.current.deviceType?.value === 'childrenDevice'">{{ instanceStore.current.parentId }}</a-descriptions-item>
|
||||
<a-descriptions-item label="说明">{{ instanceStore.current.description }}</a-descriptions-item>
|
||||
<a-descriptions-item label="设备ID">{{
|
||||
instanceStore.current.id
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="产品名称">{{
|
||||
instanceStore.current.productName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="产品分类">{{
|
||||
instanceStore.current.classifiedName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="设备类型">{{
|
||||
instanceStore.current.deviceType?.text
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="固件版本">{{
|
||||
instanceStore.current.firmwareInfo?.version
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="连接协议">{{
|
||||
instanceStore.current.protocolName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="消息协议">{{
|
||||
instanceStore.current.transport
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">{{
|
||||
instanceStore.current.createTime
|
||||
? moment(instanceStore.current.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="注册时间">{{
|
||||
instanceStore.current.registerTime
|
||||
? moment(instanceStore.current.registerTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="最后上线时间">{{
|
||||
instanceStore.current.onlineTime
|
||||
? moment(instanceStore.current.onlineTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="父设备"
|
||||
v-if="
|
||||
instanceStore.current.deviceType?.value === 'childrenDevice'
|
||||
"
|
||||
>{{ instanceStore.current.parentId }}</a-descriptions-item
|
||||
>
|
||||
<a-descriptions-item label="说明">{{
|
||||
instanceStore.current.description
|
||||
}}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<Config />
|
||||
<Tags v-if="instanceStore.current?.tags && instanceStore.current?.tags.length > 0 " />
|
||||
<Relation v-if="instanceStore.current?.relations && instanceStore.current?.relations.length > 0" />
|
||||
<Save v-if="visible" :data="instanceStore.current" @close="visible = false" @save="saveBtn" />
|
||||
<Tags
|
||||
v-if="
|
||||
instanceStore.current?.tags &&
|
||||
instanceStore.current?.tags.length > 0
|
||||
"
|
||||
/>
|
||||
<Relation
|
||||
v-if="
|
||||
instanceStore.current?.relations &&
|
||||
instanceStore.current?.relations.length > 0
|
||||
"
|
||||
/>
|
||||
<Save
|
||||
v-if="visible"
|
||||
:data="instanceStore.current"
|
||||
@close="visible = false"
|
||||
@save="saveBtn"
|
||||
/>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useInstanceStore } from '@/store/instance'
|
||||
import Save from '../../Save/index.vue'
|
||||
import Config from './components/Config/index.vue'
|
||||
import Tags from './components/Tags/index.vue'
|
||||
import Relation from './components/Relation/index.vue'
|
||||
import moment from 'moment'
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import Save from '../../Save/index.vue';
|
||||
import Config from './components/Config/index.vue';
|
||||
import Tags from './components/Tags/index.vue';
|
||||
import Relation from './components/Relation/index.vue';
|
||||
import moment from 'moment';
|
||||
|
||||
const visible = ref<boolean>(false)
|
||||
const instanceStore = useInstanceStore()
|
||||
const visible = ref<boolean>(false);
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
const saveBtn = () => {
|
||||
if(instanceStore.current?.id){
|
||||
instanceStore.refresh(instanceStore.current?.id)
|
||||
if (instanceStore.current?.id) {
|
||||
instanceStore.refresh(instanceStore.current?.id);
|
||||
}
|
||||
visible.value = false
|
||||
}
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<a-spin :spinning="loading" v-if="metadata.properties.length">
|
||||
<a-card>
|
||||
<template #extra>
|
||||
<a-space>
|
||||
|
@ -85,6 +85,7 @@
|
|||
<a-tooltip title="解绑">
|
||||
<a-popconfirm
|
||||
title="确认解绑"
|
||||
:disabled="!record.id"
|
||||
@confirm="unbind(record.id)"
|
||||
>
|
||||
<a-button type="link" :disabled="!record.id"
|
||||
|
@ -106,6 +107,9 @@
|
|||
:metaData="modelRef.dataSource"
|
||||
/>
|
||||
</a-spin>
|
||||
<a-card v-else>
|
||||
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<template #title>
|
||||
<div>
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>{{ instanceStore.current.name }}</div>
|
||||
<AIcon type="ArrowLeftOutlined" @click="onBack" />
|
||||
<div style="margin-left: 20px">{{ instanceStore.current.name }}</div>
|
||||
<a-divider type="vertical" />
|
||||
<a-space>
|
||||
<a-badge
|
||||
|
@ -19,25 +20,35 @@
|
|||
)
|
||||
"
|
||||
/>
|
||||
<a-popconfirm
|
||||
title="确认启用设备"
|
||||
@confirm="handleAction"
|
||||
<PermissionButton
|
||||
v-if="
|
||||
instanceStore.current.state?.value ===
|
||||
'notActive'
|
||||
"
|
||||
type="link"
|
||||
style="margin-top: -5px; padding: 0 20px"
|
||||
:popConfirm="{
|
||||
title: '确认启用设备',
|
||||
onConfirm: handleAction,
|
||||
}"
|
||||
hasPermission="device/Instance:action"
|
||||
>
|
||||
<a-button type="link">启用设备</a-button>
|
||||
</a-popconfirm>
|
||||
<a-popconfirm
|
||||
title="确认断开连接"
|
||||
@confirm="handleDisconnect"
|
||||
启用设备
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
v-if="
|
||||
instanceStore.current.state?.value === 'online'
|
||||
"
|
||||
type="link"
|
||||
style="margin-top: -5px; padding: 0 20px"
|
||||
:popConfirm="{
|
||||
title: '确认断开连接?',
|
||||
onConfirm: handleDisconnect,
|
||||
}"
|
||||
hasPermission="device/Instance:action"
|
||||
>
|
||||
<a-button type="link">断开连接</a-button>
|
||||
</a-popconfirm>
|
||||
断开连接
|
||||
</PermissionButton>
|
||||
<a-tooltip
|
||||
v-if="
|
||||
instanceStore.current?.accessProvider ===
|
||||
|
@ -66,14 +77,14 @@
|
|||
instanceStore.current.id
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="所属产品">
|
||||
<a-button
|
||||
style="margin-top: -5px; padding: 0"
|
||||
<PermissionButton
|
||||
type="link"
|
||||
style="margin-top: -5px; padding: 0"
|
||||
@click="jumpProduct"
|
||||
>{{
|
||||
instanceStore.current.productName
|
||||
}}</a-button
|
||||
hasPermission="device/Product:view"
|
||||
>
|
||||
{{ instanceStore.current.productName }}
|
||||
</PermissionButton>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
|
@ -109,6 +120,9 @@ import { _deploy, _disconnect } from '@/api/device/instance';
|
|||
import { message } from 'ant-design-vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { getWebSocket } from '@/utils/websocket';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const route = useRoute();
|
||||
const instanceStore = useInstanceStore();
|
||||
|
@ -180,7 +194,9 @@ watch(
|
|||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
const onBack = () => {};
|
||||
const onBack = () => {
|
||||
menuStory.jumpPage('device/Instance');
|
||||
};
|
||||
|
||||
const onTabChange = (e: string) => {
|
||||
instanceStore.tabActiveKey = e;
|
||||
|
@ -214,12 +230,18 @@ const handleRefresh = async () => {
|
|||
};
|
||||
|
||||
const jumpProduct = () => {
|
||||
message.warn('暂未开发');
|
||||
menuStory.jumpPage('device/Product/Detail', {
|
||||
id: instanceStore.current.productId,
|
||||
});
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
const keys = list.value.map((i) => i.key);
|
||||
if (instanceStore.current.protocol && !(['modbus-tcp', 'opc-ua'].includes(instanceStore.current.protocol)) && !keys.includes('Diagnose')) {
|
||||
if (
|
||||
instanceStore.current.protocol &&
|
||||
!['modbus-tcp', 'opc-ua'].includes(instanceStore.current.protocol) &&
|
||||
!keys.includes('Diagnose')
|
||||
) {
|
||||
list.value.push({
|
||||
key: 'Diagnose',
|
||||
tab: '设备诊断',
|
||||
|
|
|
@ -19,7 +19,14 @@
|
|||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
hasPermission="device/Instance:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
<a-dropdown>
|
||||
<a-button
|
||||
>批量操作 <AIcon type="DownOutlined"
|
||||
|
@ -27,77 +34,101 @@
|
|||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<a-button @click="exportVisible = true"
|
||||
><AIcon
|
||||
type="ExportOutlined"
|
||||
/>批量导出设备</a-button
|
||||
<PermissionButton
|
||||
@click="exportVisible = true"
|
||||
hasPermission="device/Instance:export"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon type="ExportOutlined"
|
||||
/></template>
|
||||
批量导出设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-button @click="importVisible = true"
|
||||
><AIcon
|
||||
type="ImportOutlined"
|
||||
/>批量导入设备</a-button
|
||||
<PermissionButton
|
||||
@click="importVisible = true"
|
||||
hasPermission="device/Instance:import"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon type="ImportOutlined"
|
||||
/></template>
|
||||
批量导入设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
@confirm="activeAllDevice"
|
||||
title="确认激活全部设备?"
|
||||
>
|
||||
<a-button type="primary" ghost
|
||||
><AIcon
|
||||
type="CheckCircleOutlined"
|
||||
/>激活全部设备</a-button
|
||||
>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-button
|
||||
@click="syncDeviceStatus"
|
||||
<PermissionButton
|
||||
ghost
|
||||
type="primary"
|
||||
><AIcon
|
||||
type="SyncOutlined"
|
||||
/>同步设备状态</a-button
|
||||
:popConfirm="{
|
||||
title: '确认激活全部设备?',
|
||||
onConfirm: activeAllDevice,
|
||||
}"
|
||||
hasPermission="device/Instance:action"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon type="CheckCircleOutlined"
|
||||
/></template>
|
||||
激活全部设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="syncDeviceStatus"
|
||||
hasPermission="device/Instance:view"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon type="SyncOutlined"
|
||||
/></template>
|
||||
同步设备状态
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="_selectedRowKeys.length">
|
||||
<a-popconfirm
|
||||
@confirm="delSelectedDevice"
|
||||
title="已启用的设备无法删除,确认删除选中的禁用状态设备?"
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
danger
|
||||
:popConfirm="{
|
||||
title: '已启用的设备无法删除,确认删除选中的禁用状态设备?',
|
||||
onConfirm: delSelectedDevice,
|
||||
}"
|
||||
hasPermission="device/Instance:delete"
|
||||
>
|
||||
<a-button type="primary" danger
|
||||
><AIcon
|
||||
type="DeleteOutlined"
|
||||
/>删除选中设备</a-button
|
||||
>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
v-if="_selectedRowKeys.length"
|
||||
title="确认激活选中设备?"
|
||||
>
|
||||
<a-popconfirm
|
||||
@confirm="activeSelectedDevice"
|
||||
>
|
||||
<a-button type="primary"
|
||||
><AIcon
|
||||
type="CheckOutlined"
|
||||
/>激活选中设备</a-button
|
||||
>
|
||||
</a-popconfirm>
|
||||
<template #icon
|
||||
><AIcon type="DeleteOutlined"
|
||||
/></template>
|
||||
删除选中设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="_selectedRowKeys.length">
|
||||
<a-popconfirm
|
||||
@confirm="disabledSelectedDevice"
|
||||
title="确认禁用选中设备?"
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
:popConfirm="{
|
||||
title: '确认激活选中设备',
|
||||
onConfirm: activeSelectedDevice,
|
||||
}"
|
||||
hasPermission="device/Instance:action"
|
||||
>
|
||||
<a-button type="primary" danger
|
||||
><AIcon
|
||||
type="StopOutlined"
|
||||
/>禁用选中设备</a-button
|
||||
>
|
||||
</a-popconfirm>
|
||||
<template #icon
|
||||
><AIcon type="CheckOutlined"
|
||||
/></template>
|
||||
激活选中设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="_selectedRowKeys.length">
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
danger
|
||||
:popConfirm="{
|
||||
title: '确认禁用选中设备?',
|
||||
onConfirm: disabledSelectedDevice,
|
||||
}"
|
||||
hasPermission="device/Instance:action"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon type="StopOutlined"
|
||||
/></template>
|
||||
禁用选中设备
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
|
@ -151,42 +182,24 @@
|
|||
</a-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
<PermissionButton
|
||||
:disabled="item.disabled"
|
||||
:popConfirm="item.popConfirm"
|
||||
:tooltip="{
|
||||
...item.tooltip,
|
||||
}"
|
||||
@click="item.onClick"
|
||||
:hasPermission="'device/Instance:' + item.key"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="item.popConfirm"
|
||||
v-bind="item.popConfirm"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<a-button :disabled="item.disabled">
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<a-button
|
||||
:disabled="item.disabled"
|
||||
@click="item.onClick"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -197,38 +210,25 @@
|
|||
/>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'device/Instance:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -278,6 +278,7 @@ import {
|
|||
queryOrgThree,
|
||||
} from '@/api/device/product';
|
||||
import { queryTree } from '@/api/device/category';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
const router = useRouter();
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
|
@ -291,6 +292,8 @@ const operationVisible = ref<boolean>(false);
|
|||
const api = ref<string>('');
|
||||
const type = ref<string>('');
|
||||
|
||||
const menuStory = useMenuStore()
|
||||
|
||||
const statusMap = new Map();
|
||||
statusMap.set('online', 'success');
|
||||
statusMap.set('offline', 'error');
|
||||
|
@ -535,7 +538,7 @@ const handleAdd = () => {
|
|||
* 查看
|
||||
*/
|
||||
const handleView = (id: string) => {
|
||||
router.push('/iot/device/instance/detail/' + id);
|
||||
menuStory.jumpPage('device/Instance/Detail', {id})
|
||||
};
|
||||
|
||||
const getActions = (
|
||||
|
@ -556,7 +559,7 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
|
|
@ -195,10 +195,11 @@ import { isNoCommunity, downloadObject } from '@/utils/utils';
|
|||
import { omit } from 'lodash-es';
|
||||
import { typeOptions } from '@/components/Search/util';
|
||||
import Save from './Save/index.vue';
|
||||
import { useMenuStore } from 'store/menu'
|
||||
/**
|
||||
* 表格数据
|
||||
*/
|
||||
|
||||
const menuStory = useMenuStore()
|
||||
const router = useRouter();
|
||||
const isAdd = ref<number>(0);
|
||||
const title = ref<string>('');
|
||||
|
@ -426,7 +427,7 @@ const beforeUpload = (file: any) => {
|
|||
* 查看
|
||||
*/
|
||||
const handleView = (id: string) => {
|
||||
router.push('/iot/device/product/detail/' + id);
|
||||
menuStory.jumpPage('device/Product/Detail',{id})
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -348,9 +348,9 @@ import BindDevice from './BindDevice.vue';
|
|||
import Import from './Import.vue';
|
||||
import Export from './Export.vue';
|
||||
import Save from './Save.vue';
|
||||
|
||||
import { useMenuStore } from 'store/menu'
|
||||
const router = useRouter();
|
||||
|
||||
const menuStory = useMenuStore()
|
||||
const cardManageRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
const _selectedRowKeys = ref<string[]>([]);
|
||||
|
@ -536,9 +536,10 @@ const getActions = (
|
|||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: () => {
|
||||
router.push({
|
||||
path: `/iot-card/CardManagement/detail/${data.id}`,
|
||||
});
|
||||
// router.push({
|
||||
// path: `/iot-card/CardManagement/detail/${data.id}`,
|
||||
// });
|
||||
menuStory.jumpPage('iot-card/CardManagement/Detail',{id:data.id})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -109,7 +109,7 @@ interface GuideItemProps {
|
|||
index?: number;
|
||||
auth: boolean;
|
||||
}
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const menuHasPermission = useMenuStore().hasPermission;
|
||||
const btnHasPermission = usePermissionStore().hasPermission;
|
||||
|
||||
|
@ -134,14 +134,16 @@ const guideList = [
|
|||
name: '平台对接',
|
||||
english: 'STEP1',
|
||||
auth: paltformPermission,
|
||||
url: platformUrl,
|
||||
// url: platformUrl,
|
||||
url: 'iot-card/Platform/Detail',
|
||||
},
|
||||
{
|
||||
key: 'SCREEN',
|
||||
name: '物联卡管理',
|
||||
english: 'STEP2',
|
||||
auth: !!cardPermission,
|
||||
url: cardUrl,
|
||||
// url: cardUrl,
|
||||
url: 'iot-card/CardManagement',
|
||||
param: { save: true },
|
||||
},
|
||||
{
|
||||
|
@ -149,7 +151,8 @@ const guideList = [
|
|||
name: '操作记录',
|
||||
english: 'STEP3',
|
||||
auth: !!recordUrl,
|
||||
url: recordUrl,
|
||||
// url: recordUrl,
|
||||
url: 'iot-card/Record',
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -177,19 +180,25 @@ const pieChartData = ref<any[]>([
|
|||
]);
|
||||
|
||||
const jumpPage = (data: GuideItemProps) => {
|
||||
if (data.url && data.auth) {
|
||||
router.push({ path: `${data.url}`, ...data.param });
|
||||
// if (data.url && data.auth) {
|
||||
// router.push({ path: `${data.url}`, ...data.param });
|
||||
// } else {
|
||||
// message.warning('暂无权限,请联系管理员');
|
||||
// }
|
||||
if (data.key === 'EQUIPMENT') {
|
||||
menuStory.jumpPage(data.url, { id: 'add' });
|
||||
} else {
|
||||
message.warning('暂无权限,请联系管理员');
|
||||
menuStory.jumpPage(data.url);
|
||||
}
|
||||
};
|
||||
|
||||
const jumpDashboard = () => {
|
||||
if (dashBoardUrl) {
|
||||
router.push(`${dashBoardUrl}`);
|
||||
} else {
|
||||
message.warning('暂无权限,请联系管理员');
|
||||
}
|
||||
// if (dashBoardUrl) {
|
||||
// router.push(`${dashBoardUrl}`);
|
||||
// } else {
|
||||
// message.warning('暂无权限,请联系管理员');
|
||||
// }
|
||||
menuStory.jumpPage('iot-card/Dashboard');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -145,9 +145,9 @@ import { getImage } from '@/utils/comm';
|
|||
import type { ActionsType } from '@/components/Table';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { queryList, update, del } from '@/api/iot-card/platform';
|
||||
|
||||
import { useMenuStore } from 'store/menu'
|
||||
const menuStory = useMenuStore()
|
||||
const router = useRouter()
|
||||
|
||||
const platformRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
|
@ -225,7 +225,8 @@ const getActions = (
|
|||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
router.push(`/iot-card/Platform/detail/${data.id}`);
|
||||
// router.push(`/iot-card/Platform/detail/${data.id}`);
|
||||
menuStory.jumpPage('iot-card/Platform/Detail',{id:data.id});
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -298,7 +299,7 @@ const handleSearch = (e: any) => {
|
|||
* 新增
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
router.push(`/iot-card/Platform/detail/:id`)
|
||||
menuStory.jumpPage('iot-card/Platform/Detail',{id:'add'})
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -8,8 +8,12 @@
|
|||
@cancel="handleCancel"
|
||||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="通知模版" v-bind="validateInfos.templateId">
|
||||
<a-form ref="formRef" layout="vertical" :model="formData">
|
||||
<a-form-item
|
||||
label="通知模版"
|
||||
name="templateId"
|
||||
:rules="{ required: true, message: '该字段为必填字段' }"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="formData.templateId"
|
||||
placeholder="请选择通知模版"
|
||||
|
@ -26,32 +30,37 @@
|
|||
</a-form-item>
|
||||
<a-form-item
|
||||
label="变量"
|
||||
v-bind="validateInfos.variableDefinitions"
|
||||
v-if="templateDetailTable && templateDetailTable.length"
|
||||
v-if="
|
||||
formData.templateDetailTable &&
|
||||
formData.templateDetailTable.length
|
||||
"
|
||||
>
|
||||
<a-table
|
||||
ref="myTable"
|
||||
class="debug-table"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="templateDetailTable"
|
||||
:data-source="formData.templateDetailTable"
|
||||
:pagination="false"
|
||||
:rowKey="
|
||||
(record, index) => {
|
||||
return record.id;
|
||||
}
|
||||
"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template
|
||||
v-if="['id', 'name'].includes(column.dataIndex)"
|
||||
>
|
||||
<span>{{ record[column.dataIndex] }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ValueItem
|
||||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
<a-form-item
|
||||
:name="['templateDetailTable', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '该字段为必填字段',
|
||||
}"
|
||||
>
|
||||
<ValueItem
|
||||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
@ -61,7 +70,6 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { PropType } from 'vue';
|
||||
import ConfigApi from '@/api/notice/config';
|
||||
import type {
|
||||
|
@ -70,8 +78,6 @@ import type {
|
|||
} from '@/views/notice/Template/types';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
};
|
||||
|
@ -115,15 +121,16 @@ watch(
|
|||
/**
|
||||
* 获取模板详情
|
||||
*/
|
||||
const templateDetailTable = ref<IVariableDefinitions[]>();
|
||||
const getTemplateDetail = async () => {
|
||||
const { result } = await ConfigApi.getTemplateDetail(
|
||||
formData.value.templateId,
|
||||
);
|
||||
templateDetailTable.value = result.variableDefinitions.map((m: any) => ({
|
||||
...m,
|
||||
value: undefined,
|
||||
}));
|
||||
formData.value.templateDetailTable = result.variableDefinitions.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
value: undefined,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
|
@ -146,31 +153,27 @@ const columns = [
|
|||
];
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
const formData = ref<{
|
||||
templateId: string;
|
||||
variableDefinitions: string;
|
||||
templateDetailTable: IVariableDefinitions[];
|
||||
}>({
|
||||
templateId: '',
|
||||
variableDefinitions: '',
|
||||
templateDetailTable: [],
|
||||
});
|
||||
|
||||
// 验证规则
|
||||
const formRules = ref({
|
||||
templateId: [{ required: true, message: '请选择通知模板' }],
|
||||
variableDefinitions: [{ required: false, message: '该字段是必填字段' }],
|
||||
});
|
||||
|
||||
const { resetFields, validate, validateInfos, clearValidate } = useForm(
|
||||
formData.value,
|
||||
formRules.value,
|
||||
);
|
||||
|
||||
/**
|
||||
* 提交
|
||||
*/
|
||||
const formRef = ref();
|
||||
const btnLoading = ref(false);
|
||||
const handleOk = () => {
|
||||
validate()
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const params = {};
|
||||
templateDetailTable.value?.forEach((item) => {
|
||||
formData.value.templateDetailTable?.forEach((item) => {
|
||||
params[item.id] = item.value;
|
||||
});
|
||||
// console.log('params: ', params);
|
||||
|
@ -186,16 +189,20 @@ const handleOk = () => {
|
|||
btnLoading.value = false;
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
console.log('err: ', err);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
_vis.value = false;
|
||||
templateDetailTable.value = [];
|
||||
resetFields();
|
||||
formRef.value.resetFields();
|
||||
formData.value.templateDetailTable = [];
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-table-cell .ant-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -329,8 +329,6 @@ const getActions = (
|
|||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
// visible.value = true;
|
||||
// current.value = data;
|
||||
menuStory.jumpPage('notice/Config/Detail', {
|
||||
id: data.id,
|
||||
});
|
||||
|
|
|
@ -8,8 +8,12 @@
|
|||
@cancel="handleCancel"
|
||||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="通知配置" v-bind="validateInfos.configId">
|
||||
<a-form ref="formRef" layout="vertical" :model="formData">
|
||||
<a-form-item
|
||||
label="通知配置"
|
||||
name="configId"
|
||||
:rules="{ required: true, message: '该字段为必填字段' }"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="formData.configId"
|
||||
placeholder="请选择通知配置"
|
||||
|
@ -25,32 +29,37 @@
|
|||
</a-form-item>
|
||||
<a-form-item
|
||||
label="变量"
|
||||
v-bind="validateInfos.variableDefinitions"
|
||||
v-if="templateDetailTable && templateDetailTable.length"
|
||||
v-if="
|
||||
formData.templateDetailTable &&
|
||||
formData.templateDetailTable.length
|
||||
"
|
||||
>
|
||||
<a-table
|
||||
ref="myTable"
|
||||
class="debug-table"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="templateDetailTable"
|
||||
:data-source="formData.templateDetailTable"
|
||||
:pagination="false"
|
||||
:rowKey="
|
||||
(record, index) => {
|
||||
return record.id;
|
||||
}
|
||||
"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template
|
||||
v-if="['id', 'name'].includes(column.dataIndex)"
|
||||
>
|
||||
<span>{{ record[column.dataIndex] }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ValueItem
|
||||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
<a-form-item
|
||||
:name="['templateDetailTable', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '该字段为必填字段',
|
||||
}"
|
||||
>
|
||||
<ValueItem
|
||||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
@ -60,7 +69,6 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { PropType } from 'vue';
|
||||
import TemplateApi from '@/api/notice/template';
|
||||
import type {
|
||||
|
@ -70,7 +78,6 @@ import type {
|
|||
} from '@/views/notice/Template/types';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
|
@ -103,6 +110,7 @@ const getConfigList = async () => {
|
|||
};
|
||||
const { result } = await TemplateApi.getConfig(params);
|
||||
configList.value = result;
|
||||
formData.value.configId = result[0]?.id;
|
||||
};
|
||||
|
||||
watch(
|
||||
|
@ -118,13 +126,14 @@ watch(
|
|||
/**
|
||||
* 获取模板详情
|
||||
*/
|
||||
const templateDetailTable = ref<IVariableDefinitions[]>();
|
||||
const getTemplateDetail = async () => {
|
||||
const { result } = await TemplateApi.getTemplateDetail(props.data.id);
|
||||
templateDetailTable.value = result.variableDefinitions.map((m: any) => ({
|
||||
...m,
|
||||
value: undefined,
|
||||
}));
|
||||
formData.value.templateDetailTable = result.variableDefinitions.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
value: undefined,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
|
@ -147,31 +156,27 @@ const columns = [
|
|||
];
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
const formData = ref<{
|
||||
configId: string;
|
||||
variableDefinitions: string;
|
||||
templateDetailTable: IVariableDefinitions[];
|
||||
}>({
|
||||
configId: '',
|
||||
variableDefinitions: '',
|
||||
templateDetailTable: [],
|
||||
});
|
||||
|
||||
// 验证规则
|
||||
const formRules = ref({
|
||||
configId: [{ required: true, message: '请选择通知模板' }],
|
||||
variableDefinitions: [{ required: false, message: '该字段是必填字段' }],
|
||||
});
|
||||
|
||||
const { resetFields, validate, validateInfos, clearValidate } = useForm(
|
||||
formData.value,
|
||||
formRules.value,
|
||||
);
|
||||
|
||||
/**
|
||||
* 提交
|
||||
*/
|
||||
const formRef = ref();
|
||||
const btnLoading = ref(false);
|
||||
const handleOk = () => {
|
||||
validate()
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const params = {};
|
||||
templateDetailTable.value?.forEach((item) => {
|
||||
formData.value.templateDetailTable?.forEach((item) => {
|
||||
params[item.id] = item.value;
|
||||
});
|
||||
// console.log('params: ', params);
|
||||
|
@ -187,16 +192,20 @@ const handleOk = () => {
|
|||
btnLoading.value = false;
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch((err: any) => {
|
||||
console.log('err: ', err);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
_vis.value = false;
|
||||
templateDetailTable.value = [];
|
||||
resetFields();
|
||||
formRef.value.resetFields();
|
||||
formData.value.templateDetailTable = [];
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-table-cell .ant-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -801,7 +801,7 @@ const resetPublicFiles = () => {
|
|||
formData.value.configId = undefined;
|
||||
|
||||
if (
|
||||
formData.value.type === 'dingTalk' ||
|
||||
formData.value.provider === 'dingTalkMessage' ||
|
||||
formData.value.type === 'weixin'
|
||||
) {
|
||||
formData.value.template.toTag = undefined;
|
||||
|
@ -961,7 +961,6 @@ const handleTypeChange = () => {
|
|||
const handleProviderChange = () => {
|
||||
formData.value.template =
|
||||
TEMPLATE_FIELD_MAP[formData.value.type][formData.value.provider];
|
||||
console.log('formData.value.template: ', formData.value.template);
|
||||
getConfigList();
|
||||
resetPublicFiles();
|
||||
};
|
||||
|
@ -1023,29 +1022,32 @@ const handleSubmit = () => {
|
|||
if (formData.value.template.messageType === 'link')
|
||||
delete formData.value.template.markdown;
|
||||
// console.log('formData.value: ', formData.value);
|
||||
validate()
|
||||
.then(async () => {
|
||||
formData.value.template.ttsCode =
|
||||
formData.value.template.templateCode;
|
||||
btnLoading.value = true;
|
||||
let res;
|
||||
if (!formData.value.id) {
|
||||
res = await templateApi.save(formData.value);
|
||||
} else {
|
||||
res = await templateApi.update(formData.value);
|
||||
}
|
||||
// console.log('res: ', res);
|
||||
if (res?.success) {
|
||||
message.success('保存成功');
|
||||
router.back();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err: ', err);
|
||||
})
|
||||
.finally(() => {
|
||||
btnLoading.value = false;
|
||||
});
|
||||
// 提交必填验证无法通过, 实际已有值, 问题未知, 暂时解决方法: 延迟验证
|
||||
setTimeout(() => {
|
||||
validate()
|
||||
.then(async () => {
|
||||
formData.value.template.ttsCode =
|
||||
formData.value.template.templateCode;
|
||||
btnLoading.value = true;
|
||||
let res;
|
||||
if (!formData.value.id) {
|
||||
res = await templateApi.save(formData.value);
|
||||
} else {
|
||||
res = await templateApi.update(formData.value);
|
||||
}
|
||||
// console.log('res: ', res);
|
||||
if (res?.success) {
|
||||
message.success('保存成功');
|
||||
router.back();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('err: ', err);
|
||||
})
|
||||
.finally(() => {
|
||||
btnLoading.value = false;
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// test
|
||||
|
|
|
@ -159,9 +159,9 @@
|
|||
<script setup lang="ts">
|
||||
import TemplateApi from '@/api/notice/template';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { getImage, LocalStore } from '@/utils/comm';
|
||||
// import { getImage, LocalStore } from '@/utils/comm';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
// import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
|
||||
import { NOTICE_METHOD, MSG_TYPE } from '@/views/notice/const';
|
||||
|
||||
|
@ -301,13 +301,6 @@ const handleExport = () => {
|
|||
downloadObject(configRef.value.dataSource, `通知配置`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
const handleView = (id: string) => {
|
||||
message.warn(id + '暂未开发');
|
||||
};
|
||||
|
||||
const syncVis = ref(false);
|
||||
const debugVis = ref(false);
|
||||
const logVis = ref(false);
|
||||
|
@ -326,8 +319,6 @@ const getActions = (
|
|||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
// visible.value = true;
|
||||
// current.value = data;
|
||||
menuStory.jumpPage('notice/Template/Detail', {
|
||||
id: data.id,
|
||||
});
|
||||
|
|
|
@ -85,9 +85,9 @@ export default defineConfig(({ mode}) => {
|
|||
// target: 'http://192.168.33.22:8800',
|
||||
// target: 'http://192.168.32.244:8881',
|
||||
// target: 'http://47.112.135.104:5096', // opcua
|
||||
// target: 'http://120.77.179.54:8844', // 120测试
|
||||
target: 'http://120.77.179.54:8844', // 120测试
|
||||
// target: 'http://47.108.63.174:8845', // 测试
|
||||
target: 'http://120.77.179.54:8844',
|
||||
// target: 'http://120.77.179.54:8844',
|
||||
ws: 'ws://120.77.179.54:8844',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
|
|
Loading…
Reference in New Issue