fix: 修改ui
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 776 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 710 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 1015 B |
Before Width: | Height: | Size: 656 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 897 B After Width: | Height: | Size: 1.9 KiB |
|
@ -1,9 +0,0 @@
|
|||
<template>
|
||||
123
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps({
|
||||
// options:
|
||||
})
|
||||
</script>
|
|
@ -150,10 +150,11 @@ const read = (type: '_read' | '_unread') => {
|
|||
|
||||
.list-item-right {
|
||||
width: 100px;
|
||||
padding: 12px 12px 12px 0;
|
||||
padding: 6px 12px 6px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -75,6 +75,10 @@ const onLeft = () => {
|
|||
font-size: 12px;
|
||||
color: #666666;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #EFF2FE;
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,46 @@
|
|||
<template>
|
||||
<j-modal visible title="查看详情" @cancel="emit('close')">
|
||||
<j-descriptions :column="1">
|
||||
<j-descriptions-item label="用户名">{{ userInfos?.username }}</j-descriptions-item>
|
||||
<j-descriptions-item label="账号ID">{{ userInfos?.id }}</j-descriptions-item>
|
||||
<j-descriptions-item label="姓名">{{ userInfos.name }}</j-descriptions-item>
|
||||
<j-descriptions-item label="角色">{{ role }}</j-descriptions-item>
|
||||
<j-descriptions-item label="组织">{{ org }}</j-descriptions-item>
|
||||
<j-descriptions-item label="手机号">{{ userInfos?.telephone || '--' }}</j-descriptions-item>
|
||||
<j-descriptions-item label="邮箱">{{ userInfos?.email || '--' }}</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
<j-modal visible @cancel="emit('close')" :closable="false">
|
||||
<div style="padding: 30px;">
|
||||
<div style="display: flex; margin-bottom: 32px">
|
||||
<j-avatar :size="100" :src="userInfos.avatar"></j-avatar>
|
||||
<div style="margin-left: 24px;">
|
||||
<div class="name">{{ userInfos.name }}</div>
|
||||
<div class="subTitle">用户名: {{ userInfos?.username }}</div>
|
||||
<div class="subTitle">账号ID: {{ userInfos?.id }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<j-descriptions
|
||||
:column="1"
|
||||
:labelStyle="{
|
||||
color: 'rgba(0, 0, 0, 0.6)',
|
||||
width: '70px',
|
||||
}"
|
||||
:contentStyle="{
|
||||
color: '#333333',
|
||||
}"
|
||||
>
|
||||
<j-descriptions-item label="角色">
|
||||
<j-ellipsis :lineClamp="2">
|
||||
{{ role }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="组织">
|
||||
<j-ellipsis :lineClamp="2">
|
||||
{{ org }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="手机号">
|
||||
<j-ellipsis :lineClamp="2">
|
||||
{{ userInfos?.telephone }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="邮箱">
|
||||
<j-ellipsis :lineClamp="2">
|
||||
{{ userInfos?.email }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
</div>
|
||||
<template #footer>
|
||||
<j-button type="primary" @click="emit('close')">关闭</j-button>
|
||||
</template>
|
||||
|
@ -22,12 +54,25 @@ const { userInfos } = useUserInfo();
|
|||
const emit = defineEmits(['close', 'save']);
|
||||
|
||||
const role = computed(() => {
|
||||
const _role = userInfos?.roleList.map((item: any) => item?.name).join(',')
|
||||
return _role || '暂无角色'
|
||||
})
|
||||
const _role = userInfos?.roleList.map((item: any) => item?.name).join(';');
|
||||
return _role || '暂无角色';
|
||||
});
|
||||
|
||||
const org = computed(() => {
|
||||
const _role = userInfos?.orgList.map((item: any) => item?.name).join(',')
|
||||
return _role || '暂无组织'
|
||||
})
|
||||
</script>
|
||||
const _role = userInfos?.orgList.map((item: any) => item?.name).join(';');
|
||||
return _role || '暂无组织';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.name {
|
||||
color: #1D2129;
|
||||
font-weight: 500;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
margin-top: 5px;
|
||||
}
|
||||
</style>
|
|
@ -122,7 +122,7 @@ const handleOk = () => {
|
|||
.then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
onlyMessage('保存成功', 'success');
|
||||
emits('save');
|
||||
emits('save', form.value);
|
||||
}
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
<template>
|
||||
<j-modal
|
||||
visible
|
||||
title="重置密码"
|
||||
@ok="handleOk"
|
||||
width="520px"
|
||||
:confirmLoading="loading"
|
||||
@cancel="emits('close')"
|
||||
>
|
||||
<j-form :model="form" layout="vertical" ref="formRef">
|
||||
<j-form-item
|
||||
label="旧密码"
|
||||
name="oldPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ validator: checkMethods.old, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.oldPassword"
|
||||
placeholder="请输入旧密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="密码"
|
||||
name="newPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ validator: checkMethods.new, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input-password
|
||||
v-model:value="form.newPassword"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="确认密码"
|
||||
name="confirmPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入确认密码' },
|
||||
{ validator: checkMethods.confirm, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input-password
|
||||
v-model:value="form.confirmPassword"
|
||||
placeholder="请再次输入密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
updateMepsd_api,
|
||||
checkOldPassword_api,
|
||||
validateField_api,
|
||||
} from '@/api/account/center';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
|
||||
type formType = {
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
confirmPassword: string;
|
||||
};
|
||||
|
||||
const emits = defineEmits(['save', 'close']);
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<any>();
|
||||
const form = ref<formType>({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
const checkMethods = {
|
||||
old: async (_rule: any, 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: any, 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: any, value: string) => {
|
||||
if (!value) return Promise.reject();
|
||||
else if (form.value.newPassword && value !== form.value.newPassword) {
|
||||
formRef.value?.validate('newPassword');
|
||||
}
|
||||
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(() => {
|
||||
loading.value = true;
|
||||
const params = {
|
||||
oldPassword: form.value.oldPassword,
|
||||
newPassword: form.value.newPassword,
|
||||
};
|
||||
updateMepsd_api(params)
|
||||
.then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
onlyMessage('保存成功', 'success');
|
||||
emits('save');
|
||||
}
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
|
@ -2,66 +2,89 @@
|
|||
<j-modal
|
||||
visible
|
||||
title="重置密码"
|
||||
width="520px"
|
||||
width="615px"
|
||||
:bodyStyle="{
|
||||
padding: 0,
|
||||
}"
|
||||
:confirmLoading="loading"
|
||||
@cancel="emits('close')"
|
||||
>
|
||||
<j-steps :current="current" size="small" progress-dot @change="onChange">
|
||||
<j-step title="验证密码" />
|
||||
<j-step title="设置密码" />
|
||||
<j-step title="二次确认" />
|
||||
</j-steps>
|
||||
<div class="content">
|
||||
<j-form :model="form" layout="vertical" ref="formRef">
|
||||
<j-form-item
|
||||
label="请输入当前密码"
|
||||
name="oldPassword"
|
||||
v-show="current === 0"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入当前密码' },
|
||||
{ validator: checkMethods.old, trigger: 'blur' },
|
||||
]"
|
||||
<div>
|
||||
<div style="background-color: #f8f9fc; padding: 24px">
|
||||
<j-steps
|
||||
:current="current"
|
||||
size="small"
|
||||
progress-dot
|
||||
@change="onChange"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.oldPassword"
|
||||
placeholder="请输入当前密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="请输入新密码"
|
||||
name="newPassword"
|
||||
v-show="current === 1"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入新密码' },
|
||||
{ validator: checkMethods.new, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input-password
|
||||
v-model:value="form.newPassword"
|
||||
placeholder="请输入新密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="请确认新密码"
|
||||
v-show="current === 2"
|
||||
name="confirmPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请确认新密码' },
|
||||
{ validator: checkMethods.confirm, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input-password
|
||||
v-model:value="form.confirmPassword"
|
||||
placeholder="请确认新密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
<j-step :title="item" v-for="(item, index) in list" :key="item">
|
||||
<template #description>
|
||||
<span v-if="current === index">进行中</span>
|
||||
<span v-if="current < index">未开始</span>
|
||||
<span v-if="current > index">已完成</span>
|
||||
</template>
|
||||
</j-step>
|
||||
</j-steps>
|
||||
</div>
|
||||
<div class="content">
|
||||
<j-form :model="form" layout="vertical" ref="formRef">
|
||||
<j-form-item
|
||||
label="当前密码"
|
||||
name="oldPassword"
|
||||
v-show="current === 0"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入当前密码' },
|
||||
{ validator: checkMethods.old, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.oldPassword"
|
||||
placeholder="请输入当前密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="新密码"
|
||||
name="newPassword"
|
||||
v-show="current === 1"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入新密码' },
|
||||
{ validator: checkMethods.new, trigger: 'blur' },
|
||||
]"
|
||||
>
|
||||
<j-input-password
|
||||
v-model:value="form.newPassword"
|
||||
placeholder="请输入新密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="确认新密码"
|
||||
v-show="current === 2"
|
||||
name="confirmPassword"
|
||||
:rules="[
|
||||
{ required: true, message: '请确认新密码' },
|
||||
{
|
||||
validator: checkMethods.confirm,
|
||||
trigger: 'blur',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="form.confirmPassword"
|
||||
placeholder="请确认新密码"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<j-button v-if="current === 0" @click="emits('close')">取消</j-button>
|
||||
<j-button v-if="current === 0" @click="emits('close')"
|
||||
>取消</j-button
|
||||
>
|
||||
<j-button v-if="current === 2" @click="onPrev">上一步</j-button>
|
||||
<j-button type="primary" v-else @click="onNext">下一步</j-button>
|
||||
<j-button v-if="current === 2" type="primary" @click="handleOk">完成</j-button>
|
||||
<j-button v-if="current === 2" type="primary" @click="handleOk"
|
||||
>完成</j-button
|
||||
>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
@ -82,6 +105,8 @@ type formType = {
|
|||
|
||||
const emits = defineEmits(['save', 'close']);
|
||||
|
||||
const list = ['验证密码', '设置密码', '二次确认']
|
||||
|
||||
const loading = ref(false);
|
||||
const formRef = ref<any>();
|
||||
|
||||
|
@ -93,28 +118,28 @@ const form = ref<formType>({
|
|||
const current = ref<number>(0);
|
||||
|
||||
const onPrev = () => {
|
||||
current.value -= 1
|
||||
}
|
||||
current.value -= 1;
|
||||
};
|
||||
|
||||
const jumpStep = (val: number) => {
|
||||
if(val === 1) {
|
||||
if (val === 1) {
|
||||
formRef.value?.validate('oldPassword').then(() => {
|
||||
current.value += 1
|
||||
})
|
||||
} else if(val === 2) {
|
||||
current.value += 1;
|
||||
});
|
||||
} else if (val === 2) {
|
||||
formRef.value?.validate('newPassword').then(() => {
|
||||
current.value += 1
|
||||
})
|
||||
current.value += 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onNext = () => {
|
||||
jumpStep(current.value + 1)
|
||||
}
|
||||
jumpStep(current.value + 1);
|
||||
};
|
||||
|
||||
const onChange = (cur: number) => {
|
||||
jumpStep(cur)
|
||||
}
|
||||
jumpStep(cur);
|
||||
};
|
||||
|
||||
const checkMethods = {
|
||||
old: async (_rule: any, value: string) => {
|
||||
|
@ -141,10 +166,7 @@ const checkMethods = {
|
|||
},
|
||||
confirm: async (_rule: any, value: string) => {
|
||||
if (!value) return Promise.resolve();
|
||||
else if (
|
||||
form.value.newPassword &&
|
||||
value !== form.value.newPassword
|
||||
) {
|
||||
else if (form.value.newPassword && value !== form.value.newPassword) {
|
||||
return Promise.reject('两次密码输入不一致');
|
||||
}
|
||||
try {
|
||||
|
@ -177,8 +199,8 @@ const handleOk = () => {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="less">
|
||||
.content {
|
||||
padding: 20px 50px;
|
||||
padding: 30px 50px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { getMe_api, getView_api, setView_api } from '@/api/home';
|
||||
import { getImage, onlyMessage } from '@/utils/comm';
|
||||
|
||||
const currentView = ref<string>('');
|
||||
const isApiUser = ref<boolean>();
|
||||
|
||||
|
@ -93,6 +94,11 @@ onMounted(() => {
|
|||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 68px;
|
||||
|
||||
button {
|
||||
background-color: @primary-2;
|
||||
color: @primary-color-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -2,75 +2,72 @@
|
|||
<j-modal
|
||||
visible
|
||||
title="详情"
|
||||
width="1000px"
|
||||
@ok="emits('update:visible', false)"
|
||||
width="754px"
|
||||
@cancel="emits('update:visible', false)"
|
||||
class="view-dialog-container"
|
||||
>
|
||||
<template v-if="type === 'alarm'">
|
||||
<j-row v-if="data?.topicProvider === 'alarm-device'">
|
||||
<j-col :span="4" class="label">告警设备</j-col>
|
||||
<j-col :span="8" class="value">
|
||||
{{ data?.targetName || '' }}
|
||||
</j-col>
|
||||
<j-col :span="4" class="label">设备ID</j-col>
|
||||
<j-col :span="8" class="value">
|
||||
{{ data?.targetId || '' }}
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-row>
|
||||
<j-col :span="4" class="label">告警名称</j-col>
|
||||
<j-col :span="8" class="value">
|
||||
{{ data?.alarmName || data?.alarmConfigName || '' }}
|
||||
</j-col>
|
||||
<j-col :span="4" class="label">告警时间</j-col>
|
||||
<j-col :span="8" class="value">
|
||||
{{ dayjs(data?.alarmTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</j-col>
|
||||
|
||||
<j-col :span="4" class="label">告警级别</j-col>
|
||||
<j-col :span="8" class="value">
|
||||
{{
|
||||
(levelList.length > 0 && getLevelLabel(data.level)) ||
|
||||
''
|
||||
}}
|
||||
</j-col>
|
||||
<j-col :span="4" class="label">告警说明</j-col>
|
||||
<j-col :span="8" class="value">{{
|
||||
data?.description || ''
|
||||
}}</j-col>
|
||||
|
||||
<j-col
|
||||
:span="4"
|
||||
class="label"
|
||||
style="display: flex; height: 440px; align-items: center"
|
||||
>告警流水</j-col
|
||||
>
|
||||
<j-col
|
||||
:span="20"
|
||||
class="value"
|
||||
style="max-height: 440px; overflow: auto"
|
||||
>
|
||||
<JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" />
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-descriptions
|
||||
:column="2"
|
||||
:contentStyle="{
|
||||
color: '#333333',
|
||||
}"
|
||||
:labelStyle="{
|
||||
color: 'rgba(0, 0, 0, 0.6)',
|
||||
width: '72px',
|
||||
}"
|
||||
>
|
||||
<template v-if="data?.topicProvider === 'alarm-device'">
|
||||
<j-descriptions-item label="告警设备">
|
||||
<j-ellipsis>{{ data?.targetName || ''}}</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="设备ID">
|
||||
<j-ellipsis>
|
||||
{{ data?.targetId || '' }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
</template>
|
||||
<j-descriptions-item label="告警名称">
|
||||
<j-ellipsis>
|
||||
{{ data?.alarmName || data?.alarmConfigName || '' }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="告警时间">{{
|
||||
dayjs(data?.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="告警级别">{{
|
||||
(levelList.length > 0 && getLevelLabel(data.level)) || ''
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="告警说明">
|
||||
<j-ellipsis>
|
||||
{{ data?.description || '' }}
|
||||
</j-ellipsis>
|
||||
</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
<div>
|
||||
<div class="label">告警流水:</div>
|
||||
<div style="padding: 10px; background-color: #fafafa">
|
||||
<j-scrollbar height="200px">
|
||||
<JsonViewer
|
||||
style="background-color: #fafafa"
|
||||
:value="JSON.parse(data?.alarmInfo || '{}')"
|
||||
/>
|
||||
</j-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<j-row>
|
||||
<j-col
|
||||
:span="4"
|
||||
class="label"
|
||||
style="display: flex; height: 440px; align-items: center"
|
||||
>通知流水</j-col
|
||||
>
|
||||
<j-col
|
||||
:span="20"
|
||||
class="value"
|
||||
style="max-height: 440px; overflow: auto"
|
||||
>
|
||||
<JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" />
|
||||
</j-col>
|
||||
</j-row>
|
||||
<div>
|
||||
<div class="label">通知流水:</div>
|
||||
<div style="padding: 10px; background-color: #fafafa">
|
||||
<j-scrollbar height="200px">
|
||||
<JsonViewer :value="JSON.parse(data?.alarmInfo || '{}')" />
|
||||
</j-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<j-button type="primary" @click="emits('update:visible', false)">确定</j-button>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
@ -110,14 +107,14 @@ const getLevelLabel = (id: number) => {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.view-dialog-container {
|
||||
.ant-row {
|
||||
.ant-col {
|
||||
padding: 16px 24px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
.label {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.label {
|
||||
width: 100%;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
<template>
|
||||
<j-modal :width="'900px'" visible @cancel="emit('close')">
|
||||
<template v-if="getType === 'notifier-dingTalk'">
|
||||
<j-spin :spinning="loading">
|
||||
<div class="code" style="height: 600px;">
|
||||
<iframe
|
||||
id="notifier_iframe"
|
||||
class="code-item"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:src="url"
|
||||
v-if="!loading"
|
||||
></iframe>
|
||||
</div>
|
||||
</j-spin>
|
||||
</template>
|
||||
<template v-else-if="getType === 'notifier-weixin'">
|
||||
<j-spin :spinning="loading">
|
||||
<div class="code" style="height: 450px">
|
||||
<iframe
|
||||
id="notifier_iframe"
|
||||
class="code-item"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:src="url"
|
||||
v-if="!loading"
|
||||
></iframe>
|
||||
</div>
|
||||
</j-spin>
|
||||
</template>
|
||||
<template #footer>
|
||||
<j-button @click="emit('close')">关闭</j-button>
|
||||
<!-- <j-button type="primary" @click="emit('close')">确定</j-button> -->
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
bindThirdParty,
|
||||
getDingTalkOAuth2,
|
||||
getUserBind,
|
||||
getWechatOAuth2,
|
||||
} from '@/api/account/notificationSubscription';
|
||||
|
||||
const emit = defineEmits(['close', 'save']);
|
||||
const props = defineProps({
|
||||
data: {
|
||||
// 外层数据
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
current: {
|
||||
// 当前的通道
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const url = ref<string>('');
|
||||
const loading = ref<boolean>(false);
|
||||
|
||||
const getType = computed(() => {
|
||||
return props.current?.channelProvider;
|
||||
});
|
||||
|
||||
const onBindHandle = (
|
||||
type: 'notifier-weixin' | 'notifier-dingTalk',
|
||||
code: string,
|
||||
) => {
|
||||
getUserBind(type === 'notifier-dingTalk' ? 'dingtalk' : 'wechat', {
|
||||
authCode: code,
|
||||
configId: props.current?.channelConfiguration.notifierId,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
const _bindCode = (resp?.result || '') as string;
|
||||
if (_bindCode) {
|
||||
bindThirdParty(
|
||||
type,
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
_bindCode,
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
// 订阅
|
||||
emit('save', props.current);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const updateIframeStyle = () => {
|
||||
const iframe = document.querySelector(
|
||||
'#notifier_iframe',
|
||||
) as HTMLIFrameElement;
|
||||
iframe.onload = () => {
|
||||
const currentUrl = iframe?.contentWindow?.location?.search || '';
|
||||
let authCode = '';
|
||||
if (currentUrl.startsWith('?')) {
|
||||
currentUrl
|
||||
.substring(1)
|
||||
.split('&')
|
||||
.map((item) => {
|
||||
if (
|
||||
props.current?.channelProvider === 'notifier-dingTalk'
|
||||
) {
|
||||
if (item.split('=')?.[0] === 'authCode') {
|
||||
authCode = item.split('=')?.[1] || '';
|
||||
}
|
||||
} else {
|
||||
if (item.split('=')?.[0] === 'code') {
|
||||
authCode = item.split('=')?.[1] || '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (authCode) {
|
||||
loading.value = true;
|
||||
onBindHandle(props.current?.channelProvider, authCode);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleSearch = async () => {
|
||||
if (props.current?.channelProvider === 'notifier-weixin') {
|
||||
loading.value = true;
|
||||
const resp = await getWechatOAuth2(
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
props.current?.channelConfiguration.templateId,
|
||||
location.href
|
||||
).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
url.value = resp.result as string;
|
||||
nextTick(() => {
|
||||
updateIframeStyle();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (props.current?.channelProvider === 'notifier-dingTalk') {
|
||||
loading.value = true;
|
||||
const resp = await getDingTalkOAuth2(
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
location.href,
|
||||
).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
url.value = resp.result as string;
|
||||
nextTick(() => {
|
||||
updateIframeStyle();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.current,
|
||||
() => {
|
||||
handleSearch();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tip {
|
||||
width: 100%;
|
||||
margin: 80px 0;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #7f7f7f;
|
||||
}
|
||||
|
||||
.code {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
justify-content: center;
|
||||
|
||||
.code-item {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<j-modal visible @cancel="emit('close')">
|
||||
<j-modal width="350px" visible @cancel="emit('close')" :footer="null">
|
||||
<template v-if="getType === 'notifier-dingTalk'">
|
||||
<!-- <div class="tip">请先绑定钉钉账号</div> -->
|
||||
<div class="tip">暂未开发</div>
|
||||
</template>
|
||||
<template v-else-if="getType === 'notifier-weixin'">
|
||||
<!-- <div class="tip">请先绑定企业微信账号</div> -->
|
||||
<div class="tip">暂未开发</div>
|
||||
</template>
|
||||
<template v-else-if="getType === 'notifier-email'">
|
||||
<div class="tip"> 绑定账号:{{ user.userInfos?.email }}</div>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<template v-else>
|
||||
<div class="tip">绑定账号:{{ user.userInfos?.telephone }}</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="btn">
|
||||
<j-button @click="emit('unsubscribe', current)">取消订阅</j-button>
|
||||
<j-button
|
||||
@click="onBind"
|
||||
|
@ -27,7 +27,7 @@
|
|||
>更换绑定账号</j-button
|
||||
>
|
||||
<j-button v-else @click="emit('close')">确定</j-button>
|
||||
</template>
|
||||
</div>
|
||||
</j-modal>
|
||||
<EditInfo
|
||||
v-if="editInfoVisible"
|
||||
|
@ -102,19 +102,12 @@ watch(
|
|||
<style lang="less" scoped>
|
||||
.tip {
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
// font-size: 14px;
|
||||
// color: #7f7f7f;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.code {
|
||||
width: 100%;
|
||||
.btn {
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
justify-content: center;
|
||||
|
||||
.code-item {
|
||||
border: none;
|
||||
}
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
|
@ -7,7 +7,7 @@
|
|||
<div class="child-item-left-auth" v-if="data?.description">
|
||||
<j-tooltip :title="data.description">
|
||||
<AIcon
|
||||
style="font-size: 16px"
|
||||
style="font-size: 16px; color: rgba(0, 0, 0, .3)"
|
||||
type="ExclamationCircleOutlined"
|
||||
/>
|
||||
</j-tooltip>
|
||||
|
@ -86,7 +86,9 @@
|
|||
</j-dropdown>
|
||||
</div>
|
||||
<div class="box-item-text">
|
||||
{{ slotProps?.name }}
|
||||
<j-ellipsis style="width: 50px;">
|
||||
{{ slotProps?.name }}
|
||||
</j-ellipsis>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -245,7 +247,7 @@ const onSave = (dt: any) => {
|
|||
|
||||
div {
|
||||
display: flex;
|
||||
margin-right: 30px;
|
||||
margin-right: 8px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
@ -260,7 +262,7 @@ const onSave = (dt: any) => {
|
|||
display: flex;
|
||||
|
||||
.box-item {
|
||||
margin-left: 10px;
|
||||
// margin: 0 5px;
|
||||
.box-item-img {
|
||||
width: 50px;
|
||||
display: flex;
|
||||
|
|
|
@ -1,34 +1,10 @@
|
|||
<template>
|
||||
<j-modal width="900px" visible @cancel="emit('close')">
|
||||
<j-modal :width="'384px'" visible @cancel="emit('close')" :footer="null">
|
||||
<template v-if="getType === 'notifier-dingTalk'">
|
||||
<!-- <div class="tip">请先绑定钉钉账号</div> -->
|
||||
<j-spin :spinning="loading">
|
||||
<div class="code" style="height: 600px;">
|
||||
<iframe
|
||||
id="notifier_iframe"
|
||||
class="code-item"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:src="url"
|
||||
v-if="!loading"
|
||||
></iframe>
|
||||
</div>
|
||||
</j-spin>
|
||||
<div class="tip">请先绑定钉钉账号</div>
|
||||
</template>
|
||||
<template v-else-if="getType === 'notifier-weixin'">
|
||||
<!-- <div class="tip">请先绑定企业微信账号</div> -->
|
||||
<j-spin :spinning="loading">
|
||||
<div class="code" style="height: 450px">
|
||||
<iframe
|
||||
id="notifier_iframe"
|
||||
class="code-item"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:src="url"
|
||||
v-if="!loading"
|
||||
></iframe>
|
||||
</div>
|
||||
</j-spin>
|
||||
<div class="tip">请先绑定企业微信账号</div>
|
||||
</template>
|
||||
<template v-else-if="getType === 'notifier-email'">
|
||||
<div class="tip">请先绑定邮箱</div>
|
||||
|
@ -36,43 +12,37 @@
|
|||
<template v-else>
|
||||
<div class="tip">请先绑定手机号</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<j-button @click="emit('close')">取消</j-button>
|
||||
<j-button
|
||||
@click="onBind"
|
||||
type="primary"
|
||||
v-if="
|
||||
[
|
||||
'notifier-email',
|
||||
'notifier-voice',
|
||||
'notifier-sms',
|
||||
].includes(getType)
|
||||
"
|
||||
>立即绑定</j-button
|
||||
>
|
||||
<j-button v-else @click="emit('close')">确定</j-button>
|
||||
</template>
|
||||
<div class="btn">
|
||||
<j-space>
|
||||
<j-button @click="emit('close')">取消</j-button>
|
||||
<j-button @click="onBind" type="primary">立即绑定</j-button>
|
||||
</j-space>
|
||||
</div>
|
||||
<EditInfo
|
||||
v-if="editInfoVisible"
|
||||
:data="user.userInfos"
|
||||
@close="editInfoVisible = false"
|
||||
@save="onSave"
|
||||
/>
|
||||
<Bind
|
||||
@close="visible = false"
|
||||
v-if="visible"
|
||||
:data="props.data"
|
||||
:current="current"
|
||||
@save="onBindSave"
|
||||
/>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
bindThirdParty,
|
||||
getDingTalkOAuth2,
|
||||
getUserBind,
|
||||
getWechatOAuth2,
|
||||
} from '@/api/account/notificationSubscription';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import EditInfo from '../../EditInfo/index.vue';
|
||||
import Bind from './Bind.vue';
|
||||
|
||||
const user = useUserInfo();
|
||||
const emit = defineEmits(['close', 'save']);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
// 外层数据
|
||||
|
@ -87,146 +57,42 @@ const props = defineProps({
|
|||
});
|
||||
|
||||
const editInfoVisible = ref<boolean>(false);
|
||||
const url = ref<string>('');
|
||||
const loading = ref<boolean>(false);
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
const getType = computed(() => {
|
||||
return props.current?.channelProvider;
|
||||
});
|
||||
|
||||
const onBind = () => {
|
||||
editInfoVisible.value = true;
|
||||
if (!['notifier-dingTalk', 'notifier-weixin'].includes(getType.value)) {
|
||||
editInfoVisible.value = true;
|
||||
} else {
|
||||
visible.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
const onSave = (info: any) => {
|
||||
editInfoVisible.value = false;
|
||||
user.getUserInfo();
|
||||
emit('save', props.current);
|
||||
if((getType.value === 'notifier-email' && info.email) || (['notifier-voice', 'notifier-sms'].includes(getType.value) && info.telephone)) {
|
||||
emit('save', props.current);
|
||||
emit('close');
|
||||
}
|
||||
};
|
||||
|
||||
const onBindSave = (cur: any) => {
|
||||
visible.value = false;
|
||||
emit('save', cur);
|
||||
emit('close');
|
||||
};
|
||||
|
||||
const onBindHandle = (
|
||||
type: 'notifier-weixin' | 'notifier-dingTalk',
|
||||
code: string,
|
||||
) => {
|
||||
getUserBind(type === 'notifier-dingTalk' ? 'dingtalk' : 'wechat', {
|
||||
authCode: code,
|
||||
configId: props.current?.channelConfiguration.notifierId,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
const _bindCode = (resp?.result || '') as string;
|
||||
if (_bindCode) {
|
||||
bindThirdParty(
|
||||
type,
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
_bindCode,
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
// 订阅
|
||||
emit('save', props.current);
|
||||
emit('close');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const updateIframeStyle = () => {
|
||||
const iframe = document.querySelector(
|
||||
'#notifier_iframe',
|
||||
) as HTMLIFrameElement;
|
||||
iframe.onload = () => {
|
||||
const currentUrl = iframe?.contentWindow?.location?.search || '';
|
||||
console.log(currentUrl)
|
||||
let authCode = '';
|
||||
if (currentUrl.startsWith('?')) {
|
||||
currentUrl
|
||||
.substring(1)
|
||||
.split('&')
|
||||
.map((item) => {
|
||||
if (
|
||||
props.current?.channelProvider === 'notifier-dingTalk'
|
||||
) {
|
||||
if (item.split('=')?.[0] === 'authCode') {
|
||||
authCode = item.split('=')?.[1] || '';
|
||||
}
|
||||
} else {
|
||||
if (item.split('=')?.[0] === 'code') {
|
||||
authCode = item.split('=')?.[1] || '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (authCode) {
|
||||
loading.value = true;
|
||||
onBindHandle(props.current?.channelProvider, authCode);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleSearch = async () => {
|
||||
if (props.current?.channelProvider === 'notifier-weixin') {
|
||||
loading.value = true;
|
||||
const resp = await getWechatOAuth2(
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
props.current?.channelConfiguration.templateId,
|
||||
location.href
|
||||
).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
url.value = resp.result as string;
|
||||
nextTick(() => {
|
||||
updateIframeStyle();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (props.current?.channelProvider === 'notifier-dingTalk') {
|
||||
loading.value = true;
|
||||
const resp = await getDingTalkOAuth2(
|
||||
props.current?.channelConfiguration.notifierId,
|
||||
location.href,
|
||||
).finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
url.value = resp.result as string;
|
||||
nextTick(() => {
|
||||
updateIframeStyle();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.current,
|
||||
() => {
|
||||
handleSearch();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tip {
|
||||
width: 100%;
|
||||
margin: 80px 0;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #7f7f7f;
|
||||
margin: 30px 0;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.code {
|
||||
|
@ -234,9 +100,10 @@ watch(
|
|||
display: flex;
|
||||
margin-top: 30px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.code-item {
|
||||
border: none;
|
||||
}
|
||||
.btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-spin :spinning="loading">
|
||||
<div>
|
||||
<div style="padding: 0 10px">
|
||||
<div class="alert">
|
||||
<AIcon type="InfoCircleOutlined" />
|
||||
你可以在该页面选择需要订阅的主题及接收通知的方式。
|
||||
|
@ -24,9 +24,6 @@
|
|||
class="custom"
|
||||
:header="item.name"
|
||||
>
|
||||
<template #header
|
||||
><h3>{{ item.name }}</h3></template
|
||||
>
|
||||
<div class="child">
|
||||
<template
|
||||
v-for="child in item.children"
|
||||
|
@ -116,9 +113,8 @@ onMounted(() => {
|
|||
height: 40px;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
color: rgba(0, 0, 0, 0.55);
|
||||
color: #999999;
|
||||
line-height: 40px;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
.custom {
|
||||
background: #F7F8FA;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
:img="cropperImg"
|
||||
@cancel="cropperVisible = false"
|
||||
@ok="saveImage"
|
||||
title="更换头像"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ export const USER_CENTER_MENU_DATA = {
|
|||
url: '/account/center',
|
||||
sortIndex: 9999,
|
||||
granted: true,
|
||||
owner: 'iot',
|
||||
buttons: [
|
||||
{
|
||||
id: USER_CENTER_MENU_BUTTON_CODE,
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<template>
|
||||
<j-modal
|
||||
:width="810"
|
||||
visible
|
||||
title="选择应用类型"
|
||||
@cancel="emit('close')"
|
||||
@ok="onSave"
|
||||
>
|
||||
<ApplyList v-model:photoUrl="photoUrl" :options="typeOptions" v-model:value="type" />
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { queryType } from '@/api/system/apply';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import ApplyList from './components/ApplyList/index.vue';
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const type = ref('');
|
||||
const photoUrl = ref('');
|
||||
const typeOptions = ref<any[]>([]);
|
||||
|
||||
const onSave = () => {
|
||||
if(type.value){
|
||||
menuStory.jumpPage('system/Apply/Save', {}, { provider: type.value, photoUrl: photoUrl.value });
|
||||
} else {
|
||||
onlyMessage('请先选择应用类型', 'error')
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
queryType().then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
const arr = resp.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.provider,
|
||||
}));
|
||||
typeOptions.value = arr;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.type-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px 24px;
|
||||
width: 100%;
|
||||
|
||||
.type-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 172px;
|
||||
border: 1px solid #e0e4e8;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
.type-item-title {
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.type-item-image {
|
||||
width: 106px;
|
||||
margin: 16px 33px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: @primary-color-hover;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: @primary-color-active;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.notify-type-item {
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
color: initial;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -40,7 +40,7 @@
|
|||
:options="typeOptions"
|
||||
v-model:photoUrl="form.data.logoUrl"
|
||||
v-model:value="form.data.provider"
|
||||
:disabled="!!routeQuery.id"
|
||||
:disabled="!!routeQuery.id || !!routeQuery?.provider"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
|
@ -53,13 +53,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<j-checkbox-group
|
||||
<j-check-button
|
||||
v-model:value="form.data.integrationModes"
|
||||
:options="joinOptions"
|
||||
:multiple="true"
|
||||
/>
|
||||
</j-form-item>
|
||||
|
||||
<j-collapse style="margin-bottom: 20px">
|
||||
<j-collapse style="margin-bottom: 20px;">
|
||||
<j-collapse-panel
|
||||
v-for="(item, index) in form.data.integrationModes"
|
||||
:key="item + index"
|
||||
|
@ -1417,7 +1418,7 @@ import FormLabel from './FormLabel.vue';
|
|||
import RequestTable from './RequestTable.vue';
|
||||
import MenuDialog from '../../componenets/MenuDialog.vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import type { formType, dictType, optionsType } from '../typing';
|
||||
import type { formType, dictType, optionsType, applyType } from '../typing';
|
||||
import { getRoleList_api } from '@/api/system/user';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { randomString } from '@/utils/utils';
|
||||
|
@ -1554,32 +1555,39 @@ const paramsValidator = () => {
|
|||
paramsValid.value ? resolve('') : reject('请输入完整的请求参数');
|
||||
});
|
||||
};
|
||||
const getType = () => {
|
||||
queryType().then((resp: any) => {
|
||||
if (resp.status === 200) {
|
||||
const arr = resp.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.provider,
|
||||
integrationModes: item.integrationModes?.map((i: any) => {
|
||||
return {
|
||||
label: i.text,
|
||||
value: i.value,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
typeOptions.value = arr;
|
||||
}
|
||||
});
|
||||
const getType = async () => {
|
||||
const resp: any = await queryType();
|
||||
if (resp.status === 200) {
|
||||
const arr = resp.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.provider,
|
||||
integrationModes: item.integrationModes?.map((i: any) => {
|
||||
return {
|
||||
label: i.text,
|
||||
value: i.value,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
typeOptions.value = arr;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getType();
|
||||
onMounted(async () => {
|
||||
await getType();
|
||||
getRoleIdList();
|
||||
getOrgIdList();
|
||||
if (routeQuery.id) {
|
||||
getInfo(routeQuery.id as string);
|
||||
}
|
||||
|
||||
if(routeQuery.provider){
|
||||
form.data.provider = routeQuery?.provider as applyType;
|
||||
if(routeQuery.photoUrl) {
|
||||
form.data.logoUrl = routeQuery?.photoUrl as string;
|
||||
}
|
||||
typeOptions.value = typeOptions.value.filter((i: any) => {
|
||||
return i.value === routeQuery.provider;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 接入方式的选项
|
||||
|
|
|
@ -20,8 +20,8 @@ export type optionsType = {
|
|||
export type formType = {
|
||||
id?:string,
|
||||
name: string;
|
||||
provider: applyType;
|
||||
logoUrl: string,
|
||||
provider: applyType | undefined;
|
||||
logoUrl: string | undefined,
|
||||
integrationModes: string[];
|
||||
config?: string;
|
||||
description: string;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<PermissionButton
|
||||
:hasPermission="`${permission}:add`"
|
||||
type="primary"
|
||||
@click="() => table.toSave()"
|
||||
@click="() => table.toAdd()"
|
||||
>
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</PermissionButton>
|
||||
|
@ -134,7 +134,7 @@
|
|||
</j-tooltip>
|
||||
</template>
|
||||
|
||||
<template #mark>
|
||||
<!-- <template #mark>
|
||||
<AIcon
|
||||
type="EyeOutlined"
|
||||
style="font-size: 24px"
|
||||
|
@ -142,7 +142,7 @@
|
|||
() => table.toSave(slotProps.id, true)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</template> -->
|
||||
</CardBox>
|
||||
</template>
|
||||
|
||||
|
@ -190,6 +190,7 @@
|
|||
@refresh="table.refresh"
|
||||
/>
|
||||
</div>
|
||||
<Add v-if="visible" @close="visible = false" />
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -206,37 +207,13 @@ import { getImage } from '@/utils/comm';
|
|||
import { useMenuStore } from '@/store/menu';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import BadgeStatus from '@/components/BadgeStatus/index.vue';
|
||||
import Add from './Save/Add.vue';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const permission = 'system/Apply';
|
||||
// const typeOptions = [
|
||||
// {
|
||||
// label: '内部独立应用',
|
||||
// value: 'internal-standalone',
|
||||
// },
|
||||
// {
|
||||
// label: '微信网站应用',
|
||||
// value: 'wechat-webapp',
|
||||
// },
|
||||
// {
|
||||
// label: '内部集成应用',
|
||||
// value: 'internal-integrated',
|
||||
// },
|
||||
// {
|
||||
// label: '钉钉企业内部应用',
|
||||
// value: 'dingtalk-ent-app',
|
||||
// },
|
||||
// {
|
||||
// label: '第三方应用',
|
||||
// value: 'third-party',
|
||||
// },
|
||||
// {
|
||||
// label: '小程序应用',
|
||||
// value: 'wechat-miniapp',
|
||||
// },
|
||||
// ];
|
||||
|
||||
const typeOptions = ref<any[]>([])
|
||||
const visible = ref<boolean>(false)
|
||||
|
||||
onMounted(() => {
|
||||
queryType().then((resp: any) => {
|
||||
|
@ -329,6 +306,9 @@ const table = {
|
|||
refresh: () => {
|
||||
tableRef.value.reload(queryParams.value);
|
||||
},
|
||||
toAdd: () => {
|
||||
visible.value = true
|
||||
},
|
||||
toSave: (id?: string, view = false) => {
|
||||
if (id) menuStory.jumpPage('system/Apply/Save', {}, { id, view });
|
||||
else menuStory.jumpPage('system/Apply/Save');
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<j-modal
|
||||
:width="900"
|
||||
:width="540"
|
||||
visible
|
||||
title="权限控制"
|
||||
@cancel="emit('close')"
|
||||
@ok="onSave"
|
||||
>
|
||||
<Role v-model="_selectedRowKeys" />
|
||||
<Role v-model="_selectedRowKeys" :gridColumn="1" />
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
|
@ -29,10 +29,6 @@ watchEffect(() => {
|
|||
});
|
||||
|
||||
const onSave = () => {
|
||||
// if(_selectedRowKeys.value.length) {
|
||||
emit('save', _selectedRowKeys.value);
|
||||
// } else {
|
||||
// onlyMessage('请配置角色权限', 'error')
|
||||
// }
|
||||
};
|
||||
</script>
|
|
@ -87,7 +87,7 @@
|
|||
</template>
|
||||
</j-dropdown>
|
||||
<div class="box-item-text">
|
||||
{{ slotProps?.name }}
|
||||
<j-ellipsis>{{ slotProps?.name }}</j-ellipsis>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -453,8 +453,13 @@ const onSave = (_data: any) => {
|
|||
align-items: center;
|
||||
|
||||
.box-item {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
width: 48px;
|
||||
margin: 0 2px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.box-item-img {
|
||||
background-color: #fff;
|
||||
width: 32px;
|
||||
|
@ -474,7 +479,6 @@ const onSave = (_data: any) => {
|
|||
|
||||
.box-item-add {
|
||||
cursor: pointer;
|
||||
margin-left: 16px;
|
||||
background-color: #f8f9fc;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
|
|
|
@ -1,37 +1,63 @@
|
|||
<template>
|
||||
<pro-search
|
||||
style="padding: 0"
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="category"
|
||||
@search="onSearch"
|
||||
/>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="queryRoleList"
|
||||
model="TABLE"
|
||||
:params="params"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
:scroll="{ y: 500 }"
|
||||
:defaultParams="{
|
||||
// pageSize: 10,
|
||||
sorts: [
|
||||
{ name: 'createTime', order: 'desc' },
|
||||
{ name: 'id', order: 'desc' },
|
||||
],
|
||||
}"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onSelect: onSelect,
|
||||
onSelectAll: onSelectAll,
|
||||
onSelectNone: cancelSelect,
|
||||
}"
|
||||
>
|
||||
<!-- <template #headerTitle>
|
||||
<j-checkbox v-model:checked="checked">全选</j-checkbox>
|
||||
</template> -->
|
||||
</j-pro-table>
|
||||
<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
|
||||
>
|
||||
</j-space>
|
||||
</div>
|
||||
</template>
|
||||
</j-alert>
|
||||
</div>
|
||||
<j-scrollbar height="400px">
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="queryRoleList"
|
||||
model="CARD"
|
||||
:params="params"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
:gridColumn="gridColumn"
|
||||
:alertRender="false"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
}"
|
||||
>
|
||||
<template #card="slotProps">
|
||||
<div class="card">
|
||||
<j-checkbox
|
||||
:checked="_selectedRowKeys.includes(slotProps?.id)"
|
||||
@change="(e) => onSelect(e, slotProps)"
|
||||
>
|
||||
<j-ellipsis>{{ slotProps.name }}</j-ellipsis>
|
||||
</j-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</j-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -43,12 +69,35 @@ const props = defineProps({
|
|||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
gridColumn: {
|
||||
type: Number,
|
||||
default: 2
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const params = ref<any>();
|
||||
const _selectedRowKeys = ref<string[]>([]);
|
||||
const tableRef = ref();
|
||||
|
||||
const dataSource = computed(() => {
|
||||
return tableRef.value?._dataSource || [];
|
||||
});
|
||||
|
||||
const indeterminate = computed(() => {
|
||||
return (
|
||||
dataSource.value.some((item: any) => {
|
||||
return _selectedRowKeys.value.includes(item.id);
|
||||
}) && !checked.value
|
||||
);
|
||||
});
|
||||
|
||||
const checked = computed(() => {
|
||||
return dataSource.value.every((item: any) => {
|
||||
return _selectedRowKeys.value.includes(item.id);
|
||||
});
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
_selectedRowKeys.value = props?.modelValue || [];
|
||||
|
@ -79,8 +128,16 @@ const columns = [
|
|||
},
|
||||
];
|
||||
|
||||
const onSearch = (e: any) => {
|
||||
params.value = e;
|
||||
const onSearch = (val: any) => {
|
||||
params.value = {
|
||||
terms: [
|
||||
{
|
||||
column: 'name',
|
||||
termType: 'like',
|
||||
value: `%${val}%`,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
// 取消全选
|
||||
|
@ -89,8 +146,9 @@ const cancelSelect = () => {
|
|||
emit('update:modelValue', []);
|
||||
};
|
||||
|
||||
const onSelect = (record: any, selected: boolean) => {
|
||||
const onSelect = (e: any, record: any) => {
|
||||
const _set = new Set(_selectedRowKeys.value);
|
||||
const selected = e.target.checked;
|
||||
if (selected) {
|
||||
_set.add(record.id);
|
||||
} else {
|
||||
|
@ -99,9 +157,10 @@ const onSelect = (record: any, selected: boolean) => {
|
|||
emit('update:modelValue', [..._set.values()]);
|
||||
};
|
||||
|
||||
const onSelectAll = (selected: boolean, _: any[], _keys: any[]) => {
|
||||
const onSelectAll = (e: any) => {
|
||||
const selected = e.target.checked;
|
||||
const _set = new Set(_selectedRowKeys.value);
|
||||
const arr = _keys.map((item: any) => item?.id);
|
||||
const arr = dataSource.value.map((item: any) => item?.id);
|
||||
if (selected) {
|
||||
arr.map((i: any) => {
|
||||
_set.add(i);
|
||||
|
@ -113,4 +172,28 @@ const onSelectAll = (selected: boolean, _: any[], _keys: any[]) => {
|
|||
}
|
||||
emit('update:modelValue', [..._set.values()]);
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.role {
|
||||
:deep(.jtable-content) {
|
||||
padding: 2px 0 16px 0;
|
||||
}
|
||||
:deep(.jtable-card-items) {
|
||||
grid-gap: 2px !important;
|
||||
}
|
||||
|
||||
.role-alert {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.card {
|
||||
width: 100%;
|
||||
background-color: #f8f9fc;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-spin :spinning="loading">
|
||||
<div class="notify-type-warp" :class="{ disabled: disabled }">
|
||||
<div class="notify-type-warp">
|
||||
<div
|
||||
:key="item.id"
|
||||
v-for="item in options"
|
||||
|
@ -9,7 +9,7 @@
|
|||
@click="onSelect(item.value, item.label)"
|
||||
>
|
||||
<div class="notify-type-item-image">
|
||||
<img :width="106" :src="item.iconUrl" />
|
||||
<img :width="64" :src="item.iconUrl" />
|
||||
</div>
|
||||
<div class="notify-type-item-title">{{item.label}}</div>
|
||||
</div>
|
||||
|
@ -80,53 +80,40 @@ onMounted(() => {
|
|||
.notify-type-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px 24px;
|
||||
width: 100%;
|
||||
padding: 50px 200px;
|
||||
gap: 16px 24px;
|
||||
|
||||
.notify-type-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 172px;
|
||||
border: 1px solid #e0e4e8;
|
||||
border-radius: 2px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
width: 96px;
|
||||
padding: 8px 16px;
|
||||
|
||||
.notify-type-item-title {
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.notify-type-item-image {
|
||||
width: 106px;
|
||||
margin: 16px 33px;
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: @primary-color-hover;
|
||||
opacity: 0.8;
|
||||
background-color: #F2F4F7;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: @primary-color-active;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.notify-type-item {
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
color: initial;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
background-color: #F2F4F7;
|
||||
border: 1px solid #ADB8C7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,30 @@
|
|||
<template>
|
||||
<j-modal
|
||||
:width="900"
|
||||
:width="1056"
|
||||
visible
|
||||
title="配置通知方式"
|
||||
@cancel="emit('close')"
|
||||
@ok="onSave"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
>
|
||||
<j-steps :current="current" size="small" @change="onChange">
|
||||
<j-step v-for="item in stepList" :title="item" :key="item" />
|
||||
</j-steps>
|
||||
<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"
|
||||
>
|
||||
<template #description>
|
||||
<span v-if="current === index">进行中</span>
|
||||
<span v-if="current < index">未开始</span>
|
||||
<span v-if="current > index">已完成</span>
|
||||
</template>
|
||||
</j-step>
|
||||
</j-steps>
|
||||
</div>
|
||||
<div style="margin: 20px">
|
||||
<template v-if="current === 0">
|
||||
<NotifyWay
|
||||
:value="formModel.channelProvider"
|
||||
:name="formModel.name"
|
||||
@change="onWayChange"
|
||||
/>
|
||||
</template>
|
||||
|
@ -43,6 +54,38 @@
|
|||
<template v-if="current === 4">
|
||||
<Role v-model="formModel.grant.role.idList" />
|
||||
</template>
|
||||
<template v-if="current === 5">
|
||||
<div>
|
||||
<div class="alert">
|
||||
<AIcon type="InfoCircleOutlined" />
|
||||
被分配了接收权限的用户将根据名称判断是否订阅该通知
|
||||
</div>
|
||||
<div style="margin: 50px 200px">
|
||||
<j-form
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
layout="vertical"
|
||||
>
|
||||
<j-form-item
|
||||
name="name"
|
||||
label="名称"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{
|
||||
max: 8,
|
||||
message: '最多可输入8个字符',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="formModel.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template #footer>
|
||||
<j-space>
|
||||
|
@ -115,6 +158,7 @@ const stepList = [
|
|||
'选择通知模板',
|
||||
'配置模板变量',
|
||||
'配置用户权限',
|
||||
'完成',
|
||||
];
|
||||
const current = ref<number>(0);
|
||||
const variable = ref([]);
|
||||
|
@ -134,6 +178,7 @@ const formModel = reactive<{
|
|||
channelConfiguration: {},
|
||||
});
|
||||
const variableRef = ref();
|
||||
const formRef = ref();
|
||||
|
||||
const _variableDefinitions = computed(() => {
|
||||
const arr = ['user', 'org'];
|
||||
|
@ -172,50 +217,41 @@ const handleVariable = (obj: any) => {
|
|||
};
|
||||
|
||||
const jumpStep = async (val: number) => {
|
||||
if (val === 0) {
|
||||
current.value = val;
|
||||
} else if (val === 1) {
|
||||
if (formModel.channelProvider) {
|
||||
current.value = val;
|
||||
} else {
|
||||
if (val >= 1) {
|
||||
if (!formModel.channelProvider) {
|
||||
onlyMessage('请选择通知方式', 'error');
|
||||
return;
|
||||
}
|
||||
} else if (val === 2) {
|
||||
if (formModel.channelConfiguration.notifierId) {
|
||||
current.value = val;
|
||||
} else {
|
||||
}
|
||||
if (val >= 2) {
|
||||
if (!formModel.channelConfiguration.notifierId) {
|
||||
onlyMessage('请选择通知配置', 'error');
|
||||
return;
|
||||
}
|
||||
} else if (val === 3) {
|
||||
if (formModel.channelConfiguration.templateId) {
|
||||
const resp = await Template.getTemplateDetail(
|
||||
formModel.channelConfiguration.templateId,
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
variable.value = resp.result?.variableDefinitions || [];
|
||||
current.value = val;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (val >= 3) {
|
||||
if (!formModel.channelConfiguration.templateId) {
|
||||
onlyMessage('请选择通知模板', 'error');
|
||||
return;
|
||||
}
|
||||
} else if (val === 4) {
|
||||
}
|
||||
if (val >= 4) {
|
||||
if (variable.value.length) {
|
||||
if (_variableDefinitions.value.length) {
|
||||
const obj = await variableRef.value.onSave();
|
||||
if (obj) {
|
||||
handleVariable(obj);
|
||||
current.value = val;
|
||||
} else {
|
||||
onlyMessage('请配置模版变量', 'error');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
handleVariable({});
|
||||
current.value = val;
|
||||
}
|
||||
} else {
|
||||
current.value = val;
|
||||
}
|
||||
}
|
||||
|
||||
current.value = val;
|
||||
};
|
||||
|
||||
const onWayChange = (obj: any) => {
|
||||
|
@ -262,7 +298,8 @@ const onChange = (cur: number) => {
|
|||
jumpStep(cur);
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
const onSave = async () => {
|
||||
await formRef.value?.validate();
|
||||
formModel.grant.permissions =
|
||||
props.provider === 'alarm'
|
||||
? [{ id: 'alarm-config', actions: ['query'] }]
|
||||
|
|