index.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <template>
  2. <el-card shadow="never" class="list-card" body-style="padding-right: 0">
  3. <template #header>
  4. <el-radio-group v-model="search.messageType" @change="changeType">
  5. <el-radio-button v-for="item in typeData" :value="item.messageType">
  6. <template #default>
  7. {{ item.messageTypeName }}
  8. <el-badge :value="item.stateNumber" class="badge" v-if="item.stateNumber > 0"></el-badge>
  9. </template>
  10. </el-radio-button>
  11. </el-radio-group>
  12. <div class="right-btn">
  13. <span @click="setMsgToolsOpen">
  14. <i-ep-Setting />
  15. 接收设置
  16. </span>
  17. <span @click="allRead">
  18. <i-ep-MessageBox /> 全部标记为已读
  19. </span>
  20. <span @click="clearMessage">
  21. <i-ep-DeleteFilled /> 清空已读
  22. </span>
  23. </div>
  24. </template>
  25. <div class="content" v-loading="loading">
  26. <template v-if="noticeData.length != 0">
  27. <div class="notice-box" v-for="item in noticeData" @click="readMessage(item)">
  28. <div class="avatar">
  29. <div class="system-icon" v-if="item.sendUserId == '0'"><i-ep-Bell size="20" color="#FFF" /></div>
  30. <el-avatar v-else :src="item.photo"></el-avatar>
  31. </div>
  32. <div class="detail-notice">
  33. <div style="flex: 1;margin-right: 10px">
  34. <p class="bold mb6">{{ item.sendUserId == '0' ? '系统通知' : item.sendUserName }} {{ item.title }}</p>
  35. <p class="light">
  36. <i
  37. v-if="item.messageIcon"
  38. :class="`iconfont ${item.messageIcon}`"
  39. :style="{ color: ['icon-ri', 'icon-yue', 'icon-zhou'].includes(item.messageIcon) ? '#1874FF' : '#909399' }"
  40. ></i> {{ item.content }}
  41. </p>
  42. </div>
  43. <div style="width: 105px">
  44. <p class="time light mb6">{{ item.date }}</p>
  45. <p class="light" :style="{ 'text-align': 'right', 'color': item.isRead ? '#8C8C8C' : '#1874FF' }">
  46. {{ item.isRead ? "已读" : "未读" }}
  47. </p>
  48. </div>
  49. </div>
  50. </div>
  51. </template>
  52. <div v-else class="notice-box no-data-box">
  53. <p>暂无数据</p>
  54. </div>
  55. </div>
  56. <pagination
  57. layout="total, sizes, prev, pager, next"
  58. v-model:total="total"
  59. v-model:page="search.pageIndex"
  60. v-model:limit="search.pageSize"
  61. @pagination="getData"
  62. style="padding-right: 20px;"
  63. />
  64. <setMsgTools ref="setMsgToolsRef"></setMsgTools>
  65. </el-card>
  66. </template>
  67. <script setup lang="ts">
  68. import { listMessage, getMessageType, updateRead, updateReadAll, clearRead } from '@/api/public'
  69. import setMsgTools from './SetMsgTools.vue'
  70. import moment from "moment";
  71. const typeData = ref([])
  72. const setMsgToolsRef = ref()
  73. const setMsgToolsOpen= ()=> {
  74. setMsgToolsRef.value.openSetting()
  75. }
  76. const search = ref({
  77. pageIndex: 1,
  78. pageSize: 10,
  79. messageType: 0,
  80. })
  81. const noticeData = ref([])
  82. const total = ref(0)
  83. const router = useRouter();
  84. const getType = () => {
  85. // getMessageType().then(res => {
  86. // if(res.success) {
  87. // typeData.value = res.result
  88. // search.value.messageType = Number(router.currentRoute.value.query.messageType) as number
  89. // getData()
  90. // }
  91. // })
  92. }
  93. const loading = ref(false)
  94. const getData = () => {
  95. loading.value = true
  96. listMessage(search.value).then(res => {
  97. let { success, result } = res
  98. if(success){
  99. noticeData.value = (result.records || []).map(item => {
  100. // 判断创建时间是不是今天
  101. if(item.createTime.slice(0, 10) == moment().format("YYYY-MM-DD")){
  102. item.date = "今天 " + item.createTime.slice(11, 16)
  103. }else{
  104. item.date = moment(item.createTime).format("MM月DD日 HH:mm")
  105. }
  106. return item
  107. })
  108. total.value = Number(result.total)
  109. }
  110. }).finally(() => {
  111. loading.value = false
  112. })
  113. }
  114. const changeType = (type: number) => {
  115. search.value.messageType = type
  116. changeSize(search.value.pageSize)
  117. }
  118. const changeSize = (size: number) => {
  119. search.value.pageIndex = 1;
  120. search.value.pageSize = size;
  121. getData()
  122. }
  123. const readMessage = (item) => {
  124. if(!item.isRead){
  125. updateRead([item.id]).then(res => {
  126. if(res.success){
  127. item.isRead = 1
  128. item.stateNumber --
  129. }else{
  130. ElMessage.error(res.msg);
  131. }
  132. })
  133. }
  134. if(item.callbackUrl){
  135. window.open(item.callbackUrl, '_blank')
  136. }
  137. }
  138. const allRead = () => {
  139. if(noticeData.value.length == 0){
  140. ElMessage.error('列表暂无数据');
  141. return
  142. }
  143. updateReadAll().then(res => {
  144. if(res.success){
  145. ElMessage.success('操作成功');
  146. typeData.value = typeData.value.map(item => {
  147. item.stateNumber = 0
  148. return item
  149. })
  150. getData()
  151. }else{
  152. ElMessage.error(res.msg);
  153. }
  154. })
  155. }
  156. const clearMessage = () => {
  157. if(noticeData.value.length == 0){
  158. ElMessage.error('列表暂无数据');
  159. return
  160. }
  161. clearRead().then(res => {
  162. if(res.success){
  163. ElMessage.success('操作成功');
  164. getData()
  165. }else{
  166. ElMessage.error(res.msg);
  167. }
  168. })
  169. }
  170. const route = useRoute();
  171. watch(route, (newRoute, oldRoute) => {
  172. let queryDataNew: any = router.currentRoute.value.query
  173. if (queryDataNew.messageType) {
  174. search.value.messageType = Number(queryDataNew.messageType)
  175. getData()
  176. }
  177. });
  178. onMounted(() => {
  179. getType()
  180. })
  181. </script>
  182. <style lang="scss" scoped>
  183. .list-card{
  184. :deep(.el-card__header){
  185. display: flex;
  186. justify-content: space-between;
  187. align-items: center;
  188. padding-bottom: 16px;
  189. }
  190. :deep(.el-radio-group){
  191. .el-radio-button__inner{
  192. display: flex;
  193. align-items: center;
  194. .el-badge{
  195. height: 14px;
  196. margin-left: 3px;
  197. .el-badge__content{
  198. border: none;
  199. height: 14px;
  200. }
  201. }
  202. }
  203. }
  204. .right-btn{
  205. span{
  206. cursor: pointer;
  207. margin-left: 15px;
  208. }
  209. svg{
  210. vertical-align: sub;
  211. }
  212. }
  213. }
  214. :deep(.el-card__body){
  215. display: flex;
  216. flex-direction: column;
  217. }
  218. .content{
  219. overflow: auto;
  220. flex: 1;
  221. padding-right: 20px;
  222. .notice-box{
  223. border-bottom: 1px solid #F0F0F0;
  224. min-height: 80px;
  225. display: flex;
  226. cursor: pointer;
  227. .avatar{
  228. margin-top: 14px;
  229. margin-right: 8px;
  230. }
  231. .system-icon{
  232. width: 32px;
  233. height: 32px;
  234. line-height: 32px;
  235. text-align: center;
  236. background: #1874FF;
  237. border-radius: 50%;
  238. }
  239. .AvatarX{
  240. width: 32px;
  241. height: 32px;
  242. }
  243. .detail-notice{
  244. display: flex;
  245. justify-content: space-between;
  246. align-items: center;
  247. flex: 1;
  248. padding: 5px 0;
  249. .bold{
  250. color: #262626;
  251. font-weight: bold;
  252. }
  253. .light{
  254. color: #8C8C8C;
  255. }
  256. .mb6{
  257. margin-bottom: 6px;
  258. }
  259. .time{
  260. text-align: right;
  261. }
  262. }
  263. }
  264. .no-data-box{
  265. align-items: center;
  266. justify-content: center;
  267. cursor: default;
  268. border: none;
  269. }
  270. }
  271. </style>