fix: 修改阿里云新增和卡片

This commit is contained in:
100011797 2023-02-23 15:47:34 +08:00
parent b239bfc8b2
commit 34d870f1ec
13 changed files with 639 additions and 482 deletions

View File

@ -51,7 +51,8 @@ const iconKeys = [
'playCircleOutlined', 'playCircleOutlined',
'RightOutlined', 'RightOutlined',
'FileTextOutlined', 'FileTextOutlined',
'UploadOutlined' 'UploadOutlined',
'ArrowLeftOutlined'
] ]
const Icon = (props: {type: string}) => { const Icon = (props: {type: string}) => {

View File

@ -4,7 +4,7 @@
<a-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled"> <a-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled">
<a-tooltip v-if="tooltip" v-bind="tooltip"> <a-tooltip v-if="tooltip" v-bind="tooltip">
<slot v-if="noButton"></slot> <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> <slot></slot>
<template #icon> <template #icon>
<slot name="icon"></slot> <slot name="icon"></slot>
@ -22,7 +22,7 @@
<template v-else-if="tooltip"> <template v-else-if="tooltip">
<a-tooltip v-bind="tooltip"> <a-tooltip v-bind="tooltip">
<slot v-if="noButton"></slot> <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> <slot></slot>
<template #icon> <template #icon>
<slot name="icon"></slot> <slot name="icon"></slot>
@ -32,7 +32,7 @@
</template> </template>
<template v-else> <template v-else>
<slot v-if="noButton"></slot> <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> <slot></slot>
<template #icon> <template #icon>
<slot name="icon"></slot> <slot name="icon"></slot>
@ -42,7 +42,7 @@
</template> </template>
<a-tooltip v-else title="没有权限"> <a-tooltip v-else title="没有权限">
<slot v-if="noButton"></slot> <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> <slot></slot>
<template #icon> <template #icon>
<slot name="icon"></slot> <slot name="icon"></slot>
@ -51,7 +51,7 @@
</a-tooltip> </a-tooltip>
</template> </template>
<script setup lang="ts" name="PermissionButton"> <script setup lang="ts" name="PermissionButton">
import { PropType } from 'vue' import { CSSProperties, PropType } from 'vue'
import { TooltipProps, PopconfirmProps } from 'ant-design-vue/es' import { TooltipProps, PopconfirmProps } from 'ant-design-vue/es'
import { buttonProps } from 'ant-design-vue/es/button/button' import { buttonProps } from 'ant-design-vue/es/button/button'
import { usePermissionStore } from '@/store/permission'; import { usePermissionStore } from '@/store/permission';
@ -85,6 +85,9 @@ const props = defineProps({
hasPermission: { hasPermission: {
type: String || Array, type: String || Array,
}, },
style: {
type: Object as PropType<CSSProperties>
},
...buttonProps() ...buttonProps()
}) })

View File

