Merge branch 'dev' into dev-hub
This commit is contained in:
commit
e96a43ad8b
|
@ -27,6 +27,7 @@ const iconKeys = [
|
||||||
'SyncOutlined',
|
'SyncOutlined',
|
||||||
'ExclamationCircleOutlined',
|
'ExclamationCircleOutlined',
|
||||||
'UploadOutlined',
|
'UploadOutlined',
|
||||||
|
'LoadingOutlined',
|
||||||
'PlusCircleOutlined',
|
'PlusCircleOutlined',
|
||||||
'QuestionCircleOutlined',
|
'QuestionCircleOutlined',
|
||||||
'DisconnectOutlined',
|
'DisconnectOutlined',
|
||||||
|
|
|
@ -1,70 +1,213 @@
|
||||||
<template>
|
<template>
|
||||||
<a-upload
|
<div class="upload-image-warp">
|
||||||
v-model:file-list="fileList"
|
<div class="upload-image-border">
|
||||||
name="avatar"
|
<a-upload
|
||||||
list-type="picture-card"
|
name="file"
|
||||||
class="avatar-uploader"
|
list-type="picture-card"
|
||||||
:show-upload-list="false"
|
class="avatar-uploader"
|
||||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
:show-upload-list="false"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
:action="FILE_UPLOAD"
|
||||||
<img v-if="imageUrl" :src="imageUrl" alt="avatar" />
|
:headers="{
|
||||||
<div v-else>
|
'X-Access-Token': LocalStore.get(TOKEN_KEY)
|
||||||
<loading-outlined v-if="loading"></loading-outlined>
|
}"
|
||||||
<plus-outlined v-else></plus-outlined>
|
v-bind="props"
|
||||||
<div class="ant-upload-text">Upload</div>
|
>
|
||||||
|
<div class="upload-image-content" :style="props.style">
|
||||||
|
<template v-if="myValue">
|
||||||
|
<!-- <div class="upload-image"
|
||||||
|
:style="{
|
||||||
|
backgroundSize: props.backgroundSize,
|
||||||
|
backgroundImage: `url(${imageUrl})`
|
||||||
|
}"
|
||||||
|
></div> -->
|
||||||
|
<img :src="myValue" class="upload-image" />
|
||||||
|
<div class="upload-image-mask">点击修改</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon type="LoadingOutlined" v-if="loading" style="font-size: 20px" />
|
||||||
|
<AIcon v-else type="PlusOutlined" style="font-size: 20px" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</a-upload>
|
||||||
|
<div class="upload-loading-mask" v-if="props.disabled"></div>
|
||||||
|
<div class="upload-loading-mask" v-if="myValue && loading">
|
||||||
|
<AIcon type="LoadingOutlined" style="font-size: 20px" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-upload>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { message, UploadChangeParam, UploadProps } from 'ant-design-vue';
|
import { message, UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||||
|
import { FILE_UPLOAD } from '@/api/comm'
|
||||||
|
import { TOKEN_KEY } from '@/utils/variable';
|
||||||
|
import { LocalStore } from '@/utils/comm';
|
||||||
|
import { CSSProperties } from 'vue';
|
||||||
|
|
||||||
|
type Emits = {
|
||||||
|
(e: 'update:modelValue', data: string): void;
|
||||||
|
};
|
||||||
|
interface JUploadProps extends UploadProps {
|
||||||
|
modelValue: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
types?: string[];
|
||||||
|
errorMessage?: string;
|
||||||
|
size?: number;
|
||||||
|
style?: CSSProperties;
|
||||||
|
backgroundSize?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const props: JUploadProps = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
const imageUrl = ref<string>(props?.modelValue || '')
|
||||||
|
const imageTypes = props.types ? props.types : ['image/jpeg', 'image/png'];
|
||||||
|
|
||||||
|
const myValue = computed({
|
||||||
|
get: () => {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
set: (val: any) => {
|
||||||
|
imageUrl.value = val;
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const handleChange = (info: UploadChangeParam) => {
|
const handleChange = (info: UploadChangeParam) => {
|
||||||
// if (info.file.status === 'uploading') {
|
if (info.file.status === 'uploading') {
|
||||||
// loading.value = true;
|
loading.value = true;
|
||||||
// return;
|
}
|
||||||
// }
|
if (info.file.status === 'done') {
|
||||||
// if (info.file.status === 'done') {
|
myValue.value = info.file.response?.result
|
||||||
// // Get this url from response in real world.
|
loading.value = false;
|
||||||
// getBase64(info.file.originFileObj, (base64Url: string) => {
|
emit('update:modelValue', imageUrl.value)
|
||||||
// imageUrl.value = base64Url;
|
}
|
||||||
// loading.value = false;
|
if (info.file.status === 'error') {
|
||||||
// });
|
loading.value = false;
|
||||||
// }
|
message.error('上传失败');
|
||||||
// if (info.file.status === 'error') {
|
}
|
||||||
// loading.value = false;
|
|
||||||
// message.error('upload error');
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
const beforeUpload = (file: UploadProps['fileList'][number]) => {
|
||||||
// const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
|
const isType = imageTypes.includes(file.type);
|
||||||
// if (!isJpgOrPng) {
|
if (!isType) {
|
||||||
// message.error('You can only upload JPG file!');
|
if (props.errorMessage) {
|
||||||
// }
|
message.error(props.errorMessage);
|
||||||
// const isLt2M = file.size / 1024 / 1024 < 2;
|
} else {
|
||||||
// if (!isLt2M) {
|
message.error(`请上传正确格式的图片`);
|
||||||
// message.error('Image must smaller than 2MB!');
|
}
|
||||||
// }
|
return false;
|
||||||
// return isJpgOrPng && isLt2M;
|
}
|
||||||
|
const isSize = file.size / 1024 / 1024 < (props.size || 4);
|
||||||
|
if (!isSize) {
|
||||||
|
message.error(`图片大小必须小于${props.size || 4}M`);
|
||||||
|
}
|
||||||
|
return isType && isSize;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.avatar-uploader {
|
@border: 1px dashed @border-color-base;
|
||||||
width: 160px;
|
@mask-color: rgba(#000, 0.35);
|
||||||
height: 160px;
|
@with: 150px;
|
||||||
padding: 8px;
|
@height: 150px;
|
||||||
background-color: rgba(0,0,0,.06);
|
|
||||||
cursor: pointer;
|
.flex-center() {
|
||||||
display: flex;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
}
|
||||||
:deep(.ant-upload.ant-upload-select-picture-card) {
|
|
||||||
|
.upload-image-warp {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.upload-image-border {
|
||||||
|
position: relative;
|
||||||
|
width: @with;
|
||||||
|
height: @height;
|
||||||
|
overflow: hidden;
|
||||||
|
//border-radius: 50%;
|
||||||
|
// border: @border;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @primary-color-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-upload-picture-card-wrapper) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
:deep(.ant-upload) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image-content {
|
||||||
|
.flex-center();
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(#000, 0.06);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
.upload-image-mask {
|
||||||
|
.flex-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: @mask-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
//border-radius: 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .upload-image-mask {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-loading-mask {
|
||||||
|
.flex-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: #fff;
|
||||||
|
background-color: @mask-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -4,8 +4,8 @@
|
||||||
<a-form :layout="'vertical'">
|
<a-form :layout="'vertical'">
|
||||||
<a-row type="flex">
|
<a-row type="flex">
|
||||||
<a-col flex="180px">
|
<a-col flex="180px">
|
||||||
<a-form-item required>
|
<a-form-item required name="photoUrl">
|
||||||
<JUpload />
|
<JUpload v-model:value="modelRef.photoUrl" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col flex="auto">
|
<a-col flex="auto">
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { queryNoPagingPost } from '@/api/device/product'
|
import { queryNoPagingPost } from '@/api/device/product'
|
||||||
|
import { getImage } from '@/utils/comm';
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
|
|
||||||
const emit = defineEmits(['close', 'save'])
|
const emit = defineEmits(['close', 'save'])
|
||||||
|
@ -49,7 +50,7 @@ const modelRef = reactive({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
describe: '',
|
describe: '',
|
||||||
photoUrl: ''
|
photoUrl: getImage('/device/instance/device-card.png')
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -1,162 +1,153 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<a-card style="margin-bottom: 20px">
|
<Search
|
||||||
<Search
|
:columns="columns"
|
||||||
:columns="columns"
|
target="notice-config"
|
||||||
target="notice-config"
|
@search="handleSearch"
|
||||||
@search="handleSearch"
|
/>
|
||||||
/>
|
<JTable
|
||||||
</a-card>
|
ref="configRef"
|
||||||
<a-card>
|
:columns="columns"
|
||||||
<JTable
|
:request="ConfigApi.list"
|
||||||
ref="configRef"
|
:defaultParams="{
|
||||||
:columns="columns"
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
:request="ConfigApi.list"
|
}"
|
||||||
:defaultParams="{
|
:params="params"
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
>
|
||||||
}"
|
<template #headerTitle>
|
||||||
:params="params"
|
<a-space>
|
||||||
>
|
<a-button type="primary" @click="handleAdd">
|
||||||
<template #headerTitle>
|
新增
|
||||||
<a-space>
|
</a-button>
|
||||||
<a-button type="primary" @click="handleAdd">
|
<a-upload
|
||||||
新增
|
name="file"
|
||||||
</a-button>
|
accept="json"
|
||||||
<a-upload
|
:showUploadList="false"
|
||||||
name="file"
|
:before-upload="beforeUpload"
|
||||||
accept="json"
|
|
||||||
:showUploadList="false"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
>
|
|
||||||
<a-button>导入</a-button>
|
|
||||||
</a-upload>
|
|
||||||
<a-popconfirm
|
|
||||||
title="确认导出当前页数据?"
|
|
||||||
ok-text="确定"
|
|
||||||
cancel-text="取消"
|
|
||||||
@confirm="handleExport"
|
|
||||||
>
|
|
||||||
<a-button>导出</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<template #card="slotProps">
|
|
||||||
<CardBox
|
|
||||||
:showStatus="false"
|
|
||||||
:value="slotProps"
|
|
||||||
:actions="getActions(slotProps, 'card')"
|
|
||||||
v-bind="slotProps"
|
|
||||||
>
|
>
|
||||||
<template #img>
|
<a-button>导入</a-button>
|
||||||
<slot name="img">
|
</a-upload>
|
||||||
<img
|
<a-popconfirm
|
||||||
:src="
|
title="确认导出当前页数据?"
|
||||||
getLogo(
|
ok-text="确定"
|
||||||
slotProps.type,
|
cancel-text="取消"
|
||||||
slotProps.provider,
|
@confirm="handleExport"
|
||||||
)
|
>
|
||||||
"
|
<a-button>导出</a-button>
|
||||||
/>
|
</a-popconfirm>
|
||||||
</slot>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #card="slotProps">
|
||||||
<h3 class="card-item-content-title">
|
<CardBox
|
||||||
{{ slotProps.name }}
|
:showStatus="false"
|
||||||
</h3>
|
:value="slotProps"
|
||||||
<a-row>
|
:actions="getActions(slotProps, 'card')"
|
||||||
<a-col :span="12">
|
v-bind="slotProps"
|
||||||
<div class="card-item-content-text">
|
>
|
||||||
通知方式
|
<template #img>
|
||||||
</div>
|
<slot name="img">
|
||||||
<div>
|
<img
|
||||||
{{ getMethodTxt(slotProps.type) }}
|
:src="
|
||||||
</div>
|
getLogo(slotProps.type, slotProps.provider)
|
||||||
</a-col>
|
"
|
||||||
<a-col :span="12">
|
/>
|
||||||
<div class="card-item-content-text">
|
</slot>
|
||||||
说明
|
</template>
|
||||||
</div>
|
<template #content>
|
||||||
<div>{{ slotProps.description }}</div>
|
<h3 class="card-item-content-title">
|
||||||
</a-col>
|
{{ slotProps.name }}
|
||||||
</a-row>
|
</h3>
|
||||||
</template>
|
<a-row>
|
||||||
<template #actions="item">
|
<a-col :span="12">
|
||||||
<a-tooltip
|
<div class="card-item-content-text">
|
||||||
v-bind="item.tooltip"
|
通知方式
|
||||||
:title="item.disabled && item.tooltip.title"
|
</div>
|
||||||
>
|
<div>
|
||||||
<a-popconfirm
|
{{ getMethodTxt(slotProps.type) }}
|
||||||
v-if="item.popConfirm"
|
</div>
|
||||||
v-bind="item.popConfirm"
|
</a-col>
|
||||||
:disabled="item.disabled"
|
<a-col :span="12">
|
||||||
>
|
<div class="card-item-content-text">说明</div>
|
||||||
<a-button :disabled="item.disabled">
|
<div>{{ slotProps.description }}</div>
|
||||||
<AIcon
|
</a-col>
|
||||||
type="DeleteOutlined"
|
</a-row>
|
||||||
v-if="item.key === 'delete'"
|
</template>
|
||||||
/>
|
<template #actions="item">
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item.text }}</span>
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
<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>
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</CardBox>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<a-space :size="16">
|
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
v-bind="item.tooltip"
|
||||||
:key="i.key"
|
:title="item.disabled && item.tooltip.title"
|
||||||
v-bind="i.tooltip"
|
|
||||||
>
|
>
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-if="i.popConfirm"
|
v-if="item.popConfirm"
|
||||||
v-bind="i.popConfirm"
|
v-bind="item.popConfirm"
|
||||||
:disabled="i.disabled"
|
:disabled="item.disabled"
|
||||||
>
|
>
|
||||||
<a-button
|
<a-button :disabled="item.disabled">
|
||||||
:disabled="i.disabled"
|
<AIcon
|
||||||
style="padding: 0"
|
type="DeleteOutlined"
|
||||||
type="link"
|
v-if="item.key === 'delete'"
|
||||||
><AIcon :type="i.icon"
|
/>
|
||||||
/></a-button>
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<a-space :size="16">
|
||||||
|
<a-tooltip
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
|
v-bind="i.tooltip"
|
||||||
|
>
|
||||||
|
<a-popconfirm
|
||||||
|
v-if="i.popConfirm"
|
||||||
|
v-bind="i.popConfirm"
|
||||||
|
:disabled="i.disabled"
|
||||||
|
>
|
||||||
<a-button
|
<a-button
|
||||||
|
:disabled="i.disabled"
|
||||||
style="padding: 0"
|
style="padding: 0"
|
||||||
type="link"
|
type="link"
|
||||||
v-else
|
><AIcon :type="i.icon"
|
||||||
@click="i.onClick && i.onClick(slotProps)"
|
/></a-button>
|
||||||
>
|
</a-popconfirm>
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="i.disabled"
|
style="padding: 0"
|
||||||
style="padding: 0"
|
type="link"
|
||||||
type="link"
|
v-else
|
||||||
><AIcon :type="i.icon"
|
@click="i.onClick && i.onClick(slotProps)"
|
||||||
/></a-button>
|
>
|
||||||
</a-button>
|
<a-button
|
||||||
</a-tooltip>
|
:disabled="i.disabled"
|
||||||
</a-space>
|
style="padding: 0"
|
||||||
</template>
|
type="link"
|
||||||
</JTable>
|
><AIcon :type="i.icon"
|
||||||
</a-card>
|
/></a-button>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</JTable>
|
||||||
|
|
||||||
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
||||||
<Log v-model:visible="logVis" :data="currentConfig" />
|
<Log v-model:visible="logVis" :data="currentConfig" />
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
:confirmLoading="btnLoading"
|
:confirmLoading="btnLoading"
|
||||||
>
|
>
|
||||||
<a-form layout="vertical">
|
<a-form layout="vertical">
|
||||||
<a-form-item label="通知模版" v-bind="validateInfos.templateId">
|
<a-form-item label="通知配置" v-bind="validateInfos.configId">
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="formData.templateId"
|
v-model:value="formData.configId"
|
||||||
placeholder="请选择通知模版"
|
placeholder="请选择通知配置"
|
||||||
@change="getTemplateDetail"
|
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="(item, index) in templateList"
|
v-for="(item, index) in configList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
>
|
>
|
||||||
|
@ -63,10 +62,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import ConfigApi from '@/api/notice/config';
|
import TemplateApi from '@/api/notice/template';
|
||||||
import {
|
import {
|
||||||
TemplateFormData,
|
TemplateFormData,
|
||||||
IVariableDefinitions,
|
IVariableDefinitions,
|
||||||
|
BindConfig,
|
||||||
} from '@/views/notice/Template/types';
|
} from '@/views/notice/Template/types';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
@ -93,22 +93,25 @@ const _vis = computed({
|
||||||
/**
|
/**
|
||||||
* 获取通知模板
|
* 获取通知模板
|
||||||
*/
|
*/
|
||||||
const templateList = ref<TemplateFormData[]>([]);
|
const configList = ref<BindConfig[]>([]);
|
||||||
const getTemplateList = async () => {
|
const getConfigList = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
terms: [
|
terms: [
|
||||||
{ column: 'type', value: props.data.type },
|
{ column: 'type', value: props.data.type },
|
||||||
{ column: 'provider', value: props.data.provider },
|
{ column: 'provider', value: props.data.provider },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const { result } = await ConfigApi.getTemplate(params, props.data.id);
|
const { result } = await TemplateApi.getConfig(params);
|
||||||
templateList.value = result;
|
configList.value = result;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => _vis.value,
|
() => _vis.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) getTemplateList();
|
if (val) {
|
||||||
|
getConfigList();
|
||||||
|
getTemplateDetail();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -117,9 +120,7 @@ watch(
|
||||||
*/
|
*/
|
||||||
const templateDetailTable = ref<IVariableDefinitions[]>();
|
const templateDetailTable = ref<IVariableDefinitions[]>();
|
||||||
const getTemplateDetail = async () => {
|
const getTemplateDetail = async () => {
|
||||||
const { result } = await ConfigApi.getTemplateDetail(
|
const { result } = await TemplateApi.getTemplateDetail(props.data.id);
|
||||||
formData.value.templateId,
|
|
||||||
);
|
|
||||||
templateDetailTable.value = result.variableDefinitions.map((m: any) => ({
|
templateDetailTable.value = result.variableDefinitions.map((m: any) => ({
|
||||||
...m,
|
...m,
|
||||||
value: undefined,
|
value: undefined,
|
||||||
|
@ -147,13 +148,13 @@ const columns = [
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
templateId: '',
|
configId: '',
|
||||||
variableDefinitions: '',
|
variableDefinitions: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// 验证规则
|
// 验证规则
|
||||||
const formRules = ref({
|
const formRules = ref({
|
||||||
templateId: [{ required: true, message: '请选择通知模板' }],
|
configId: [{ required: true, message: '请选择通知模板' }],
|
||||||
variableDefinitions: [{ required: false, message: '该字段是必填字段' }],
|
variableDefinitions: [{ required: false, message: '该字段是必填字段' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ const handleOk = () => {
|
||||||
});
|
});
|
||||||
// console.log('params: ', params);
|
// console.log('params: ', params);
|
||||||
btnLoading.value = true;
|
btnLoading.value = true;
|
||||||
ConfigApi.debug(params, props.data.id, formData.value.templateId)
|
TemplateApi.debug(params, formData.value.configId, props.data.id)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<JTable
|
<JTable
|
||||||
ref="instanceRef"
|
ref="instanceRef"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:request="(e:any) => configApi.getHistory(e, data.id)"
|
:request="(e:any) => templateApi.getHistory(e, data.id)"
|
||||||
:defaultParams="{
|
:defaultParams="{
|
||||||
sorts: [{ name: 'notifyTime', order: 'desc' }],
|
sorts: [{ name: 'notifyTime', order: 'desc' }],
|
||||||
terms: [{ column: 'notifyType$IN', value: data.type }],
|
terms: [{ column: 'notifyType$IN', value: data.type }],
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import configApi from '@/api/notice/config';
|
import templateApi from '@/api/notice/template';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Modal } from 'ant-design-vue';
|
import { Modal } from 'ant-design-vue';
|
||||||
|
|
|
@ -1,162 +1,153 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<a-card style="margin-bottom: 20px">
|
<Search
|
||||||
<Search
|
:columns="columns"
|
||||||
:columns="columns"
|
target="notice-config"
|
||||||
target="notice-config"
|
@search="handleSearch"
|
||||||
@search="handleSearch"
|
/>
|
||||||
/>
|
<JTable
|
||||||
</a-card>
|
ref="configRef"
|
||||||
<a-card>
|
:columns="columns"
|
||||||
<JTable
|
:request="TemplateApi.list"
|
||||||
ref="configRef"
|
:defaultParams="{
|
||||||
:columns="columns"
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
:request="ConfigApi.list"
|
}"
|
||||||
:defaultParams="{
|
:params="params"
|
||||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
>
|
||||||
}"
|
<template #headerTitle>
|
||||||
:params="params"
|
<a-space>
|
||||||
>
|
<a-button type="primary" @click="handleAdd">
|
||||||
<template #headerTitle>
|
新增
|
||||||
<a-space>
|
</a-button>
|
||||||
<a-button type="primary" @click="handleAdd">
|
<a-upload
|
||||||
新增
|
name="file"
|
||||||
</a-button>
|
accept="json"
|
||||||
<a-upload
|
:showUploadList="false"
|
||||||
name="file"
|
:before-upload="beforeUpload"
|
||||||
accept="json"
|
|
||||||
:showUploadList="false"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
>
|
|
||||||
<a-button>导入</a-button>
|
|
||||||
</a-upload>
|
|
||||||
<a-popconfirm
|
|
||||||
title="确认导出当前页数据?"
|
|
||||||
ok-text="确定"
|
|
||||||
cancel-text="取消"
|
|
||||||
@confirm="handleExport"
|
|
||||||
>
|
|
||||||
<a-button>导出</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<template #card="slotProps">
|
|
||||||
<CardBox
|
|
||||||
:showStatus="false"
|
|
||||||
:value="slotProps"
|
|
||||||
:actions="getActions(slotProps, 'card')"
|
|
||||||
v-bind="slotProps"
|
|
||||||
>
|
>
|
||||||
<template #img>
|
<a-button>导入</a-button>
|
||||||
<slot name="img">
|
</a-upload>
|
||||||
<img
|
<a-popconfirm
|
||||||
:src="
|
title="确认导出当前页数据?"
|
||||||
getLogo(
|
ok-text="确定"
|
||||||
slotProps.type,
|
cancel-text="取消"
|
||||||
slotProps.provider,
|
@confirm="handleExport"
|
||||||
)
|
>
|
||||||
"
|
<a-button>导出</a-button>
|
||||||
/>
|
</a-popconfirm>
|
||||||
</slot>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #card="slotProps">
|
||||||
<h3 class="card-item-content-title">
|
<CardBox
|
||||||
{{ slotProps.name }}
|
:showStatus="false"
|
||||||
</h3>
|
:value="slotProps"
|
||||||
<a-row>
|
:actions="getActions(slotProps, 'card')"
|
||||||
<a-col :span="12">
|
v-bind="slotProps"
|
||||||
<div class="card-item-content-text">
|
>
|
||||||
通知方式
|
<template #img>
|
||||||
</div>
|
<slot name="img">
|
||||||
<div>
|
<img
|
||||||
{{ getMethodTxt(slotProps.type) }}
|
:src="
|
||||||
</div>
|
getLogo(slotProps.type, slotProps.provider)
|
||||||
</a-col>
|
"
|
||||||
<a-col :span="12">
|
/>
|
||||||
<div class="card-item-content-text">
|
</slot>
|
||||||
说明
|
</template>
|
||||||
</div>
|
<template #content>
|
||||||
<div>{{ slotProps.description }}</div>
|
<h3 class="card-item-content-title">
|
||||||
</a-col>
|
{{ slotProps.name }}
|
||||||
</a-row>
|
</h3>
|
||||||
</template>
|
<a-row>
|
||||||
<template #actions="item">
|
<a-col :span="12">
|
||||||
<a-tooltip
|
<div class="card-item-content-text">
|
||||||
v-bind="item.tooltip"
|
通知方式
|
||||||
:title="item.disabled && item.tooltip.title"
|
</div>
|
||||||
>
|
<div>
|
||||||
<a-popconfirm
|
{{ getMethodTxt(slotProps.type) }}
|
||||||
v-if="item.popConfirm"
|
</div>
|
||||||
v-bind="item.popConfirm"
|
</a-col>
|
||||||
:disabled="item.disabled"
|
<a-col :span="12">
|
||||||
>
|
<div class="card-item-content-text">说明</div>
|
||||||
<a-button :disabled="item.disabled">
|
<div>{{ slotProps.description }}</div>
|
||||||
<AIcon
|
</a-col>
|
||||||
type="DeleteOutlined"
|
</a-row>
|
||||||
v-if="item.key === 'delete'"
|
</template>
|
||||||
/>
|
<template #actions="item">
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item.text }}</span>
|
|
||||||
</template>
|
|
||||||
</a-button>
|
|
||||||
</a-popconfirm>
|
|
||||||
<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>
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</CardBox>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<a-space :size="16">
|
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
v-bind="item.tooltip"
|
||||||
:key="i.key"
|
:title="item.disabled && item.tooltip.title"
|
||||||
v-bind="i.tooltip"
|
|
||||||
>
|
>
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
v-if="i.popConfirm"
|
v-if="item.popConfirm"
|
||||||
v-bind="i.popConfirm"
|
v-bind="item.popConfirm"
|
||||||
:disabled="i.disabled"
|
:disabled="item.disabled"
|
||||||
>
|
>
|
||||||
<a-button
|
<a-button :disabled="item.disabled">
|
||||||
:disabled="i.disabled"
|
<AIcon
|
||||||
style="padding: 0"
|
type="DeleteOutlined"
|
||||||
type="link"
|
v-if="item.key === 'delete'"
|
||||||
><AIcon :type="i.icon"
|
/>
|
||||||
/></a-button>
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item.text }}</span>
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<a-space :size="16">
|
||||||
|
<a-tooltip
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
|
v-bind="i.tooltip"
|
||||||
|
>
|
||||||
|
<a-popconfirm
|
||||||
|
v-if="i.popConfirm"
|
||||||
|
v-bind="i.popConfirm"
|
||||||
|
:disabled="i.disabled"
|
||||||
|
>
|
||||||
<a-button
|
<a-button
|
||||||
|
:disabled="i.disabled"
|
||||||
style="padding: 0"
|
style="padding: 0"
|
||||||
type="link"
|
type="link"
|
||||||
v-else
|
><AIcon :type="i.icon"
|
||||||
@click="i.onClick && i.onClick(slotProps)"
|
/></a-button>
|
||||||
>
|
</a-popconfirm>
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="i.disabled"
|
style="padding: 0"
|
||||||
style="padding: 0"
|
type="link"
|
||||||
type="link"
|
v-else
|
||||||
><AIcon :type="i.icon"
|
@click="i.onClick && i.onClick(slotProps)"
|
||||||
/></a-button>
|
>
|
||||||
</a-button>
|
<a-button
|
||||||
</a-tooltip>
|
:disabled="i.disabled"
|
||||||
</a-space>
|
style="padding: 0"
|
||||||
</template>
|
type="link"
|
||||||
</JTable>
|
><AIcon :type="i.icon"
|
||||||
</a-card>
|
/></a-button>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</JTable>
|
||||||
|
|
||||||
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
||||||
<Log v-model:visible="logVis" :data="currentConfig" />
|
<Log v-model:visible="logVis" :data="currentConfig" />
|
||||||
|
@ -164,7 +155,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ConfigApi from '@/api/notice/config';
|
import TemplateApi from '@/api/notice/template';
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
import type { ActionsType } from '@/components/Table/index.vue';
|
||||||
import { getImage, LocalStore } from '@/utils/comm';
|
import { getImage, LocalStore } from '@/utils/comm';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
@ -188,7 +179,7 @@ const params = ref<Record<string, any>>({});
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '配置名称',
|
title: '模板名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
search: {
|
search: {
|
||||||
|
@ -243,9 +234,9 @@ const columns = [
|
||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
const handleSearch = (e: any) => {
|
const handleSearch = (e: any) => {
|
||||||
console.log('handleSearch:', e);
|
// console.log('handleSearch:', e);
|
||||||
params.value = e;
|
params.value = e;
|
||||||
console.log('params.value: ', params.value);
|
// console.log('params.value: ', params.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,7 +275,7 @@ const beforeUpload = (file: any) => {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text || '{}');
|
const data = JSON.parse(text || '{}');
|
||||||
const { success } = await ConfigApi.update(data);
|
const { success } = await TemplateApi.update(data);
|
||||||
if (success) {
|
if (success) {
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
configRef.value.reload();
|
configRef.value.reload();
|
||||||
|
@ -347,6 +338,17 @@ const getActions = (
|
||||||
currentConfig.value = data;
|
currentConfig.value = data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'debug',
|
||||||
|
text: '导出',
|
||||||
|
tooltip: {
|
||||||
|
title: '导出',
|
||||||
|
},
|
||||||
|
icon: 'ArrowDownOutlined',
|
||||||
|
onClick: () => {
|
||||||
|
downloadObject(data, `通知配置`);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'debug',
|
key: 'debug',
|
||||||
text: '通知记录',
|
text: '通知记录',
|
||||||
|
@ -359,24 +361,13 @@ const getActions = (
|
||||||
currentConfig.value = data;
|
currentConfig.value = data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'debug',
|
|
||||||
text: '导出',
|
|
||||||
tooltip: {
|
|
||||||
title: '导出',
|
|
||||||
},
|
|
||||||
icon: 'ArrowDownOutlined',
|
|
||||||
onClick: () => {
|
|
||||||
downloadObject(data, `通知配置`);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
text: '删除',
|
text: '删除',
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '确认删除?',
|
title: '确认删除?',
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
const resp = await ConfigApi.del(data.id);
|
const resp = await TemplateApi.del(data.id);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
configRef.value?.reload();
|
configRef.value?.reload();
|
||||||
|
|
Loading…
Reference in New Issue