diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/utils/security.ts b/src/utils/security.ts index 9252b14..160b4b0 100644 --- a/src/utils/security.ts +++ b/src/utils/security.ts @@ -28,4 +28,25 @@ } return enRes } - +/** + * 解密 + * @param value 待解密数据 + * @returns 解密结果 + */ +export async function RSAdecrypt(value: string): Promise { + var encrypt = new JsEncrypt() + let enRes = '' + if (userStore.getPrivateKey && userStore.getPrivateKey === '') { + const res = await userStore.getBaseConfig() + if (res && res.privateKey) { + const privateKey = res.privateKey + encrypt.setPrivateKey(privateKey) + enRes = encrypt.decrypt(value) || '' + } + } + else { + encrypt.setPrivateKey(userStore.getPrivateKey) + enRes = encrypt.decrypt(value) || '' + } + return enRes +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/utils/security.ts b/src/utils/security.ts index 9252b14..160b4b0 100644 --- a/src/utils/security.ts +++ b/src/utils/security.ts @@ -28,4 +28,25 @@ } return enRes } - +/** + * 解密 + * @param value 待解密数据 + * @returns 解密结果 + */ +export async function RSAdecrypt(value: string): Promise { + var encrypt = new JsEncrypt() + let enRes = '' + if (userStore.getPrivateKey && userStore.getPrivateKey === '') { + const res = await userStore.getBaseConfig() + if (res && res.privateKey) { + const privateKey = res.privateKey + encrypt.setPrivateKey(privateKey) + enRes = encrypt.decrypt(value) || '' + } + } + else { + encrypt.setPrivateKey(userStore.getPrivateKey) + enRes = encrypt.decrypt(value) || '' + } + return enRes +} diff --git a/src/views/login.vue b/src/views/login.vue index 1f1a316..bd0d64d 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -9,7 +9,8 @@ import type { FormInstance, FormRules } from 'element-plus' import { ElMessage } from 'element-plus' import useUserStore from '@/store/modules/user' -import { RSAencrypt } from '@/utils/security' +import { RSAdecrypt, RSAencrypt } from '@/utils/security' +import { getPrivateKey, removePrivateKey } from '@/utils/auth' const route = useRoute() const router = useRouter() @@ -88,10 +89,18 @@ }) loading.value = false if (loginForm.value.remember) { + // 保存用户名 localStorage.setItem('login_username', loginForm.value.username) + // 保存 加密密码串 + localStorage.setItem('login_password', finalForm.password) } else { + // 移除用户名 localStorage.removeItem('login_username') + // 移除 加密密码串 + localStorage.removeItem('login_password') + // 移除私钥 + removePrivateKey() } router.push(redirect.value) }) @@ -186,8 +195,12 @@ loginForm.value.password = '111111' handleLogin() } -onBeforeMount(() => { +onBeforeMount(async () => { loginForm.value.username = localStorage.login_username || '' + if (localStorage.login_username) { + const passwoed = await RSAdecrypt(localStorage.login_password) + loginForm.value.password = passwoed + } getBaseConfig() }) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/utils/security.ts b/src/utils/security.ts index 9252b14..160b4b0 100644 --- a/src/utils/security.ts +++ b/src/utils/security.ts @@ -28,4 +28,25 @@ } return enRes } - +/** + * 解密 + * @param value 待解密数据 + * @returns 解密结果 + */ +export async function RSAdecrypt(value: string): Promise { + var encrypt = new JsEncrypt() + let enRes = '' + if (userStore.getPrivateKey && userStore.getPrivateKey === '') { + const res = await userStore.getBaseConfig() + if (res && res.privateKey) { + const privateKey = res.privateKey + encrypt.setPrivateKey(privateKey) + enRes = encrypt.decrypt(value) || '' + } + } + else { + encrypt.setPrivateKey(userStore.getPrivateKey) + enRes = encrypt.decrypt(value) || '' + } + return enRes +} diff --git a/src/views/login.vue b/src/views/login.vue index 1f1a316..bd0d64d 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -9,7 +9,8 @@ import type { FormInstance, FormRules } from 'element-plus' import { ElMessage } from 'element-plus' import useUserStore from '@/store/modules/user' -import { RSAencrypt } from '@/utils/security' +import { RSAdecrypt, RSAencrypt } from '@/utils/security' +import { getPrivateKey, removePrivateKey } from '@/utils/auth' const route = useRoute() const router = useRouter() @@ -88,10 +89,18 @@ }) loading.value = false if (loginForm.value.remember) { + // 保存用户名 localStorage.setItem('login_username', loginForm.value.username) + // 保存 加密密码串 + localStorage.setItem('login_password', finalForm.password) } else { + // 移除用户名 localStorage.removeItem('login_username') + // 移除 加密密码串 + localStorage.removeItem('login_password') + // 移除私钥 + removePrivateKey() } router.push(redirect.value) }) @@ -186,8 +195,12 @@ loginForm.value.password = '111111' handleLogin() } -onBeforeMount(() => { +onBeforeMount(async () => { loginForm.value.username = localStorage.login_username || '' + if (localStorage.login_username) { + const passwoed = await RSAdecrypt(localStorage.login_password) + loginForm.value.password = passwoed + } getBaseConfig() }) diff --git a/src/views/system/area/editArea.vue b/src/views/system/area/editArea.vue index 8256924..70384ba 100644 --- a/src/views/system/area/editArea.vue +++ b/src/views/system/area/editArea.vue @@ -6,7 +6,7 @@ import AreaSelectTree from './areaSelectTree.vue' import type { IareaForm } from './area-interface' import { addArea, getAreaType, updateArea } from '@/api/system/area' -const emits = defineEmits(['watchChild']) +const emits = defineEmits(['watchChild', 'refresh']) const dataFormRef = ref() const areaSelect = ref() const dialogFormVisible = ref(false) // 对话框是否显示 @@ -18,7 +18,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 1, // 排序 }) // 表单 const areaSelectShow = ref(false) const areaLevelList = ref([]) as any // 区域树列表数据 @@ -28,7 +28,7 @@ } // 表头显示标题 const btnLoading = ref(false) // 保存按钮的加载中状态 const rules: FormRules = { - id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }], + id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }, { type: 'number', message: '必须为数字值' }], areaName: [{ required: true, message: '区域名称不能为空', trigger: ['blur', 'change'] }], simpleName: [{ required: true, message: '区域简称不能为空', trigger: ['blur', 'change'] }], pName: [{ required: true, message: '上级区域必选', trigger: ['blur', 'change'] }], @@ -49,7 +49,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 4, // 排序 } } // 获取区域类型 @@ -118,6 +118,10 @@ nextTick(() => { dataFormRef.value.clearValidate() }) + // 通知父组件刷新状态 + setTimeout(() => { + emits('refresh') + }) }).catch(() => { // 选否,关闭窗口,并刷新页面 emits('watchChild') dialogFormVisible.value = false @@ -143,6 +147,9 @@ }) dataFormRef.value.clearValidate() emits('watchChild') + setTimeout(() => { + emits('refresh') + }) dialogFormVisible.value = false } }).catch((_) => { // 异常情况,loading置为false diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/utils/security.ts b/src/utils/security.ts index 9252b14..160b4b0 100644 --- a/src/utils/security.ts +++ b/src/utils/security.ts @@ -28,4 +28,25 @@ } return enRes } - +/** + * 解密 + * @param value 待解密数据 + * @returns 解密结果 + */ +export async function RSAdecrypt(value: string): Promise { + var encrypt = new JsEncrypt() + let enRes = '' + if (userStore.getPrivateKey && userStore.getPrivateKey === '') { + const res = await userStore.getBaseConfig() + if (res && res.privateKey) { + const privateKey = res.privateKey + encrypt.setPrivateKey(privateKey) + enRes = encrypt.decrypt(value) || '' + } + } + else { + encrypt.setPrivateKey(userStore.getPrivateKey) + enRes = encrypt.decrypt(value) || '' + } + return enRes +} diff --git a/src/views/login.vue b/src/views/login.vue index 1f1a316..bd0d64d 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -9,7 +9,8 @@ import type { FormInstance, FormRules } from 'element-plus' import { ElMessage } from 'element-plus' import useUserStore from '@/store/modules/user' -import { RSAencrypt } from '@/utils/security' +import { RSAdecrypt, RSAencrypt } from '@/utils/security' +import { getPrivateKey, removePrivateKey } from '@/utils/auth' const route = useRoute() const router = useRouter() @@ -88,10 +89,18 @@ }) loading.value = false if (loginForm.value.remember) { + // 保存用户名 localStorage.setItem('login_username', loginForm.value.username) + // 保存 加密密码串 + localStorage.setItem('login_password', finalForm.password) } else { + // 移除用户名 localStorage.removeItem('login_username') + // 移除 加密密码串 + localStorage.removeItem('login_password') + // 移除私钥 + removePrivateKey() } router.push(redirect.value) }) @@ -186,8 +195,12 @@ loginForm.value.password = '111111' handleLogin() } -onBeforeMount(() => { +onBeforeMount(async () => { loginForm.value.username = localStorage.login_username || '' + if (localStorage.login_username) { + const passwoed = await RSAdecrypt(localStorage.login_password) + loginForm.value.password = passwoed + } getBaseConfig() }) diff --git a/src/views/system/area/editArea.vue b/src/views/system/area/editArea.vue index 8256924..70384ba 100644 --- a/src/views/system/area/editArea.vue +++ b/src/views/system/area/editArea.vue @@ -6,7 +6,7 @@ import AreaSelectTree from './areaSelectTree.vue' import type { IareaForm } from './area-interface' import { addArea, getAreaType, updateArea } from '@/api/system/area' -const emits = defineEmits(['watchChild']) +const emits = defineEmits(['watchChild', 'refresh']) const dataFormRef = ref() const areaSelect = ref() const dialogFormVisible = ref(false) // 对话框是否显示 @@ -18,7 +18,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 1, // 排序 }) // 表单 const areaSelectShow = ref(false) const areaLevelList = ref([]) as any // 区域树列表数据 @@ -28,7 +28,7 @@ } // 表头显示标题 const btnLoading = ref(false) // 保存按钮的加载中状态 const rules: FormRules = { - id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }], + id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }, { type: 'number', message: '必须为数字值' }], areaName: [{ required: true, message: '区域名称不能为空', trigger: ['blur', 'change'] }], simpleName: [{ required: true, message: '区域简称不能为空', trigger: ['blur', 'change'] }], pName: [{ required: true, message: '上级区域必选', trigger: ['blur', 'change'] }], @@ -49,7 +49,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 4, // 排序 } } // 获取区域类型 @@ -118,6 +118,10 @@ nextTick(() => { dataFormRef.value.clearValidate() }) + // 通知父组件刷新状态 + setTimeout(() => { + emits('refresh') + }) }).catch(() => { // 选否,关闭窗口,并刷新页面 emits('watchChild') dialogFormVisible.value = false @@ -143,6 +147,9 @@ }) dataFormRef.value.clearValidate() emits('watchChild') + setTimeout(() => { + emits('refresh') + }) dialogFormVisible.value = false } }).catch((_) => { // 异常情况,loading置为false diff --git a/src/views/system/area/listArea.vue b/src/views/system/area/listArea.vue index 38fd8ae..deb0bfe 100644 --- a/src/views/system/area/listArea.vue +++ b/src/views/system/area/listArea.vue @@ -44,6 +44,7 @@ // 获取区域数据 const fetchData = () => { listLoading.value = true + list.value = [] getAreaByPid('0').then((res) => { list.value = res.data.map((item: any) => ({ ...item, hasChildren: true })) list.value = toTreeList(list.value) @@ -118,7 +119,7 @@ ) => { getAreaByPid(row.id).then((res) => { console.log(res.data, 'res.data') - const data = res.data.map((item: any) => ({ ...item, hasChildren: item.level < 4 })) + const data = res.data.map((item: any) => ({ ...item, hasChildren: true })) resolve(data) }) } @@ -150,7 +151,7 @@ - + diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index cfcbfaf..45b4fe4 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -4,6 +4,7 @@ import { doLogin, getConfig, getInfo, getUserMenus } from '@/api/system/login' import { changePwd } from '@/api/system/user' import type { Menu } from '@/global' +import { getPrivateKey, privateStr, setPrivateKey } from '@/utils/auth' const useUserStore = defineStore( // 唯一ID @@ -20,6 +21,7 @@ attr1: '', // 备用属性 tenantId: '', // 租户id publicKey: localStorage.publicKey || '', // 公钥 + privateKey: getPrivateKey() || '', // 私钥 roleList: [] as string[], // 角色id集合 roleNames: [] as string[], // 角色名称集合 roleTips: [] as string[], // 角色标签集合 @@ -47,6 +49,9 @@ getPublicKey: (state) => { return state.publicKey }, + getPrivateKey: (state) => { + return state.privateKey + }, getMenus: (state): Menu.menu[] => { return state.menus }, @@ -61,6 +66,9 @@ getConfig().then((res) => { this.publicKey = res.data.publicKey localStorage.setItem('publicKey', res.data.publicKey) + // 保存私钥 + setPrivateKey(privateStr) + this.privateKey = privateStr resolve(res.data) }).catch((e) => { reject(e) diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..fb2046a --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,14 @@ +const PrivateKey = 'private_key' // 私钥 +export const privateStr = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK7mTyBxMUnLlS0x+a0qJHd/8RxR73eTN+15GPr6wzl8dG86Jvzb66pAyOBpFmIxyvceIcgVjm8Dpz5F9vlHYI6K2g6HHID1TZ4teSfPEtRAgCpcC8pA7wqd6sDVCNx2zvGEkHZc+FYWVjhFW0xPbCvaUx3b1AMTgX+TPIOE0GnHAgMBAAECgYEAhJApfzRsIDu++L99N4POmgiOLmHn+CDMbiCwD2LLX6H1+mwAKv1hVOy/lF/ySEDnToA3KJk2GOyS8X9EH1K7WmxRcJ1am1JLwy+spHkExQzvAO9mrEhtavpwAZLiBoCUB4uQazETHncM0lNXtUYY8Ydd/zKodCMVPN4tql84f0kCQQDrPEgk6vdAc8vW1JL3ldhRkbl7DKuvDhhoixGEbXrsXXiKN6iB0A3lNTptMxcd1TjSJz8CF8piGRpVyLGoZOYLAkEAvlaXoVXndT+hbsStjORp2RGxZWMPyyyJ4Kw2TnMaUuODXA0PtnYcSA5lI6SpVAvTthSX7VDi5C9xLyc+QRvMtQJAVjzhTfd98XkCL536yx16El1UHFJG1oRaWmkxYNUqDWEvAazp770weukKpGHohZ1XmWOd68yA+3msd+p9hviGhQJAUIntgUwLM3aoRWmdkhd4nmw5JxCCt1LySIo2NH3J7rbsd3/jXS6fCvJkY2+iYrjabZpLKxTl3O4iM3SkiAJOXQJBAN++IAMMs7HVTQnsIN+L+tQwcWM5jn0sSRLGFvSkPjlT2W++qJNTW/oswmcQTPFn7Vf3GaE5JF6XAxrZMOZBG00=' +// 获取私钥 +export function getPrivateKey() { + return window.localStorage.getItem(PrivateKey) +} +// 设置私钥 +export function setPrivateKey(privateKey: string) { + return window.localStorage.setItem(PrivateKey, privateKey) +} +// 移除私钥 +export function removePrivateKey() { + return window.localStorage.removeItem(PrivateKey) +} diff --git a/src/utils/security.ts b/src/utils/security.ts index 9252b14..160b4b0 100644 --- a/src/utils/security.ts +++ b/src/utils/security.ts @@ -28,4 +28,25 @@ } return enRes } - +/** + * 解密 + * @param value 待解密数据 + * @returns 解密结果 + */ +export async function RSAdecrypt(value: string): Promise { + var encrypt = new JsEncrypt() + let enRes = '' + if (userStore.getPrivateKey && userStore.getPrivateKey === '') { + const res = await userStore.getBaseConfig() + if (res && res.privateKey) { + const privateKey = res.privateKey + encrypt.setPrivateKey(privateKey) + enRes = encrypt.decrypt(value) || '' + } + } + else { + encrypt.setPrivateKey(userStore.getPrivateKey) + enRes = encrypt.decrypt(value) || '' + } + return enRes +} diff --git a/src/views/login.vue b/src/views/login.vue index 1f1a316..bd0d64d 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -9,7 +9,8 @@ import type { FormInstance, FormRules } from 'element-plus' import { ElMessage } from 'element-plus' import useUserStore from '@/store/modules/user' -import { RSAencrypt } from '@/utils/security' +import { RSAdecrypt, RSAencrypt } from '@/utils/security' +import { getPrivateKey, removePrivateKey } from '@/utils/auth' const route = useRoute() const router = useRouter() @@ -88,10 +89,18 @@ }) loading.value = false if (loginForm.value.remember) { + // 保存用户名 localStorage.setItem('login_username', loginForm.value.username) + // 保存 加密密码串 + localStorage.setItem('login_password', finalForm.password) } else { + // 移除用户名 localStorage.removeItem('login_username') + // 移除 加密密码串 + localStorage.removeItem('login_password') + // 移除私钥 + removePrivateKey() } router.push(redirect.value) }) @@ -186,8 +195,12 @@ loginForm.value.password = '111111' handleLogin() } -onBeforeMount(() => { +onBeforeMount(async () => { loginForm.value.username = localStorage.login_username || '' + if (localStorage.login_username) { + const passwoed = await RSAdecrypt(localStorage.login_password) + loginForm.value.password = passwoed + } getBaseConfig() }) diff --git a/src/views/system/area/editArea.vue b/src/views/system/area/editArea.vue index 8256924..70384ba 100644 --- a/src/views/system/area/editArea.vue +++ b/src/views/system/area/editArea.vue @@ -6,7 +6,7 @@ import AreaSelectTree from './areaSelectTree.vue' import type { IareaForm } from './area-interface' import { addArea, getAreaType, updateArea } from '@/api/system/area' -const emits = defineEmits(['watchChild']) +const emits = defineEmits(['watchChild', 'refresh']) const dataFormRef = ref() const areaSelect = ref() const dialogFormVisible = ref(false) // 对话框是否显示 @@ -18,7 +18,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 1, // 排序 }) // 表单 const areaSelectShow = ref(false) const areaLevelList = ref([]) as any // 区域树列表数据 @@ -28,7 +28,7 @@ } // 表头显示标题 const btnLoading = ref(false) // 保存按钮的加载中状态 const rules: FormRules = { - id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }], + id: [{ required: true, message: '区域编号不能为空', trigger: ['blur', 'change'] }, { type: 'number', message: '必须为数字值' }], areaName: [{ required: true, message: '区域名称不能为空', trigger: ['blur', 'change'] }], simpleName: [{ required: true, message: '区域简称不能为空', trigger: ['blur', 'change'] }], pName: [{ required: true, message: '上级区域必选', trigger: ['blur', 'change'] }], @@ -49,7 +49,7 @@ areaName: '', // 区域名 simpleName: '', // 别名, level: '', - num: 99, // 排序 + num: 4, // 排序 } } // 获取区域类型 @@ -118,6 +118,10 @@ nextTick(() => { dataFormRef.value.clearValidate() }) + // 通知父组件刷新状态 + setTimeout(() => { + emits('refresh') + }) }).catch(() => { // 选否,关闭窗口,并刷新页面 emits('watchChild') dialogFormVisible.value = false @@ -143,6 +147,9 @@ }) dataFormRef.value.clearValidate() emits('watchChild') + setTimeout(() => { + emits('refresh') + }) dialogFormVisible.value = false } }).catch((_) => { // 异常情况,loading置为false diff --git a/src/views/system/area/listArea.vue b/src/views/system/area/listArea.vue index 38fd8ae..deb0bfe 100644 --- a/src/views/system/area/listArea.vue +++ b/src/views/system/area/listArea.vue @@ -44,6 +44,7 @@ // 获取区域数据 const fetchData = () => { listLoading.value = true + list.value = [] getAreaByPid('0').then((res) => { list.value = res.data.map((item: any) => ({ ...item, hasChildren: true })) list.value = toTreeList(list.value) @@ -118,7 +119,7 @@ ) => { getAreaByPid(row.id).then((res) => { console.log(res.data, 'res.data') - const data = res.data.map((item: any) => ({ ...item, hasChildren: item.level < 4 })) + const data = res.data.map((item: any) => ({ ...item, hasChildren: true })) resolve(data) }) } @@ -150,7 +151,7 @@ - + diff --git a/src/views/system/dept/listDept.vue b/src/views/system/dept/listDept.vue index 64ffbc4..95dd3c2 100644 --- a/src/views/system/dept/listDept.vue +++ b/src/views/system/dept/listDept.vue @@ -11,16 +11,16 @@ const { proxy } = getCurrentInstance() as any // 默认查询条件 -const defaultQuery = { - keyword: '', -} +// const defaultQuery = { +// deptName: '', +// } // 查询条件 -const listQuery = reactive({ ...defaultQuery }) +const listQuery = reactive({ deptName: '' }) // 搜索重置 -function reset() { - Object.assign(listQuery, defaultQuery) - fetchData() -} +// function reset() { +// Object.assign(listQuery, defaultQuery) +// fetchData() +// } // 表格表头 const columns = ref([ { text: '组织名称', value: 'simpleName', align: 'left' }, @@ -39,6 +39,7 @@ // 查询数据 function fetchData() { loading.value = true + console.log(listQuery, 'listQuery') getDeptList(listQuery).then((res) => { const treeData = toTreeList(res.data.list, '0', false) list.value = treeData @@ -99,7 +100,7 @@ - +