通知公告样式优化,业务单号规则页面
This commit is contained in:
parent
48a255ff27
commit
3550f07731
32
src/api/system/baseCodeRole.ts
Normal file
32
src/api/system/baseCodeRole.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export const addBaseCodeRule = (data: any) => {
|
||||
return request({
|
||||
url: 'base/codeRule/addBaseCodeRule',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteBaseCodeRule = (code: any) => {
|
||||
return request({
|
||||
url: 'base/codeRule/deleteBaseCodeRule' + '/' + code,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export const getBaseCodeRuleList = (params: any) => {
|
||||
return request({
|
||||
url: 'base/codeRule/getBaseCodeRuleList',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export const updateBaseCodeRule = (data: any) => {
|
||||
return request({
|
||||
url: 'base/codeRule/updateBaseCodeRule',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-popover placement="bottom" trigger="hover" width="300px" popper-class="el-popover-pupop-user-news">
|
||||
<el-popover placement="bottom" trigger="hover" width="400px" popper-class="el-popover-pupop-user-news">
|
||||
<template #reference>
|
||||
<el-badge :is-dot="noticeDot" style="line-height: 18px">
|
||||
<el-icon><bell /></el-icon>
|
||||
@ -14,42 +14,34 @@
|
||||
</template>
|
||||
<div class="content-box">
|
||||
<template v-if="unreadNoticeList.length > 0">
|
||||
<div class="content-box-item" v-for="(v, k) in unreadNoticeList" :key="k">
|
||||
<el-link :type="v.isRead ? 'primary' : 'danger'" @click="viewNoticeDetail(v.noticeId, v.isRead, v.noticeContent)">{{
|
||||
v.noticeTitle
|
||||
}}</el-link>
|
||||
<el-divider />
|
||||
<div class="content-box-time">{{ v.updateTime }}</div>
|
||||
<div
|
||||
class="content-box-item"
|
||||
v-for="item in unreadNoticeList"
|
||||
@click="viewNoticeDetail({ ...item, noticeType: NoticeType.notice })">
|
||||
<el-icon :size="30" color="#409EFF"><bell /></el-icon>
|
||||
<div class="content">
|
||||
<div class="title">{{ item.noticeTitle }}</div>
|
||||
<div class="content-box-time">{{ formatDate(item.create_time) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="content-box-empty" v-if="unreadNoticeList.length === 0">
|
||||
<div class="content-box-empty-margin">
|
||||
<el-icon><Promotion /></el-icon>
|
||||
<div class="mt15">全部已读</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></el-tab-pane
|
||||
>
|
||||
<el-empty v-if="unreadNoticeList.length <= 0" :image-size="60" description="暂无通知公告"></el-empty></div
|
||||
></el-tab-pane>
|
||||
<el-tab-pane name="aimMsg">
|
||||
<template #label>
|
||||
<el-badge :value="unreadAimList.length" style="line-height: 18px" :hidden="unreadAimList.length === 0"> 业务信息 </el-badge>
|
||||
</template>
|
||||
<div class="content-box">
|
||||
<template v-if="unreadAimList.length > 0">
|
||||
<div class="content-box-item" v-for="(v, k) in unreadAimList" :key="k">
|
||||
<el-link :type="v.isRead ? 'primary' : 'danger'" @click="viewAimMsgDetail(v.noticeId, v.isRead, v.noticeContent)">{{
|
||||
v.noticeTitle
|
||||
}}</el-link>
|
||||
<el-divider />
|
||||
<div class="content-box-time">{{ v.updateTime }}</div>
|
||||
<div class="content-box-item" v-for="item in unreadAimList" @click="viewNoticeDetail({ ...item, noticeType: NoticeType.aimMsg })">
|
||||
<el-icon :size="30" color="#409EFF"><bell /></el-icon>
|
||||
<div class="content">
|
||||
<div class="title">{{ item.noticeTitle }}</div>
|
||||
<div class="content-box-time">{{ formatDate(item.create_time) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="content-box-empty" v-if="unreadAimList.length === 0">
|
||||
<div class="content-box-empty-margin">
|
||||
<el-icon><Promotion /></el-icon>
|
||||
<div class="mt15">全部已读</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-if="unreadAimList.length <= 0" :image-size="60" description="暂无业务信息"></el-empty>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@ -66,86 +58,102 @@
|
||||
</div>
|
||||
</el-popover>
|
||||
|
||||
<el-dialog v-model="noticeDialogOpen" title="查看通知详情" draggable :close-on-click-modal="false">
|
||||
<noticeDialog v-model="form.noticeContent" />
|
||||
</el-dialog>
|
||||
<noticeDialog v-model="noticeDialogOpen" :notice-model="info" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="noticeIndex">
|
||||
<script setup name="noticeIndex" lang="ts">
|
||||
import useSocketStore from '@/store/modules/socket'
|
||||
import signalR from '@/utils/signalR'
|
||||
import signalR from '@/signalr'
|
||||
import noticeDialog from './noticeDialog/index.vue'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
const router = useRouter()
|
||||
const { proxy } = getCurrentInstance()
|
||||
const activeTab = ref('notice')
|
||||
// 小红点
|
||||
const newsDot = ref(false)
|
||||
|
||||
enum NoticeType {
|
||||
notice = 1,
|
||||
aimMsg = 2,
|
||||
chat = 3
|
||||
}
|
||||
interface noticeInfo {
|
||||
noticeId: string
|
||||
noticeTitle: string
|
||||
noticeContent: string
|
||||
noticeType: NoticeType
|
||||
isRead: boolean
|
||||
create_name: string
|
||||
create_time: string
|
||||
}
|
||||
const noticeDot = computed(() => {
|
||||
return useSocketStore().noticeDot
|
||||
})
|
||||
const readNoticeList = computed(() => {
|
||||
return useSocketStore().readNoticeList
|
||||
})
|
||||
const unreadNoticeList = computed(() => {
|
||||
const unreadNoticeList = computed<any[]>(() => {
|
||||
return useSocketStore().unreadNoticeList
|
||||
})
|
||||
const noticeList = computed(() => {
|
||||
const noticeList = computed<any[]>(() => {
|
||||
return readNoticeList.value
|
||||
.map((item) => ({
|
||||
.map((item: any) => ({
|
||||
...item,
|
||||
isRead: true
|
||||
}))
|
||||
.concat(unreadNoticeList.value.map((item) => ({ ...item, isRead: false })))
|
||||
})
|
||||
const readAimList = computed(() => {
|
||||
const readAimList = computed<any[]>(() => {
|
||||
return useSocketStore().readAimList
|
||||
})
|
||||
const unreadAimList = computed(() => {
|
||||
const unreadAimList = computed<any[]>(() => {
|
||||
return useSocketStore().unreadAimList
|
||||
})
|
||||
const aimList = computed(() => {
|
||||
const aimList = computed<any[]>(() => {
|
||||
return readAimList.value
|
||||
.map((item) => ({
|
||||
.map((item: any) => ({
|
||||
...item,
|
||||
isRead: true
|
||||
}))
|
||||
.concat(unreadAimList.value.map((item) => ({ ...item, isRead: false })))
|
||||
})
|
||||
// console.log(noticeList.value)
|
||||
// 全部已读点击
|
||||
function onAllReadClick() {
|
||||
// newsDot.value = false
|
||||
if (activeTab.value === 'notice') {
|
||||
signalR.AllReadNotice()
|
||||
} else {
|
||||
signalR.AllReadAimMsg()
|
||||
}
|
||||
}
|
||||
// 前往通知中心点击
|
||||
function onGoToGiteeClick() {
|
||||
window.open('https://gitee.com/izory/ZrAdminNetCore')
|
||||
}
|
||||
const form = ref({
|
||||
noticeContent: ''
|
||||
const info = ref<noticeInfo>({
|
||||
noticeId: '',
|
||||
noticeTitle: '',
|
||||
noticeContent: '',
|
||||
noticeType: NoticeType.notice,
|
||||
isRead: false,
|
||||
create_name: '',
|
||||
create_time: ''
|
||||
})
|
||||
const noticeDialogOpen = ref(false)
|
||||
const viewNoticeDetail = (noticeId, isRead, noticeContent) => {
|
||||
if (!isRead) signalR.ReadNotice(noticeId)
|
||||
const viewNoticeDetail = (notice: noticeInfo) => {
|
||||
noticeDialogOpen.value = true
|
||||
form.value.noticeContent = noticeContent
|
||||
}
|
||||
const viewAimMsgDetail = (noticeId, isRead, noticeContent) => {
|
||||
if (!isRead) signalR.ReadAimMsg(noticeId)
|
||||
noticeDialogOpen.value = true
|
||||
form.value.noticeContent = noticeContent
|
||||
info.value = notice
|
||||
}
|
||||
// 前往通知中心点击
|
||||
const viewMoreNotice = () => {
|
||||
router.push({ path: '/notice/center' })
|
||||
}
|
||||
const formatDate = (dateTime) => {
|
||||
const dateObj = new Date(dateTime)
|
||||
const options: any = {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
// hour: '2-digit',
|
||||
// minute: '2-digit',
|
||||
// second: '2-digit'
|
||||
}
|
||||
return dateObj.toLocaleDateString('zh-CN', options)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -169,18 +177,35 @@ const viewMoreNotice = () => {
|
||||
}
|
||||
.content-box {
|
||||
font-size: 13px;
|
||||
min-height: 160px;
|
||||
max-height: 230px;
|
||||
overflow: auto;
|
||||
|
||||
.content-box-item {
|
||||
//padding-top: 12px;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.content-box-msg {
|
||||
color: #999999;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
.content {
|
||||
margin-left: 8px;
|
||||
|
||||
.name {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 2px 10px 0 0;
|
||||
}
|
||||
.content-box-time {
|
||||
color: #999999;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
.content-box-empty {
|
||||
|
||||
@ -1,28 +1,53 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<Editor
|
||||
style="height: 600px; overflow-y: hidden"
|
||||
v-model="valueHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
mode="default"
|
||||
@onCreated="handleCreated"
|
||||
@onChange="handleChange" />
|
||||
<div>
|
||||
<el-dialog v-model="noticeDialogOpen" draggable :close-on-click-modal="false" append-to-body>
|
||||
<template #header>
|
||||
{{ noticeModel.noticeTitle }}
|
||||
</template>
|
||||
<!-- <Editor
|
||||
style="overflow-y: auto"
|
||||
v-model="valueHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
mode="default"
|
||||
@onCreated="handleCreated"
|
||||
@onChange="handleChange" /> -->
|
||||
<div v-html="noticeModel.noticeContent"></div>
|
||||
<div class="n_right">
|
||||
{{ noticeModel.create_name }}
|
||||
</div>
|
||||
<div class="n_right">{{ formatDate(noticeModel.create_time) }}</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import '@wangeditor/editor/dist/css/style.css' // 引入 css
|
||||
import signalR from '@/signalr'
|
||||
import { Editor } from '@wangeditor/editor-for-vue'
|
||||
interface props {
|
||||
modelValue: string
|
||||
modelValue: boolean
|
||||
noticeModel: noticeInfo
|
||||
}
|
||||
const props = defineProps<props>()
|
||||
const emit = defineEmits()
|
||||
const valueHtml = ref(props.modelValue)
|
||||
const valueHtml = ref(props.noticeModel.noticeContent)
|
||||
const editorRef = shallowRef()
|
||||
const editorConfig = {
|
||||
readOnly: true
|
||||
}
|
||||
const noticeDialogOpen = ref(props.modelValue)
|
||||
watch(
|
||||
() => noticeDialogOpen.value,
|
||||
(val) => {
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
noticeDialogOpen.value = val
|
||||
}
|
||||
)
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value
|
||||
if (editor == null) return
|
||||
@ -32,19 +57,64 @@ const handleCreated = (editor) => {
|
||||
editorRef.value = editor
|
||||
}
|
||||
const handleChange = (editor) => {
|
||||
emit('update:modelValue', editor.getHtml())
|
||||
emit('update:noticeModel.noticeContent', editor.getHtml())
|
||||
}
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => props.noticeModel,
|
||||
(value) => {
|
||||
const editor = editorRef.value
|
||||
if (value == undefined) {
|
||||
editor.clear()
|
||||
return
|
||||
}
|
||||
valueHtml.value = value
|
||||
valueHtml.value = value.noticeContent
|
||||
viewNoticeDetail(value)
|
||||
}
|
||||
)
|
||||
enum NoticeType {
|
||||
notice = 1,
|
||||
aimMsg = 2,
|
||||
chat = 3
|
||||
}
|
||||
interface noticeInfo {
|
||||
noticeId: string
|
||||
noticeTitle: string
|
||||
noticeContent: string
|
||||
noticeType: NoticeType
|
||||
isRead: boolean
|
||||
create_name: string
|
||||
create_time: string
|
||||
}
|
||||
const viewNoticeDetail = (notice: noticeInfo) => {
|
||||
if (!notice.isRead) {
|
||||
switch (notice.noticeType) {
|
||||
case NoticeType.notice:
|
||||
signalR.ReadNotice(notice.noticeId)
|
||||
break
|
||||
case NoticeType.aimMsg:
|
||||
signalR.ReadAimMsg(notice.noticeId)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const formatDate = (dateTime) => {
|
||||
const dateObj = new Date(dateTime)
|
||||
const options: any = {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
// hour: '2-digit',
|
||||
// minute: '2-digit',
|
||||
// second: '2-digit'
|
||||
}
|
||||
return dateObj.toLocaleDateString('zh-CN', options)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
.n_right {
|
||||
text-align: right;
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -11,7 +11,7 @@ import directive from './directive' // directive
|
||||
// 注册指令
|
||||
import plugins from './plugins' // plugins
|
||||
import { downFile } from '@/utils/request'
|
||||
import signalR from '@/utils/signalR'
|
||||
import signalR from '@/signalr'
|
||||
import vueI18n from './i18n/index'
|
||||
import pinia from '@/store/index'
|
||||
|
||||
|
||||
61
src/signalr/analysis.js
Normal file
61
src/signalr/analysis.js
Normal file
@ -0,0 +1,61 @@
|
||||
import { ElNotification, ElMessageBox } from 'element-plus'
|
||||
import useSocketStore from '@/store/modules/socket'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import { webNotify } from '@/utils/index'
|
||||
|
||||
export default {
|
||||
onMessage(connection) {
|
||||
connection.on(MsgType.M001, (data) => {
|
||||
useSocketStore().setOnlineUserNum(data)
|
||||
})
|
||||
|
||||
connection.on(MsgType.M002, (data) => {})
|
||||
// 接受后台手动推送消息
|
||||
connection.on(MsgType.M003, (title, data) => {
|
||||
ElNotification({
|
||||
type: 'info',
|
||||
title: title,
|
||||
message: data,
|
||||
dangerouslyUseHTMLString: true,
|
||||
duration: 0
|
||||
})
|
||||
webNotify({ title: title, body: data })
|
||||
})
|
||||
// 接受系统通知/公告
|
||||
connection.on(MsgType.M004, (data1, data2) => {
|
||||
// if (data.code == 200) {
|
||||
useSocketStore().setUnreadNoticeList(data1)
|
||||
useSocketStore().setReadNoticeList(data2)
|
||||
// }
|
||||
})
|
||||
// 接受聊天数据
|
||||
connection.on(MsgType.M005, (data) => {
|
||||
const { fromUser, message } = data
|
||||
|
||||
useSocketStore().setChat(data)
|
||||
|
||||
if (data.userid != useUserStore().userId) {
|
||||
ElNotification({
|
||||
title: fromUser.nickName,
|
||||
message: message,
|
||||
type: 'success',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
webNotify({ title: fromUser.nickName, body: message })
|
||||
})
|
||||
},
|
||||
AllReadNotice(connection) {
|
||||
connection.invoke('AllReadNotice')
|
||||
},
|
||||
ReadNotice(connection, noticeId) {
|
||||
connection.invoke('ReadNotice', noticeId)
|
||||
}
|
||||
}
|
||||
const MsgType = {
|
||||
M001: 'onlineNum',
|
||||
M002: 'connId',
|
||||
M003: 'receiveNotice',
|
||||
M004: 'moreNotice',
|
||||
M005: 'receiveChat'
|
||||
}
|
||||
87
src/signalr/index.js
Normal file
87
src/signalr/index.js
Normal file
@ -0,0 +1,87 @@
|
||||
// 官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2&tabs=visual-studio
|
||||
import * as signalR from '@microsoft/signalr'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import cache from '@/plugins/cache'
|
||||
import analysis from '@/signalr/analysis'
|
||||
|
||||
export default {
|
||||
// signalR对象
|
||||
SR: {},
|
||||
// 失败连接重试次数
|
||||
failNum: 4,
|
||||
init(url) {
|
||||
var socketUrl = window.location.origin + url + '?clientId=' + cache.local.get('clientId')
|
||||
const connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl(socketUrl, { accessTokenFactory: () => getToken() })
|
||||
.withAutomaticReconnect() //自动重新连接
|
||||
.configureLogging(signalR.LogLevel.Warning)
|
||||
.build()
|
||||
this.SR = connection
|
||||
// 断线重连
|
||||
connection.onclose(async (error) => {
|
||||
console.error('断开连接了' + error)
|
||||
console.assert(connection.state === signalR.HubConnectionState.Disconnected)
|
||||
// 建议用户重新刷新浏览器
|
||||
await this.start()
|
||||
})
|
||||
|
||||
connection.onreconnected((connectionId) => {
|
||||
ElMessage({
|
||||
message: '与服务器通讯已连接成功',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
console.log('断线重新连接成功' + connectionId)
|
||||
})
|
||||
|
||||
connection.onreconnecting(async () => {
|
||||
console.log('断线重新连接中... ')
|
||||
|
||||
await this.start()
|
||||
})
|
||||
analysis.onMessage(connection)
|
||||
// 启动
|
||||
// this.start();
|
||||
},
|
||||
/**
|
||||
* 调用 this.signalR.start().then(async () => { await this.SR.invoke("method")})
|
||||
* @returns
|
||||
*/
|
||||
async start() {
|
||||
try {
|
||||
console.debug('signalR-1', this.SR.state)
|
||||
//使用async和await 或 promise的then 和catch 处理来自服务端的异常
|
||||
if (this.SR.state === signalR.HubConnectionState.Disconnected) {
|
||||
await this.SR.start()
|
||||
}
|
||||
|
||||
console.debug('signalR-2', this.SR.state)
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.failNum--
|
||||
// console.log(`失败重试剩余次数${that.failNum}`, error)
|
||||
if (this.failNum > 0 && this.SR.state.Disconnected) {
|
||||
setTimeout(async () => {
|
||||
await this.start()
|
||||
}, 5000)
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
AllReadNotice() {
|
||||
analysis.AllReadNotice(this.SR)
|
||||
},
|
||||
ReadNotice(noticeId) {
|
||||
analysis.ReadNotice(this.SR, noticeId)
|
||||
}
|
||||
// AllReadAimMsg() {
|
||||
// const connection = this.SR
|
||||
// connection.invoke('AllReadAimMsg')
|
||||
// },
|
||||
// ReadAimMsg(msgId) {
|
||||
// const connection = this.SR
|
||||
// connection.invoke('ReadAimMsg', msgId)
|
||||
// }
|
||||
}
|
||||
@ -7,14 +7,23 @@
|
||||
</template>
|
||||
<el-divider />
|
||||
<el-empty :image-size="150" description="暂无通知公告" v-if="noticeList.length === 0" />
|
||||
<el-table :data="noticeList" height="600" :show-header="false" v-else>
|
||||
<el-table :data="noticeList" height="600" :show-header="false" :cell-style="{ height: '40px' }" v-else>
|
||||
<el-table-column prop="noticeTitle" label="标题">
|
||||
<template #default="{ row }">
|
||||
<el-link :type="row.isRead ? 'primary' : 'danger'" @click="viewNoticeDetail(row.noticeId, row.isRead, row.noticeContent)">{{
|
||||
row.noticeTitle
|
||||
}}</el-link>
|
||||
<el-icon :size="20" color="#409EFF"><bell /></el-icon>
|
||||
<el-link
|
||||
:type="row.isRead ? 'primary' : 'danger'"
|
||||
style="margin-left: 8px"
|
||||
@click="viewNoticeDetail({ ...row, noticeType: NoticeType.notice })"
|
||||
>{{ row.noticeTitle }}</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="noticeContent" label="内容">
|
||||
<template #default="{ row }">
|
||||
<div v-html="row.noticeContent"></div>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="create_time" label="时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.create_time) }}
|
||||
@ -28,14 +37,23 @@
|
||||
</template>
|
||||
<el-divider />
|
||||
<el-empty :image-size="150" description="暂无业务信息" v-if="aimList.length === 0" />
|
||||
<el-table :data="aimList" height="600" :show-header="false" v-else>
|
||||
<el-table :data="aimList" height="600" :show-header="false" :cell-style="{ height: '40px' }" v-else>
|
||||
<el-table-column prop="noticeTitle" label="标题">
|
||||
<template #default="{ row }">
|
||||
<el-link :type="row.isRead ? 'primary' : 'danger'" @click="viewAimMsgDetail(row.noticeId, row.isRead, row.noticeContent)">{{
|
||||
row.noticeTitle
|
||||
}}</el-link>
|
||||
<el-icon :size="20" color="#409EFF"><bell /></el-icon>
|
||||
<el-link
|
||||
:type="row.isRead ? 'primary' : 'danger'"
|
||||
style="margin-left: 8px"
|
||||
@click="viewNoticeDetail({ ...row, noticeType: NoticeType.notice })"
|
||||
>{{ row.noticeTitle }}</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="noticeContent" label="内容">
|
||||
<template #default="{ row }">
|
||||
<div v-html="row.noticeContent"></div>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="create_time" label="时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.create_time) }}
|
||||
@ -49,18 +67,21 @@
|
||||
<el-button type="primary" link class="left-top-button">全部标为已读</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-dialog v-model="noticeDialogOpen" title="查看通知详情" draggable :close-on-click-modal="false">
|
||||
<noticeDialog v-model="form.noticeContent" />
|
||||
</el-dialog>
|
||||
<noticeDialog v-model="noticeDialogOpen" :notice-model="info" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useSocketStore from '@/store/modules/socket'
|
||||
import signalR from '@/utils/signalR'
|
||||
import signalR from '@/signalr'
|
||||
import noticeDialog from '@/components/Notice/noticeDialog/index.vue'
|
||||
import { ElTable } from 'element-plus'
|
||||
|
||||
enum NoticeType {
|
||||
notice = 1,
|
||||
aimMsg = 2,
|
||||
chat = 3
|
||||
}
|
||||
const activeTab = ref('notice')
|
||||
const readNoticeList = computed(() => {
|
||||
return useSocketStore().readNoticeList
|
||||
@ -91,20 +112,30 @@ const aimList = computed(() => {
|
||||
}))
|
||||
.concat(unreadAimList.value.map((item: any) => ({ ...item, isRead: false })))
|
||||
})
|
||||
const form = ref({
|
||||
noticeContent: ''
|
||||
interface noticeInfo {
|
||||
noticeId: string
|
||||
noticeTitle: string
|
||||
noticeContent: string
|
||||
noticeType: NoticeType
|
||||
isRead: boolean
|
||||
create_name: string
|
||||
create_time: string
|
||||
}
|
||||
const info = ref<noticeInfo>({
|
||||
noticeId: '',
|
||||
noticeTitle: '',
|
||||
noticeContent: '',
|
||||
noticeType: NoticeType.notice,
|
||||
isRead: false,
|
||||
create_name: '',
|
||||
create_time: ''
|
||||
})
|
||||
const noticeDialogOpen = ref(false)
|
||||
const viewNoticeDetail = (noticeId, isRead, noticeContent) => {
|
||||
if (!isRead) signalR.ReadNotice(noticeId)
|
||||
const viewNoticeDetail = (notice: noticeInfo) => {
|
||||
noticeDialogOpen.value = true
|
||||
form.value.noticeContent = noticeContent
|
||||
}
|
||||
const viewAimMsgDetail = (noticeId, isRead, noticeContent) => {
|
||||
if (!isRead) signalR.ReadAimMsg(noticeId)
|
||||
noticeDialogOpen.value = true
|
||||
form.value.noticeContent = noticeContent
|
||||
info.value = notice
|
||||
}
|
||||
|
||||
function onAllReadClick() {
|
||||
if (activeTab.value === 'notice') {
|
||||
signalR.AllReadNotice()
|
||||
|
||||
260
src/views/system/codeRule/index.vue
Normal file
260
src/views/system/codeRule/index.vue
Normal file
@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="plus" @click="handleAdd(ruleFormRef)">
|
||||
{{ $t('btn.add') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="edit" :disabled="single" @click="handleEdit(ruleFormRef)">
|
||||
{{ $t('btn.edit') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="delete" :disabled="multiple" @click="handleDelete()">
|
||||
{{ $t('btn.delete') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="codeRoleList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="代码" align="center" prop="code" width="150" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="名称" align="center" prop="name" width="200" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="类型" align="center" prop="type" width="180" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="前缀" align="center" prop="prefix" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="宽度" align="center" prop="width" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="初始值" align="center" prop="initVal" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="增量" align="center" prop="step" width="180" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="终止值" align="center" prop="finishVal" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="循环" align="center" prop="cycle" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="后缀" align="center" prop="sufix" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="分隔符" align="center" prop="joinChar" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="填充符" align="center" prop="fillChar" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="类型值" align="center" prop="typeVal" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="循环号" align="center" prop="cycleVal" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="当前值" align="center" prop="currVal" width="180" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="版本号" align="center" prop="version" width="180" :show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
<pagination v-model:total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<!-- 新增/编辑 -->
|
||||
<el-dialog v-model="dialogVisible" v-if="dialogVisible" :title="dialogTitle" draggable>
|
||||
<el-form ref="ruleFormRef" :model="codeRuleForm" :rules="rules" status-icon label-width="90px">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="代码" prop="code">
|
||||
<el-input v-model="codeRuleForm.code" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="codeRuleForm.name" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-input v-model="codeRuleForm.type" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="前缀" prop="prefix">
|
||||
<el-input v-model="codeRuleForm.prefix" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="宽度" prop="width">
|
||||
<el-input v-model="codeRuleForm.width" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="初始值" prop="initVal">
|
||||
<el-input v-model="codeRuleForm.initVal" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="增量" prop="step">
|
||||
<el-input v-model="codeRuleForm.step" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="终止值" prop="finishVal">
|
||||
<el-input v-model="codeRuleForm.finishVal" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="循环" prop="cycle">
|
||||
<el-input v-model="codeRuleForm.cycle" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="后缀" prop="sufix">
|
||||
<el-input v-model="codeRuleForm.sufix" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分隔符" prop="joinChar">
|
||||
<el-input v-model="codeRuleForm.joinChar" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="填充符" prop="fillChar">
|
||||
<el-input v-model="codeRuleForm.fillChar" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm(ruleFormRef)">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { addBaseCodeRule, deleteBaseCodeRule, updateBaseCodeRule, getBaseCodeRuleList } from '@/api/system/baseCodeRole'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import useCurrentInstance from '@/utils/useCurrentInstance'
|
||||
const { globalProperties } = useCurrentInstance()
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const multipleSelection = ref([])
|
||||
let codeRuleForm: any = reactive({
|
||||
code: null,
|
||||
name: null,
|
||||
type: null,
|
||||
prefix: null,
|
||||
width: null,
|
||||
initVal: null,
|
||||
step: null,
|
||||
finishVal: null,
|
||||
cycle: null,
|
||||
sufix: null,
|
||||
joinChar: null,
|
||||
fillChar: null
|
||||
})
|
||||
let rules = reactive<FormRules>({
|
||||
code: [{ required: true, message: '不可为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '不可为空', trigger: 'blur' }]
|
||||
})
|
||||
// 遮罩层
|
||||
const loading = ref(true)
|
||||
// 选中数组
|
||||
const ids = ref([])
|
||||
// 非单个禁用
|
||||
const single = ref(true)
|
||||
// 非多个禁用
|
||||
const multiple = ref(true)
|
||||
// 显示搜索条件
|
||||
const showSearch = ref(true)
|
||||
// 业务维护编码表格数据
|
||||
let codeRoleList: any[] = reactive([])
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
// 总条数
|
||||
const total = ref(0)
|
||||
const getList = () => {
|
||||
loading.value = true
|
||||
getBaseCodeRuleList(queryParams).then((res) => {
|
||||
codeRoleList = res.data.result
|
||||
total.value = res.data.totalNum
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map((item) => item.code)
|
||||
single.value = ids.value.length !== 1
|
||||
multiple.value = !ids.value.length
|
||||
multipleSelection.value = selection
|
||||
}
|
||||
const resetCodeRuleForm = (isUpdate?: boolean, row?) => {
|
||||
if (isUpdate) {
|
||||
codeRuleForm = reactive({
|
||||
code: row.code,
|
||||
name: row.name,
|
||||
type: row.type,
|
||||
prefix: row.prefix,
|
||||
width: row.width,
|
||||
initVal: row.initVal,
|
||||
step: row.step,
|
||||
finishVal: row.finishVal,
|
||||
cycle: row.cycle,
|
||||
sufix: row.sufix,
|
||||
joinChar: row.joinChar,
|
||||
fillChar: row.fillChar
|
||||
})
|
||||
} else {
|
||||
codeRuleForm = reactive({
|
||||
code: null,
|
||||
name: null,
|
||||
type: null,
|
||||
prefix: null,
|
||||
width: null,
|
||||
initVal: null,
|
||||
step: null,
|
||||
finishVal: null,
|
||||
cycle: null,
|
||||
sufix: null,
|
||||
joinChar: null,
|
||||
fillChar: null
|
||||
})
|
||||
}
|
||||
}
|
||||
const handleAdd = (formEl: FormInstance | undefined) => {
|
||||
dialogTitle.value = '新增规则'
|
||||
dialogVisible.value = true
|
||||
resetCodeRuleForm(false)
|
||||
formEl && formEl.clearValidate()
|
||||
}
|
||||
const handleEdit = (formEl: FormInstance | undefined) => {
|
||||
dialogTitle.value = '编辑规则'
|
||||
dialogVisible.value = true
|
||||
resetCodeRuleForm(true, multipleSelection.value[0])
|
||||
formEl && formEl.clearValidate()
|
||||
}
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async () => {
|
||||
const Ids = ids.value
|
||||
globalProperties
|
||||
.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?')
|
||||
.then(async function () {
|
||||
return await deleteBaseCodeRule(Ids)
|
||||
})
|
||||
.then(() => {
|
||||
getList()
|
||||
globalProperties.$modal.msgSuccess('删除成功')
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
// 提交
|
||||
if (dialogTitle.value === '新增规则') {
|
||||
addBaseCodeRule(codeRuleForm).then((res) => {
|
||||
getList()
|
||||
dialogVisible.value = false
|
||||
})
|
||||
} else {
|
||||
updateBaseCodeRule(codeRuleForm).then((res) => {
|
||||
getList()
|
||||
dialogVisible.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
Loading…
x
Reference in New Issue
Block a user