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

This commit is contained in:
XieYongHong 2023-07-11 14:22:11 +08:00
commit bd34de8642
23 changed files with 346 additions and 215 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -202,13 +202,15 @@ const modelRef = reactive({
const property = ref<any>({});
const onPropertyChange = (val: string) => {
const onPropertyChange = (val: string, flag?: boolean) => {
if (val) {
const _item = props.metadata?.properties.find(
(item: any) => item.id === val,
);
property.value = _item || {};
modelRef.message.value = undefined
if(!flag){
modelRef.message.value = undefined
}
}
};
@ -227,7 +229,7 @@ watch(
if (newVal) {
Object.assign(modelRef, newVal);
if (newVal?.message?.properties) {
onPropertyChange(newVal?.message?.properties);
onPropertyChange(newVal?.message?.properties, true);
}
}
},
@ -263,6 +265,7 @@ const saveBtn = () =>
resolve(false);
});
}
console.log(_data)
emit('update:modelValue', _data)
resolve(_data);
})

View File

@ -75,6 +75,7 @@ import { getImage } from '@/utils/comm';
padding: 8px 16px;
color: #2f54eb;
background-color: rgba(#a7bdf7, 0.2);
word-wrap: break-word;
}
h1 {

View File

@ -163,6 +163,7 @@ const columns = [
title: '名称',
dataIndex: 'name',
key: 'name',
ellipsis: true,
search: {
type: 'string',
},
@ -229,7 +230,7 @@ const columns = [
title: '操作',
key: 'action',
fixed: 'right',
width: 160,
width: 180,
scopedSlots: true,
},
];

View File

@ -25,7 +25,6 @@
:src="url"
v-if="!loading"
></iframe>
<!-- sandbox="allow-forms allow-scripts allow-same-origin allow-popups" -->
</div>
</j-spin>
</template>
@ -105,7 +104,6 @@ const updateIframeStyle = () => {
) as HTMLIFrameElement;
iframe.onload = () => {
const currentUrl = iframe?.contentWindow?.location?.search || '';
console.log(currentUrl)
let authCode = '';
if (currentUrl.startsWith('?')) {
currentUrl

View File

@ -0,0 +1,129 @@
<template>
<div class="box-item">
<div class="box-item-img">
<j-popover
v-model:visible="popoverVisible"
placement="top"
:trigger="['click']"
>
<div
:class="{
disabled: !notifyChannels?.includes(current?.id),
}"
>
<img
:src="iconMap.get(current?.channelProvider)"
style="width: 32px"
/>
</div>
<template #content>
<PermissionButton
v-if="!notifyChannels?.includes(current?.id)"
type="link"
:hasPermission="true"
@click="onCheckChange(current)"
>
订阅
</PermissionButton>
<template v-else>
<Detail
@unsubscribe="onUnSubscribe"
@save="onSave"
v-if="current?.channelProvider !== 'inside-mail'"
:current="current"
:data="props.data"
@close="popoverVisible = false"
/>
<PermissionButton
v-else
type="link"
:hasPermission="true"
@click="onUnSubscribe(current)"
>
取消订阅
</PermissionButton>
</template>
</template>
</j-popover>
</div>
<div class="box-item-text">
<j-ellipsis style="width: 50px">
{{ current?.name }}
</j-ellipsis>
</div>
</div>
</template>
<script lang="ts" setup>
import { getImage } from '@/utils/comm';
import Detail from './Detail.vue';
const iconMap = new Map();
iconMap.set('notifier-dingTalk', getImage('/notice-rule/dingtalk.png'));
iconMap.set('notifier-weixin', getImage('/notice-rule/wechat.png'));
iconMap.set('notifier-email', getImage('/notice-rule/email.png'));
iconMap.set('notifier-voice', getImage('/notice-rule/voice.png'));
iconMap.set('notifier-sms', getImage('/notice-rule/sms.png'));
iconMap.set('inside-mail', getImage('/notice-rule/inside-mail.png'));
const emit = defineEmits(['save', 'unsubscribe']);
const props = defineProps({
data: {
//
type: Object,
default: () => {},
},
current: {
//
type: Object,
default: () => {},
},
notifyChannels: {
type: Array,
default: () => []
}
});
const popoverVisible = ref<boolean>(false);
const onUnSubscribe = (dt: any) => {
emit('unsubscribe', dt);
popoverVisible.value = false
};
const onCheckChange = (dt: any) => {
emit('save', dt)
popoverVisible.value = false
};
</script>
<style lang="less" scoped>
.box-item {
// margin: 0 5px;
.box-item-img {
width: 50px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
img {
z-index: 1;
cursor: pointer;
}
.disabled {
filter: grayscale(100%);
// filter: brightness(0);
// opacity: 50%;
}
}
.box-item-text {
width: 100%;
text-align: center;
color: #666666;
font-size: 12px;
}
}
</style>

View File

@ -1,16 +1,16 @@
<template>
<j-modal width="350px" visible @cancel="emit('close')" :footer="null">
<div style="width: 300px">
<template v-if="getType === 'notifier-dingTalk'">
<div class="tip">绑定账号{{ info }}</div>
<div class="tip"><j-ellipsis :lineClamp="2">绑定账号{{ info }}</j-ellipsis></div>
</template>
<template v-else-if="getType === 'notifier-weixin'">
<div class="tip">绑定账号{{ info }}</div>
<div class="tip"><j-ellipsis :lineClamp="2">绑定账号{{ info }}</j-ellipsis></div>
</template>
<template v-else-if="getType === 'notifier-email'">
<div class="tip">绑定账号{{ user.userInfos?.email }}</div>
<div class="tip"><j-ellipsis :lineClamp="2">绑定账号{{ user.userInfos?.email }}</j-ellipsis></div>
</template>
<template v-else>
<div class="tip">绑定账号{{ user.userInfos?.telephone }}</div>
<div class="tip"><j-ellipsis :lineClamp="2">绑定账号{{ user.userInfos?.telephone }}</j-ellipsis></div>
</template>
<div class="btn">
<j-button @click="emit('unsubscribe', current)">取消订阅</j-button>
@ -20,7 +20,7 @@
>更换绑定账号</j-button
>
</div>
</j-modal>
</div>
<EditInfo
v-if="editInfoVisible"
:data="user.userInfos"
@ -43,7 +43,7 @@ import EditInfo from '../../EditInfo/index.vue';
import Bind from './Bind.vue';
const user = useUserInfo();
const emit = defineEmits(['close', 'save', 'unsubscribe']);
const emit = defineEmits(['save', 'unsubscribe', 'close']);
const info = ref<any>(null);
const props = defineProps({
data: {
@ -75,18 +75,17 @@ const onBind = () => {
} else {
visible.value = true
}
emit('close')
};
const onSave = () => {
editInfoVisible.value = false;
user.getUserInfo();
emit('save', props.current);
emit('close');
};
const onBindSave = () => {
emit('save', props.current);
emit('close');
}
const handleSearch = async () => {
@ -123,7 +122,7 @@ watch(
<style lang="less" scoped>
.tip {
width: 100%;
margin: 30px 0;
margin: 20px 0;
}
.btn {

View File

@ -7,7 +7,7 @@
<div class="child-item-left-auth" v-if="data?.description">
<j-tooltip :title="data.description">
<AIcon
style="font-size: 16px; color: rgba(0, 0, 0, .3)"
style="font-size: 16px; color: rgba(0, 0, 0, 0.3)"
type="ExclamationCircleOutlined"
/>
</j-tooltip>
@ -16,81 +16,7 @@
<div class="child-item-right">
<MCarousel :data="data?.channels">
<template #card="slotProps">
<div class="box-item">
<div class="box-item-img">
<j-dropdown placement="top" :trigger="['click']">
<div
:class="{
disabled: !notifyChannels?.includes(
slotProps?.id,
),
}"
>
<img
:src="
iconMap.get(
slotProps?.channelProvider,
)
"
style="width: 32px"
/>
</div>
<template #overlay>
<j-menu>
<j-menu-item
v-if="
!notifyChannels?.includes(
slotProps?.id,
)
"
>
<PermissionButton
type="link"
:hasPermission="true"
@click="
onCheckChange(slotProps)
"
>
订阅
</PermissionButton>
</j-menu-item>
<template v-else>
<j-menu-item>
<PermissionButton
type="text"
:hasPermission="true"
@click="
onUnSubscribe(slotProps)
"
>
取消订阅
</PermissionButton>
</j-menu-item>
<j-menu-item
v-if="
slotProps.channelProvider !==
'inside-mail'
"
>
<PermissionButton
type="link"
:hasPermission="true"
@click="onDetail(slotProps)"
>
查看详情
</PermissionButton>
</j-menu-item>
</template>
</j-menu>
</template>
</j-dropdown>
</div>
<div class="box-item-text">
<j-ellipsis style="width: 50px;">
{{ slotProps?.name }}
</j-ellipsis>
</div>
</div>
<Card @save="onCheckChange" @unsubscribe="onUnSubscribe" :notifyChannels="notifyChannels" :data="props.data" :current="slotProps" />
</template>
</MCarousel>
</div>
@ -102,28 +28,19 @@
:current="current"
@close="visible = false"
/>
<Detail @unsubscribe="onUnSubscribe" @save="onSave" @close="_visible = false" v-if="_visible" :current="current" :data="props.data" />
</template>
<script lang="ts" setup>
import { getImage, onlyMessage } from '@/utils/comm';
import { onlyMessage } from '@/utils/comm';
import MCarousel from '@/components/MCarousel/index.vue';
import Unsubscribe from './Unsubscribe.vue';
import Detail from './Detail.vue';
import Card from './Card.vue';
import {
getIsBindThird,
save_api,
} from '@/api/account/notificationSubscription';
import { useUserInfo } from '@/store/userInfo';
const iconMap = new Map();
iconMap.set('notifier-dingTalk', getImage('/notice-rule/dingtalk.png'));
iconMap.set('notifier-weixin', getImage('/notice-rule/wechat.png'));
iconMap.set('notifier-email', getImage('/notice-rule/email.png'));
iconMap.set('notifier-voice', getImage('/notice-rule/voice.png'));
iconMap.set('notifier-sms', getImage('/notice-rule/sms.png'));
iconMap.set('inside-mail', getImage('/notice-rule/inside-mail.png'));
const current = ref<any>({});
const visible = ref<boolean>(false);
const _visible = ref<boolean>(false);
@ -159,7 +76,7 @@ const onSubscribe = async (obj: any) => {
if (resp.status === 200) {
onlyMessage('操作成功');
emits('refresh');
_visible.value = false
_visible.value = false;
} else {
onlyMessage('操作失败', 'error');
}
@ -177,7 +94,7 @@ const onUnSubscribe = async (obj: any) => {
};
const resp = await save_api(_obj);
if (resp.status === 200) {
_visible.value = false
_visible.value = false;
onlyMessage('操作成功');
emits('refresh');
} else {
@ -223,14 +140,9 @@ const onCheckChange = async (_data: any) => {
}
};
const onDetail = (dt: any) => {
current.value = dt;
_visible.value = true
};
const onSave = (dt: any) => {
onSubscribe(dt);
}
};
</script>
<style lang="less" scoped>
@ -260,35 +172,6 @@ const onSave = (dt: any) => {
.child-item-right {
display: flex;
.box-item {
// margin: 0 5px;
.box-item-img {
width: 50px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
img {
z-index: 1;
cursor: pointer;
}
.disabled {
filter: grayscale(100%);
// filter: brightness(0);
// opacity: 50%;
}
}
.box-item-text {
width: 100%;
text-align: center;
color: #666666;
font-size: 12px;
}
}
}
}
</style>

View File

@ -3,7 +3,7 @@
<div style="padding: 0 10px">
<div class="alert">
<AIcon type="InfoCircleOutlined" />
注意接收人需要有告警配置页面的查询权限才能收到告警类通知
你可以在该页面选择需要订阅的主题及接收通知的方式
</div>
<div class="content-collapse">
<template v-if="dataSource.length">

View File

@ -164,8 +164,9 @@ const onSubmit = async () => {
...params,
firmwareId,
productId,
});
loading.value = false;
}).finally(() => {
loading.value = false;
})
resp.success && emit('change', true);
};

View File

@ -131,6 +131,7 @@ const formData = ref<FormDataType>({
});
const changeType = (value: Array<string>) => {
formData.value.type = value[0];
formData.value.configuration.location = '';
};
const onSubmit = async () => {
@ -168,12 +169,6 @@ const handleCancel = () => {
emit('change', false);
};
watch(
() => formData.value.type,
() => {
formData.value.configuration.location = '';
},
);
watch(
() => props.data,
(value) => {

View File

@ -8,6 +8,7 @@
okText="确定"
@ok="handleSubmit"
@cancel="handleCancel"
:confirmLoading="loading"
>
<j-form ref="formRef" :model="formData" layout="vertical">
<j-row :gutter="10">
@ -208,6 +209,7 @@ const formData = ref({
media_username: '',
});
const loading = ref<boolean>(false)
watch(
() => props.channelData,
(val: any) => {
@ -279,11 +281,11 @@ const validateUrl = async (_rule: Rule, value: string) => {
/**
* 提交
*/
const btnLoading = ref<boolean>(false);
const handleSubmit = () => {
formRef.value
.validate()
.then(async () => {
loading.value = true;
const {
media_url,
media_password,
@ -299,20 +301,20 @@ const handleSubmit = () => {
media_username,
};
}
btnLoading.value = true;
const res = formData.value.id
? await ChannelApi.update(formData.value.id, extraFormData)
: await ChannelApi.save(extraFormData);
btnLoading.value = false;
if (res.success) {
onlyMessage('操作成功');
_vis.value = false;
emit('submit');
} else {
loading.value = false;
onlyMessage('操作失败', 'error');
}
})
.catch((err: any) => {
loading.value = false;
console.log('err: ', err);
});
};

View File

@ -182,6 +182,7 @@ type Emits = {
(e: 'update:productId', data: string): void;
(e: 'close'): void;
(e: 'save', data: Record<string, any>): void;
(e: 'update:password',data:string):void
};
const emit = defineEmits<Emits>();
@ -288,8 +289,10 @@ const handleOk = () => {
.then(async () => {
btnLoading.value = true;
const res = await DeviceApi.saveProduct(formData.value);
console.log(res)
if (res.success) {
emit('update:productId', res.result.id);
emit('update:password', res.result.configuration.access_pwd)
const deployResp = await DeviceApi.deployProductById(
res.result.id,
);

View File

@ -290,6 +290,7 @@
<SaveProduct
v-model:visible="saveProductVis"
v-model:productId="formData.productId"
v-model:password="formData.others.access_pwd"
:channel="formData.channel"
@close="getProductList"
/>

View File

@ -413,6 +413,7 @@
formData.template.templateType
"
placeholder="请选择类型"
@change="onVoiceTemplateTypeChange"
>
<j-select-option
v-for="(item, index) in VOICE_TYPE"
@ -1019,6 +1020,11 @@ watch(
},
);
const onVoiceTemplateTypeChange = () => {
formData.value.template.ttsmessage = undefined
formData.value.variableDefinitions = []
}
/**
* 将需要提取变量的字段值拼接为一个字符串, 用于统一提取变量
*/
@ -1205,6 +1211,8 @@ const getSignsList = async () => {
* 表单提交
*/
const btnLoading = ref<boolean>(false);
const handleSubmit = () => {
// ,
if (

View File

@ -51,8 +51,8 @@
<j-descriptions-item label="告警流水" :span="2"
><div style="max-height: 500px; overflow-y: auto">
<JsonViewer
:value="JSON.parse(data?.alarmInfo || '{}')"
:expand-depth="5"
:value="data"
:expanded="true" :expandDepth="4"
></JsonViewer></div
></j-descriptions-item>
</j-descriptions>
@ -67,6 +67,10 @@ const props = defineProps({
data: Object,
description: String,
});
const data = computed(()=>{
return JSON.parse(props.data?.alarmInfo);
})
const emit = defineEmits(['close']);
const closeModal = () => {
emit('close');

View File

@ -27,7 +27,9 @@
:params="queryParams"
:rowSelection="{
selectedRowKeys: table._selectedRowKeys.value,
onChange: selectChange,
onSelect: selectChange,
onSelectNone: ()=> table._selectedRowKeys.value = [],
onSelectAll: selectAll
}"
:columns="columns"
>
@ -422,14 +424,33 @@ table.init();
// };
// fix: bug#10749
const selectChange = (record: any,selected: boolean,selectedRows: any,) => {
const arr = new Set(table._selectedRowKeys.value);
if(selected){
table._selectedRowKeys.value.push(record?.id)
arr.add(record.id)
}else{
arr.delete(record.id)
}
console.log(record,selected,selectedRows);
table._selectedRowKeys.value = [...arr.values()]
};
const selectAll = (selected: Boolean, selectedRows: any,changeRows:any) => {
if (selected) {
changeRows.map((i: any) => {
if (!table._selectedRowKeys.value.includes(i.id)) {
table._selectedRowKeys.value.push(i.id)
}
})
} else {
const arr = changeRows.map((item: any) => item.id)
const _ids: string[] = [];
table._selectedRowKeys.value.map((i: any) => {
if (!arr.includes(i)) {
_ids.push(i)
}
})
table._selectedRowKeys.value = _ids
}
}
const cancel = () => {
departmentStore.setProductId()
emits('update:visible', false)

View File

@ -265,7 +265,7 @@ init();
.tree {
overflow-y: auto;
overflow-x: hidden;
overflow-x: auto;
.department-tree-item-content {
display: flex;
@ -274,11 +274,13 @@ init();
.title {
flex: 1;
min-width: 80px;
margin-right: 80px;
}
.func-btns {
display: none;
font-size: 14px;
width: 80px;
margin-left: -80px;
:deep(.ant-btn-link) {
padding: 0 4px;
height: 24px;

View File

@ -15,7 +15,13 @@
</j-tooltip>
</div>
<div class="child-item-left-auth" :class="{ disabled: !checked }">
<j-tooltip :title="!update ? '暂无权限,请联系管理员' : ''">
<j-tooltip>
<template #title>
<span v-if="!update">暂无权限请联系管理员</span>
<div v-else>
用于配制外层权限<br />未配置外层权限将执行通知方式中配置的权限<br />配置外层权限后将覆盖所有通知方式中配置的权限
</div>
</template>
<j-button
:disabled="!update || !checked"
type="text"

View File

@ -1,33 +1,75 @@
<template>
<div class="role">
<j-input-search
allowClear
@search="onSearch"
placeholder="请输入名称"
/>
<div class="role-alert">
<j-alert type="info">
<template #message>
<div class="header">
<j-checkbox
:indeterminate="indeterminate"
:checked="checked"
@change="onSelectAll"
>全选</j-checkbox
>
<j-space v-if="_selectedRowKeys.length">
<span>已选择{{ _selectedRowKeys.length }}</span>
<j-button
style="padding: 0; height: 22px"
type="link"
@click="cancelSelect"
>取消选择</j-button
<template v-if="type !== 'add'">
<j-input-search
allowClear
@search="onSearch"
placeholder="请输入名称"
/>
<div class="role-alert">
<j-alert type="info">
<template #message>
<div class="header">
<j-checkbox
:indeterminate="indeterminate"
:checked="checked"
@change="onSelectAll"
>全选</j-checkbox
>
</j-space>
</div>
</template>
</j-alert>
</div>
<j-space v-if="_selectedRowKeys.length">
<span
>已选择{{ _selectedRowKeys.length }}</span
>
<j-button
style="padding: 0; height: 22px"
type="link"
@click="cancelSelect"
>取消选择</j-button
>
</j-space>
</div>
</template>
</j-alert>
</div>
</template>
<template v-else>
<div class="role-alert" style="margin-bottom: 10px;">
<j-alert type="info">
<template #message>
<div style="justify-content: space-between; display: flex; align-items: center;">
<j-input-search
allowClear
@search="onSearch"
placeholder="请输入名称"
style="width: 300px"
/>
<j-space>
<template v-if="_selectedRowKeys.length">
<span
>已选择{{
_selectedRowKeys.length
}}</span
>
<j-button
style="padding: 0; height: 22px"
type="link"
@click="cancelSelect"
>取消选择</j-button
>
</template>
<j-checkbox
:indeterminate="indeterminate"
:checked="checked"
@change="onSelectAll"
>全选</j-checkbox
>
</j-space>
</div>
</template>
</j-alert>
</div>
</template>
<j-scrollbar height="400px">
<j-pro-table
ref="tableRef"
@ -71,8 +113,12 @@ const props = defineProps({
},
gridColumn: {
type: Number,
default: 3
}
default: 3,
},
type: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:modelValue']);

View File

@ -8,11 +8,18 @@
>
<div style="background-color: #f8f9fc; padding: 25px 100px">
<j-steps :current="current" size="small" @change="onChange">
<j-step
v-for="(item, index) in stepList"
:title="item"
:key="item"
>
<j-step v-for="(item, index) in stepList" :key="item">
<template #title>
{{ item
}}<j-tooltip
v-if="index === 4"
>
<template #title>
<span>内层权限配置<br />外层权限已配置的情况下将取外层权限与当前页面分配权限的交集向对应角色发送通知<br />外层权限未配置的情况下将按此处配置的权限发送通知</span>
</template>
<AIcon type="QuestionCircleOutlined"
/></j-tooltip>
</template>
<template #description>
<span v-if="current === index">进行中</span>
<span v-if="current < index">未开始</span>
@ -52,7 +59,11 @@
/>
</template>
<template v-if="current === 4">
<Role v-model="formModel.grant.role.idList" />
<div class="alert">
<AIcon type="InfoCircleOutlined" />
已规定固定收信人的模板在当前页面将被过滤
</div>
<Role type="add" v-model="formModel.grant.role.idList" />
</template>
<template v-if="current === 5">
<div>
@ -235,7 +246,9 @@ const jumpStep = async (val: number) => {
return;
} else {
//
const resp = await Template.getTemplateDetail(formModel.channelConfiguration.templateId);
const resp = await Template.getTemplateDetail(
formModel.channelConfiguration.templateId,
);
if (resp.status === 200) {
variable.value = resp.result?.variableDefinitions || [];
}
@ -244,7 +257,7 @@ const jumpStep = async (val: number) => {
if (val >= 4) {
if (variable.value.length) {
if (_variableDefinitions.value.length) {
if(variableRef.value) {
if (variableRef.value) {
const obj = await variableRef.value?.onSave();
if (obj) {
handleVariable(obj);
@ -253,22 +266,27 @@ const jumpStep = async (val: number) => {
return;
}
} else {
const flag = _variableDefinitions.value.every((item: any) => {
const _value = formModel.channelConfiguration.variables[item.id];
if(!_value) {
return false
}
if(_value.source === 'fixed') {
return _value.value !== undefined
}
if(_value.source === 'upper') {
return _value.upperKey !== undefined
}
return true
})
if(!flag) {
const flag = _variableDefinitions.value.every(
(item: any) => {
const _value =
formModel.channelConfiguration.variables[
item.id
];
if (!_value) {
return false;
}
if (_value.source === 'fixed') {
return _value.value !== undefined;
}
if (_value.source === 'upper') {
return _value.upperKey !== undefined;
}
return true;
},
);
if (!flag) {
onlyMessage('请配置模版变量', 'error');
return
return;
}
}
} else {
@ -333,3 +351,14 @@ const onSave = async () => {
emit('save', formModel);
};
</script>
<style lang="less" scoped>
.alert {
height: 40px;
padding: 0 20px 0 10px;
margin-bottom: 10px;
color: rgba(0, 0, 0, 0.55);
line-height: 40px;
background-color: #f6f6f6;
}
</style>

View File

@ -113,6 +113,5 @@ const selectAll = (selected: Boolean, selectedRows: any,changeRows:any) => {
selectedRowKeys.value = _ids
}
}
</script>