@ -154,6 +154,7 @@ const JTable = defineComponent<JTableProps>({
const pageSize = ref<number>(6) const pageSize = ref<number>(6)
const total = ref<number>(0) const total = ref<number>(0)
const loading = ref<boolean>(true) const loading = ref<boolean>(true)
const loading1 = ref<boolean>(true)
const _columns = computed(() => props.columns.filter(i => !(i?.hideInTable))) const _columns = computed(() => props.columns.filter(i => !(i?.hideInTable)))
@ -244,10 +245,6 @@ const JTable = defineComponent<JTableProps>({
window.onresize = null window.onresize = null
}) })
watchEffect(() => {
// console.log(props.bodyStyle)
})
/** /**
* *
* @param _params * @param _params
@ -292,92 +289,94 @@ const JTable = defineComponent<JTableProps>({
</div> </div>
</div> </div>
{/* content */} {/* content */}
<div class={styles['jtable-content']}> {
{ !loading.value ? <div class={styles['jtable-content']}>
props.alertRender && props?.rowSelection && props?.rowSelection?.selectedRowKeys && props.rowSelection.selectedRowKeys?.length ? {
<div class={styles['jtable-alert']}> props.alertRender && props?.rowSelection && props?.rowSelection?.selectedRowKeys && props.rowSelection.selectedRowKeys?.length ?
<Alert <div class={styles['jtable-alert']}>
message={'已选择' + props?.rowSelection?.selectedRowKeys?.length + '项'} <Alert
type="info" message={'已选择' + props?.rowSelection?.selectedRowKeys?.length + '项'}
onClose={() => { type="info"
emit('cancelSelect') onClose={() => {
}} emit('cancelSelect')
closeText={<a-button type="link"></a-button>} }}
/> closeText={<a-button type="link"></a-button>}
</div> : null />
} </div> : null
{ }
_model.value === ModelEnum.CARD ? {
<div class={styles['jtable-card']}> _model.value === ModelEnum.CARD ?
{ <div class={styles['jtable-card']}>
_dataSource.value.length ? {
<div _dataSource.value.length ?
class={styles['jtable-card-items']} <div
style={{ gridTemplateColumns: `repeat(${column.value}, 1fr)` }} 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]}> _dataSource.value.map(item => slots.card ?
{slots.card(item)} <div class={[styles['jtable-card-item'], props.cardBodyClass]}>
</div> : null {slots.card(item)}
) </div> : null
} )
</div> : }
<div><JEmpty style="margin: 10% 0" /></div> </div> :
} <div><JEmpty style="margin: 10% 0" /></div>
</div> : }
<div> </div> :
<Table <div>
dataSource={_dataSource.value} <Table
columns={_columns.value} dataSource={_dataSource.value}
pagination={false} columns={_columns.value}
rowKey="id" pagination={false}
rowSelection={props.rowSelection} rowKey="id"
scroll={{ x: 1366 }} rowSelection={props.rowSelection}
v-slots={{ scroll={{ x: 1366 }}
bodyCell: (dt: Record<string, any>) => { v-slots={{
const { column, record } = dt; bodyCell: (dt: Record<string, any>) => {
if ((column?.key || column?.dataIndex) && column?.scopedSlots && (slots?.[column?.dataIndex] || slots?.[column?.key])) { const { column, record } = dt;
const _key = column?.key || column?.dataIndex if ((column?.key || column?.dataIndex) && column?.scopedSlots && (slots?.[column?.dataIndex] || slots?.[column?.key])) {
return slots?.[_key]!(record) const _key = column?.key || column?.dataIndex
} else { return slots?.[_key]!(record)
return record?.[column?.dataIndex] || '' } else {
} return record?.[column?.dataIndex] || ''
}, }
emptyText: () => <JEmpty style="margin: 10% 0" /> },
}} emptyText: () => <JEmpty style="margin: 10% 0" />
/> }}
</div> />
} </div>
</div> }
</div> : <div style="width: 100%; height: 400px"></div>
}
{/* 分页 */} {/* 分页 */}
{ {
(!!_dataSource.value.length) && !props.noPagination && props.type === 'PAGE' && (!!_dataSource.value.length) && !props.noPagination && props.type === 'PAGE' &&
<div class={styles['jtable-pagination']}> <div class={styles['jtable-pagination']}>
{ {
slots?.paginationRender ? slots?.paginationRender ?
slots.paginationRender() : slots.paginationRender() :
<Pagination <Pagination
size="small" size="small"
total={total.value} total={total.value}
showQuickJumper={false} showQuickJumper={false}
showSizeChanger={true} showSizeChanger={true}
current={pageIndex.value + 1} current={pageIndex.value + 1}
pageSize={pageSize.value} pageSize={pageSize.value}
pageSizeOptions={['12', '24', '48', '60', '100']} pageSizeOptions={['12', '24', '48', '60', '100']}
showTotal={(num) => { showTotal={(num) => {
const minSize = pageIndex.value * pageSize.value + 1; const minSize = pageIndex.value * pageSize.value + 1;
const MaxSize = (pageIndex.value + 1) * pageSize.value; const MaxSize = (pageIndex.value + 1) * pageSize.value;
return `${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num}`; return `${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num}`;
}} }}
onChange={(page, size) => { onChange={(page, size) => {
handleSearch({ handleSearch({
...props.params, ...props.params,
pageSize: size, pageSize: size,
pageIndex: pageSize.value === size ? (page ? page - 1 : 0) : 0 pageIndex: pageSize.value === size ? (page ? page - 1 : 0) : 0
}) })
}} }}
/> />
} }
</div> </div>
} }

View File

