page: 📄 消息详情和部分缺陷修复
This commit is contained in:
parent
a9e06b151a
commit
a6eaa41226
|
@ -6,6 +6,21 @@ export const fetchGetMessageList = (data: any) => {
|
||||||
return http.request<BaseResult<ResultTable>>('get', `message/getMessageList/${data.currentPage}/${data.pageSize}`, { params: data });
|
return http.request<BaseResult<ResultTable>>('get', `message/getMessageList/${data.currentPage}/${data.pageSize}`, { params: data });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 系统消息---获取系统消息列表 */
|
||||||
|
export const fetchGetUserMessageList = (data: any) => {
|
||||||
|
return http.request<BaseResult<ResultTable>>('get', `message/noManage/getUserMessageList/${data.currentPage}/${data.pageSize}`, { params: data });
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 系统消息---根据消息id获取接收人信息 */
|
||||||
|
export const fetchGetReceivedUserinfoByMessageId = (data: any) => {
|
||||||
|
return http.request<BaseResult<any>>('get', `messageReceived/noManage/getReceivedUserinfoByMessageId`, { params: data });
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 系统消息---根据消息id查询消息详情 */
|
||||||
|
export const fetchGetMessageDetailById = (data: any) => {
|
||||||
|
return http.request<BaseResult<any>>('get', `message/noManage/getMessageDetailById`, { params: data });
|
||||||
|
};
|
||||||
|
|
||||||
/** 系统消息---添加系统消息 */
|
/** 系统消息---添加系统消息 */
|
||||||
export const fetchAddMessage = (data: any) => {
|
export const fetchAddMessage = (data: any) => {
|
||||||
return http.request<BaseResult<object>>('post', 'message/addMessage', { data });
|
return http.request<BaseResult<object>>('post', 'message/addMessage', { data });
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 是否默认
|
* * 是否默认
|
||||||
|
@ -32,6 +33,12 @@ export const enabledOrNotStatus = [
|
||||||
{ value: false, label: '禁用' },
|
{ value: false, label: '禁用' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** 是否已读 */
|
||||||
|
export const isReadStatus = [
|
||||||
|
{ value: true, label: $t('readAlready') },
|
||||||
|
{ value: false, label: $t('unread') },
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 分页默认数组个数
|
* * 分页默认数组个数
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { ListItem } from '../data';
|
||||||
import { nextTick, PropType, ref } from 'vue';
|
import { nextTick, PropType, ref } from 'vue';
|
||||||
import { useNav } from '@/layout/hooks/useNav';
|
import { useNav } from '@/layout/hooks/useNav';
|
||||||
import { deviceDetection } from '@pureadmin/utils';
|
import { deviceDetection } from '@pureadmin/utils';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
noticeItem: {
|
noticeItem: {
|
||||||
|
@ -17,6 +18,7 @@ const descriptionRef = ref(null);
|
||||||
const descriptionTooltip = ref(false);
|
const descriptionTooltip = ref(false);
|
||||||
const { tooltipEffect } = useNav();
|
const { tooltipEffect } = useNav();
|
||||||
const isMobile = deviceDetection();
|
const isMobile = deviceDetection();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
function hoverTitle() {
|
function hoverTitle() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
@ -39,10 +41,14 @@ function hoverDescription(event, description) {
|
||||||
// 当文本宽度大于容器宽度两倍时,代表文本显示超过两行
|
// 当文本宽度大于容器宽度两倍时,代表文本显示超过两行
|
||||||
currentWidth > 2 * cellWidth ? (descriptionTooltip.value = true) : (descriptionTooltip.value = false);
|
currentWidth > 2 * cellWidth ? (descriptionTooltip.value = true) : (descriptionTooltip.value = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goMessageDetail(message: ListItem) {
|
||||||
|
router.push({ path: `/message-detail/${message.messageType}/${message.messageId}` });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="notice-container border-b-[1px] border-solid border-[#f0f0f0] dark:border-[#303030]">
|
<div class="notice-container border-b-[1px] border-solid border-[#f0f0f0] dark:border-[#303030]" @click="goMessageDetail(noticeItem)">
|
||||||
<el-avatar v-if="noticeItem.cover" :size="30" :src="noticeItem.cover" class="notice-container-avatar" />
|
<el-avatar v-if="noticeItem.cover" :size="30" :src="noticeItem.cover" class="notice-container-avatar" />
|
||||||
<div class="notice-container-text">
|
<div class="notice-container-text">
|
||||||
<div class="notice-text-title text-[#000000d9] dark:text-white">
|
<div class="notice-text-title text-[#000000d9] dark:text-white">
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { fetchGetMessageList } from '@/api/v1/message';
|
import { fetchGetUserMessageList } from '@/api/v1/message';
|
||||||
|
import { throttle } from '@pureadmin/utils';
|
||||||
|
|
||||||
export interface ListItem {
|
export interface ListItem {
|
||||||
|
messageId: string;
|
||||||
cover: string;
|
cover: string;
|
||||||
title: string;
|
title: string;
|
||||||
datetime: string;
|
datetime: string;
|
||||||
type: string;
|
type: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
messageType: string;
|
||||||
status?: 'primary' | 'success' | 'warning' | 'info' | 'danger';
|
status?: 'primary' | 'success' | 'warning' | 'info' | 'danger';
|
||||||
extra?: string;
|
extra?: string;
|
||||||
}
|
}
|
||||||
|
@ -26,19 +29,21 @@ export const noticesData = ref<TabItem[]>([]);
|
||||||
|
|
||||||
/** 获取所有消息 */
|
/** 获取所有消息 */
|
||||||
export const getAllMessageList = async () => {
|
export const getAllMessageList = async () => {
|
||||||
const baseResult = await fetchGetMessageList(form);
|
const baseResult = await fetchGetUserMessageList(form);
|
||||||
const datalist = baseResult.data.list;
|
const datalist = baseResult?.data?.list;
|
||||||
|
|
||||||
// 通知消息
|
// 通知消息
|
||||||
const notifications = datalist
|
const notifications = datalist
|
||||||
.filter(message => message.messageType === 'notifications')
|
.filter(message => message.messageType === 'notifications')
|
||||||
.map(message => ({
|
.map(message => ({
|
||||||
|
messageId: message.id,
|
||||||
cover: message.cover,
|
cover: message.cover,
|
||||||
title: message.title,
|
title: message.title,
|
||||||
datetime: message.createTime,
|
datetime: message.createTime,
|
||||||
description: message.summary,
|
description: message.summary,
|
||||||
|
messageType: message.messageType,
|
||||||
type: '1',
|
type: '1',
|
||||||
status: message.statusType,
|
status: message.level,
|
||||||
extra: message.extra,
|
extra: message.extra,
|
||||||
})) as ListItem[];
|
})) as ListItem[];
|
||||||
|
|
||||||
|
@ -46,12 +51,14 @@ export const getAllMessageList = async () => {
|
||||||
const notify = datalist
|
const notify = datalist
|
||||||
.filter(message => message.messageType !== 'notifications' && message.messageType !== 'sys')
|
.filter(message => message.messageType !== 'notifications' && message.messageType !== 'sys')
|
||||||
.map(message => ({
|
.map(message => ({
|
||||||
|
messageId: message.id,
|
||||||
cover: message.cover,
|
cover: message.cover,
|
||||||
description: message.summary,
|
description: message.summary,
|
||||||
|
messageType: message.messageType,
|
||||||
title: message.title,
|
title: message.title,
|
||||||
datetime: message.createTime,
|
datetime: message.createTime,
|
||||||
type: '2',
|
type: '2',
|
||||||
status: message.statusType,
|
status: message.level,
|
||||||
extra: message.extra,
|
extra: message.extra,
|
||||||
})) as ListItem[];
|
})) as ListItem[];
|
||||||
|
|
||||||
|
@ -59,12 +66,14 @@ export const getAllMessageList = async () => {
|
||||||
const system = datalist
|
const system = datalist
|
||||||
.filter(message => message.messageType === 'sys')
|
.filter(message => message.messageType === 'sys')
|
||||||
.map(message => ({
|
.map(message => ({
|
||||||
|
messageId: message.id,
|
||||||
cover: message.cover,
|
cover: message.cover,
|
||||||
description: message.summary,
|
description: message.summary,
|
||||||
|
messageType: message.messageType,
|
||||||
title: message.title,
|
title: message.title,
|
||||||
datetime: message.createTime,
|
datetime: message.createTime,
|
||||||
type: '3',
|
type: '3',
|
||||||
status: message.statusType,
|
status: message.level,
|
||||||
extra: message.extra,
|
extra: message.extra,
|
||||||
})) as ListItem[];
|
})) as ListItem[];
|
||||||
|
|
||||||
|
@ -74,3 +83,23 @@ export const getAllMessageList = async () => {
|
||||||
{ key: '3', name: $t('status.systemMessage'), list: system, emptyText: $t('status.systemMessage') },
|
{ key: '3', name: $t('status.systemMessage'), list: system, emptyText: $t('status.systemMessage') },
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 通知消息数据
|
||||||
|
export const noticesNum = ref(0);
|
||||||
|
export const notices = ref(noticesData);
|
||||||
|
// 选择的消息栏目
|
||||||
|
export const activeKey = ref(noticesData.value[0]?.key);
|
||||||
|
export const getLabel = computed(() => item => item.name + (item.list.length > 0 ? `(${item.list.length})` : ''));
|
||||||
|
|
||||||
|
/** 计算消息数量 */
|
||||||
|
export const computedNoticesNum = throttle(async () => {
|
||||||
|
// 获取所有的消息
|
||||||
|
await getAllMessageList();
|
||||||
|
// 请求成功后将原本条数置为0
|
||||||
|
noticesNum.value = 0;
|
||||||
|
// 整合消息一共多少条
|
||||||
|
notices.value.map(v => (noticesNum.value += v.list.length));
|
||||||
|
// 默认选中的消息类别
|
||||||
|
activeKey.value = noticesData.value[0]?.key;
|
||||||
|
// 定时刷新
|
||||||
|
}, 666);
|
||||||
|
|
|
@ -1,42 +1,20 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import { getAllMessageList, noticesData } from './data';
|
import { activeKey, computedNoticesNum, getLabel, notices, noticesNum } from './data';
|
||||||
import NoticeList from './components/NoticeList.vue';
|
import NoticeList from './components/NoticeList.vue';
|
||||||
import BellIcon from '@iconify-icons/ep/bell';
|
import BellIcon from '@iconify-icons/ep/bell';
|
||||||
import { useIntervalFn } from '@vueuse/core';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
// 通知消息数据
|
|
||||||
const noticesNum = ref(0);
|
|
||||||
const notices = ref(noticesData);
|
|
||||||
// 选择的消息栏目
|
|
||||||
const activeKey = ref(noticesData.value[0]?.key);
|
|
||||||
const getLabel = computed(() => item => item.name + (item.list.length > 0 ? `(${item.list.length})` : ''));
|
|
||||||
|
|
||||||
/** 计算消息数量 */
|
|
||||||
const computedNoticesNum = async () => {
|
|
||||||
// 获取所有的消息
|
|
||||||
await getAllMessageList();
|
|
||||||
// 请求成功后将原本条数置为0
|
|
||||||
noticesNum.value = 0;
|
|
||||||
// 整合消息一共多少条
|
|
||||||
notices.value.map(v => (noticesNum.value += v.list.length));
|
|
||||||
// 默认选中的消息类别
|
|
||||||
activeKey.value = noticesData.value[0]?.key;
|
|
||||||
// 定时刷新
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
computedNoticesNum();
|
computedNoticesNum();
|
||||||
// 定时刷新消息内容
|
|
||||||
useIntervalFn(() => computedNoticesNum(), 1000 * 30);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dropdown placement="bottom-end" trigger="click">
|
<el-dropdown placement="bottom-end" trigger="click">
|
||||||
<span :class="['dropdown-badge', 'navbar-bg-hover', 'select-none', Number(noticesNum) !== 0 && 'mr-[10px]']">
|
<span :class="['dropdown-badge', 'navbar-bg-hover', 'select-none', Number(noticesNum) !== 0 && 'mr-[10px]']" @click="computedNoticesNum">
|
||||||
<el-badge :max="99" :value="Number(noticesNum) === 0 ? '' : noticesNum">
|
<el-badge :max="99" :value="Number(noticesNum) === 0 ? '' : noticesNum">
|
||||||
<span class="header-notice-icon">
|
<span class="header-notice-icon">
|
||||||
<IconifyIconOffline :icon="BellIcon" />
|
<IconifyIconOffline :icon="BellIcon" />
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
const { VITE_HIDE_HOME } = import.meta.env;
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
const Layout = () => import("@/layout/index.vue");
|
const Layout = () => import('@/layout/index.vue');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: "/",
|
path: '/',
|
||||||
name: "Home",
|
name: 'Home',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: "/welcome",
|
redirect: '/welcome',
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ep:home-filled",
|
icon: 'ep:home-filled',
|
||||||
title: "menus.home",
|
title: 'menus.home',
|
||||||
rank: 0
|
rank: 0,
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/welcome",
|
path: '/welcome',
|
||||||
name: "Welcome",
|
name: 'Welcome',
|
||||||
component: () => import("@/views/welcome/index.vue"),
|
component: () => import('@/views/welcome/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: "menus.home",
|
title: 'menus.home',
|
||||||
showLink: VITE_HIDE_HOME !== "true"
|
showLink: VITE_HIDE_HOME !== 'true',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
} satisfies RouteConfigsTable;
|
} satisfies RouteConfigsTable;
|
||||||
|
|
|
@ -34,7 +34,27 @@ export default [
|
||||||
meta: {
|
meta: {
|
||||||
title: 'buttons.accountSettings',
|
title: 'buttons.accountSettings',
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 104,
|
rank: 103,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/message-detail',
|
||||||
|
name: 'MessageDetail',
|
||||||
|
component: () => import('@/views/message-management/message-detail/index.vue'),
|
||||||
|
meta: { title: 'message', showLink: false, rank: 104 },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/message-detail/:messageType',
|
||||||
|
name: 'MessageDetailByMessageType',
|
||||||
|
component: () => import('@/views/message-management/message-detail/detail-type.vue'),
|
||||||
|
meta: { title: 'message', showLink: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/message-detail/:messageType/:messageId',
|
||||||
|
name: 'MessageDetailByMessageId',
|
||||||
|
component: () => import('@/views/message-management/message-detail/detail-message-id.vue'),
|
||||||
|
meta: { title: 'message', showLink: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
] satisfies Array<RouteConfigsTable>;
|
] satisfies Array<RouteConfigsTable>;
|
||||||
|
|
|
@ -28,6 +28,10 @@ export const useMessageStore = defineStore('messageStore', {
|
||||||
content: undefined,
|
content: undefined,
|
||||||
// 编辑器类型
|
// 编辑器类型
|
||||||
editorType: undefined,
|
editorType: undefined,
|
||||||
|
// 消息等级
|
||||||
|
level: undefined,
|
||||||
|
// 消息等级详情
|
||||||
|
extra: undefined,
|
||||||
// 0:未读 1:已读
|
// 0:未读 1:已读
|
||||||
status: undefined,
|
status: undefined,
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import 'plus-pro-components/es/components/check-card-group/style/css';
|
||||||
|
import MarkdownPreview from '@/components/Editor/MarkdownPreview.vue';
|
||||||
|
import { fetchGetMessageDetailById } from '@/api/v1/message';
|
||||||
|
import { decode } from 'js-base64';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const messageDetail = ref<any>({});
|
||||||
|
|
||||||
|
/** 获取消息详情 */
|
||||||
|
const getMessageDetail = async () => {
|
||||||
|
// 从路由中获取地址栏信息
|
||||||
|
const messageId = route.params.messageId;
|
||||||
|
|
||||||
|
// 获取消息详情
|
||||||
|
const result = await fetchGetMessageDetailById({ id: messageId });
|
||||||
|
if (result.code !== 200) return;
|
||||||
|
|
||||||
|
// 将消息详情赋值
|
||||||
|
messageDetail.value = result.data;
|
||||||
|
|
||||||
|
// 解码消息内容
|
||||||
|
messageDetail.value.content = decode(messageDetail.value.content);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getMessageDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<header class="flex items-center h-[80px]">
|
||||||
|
<el-avatar :src="messageDetail.cover" size="large" />
|
||||||
|
<div class="content ms-3">
|
||||||
|
<h3>{{ messageDetail.title }}</h3>
|
||||||
|
|
||||||
|
<p>{{ messageDetail.summary }}</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<span>
|
||||||
|
<el-text>{{ messageDetail.updateTime }}</el-text>
|
||||||
|
<el-text type="primary"> By:{{ messageDetail.sendNickname }}</el-text>
|
||||||
|
</span>
|
||||||
|
<markdown-preview v-if="messageDetail.editorType === 'markdown'" id="message-detail-markdown" :text="messageDetail.content" />
|
||||||
|
<div v-else v-html="messageDetail.content" />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { PlusCheckCardGroup } from 'plus-pro-components';
|
||||||
|
import 'plus-pro-components/es/components/check-card-group/style/css';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
/** 获取消息详情 */
|
||||||
|
const getMessageDetail = () => {
|
||||||
|
const messageId = route.params.messageId;
|
||||||
|
};
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
title: '标题一',
|
||||||
|
value: '0',
|
||||||
|
description: '坚持梦想,成就不凡的自己',
|
||||||
|
avatar: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标题二',
|
||||||
|
value: '1',
|
||||||
|
description: '每一次努力,都是成长的契机',
|
||||||
|
avatar: 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const size = ref('default');
|
||||||
|
const dynamicSize = ref();
|
||||||
|
const list = ref('0');
|
||||||
|
onMounted(() => {
|
||||||
|
getMessageDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PlusCheckCardGroup v-model="list" :disabled="size === 'disabled'" :options="options" :size="dynamicSize" />
|
||||||
|
</template>
|
|
@ -0,0 +1,112 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { onBeforeMount, ref } from 'vue';
|
||||||
|
import { deviceDetection, useGlobal } from '@pureadmin/utils';
|
||||||
|
import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange';
|
||||||
|
import leftLine from '@iconify-icons/ri/arrow-left-s-line';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
import { useMessageTypeStore } from '@/store/message/messageType';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const isOpen = ref(!deviceDetection());
|
||||||
|
const { $storage } = useGlobal<GlobalPropertiesApi>();
|
||||||
|
const witchPane = ref('profile');
|
||||||
|
const messageTypeStore = useMessageTypeStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const routerMessageType = ref('');
|
||||||
|
|
||||||
|
/** 点击菜单时 */
|
||||||
|
const onMenuClick = (item: any) => {
|
||||||
|
const messageType = item.messageType;
|
||||||
|
const messageId = item.messageId;
|
||||||
|
routerMessageType.value = messageType;
|
||||||
|
router.push({ path: `/message-detail/${item.messageType}` });
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
messageTypeStore.getAllMessageTypeList();
|
||||||
|
routerMessageType.value = route.params.messageType as string;
|
||||||
|
useDataThemeChange().dataThemeChange($storage.layout?.overallStyle);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container class="h-full">
|
||||||
|
<el-aside
|
||||||
|
v-if="isOpen"
|
||||||
|
:width="deviceDetection() ? '180px' : '240px'"
|
||||||
|
class="pure-account-settings overflow-hidden px-2 dark:!bg-[var(--el-bg-color)] border-r-[1px] border-[var(--pure-border-color)]"
|
||||||
|
>
|
||||||
|
<el-menu :default-active="witchPane" class="pure-account-settings-menu">
|
||||||
|
<!--<el-menu-item class="hover:!transition-all hover:!duration-200 hover:!text-base !h-[50px]" @click="router.go(-1)">-->
|
||||||
|
<el-menu-item class="hover:!transition-all hover:!duration-200 hover:!text-base !h-[50px]" @click="router.push('/')">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<IconifyIconOffline :icon="leftLine" />
|
||||||
|
<span class="ml-2">{{ $t('back') }}</span>
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item v-for="item in messageTypeStore.allMessageTypeList" :key="item.id" :class="routerMessageType === item.messageType ? 'is-active' : ''" :index="item.id" @click="onMenuClick(item)">
|
||||||
|
<div class="flex items-center z-10">
|
||||||
|
<span>{{ item.messageName }}</span>
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</el-aside>
|
||||||
|
<el-main>
|
||||||
|
<RouterView />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pure-account-settings {
|
||||||
|
background: $menuBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-account-settings-menu {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.el-menu-item {
|
||||||
|
height: 48px !important;
|
||||||
|
color: $menuText;
|
||||||
|
background-color: transparent !important;
|
||||||
|
transition: color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $menuTitleHover !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
color: #fff !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0 8px;
|
||||||
|
margin: 4px 0;
|
||||||
|
clear: both;
|
||||||
|
content: '';
|
||||||
|
background: var(--el-color-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
body[layout] {
|
||||||
|
.el-menu--vertical .is-active {
|
||||||
|
color: #fff !important;
|
||||||
|
transition: color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import SplitPane from '@/components/SplitPane';
|
||||||
|
import MessageEditorFrom from '@/views/message-management/message-editing/message-editor-from.vue';
|
||||||
|
import RichEditor from '@/views/message-management/message-editing/rich-editor.vue';
|
||||||
|
import { formState } from '@/views/message-management/message-editing/utils/hooks';
|
||||||
|
import MarkdownEditor from '@/views/message-management/message-editing/markdown-editor.vue';
|
||||||
|
import { settingLR } from '@/views/message-management/message-editing/utils/columns';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<div class="split-pane">
|
||||||
|
<SplitPane :splitSet="settingLR">
|
||||||
|
<template #paneL>
|
||||||
|
<rich-editor v-if="formState.editorType === 'rich'" />
|
||||||
|
<markdown-editor v-else />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #paneR>
|
||||||
|
<message-editor-from />
|
||||||
|
</template>
|
||||||
|
</SplitPane>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.split-pane {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,7 +2,7 @@
|
||||||
import { MdEditor } from 'md-editor-v3';
|
import { MdEditor } from 'md-editor-v3';
|
||||||
import 'md-editor-v3/lib/style.css';
|
import 'md-editor-v3/lib/style.css';
|
||||||
import { fetchUploadFile } from '@/api/v1/system';
|
import { fetchUploadFile } from '@/api/v1/system';
|
||||||
import { formState } from '@/views/messageManagement/messageEditing/utils/hooks';
|
import { formState } from '@/views/message-management/message-editing/utils/hooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 上传图片
|
* * 上传图片
|
|
@ -1,10 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { beforeUpload, coverUrl, formState, loading, onSearchUserinfo, onUpload, userDataList } from '@/views/messageManagement/messageEditing/utils/hooks';
|
import { beforeUpload, coverUrl, formState, loading, onSearchUserinfo, onUpload, userDataList } from '@/views/message-management/message-editing/utils/hooks';
|
||||||
import { onMounted, ref, toRaw } from 'vue';
|
import { onMounted, ref, toRaw } from 'vue';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { rules } from '@/views/messageManagement/messageEditing/utils/columns';
|
import { messageLevel, rules } from '@/views/message-management/message-editing/utils/columns';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { editorTypeList } from '@/views/messageManagement/message/utils/columns';
|
import { editorTypeList } from '@/views/message-management/message/utils/columns';
|
||||||
import LoadingSvg from '@/assets/svg/loading.svg';
|
import LoadingSvg from '@/assets/svg/loading.svg';
|
||||||
import { useMessageTypeStore } from '@/store/message/messageType';
|
import { useMessageTypeStore } from '@/store/message/messageType';
|
||||||
import { encode } from 'js-base64';
|
import { encode } from 'js-base64';
|
||||||
|
@ -57,6 +57,7 @@ onMounted(() => {
|
||||||
messageTypeStore.getAllMessageTypeList();
|
messageTypeStore.getAllMessageTypeList();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="formRef" :model="formState" :rules="rules" class="w-[100%] p-5" label-width="auto">
|
<el-form ref="formRef" :model="formState" :rules="rules" class="w-[100%] p-5" label-width="auto">
|
||||||
<!-- 标题 -->
|
<!-- 标题 -->
|
||||||
|
@ -117,6 +118,18 @@ onMounted(() => {
|
||||||
<el-input v-model="formState.summary" :autosize="{ minRows: 3, maxRows: 6 }" maxlength="200" minlength="10" show-word-limit type="textarea" />
|
<el-input v-model="formState.summary" :autosize="{ minRows: 3, maxRows: 6 }" maxlength="200" minlength="10" show-word-limit type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 消息等级 -->
|
||||||
|
<el-form-item :label="$t('level')" prop="level">
|
||||||
|
<el-select v-model="formState.level" :placeholder="$t('level')" clearable filterable remote remote-show-suffix>
|
||||||
|
<el-option v-for="item in messageLevel" :key="item" :label="$t(item)" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 消息等级简介 -->
|
||||||
|
<el-form-item :label="$t('extra')" prop="extra">
|
||||||
|
<el-input v-model="formState.extra" maxlength="20" minlength="10" show-word-limit type="text" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 提交 -->
|
<!-- 提交 -->
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="submitForm(formRef)">{{ $t('submit') }}</el-button>
|
<el-button type="primary" @click="submitForm(formRef)">{{ $t('submit') }}</el-button>
|
|
@ -2,7 +2,7 @@
|
||||||
import { onBeforeUnmount, ref, shallowRef } from 'vue';
|
import { onBeforeUnmount, ref, shallowRef } from 'vue';
|
||||||
import '@wangeditor/editor/dist/css/style.css';
|
import '@wangeditor/editor/dist/css/style.css';
|
||||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||||
import { formState } from '@/views/messageManagement/messageEditing/utils/hooks';
|
import { formState } from '@/views/message-management/message-editing/utils/hooks';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
|
|
||||||
const mode = 'default';
|
const mode = 'default';
|
|
@ -1,4 +1,6 @@
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
|
import type { ContextProps } from '@/components/SplitPane';
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
export const rules = {
|
export const rules = {
|
||||||
// 消息标题
|
// 消息标题
|
||||||
|
@ -12,3 +14,11 @@ export const rules = {
|
||||||
// 消息简介
|
// 消息简介
|
||||||
summary: [{ required: true, message: `${$t('input')}${$t('summary')}`, trigger: 'blur' }],
|
summary: [{ required: true, message: `${$t('input')}${$t('summary')}`, trigger: 'blur' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const messageLevel = ['primary', 'success', 'warning', 'info', 'danger'];
|
||||||
|
|
||||||
|
export const settingLR: ContextProps = reactive({
|
||||||
|
minPercent: 20,
|
||||||
|
defaultPercent: 80,
|
||||||
|
split: 'vertical',
|
||||||
|
});
|
|
@ -20,6 +20,8 @@ export const formState = reactive({
|
||||||
editorType: 'markdown',
|
editorType: 'markdown',
|
||||||
status: false,
|
status: false,
|
||||||
summary: '',
|
summary: '',
|
||||||
|
level: '',
|
||||||
|
extra: '',
|
||||||
cover: '',
|
cover: '',
|
||||||
});
|
});
|
||||||
const adminUserStore = useAdminUserStore();
|
const adminUserStore = useAdminUserStore();
|
|
@ -1,10 +1,10 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { columns } from '@/views/messageManagement/messageType/utils/columns';
|
import { columns } from '@/views/message-management/message-type/utils/columns';
|
||||||
import PureTableBar from '@/components/TableBar/src/bar';
|
import PureTableBar from '@/components/TableBar/src/bar';
|
||||||
import AddFill from '@iconify-icons/ri/add-circle-line';
|
import AddFill from '@iconify-icons/ri/add-circle-line';
|
||||||
import PureTable from '@pureadmin/table';
|
import PureTable from '@pureadmin/table';
|
||||||
import { deleteIds, onAdd, onDelete, onDeleteBatch, onSearch, onUpdate } from '@/views/messageManagement/messageType/utils/hooks';
|
import { deleteIds, onAdd, onDelete, onDeleteBatch, onSearch, onUpdate } from '@/views/message-management/message-type/utils/hooks';
|
||||||
import Delete from '@iconify-icons/ep/delete';
|
import Delete from '@iconify-icons/ep/delete';
|
||||||
import EditPen from '@iconify-icons/ep/edit-pen';
|
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||||
import Refresh from '@iconify-icons/ep/refresh';
|
import Refresh from '@iconify-icons/ep/refresh';
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { rules } from '@/views/messageManagement/messageType/utils/columns';
|
import { rules } from '@/views/message-management/message-type/utils/columns';
|
||||||
import { FormProps } from '@/views/messageManagement/messageType/utils/types';
|
import { FormProps } from '@/views/message-management/message-type/utils/types';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { usePublicHooks } from '@/views/hooks';
|
import { usePublicHooks } from '@/views/hooks';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { addDialog } from '@/components/BaseDialog/index';
|
import { addDialog } from '@/components/BaseDialog/index';
|
||||||
import MessageTypeDialog from '@/views/messageManagement/messageType/message-type-dialog.vue';
|
import MessageTypeDialog from '@/views/message-management/message-type/message-type-dialog.vue';
|
||||||
import { useMessageTypeStore } from '@/store/message/messageType';
|
import { useMessageTypeStore } from '@/store/message/messageType';
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
import { message, messageBox } from '@/utils/message';
|
import { message, messageBox } from '@/utils/message';
|
||||||
import type { FormItemProps } from '@/views/messageManagement/messageType/utils/types';
|
import type { FormItemProps } from '@/views/message-management/message-type/utils/types';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { columns, editorTypeList } from '@/views/messageManagement/message/utils/columns';
|
import { columns } from '@/views/message-management/message/utils/columns';
|
||||||
import PureTableBar from '@/components/TableBar/src/bar';
|
import PureTableBar from '@/components/TableBar/src/bar';
|
||||||
import PureTable from '@pureadmin/table';
|
import PureTable from '@pureadmin/table';
|
||||||
import { deleteIds, onDelete, onDeleteBatch, onSearch, onUpdate } from '@/views/messageManagement/message/utils/hooks';
|
import { deleteIds, onDelete, onDeleteBatch, onSearch, onUpdate } from '@/views/message-management/message/utils/hooks';
|
||||||
import Delete from '@iconify-icons/ep/delete';
|
import Delete from '@iconify-icons/ep/delete';
|
||||||
import EditPen from '@iconify-icons/ep/edit-pen';
|
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||||
import Refresh from '@iconify-icons/ep/refresh';
|
import Refresh from '@iconify-icons/ep/refresh';
|
||||||
|
@ -12,6 +12,8 @@ import { $t } from '@/plugins/i18n';
|
||||||
import { useMessageStore } from '@/store/message/message';
|
import { useMessageStore } from '@/store/message/message';
|
||||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
|
import { messageLevel } from '@/views/message-management/message-editing/utils/columns';
|
||||||
|
import { isReadStatus } from '@/enums/baseConstant';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
@ -63,31 +65,28 @@ onMounted(() => {
|
||||||
<el-input v-model="messageStore.form.title" :placeholder="`${$t('input')}${$t('title')}`" class="!w-[180px]" clearable />
|
<el-input v-model="messageStore.form.title" :placeholder="`${$t('input')}${$t('title')}`" class="!w-[180px]" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 发送人昵称 -->
|
|
||||||
<el-form-item :label="$t('sendNickname')" prop="sendNickname">
|
|
||||||
<el-input v-model="messageStore.form.sendNickname" :placeholder="`${$t('input')}${$t('sendNickname')}`" class="!w-[180px]" clearable />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 消息类型 -->
|
<!-- 消息类型 -->
|
||||||
<el-form-item :label="$t('messageType')" prop="messageType">
|
<el-form-item :label="$t('messageType')" prop="messageType">
|
||||||
<el-input v-model="messageStore.form.messageType" :placeholder="`${$t('input')}${$t('messageType')}`" class="!w-[180px]" clearable />
|
<el-input v-model="messageStore.form.messageType" :placeholder="`${$t('input')}${$t('messageType')}`" class="!w-[180px]" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 消息内容 -->
|
<!-- 消息等级 -->
|
||||||
<el-form-item :label="$t('content')" prop="content">
|
<el-form-item :label="$t('level')" prop="level">
|
||||||
<el-input v-model="messageStore.form.content" :placeholder="`${$t('input')}${$t('content')}`" class="!w-[180px]" clearable />
|
<el-select v-model="messageStore.form.level" :placeholder="$t('level')" class="!w-[180px]" clearable filterable remote remote-show-suffix>
|
||||||
|
<el-option v-for="item in messageLevel" :key="item" :label="$t(item)" :value="item" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 编辑器类型 -->
|
<!-- 消息等级简介 -->
|
||||||
<el-form-item :label="$t('editorType')" prop="editorType">
|
<el-form-item :label="$t('extra')" prop="extra">
|
||||||
<el-select v-model="messageStore.form.editorType" :placeholder="`${$t('select')}${$t('editorType')}`" class="!w-[180px]" clearable filterable>
|
<el-input v-model="messageStore.form.extra" class="!w-[180px]" maxlength="20" minlength="10" show-word-limit type="text" />
|
||||||
<el-option v-for="(item, index) in editorTypeList" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 0:未读 1:已读 -->
|
<!-- 0:未读 1:已读 -->
|
||||||
<el-form-item :label="$t('status')" prop="status">
|
<el-form-item :label="$t('status')" prop="status">
|
||||||
<el-input v-model="messageStore.form.status" :placeholder="`${$t('input')}${$t('status')}`" class="!w-[180px]" clearable />
|
<el-select v-model="messageStore.form.status" :placeholder="$t('status')" class="!w-[180px]" clearable filterable remote remote-show-suffix>
|
||||||
|
<el-option v-for="(item, index) in isReadStatus" :key="index" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { MdEditor } from 'md-editor-v3';
|
||||||
|
import 'md-editor-v3/lib/style.css';
|
||||||
|
import { fetchUploadFile } from '@/api/v1/system';
|
||||||
|
import { updateMessage } from '@/views/message-management/message/utils/hooks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * 上传图片
|
||||||
|
* @param files
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
const onUploadImg = async (files: any, callback: any) => {
|
||||||
|
// 上传图片等待结果
|
||||||
|
const res = await Promise.all(
|
||||||
|
files.map((file: any) => {
|
||||||
|
return new Promise(async resolve => {
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('file', file);
|
||||||
|
form.append('type', 'message');
|
||||||
|
resolve(await fetchUploadFile(form));
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 插入图片内容
|
||||||
|
callback(res.map(item => item.data.url));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<MdEditor v-model="updateMessage.content" :showToolbarName="true" style="height: calc(100vh - 120px)" @onUploadImg="onUploadImg" />
|
||||||
|
</template>
|
|
@ -0,0 +1,134 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { FormInstance } from 'element-plus';
|
||||||
|
import { editorTypeList, rules } from '@/views/message-management/message/utils/columns';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
import { usePublicHooks } from '@/views/hooks';
|
||||||
|
import { useMessageTypeStore } from '@/store/message/messageType';
|
||||||
|
import LoadingSvg from '@/assets/svg/loading.svg';
|
||||||
|
import { coverUrl, loading, onSearchUserinfo, onUpload, updateMessage, userDataList } from '@/views/message-management/message/utils/hooks';
|
||||||
|
import { messageLevel, settingLR } from '@/views/message-management/message-editing/utils/columns';
|
||||||
|
import { Plus } from '@element-plus/icons-vue';
|
||||||
|
import { beforeUpload } from '@/views/message-management/message-editing/utils/hooks';
|
||||||
|
import SplitPane from '@/components/SplitPane';
|
||||||
|
import RichEditor from '@/views/message-management/message/rich-editor.vue';
|
||||||
|
import MarkdownEditor from '@/views/message-management/message/markdown-editor.vue';
|
||||||
|
|
||||||
|
// 用户是否停用样式
|
||||||
|
const { switchStyle } = usePublicHooks();
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const messageTypeStore = useMessageTypeStore();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
messageTypeStore.getAllMessageTypeList();
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({ formRef });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never" style="height: calc(100vh - 200px); overflow: auto">
|
||||||
|
<div class="split-pane">
|
||||||
|
<SplitPane :splitSet="settingLR">
|
||||||
|
<template #paneL>
|
||||||
|
<rich-editor v-if="updateMessage.editorType === 'rich'" />
|
||||||
|
<markdown-editor v-else />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #paneR>
|
||||||
|
<el-form ref="formRef" :model="updateMessage" :rules="rules" class="w-[100%] p-5" label-width="auto">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<el-form-item :label="$t('title')" prop="title">
|
||||||
|
<el-input v-model="updateMessage.title" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 消息类型 -->
|
||||||
|
<el-form-item :label="$t('messageType')" prop="messageType">
|
||||||
|
<el-select v-model="updateMessage.messageType" :placeholder="`${$t('select')}${$t('messageType')}`" clearable filterable>
|
||||||
|
<el-option v-for="(item, index) in messageTypeStore.allMessageTypeList" :key="index" :label="item.messageName" :navigationBar="false" :value="item.messageType" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 接收人ID -->
|
||||||
|
<el-form-item :label="$t('receivedUserIds')" prop="receivedUserIds">
|
||||||
|
<el-select
|
||||||
|
v-model="updateMessage.receivedUserIds"
|
||||||
|
:loading="loading"
|
||||||
|
:placeholder="$t('receivedUserIdTip')"
|
||||||
|
:remote-method="onSearchUserinfo"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
multiple
|
||||||
|
remote
|
||||||
|
remote-show-suffix
|
||||||
|
>
|
||||||
|
<el-option v-for="item in userDataList" :key="item.id" :label="item.username" :value="item.id" />
|
||||||
|
<template #loading>
|
||||||
|
<el-icon class="is-loading">
|
||||||
|
<LoadingSvg />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 编辑器类型 -->
|
||||||
|
<el-form-item :label="$t('editorType')" prop="editorType">
|
||||||
|
<el-radio-group v-model="updateMessage.editorType">
|
||||||
|
<el-radio v-for="(item, index) in editorTypeList" :key="index" :navigationBar="false" :value="item.value">
|
||||||
|
{{ item.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 是否已读 -->
|
||||||
|
<el-form-item :label="$t('isRead')" prop="status">
|
||||||
|
<el-switch v-model="updateMessage.status" :active-text="$t('readAlready')" :active-value="true" :inactive-text="$t('unread')" :inactive-value="false" :style="switchStyle" inline-prompt />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 封面内容 -->
|
||||||
|
<el-form-item :label="$t('cover')" prop="cover">
|
||||||
|
<el-upload :auto-upload="true" :before-upload="beforeUpload" :http-request="onUpload" :show-file-list="false" accept="image/*" drag>
|
||||||
|
<el-image v-if="coverUrl" :src="coverUrl" fit="cover" lazy>
|
||||||
|
<template #placeholder>
|
||||||
|
<img alt="" src="@/assets/images/tip/loading.gif" />
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
<el-icon v-else size="36">
|
||||||
|
<Plus />
|
||||||
|
</el-icon>
|
||||||
|
</el-upload>
|
||||||
|
<el-button v-show="coverUrl" link type="primary" @click="coverUrl = ''"> 删除图片</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 简介 -->
|
||||||
|
<el-form-item :label="$t('summary')" prop="summary">
|
||||||
|
<el-input v-model="updateMessage.summary" :autosize="{ minRows: 3, maxRows: 6 }" maxlength="200" minlength="10" show-word-limit type="textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 消息等级 -->
|
||||||
|
<el-form-item :label="$t('level')" prop="level">
|
||||||
|
<el-select v-model="updateMessage.level" :placeholder="$t('level')" clearable filterable remote remote-show-suffix>
|
||||||
|
<el-option v-for="item in messageLevel" :key="item" :label="$t(item)" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 消息等级简介 -->
|
||||||
|
<el-form-item :label="$t('extra')" prop="extra">
|
||||||
|
<el-input v-model="updateMessage.extra" maxlength="20" minlength="10" show-word-limit type="text" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
</SplitPane>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.el-upload-dragger) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onBeforeUnmount, ref, shallowRef } from 'vue';
|
||||||
|
import '@wangeditor/editor/dist/css/style.css';
|
||||||
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||||
|
import { getToken } from '@/utils/auth';
|
||||||
|
import { updateMessage } from '@/views/message-management/message/utils/hooks';
|
||||||
|
|
||||||
|
const mode = 'default';
|
||||||
|
// 编辑器实例,必须用 shallowRef
|
||||||
|
const editorRef = shallowRef();
|
||||||
|
const toolbarConfig: any = { excludeKeys: 'fullScreen' };
|
||||||
|
const editorConfig = { placeholder: '请输入内容...', MENU_CONF: {} };
|
||||||
|
const token = ref(getToken().token);
|
||||||
|
|
||||||
|
editorConfig.MENU_CONF['uploadImage'] = {
|
||||||
|
// 服务端上传地址,根据实际业务改写
|
||||||
|
server: '/api/files/upload',
|
||||||
|
// form-data 的 fieldName,根据实际业务改写
|
||||||
|
fieldName: 'file',
|
||||||
|
// 选择文件时的类型限制,根据实际业务改写
|
||||||
|
allowedFileTypes: ['image/png', 'image/jpg', 'image/jpeg'],
|
||||||
|
meta: { type: 'message' },
|
||||||
|
headers: { token: token.value },
|
||||||
|
// 自定义插入图片
|
||||||
|
customInsert(res: any, insertFn) {
|
||||||
|
// res.data.url是后端返回的图片地址,根据实际业务改写
|
||||||
|
if (res.data.url) {
|
||||||
|
// const form = new FormData();
|
||||||
|
// form.append('file', file);
|
||||||
|
// form.append('type', 'message');
|
||||||
|
// await fetchUploadFile(form)
|
||||||
|
setTimeout(() => {
|
||||||
|
// insertFn插入图片进编辑器
|
||||||
|
insertFn(res.data.url);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreated = editor => {
|
||||||
|
// 记录 editor 实例,重要!
|
||||||
|
editorRef.value = editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件销毁时,也及时销毁编辑器
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
const editor = editorRef.value;
|
||||||
|
if (editor == null) return;
|
||||||
|
editor.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="wangeditor">
|
||||||
|
<Toolbar :defaultConfig="toolbarConfig" :editor="editorRef" :mode="mode" style="border-bottom: 1px solid #ccc" />
|
||||||
|
<Editor v-model="updateMessage.content" :defaultConfig="editorConfig" :mode="mode" style="height: 500px; overflow-y: hidden" @onCreated="handleCreated" />
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,6 +1,7 @@
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import type { FormRules } from 'element-plus';
|
import type { FormRules } from 'element-plus';
|
||||||
|
import { ElTag } from 'element-plus';
|
||||||
|
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
|
@ -8,28 +9,28 @@ export const columns: TableColumnList = [
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
||||||
// 消息标题
|
// 消息标题
|
||||||
{ label: $t('title'), prop: 'title' },
|
{ label: $t('title'), prop: 'title' },
|
||||||
// 接收人用户ID
|
|
||||||
{
|
|
||||||
label: $t('receivedUserIds'),
|
|
||||||
prop: 'receivedUserIds',
|
|
||||||
formatter({ receivedUserIds }) {
|
|
||||||
return !receivedUserIds ? $t('all') : $t('portion');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 发送人昵称
|
// 发送人昵称
|
||||||
{ label: $t('sendNickname'), prop: 'sendNickname' },
|
{ label: $t('sendNickname'), prop: 'sendNickname' },
|
||||||
// 消息类型
|
// 消息类型
|
||||||
{ label: $t('messageType'), prop: 'messageType' },
|
{ label: $t('messageType'), prop: 'messageType' },
|
||||||
// 消息内容
|
|
||||||
{ label: $t('content'), prop: 'content' },
|
|
||||||
// 编辑器类型
|
// 编辑器类型
|
||||||
{ label: $t('editorType'), prop: 'editorType' },
|
{ label: $t('editorType'), prop: 'editorType' },
|
||||||
|
// 编辑器类型
|
||||||
|
{
|
||||||
|
label: $t('level'),
|
||||||
|
prop: 'level',
|
||||||
|
formatter({ level }) {
|
||||||
|
return <ElTag type={level}>{$t(level)}</ElTag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 编辑器类型
|
||||||
|
{ label: $t('extra'), prop: 'extra' },
|
||||||
// 0:未读 1:已读
|
// 0:未读 1:已读
|
||||||
{
|
{
|
||||||
label: $t('status'),
|
label: $t('status'),
|
||||||
prop: 'status',
|
prop: 'status',
|
||||||
formatter({ status }) {
|
formatter({ status }) {
|
||||||
return status ? $t('readAlready') : $t('unread');
|
return status ? <ElTag type={'info'}>{$t('readAlready')}</ElTag> : <ElTag type={'primary'}>{$t('unread')}</ElTag>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true, width: 160 },
|
{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true, width: 160 },
|
|
@ -1,20 +1,51 @@
|
||||||
import { addDialog } from '@/components/BaseDialog/index';
|
import { addDialog } from '@/components/BaseDialog/index';
|
||||||
import MessageDialog from '@/views/messageManagement/message/message-dialog.vue';
|
import MessageDialog from '@/views/message-management/message/message-dialog.vue';
|
||||||
import { useMessageStore } from '@/store/message/message';
|
import { useMessageStore } from '@/store/message/message';
|
||||||
import { h, ref } from 'vue';
|
import { h, reactive, ref, toRaw } from 'vue';
|
||||||
import { message, messageBox } from '@/utils/message';
|
import { message, messageBox } from '@/utils/message';
|
||||||
import type { FormItemProps } from '@/views/messageManagement/message/utils/types';
|
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
||||||
import { useAdminUserStore } from '@/store/system/adminUser';
|
import { useAdminUserStore } from '@/store/system/adminUser';
|
||||||
|
import { fetchGetReceivedUserinfoByMessageId } from '@/api/v1/message';
|
||||||
|
import { decode, encode } from 'js-base64';
|
||||||
|
import type { UploadRequestOptions } from 'element-plus';
|
||||||
|
import { fetchUploadFile } from '@/api/v1/system';
|
||||||
|
|
||||||
export const formRef = ref();
|
export const formRef = ref();
|
||||||
// 删除ids
|
// 删除ids
|
||||||
export const deleteIds = ref([]);
|
export const deleteIds = ref([]);
|
||||||
// 用户信息列表
|
// 用户信息列表
|
||||||
export const userDataList = ref();
|
export const userDataList = ref();
|
||||||
|
// 更新时封面图片
|
||||||
|
export const coverUrl = ref('');
|
||||||
// 搜索用户加载
|
// 搜索用户加载
|
||||||
export const loading = ref(false);
|
export const loading = ref(false);
|
||||||
|
export const updateMessage = reactive({
|
||||||
|
// 消息标题
|
||||||
|
title: undefined,
|
||||||
|
// 封面
|
||||||
|
cover: undefined,
|
||||||
|
// 接收人用户ID
|
||||||
|
receivedUserIds: undefined,
|
||||||
|
// 发送人用户ID
|
||||||
|
sendUserId: undefined,
|
||||||
|
// 发送人昵称
|
||||||
|
sendNickName: undefined,
|
||||||
|
// 消息类型
|
||||||
|
messageType: undefined,
|
||||||
|
// 消息内容
|
||||||
|
content: undefined,
|
||||||
|
// 简介
|
||||||
|
summary: undefined,
|
||||||
|
// 消息等级
|
||||||
|
level: undefined,
|
||||||
|
// 消息等级类型
|
||||||
|
extra: undefined,
|
||||||
|
// 编辑器类型
|
||||||
|
editorType: undefined,
|
||||||
|
// 0:未读 1:已读
|
||||||
|
status: undefined,
|
||||||
|
});
|
||||||
const messageStore = useMessageStore();
|
const messageStore = useMessageStore();
|
||||||
const adminUserStore = useAdminUserStore();
|
const adminUserStore = useAdminUserStore();
|
||||||
|
|
||||||
|
@ -25,39 +56,55 @@ export async function onSearch() {
|
||||||
messageStore.loading = false;
|
messageStore.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 搜索 */
|
||||||
|
export const onSearchUserinfo = async (keyword: string) => {
|
||||||
|
loading.value = true;
|
||||||
|
userDataList.value = await adminUserStore.queryUser({ keyword });
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 更新系统消息
|
* * 更新系统消息
|
||||||
* @param row
|
* @param row
|
||||||
*/
|
*/
|
||||||
export async function onUpdate(row: any) {
|
export async function onUpdate(row: any) {
|
||||||
await onSearchUserinfo('');
|
// 将表格数据合并到更新数据中
|
||||||
|
Object.assign(updateMessage, row);
|
||||||
|
|
||||||
|
// 解码内容
|
||||||
|
updateMessage.content = decode(row.content);
|
||||||
|
|
||||||
|
// 获取当前消息内容和接收者信息
|
||||||
|
const result = await fetchGetReceivedUserinfoByMessageId({ messageId: row.id });
|
||||||
|
userDataList.value = result.data.map((item: any) => ({
|
||||||
|
id: item.receivedUserId,
|
||||||
|
nickname: item.nickname,
|
||||||
|
username: item.username,
|
||||||
|
}));
|
||||||
|
updateMessage.receivedUserIds = result.data.map((item: any) => item.receivedUserId);
|
||||||
|
|
||||||
|
// 设置封面图片
|
||||||
|
coverUrl.value = row.cover;
|
||||||
|
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `${$t('modify')}${$t('message')}`,
|
title: `${$t('modify')}${$t('message')}`,
|
||||||
width: '30%',
|
width: '85%',
|
||||||
props: {
|
|
||||||
formInline: {
|
|
||||||
title: row.title,
|
|
||||||
receivedUserIds: row.receivedUserIds ? row.receivedUserIds.split(',') : row.receivedUserIds,
|
|
||||||
sendUserId: row.sendUserId,
|
|
||||||
sendNickName: row.sendNickName,
|
|
||||||
messageType: row.messageType,
|
|
||||||
content: row.content,
|
|
||||||
editorType: row.editorType,
|
|
||||||
status: row.status,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
draggable: true,
|
draggable: true,
|
||||||
fullscreenIcon: true,
|
fullscreenIcon: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
contentRenderer: () => h(MessageDialog, { ref: formRef }),
|
contentRenderer: () => h(MessageDialog, { ref: formRef }),
|
||||||
beforeSure: (done, { options }) => {
|
beforeSure: done => {
|
||||||
const form = options.props.formInline as FormItemProps;
|
|
||||||
formRef.value.formRef.validate(async (valid: any) => {
|
formRef.value.formRef.validate(async (valid: any) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
|
||||||
const result = await messageStore.updateMessage({ ...form, id: row.id });
|
// 将更新的信息进行编码
|
||||||
|
const data = toRaw(updateMessage);
|
||||||
|
data.content = encode(data.content);
|
||||||
|
|
||||||
|
// 更新消息内容
|
||||||
|
const result = await messageStore.updateMessage({ ...data, id: row.id });
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
|
Object.assign(updateMessage, {});
|
||||||
done();
|
done();
|
||||||
await onSearch();
|
await onSearch();
|
||||||
});
|
});
|
||||||
|
@ -113,9 +160,10 @@ export const onDeleteBatch = async () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 搜索 */
|
/** 上传时 */
|
||||||
export const onSearchUserinfo = async (keyword: string) => {
|
export const onUpload = async (options: UploadRequestOptions) => {
|
||||||
loading.value = true;
|
const data = { file: options.file, type: 'message' };
|
||||||
userDataList.value = await adminUserStore.queryUser({ keyword });
|
const result: any = await fetchUploadFile(data);
|
||||||
loading.value = false;
|
coverUrl.value = result.data.url;
|
||||||
|
updateMessage.cover = result.data.filepath;
|
||||||
};
|
};
|
|
@ -10,6 +10,10 @@ export interface FormItemProps {
|
||||||
messageType: string;
|
messageType: string;
|
||||||
// 消息内容
|
// 消息内容
|
||||||
content: string;
|
content: string;
|
||||||
|
// 消息等级
|
||||||
|
level: string;
|
||||||
|
// 消息等级类型
|
||||||
|
extra: string;
|
||||||
// 编辑器类型
|
// 编辑器类型
|
||||||
editorType: string;
|
editorType: string;
|
||||||
// 0:未读 1:已读
|
// 0:未读 1:已读
|
|
@ -1,100 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
import { FormInstance } from 'element-plus';
|
|
||||||
import { editorTypeList, rules } from '@/views/messageManagement/message/utils/columns';
|
|
||||||
import { FormProps } from '@/views/messageManagement/message/utils/types';
|
|
||||||
import { $t } from '@/plugins/i18n';
|
|
||||||
import { usePublicHooks } from '@/views/hooks';
|
|
||||||
import { useMessageTypeStore } from '@/store/message/messageType';
|
|
||||||
import LoadingSvg from '@/assets/svg/loading.svg';
|
|
||||||
import { loading, onSearchUserinfo, userDataList } from '@/views/messageManagement/message/utils/hooks';
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<FormProps>(), {
|
|
||||||
formInline: () => ({
|
|
||||||
// 消息标题
|
|
||||||
title: undefined,
|
|
||||||
// 接收人用户ID
|
|
||||||
receivedUserIds: undefined,
|
|
||||||
// 发送人用户ID
|
|
||||||
sendUserId: undefined,
|
|
||||||
// 发送人昵称
|
|
||||||
sendNickName: undefined,
|
|
||||||
// 消息类型
|
|
||||||
messageType: undefined,
|
|
||||||
// 消息内容
|
|
||||||
content: undefined,
|
|
||||||
// 编辑器类型
|
|
||||||
editorType: undefined,
|
|
||||||
// 0:未读 1:已读
|
|
||||||
status: undefined,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
// 用户是否停用样式
|
|
||||||
const { switchStyle } = usePublicHooks();
|
|
||||||
const formRef = ref<FormInstance>();
|
|
||||||
const form = ref(props.formInline);
|
|
||||||
const messageTypeStore = useMessageTypeStore();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
messageTypeStore.getAllMessageTypeList();
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({ formRef });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
|
|
||||||
<!-- 消息标题 -->
|
|
||||||
<el-form-item :label="$t('title')" prop="title">
|
|
||||||
<el-input v-model="form.title" :placeholder="$t('input') + $t('title')" autocomplete="off" maxlength="100" type="text" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 接收人用户ID -->
|
|
||||||
<el-form-item :label="$t('receivedUserIds')" prop="receivedUserIds">
|
|
||||||
<el-select v-model="form.receivedUserIds" :loading="loading" :placeholder="$t('receivedUserIdTip')" :remote-method="onSearchUserinfo" clearable filterable multiple remote remote-show-suffix>
|
|
||||||
<el-option v-for="item in userDataList" :key="item.id" :label="item.username" :value="item.id" />
|
|
||||||
<template #loading>
|
|
||||||
<el-icon class="is-loading">
|
|
||||||
<LoadingSvg />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 发送人用户ID -->
|
|
||||||
<el-form-item :label="$t('sendUserId')" prop="sendUserId">
|
|
||||||
<el-select v-model="form.sendUserId" :loading="loading" :placeholder="$t('select') + $t('sendUserId')" :remote-method="onSearchUserinfo" clearable filterable remote remote-show-suffix>
|
|
||||||
<el-option v-for="item in userDataList" :key="item.id" :label="item.username" :value="item.id" />
|
|
||||||
<template #loading>
|
|
||||||
<el-icon class="is-loading">
|
|
||||||
<LoadingSvg />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 消息类型 -->
|
|
||||||
<el-form-item :label="$t('messageType')" prop="messageType">
|
|
||||||
<el-select v-model="form.messageType" :placeholder="`${$t('select')}${$t('messageType')}`" clearable filterable>
|
|
||||||
<el-option v-for="(item, index) in messageTypeStore.allMessageTypeList" :key="index" :label="item.messageName" :navigationBar="false" :value="item.messageType" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 编辑器类型 -->
|
|
||||||
<el-form-item :label="$t('editorType')" prop="editorType">
|
|
||||||
<el-select v-model="form.editorType" :placeholder="`${$t('select')}${$t('editorType')}`" clearable filterable>
|
|
||||||
<el-option v-for="(item, index) in editorTypeList" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 消息内容 -->
|
|
||||||
<el-form-item :label="$t('content')" prop="content">
|
|
||||||
<el-input v-model="form.content" :placeholder="$t('input') + $t('content')" autocomplete="off" type="textarea" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 0:未读 1:已读 -->
|
|
||||||
<el-form-item :label="$t('status')" prop="status">
|
|
||||||
<el-switch v-model="form.status" :active-text="$t('readAlready')" :active-value="true" :inactive-text="$t('unread')" :inactive-value="false" :style="switchStyle" inline-prompt />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
|
|
@ -1,38 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import splitpane, { ContextProps } from '@/components/SplitPane';
|
|
||||||
import { reactive } from 'vue';
|
|
||||||
import MessageEditorFrom from '@/views/messageManagement/messageEditing/message-editor-from.vue';
|
|
||||||
import RichEditor from '@/views/messageManagement/messageEditing/rich-editor.vue';
|
|
||||||
import { formState } from '@/views/messageManagement/messageEditing/utils/hooks';
|
|
||||||
import MarkdownEditor from '@/views/messageManagement/messageEditing/markdown-editor.vue';
|
|
||||||
|
|
||||||
const settingLR: ContextProps = reactive({
|
|
||||||
minPercent: 20,
|
|
||||||
defaultPercent: 80,
|
|
||||||
split: 'vertical',
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<el-card shadow="never">
|
|
||||||
<div class="split-pane">
|
|
||||||
<splitpane :splitSet="settingLR">
|
|
||||||
<template #paneL>
|
|
||||||
<RichEditor v-if="formState.editorType === 'rich'" />
|
|
||||||
<markdown-editor v-else />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #paneR>
|
|
||||||
<message-editor-from />
|
|
||||||
</template>
|
|
||||||
</splitpane>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.split-pane {
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100vh - 120px);
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue