Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
421788b2d6
|
@ -1,3 +1,31 @@
|
|||
import server from '@/utils/request'
|
||||
|
||||
export const getSsoBinds_api = (): any =>server.get(`/application/sso/me/bindings`)
|
||||
|
||||
// 获取登录用户信息
|
||||
export const getMeInfo_api = () => server.get(`/user/detail`);
|
||||
// 修改登录用户信息
|
||||
export const updateMeInfo_api = (data:object) => server.put(`/user/detail`,data);
|
||||
// 修改登录用户密码
|
||||
export const updateMepsd_api = (data:object) => server.put(`/user/passwd`,data);
|
||||
// 第三方账号解绑
|
||||
export const unBind_api = (appId: string) => server.post(`/application/sso/${appId}/unbind/me`);
|
||||
/**
|
||||
* 校验字段合法性
|
||||
* @param type 类型
|
||||
* @param name 值
|
||||
*/
|
||||
export const validateField_api = (type: 'username' | 'password', name: string) => server.post(`/user/${type}/_validate`,name,{
|
||||
headers: {
|
||||
'Content-Type': 'text/plain'
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 校验旧密码是否正确
|
||||
* @param password 旧密码
|
||||
*/
|
||||
export const checkOldPassword_api = (password:string) => server.post(`/user/me/password/_validate`,password,{
|
||||
headers: {
|
||||
'Content-Type': 'text/plain'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -85,6 +85,7 @@ export const batchDeleteDevice = (data: string[]) => server.put(`/device-instanc
|
|||
*/
|
||||
export const deviceTemplateDownload = (productId: string, type: string) => `${BASE_API_PATH}/device-instance/${productId}/template.${type}`
|
||||
|
||||
export const templateDownload = (productId: string, type: string) => server.get(`/device-instance/${productId}/template.${type}`,{},{responseType: 'blob'})
|
||||
/**
|
||||
* 设备导入
|
||||
* @param productId 产品id
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { OperatorItem } from '@/components/FRuleEditor/Operator/typings'
|
||||
import server from '@/utils/request'
|
||||
import { DeviceMetadata, ProductItem, DepartmentItem } from '@/views/device/Product/typings'
|
||||
import { DeviceMetadata, ProductItem, DepartmentItem, MetadataType } from '@/views/device/Product/typings'
|
||||
|
||||
/**
|
||||
* 根据条件查询产品(不带翻页)
|
||||
|
|
|
@ -99,6 +99,12 @@ export const _import = (configId: any, params: any) => server.get(`/network/card
|
|||
*/
|
||||
export const _export = (format: string, data: any) => server.post(`/network/card/download.${format}/_query`, data, { responseType: 'blob' });
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
* @param format 类型 xlsx、csv
|
||||
*/
|
||||
export const exportCard = (format: string) => server.get(`/network/card/template.${format}`,{},{responseType: 'blob'});
|
||||
|
||||
/**
|
||||
* 验证iccid
|
||||
* @param id
|
||||
|
|
|
@ -3,15 +3,13 @@ import { BASE_API_PATH } from '@/utils/variable';
|
|||
|
||||
export const PROTOCOL_UPLOAD = `${BASE_API_PATH}/file/upload`;
|
||||
|
||||
export const detail = (id: string) => server.get(`/gateway/device/${id}`);
|
||||
export const save = (data: Object) => server.post(`/protocol`, data);
|
||||
|
||||
export const save = (data: Object) => server.post(`/gateway/device`, data);
|
||||
|
||||
export const update = (data: Object) => server.patch(`/gateway/device`, data);
|
||||
export const update = (data: Object) => server.patch(`/protocol`, data);
|
||||
|
||||
export const list = (data: Object) => server.post(`/protocol/_query`, data);
|
||||
|
||||
export const remove = (id: string) => server.remove(`/gateway/device/${id}`);
|
||||
export const remove = (id: string) => server.remove(`/protocol/${id}`);
|
||||
|
||||
export const querySystemApi = (data: Object) =>
|
||||
server.post(`/system/config/scopes`, data);
|
||||
|
|
|
@ -33,8 +33,10 @@ export default {
|
|||
// 验证国标ID是否存在
|
||||
validateField: (id: string, data: string[]): any => server.post(`/media/gb28181-cascade/${id}/gbChannelId/_validate`, data),
|
||||
// 更改国标ID
|
||||
updateGbChannelId: (id: string, data: any): any => server.post(`/media/gb28181-cascade/binding/${id}`, data),
|
||||
updateGbChannelId: (id: string, data: any): any => server.put(`/media/gb28181-cascade/binding/${id}`, data),
|
||||
// 查询通道分页列表
|
||||
queryChannelList: (data: any): any => server.post(`media/channel/_query`, data),
|
||||
// 推送
|
||||
publish: (id: string, params: any) => server.get(`/media/gb28181-cascade/${id}/bindings/publish`, params)
|
||||
|
||||
}
|
|
@ -23,4 +23,19 @@ export const query = (data:any) => server.post('/alarm/record/_query/',data);
|
|||
/**
|
||||
* 告警处理
|
||||
*/
|
||||
export const handleLog = (data:any) => server.post('/alarm/record/_handle',data)
|
||||
export const handleLog = (data:any) => server.post('/alarm/record/_handle',data);
|
||||
|
||||
/**
|
||||
* 告警记录
|
||||
*/
|
||||
export const detail = (id:string) => server.get(`/alarm/record/${id}`);
|
||||
|
||||
/**
|
||||
* 告警历史记录
|
||||
*/
|
||||
export const queryHistoryList = (data:any) => server.post('/alarm/history/_query',data);
|
||||
|
||||
/**
|
||||
* 获取告警处理结果
|
||||
*/
|
||||
export const queryHandleHistory = (data:any) => server.post('/alarm/record/handle-history/_query',data);
|
|
@ -63,7 +63,7 @@ const iconKeys = [
|
|||
'HistoryOutlined',
|
||||
'ToolOutlined',
|
||||
'FileOutlined',
|
||||
'LikeOutlined'
|
||||
'LikeOutlined',
|
||||
]
|
||||
|
||||
const Icon = (props: {type: string}) => {
|
||||
|
|
|
@ -74,6 +74,10 @@ watchEffect(() => {
|
|||
}, 300);
|
||||
});
|
||||
|
||||
/**
|
||||
* 光标位置插入内容
|
||||
* @param {String} val
|
||||
*/
|
||||
const insert = (val) => {
|
||||
if (!instance) return;
|
||||
const position = instance.getPosition();
|
||||
|
@ -90,12 +94,18 @@ const insert = (val) => {
|
|||
]);
|
||||
};
|
||||
|
||||
// watch(
|
||||
// () => props.modelValue,
|
||||
// (val) => {
|
||||
// instance.setValue(val);
|
||||
// },
|
||||
// );
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (!instance) return;
|
||||
// setValue之前获取光标位置
|
||||
const position = instance.getPosition();
|
||||
// setValue之后光标位置改变
|
||||
instance.setValue(val);
|
||||
// 设置光标位置为setValue之前的位置
|
||||
instance.setPosition(position);
|
||||
},
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
editorFormat,
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
import { FILE_UPLOAD } from '@/api/comm'
|
||||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { downloadFile } from '@/utils/utils';
|
||||
import { deviceImport, deviceTemplateDownload } from '@/api/device/instance'
|
||||
import { downloadFile, downloadFileByUrl } from '@/utils/utils';
|
||||
import { deviceImport, deviceTemplateDownload ,templateDownload} from '@/api/device/instance'
|
||||
import { EventSourcePolyfill } from 'event-source-polyfill'
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
|
@ -72,8 +72,20 @@ const flag = ref<boolean>(false)
|
|||
const count = ref<number>(0)
|
||||
const errMessage = ref<string>('')
|
||||
|
||||
const downFile = (type: string) => {
|
||||
downloadFile(deviceTemplateDownload(props.product, type));
|
||||
const downFile =async (type: string) => {
|
||||
// downloadFile(deviceTemplateDownload(props.product, type));
|
||||
const res:any =await templateDownload(props.product, type)
|
||||
if(res){
|
||||
const blob = new Blob([res], { type: type });
|
||||
const url = URL.createObjectURL(blob);
|
||||
console.log(url);
|
||||
downloadFileByUrl(
|
||||
url,
|
||||
`设备导入模版`,
|
||||
type,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const submitData = async (fileUrl: string) => {
|
||||
|
|
|
@ -144,7 +144,7 @@ const columns = [
|
|||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
// width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '请求方法',
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<a-modal
|
||||
visible
|
||||
title="编辑"
|
||||
@ok="handleOk"
|
||||
width="770px"
|
||||
@cancel="emits('update:visible', false)"
|
||||
>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
label="姓名"
|
||||
:rules="[{ required: true, message: '姓名必填' }]"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
placeholder="请输入姓名"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="用户名">
|
||||
<a-input
|
||||
v-model:value="form.username"
|
||||
placeholder="请输入用户名"
|
||||
disabled
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="角色">
|
||||
<a-input
|
||||
:value="
|
||||
form.roleList.map((item) => item.name).join(',')
|
||||
"
|
||||
placeholder="请输入角色"
|
||||
disabled
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="组织">
|
||||
<a-input
|
||||
:value="
|
||||
form.orgList.map((item) => item.name).join(',')
|
||||
"
|
||||
placeholder="请输入组织"
|
||||
disabled
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="手机号">
|
||||
<a-input
|
||||
v-model:value="form.telephone"
|
||||
placeholder="请输入手机号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="邮箱">
|
||||
<a-input
|
||||
v-model:value="form.email"
|
||||
placeholder="请输入邮箱"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { updateMeInfo_api } from '@/api/account/center';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { userInfoType } from '../typing';
|
||||
|
||||
const emits = defineEmits(['ok', 'update:visible']);
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
data: userInfoType;
|
||||
}>();
|
||||
const form = ref(props.data);
|
||||
|
||||
const handleOk = () => {
|
||||
updateMeInfo_api(form.value).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('保存成功');
|
||||
emits('ok');
|
||||
emits('update:visible', false);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -0,0 +1,138 @@
|
|||
<template>
|
||||
<a-modal
|
||||
visible
|
||||
title="重置密码"
|
||||
@ok="handleOk"
|
||||
width="520px"
|
||||
@cancel="emits('update:visible', false)"
|
||||
>
|
||||
<a-form :model="form" layout="vertical" ref="formRef">
|
||||
<a-form-item
|
||||
label="旧密码"
|
||||
name="oldPassword"
|
||||
:rules="[
|
||||
{ required: true },
|
||||
{ validator: checkMothods.old, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="form.oldPassword"
|
||||
placeholder="请输入旧密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="密码"
|
||||
name="newPassword"
|
||||
:rules="[
|
||||
{ required: true },
|
||||
{ validator: checkMothods.new, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="form.newPassword"
|
||||
placeholder="请输入姓名"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="确认密码"
|
||||
name="confirmPassword"
|
||||
:rules="[
|
||||
{ required: true },
|
||||
{ validator: checkMothods.confirm, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<a-input-password
|
||||
v-model:value="form.confirmPassword"
|
||||
placeholder="请输入姓名"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
updateMepsd_api,
|
||||
checkOldPassword_api,
|
||||
validateField_api,
|
||||
} from '@/api/account/center';
|
||||
import { FormInstance, message } from 'ant-design-vue';
|
||||
import { Rule } from 'ant-design-vue/lib/form';
|
||||
|
||||
const emits = defineEmits(['ok', 'update:visible']);
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
const formRef = ref<FormInstance>();
|
||||
const form = ref<formType>({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
const checkMothods = {
|
||||
old: async (_rule: Rule, value: string) => {
|
||||
if (!value) return Promise.reject('请输入密码');
|
||||
try {
|
||||
const resp: any = await checkOldPassword_api(value);
|
||||
if (resp.status === 200 && !resp.result.passed)
|
||||
return Promise.reject(resp.result.reason);
|
||||
else return Promise.resolve();
|
||||
} catch (error) {
|
||||
return Promise.reject('验证失败');
|
||||
}
|
||||
},
|
||||
new: async (_rule: Rule, value: string) => {
|
||||
if (!value) return Promise.reject('请输入密码');
|
||||
else if (
|
||||
form.value.confirmPassword &&
|
||||
value !== form.value.confirmPassword
|
||||
)
|
||||
return Promise.reject('两次密码输入不一致');
|
||||
try {
|
||||
const resp: any = await validateField_api('password', value);
|
||||
if (resp.status === 200 && !resp.result.passed)
|
||||
return Promise.reject(resp.result.reason);
|
||||
else return Promise.resolve();
|
||||
} catch (error) {
|
||||
return Promise.reject('验证失败');
|
||||
}
|
||||
},
|
||||
confirm: async (_rule: Rule, value: string) => {
|
||||
if (!value) return Promise.reject('请输入确认密码');
|
||||
|
||||
try {
|
||||
const resp: any = await validateField_api('password', value);
|
||||
if (resp.status === 200 && !resp.result.passed)
|
||||
return Promise.reject(resp.result.reason);
|
||||
else return Promise.resolve();
|
||||
} catch (error) {
|
||||
return Promise.reject('验证失败');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
formRef.value?.validate().then(() => {
|
||||
const params = {
|
||||
oldPassword: form.value.oldPassword,
|
||||
newPassword: form.value.newPassword,
|
||||
};
|
||||
// updateMepsd_api(params).then((resp) => {
|
||||
// if (resp.status === 200) {
|
||||
// message.success('保存成功');
|
||||
// emits('ok');
|
||||
// emits('update:visible', false);
|
||||
// }
|
||||
// });
|
||||
});
|
||||
};
|
||||
console.clear();
|
||||
type formType = {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
confirmPassword: string;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -63,11 +63,27 @@
|
|||
</div>
|
||||
<div class="info-card">
|
||||
<p>角色</p>
|
||||
<p>{{ userInfo.roleList.join(',') || '-' }}</p>
|
||||
<p>
|
||||
{{
|
||||
(userInfo.roleList &&
|
||||
userInfo.roleList
|
||||
.map((item) => item.name)
|
||||
.join(',')) ||
|
||||
'-'
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<p>组织</p>
|
||||
<p>{{ userInfo.orgList.join(',') || '-' }}</p>
|
||||
<p>
|
||||
{{
|
||||
(userInfo.orgList &&
|
||||
userInfo.orgList
|
||||
.map((item) => item.name)
|
||||
.join(',')) ||
|
||||
'-'
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="info-card">
|
||||
<p>邮箱</p>
|
||||
|
@ -78,6 +94,7 @@
|
|||
type="EditOutlined"
|
||||
class="edit"
|
||||
style="right: 40px"
|
||||
@click="editInfoVisible = true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,10 +111,19 @@
|
|||
>安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过8位的密码</span
|
||||
>
|
||||
</div>
|
||||
<AIcon type="EditOutlined" class="edit" />
|
||||
<span class="edit">
|
||||
<PermissionButton
|
||||
:uhasPermission="`${permission}:update`"
|
||||
type="link"
|
||||
@click="editPasswordVisible = true"
|
||||
>
|
||||
<AIcon type="EditOutlined" style="color: #1d39c4;" />
|
||||
</PermissionButton>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<!-- 社区版不显示 -->
|
||||
<div class="card" v-if="isNoCommunity">
|
||||
<h3>绑定三方账号</h3>
|
||||
<div class="content">
|
||||
<div class="account-card" v-for="item in bindList">
|
||||
|
@ -106,7 +132,7 @@
|
|||
style="height: 50px"
|
||||
alt=""
|
||||
/>
|
||||
<div class="text">
|
||||
<Ellipsis style="width: 150px; font-size: 22px">
|
||||
<div v-if="item.bound">
|
||||
<div>绑定名:{{ item.others.name }}</div>
|
||||
<div>
|
||||
|
@ -118,30 +144,99 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-else>{{ item.name }}未绑定</div>
|
||||
</div>
|
||||
|
||||
<a-button v-if="item.bound">解除绑定</a-button>
|
||||
<a-button v-else type="primary">立即绑定</a-button>
|
||||
</Ellipsis>
|
||||
<a-popconfirm
|
||||
v-if="item.bound"
|
||||
title="确认解除绑定嘛?"
|
||||
@confirm="() => unBind(item.id)"
|
||||
>
|
||||
<a-button>解除绑定</a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
v-else
|
||||
type="primary"
|
||||
@click="clickBind(item.id)"
|
||||
>立即绑定</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<!-- 第三方用户不显示 -->
|
||||
<div class="card" v-if="!isApiUser">
|
||||
<h3>首页视图</h3>
|
||||
<div class="choose-view">
|
||||
<a-row class="view-content" :gutter="24">
|
||||
<a-col
|
||||
:span="6"
|
||||
class="select-item"
|
||||
:class="{ selected: currentView === 'device' }"
|
||||
@click="currentView = 'device'"
|
||||
>
|
||||
<img :src="getImage('/home/device.png')" alt="" />
|
||||
</a-col>
|
||||
<a-col
|
||||
:span="6"
|
||||
class="select-item"
|
||||
:class="{ selected: currentView === 'ops' }"
|
||||
@click="currentView = 'ops'"
|
||||
>
|
||||
<img :src="getImage('/home/ops.png')" alt="" />
|
||||
</a-col>
|
||||
<a-col
|
||||
:span="6"
|
||||
class="select-item"
|
||||
:class="{
|
||||
selected: currentView === 'comprehensive',
|
||||
}"
|
||||
@click="currentView = 'comprehensive'"
|
||||
>
|
||||
<img
|
||||
:src="getImage('/home/comprehensive.png')"
|
||||
alt=""
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-button type="primary" class="btn" @click="confirm"
|
||||
>确定</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<EditInfoDialog
|
||||
v-if="editInfoVisible"
|
||||
v-model:visible="editInfoVisible"
|
||||
:data="userInfo"
|
||||
@ok="getUserInfo"
|
||||
/>
|
||||
<EditPasswordDialog
|
||||
v-if="editPasswordVisible"
|
||||
v-model:visible="editPasswordVisible"
|
||||
/>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||
import EditInfoDialog from './components/EditInfoDialog.vue';
|
||||
import EditPasswordDialog from './components/EditPasswordDialog.vue';
|
||||
import { LockOutlined } from '@ant-design/icons-vue';
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore, getImage } from '@/utils/comm';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
import { message, UploadChangeParam, UploadFile } from 'ant-design-vue';
|
||||
import { getSsoBinds_api } from '@/api/account/center';
|
||||
import {
|
||||
getMeInfo_api,
|
||||
getSsoBinds_api,
|
||||
unBind_api,
|
||||
} from '@/api/account/center';
|
||||
import moment from 'moment';
|
||||
import { getMe_api, getView_api, setView_api } from '@/api/home';
|
||||
import { isNoCommunity } from '@/utils/utils';
|
||||
import { userInfoType } from './typing';
|
||||
|
||||
const userInfo = useUserInfo().$state.userInfos as any as userInfoType;
|
||||
const permission = 'system/User';
|
||||
const userInfo = ref<userInfoType>({});
|
||||
// 第三方账号
|
||||
const bindList = ref<any[]>([]);
|
||||
const bindIcon = {
|
||||
'dingtalk-ent-app': '/notice/dingtalk.png',
|
||||
|
@ -149,6 +244,24 @@ const bindIcon = {
|
|||
'internal-standalone': '/apply/provider1.png',
|
||||
'third-party': '/apply/provider5.png',
|
||||
};
|
||||
const unBind = (id: string) => {
|
||||
unBind_api(id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('解绑成功');
|
||||
getSsoBinds();
|
||||
}
|
||||
});
|
||||
};
|
||||
const clickBind = (id: string) => {
|
||||
window.open(`/${origin}/application/sso/${id}/login?autoCreateUser=false`);
|
||||
localStorage.setItem('onBind', 'false');
|
||||
localStorage.setItem('onLogin', 'yes');
|
||||
window.onstorage = (e) => {
|
||||
if (e.newValue) {
|
||||
getSsoBinds();
|
||||
}
|
||||
};
|
||||
};
|
||||
const upload = reactive({
|
||||
fileList: [] as any[],
|
||||
uploadLoading: false,
|
||||
|
@ -158,36 +271,74 @@ const upload = reactive({
|
|||
} else if (info.file.status === 'done') {
|
||||
info.file.url = info.file.response?.result;
|
||||
upload.uploadLoading = false;
|
||||
userInfo.avatar = info.file.response?.result;
|
||||
userInfo.value.avatar = info.file.response?.result;
|
||||
} else if (info.file.status === 'error') {
|
||||
console.log(info.file);
|
||||
upload.uploadLoading = false;
|
||||
message.error('logo上传失败,请稍后再试');
|
||||
}
|
||||
},
|
||||
});
|
||||
// 首页视图
|
||||
const isApiUser = ref<boolean>();
|
||||
const currentView = ref<string>('');
|
||||
const confirm = () => {
|
||||
setView_api({
|
||||
name: 'view',
|
||||
content: currentView.value,
|
||||
}).then(() => message.success('保存成功'));
|
||||
};
|
||||
|
||||
const editInfoVisible = ref<boolean>(false);
|
||||
const editPasswordVisible = ref<boolean>(false);
|
||||
init();
|
||||
|
||||
function init() {
|
||||
getUserInfo();
|
||||
isNoCommunity && getSsoBinds();
|
||||
getViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
function getUserInfo() {
|
||||
getMeInfo_api().then((resp) => {
|
||||
userInfo.value = resp.result as userInfoType;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取绑定第三方账号
|
||||
*/
|
||||
function getSsoBinds() {
|
||||
getSsoBinds_api().then((resp: any) => {
|
||||
if (resp.status === 200) bindList.value = resp.result;
|
||||
});
|
||||
}
|
||||
|
||||
type userInfoType = {
|
||||
avatar: string;
|
||||
createTime: number;
|
||||
email: string;
|
||||
id: string;
|
||||
name: string;
|
||||
orgList: string[];
|
||||
roleList: string[];
|
||||
status: number;
|
||||
telephone: string;
|
||||
tenantDisabled: boolean;
|
||||
type: { name: string; id: string };
|
||||
username: string;
|
||||
};
|
||||
/**
|
||||
* 获取首页视图
|
||||
*/
|
||||
function getViews() {
|
||||
// 判断是否是api用户 不是则获取选中的视图
|
||||
getMe_api()
|
||||
.then((resp: any) => {
|
||||
if (resp && resp.status === 200) {
|
||||
isApiUser.value = resp.result.dimensions.find(
|
||||
(item: any) =>
|
||||
item.type === 'api-client' ||
|
||||
item.type.id === 'api-client',
|
||||
);
|
||||
if (!isApiUser.value) return getView_api();
|
||||
}
|
||||
})
|
||||
.then((resp: any) => {
|
||||
if (resp?.status === 200) {
|
||||
if (resp.result) currentView.value = resp.result?.content;
|
||||
else if (resp.result.username === 'admin') {
|
||||
currentView.value = 'comprehensive';
|
||||
} else currentView.value = 'init';
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@ -216,6 +367,7 @@ type userInfoType = {
|
|||
.content {
|
||||
display: flex;
|
||||
margin-top: 24px;
|
||||
flex-wrap: wrap;
|
||||
.content-item {
|
||||
margin-right: 24px;
|
||||
.info-card {
|
||||
|
@ -250,16 +402,32 @@ type userInfoType = {
|
|||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
display: -webkit-box;
|
||||
font-size: 22px;
|
||||
width: 150px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
.choose-view {
|
||||
width: 100%;
|
||||
margin-top: 48px;
|
||||
.view-content {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
.select-item {
|
||||
border: 2px solid transparent;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-color: #10239e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: block;
|
||||
margin: 48px auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
import { dictType } from '@/views/system/Department/typing';
|
||||
|
||||
export type userInfoType = {
|
||||
avatar: string;
|
||||
createTime: number;
|
||||
email: string;
|
||||
id: string;
|
||||
name: string;
|
||||
orgList: dictType;
|
||||
roleList: dictType;
|
||||
status: number;
|
||||
telephone: string;
|
||||
tenantDisabled: boolean;
|
||||
type: { name: string; id: string };
|
||||
username: string;
|
||||
};
|
|
@ -17,19 +17,21 @@
|
|||
</div>
|
||||
|
||||
<div class="state-title-right">
|
||||
<div>
|
||||
<a-popconfirm
|
||||
title="确定批量重试?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="confirm"
|
||||
<div class="state-button">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
v-if="
|
||||
item.key === 'failed' &&
|
||||
stateInfo?.mode?.value === 'push'
|
||||
"
|
||||
hasPermission="device/Firmware:update"
|
||||
:popConfirm="{
|
||||
title: `确定批量重试`,
|
||||
onConfirm: confirm,
|
||||
}"
|
||||
>
|
||||
<a href="#">批量重试</a>
|
||||
</a-popconfirm>
|
||||
批量重试
|
||||
</PermissionButton>
|
||||
</div>
|
||||
|
||||
<div class="img">
|
||||
|
@ -85,37 +87,27 @@
|
|||
<span>{{ slotProps.progress }}%</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
style="padding: 0px"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
:hasPermission="'device/Firmware:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -129,7 +121,6 @@ import {
|
|||
taskById,
|
||||
history,
|
||||
historyCount,
|
||||
queryProduct,
|
||||
startTask,
|
||||
startOneTask,
|
||||
} from '@/api/device/firmware';
|
||||
|
@ -138,8 +129,8 @@ import { getImage } from '@/utils/comm';
|
|||
import moment from 'moment';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import Save from './Save.vue';
|
||||
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const params = ref<Record<string, any>>({});
|
||||
const taskId = route.params?.id as string;
|
||||
|
@ -286,7 +277,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
}
|
||||
const Actions = [
|
||||
{
|
||||
key: 'eye',
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
|
@ -297,25 +288,23 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'try',
|
||||
key: 'update',
|
||||
text: '重试',
|
||||
tooltip: {
|
||||
title: '重试',
|
||||
},
|
||||
icon: 'RedoOutlined',
|
||||
onClick: async () => {
|
||||
handlTry(data.id);
|
||||
popConfirm: {
|
||||
title: `确认重试?`,
|
||||
onConfirm: async () => {
|
||||
handlTry(data.id);
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
return Actions;
|
||||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
current.value = {};
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const handlEye = (data: string) => {
|
||||
current.value = data || '';
|
||||
visible.value = true;
|
||||
|
@ -434,4 +423,8 @@ const handleSearch = (e: any) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
.state-button {
|
||||
margin-top: -5px;
|
||||
margin-right: -12px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -13,9 +13,14 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><AIcon type="PlusOutlined" />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="device/Firmware:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #mode="slotProps">
|
||||
<span>{{ slotProps.mode.text }}</span>
|
||||
|
@ -225,7 +230,7 @@ const handlEye = (data: object) => {
|
|||
};
|
||||
|
||||
const handlDetails = (id: string) => {
|
||||
// menuStory.jumpPage('device/Firmware/Task/Detail', { id });
|
||||
menuStory.jumpPage('device/Firmware/Task/Detail', { id });
|
||||
};
|
||||
const saveChange = (value: boolean) => {
|
||||
visible.value = false;
|
||||
|
|
|
@ -13,9 +13,14 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><plus-outlined />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="device/Firmware:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #productId="slotProps">
|
||||
<span>{{ slotProps.productName }}</span>
|
||||
|
@ -28,37 +33,27 @@
|
|||
}}</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
style="padding: 0px"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
:hasPermission="'device/Firmware:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -79,7 +74,6 @@ import type { FormDataType } from './type';
|
|||
const menuStory = useMenuStore();
|
||||
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const productOptions = ref([]);
|
||||
|
@ -174,7 +168,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
}
|
||||
return [
|
||||
{
|
||||
key: 'FileTextOutlined',
|
||||
key: 'view',
|
||||
text: '升级任务',
|
||||
tooltip: {
|
||||
title: '升级任务',
|
||||
|
@ -185,7 +179,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -211,7 +205,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
];
|
||||
};
|
||||
|
||||
const handlUpdate = (data: FormDataType) => {
|
||||
const handlUpdate = (data: Partial<Record<string, any>>) => {
|
||||
menuStory.jumpPage(
|
||||
'device/Firmware/Task',
|
||||
{},
|
||||
|
@ -226,7 +220,7 @@ const handlAdd = () => {
|
|||
current.value = {};
|
||||
visible.value = true;
|
||||
};
|
||||
const handlEdit = (data: FormDataType) => {
|
||||
const handlEdit = (data: Partial<Record<string, any>>) => {
|
||||
current.value = _.cloneDeep(data);
|
||||
visible.value = true;
|
||||
};
|
||||
|
|
|
@ -146,12 +146,6 @@ const rest = async () => {
|
|||
getDeviceCode();
|
||||
message.success('操作成功')
|
||||
}
|
||||
// service.delDeviceCode(productId, deviceId).then((res) => {
|
||||
// if (res.status === 200) {
|
||||
// getDeviceCode(productId, deviceId);
|
||||
// onlyMessage('操作成功');
|
||||
// }
|
||||
// });
|
||||
};
|
||||
//获取topic
|
||||
const getTopic = async () => {
|
||||
|
@ -285,7 +279,7 @@ onMounted(() => {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
background-color: '#f7f7f7';
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.bottom-title {
|
||||
display: flex;
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="Parsing">
|
||||
<script setup lang='ts' name="DataAnalysis">
|
||||
import AIcon from '@/components/AIcon'
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
|
@ -225,7 +225,7 @@ onMounted(() => {
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
background-color: '#f7f7f7';
|
||||
background-color: #f7f7f7;
|
||||
|
||||
.bottom-title {
|
||||
display: flex;
|
||||
|
|
|
@ -205,7 +205,9 @@ const getProtocol = async () => {
|
|||
}
|
||||
}
|
||||
};
|
||||
getProtocol();
|
||||
onMounted(()=>{
|
||||
getProtocol();
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.ant-switch-loading,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<a-button :loading="save.loading" type="primary" @click="save.saveMetadata">保存</a-button>
|
||||
</template>
|
||||
<a-form ref="formRef" :model="form.model" layout="vertical">
|
||||
<BaseForm :model-type="metadataStore.model.type" :type="type" v-model:value="form.model"></BaseForm>
|
||||
<BaseForm :model-type="metadataStore.model.type" :type="type" v-model:value="form.model"></BaseForm>
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
@ -17,11 +17,11 @@ import { ProductItem } from '@/views/device/Product/typings';
|
|||
import { message } from 'ant-design-vue/es';
|
||||
import type { FormInstance } from 'ant-design-vue/es';
|
||||
import { updateMetadata, asyncUpdateMetadata } from '../../metadata'
|
||||
import { Store } from 'jetlinks-store';
|
||||
import { detail } from '@/api/device/instance';
|
||||
import { DeviceInstance } from '@/views/device/Instance/typings';
|
||||
import BaseForm from './BaseForm.vue';
|
||||
import { PropType } from 'vue';
|
||||
import { _deploy } from '@/api/device/product';
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
|
@ -104,10 +104,16 @@ const save = reactive({
|
|||
setTimeout(() => window.close(), 300);
|
||||
}
|
||||
} else {
|
||||
const { id } = route.params
|
||||
if (props?.type === 'device') {
|
||||
instanceStore.refresh(id as string)
|
||||
} else {
|
||||
productStore.refresh(id as string)
|
||||
}
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
|
||||
if (deploy) {
|
||||
// TODO 是否发布
|
||||
Store.set('product-deploy', deploy);
|
||||
_deploy(id as string)
|
||||
// Store.set('product-deploy', deploy);
|
||||
} else {
|
||||
save.resetMetadata();
|
||||
message.success({
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<a-tabs @change="handleConvertMetadata">
|
||||
<a-tab-pane v-for="item in codecs" :key="item.id" :tab="item.name">
|
||||
<div class="cat-panel">
|
||||
<!-- TODO 代码编辑器 -->
|
||||
<MonacoEditor v-model="value" theme="vs" style="height: 100%"></MonacoEditor>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
||||
<!-- TODO代码编辑器 -->
|
||||
<MonacoEditor v-model="formModel.import" theme="vs" style="height: 300px"></MonacoEditor>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -57,8 +56,6 @@ import type { DefaultOptionType } from 'ant-design-vue/es/select';
|
|||
import type { UploadProps, UploadFile, UploadChangeParam } from 'ant-design-vue/es';
|
||||
import type { DeviceMetadata, ProductItem } from '@/views/device/Product/typings'
|
||||
import { message } from 'ant-design-vue/es';
|
||||
import { Store } from 'jetlinks-store';
|
||||
import { SystemConst } from '@/utils/consts';
|
||||
import { useInstanceStore } from '@/store/instance'
|
||||
import { useProductStore } from '@/store/product';
|
||||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
|
@ -139,11 +136,6 @@ const rules = reactive({
|
|||
],
|
||||
})
|
||||
const { validate, validateInfos } = useForm(formModel, rules);
|
||||
const onSubmit = () => {
|
||||
validate().then(() => {
|
||||
|
||||
})
|
||||
}
|
||||
const fileList = ref<UploadFile[]>([])
|
||||
|
||||
const productList = ref<DefaultOptionType[]>([])
|
||||
|
@ -208,11 +200,11 @@ const operateLimits = (mdata: DeviceMetadata) => {
|
|||
const handleImport = async () => {
|
||||
validate().then(async (data) => {
|
||||
loading.value = true
|
||||
const { id } = route.params || {}
|
||||
if (data.metadata === 'alink') {
|
||||
const res = await convertMetadata('from', 'alink', data.import)
|
||||
if (res.status === 200) {
|
||||
const metadata = JSON.stringify(operateLimits(res.result))
|
||||
const { id } = route.params || {}
|
||||
if (props?.type === 'device') {
|
||||
await saveMetadata(id as string, metadata)
|
||||
instanceStore.setCurrent(JSON.parse(metadata || '{}'))
|
||||
|
@ -227,8 +219,13 @@ const handleImport = async () => {
|
|||
loading.value = false
|
||||
message.error('发生错误!')
|
||||
}
|
||||
Store.set(SystemConst.GET_METADATA, true)
|
||||
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
if (props?.type === 'device') {
|
||||
instanceStore.refresh(id as string)
|
||||
} else {
|
||||
productStore.refresh(id as string)
|
||||
}
|
||||
// Store.set(SystemConst.GET_METADATA, true)
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
close()
|
||||
} else {
|
||||
try {
|
||||
|
@ -255,21 +252,24 @@ const handleImport = async () => {
|
|||
loading.value = false
|
||||
if (resp.status === 200) {
|
||||
if (props?.type === 'device') {
|
||||
const metadata: DeviceMetadata = JSON.parse(paramsDevice || '{}')
|
||||
// TODO导入
|
||||
// MetadataAction.insert(metadata);
|
||||
// instanceStore.setCurrent(metadata)
|
||||
const detail = instanceStore.current
|
||||
detail.metadata = paramsDevice
|
||||
instanceStore.setCurrent(detail)
|
||||
message.success('导入成功')
|
||||
} else {
|
||||
const metadata: ProductItem = JSON.parse(params?.metadata || '{}')
|
||||
// TODO导入
|
||||
// MetadataAction.insert(metadata);
|
||||
// productStore.setCurrent(metadata)
|
||||
const detail = productStore.current
|
||||
detail.metadata = params.metadata
|
||||
productStore.setCurrent(detail)
|
||||
message.success('导入成功')
|
||||
}
|
||||
}
|
||||
Store.set(SystemConst.GET_METADATA, true)
|
||||
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
// Store.set(SystemConst.GET_METADATA, true)
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
if (props?.type === 'device') {
|
||||
instanceStore.refresh(id as string)
|
||||
} else {
|
||||
productStore.refresh(id as string)
|
||||
}
|
||||
close();
|
||||
} catch (e) {
|
||||
loading.value = false
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
:tooltip="{ title: '重置后将使用产品的物模型配置' }" key="reload">
|
||||
重置操作
|
||||
</PermissionButton>
|
||||
<PermissionButton :uhasPermission="`${permission}:update`" @click="visible = true">快速导入</PermissionButton>
|
||||
<PermissionButton :uhasPermission="`${permission}:update`" @click="cat = true">物模型TSL</PermissionButton>
|
||||
<PermissionButton :hasPermission="`${permission}:update`" @click="visible = true">快速导入</PermissionButton>
|
||||
<PermissionButton :hasPermission="`${permission}:update`" @click="cat = true">物模型TSL</PermissionButton>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
|
@ -50,7 +50,6 @@
|
|||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
import { deleteMetadata } from '@/api/device/instance.js'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { Store } from 'jetlinks-store'
|
||||
import { SystemConst } from '@/utils/consts'
|
||||
import { useInstanceStore } from '@/store/instance'
|
||||
import Import from './Import/index.vue'
|
||||
|
@ -75,11 +74,11 @@ const resetMetadata = async () => {
|
|||
const resp = await deleteMetadata(id as string)
|
||||
if (resp.status === 200) {
|
||||
message.info('操作成功')
|
||||
|
||||
Store.set(SystemConst.REFRESH_DEVICE, true)
|
||||
setTimeout(() => {
|
||||
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
}, 400)
|
||||
instanceStore.refresh(id as string)
|
||||
// Store.set(SystemConst.REFRESH_DEVICE, true)
|
||||
// setTimeout(() => {
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
// }, 400)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -80,8 +80,8 @@
|
|||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { downloadFile } from '@/utils/utils';
|
||||
import { queryPlatformNoPage, _import } from '@/api/iot-card/cardManagement';
|
||||
import { downloadFile, downloadFileByUrl } from '@/utils/utils';
|
||||
import { queryPlatformNoPage, _import ,exportCard} from '@/api/iot-card/cardManagement';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
@ -136,9 +136,21 @@ const fileChange = (info: any) => {
|
|||
}
|
||||
};
|
||||
|
||||
const downFileFn = (type: string) => {
|
||||
const url = `${BASE_API_PATH}/network/card/template.${type}`;
|
||||
downloadFile(url);
|
||||
const downFileFn =async (type: string) => {
|
||||
// const url = `${BASE_API_PATH}/network/card/template.${type}`;
|
||||
// downloadFile(url);
|
||||
const res:any = await exportCard(type)
|
||||
if(res){
|
||||
const blob = new Blob([res], { type: type });
|
||||
const url = URL.createObjectURL(blob);
|
||||
console.log(url);
|
||||
downloadFileByUrl(
|
||||
url,
|
||||
`物联卡导入模版`,
|
||||
type,
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
<!-- 物联卡管理 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="iot-card-management-search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
ref="cardManageRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:rowSelection="{
|
||||
<Search :columns="columns" target="iot-card-management-search" @search="handleSearch" />
|
||||
<JTable ref="cardManageRef" :columns="columns" :request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onChange: onSelectChange,
|
||||
}"
|
||||
@cancelSelect="cancelSelect"
|
||||
:params="params"
|
||||
:gridColumn="3"
|
||||
>
|
||||
}" @cancelSelect="cancelSelect" :params="params" :gridColumn="3">
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
|
@ -32,72 +20,62 @@
|
|||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<a-button @click="exportVisible = true">
|
||||
<PermissionButton @click="exportVisible = true"
|
||||
:hasPermission="'iot-card/CardManagement:export'">
|
||||
<AIcon type="ExportOutlined" />
|
||||
批量导出
|
||||
</a-button>
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-button @click="importVisible = true"
|
||||
><AIcon
|
||||
type="ImportOutlined"
|
||||
/>批量导入</a-button
|
||||
>
|
||||
<PermissionButton @click="importVisible = true"
|
||||
:hasPermission="'iot-card/CardManagement:import'">
|
||||
<AIcon type="ImportOutlined" />批量导入
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
@confirm="handleActive"
|
||||
title="确认激活吗?"
|
||||
>
|
||||
<a-button>
|
||||
<AIcon type="CheckCircleOutlined" />
|
||||
批量激活
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认激活吗?',
|
||||
onConfirm: handleActive,
|
||||
}" :hasPermission="'iot-card/CardManagement:active'">
|
||||
<AIcon type="CheckCircleOutlined" />
|
||||
批量激活
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
@confirm="handleStop"
|
||||
title="确认停用吗?"
|
||||
>
|
||||
<a-button type="primary" ghost>
|
||||
<AIcon type="StopOutlined" />
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认停用吗?',
|
||||
onConfirm: handleStop,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:action'">
|
||||
<AIcon type="StopOutlined" />
|
||||
批量停用
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
@confirm="handleResumption"
|
||||
title="确认复机吗?"
|
||||
>
|
||||
<a-button type="primary" ghost>
|
||||
<AIcon type="PoweroffOutlined" />
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认复机吗?',
|
||||
onConfirm: handleResumption,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:action'">
|
||||
<AIcon type="PoweroffOutlined" />
|
||||
批量复机
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-popconfirm
|
||||
@confirm="handleSync"
|
||||
title="确认同步状态吗?"
|
||||
>
|
||||
<a-button type="primary" ghost>
|
||||
<AIcon type="SwapOutlined" />
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认同步状态吗?',
|
||||
onConfirm: handleSync,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:sync'">
|
||||
<AIcon type="SwapOutlined" />
|
||||
同步状态
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="_selectedRowKeys.length > 0">
|
||||
<a-popconfirm
|
||||
@confirm="handelRemove"
|
||||
title="确认删除吗?"
|
||||
>
|
||||
<a-button>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
批量删除
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<PermissionButton :popConfirm="{
|
||||
title: '确认删除吗?',
|
||||
onConfirm: handelRemove,
|
||||
}" ghost type="primary" :hasPermission="'iot-card/CardManagement:delete'">
|
||||
<AIcon type="SwapOutlined" />
|
||||
批量删除
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
|
@ -105,20 +83,13 @@
|
|||
</a-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value="slotProps"
|
||||
@click="handleClick"
|
||||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:active="_selectedRowKeys.includes(slotProps.id)"
|
||||
:status="slotProps.cardStateType.value"
|
||||
:statusText="slotProps.cardStateType.text"
|
||||
:statusNames="{
|
||||
<CardBox :value="slotProps" @click="handleClick" :actions="getActions(slotProps, 'card')" v-bind="slotProps"
|
||||
:active="_selectedRowKeys.includes(slotProps.id)" :status="slotProps.cardStateType.value"
|
||||
:statusText="slotProps.cardStateType.text" :statusNames="{
|
||||
using: 'success',
|
||||
toBeActivated: 'default',
|
||||
deactivate: 'error',
|
||||
}"
|
||||
>
|
||||
}">
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/iot-card/iot-card-bg.png')" />
|
||||
|
@ -150,8 +121,7 @@
|
|||
{{ slotProps.totalFlow }}
|
||||
</span>
|
||||
<span class="card-item-content-text">
|
||||
M 使用流量</span
|
||||
>
|
||||
M 使用流量</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="progress-text">
|
||||
|
@ -165,17 +135,22 @@
|
|||
总共 {{ slotProps.totalFlow }} M
|
||||
</div>
|
||||
</div>
|
||||
<a-progress
|
||||
:strokeColor="'#ADC6FF'"
|
||||
:showInfo="false"
|
||||
:percent="
|
||||
slotProps.totalFlow - slotProps.usedFlow
|
||||
"
|
||||
/>
|
||||
<a-progress :strokeColor="'#ADC6FF'" :showInfo="false" :percent="
|
||||
slotProps.totalFlow - slotProps.usedFlow
|
||||
" />
|
||||
</div>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
<PermissionButton :disabled="item.disabled" :popConfirm="item.popConfirm" :tooltip="{
|
||||
...item.tooltip,
|
||||
}" @click="item.onClick" :hasPermission="'iot-card/CardManagement:' + item.key">
|
||||
<AIcon type="DeleteOutlined" v-if="item.key === 'delete'" />
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item?.text }}</span>
|
||||
</template>
|
||||
</PermissionButton>
|
||||
<!-- <a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
>
|
||||
|
@ -210,7 +185,7 @@
|
|||
</template>
|
||||
</a-button>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</a-tooltip> -->
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -221,8 +196,8 @@
|
|||
<div>
|
||||
{{
|
||||
slotProps.totalFlow
|
||||
? slotProps.totalFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
? slotProps.totalFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -230,8 +205,8 @@
|
|||
<div>
|
||||
{{
|
||||
slotProps.usedFlow
|
||||
? slotProps.usedFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
? slotProps.usedFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -239,8 +214,8 @@
|
|||
<div>
|
||||
{{
|
||||
slotProps.residualFlow
|
||||
? slotProps.residualFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
? slotProps.residualFlow.toFixed(2) + ' M'
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -253,74 +228,52 @@
|
|||
<template #activationDate="slotProps">
|
||||
{{
|
||||
slotProps.activationDate
|
||||
? moment(slotProps.activationDate).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
? moment(slotProps.activationDate).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
<template #updateTime="slotProps">
|
||||
{{
|
||||
slotProps.updateTime
|
||||
? moment(slotProps.updateTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
? moment(slotProps.updateTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
<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">
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'iot-card/CardManagement:' + 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>
|
||||
<!-- 批量导入 -->
|
||||
<Import v-if="importVisible" @close="importVisible = false" />
|
||||
<!-- 批量导出 -->
|
||||
<Export
|
||||
v-if="exportVisible"
|
||||
@close="exportVisible = false"
|
||||
:data="_selectedRowKeys"
|
||||
/>
|
||||
<Export v-if="exportVisible" @close="exportVisible = false" :data="_selectedRowKeys" />
|
||||
<!-- 绑定设备 -->
|
||||
<BindDevice
|
||||
v-if="bindDeviceVisible"
|
||||
:cardId="cardId"
|
||||
@change="bindDevice"
|
||||
/>
|
||||
<BindDevice v-if="bindDeviceVisible" :cardId="cardId" @change="bindDevice" />
|
||||
<!-- 新增、编辑 -->
|
||||
<Save
|
||||
v-if="visible"
|
||||
:type="saveType"
|
||||
:data="current"
|
||||
@change="saveChange"
|
||||
/>
|
||||
<Save v-if="visible" :type="saveType" :data="current" @change="saveChange" />
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -516,7 +469,21 @@ const getActions = (
|
|||
if (!data) return [];
|
||||
return [
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: () => {
|
||||
// router.push({
|
||||
// path: `/iot-card/CardManagement/detail/${data.id}`,
|
||||
// });
|
||||
menuStory.jumpPage('iot-card/CardManagement/Detail', { id: data.id })
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -529,21 +496,7 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: () => {
|
||||
// router.push({
|
||||
// path: `/iot-card/CardManagement/detail/${data.id}`,
|
||||
// });
|
||||
menuStory.jumpPage('iot-card/CardManagement/Detail',{id:data.id})
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'bindDevice',
|
||||
key: 'bind',
|
||||
text: data.deviceId ? '解绑设备' : '绑定设备',
|
||||
tooltip: {
|
||||
title: data.deviceId ? '解绑设备' : '绑定设备',
|
||||
|
@ -551,18 +504,18 @@ const getActions = (
|
|||
icon: data.deviceId ? 'DisconnectOutlined' : 'LinkOutlined',
|
||||
popConfirm: data.deviceId
|
||||
? {
|
||||
title: '确认解绑设备?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: async () => {
|
||||
unbind(data.id).then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
title: '确认解绑设备?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: async () => {
|
||||
unbind(data.id).then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功');
|
||||
cardManageRef.value?.reload();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
onClick: () => {
|
||||
if (!data.deviceId) {
|
||||
|
@ -572,34 +525,34 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'activation',
|
||||
key: data.cardStateType?.value === 'toBeActivated' ? 'active' : 'action',
|
||||
text:
|
||||
data.cardStateType?.value === 'toBeActivated'
|
||||
? '激活'
|
||||
: data.cardStateType?.value === 'deactivate'
|
||||
? '复机'
|
||||
: '停用',
|
||||
? '复机'
|
||||
: '停用',
|
||||
tooltip: {
|
||||
title:
|
||||
data.cardStateType?.value === 'toBeActivated'
|
||||
? '激活'
|
||||
: data.cardStateType?.value === 'deactivate'
|
||||
? '复机'
|
||||
: '停用',
|
||||
? '复机'
|
||||
: '停用',
|
||||
},
|
||||
icon:
|
||||
data.cardStateType?.value === 'toBeActivated'
|
||||
? 'CheckCircleOutlined'
|
||||
: data.cardStateType?.value === 'deactivate'
|
||||
? 'PoweroffOutlined'
|
||||
: 'StopOutlined',
|
||||
? 'PoweroffOutlined'
|
||||
: 'StopOutlined',
|
||||
popConfirm: {
|
||||
title:
|
||||
data.cardStateType?.value === 'toBeActivated'
|
||||
? '确认激活?'
|
||||
: data.cardStateType?.value === 'deactivate'
|
||||
? '确认复机?'
|
||||
: '确认停用?',
|
||||
? '确认复机?'
|
||||
: '确认停用?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: async () => {
|
||||
|
@ -793,14 +746,17 @@ const handelRemove = async () => {
|
|||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.ant-progress-inner) {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
:deep(.ant-progress-bg) {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
|
|
@ -56,42 +56,15 @@
|
|||
</a-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
>
|
||||
<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>
|
||||
<PermissionButton :disabled="item.disabled" :popConfirm="item.popConfirm" :tooltip="{
|
||||
...item.tooltip,
|
||||
}" @click="item.onClick" :hasPermission="'iot-card/Platform:' + item.key">
|
||||
<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>
|
||||
|
@ -107,33 +80,24 @@
|
|||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
<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">
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'iot-card/Platform:' + 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>
|
||||
|
@ -218,7 +182,7 @@ const getActions = (
|
|||
if (!data) return [];
|
||||
return [
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
|
|
@ -1,24 +1,14 @@
|
|||
<!-- 充值管理 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="recharge-search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
ref="rechargeRef"
|
||||
:columns="columns"
|
||||
:request="queryRechargeList"
|
||||
model="TABLE"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:params="params"
|
||||
>
|
||||
<Search :columns="columns" target="recharge-search" @search="handleSearch" />
|
||||
<JTable ref="rechargeRef" :columns="columns" :request="queryRechargeList" model="TABLE"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :params="params">
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="visible = true">
|
||||
<PermissionButton @click="visible = true" :hasPermission="'iot-card/Recharge:pay'" type="primary">
|
||||
充值
|
||||
</a-button>
|
||||
</PermissionButton>
|
||||
<div class="tips-text">
|
||||
<span style="margin-right: 8px; font-size: 16px">
|
||||
<AIcon type="ExclamationCircleOutlined"></AIcon>
|
||||
|
@ -30,41 +20,32 @@
|
|||
<template #createTime="slotProps">
|
||||
{{
|
||||
slotProps.createTime
|
||||
? moment(slotProps.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
? moment(slotProps.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<template
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'iot-card/Recharge:' + 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>
|
||||
|
@ -145,8 +126,8 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: () => {
|
||||
detailVisible.value = true;
|
||||
current.value = data;
|
||||
detailVisible.value = true;
|
||||
current.value = data;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -98,7 +98,13 @@ const getTypeList = (result: Record<string, any>) => {
|
|||
edge.push(item);
|
||||
} else {
|
||||
item.type = 'network';
|
||||
network.push(item);
|
||||
// network.push(item);
|
||||
/**
|
||||
* 插件设备接入 暂时不开发 todo
|
||||
*/
|
||||
if (item.id !== 'plugin_gateway' || item.name !== '插件设备接入') {
|
||||
network.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -135,6 +141,10 @@ const queryProviders = async () => {
|
|||
const resp = await getProviders();
|
||||
if (resp.status === 200) {
|
||||
dataSource.value = getTypeList(resp.result);
|
||||
// dataSource.value = getTypeList(resp.result)[0].list.filter(
|
||||
// (item) => item.name !== '插件设备接入',
|
||||
// );
|
||||
console.log(111, dataSource.value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
gridColumn="2"
|
||||
gridColumns="[2]"
|
||||
:gridColumns="[1, 2]"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
|
|
|
@ -13,45 +13,40 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><AIcon type="PlusOutlined" />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="link/Certificate:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #type="slotProps">
|
||||
<span>{{ slotProps.type.text }}</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<a-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
style="padding: 0px"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
:hasPermission="'link/Certificate:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -62,9 +57,10 @@
|
|||
import type { ActionsType } from '@/components/Table/index';
|
||||
import { query, remove } from '@/api/link/certificate';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const columns = [
|
||||
|
@ -119,7 +115,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
}
|
||||
return [
|
||||
{
|
||||
key: 'eye',
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
|
@ -130,7 +126,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -157,24 +153,19 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/:id`,
|
||||
query: { view: false },
|
||||
});
|
||||
menuStory.jumpPage(
|
||||
`link/Certificate/Detail`,
|
||||
{ id: ':id' },
|
||||
{ view: false },
|
||||
);
|
||||
};
|
||||
|
||||
const handlEye = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/${id}`,
|
||||
query: { view: true },
|
||||
});
|
||||
menuStory.jumpPage(`link/Certificate/Detail`, { id }, { view: true });
|
||||
};
|
||||
|
||||
const handlEdit = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/${id}`,
|
||||
query: { view: false },
|
||||
});
|
||||
menuStory.jumpPage(`link/Certificate/Detail`, { id }, { view: false });
|
||||
};
|
||||
|
||||
const handlDelete = async (id: string) => {
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
format="YYYY-MM-DD HH:mm:ss"
|
||||
v-model="data.time"
|
||||
>
|
||||
<template #suffixIcon><a-icon type="calendar" /></template>
|
||||
<template #suffixIcon
|
||||
><AIcon type="CalendarOutlined"
|
||||
/></template>
|
||||
<template #renderExtraFooter>
|
||||
<a-radio-group
|
||||
default-value="a"
|
||||
|
@ -31,7 +33,8 @@
|
|||
>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<div ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div v-else ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
@ -50,8 +53,8 @@ import {
|
|||
} from './tool.ts';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
|
||||
const loading = ref(false);
|
||||
const empty = ref(false);
|
||||
const data = ref({
|
||||
type: 'hour',
|
||||
time: [null, null],
|
||||
|
@ -140,6 +143,7 @@ const handleCpuOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -186,4 +190,7 @@ watch(
|
|||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
format="YYYY-MM-DD HH:mm:ss"
|
||||
v-model="data.time"
|
||||
>
|
||||
<template #suffixIcon><a-icon type="calendar" /></template>
|
||||
<template #suffixIcon
|
||||
><AIcon type="CalendarOutlined"
|
||||
/></template>
|
||||
<template #renderExtraFooter>
|
||||
<a-radio-group
|
||||
default-value="a"
|
||||
|
@ -31,7 +33,8 @@
|
|||
>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
<div ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div v-else ref="chartRef" style="width: 100%; height: 300px"></div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
@ -50,7 +53,7 @@ import {
|
|||
} from './tool.ts';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
|
||||
const empty = ref(false);
|
||||
const loading = ref(false);
|
||||
const data = ref({
|
||||
type: 'hour',
|
||||
|
@ -144,6 +147,7 @@ const handleJVMOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -190,4 +194,7 @@ watch(
|
|||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -43,12 +43,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-empty v-if="empty" class="empty" />
|
||||
<div
|
||||
v-else
|
||||
ref="chartRef"
|
||||
v-if="flag"
|
||||
style="width: 100%; height: 350px"
|
||||
></div>
|
||||
<a-empty v-else style="height: 300px; margin-top: 120px" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
|
@ -67,10 +67,8 @@ import moment from 'moment';
|
|||
import * as echarts from 'echarts';
|
||||
|
||||
const chartRef = ref<Record<string, any>>({});
|
||||
|
||||
const flag = ref(true);
|
||||
const empty = ref(false);
|
||||
const loading = ref(false);
|
||||
const myChart = ref(null);
|
||||
const data = ref({
|
||||
type: 'bytesRead',
|
||||
time: {
|
||||
|
@ -163,6 +161,7 @@ const handleNetworkOptions = (optionsData, xAxis) => {
|
|||
: typeDataLine,
|
||||
};
|
||||
myChart.setOption(options);
|
||||
// xAxis.length === 0 && (empty.value = true);
|
||||
window.addEventListener('resize', function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
@ -216,4 +215,7 @@ watch(
|
|||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.empty {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
<template lang="">
|
||||
<a-modal
|
||||
:title="data.id ? '编辑' : '新增'"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
:visible="true"
|
||||
width="700px"
|
||||
:confirm-loading="loading"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-form
|
||||
class="form"
|
||||
|
@ -55,6 +51,19 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button key="back" @click="handleCancel">取消</a-button>
|
||||
<PermissionButton
|
||||
key="submit"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleOk"
|
||||
style="margin-left: 8px"
|
||||
:hasPermission="`link/Protocol:${id ? 'update' : 'add'}`"
|
||||
>
|
||||
确认
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
@ -124,7 +133,6 @@ const onSubmit = () => {
|
|||
? await save(params)
|
||||
: await update({ ...props.data, ...params });
|
||||
if (response.status === 200) {
|
||||
message.success('操作成功');
|
||||
emit('change', true);
|
||||
}
|
||||
loading.value = false;
|
||||
|
|
|
@ -13,9 +13,14 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><AIcon type="PlusOutlined" />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="link/Protocol:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -31,11 +36,16 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div class="card-item-content">
|
||||
<h3
|
||||
class="card-item-content-title card-item-content-title-a"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-tooltip>
|
||||
<template #title>
|
||||
{{ slotProps.name }}
|
||||
</template>
|
||||
<h3
|
||||
class="card-item-content-title card-item-content-title-a"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
</a-tooltip>
|
||||
<a-row class="card-item-content-box">
|
||||
<a-col
|
||||
:span="12"
|
||||
|
@ -70,78 +80,49 @@
|
|||
</div>
|
||||
</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="'link/Protocol:' + 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>
|
||||
<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="'link/Protocol:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
@ -173,7 +154,6 @@ const columns = [
|
|||
},
|
||||
width: 200,
|
||||
fixed: 'left',
|
||||
// scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
|
@ -182,6 +162,7 @@ const columns = [
|
|||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
|
@ -227,7 +208,7 @@ const getActions = (
|
|||
if (!data) return [];
|
||||
const actions = [
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
|
|
@ -56,10 +56,9 @@
|
|||
独立配置:集群下不同节点使用不同配置
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
<a-radio-group
|
||||
v-model:value="formData.shareCluster"
|
||||
button-style="solid"
|
||||
|
@ -101,8 +100,9 @@
|
|||
:header="`#${index + 1}.节点`"
|
||||
>
|
||||
<template #extra v-if="!shareCluster">
|
||||
<delete-outlined
|
||||
<AIcon
|
||||
@click="removeCluster(cluster)"
|
||||
type="DeleteOutlined"
|
||||
/>
|
||||
</template>
|
||||
<a-row :gutter="[24, 0]">
|
||||
|
@ -171,7 +171,9 @@
|
|||
绑定到服务器上的网卡地址,绑定到所有网卡:0.0.0.0
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
|
@ -230,7 +232,9 @@
|
|||
监听指定端口的请求
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-select
|
||||
|
@ -281,7 +285,9 @@
|
|||
对外提供访问的地址,内网环境时填写服务器的内网IP地址
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input
|
||||
|
@ -324,7 +330,9 @@
|
|||
对外提供访问的端口
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
|
@ -517,7 +525,9 @@
|
|||
当连接的服务为EMQ时,可能需要使用共享的订阅前缀,如:$queue或$share
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input
|
||||
|
@ -560,7 +570,9 @@
|
|||
单次收发消息的最大长度,单位:字节;设置过大可能会影响性能
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-input-number
|
||||
|
@ -691,7 +703,9 @@
|
|||
处理TCP粘拆包的方式
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<a-select
|
||||
|
@ -966,7 +980,7 @@
|
|||
</div>
|
||||
<a-form-item v-if="!shareCluster">
|
||||
<a-button type="dashed" block @click="addCluster">
|
||||
<PlusOutlined />
|
||||
<AIcon type="PlusOutlined" />
|
||||
新增
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
|
@ -986,14 +1000,15 @@
|
|||
</a-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a-button
|
||||
<PermissionButton
|
||||
v-if="view === 'false'"
|
||||
type="primary"
|
||||
@click="saveData"
|
||||
:loading="loading"
|
||||
:hasPermission="`link/Type:${id ? 'update' : 'add'}`"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-card>
|
||||
</page-container>
|
||||
|
@ -1002,11 +1017,6 @@
|
|||
<script lang="ts" setup name="AccessNetwork">
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
PlusOutlined,
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import {
|
||||
update,
|
||||
save,
|
||||
|
|
|
@ -301,3 +301,13 @@ export const Rules = {
|
|||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const TiTlePermissionButtonStyle = {
|
||||
padding: 0,
|
||||
color: ' #1890ff !important',
|
||||
'font-weight': 700,
|
||||
'font-size': '16px',
|
||||
overflow: 'hidden',
|
||||
'text-overflow': 'ellipsis',
|
||||
'white-space': 'nowrap',
|
||||
};
|
||||
|
|
|
@ -14,9 +14,14 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><AIcon type="PlusOutlined" />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="link/Type:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -43,18 +48,14 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div class="card-item-content">
|
||||
<!-- <a
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="handlEye(slotProps.id)"
|
||||
class="card-item-content-title-a"
|
||||
hasPermission="link/Type:view"
|
||||
:style="TiTlePermissionButtonStyle"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</a> -->
|
||||
<h3
|
||||
@click="handlEye(slotProps.id)"
|
||||
class="card-item-content-title card-item-content-title-a"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
</PermissionButton>
|
||||
<a-row class="card-item-content-box">
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
|
@ -88,78 +89,49 @@
|
|||
</div>
|
||||
</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="'link/Type:' + 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>
|
||||
<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="'link/Type:' + i.key"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
|
@ -186,13 +158,15 @@
|
|||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="TypePage">
|
||||
import type { ActionsType } from '@/components/Table/index'
|
||||
import type { ActionsType } from '@/components/Table/index';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { supports, query, remove, start, shutdown } from '@/api/link/type';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { TiTlePermissionButtonStyle } from './data';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const params = ref<Record<string, any>>({});
|
||||
const options = ref([]);
|
||||
|
||||
|
@ -282,9 +256,10 @@ const getActions = (
|
|||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const state = data.state.value;
|
||||
const stateText = state === 'enabled' ? '禁用' : '启用';
|
||||
const actions = [
|
||||
{
|
||||
key: 'eye',
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
|
@ -295,7 +270,7 @@ const getActions = (
|
|||
},
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -307,13 +282,13 @@ const getActions = (
|
|||
},
|
||||
{
|
||||
key: 'action',
|
||||
text: state === 'enabled' ? '禁用' : '启用',
|
||||
text: stateText,
|
||||
tooltip: {
|
||||
title: state === 'enabled' ? '禁用' : '启用',
|
||||
title: stateText,
|
||||
},
|
||||
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
|
||||
popConfirm: {
|
||||
title: `确认${state === 'enabled' ? '禁用' : '启用'}?`,
|
||||
title: `确认${stateText}?`,
|
||||
onConfirm: async () => {
|
||||
let res =
|
||||
state === 'enabled'
|
||||
|
@ -353,36 +328,19 @@ const getActions = (
|
|||
];
|
||||
return type === 'table'
|
||||
? actions
|
||||
: actions.filter((item) => item.key !== 'eye');
|
||||
: actions.filter((item) => item.key !== 'view');
|
||||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push({
|
||||
path: `/iot/link/type/detail/:id`,
|
||||
query: { view: false },
|
||||
});
|
||||
menuStory.jumpPage(`link/Type/Detail`, { id: ':id' }, { view: false });
|
||||
};
|
||||
|
||||
const handlEye = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/type/detail/${id}`,
|
||||
query: { view: true },
|
||||
});
|
||||
menuStory.jumpPage(`link/Type/Detail`, { id }, { view: true });
|
||||
};
|
||||
|
||||
const handlEdit = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/type/detail/${id}`,
|
||||
query: { view: false },
|
||||
});
|
||||
};
|
||||
|
||||
const handlDelete = async (id: string) => {
|
||||
const res = await remove(id);
|
||||
if (res.success) {
|
||||
message.success('操作成功');
|
||||
tableRef.value.reload();
|
||||
}
|
||||
menuStory.jumpPage(`link/Type/Detail`, { id }, { view: false });
|
||||
};
|
||||
|
||||
const getDetails = (slotProps: Partial<Record<string, any>>) => {
|
||||
|
|
|
@ -40,6 +40,53 @@
|
|||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #gbChannelId="slotProps">
|
||||
<a-space>
|
||||
<Ellipsis>
|
||||
{{ slotProps.gbChannelId }}
|
||||
</Ellipsis>
|
||||
<a-popover
|
||||
v-model:visible="slotProps.popVis"
|
||||
trigger="click"
|
||||
>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<span>编辑国标ID</span>
|
||||
<AIcon
|
||||
type="CloseOutlined"
|
||||
@click="handleClose(slotProps)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="simple-form">
|
||||
<a-input
|
||||
v-model:value="gbID"
|
||||
@change="validField(slotProps)"
|
||||
/>
|
||||
<div
|
||||
class="error"
|
||||
v-if="valid && !valid?.passed"
|
||||
>
|
||||
<!-- {{ valid?.reason }} -->
|
||||
该国标ID在同一设备下已存在
|
||||
</div>
|
||||
</div>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleSave(slotProps)"
|
||||
:loading="loading"
|
||||
style="width: 100%"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</template>
|
||||
<a-button type="link" @click="slotProps.popVis = true">
|
||||
<AIcon type="EditOutlined" />
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
|
@ -106,6 +153,8 @@ const columns = [
|
|||
title: '设备名称',
|
||||
dataIndex: 'deviceName',
|
||||
key: 'deviceName',
|
||||
// width: 200,
|
||||
// fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
|
@ -174,7 +223,6 @@ const params = ref<Record<string, any>>({});
|
|||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
console.log('params.value: ', params.value);
|
||||
};
|
||||
|
||||
const listRef = ref();
|
||||
|
@ -250,6 +298,10 @@ const getActions = (
|
|||
* 批量解绑
|
||||
*/
|
||||
const handleMultipleUnbind = async () => {
|
||||
if (!_selectedRowKeys.value.length) {
|
||||
message.error('请先选择需要解绑的通道列表');
|
||||
return;
|
||||
}
|
||||
const channelIds = listRef.value?._dataSource
|
||||
.filter((f: any) => _selectedRowKeys.value.includes(f.id))
|
||||
.map((m: any) => m.channelId);
|
||||
|
@ -264,4 +316,61 @@ const handleMultipleUnbind = async () => {
|
|||
message.error('操作失败!');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 编辑国标ID
|
||||
*/
|
||||
const gbID = ref('');
|
||||
const loading = ref(false);
|
||||
const handleSave = async (data: any) => {
|
||||
if (!gbID.value) message.error('请输入国标ID');
|
||||
if (!valid.value?.passed) return;
|
||||
|
||||
loading.value = true;
|
||||
const resp = await CascadeApi.updateGbChannelId(data.id, {
|
||||
gbChannelId: gbID.value,
|
||||
});
|
||||
loading.value = false;
|
||||
if (resp.success) {
|
||||
message.success('操作成功!');
|
||||
listRef.value?.reload();
|
||||
valid.value = undefined;
|
||||
gbID.value = '';
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 验证ID是否存在
|
||||
*/
|
||||
const valid = ref<{ passed: string; reason: string }>();
|
||||
const validField = async (data: any) => {
|
||||
const { result } = await CascadeApi.validateField(data.cascadeId, [
|
||||
gbID.value,
|
||||
]);
|
||||
valid.value = result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
const handleClose = (data: any) => {
|
||||
data.popVis = false;
|
||||
valid.value = undefined;
|
||||
gbID.value = '';
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.simple-form {
|
||||
margin-bottom: 10px;
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
<!-- 国标级联-推送 -->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="_vis"
|
||||
title="推送"
|
||||
cancelText="取消"
|
||||
okText="确定"
|
||||
width="900px"
|
||||
@ok="_vis = false"
|
||||
@cancel="_vis = false"
|
||||
>
|
||||
<a-row :gutter="20">
|
||||
<a-col :span="8">
|
||||
<p>成功:{{ successCount }}</p>
|
||||
<a-space>
|
||||
<p>失败:{{ failCount }}</p>
|
||||
<a
|
||||
v-if="errMessage.length"
|
||||
@click="
|
||||
downloadObject(
|
||||
errMessage || '',
|
||||
data.name + '-推送失败',
|
||||
)
|
||||
"
|
||||
>下载</a
|
||||
>
|
||||
</a-space>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<p>推送通道数量:{{ data.count }}</p>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<p>已推送通道数量:{{ successCount + failCount }}</p>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div v-if="flag">
|
||||
<a-textarea :rows="10" v-model:value="errStr" />
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
import { EventSourcePolyfill } from 'event-source-polyfill';
|
||||
import { PropType } from 'vue';
|
||||
import { downloadObject } from '@/utils/utils';
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
data: {
|
||||
type: Object as PropType<Partial<Record<string, any>>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const _vis = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val),
|
||||
});
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val: boolean) => {
|
||||
if (val) publish();
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* 推送
|
||||
*/
|
||||
const successCount = ref(0);
|
||||
const failCount = ref(0);
|
||||
const flag = ref(false);
|
||||
const errMessage = ref<any[]>([]);
|
||||
const errStr = computed(() => JSON.stringify(errMessage.value));
|
||||
const publish = () => {
|
||||
const activeAPI = `${BASE_API_PATH}/media/gb28181-cascade/${
|
||||
props.data.id
|
||||
}/bindings/publish?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`;
|
||||
const source = new EventSourcePolyfill(activeAPI);
|
||||
source.onmessage = (e: any) => {
|
||||
const res = JSON.parse(e.data);
|
||||
if (res.successful) {
|
||||
successCount.value += 1;
|
||||
} else {
|
||||
failCount.value += 1;
|
||||
if (errMessage.value.length <= 5) {
|
||||
errMessage.value.push({ ...res });
|
||||
}
|
||||
}
|
||||
};
|
||||
source.onerror = () => {
|
||||
source.close();
|
||||
};
|
||||
source.onopen = () => {};
|
||||
};
|
||||
</script>
|
|
@ -193,6 +193,8 @@
|
|||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
||||
<Publish v-model:visible="publishVis" :data="currentData" />
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -201,6 +203,7 @@ import CascadeApi from '@/api/media/cascade';
|
|||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import Publish from './Publish/index.vue';
|
||||
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
|
@ -314,6 +317,13 @@ const handleAdd = () => {
|
|||
menuStory.jumpPage('media/Cascade/Save');
|
||||
};
|
||||
|
||||
const publishVis = ref(false);
|
||||
const currentData = ref();
|
||||
/**
|
||||
* 按钮
|
||||
* @param data
|
||||
* @param type
|
||||
*/
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
|
@ -366,7 +376,8 @@ const getActions = (
|
|||
disabled: data.status?.value === 'disabled',
|
||||
icon: 'ShareAltOutlined',
|
||||
onClick: () => {
|
||||
// updateChannel()
|
||||
publishVis.value = true;
|
||||
currentData.value = data;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
<template #title>
|
||||
<p>调用流媒体接口时请求的服务地址</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
|
@ -144,7 +144,7 @@
|
|||
视频设备将流推送到该IP地址下,部分设备仅支持IP地址,建议全是用IP地址
|
||||
</p>
|
||||
</template>
|
||||
<question-circle-outlined />
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
|
@ -266,10 +266,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup name="StreamDetail">
|
||||
import { message, Form } from 'ant-design-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { queryProviders, queryDetail, save, update } from '@/api/media/stream';
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import { FormDataType } from '../type';
|
||||
|
||||
|
|
|
@ -16,9 +16,14 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><plus-outlined />新增</a-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="media/Stream:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -106,42 +111,24 @@
|
|||
</div>
|
||||
</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="'media/Stream:' + 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>
|
||||
|
@ -154,10 +141,10 @@ import type { ActionsType } from '@/components/Table/index.vue';
|
|||
import { getImage } from '@/utils/comm';
|
||||
import { query, remove, disable, enalbe } from '@/api/media/stream';
|
||||
import { message } from 'ant-design-vue';
|
||||
import Detail from './Detail/index.vue';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const columns = [
|
||||
|
@ -194,9 +181,10 @@ const columns = [
|
|||
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const state = data.state.value;
|
||||
const stateText = state === 'enabled' ? '禁用' : '启用';
|
||||
const actions = [
|
||||
{
|
||||
key: 'edit',
|
||||
key: 'update',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
|
@ -208,13 +196,13 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
},
|
||||
{
|
||||
key: 'action',
|
||||
text: state === 'enabled' ? '禁用' : '启用',
|
||||
text: stateText,
|
||||
tooltip: {
|
||||
title: state === 'enabled' ? '禁用' : '启用',
|
||||
title: stateText,
|
||||
},
|
||||
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
|
||||
popConfirm: {
|
||||
title: `确认${state === 'enabled' ? '禁用' : '启用'}?`,
|
||||
title: `确认${stateText}?`,
|
||||
onConfirm: async () => {
|
||||
let res =
|
||||
state === 'enabled'
|
||||
|
@ -255,22 +243,13 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push({
|
||||
path: `/iot/link/Stream/detail/:id`,
|
||||
query: { view: false },
|
||||
});
|
||||
menuStory.jumpPage(`media/Stream/Detail`, { id: ':id' }, { view: false });
|
||||
};
|
||||
const handlEdit = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/Stream/detail/${id}`,
|
||||
query: { view: false },
|
||||
});
|
||||
menuStory.jumpPage(`media/Stream/Detail`, { id }, { view: false });
|
||||
};
|
||||
const handlEye = (id: string) => {
|
||||
router.push({
|
||||
path: `/iot/link/Stream/detail/${id}`,
|
||||
query: { view: true },
|
||||
});
|
||||
menuStory.jumpPage(`media/Stream/Detail`, { id }, { view: true });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
:columns="columns"
|
||||
:request="queryList"
|
||||
:gridColumn="3"
|
||||
:gridColumns="[1,2,3]"
|
||||
ref="tableRef"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
|
|
|
@ -1,37 +1,182 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<Search :columns="columns" target="alarm-log-detail"></Search>
|
||||
<JTable :columns="columns" model="TABLE" :request="queryList"></JTable>
|
||||
</page-container>
|
||||
<page-container>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="alarm-log-detail"
|
||||
@search="handleSearch"
|
||||
></Search>
|
||||
<JTable
|
||||
:columns="columns"
|
||||
model="TABLE"
|
||||
:request="queryList"
|
||||
:params="params"
|
||||
:defaultParams="{
|
||||
terms,
|
||||
sorts: [{ name: 'alarmTime', order: 'desc' }],
|
||||
}"
|
||||
>
|
||||
<template #alarmTime="slotProps">{{
|
||||
moment(slotProps.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</template>
|
||||
<template #action="slotProps">
|
||||
<a-space
|
||||
><template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
>
|
||||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
@click="i.onClick"
|
||||
type="link"
|
||||
style="padding: 0px"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon"/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
<Info v-if="visiable" :data="current" @close="close"/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const columns = [{
|
||||
title:'告警时间',
|
||||
dataIndex:'alarmTime',
|
||||
key:'alarmTime',
|
||||
search:{
|
||||
type:'date'
|
||||
}
|
||||
},{
|
||||
title:'告警名称',
|
||||
dataIndex:'alarmConfigName',
|
||||
key:'alarmConfigName',
|
||||
},{
|
||||
title:'说明',
|
||||
dataIndex:'description',
|
||||
key:'description'
|
||||
},{
|
||||
title:'操作',
|
||||
dataIndex:'action',
|
||||
key:'action'
|
||||
}]
|
||||
|
||||
import { detail, queryHistoryList } from '@/api/rule-engine/log';
|
||||
import { useRoute } from 'vue-router';
|
||||
import moment from 'moment';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useAlarmStore } from '@/store/alarm';
|
||||
import Info from './info.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
const route = useRoute();
|
||||
const id = route.params?.id;
|
||||
let visiable = ref(false);
|
||||
const columns = [
|
||||
{
|
||||
title: '告警时间',
|
||||
dataIndex: 'alarmTime',
|
||||
key: 'alarmTime',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '告警名称',
|
||||
dataIndex: 'alarmConfigName',
|
||||
key: 'alarmConfigName',
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
key: 'action',
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type?: 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
const actions = [
|
||||
{
|
||||
key: 'view',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
},
|
||||
icon: 'SearchOutlined',
|
||||
onClick: () => {
|
||||
current.value = data;
|
||||
visiable.value = true;
|
||||
},
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
const terms = [
|
||||
{
|
||||
column: 'alarmRecordId',
|
||||
termType: 'eq$not',
|
||||
value: id,
|
||||
type: 'and',
|
||||
},
|
||||
];
|
||||
let params = ref({});
|
||||
const alarmStore = useAlarmStore();
|
||||
const { data } = alarmStore;
|
||||
let current = ref(); // 当前告警记录信息
|
||||
let details = ref(); // 告警记录的详情
|
||||
/**
|
||||
* 获取详情列表
|
||||
*/
|
||||
const queryList = () =>{
|
||||
const queryList = async (params: any) => {
|
||||
const res = await queryHistoryList({
|
||||
...params,
|
||||
// sorts: [{ name: 'alarmTime', order: 'desc' }],
|
||||
});
|
||||
if (res.status === 200) {
|
||||
|
||||
return {
|
||||
code: res.message,
|
||||
result: {
|
||||
data: res.result.data,
|
||||
pageIndex: res.result.pageIndex,
|
||||
pageSize: res.result.pageSize,
|
||||
total: res.result.total,
|
||||
},
|
||||
status: res.status,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
code: 200,
|
||||
result: {
|
||||
data: [],
|
||||
pageIndex: 0,
|
||||
pageSize: 0,
|
||||
total: 0,
|
||||
},
|
||||
status: 200,
|
||||
};
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 根据id初始化数据
|
||||
*/
|
||||
watchEffect(async () => {
|
||||
const res = await detail(id);
|
||||
if (res.status === 200) {
|
||||
data.current = res.result;
|
||||
if (res.result.targetType === 'device') {
|
||||
columns.splice(2, 0, {
|
||||
dataIndex: 'targetName',
|
||||
title: '告警设备',
|
||||
key: 'targetName',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
const handleSearch = (_params: any) => {
|
||||
params.value = _params;
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭模态弹窗
|
||||
*/
|
||||
const close = () => {
|
||||
visiable.value = false
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<a-modal visible title="详情" okText="确定" cancelText="取消" :width="1000" @ok="closeModal" @cancel="closeModal">
|
||||
<a-descriptions bordered :column="2">
|
||||
<a-descriptions-item v-if="props.data.targetType==='device'" label="告警设备" :span="1">{{props.data?.targetName || ''}}</a-descriptions-item>
|
||||
<a-descriptions-item v-if="props.data.targetType==='device'" label="设备ID" :span="1">{{props.data?.targetId || ''}}</a-descriptions-item>
|
||||
<a-descriptions-item label="告警名称" :span="1">{{
|
||||
props.data?.alarmConfigName
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="告警时间" :span="1">{{
|
||||
moment(data?.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</a-descriptions-item>
|
||||
<a-descriptions-item label="告警级别" :span="1">
|
||||
<a-tooltip
|
||||
placement="topLeft"
|
||||
:title="(Store.get('default-level') || []).find((item: any) => item?.level === data?.level)
|
||||
?.title || props.data?.level"
|
||||
>
|
||||
<Ellipsis>
|
||||
<span>
|
||||
{{(Store.get('default-level') || []).find((item: any) => item?.level === data?.level)
|
||||
?.title || props.data?.level}}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
</a-tooltip>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="告警说明" :span="1"
|
||||
><a-tooltip
|
||||
placement="topLeft"
|
||||
:title="data?.description || ''"
|
||||
>
|
||||
<Ellipsis>
|
||||
<span>
|
||||
{{ data?.description || '' }}
|
||||
</span> </Ellipsis
|
||||
>
|
||||
</a-tooltip></a-descriptions-item
|
||||
>
|
||||
<a-descriptions-item
|
||||
label="告警流水"
|
||||
:span="2"
|
||||
><div style="max-height: 500px; overflow-y: auto;"><JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" :expand-depth="5"></JsonViewer></div></a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import moment from 'moment';
|
||||
import { Store } from 'jetlinks-store';
|
||||
import JsonViewer from 'vue-json-viewer';
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
});
|
||||
const emit = defineEmits(['close'])
|
||||
const closeModal = () => {
|
||||
emit('close');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<a-modal
|
||||
title="告警处理"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
visible
|
||||
@cancel="handleCancel"
|
||||
@ok="handleSave"
|
||||
destroyOnClose
|
||||
:confirmLoading="loading"
|
||||
>
|
||||
<a-form :rules="rules" layout="vertical" ref="formRef" :model="form">
|
||||
<a-form-item label="处理结果" name="describe">
|
||||
<a-textarea
|
||||
:rows="8"
|
||||
:maxlength="200"
|
||||
showCount
|
||||
placeholder="请输入处理结果"
|
||||
v-model:value="form.describe"
|
||||
></a-textarea>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { handleLog } from '@/api/rule-engine/log';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
},
|
||||
});
|
||||
const loading = ref<boolean>(false);
|
||||
const formRef = ref();
|
||||
const rules = {
|
||||
describe: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入处理结果',
|
||||
},
|
||||
],
|
||||
};
|
||||
const form = reactive({
|
||||
describe: '',
|
||||
});
|
||||
let visible = ref(true);
|
||||
const emit = defineEmits(['closeSolve'])
|
||||
const handleCancel = () => {
|
||||
emit('closeSolve');
|
||||
};
|
||||
const handleSave = () => {
|
||||
loading.value = true;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const res = await handleLog({
|
||||
describe: form.describe,
|
||||
type: 'user',
|
||||
state: 'normal',
|
||||
alarmRecordId: props.data?.current?.id || '',
|
||||
alarmConfigId: props.data?.current?.alarmConfigId || '',
|
||||
alarmTime: props?.data?.current?.alarmTime || '',
|
||||
});
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功!');
|
||||
} else {
|
||||
onlyMessage('操作失败!', 'error');
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -1,78 +1,130 @@
|
|||
<template>
|
||||
<a-modal
|
||||
title="告警处理"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
visible
|
||||
@cancel="handleCancel"
|
||||
@ok="handleSave"
|
||||
destroyOnClose
|
||||
:confirmLoading="loading"
|
||||
title="处理记录"
|
||||
:width="1200"
|
||||
cancelText="取消"
|
||||
okText="确定"
|
||||
@ok="clsoeModal"
|
||||
@cancel="clsoeModal"
|
||||
>
|
||||
<a-form :rules="rules" layout="vertical" ref="formRef" :model="form">
|
||||
<a-form-item label="处理结果" name="describe">
|
||||
<a-textarea
|
||||
:rows="8"
|
||||
:maxlength="200"
|
||||
showCount
|
||||
placeholder="请输入处理结果"
|
||||
v-model:value="form.describe"
|
||||
></a-textarea>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="bind-channel"
|
||||
@search="handleSearch"
|
||||
></Search>
|
||||
<JTable
|
||||
model="TABLE"
|
||||
:columns="columns"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
terms,
|
||||
}"
|
||||
:request="queryHandleHistory"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<h3>记录列表</h3>
|
||||
</template>
|
||||
<template #handleTime="slotsProps">
|
||||
<span>
|
||||
{{
|
||||
moment(slotsProps.handleTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss'
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
<template #handleType="slotProps">
|
||||
<span>{{ slotProps.handleType.text }}</span>
|
||||
</template>
|
||||
<template #alarmTime="slotProps">
|
||||
<span>
|
||||
{{
|
||||
moment(slotProps.alarmTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</JTable>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { handleLog } from '@/api/rule-engine/log';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { queryHandleHistory } from '@/api/rule-engine/log';
|
||||
import moment from 'moment';
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
},
|
||||
});
|
||||
const loading = ref<boolean>(false);
|
||||
const formRef = ref();
|
||||
const rules = {
|
||||
describe: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入处理结果',
|
||||
const terms = [
|
||||
{
|
||||
column: 'alarmRecordId',
|
||||
termType: 'eq',
|
||||
value: props.data.id,
|
||||
type: 'and',
|
||||
},
|
||||
];
|
||||
const columns = [
|
||||
{
|
||||
title: '处理时间',
|
||||
dataIndex: 'handleTime',
|
||||
key: 'handleTime',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
dataIndex: 'handleType',
|
||||
title: '处理类型',
|
||||
key: 'handleType',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '系统',
|
||||
value: 'system',
|
||||
},
|
||||
{
|
||||
label: '人工',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '告警时间',
|
||||
dataIndex: 'alarmTime',
|
||||
key: 'alarmTime',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '告警处理',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
];
|
||||
const params = ref();
|
||||
const emit = defineEmits(['closeLog']);
|
||||
/**
|
||||
* 关闭弹窗
|
||||
*/
|
||||
const clsoeModal = () => {
|
||||
emit('closeLog');
|
||||
};
|
||||
const form = reactive({
|
||||
describe: '',
|
||||
});
|
||||
let visible = ref(true);
|
||||
const emit = defineEmits(['closeSolve'])
|
||||
const handleCancel = () => {
|
||||
emit('closeSolve');
|
||||
};
|
||||
const handleSave = () => {
|
||||
loading.value = true;
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const res = await handleLog({
|
||||
describe: form.describe,
|
||||
type: 'user',
|
||||
state: 'normal',
|
||||
alarmRecordId: props.data?.current?.id || '',
|
||||
alarmConfigId: props.data?.current?.alarmConfigId || '',
|
||||
alarmTime: props?.data?.current?.alarmTime || '',
|
||||
});
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功!');
|
||||
} else {
|
||||
onlyMessage('操作失败!', 'error');
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
:columns="columns"
|
||||
:request="handleSearch"
|
||||
:params="params"
|
||||
:gridColumns="[1,1,2]"
|
||||
:gridColumn="2"
|
||||
model="CARD"
|
||||
>
|
||||
|
@ -115,7 +116,8 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
</JTable>
|
||||
<SolveLog :data="data" v-if="data.solveVisible" @closeSolve="closeSolve"/>
|
||||
<SolveComponent :data="data" v-if="data.solveVisible" @closeSolve="closeSolve"/>
|
||||
<SolveLog :data="data.current" v-if="data.logVisible" @closeLog="closeLog"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -134,6 +136,7 @@ import { storeToRefs } from 'pinia';
|
|||
import { Store } from 'jetlinks-store';
|
||||
import moment from 'moment';
|
||||
import type { ActionsType } from '@/components/Table';
|
||||
import SolveComponent from '../SolveComponent/index.vue';
|
||||
import SolveLog from '../SolveLog/index.vue'
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
const menuStory = useMenuStore();
|
||||
|
@ -390,12 +393,25 @@ const getActions = (
|
|||
title: '处理记录',
|
||||
},
|
||||
icon: 'FileTextOutlined',
|
||||
onClick:() =>{
|
||||
data.value.current = currentData;
|
||||
data.value.logVisible = true;
|
||||
}
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
/**
|
||||
* 关闭告警日志
|
||||
*/
|
||||
const closeSolve = () =>{
|
||||
data.value.solveVisible = false
|
||||
data.value.solveVisible = false;
|
||||
}
|
||||
/**
|
||||
* 关闭处理记录
|
||||
*/
|
||||
const closeLog = () =>{
|
||||
data.value.logVisible = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -105,7 +105,6 @@
|
|||
@click="i.onClick"
|
||||
type="link"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'device/Instance:' + i.key"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
|
|
Loading…
Reference in New Issue