@ -226,11 +226,11 @@
:key="index" :key="index"
:header=" :header="
item.productKey item.productKey
? aliyunProductList.find( ? (aliyunProductList.find(
(i) => (i) =>
i.productKey === i.productKey ===
item.productKey, item.productKey,
)?.productName )?.productName || `产品映射${index + 1}`)
: `产品映射${index + 1}` : `产品映射${index + 1}`
" "
> >
@ -356,12 +356,14 @@
</a-row> </a-row>
</a-form> </a-form>
<div v-if="type === 'edit'"> <div v-if="type === 'edit'">
<a-button <PermissionButton
:loading="loading"
type="primary" type="primary"
:loading="loading"
@click="saveBtn" @click="saveBtn"
>保存</a-button :hasPermission="['Northbound/AliCloud:add', 'Northbound/AliCloud:update']"
> >
保存
</PermissionButton>
</div> </div>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
@ -497,11 +499,11 @@ const saveBtn = () => {
.then(async (data: any) => { .then(async (data: any) => {
const product = (aliyunProductList.value || []).find( const product = (aliyunProductList.value || []).find(
(item: any) => (item: any) =>
item?.bridgeProductKey === data?.bridgeProductKey, item?.productKey === data?.bridgeProductKey,
); );
data.bridgeProductName = product?.productName || ''; data.bridgeProductName = product?.productName || '';
loading.value = true; loading.value = true;
const resp = await savePatch(toRaw(modelRef)); const resp = await savePatch({...toRaw(modelRef), ...data});
loading.value = false; loading.value = false;
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');

View File

@ -1,6 +1,6 @@
<template> <template>
<page-container> <page-container>
<Search :columns="columns" target="northbound-dueros" @search="handleSearch" /> <Search :columns="columns" target="northbound-aliyun" @search="handleSearch" />
<JTable <JTable
ref="instanceRef" ref="instanceRef"
:columns="columns" :columns="columns"
@ -10,7 +10,14 @@
> >
<template #headerTitle> <template #headerTitle>
<a-space> <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> </a-space>
</template> </template>
<template #card="slotProps"> <template #card="slotProps">
@ -57,42 +64,22 @@
</a-row> </a-row>
</template> </template>
<template #actions="item"> <template #actions="item">
<a-tooltip <PermissionButton
v-bind="item.tooltip" :disabled="item.disabled"
:title="item.disabled && item.tooltip.title" :popConfirm="item.popConfirm"
:tooltip="item.tooltip"
@click="item.onClick"
:hasPermission="'Northbound/AliCloud:' + item.key"
> >
<a-popconfirm <AIcon
v-if="item.popConfirm" type="DeleteOutlined"
v-bind="item.popConfirm" v-if="item.key === 'delete'"
: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>
<template v-else> <template v-else>
<a-button <AIcon :type="item.icon" />
:disabled="item.disabled" <span>{{ item?.text }}</span>
@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>
</template> </template>
</a-tooltip> </PermissionButton>
</template> </template>
</CardBox> </CardBox>
</template> </template>
@ -103,38 +90,23 @@
/> />
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
<a-space :size="16"> <a-space>
<a-tooltip <template
v-for="i in getActions(slotProps, 'table')" v-for="i in getActions(slotProps, 'table')"
:key="i.key" :key="i.key"
v-bind="i.tooltip"
> >
<a-popconfirm <PermissionButton
v-if="i.popConfirm"
v-bind="i.popConfirm"
:disabled="i.disabled" :disabled="i.disabled"
> :popConfirm="i.popConfirm"
<a-button :tooltip="i.tooltip"
:disabled="i.disabled" style="padding: 0px"
style="padding: 0" @click="i.onClick"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-popconfirm>
<a-button
style="padding: 0"
type="link" type="link"
v-else :hasPermission="'Northbound/AliCloud:' + i.key"
@click="i.onClick && i.onClick(slotProps)"
> >
<a-button <template #icon><AIcon :type="i.icon" /></template>
:disabled="i.disabled" </PermissionButton>
style="padding: 0" </template>
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip>
</a-space> </a-space>
</template> </template>
</JTable> </JTable>
@ -240,7 +212,7 @@ const getActions = (
}, },
}, },
{ {
key: 'edit', key: 'update',
text: '编辑', text: '编辑',
tooltip: { tooltip: {
title: '编辑', title: '编辑',
@ -257,7 +229,7 @@ const getActions = (
title: data.state?.value !== 'disabled' ? '禁用' : '启用', title: data.state?.value !== 'disabled' ? '禁用' : '启用',
}, },
icon: icon:
data.state.value !== 'notActive' data.state.value !== 'disabled'
? 'StopOutlined' ? 'StopOutlined'
: 'CheckCircleOutlined', : 'CheckCircleOutlined',
popConfirm: { popConfirm: {

View File

@ -43,7 +43,11 @@
]" ]"
> >
<a-select <a-select
:disabled="type !== 'edit' && modelRef.id && modelRef.id !== ':id'" :disabled="
type !== 'edit' &&
modelRef.id &&
modelRef.id !== ':id'
"
placeholder="请选择产品" placeholder="请选择产品"
v-model:value="modelRef.id" v-model:value="modelRef.id"
show-search show-search
@ -410,12 +414,14 @@
</a-row> </a-row>
</a-form> </a-form>
<div v-if="type === 'edit'"> <div v-if="type === 'edit'">
<a-button <PermissionButton
:loading="loading"
type="primary" type="primary"
:loading="loading"
@click="saveBtn" @click="saveBtn"
>保存</a-button :hasPermission="['Northbound/DuerOS:add', 'Northbound/DuerOS:update']"
> >
保存
</PermissionButton>
</div> </div>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
@ -616,8 +622,8 @@ const getTypesActions = (val: string) => {
const saveBtn = async () => { const saveBtn = async () => {
const tasks: any[] = []; const tasks: any[] = [];
for (let i = 0; i < command.value.length; i++) { for (let i = 0; i < command.value.length; i++) {
const res = await (command.value[i] as any)?.saveBtn() const res = await (command.value[i] as any)?.saveBtn();
if(!res || (res?.errorFields && res.errorFields.length)) { if (!res || (res?.errorFields && res.errorFields.length)) {
actionActiveKey.value.push(String(i)); actionActiveKey.value.push(String(i));
tasks.push(false); tasks.push(false);
} else { } else {
@ -629,7 +635,7 @@ const saveBtn = async () => {
.then(async (data: any) => { .then(async (data: any) => {
if (tasks.every((item) => item) && data) { if (tasks.every((item) => item) && data) {
loading.value = true; loading.value = true;
const resp = await savePatch(toRaw(modelRef)); const resp = await savePatch(data);
loading.value = false; loading.value = false;
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
@ -642,10 +648,16 @@ const saveBtn = async () => {
const _arr = err.errorFields.map((item: any) => item.name); const _arr = err.errorFields.map((item: any) => item.name);
_arr.map((item: string | any[]) => { _arr.map((item: string | any[]) => {
if (item.length >= 3) { 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]); 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]); actionActiveKey.value.push(item[1]);
} }
} }

View File

@ -14,7 +14,14 @@
> >
<template #headerTitle> <template #headerTitle>
<a-space> <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> </a-space>
</template> </template>
<template #card="slotProps"> <template #card="slotProps">
@ -55,42 +62,24 @@
</a-row> </a-row>
</template> </template>
<template #actions="item"> <template #actions="item">
<a-tooltip <PermissionButton
v-bind="item.tooltip" :disabled="item.disabled"
:title="item.disabled && item.tooltip.title" :popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="'Northbound/DuerOS:' + item.key"
> >
<a-popconfirm <AIcon
v-if="item.popConfirm" type="DeleteOutlined"
v-bind="item.popConfirm" v-if="item.key === 'delete'"
: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>
<template v-else> <template v-else>
<a-button <AIcon :type="item.icon" />
:disabled="item.disabled" <span>{{ item?.text }}</span>
@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>
</template> </template>
</a-tooltip> </PermissionButton>
</template> </template>
</CardBox> </CardBox>
</template> </template>
@ -104,38 +93,25 @@
{{ slotProps.applianceType.text }} {{ slotProps.applianceType.text }}
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
<a-space :size="16"> <a-space>
<a-tooltip <template
v-for="i in getActions(slotProps, 'table')" v-for="i in getActions(slotProps, 'table')"
:key="i.key" :key="i.key"
v-bind="i.tooltip"
> >
<a-popconfirm <PermissionButton
v-if="i.popConfirm"
v-bind="i.popConfirm"
:disabled="i.disabled" :disabled="i.disabled"
> :popConfirm="i.popConfirm"
<a-button :tooltip="{
:disabled="i.disabled" ...i.tooltip,
style="padding: 0" }"
type="link" style="padding: 0px"
><AIcon :type="i.icon" @click="i.onClick"
/></a-button>
</a-popconfirm>
<a-button
style="padding: 0"
type="link" type="link"
v-else :hasPermission="'Northbound/DuerOS:' + i.key"
@click="i.onClick && i.onClick(slotProps)"
> >
<a-button <template #icon><AIcon :type="i.icon" /></template>
:disabled="i.disabled" </PermissionButton>
style="padding: 0" </template>
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip>
</a-space> </a-space>
</template> </template>
</JTable> </JTable>
@ -143,17 +119,24 @@
</template> </template>
<script setup lang="ts"> <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 type { ActionsType } from '@/components/Table/index.vue';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useMenuStore } from 'store/menu' import { useMenuStore } from 'store/menu';
const router = useRouter(); const router = useRouter();
const instanceRef = ref<Record<string, any>>({}); const instanceRef = ref<Record<string, any>>({});
const params = ref<Record<string, any>>({}); const params = ref<Record<string, any>>({});
const current = ref<Record<string, any>>({}); const current = ref<Record<string, any>>({});
const menuStory = useMenuStore() const menuStory = useMenuStore();
const statusMap = new Map(); const statusMap = new Map();
statusMap.set('enabled', 'success'); statusMap.set('enabled', 'success');
@ -238,14 +221,14 @@ const columns = [
* 新增 * 新增
*/ */
const handleAdd = () => { const handleAdd = () => {
menuStory.jumpPage('Northbound/DuerOS/Detail', { id: ':id'}) menuStory.jumpPage('Northbound/DuerOS/Detail', { id: ':id' });
}; };
/** /**
* 查看 * 查看
*/ */
const handleView = (id: string) => { const handleView = (id: string) => {
menuStory.jumpPage('Northbound/DuerOS/Detail', { id }, { type: 'view' }) menuStory.jumpPage('Northbound/DuerOS/Detail', { id }, { type: 'view' });
}; };
const getActions = ( const getActions = (
@ -266,14 +249,18 @@ const getActions = (
}, },
}, },
{ {
key: 'edit', key: 'update',
text: '编辑', text: '编辑',
tooltip: { tooltip: {
title: '编辑', title: '编辑',
}, },
icon: 'EditOutlined', icon: 'EditOutlined',
onClick: () => { 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' ? '禁用' : '启用', title: data.state?.value !== 'disabled' ? '禁用' : '启用',
}, },
icon: icon:
data.state.value !== 'notActive' data.state.value !== 'disabled'
? 'StopOutlined' ? 'StopOutlined'
: 'CheckCircleOutlined', : 'CheckCircleOutlined',
popConfirm: { popConfirm: {

View File

@ -1,90 +1,153 @@
<template> <template>
<div style="margin-top: 20px" v-if="config.length"> <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> <div style="font-size: 16px; font-weight: 700">配置</div>
<a-space> <a-space>
<a-button type="link" @click="visible = true"><AIcon type="EditOutlined" />编辑</a-button> <PermissionButton
<a-popconfirm title="确认重新应用该配置?" @confirm="deployBtn"> type="link"
<a-button type="link" v-if="instanceStore.detail.current?.value !== 'notActive'"><AIcon type="CheckOutlined" />应用配置<a-tooltip title="修改配置后需重新应用后才能生效。"><AIcon type="QuestionCircleOutlined" /></a-tooltip></a-button> @click="visible = true"
</a-popconfirm> hasPermission="device/Instance:update"
<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> <template #icon><AIcon type="EditOutlined" /></template>
</a-popconfirm> 编辑
</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> </a-space>
</div> </div>
<a-descriptions bordered size="small" v-for="i in config" :key="i.name"> <a-descriptions bordered size="small" v-for="i in config" :key="i.name">
<template #title><h4 style="font-size: 15px">{{i.name}}</h4></template> <template #title
<a-descriptions-item v-for="item in i.properties" :key="item.property"> ><h4 style="font-size: 15px">{{ i.name }}</h4></template
>
<a-descriptions-item
v-for="item in i.properties"
:key="item.property"
>
<template #label> <template #label>
<span style="margin-right: 5px">{{item.name}}</span> <span style="margin-right: 5px">{{ item.name }}</span>
<a-tooltip v-if="item.description" :title="item.description"><AIcon type="QuestionCircleOutlined" /></a-tooltip> <a-tooltip v-if="item.description" :title="item.description"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
</template> </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 v-else>
<span>{{ instanceStore.current?.configuration?.[item.property] || '' }}</span> <span>{{
<a-tooltip v-if="isExit(item.property)" :title="`有效值:${instanceStore.current?.configuration?.[item.property]}`"><AIcon type="QuestionCircleOutlined" /></a-tooltip> 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> </span>
</a-descriptions-item> </a-descriptions-item>
</a-descriptions> </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> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useInstanceStore } from "@/store/instance" import { useInstanceStore } from '@/store/instance';
import { ConfigMetadata } from "@/views/device/Product/typings" import { ConfigMetadata } from '@/views/device/Product/typings';
import { getConfigMetadata, _deploy, configurationReset } from '@/api/device/instance' import {
import { message } from "ant-design-vue" getConfigMetadata,
import Save from './Save.vue' _deploy,
configurationReset,
} from '@/api/device/instance';
import { message } from 'ant-design-vue';
import Save from './Save.vue';
const instanceStore = useInstanceStore() const instanceStore = useInstanceStore();
const visible = ref<boolean>(false) const visible = ref<boolean>(false);
const config = ref<ConfigMetadata[]>([]) const config = ref<ConfigMetadata[]>([]);
watchEffect(() => { watchEffect(() => {
if(instanceStore.current.id){ if (instanceStore.current.id) {
getConfigMetadata(instanceStore.current.id).then(resp => { getConfigMetadata(instanceStore.current.id).then((resp) => {
if(resp.status === 200){ if (resp.status === 200) {
config.value = resp?.result as ConfigMetadata[] config.value = resp?.result as ConfigMetadata[];
} }
}) });
} }
}) });
const isExit = (property: string) => { const isExit = (property: string) => {
return ( return (
instanceStore.current?.cachedConfiguration && instanceStore.current?.cachedConfiguration &&
instanceStore.current?.cachedConfiguration[property] !== undefined && instanceStore.current?.cachedConfiguration[property] !== undefined &&
instanceStore.current?.configuration && instanceStore.current?.configuration &&
instanceStore.current?.configuration[property] !== instanceStore.current?.configuration[property] !==
instanceStore.current?.cachedConfiguration[property] instanceStore.current?.cachedConfiguration[property]
); );
} };
const deployBtn = async () => { const deployBtn = async () => {
if(instanceStore.current.id){ if (instanceStore.current.id) {
const resp = await _deploy(instanceStore.current.id) const resp = await _deploy(instanceStore.current.id);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功') message.success('操作成功');
instanceStore.refresh(instanceStore.current.id) instanceStore.refresh(instanceStore.current.id);
} }
} }
} };
const resetBtn = async () => { const resetBtn = async () => {
if(instanceStore.current.id){ if (instanceStore.current.id) {
const resp = await configurationReset(instanceStore.current.id) const resp = await configurationReset(instanceStore.current.id);
if (resp.status === 200) { if (resp.status === 200) {
message.success('恢复默认配置成功') message.success('恢复默认配置成功');
instanceStore.refresh(instanceStore.current.id) instanceStore.refresh(instanceStore.current.id);
} }
} }
} };
const saveBtn = () => { const saveBtn = () => {
visible.value = false visible.value = false;
if(instanceStore.current.id){ if (instanceStore.current.id) {
instanceStore.refresh(instanceStore.current.id) instanceStore.refresh(instanceStore.current.id);
} }
} };
</script> </script>

View File

@ -3,31 +3,50 @@
<a-descriptions bordered> <a-descriptions bordered>
<template #title> <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> </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> </a-descriptions>
<Save v-if="visible" @save="saveBtn" @close="visible = false" /> <Save v-if="visible" @save="saveBtn" @close="visible = false" />
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useInstanceStore } from "@/store/instance" import { useInstanceStore } from '@/store/instance';
import Save from './Save.vue' import Save from './Save.vue';
const instanceStore = useInstanceStore() const instanceStore = useInstanceStore();
const dataSource = ref<Record<any, any>[]>([]) const dataSource = ref<Record<any, any>[]>([]);
const visible = ref<boolean>(false); const visible = ref<boolean>(false);
watchEffect(() => { watchEffect(() => {
const arr = (instanceStore.current?.relations || []).reverse() const arr = (instanceStore.current?.relations || []).reverse();
dataSource.value = arr as Record<any, any>[] dataSource.value = arr as Record<any, any>[];
}) });
const saveBtn = () => { const saveBtn = () => {
visible.value = false visible.value = false;
if(instanceStore.current.id){ if (instanceStore.current.id) {
instanceStore.refresh(instanceStore.current.id) instanceStore.refresh(instanceStore.current.id);
} }
} };
</script> </script>

View File

@ -3,32 +3,44 @@
<a-descriptions bordered> <a-descriptions bordered>
<template #title> <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> </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> </a-descriptions>
<Save v-if="visible" @close="visible = false" @save="saveBtn" /> <Save v-if="visible" @close="visible = false" @save="saveBtn" />
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useInstanceStore } from "@/store/instance" import { useInstanceStore } from '@/store/instance';
import Save from './Save.vue' import Save from './Save.vue';
const instanceStore = useInstanceStore() const instanceStore = useInstanceStore();
const dataSource = ref<Record<any, any>[]>([]) const dataSource = ref<Record<any, any>[]>([]);
const visible = ref<boolean>(false) const visible = ref<boolean>(false);
watchEffect(() => { watchEffect(() => {
const arr = (instanceStore.current?.tags || []) const arr = instanceStore.current?.tags || [];
dataSource.value = arr as Record<any, any>[] dataSource.value = arr as Record<any, any>[];
}) });
const saveBtn = () => { const saveBtn = () => {
visible.value = false visible.value = false;
if(instanceStore.current.id){ if (instanceStore.current.id) {
instanceStore.refresh(instanceStore.current.id) instanceStore.refresh(instanceStore.current.id);
} }
} };
</script> </script>

View File

@ -3,43 +3,105 @@
<a-descriptions bordered> <a-descriptions bordered>
<template #title> <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> </template>
<a-descriptions-item label="设备ID">{{ instanceStore.current.id }}</a-descriptions-item> <a-descriptions-item label="设备ID">{{
<a-descriptions-item label="产品名称">{{ instanceStore.current.productName }}</a-descriptions-item> instanceStore.current.id
<a-descriptions-item label="产品分类">{{ instanceStore.current.classifiedName }}</a-descriptions-item> }}</a-descriptions-item>
<a-descriptions-item label="设备类型">{{ instanceStore.current.deviceType?.text }}</a-descriptions-item> <a-descriptions-item label="产品名称">{{
<a-descriptions-item label="固件版本">{{ instanceStore.current.firmwareInfo?.version }}</a-descriptions-item> instanceStore.current.productName
<a-descriptions-item label="连接协议">{{ instanceStore.current.protocolName }}</a-descriptions-item> }}</a-descriptions-item>
<a-descriptions-item label="消息协议">{{ instanceStore.current.transport }}</a-descriptions-item> <a-descriptions-item label="产品分类">{{
<a-descriptions-item label="创建时间">{{ instanceStore.current.createTime ? moment(instanceStore.current.createTime).format('YYYY-MM-DD HH:mm:ss') : '' }}</a-descriptions-item> instanceStore.current.classifiedName
<a-descriptions-item label="注册时间">{{ instanceStore.current.registerTime ? moment(instanceStore.current.registerTime).format('YYYY-MM-DD HH:mm:ss') : ''}}</a-descriptions-item> }}</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="设备类型">{{
<a-descriptions-item label="父设备" v-if="instanceStore.current.deviceType?.value === 'childrenDevice'">{{ instanceStore.current.parentId }}</a-descriptions-item> instanceStore.current.deviceType?.text
<a-descriptions-item label="说明">{{ instanceStore.current.description }}</a-descriptions-item> }}</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> </a-descriptions>
<Config /> <Config />
<Tags v-if="instanceStore.current?.tags && instanceStore.current?.tags.length > 0 " /> <Tags
<Relation v-if="instanceStore.current?.relations && instanceStore.current?.relations.length > 0" /> v-if="
<Save v-if="visible" :data="instanceStore.current" @close="visible = false" @save="saveBtn" /> 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> </a-card>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useInstanceStore } from '@/store/instance' import { useInstanceStore } from '@/store/instance';
import Save from '../../Save/index.vue' import Save from '../../Save/index.vue';
import Config from './components/Config/index.vue' import Config from './components/Config/index.vue';
import Tags from './components/Tags/index.vue' import Tags from './components/Tags/index.vue';
import Relation from './components/Relation/index.vue' import Relation from './components/Relation/index.vue';
import moment from 'moment' import moment from 'moment';
const visible = ref<boolean>(false) const visible = ref<boolean>(false);
const instanceStore = useInstanceStore() const instanceStore = useInstanceStore();
const saveBtn = () => { const saveBtn = () => {
if(instanceStore.current?.id){ if (instanceStore.current?.id) {
instanceStore.refresh(instanceStore.current?.id) instanceStore.refresh(instanceStore.current?.id);
} }
visible.value = false visible.value = false;
} };
</script> </script>

View File

@ -8,7 +8,8 @@
<template #title> <template #title>
<div> <div>
<div style="display: flex; align-items: center"> <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-divider type="vertical" />
<a-space> <a-space>
<a-badge <a-badge
@ -19,25 +20,35 @@
) )
" "
/> />
<a-popconfirm <PermissionButton
title="确认启用设备"
@confirm="handleAction"
v-if=" v-if="
instanceStore.current.state?.value === instanceStore.current.state?.value ===
'notActive' '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> </PermissionButton>
<a-popconfirm <PermissionButton
title="确认断开连接"
@confirm="handleDisconnect"
v-if=" v-if="
instanceStore.current.state?.value === 'online' 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 <a-tooltip
v-if=" v-if="
instanceStore.current?.accessProvider === instanceStore.current?.accessProvider ===
@ -66,14 +77,14 @@
instanceStore.current.id instanceStore.current.id
}}</a-descriptions-item> }}</a-descriptions-item>
<a-descriptions-item label="所属产品"> <a-descriptions-item label="所属产品">
<a-button <PermissionButton
style="margin-top: -5px; padding: 0"
type="link" type="link"
style="margin-top: -5px; padding: 0"
@click="jumpProduct" @click="jumpProduct"
>{{ hasPermission="device/Product:view"
instanceStore.current.productName
}}</a-button
> >
{{ instanceStore.current.productName }}
</PermissionButton>
</a-descriptions-item> </a-descriptions-item>
</a-descriptions> </a-descriptions>
</div> </div>
@ -109,6 +120,9 @@ import { _deploy, _disconnect } from '@/api/device/instance';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
import { getWebSocket } from '@/utils/websocket'; import { getWebSocket } from '@/utils/websocket';
import { useMenuStore } from '@/store/menu';
const menuStory = useMenuStore();
const route = useRoute(); const route = useRoute();
const instanceStore = useInstanceStore(); const instanceStore = useInstanceStore();
@ -180,7 +194,9 @@ watch(
{ immediate: true, deep: true }, { immediate: true, deep: true },
); );
const onBack = () => {}; const onBack = () => {
menuStory.jumpPage('device/Instance');
};
const onTabChange = (e: string) => { const onTabChange = (e: string) => {
instanceStore.tabActiveKey = e; instanceStore.tabActiveKey = e;
@ -214,12 +230,18 @@ const handleRefresh = async () => {
}; };
const jumpProduct = () => { const jumpProduct = () => {
message.warn('暂未开发'); menuStory.jumpPage('device/Product/Detail', {
id: instanceStore.current.productId,
});
}; };
watchEffect(() => { watchEffect(() => {
const keys = list.value.map((i) => i.key); 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({ list.value.push({
key: 'Diagnose', key: 'Diagnose',
tab: '设备诊断', tab: '设备诊断',

View File

@ -19,7 +19,14 @@
> >
<template #headerTitle> <template #headerTitle>
<a-space> <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-dropdown>
<a-button <a-button
>批量操作 <AIcon type="DownOutlined" >批量操作 <AIcon type="DownOutlined"
@ -27,77 +34,101 @@
<template #overlay> <template #overlay>
<a-menu> <a-menu>
<a-menu-item> <a-menu-item>
<a-button @click="exportVisible = true" <PermissionButton
><AIcon @click="exportVisible = true"
type="ExportOutlined" hasPermission="device/Instance:export"
/></a-button
> >
<template #icon
><AIcon type="ExportOutlined"
/></template>
批量导出设备
</PermissionButton>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item>
<a-button @click="importVisible = true" <PermissionButton
><AIcon @click="importVisible = true"
type="ImportOutlined" hasPermission="device/Instance:import"
/></a-button
> >
<template #icon
><AIcon type="ImportOutlined"
/></template>
批量导入设备
</PermissionButton>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item>
<a-popconfirm <PermissionButton
@confirm="activeAllDevice" ghost
title="确认激活全部设备?"
>
<a-button type="primary" ghost
><AIcon
type="CheckCircleOutlined"
/></a-button
>
</a-popconfirm>
</a-menu-item>
<a-menu-item>
<a-button
@click="syncDeviceStatus"
type="primary" type="primary"
><AIcon :popConfirm="{
type="SyncOutlined" title: '确认激活全部设备?',
/></a-button 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>
<a-menu-item v-if="_selectedRowKeys.length"> <a-menu-item v-if="_selectedRowKeys.length">
<a-popconfirm <PermissionButton
@confirm="delSelectedDevice" type="primary"
title="已启用的设备无法删除,确认删除选中的禁用状态设备?" danger
:popConfirm="{
title: '已启用的设备无法删除,确认删除选中的禁用状态设备?',
onConfirm: delSelectedDevice,
}"
hasPermission="device/Instance:delete"
> >
<a-button type="primary" danger <template #icon
><AIcon ><AIcon type="DeleteOutlined"
type="DeleteOutlined" /></template>
/></a-button 删除选中设备
> </PermissionButton>
</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>
</a-menu-item> </a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length"> <a-menu-item v-if="_selectedRowKeys.length">
<a-popconfirm <PermissionButton
@confirm="disabledSelectedDevice" type="primary"
title="确认禁用选中设备?" :popConfirm="{
title: '确认激活选中设备',
onConfirm: activeSelectedDevice,
}"
hasPermission="device/Instance:action"
> >
<a-button type="primary" danger <template #icon
><AIcon ><AIcon type="CheckOutlined"
type="StopOutlined" /></template>
/></a-button 激活选中设备
> </PermissionButton>
</a-popconfirm> </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-item>
</a-menu> </a-menu>
</template> </template>
@ -151,42 +182,24 @@
</a-row> </a-row>
</template> </template>
<template #actions="item"> <template #actions="item">
<a-tooltip <PermissionButton
v-bind="item.tooltip" :disabled="item.disabled"
:title="item.disabled && item.tooltip.title" :popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="'device/Instance:' + item.key"
> >
<a-popconfirm <AIcon
v-if="item.popConfirm" type="DeleteOutlined"
v-bind="item.popConfirm" v-if="item.key === 'delete'"
: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>
<template v-else> <template v-else>
<a-button <AIcon :type="item.icon" />
:disabled="item.disabled" <span>{{ item?.text }}</span>
@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>
</template> </template>
</a-tooltip> </PermissionButton>
</template> </template>
</CardBox> </CardBox>
</template> </template>
@ -197,38 +210,25 @@
/> />
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
<a-space :size="16"> <a-space>
<a-tooltip <template
v-for="i in getActions(slotProps, 'table')" v-for="i in getActions(slotProps, 'table')"
:key="i.key" :key="i.key"
v-bind="i.tooltip"
> >
<a-popconfirm <PermissionButton
v-if="i.popConfirm"
v-bind="i.popConfirm"
:disabled="i.disabled" :disabled="i.disabled"
> :popConfirm="i.popConfirm"
<a-button :tooltip="{
:disabled="i.disabled" ...i.tooltip,
style="padding: 0" }"
type="link" @click="i.onClick"
><AIcon :type="i.icon"
/></a-button>
</a-popconfirm>
<a-button
style="padding: 0"
type="link" type="link"
v-else style="padding: 0px"
@click="i.onClick && i.onClick(slotProps)" :hasPermission="'device/Instance:' + i.key"
> >
<a-button <template #icon><AIcon :type="i.icon" /></template>
:disabled="i.disabled" </PermissionButton>
style="padding: 0" </template>
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip>
</a-space> </a-space>
</template> </template>
</JTable> </JTable>
@ -278,6 +278,7 @@ import {
queryOrgThree, queryOrgThree,
} from '@/api/device/product'; } from '@/api/device/product';
import { queryTree } from '@/api/device/category'; import { queryTree } from '@/api/device/category';
import { useMenuStore } from '@/store/menu';
const router = useRouter(); const router = useRouter();
const instanceRef = ref<Record<string, any>>({}); const instanceRef = ref<Record<string, any>>({});
@ -291,6 +292,8 @@ const operationVisible = ref<boolean>(false);
const api = ref<string>(''); const api = ref<string>('');
const type = ref<string>(''); const type = ref<string>('');
const menuStory = useMenuStore()
const statusMap = new Map(); const statusMap = new Map();
statusMap.set('online', 'success'); statusMap.set('online', 'success');
statusMap.set('offline', 'error'); statusMap.set('offline', 'error');
@ -535,7 +538,7 @@ const handleAdd = () => {
* 查看 * 查看
*/ */
const handleView = (id: string) => { const handleView = (id: string) => {
router.push('/iot/device/instance/detail/' + id); menuStory.jumpPage('device/Instance/Detail', {id})
}; };
const getActions = ( const getActions = (
@ -556,7 +559,7 @@ const getActions = (
}, },
}, },
{ {
key: 'edit', key: 'update',
text: '编辑', text: '编辑',
tooltip: { tooltip: {
title: '编辑', title: '编辑',