mirror of
https://github.com/1024-lab/smart-admin.git
synced 2025-09-03 19:29:07 +00:00
v3.9.0【优化】typescript版本;【优化】App端消息;【优化】弹出层z-index;
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
NODE_ENV=development
|
||||
VITE_APP_TITLE='SmartAdmin 开发环境(Dev)'
|
||||
VITE_APP_API_URL='https://app.smartadmin.vip/smart-app-api'
|
||||
VITE_APP_API_URL='http://127.0.0.1:1024'
|
||||
|
16
smart-app/src/api/support/message-api.js
Normal file
16
smart-app/src/api/support/message-api.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { postRequest, getRequest } from '@/lib/smart-request';
|
||||
|
||||
export const messageApi = {
|
||||
// 通知消息-分页查询
|
||||
queryMessage: (param) => {
|
||||
return postRequest('/support/message/queryMyMessage', param);
|
||||
},
|
||||
// 通知消息-查询未读消息数
|
||||
queryUnreadCount: () => {
|
||||
return getRequest('/support/message/getUnreadCount');
|
||||
},
|
||||
// 通知消息-标记已读
|
||||
updateReadFlag: (messageId) => {
|
||||
return getRequest(`/support/message/read/${messageId}`);
|
||||
},
|
||||
};
|
@@ -13,6 +13,7 @@ import enterpriseConst from './business/oa/enterprise-const';
|
||||
import goodsConst from './business/erp/goods-const';
|
||||
import changeLogConst from './support/change-log-const';
|
||||
import fileConst from './support/file-const';
|
||||
import messageConst from "./support/message-const";
|
||||
|
||||
export default {
|
||||
FLAG_NUMBER_ENUM,
|
||||
@@ -23,4 +24,5 @@ export default {
|
||||
...goodsConst,
|
||||
...changeLogConst,
|
||||
...fileConst,
|
||||
...messageConst
|
||||
};
|
||||
|
30
smart-app/src/constants/support/message-const.js
Normal file
30
smart-app/src/constants/support/message-const.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* @Description: file content
|
||||
* @Author: yandy
|
||||
* @Date: 2022-07-24 21:43:43
|
||||
* @LastEditors:
|
||||
* @LastEditTime: 2022-07-24 21:43:43
|
||||
*/
|
||||
export const MESSAGE_TYPE_ENUM = {
|
||||
MAIL: {
|
||||
value: 1,
|
||||
desc: '站内信'
|
||||
},
|
||||
ORDER: {
|
||||
value: 2,
|
||||
desc: '订单'
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
export const MESSAGE_RECEIVE_TYPE_ENUM = {
|
||||
EMPLOYEE: {
|
||||
value: 1,
|
||||
desc: '员工'
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
MESSAGE_TYPE_ENUM,
|
||||
MESSAGE_RECEIVE_TYPE_ENUM
|
||||
};
|
@@ -2,7 +2,7 @@ import CryptoJS from 'crypto-js';
|
||||
import CryptoSM from 'sm-crypto';
|
||||
|
||||
function object2string(data) {
|
||||
if (typeof data === 'Object') {
|
||||
if (typeof data === 'object') {
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,29 @@ function object2string(data) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// ----------------------- AES 加密、解密 -----------------------
|
||||
const AES_KEY = '1024abcd1024abcd1024abcd1024abcd';
|
||||
/**
|
||||
* 字符串转为数字
|
||||
*/
|
||||
function stringToHex(str) {
|
||||
let hex = '';
|
||||
for(let i = 0; i < str.length; i++) {
|
||||
hex += str.charCodeAt(i).toString(16).padStart(2, '0');
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* -------------------- ※ AES 加密、解密 begin ※ --------------------
|
||||
*
|
||||
* 1、AES加密算法支持三种密钥长度:128位、192位和256位,这里选择128位
|
||||
* 2、AES 要求秘钥为 128bit,转化字节为 16个字节;
|
||||
* 3、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节;
|
||||
* 4、所以:秘钥Key 组成为:字母、数字、特殊符号 一共16个即可
|
||||
*
|
||||
* -------------------- ※ AES 加密、解密 end ※ --------------------
|
||||
*/
|
||||
const AES_KEY = '1024lab__1024lab';
|
||||
|
||||
const AES = {
|
||||
encryptData: function (data) {
|
||||
@@ -28,8 +49,7 @@ const AES = {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
});
|
||||
|
||||
return encrypted.toString();
|
||||
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
|
||||
},
|
||||
|
||||
decryptData: function (data) {
|
||||
@@ -45,13 +65,24 @@ const AES = {
|
||||
},
|
||||
};
|
||||
|
||||
// ----------------------- 国密SM4算法 加密、解密 -----------------------
|
||||
const SM4_KEY = '1024abcd1024abcd1024abcd1024abcd';
|
||||
/*
|
||||
* -------------------- ※ 国密SM4算法 加密、解密 begin ※ --------------------
|
||||
*
|
||||
* 1、国密SM4 要求秘钥为 128bit,转化字节为 16个字节;
|
||||
* 2、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节;
|
||||
* 3、java中 每个 字母数字 也是占用1个字节;
|
||||
* 4、所以:前端和后端的 秘钥Key 组成为:字母、数字、特殊符号 一共16个即可
|
||||
*
|
||||
* -------------------- ※ 国密SM4算法 加密、解密 end ※ --------------------
|
||||
*/
|
||||
|
||||
// 秘钥Key 组成为:字母、数字、特殊符号 一共16个即可
|
||||
const SM4_KEY = '1024lab__1024lab';
|
||||
|
||||
const SM4 = {
|
||||
encryptData: function (data) {
|
||||
// 第一步:SM4 加密
|
||||
let encryptData = CryptoSM.sm4.encrypt(object2string(data), SM4_KEY);
|
||||
let encryptData = CryptoSM.sm4.encrypt(object2string(data), stringToHex(SM4_KEY));
|
||||
// 第二步: Base64 编码
|
||||
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encryptData));
|
||||
},
|
||||
@@ -62,10 +93,12 @@ const SM4 = {
|
||||
let decode64Str = CryptoJS.enc.Utf8.stringify(words);
|
||||
|
||||
// 第二步:SM4 解密
|
||||
return CryptoSM.sm4.decrypt(decode64Str, SM4_KEY);
|
||||
return CryptoSM.sm4.decrypt(decode64Str, stringToHex(SM4_KEY));
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ----------------------- 对外暴露: 加密、解密 -----------------------
|
||||
|
||||
// 默认使用SM4算法
|
||||
|
@@ -1,31 +1,105 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="message" v-for="(item, index) in 10">
|
||||
<view class="message-header">
|
||||
<view class="header-left">
|
||||
<image src="/src/static/images/message/message.png" mode=""></image>
|
||||
<view> 系统通知 </view>
|
||||
<mescroll-body @init="mescrollInit" :down="{ auto: false }" @down="onDown" @up="onUp">
|
||||
<mescroll-empty v-if="messageListData.length === 0"></mescroll-empty>
|
||||
<view class="message" v-for="(item, index) in messageListData">
|
||||
<view class="message-header">
|
||||
<view class="header-left">
|
||||
<image src="/src/static/images/message/message.png" mode=""></image>
|
||||
<view>
|
||||
{{ $smartEnumPlugin.getDescByValue('MESSAGE_TYPE_ENUM', item.messageType) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="header-time"> {{item.createTime}} </view>
|
||||
</view>
|
||||
<view class="header-time"> 2023-08-20 20:48:21 </view>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view class="message-title">
|
||||
报销-付款已完成
|
||||
<uni-icons v-if="index % 2 === 1" color="red" class="smart-margin-left10" type="info-filled" :size="14"></uni-icons>
|
||||
<view class="content">
|
||||
<view class="message-title">
|
||||
<uni-icons v-if="!item.readFlag" color="red" class="smart-margin-right10" type="info-filled" :size="14"></uni-icons>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
<view class="message-body"> {{item.content}} </view>
|
||||
</view>
|
||||
<view class="message-body"> 您的费用保修单已完成,付款金额300.00元,请注意查收。 </view>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {},
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import useMescroll from '@/uni_modules/uni-mescroll/hooks/useMescroll';
|
||||
import { smartSentry } from '@/lib/smart-sentry';
|
||||
import { messageApi } from '@/api/support/message-api';
|
||||
|
||||
// --------------------------- 查询 ---------------------------------
|
||||
|
||||
const defaultForm = {
|
||||
searchWord: '',
|
||||
messageType: null,
|
||||
dataId: null,
|
||||
readFlag: null,
|
||||
endDate: null,
|
||||
startDate: null,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
searchCount: true,
|
||||
receiverType: null,
|
||||
receiverId: null,
|
||||
};
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive({ ...defaultForm });
|
||||
// 通知列表数据
|
||||
const messageListData = ref([]);
|
||||
|
||||
function buildQueryParam(pageNum) {
|
||||
queryForm.pageNum = pageNum;
|
||||
return Object.assign({}, queryForm, { pageNum });
|
||||
}
|
||||
|
||||
async function query(mescroll, isDownFlag, param) {
|
||||
try {
|
||||
let res = await messageApi.queryMessage(param);
|
||||
res.data.list.map(e => e.content = e.content.substr(0,50));
|
||||
if (!isDownFlag) {
|
||||
messageListData.value = messageListData.value.concat(res.data.list);
|
||||
} else {
|
||||
messageListData.value = res.data.list;
|
||||
}
|
||||
mescroll.endSuccess(res.data.list.length, res.data.pages > res.data.pageNum);
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
//联网失败, 结束加载
|
||||
mescroll.endErr();
|
||||
}
|
||||
}
|
||||
|
||||
const { mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
function search() {
|
||||
query(getMescroll(), true, buildQueryParam(1));
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉刷新
|
||||
*/
|
||||
function onDown(mescroll) {
|
||||
queryForm.pageNum = 1;
|
||||
query(mescroll, true, buildQueryParam(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 上拉加载更多
|
||||
*/
|
||||
function onUp(mescroll) {
|
||||
query(mescroll, false, buildQueryParam(mescroll.num));
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -74,9 +148,13 @@
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
white-space: nowrap; /* 确保文本不会换行 */
|
||||
overflow: hidden; /* 隐藏溢出的内容 */
|
||||
text-overflow: ellipsis; /* 在文本溢出处显示省略号 */
|
||||
}
|
||||
.message-body {
|
||||
font-size: 28rpx;
|
||||
max-height: 3.2rem;
|
||||
color: #777777;
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<image class="icon" src="/static/images/mine/mine-account.png" mode=""></image>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<uni-list-item title="消息通知" link="switchTab" showBadge badgeText="6" badgeType="error" to="/pages/message/message">
|
||||
<uni-list-item title="消息通知" link="switchTab" showBadge :badgeText="messageCount" badgeType="error" to="/pages/message/message">
|
||||
<template #header>
|
||||
<image class="icon" src="/static/images/mine/mine-message.png" mode=""></image>
|
||||
</template>
|
||||
@@ -67,8 +67,12 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { SmartToast } from '@/lib/smart-support';
|
||||
import { useUserStore } from '@/store/modules/system/user';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const emits = defineEmits(['changeStyle']);
|
||||
const userStore = useUserStore();
|
||||
const messageCount = computed(() => userStore.$state.unreadMessageCount);
|
||||
|
||||
function changeStyle() {
|
||||
emits('changeStyle');
|
||||
|
@@ -11,10 +11,15 @@ import _ from 'lodash';
|
||||
import { defineStore } from 'pinia';
|
||||
import { USER_TOKEN } from '@/constants/local-storage-key-const';
|
||||
import { loginApi } from '@/api/system/login-api';
|
||||
import { smartSentry } from '@/lib/smart-sentry';
|
||||
import {messageApi} from "@/api/support/message-api";
|
||||
|
||||
const defaultUserInfo = {
|
||||
token: '',
|
||||
//员工id
|
||||
employeeId: '',
|
||||
// 头像
|
||||
avatar: '',
|
||||
//登录名
|
||||
loginName: '',
|
||||
//姓名
|
||||
@@ -25,6 +30,8 @@ const defaultUserInfo = {
|
||||
departmentId: '',
|
||||
//部门名词
|
||||
departmentName: '',
|
||||
//是否需要修改密码
|
||||
needUpdatePwdFlag: false,
|
||||
//是否为超级管理员
|
||||
administratorFlag: true,
|
||||
//上次登录ip
|
||||
@@ -35,6 +42,8 @@ const defaultUserInfo = {
|
||||
lastLoginUserAgent: '',
|
||||
//上次登录时间
|
||||
lastLoginTime: '',
|
||||
// 未读消息数量
|
||||
unreadMessageCount: 0,
|
||||
};
|
||||
|
||||
export const useUserStore = defineStore({
|
||||
@@ -62,6 +71,15 @@ export const useUserStore = defineStore({
|
||||
let res = await loginApi.getLoginInfo();
|
||||
this.setUserLoginInfo(res.data);
|
||||
},
|
||||
// 查询未读消息数量
|
||||
async queryUnreadMessageCount() {
|
||||
try {
|
||||
let result = await messageApi.queryUnreadCount();
|
||||
this.unreadMessageCount = result.data;
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
}
|
||||
},
|
||||
//设置登录信息
|
||||
setUserLoginInfo(data) {
|
||||
// 用户基本信息
|
||||
@@ -79,6 +97,9 @@ export const useUserStore = defineStore({
|
||||
this.lastLoginTime = data.lastLoginTime;
|
||||
|
||||
uni.setStorageSync(USER_TOKEN, data.token);
|
||||
|
||||
// 获取用户未读消息
|
||||
this.queryUnreadMessageCount();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
Reference in New Issue
Block a user