Commit db1a2091 authored by sunguoshu's avatar sunguoshu

优化

parent e7d69ef8
**/.git
**/.svn
**/.hg
**/node_modules
.idea
DS_Store
dist
\ No newline at end of file
...@@ -10,13 +10,13 @@ declare module 'vue' { ...@@ -10,13 +10,13 @@ declare module 'vue' {
AppContainer: typeof import('./src/layouts/components/AppContainer/components/AppContainer.vue')['default'] AppContainer: typeof import('./src/layouts/components/AppContainer/components/AppContainer.vue')['default']
AppLoading: typeof import('./src/layouts/components/AppContainer/components/AppLoading.vue')['default'] AppLoading: typeof import('./src/layouts/components/AppContainer/components/AppLoading.vue')['default']
Index: typeof import('./src/views/system/Affiche.vue')['default'] Index: typeof import('./src/views/system/Affiche.vue')['default']
Lock: typeof import('./src/components/Lock/components/Lock.vue')['default'] Lock: typeof import('./src/components/TheLock/components/Lock.vue')['default']
Magnifier: typeof import('./src/components/Magnifier/magnifier.vue')['default'] Magnifier: typeof import('./src/components/Magnifier/magnifier.vue')['default']
MagnifierDialog: typeof import('./src/components/Magnifier/magnifierDialog.vue')['default'] MagnifierDialog: typeof import('./src/components/Magnifier/magnifierDialog.vue')['default']
Modal: typeof import('./src/components/Modal/index.vue')['default'] Modal: typeof import('./src/components/TheModal/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
TheModal: typeof import('./src/layouts/components/Modal/index.vue')['default'] TheModal: typeof import('./src/components/TheModal/index.vue')['default']
TimeBetween: typeof import('./src/components/TimeBetween/components/TimeBetween.vue')['default'] TimeBetween: typeof import('./src/components/TimeBetween/components/TimeBetween.vue')['default']
Upload: typeof import('./src/components/Upload/components/Upload.vue')['default'] Upload: typeof import('./src/components/Upload/components/Upload.vue')['default']
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.png" /> <link rel="icon" type="image/svg+xml" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>信贷系统</title> <title></title>
</head> </head>
<body> <body>
<div id="markWaterDiv"></div> <div id="markWaterDiv"></div>
......
import { defineMock } from 'vite-plugin-mock-dev-server'
import mockjs from 'mockjs'
export default defineMock([
{
url: '/api/sso/user/queryUser',
body: mockjs.mock({
responseCode: '200',
data: {
userId: '1234567890',
userName: '张三',
token: '1234567890'
}
})
},
{
url: '/api/sso/lazyload',
body: {
img: 'https://tudingtu.cn/i/2023/01/30/i7kc99.png'
}
}
])
...@@ -8,14 +8,14 @@ const menu: Menu[] = [ ...@@ -8,14 +8,14 @@ const menu: Menu[] = [
title: '首页', title: '首页',
path: '/home', path: '/home',
type: 'menu', type: 'menu',
icon: 'el-icon-s-home' icon: 'material-symbols:home'
}, },
{ {
id: '2', id: '2',
name: 'Trade', name: 'Trade',
title: '交易管理', title: '交易管理',
type: 'dir', type: 'dir',
icon: 'el-icon-s-tools', icon: 'mdi:form',
children: [ children: [
{ {
id: 'T1001', id: 'T1001',
......
...@@ -9,6 +9,7 @@ module.exports = defineConfig({ ...@@ -9,6 +9,7 @@ module.exports = defineConfig({
printer: { printer: {
axiosImport: 'import axios from \'@/utils/remote\';', axiosImport: 'import axios from \'@/utils/remote\';',
prettier: fs.readJsonSync(path.resolve(__dirname, '.prettierrc.json')), prettier: fs.readJsonSync(path.resolve(__dirname, '.prettierrc.json')),
responseTypeName: 'Promise',
}, },
openAPIs: [ openAPIs: [
{ {
......
...@@ -16,6 +16,31 @@ ...@@ -16,6 +16,31 @@
"description": "", "description": "",
"tags": [], "tags": [],
"parameters": [], "parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "菜单名称",
"description": "英文名",
"additionalProperties": false
}
},
"x-apifox-orders": [
"name"
],
"x-apifox-refs": {},
"required": [
"name"
],
"x-apifox-ignore-properties": []
}
}
}
},
"responses": { "responses": {
"200": { "200": {
"description": "成功", "description": "成功",
...@@ -58,6 +83,83 @@ ...@@ -58,6 +83,83 @@
}, },
"x-run-in-apifox": "https://apifox.com/web/project/3045565/apis/api-97257136-run" "x-run-in-apifox": "https://apifox.com/web/project/3045565/apis/api-97257136-run"
} }
},
"/sso/login": {
"post": {
"summary": "未命名接口",
"x-apifox-folder": "",
"x-apifox-status": "developing",
"deprecated": false,
"description": "",
"tags": [],
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"userId": {
"type": "string",
"title": "账号"
},
"password": {
"type": "string",
"title": "密码"
}
},
"x-apifox-orders": [
"userId",
"password"
],
"required": [
"userId",
"password"
],
"x-apifox-ignore-properties": []
}
}
}
},
"responses": {
"200": {
"description": "成功",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"userId": {
"type": "string",
"title": "账号"
},
"username": {
"type": "string",
"title": "用户名"
},
"token": {
"type": "string",
"title": "token"
}
},
"x-apifox-orders": [
"userId",
"username",
"token"
],
"required": [
"userId",
"username",
"token"
],
"x-apifox-ignore-properties": []
}
}
}
}
},
"x-run-in-apifox": "https://apifox.com/web/project/3045565/apis/api-98004163-run"
}
} }
}, },
"components": { "components": {
......
This diff is collapsed.
...@@ -32,10 +32,12 @@ ...@@ -32,10 +32,12 @@
"vue": "2.7.14", "vue": "2.7.14",
"vue-router": "3.6.5", "vue-router": "3.6.5",
"vue2-editor": "^2.10.3", "vue2-editor": "^2.10.3",
"vxe-table": "^3.6.13",
"xe-utils": "^3.5.11",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@happygen/openapi-axios": "^0.1.3", "@happygen/openapi-axios": "^0.1.5",
"@iconify/vue2": "^2.1.0", "@iconify/vue2": "^2.1.0",
"@types/lodash": "^4.14.195", "@types/lodash": "^4.14.195",
"@types/mockjs": "^1.0.7", "@types/mockjs": "^1.0.7",
......
...@@ -44,14 +44,20 @@ dependencies: ...@@ -44,14 +44,20 @@ dependencies:
vue2-editor: vue2-editor:
specifier: ^2.10.3 specifier: ^2.10.3
version: 2.10.3 version: 2.10.3
vxe-table:
specifier: ^3.6.13
version: 3.6.13(vue@2.7.14)(xe-utils@3.5.11)
xe-utils:
specifier: ^3.5.11
version: 3.5.11
xlsx: xlsx:
specifier: ^0.18.5 specifier: ^0.18.5
version: 0.18.5 version: 0.18.5
devDependencies: devDependencies:
'@happygen/openapi-axios': '@happygen/openapi-axios':
specifier: ^0.1.3 specifier: ^0.1.5
version: 0.1.3(vitest@0.33.0) version: 0.1.5(vitest@0.33.0)
'@iconify/vue2': '@iconify/vue2':
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(vue@2.7.14) version: 2.1.0(vue@2.7.14)
...@@ -1584,8 +1590,8 @@ packages: ...@@ -1584,8 +1590,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@happygen/openapi-axios@0.1.3(vitest@0.33.0): /@happygen/openapi-axios@0.1.5(vitest@0.33.0):
resolution: {integrity: sha512-EfH1G5uFSIuEdE5gcTYStYoEzk8Pii9Y1Cqgmu+UhQJ0NOUI3Ifc+CqgWbj/WCbreL+IQw1uBTI8Yvi4w8bMJg==} resolution: {integrity: sha512-DTknLJVCI0eoh7d64JEdwMmP5Dshyn604LUTb38WS26E2fRO1cnS9ZhQ0ENA2ARAsUBPi71+U5QfG2ginrL7Uw==}
engines: {node: '>=14.21'} engines: {node: '>=14.21'}
hasBin: true hasBin: true
dependencies: dependencies:
...@@ -5256,6 +5262,16 @@ packages: ...@@ -5256,6 +5262,16 @@ packages:
'@vue/shared': 3.3.4 '@vue/shared': 3.3.4
dev: true dev: true
/vxe-table@3.6.13(vue@2.7.14)(xe-utils@3.5.11):
resolution: {integrity: sha512-Lm4J1dH4CAHnHWO/JKPo77SCaggPTdk7RFhCNvkMWRsReBvWwTR4zBUnEwmnomhNorRVdBYETjOnsbfor7us9Q==}
peerDependencies:
vue: ^2.6.0
xe-utils: ^3.5.0
dependencies:
vue: 2.7.14
xe-utils: 3.5.11
dev: false
/warning@4.0.3: /warning@4.0.3:
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
dependencies: dependencies:
...@@ -5365,6 +5381,10 @@ packages: ...@@ -5365,6 +5381,10 @@ packages:
optional: true optional: true
dev: true dev: true
/xe-utils@3.5.11:
resolution: {integrity: sha512-lyKc/lTBga1Zb63p+FED8mtxLnYIjSS8PVJM1N64NGdCu/3d1XubaVeke2p91RHssP0ExVAl2LUqZYperoz76Q==}
dev: false
/xlsx@0.18.5: /xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'} engines: {node: '>=0.8'}
......
<template> <template>
<a-config-provider :locale="zhCN"> <a-config-provider :locale="zhCN">
<router-view /> <div>
<Lock v-show="configStore.isLock" /> <router-view />
<TheModal /> <TheLock v-if="configStore.isLock" />
<MagnifierDialogVue /> <TheModal />
<TheMagnifierDialogVue />
</div>
</a-config-provider> </a-config-provider>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import zhCN from 'ant-design-vue/lib/locale/zh_CN' import zhCN from 'ant-design-vue/lib/locale/zh_CN'
import Lock from '@/components/Lock' import TheLock from '@/components/TheLock'
import MagnifierDialogVue from '@/components/Magnifier/magnifierDialog.vue' import TheMagnifierDialogVue from '@/components/Magnifier/magnifierDialog.vue'
import TheModal from '@/components/Modal/index.vue' import TheModal from '@/components/TheModal/index.vue'
import { useConfigStore } from '@/store/modules' import { useConfigStore } from '@/store/modules'
const configStore = useConfigStore() const configStore = useConfigStore()
</script> </script>
<style>
.main {
height: 100vh;
width: 100vw;
}
</style>
...@@ -14,31 +14,34 @@ import axios from '@/utils/remote' ...@@ -14,31 +14,34 @@ import axios from '@/utils/remote'
const request = axios.request const request = axios.request
export type PostQueryMenuResData = { /**
/** * @title 未命名接口
* @title 菜单数据 * @description
*/ */
data: Array<Menu> export async function postLogin(
/** data?: PostLoginReqData,
* @title 状态码 config?: AxiosRequestConfig
*/ ): Promise<PostLoginResData> {
responseCode: string return request({
/** url: `/sso/login`,
* @title 返回信息 method: POST,
* @description 报错时提示该条信息 data,
*/ ...config
responseMsg?: string })
} }
/** /**
* @title 查询菜单 * @title 查询菜单
* @description * @description
*/ */
export async function postQueryMenu( export async function postQueryMenu(
data?: PostQueryMenuReqData,
config?: AxiosRequestConfig config?: AxiosRequestConfig
): AxiosPromise<PostQueryMenuResData> { ): Promise<PostQueryMenuResData> {
return request({ return request({
url: `/sso/menu/queryMenu`, url: `/sso/menu/queryMenu`,
method: POST, method: POST,
data,
...config ...config
}) })
} }
...@@ -55,7 +55,6 @@ ...@@ -55,7 +55,6 @@
</template> </template>
<script> <script>
import { post } from '@/utils/remote' import { post } from '@/utils/remote'
import { handleNumberToString } from '@/utils'
export default { export default {
name: 'magnifierDialog', name: 'magnifierDialog',
...@@ -183,12 +182,11 @@ export default { ...@@ -183,12 +182,11 @@ export default {
post( post(
this.tablePostUrl, this.tablePostUrl,
{ {
...handleNumberToString(params) ...params
}, },
(res) => { (res) => {
this.data = res.data this.data = res.data
this.pagination.total = res[this.totalNumber] this.pagination.total = res[this.totalNumber]
//
}, },
(res) => {}, (res) => {},
{ {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="loginDialog" v-if="isShowDialog"> <div class="loginDialog" v-if="isShowDialog">
<div class="userInfo"> <div class="userInfo">
<img src="../../../assets/img/header.png" alt="用户头像" /> <img src="@/assets/img/header.png" alt="用户头像" />
<div class="userName">{{ userStore.userInfo?.userName }}</div> <div class="userName">{{ userStore.userInfo?.userName }}</div>
</div> </div>
<div class="rowInput"> <div class="rowInput">
...@@ -29,59 +29,29 @@ ...@@ -29,59 +29,29 @@
/> />
</div> </div>
<div class="buttonList"> <div class="buttonList">
<span class="back" @click="goBack()"> 返回 &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class="back" @click="isShowDialog = false">返回</span>
<span class="backToLogin" @click="backToLogin()">返回登录</span> <span class="backToLogin" @click="appStore.logout()">返回登录</span>
<span class="joinSystem" @click="joinSys()">进入系统</span> <span class="joinSystem" @click="userSystem.setLock(false)">进入系统</span>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Icon } from '@iconify/vue2' import { Icon } from '@iconify/vue2'
import { useConfigStore } from '@/store/modules' import { useAppStore, useUserStore, useConfigStore } from '@/store/modules'
import { ref, onUnmounted } from 'vue' import { useTime } from '@/hooks/utils'
import { useUserStore } from '@/store/modules' const appStore = useAppStore()
const userSystem = useConfigStore() const userSystem = useConfigStore()
const userStore = useUserStore() const userStore = useUserStore()
//周数组 const { day, hour, minute } = useTime()
const days: Array<string> = ['日', '一', '二', '三', '四', '五', '六'] const time = computed(() => day.value.format('YYYY/MM/DD dddd'))
//时间
let hour = ref(new Date().getHours())
//秒
let minute = ref(new Date().getMinutes())
//总时间 年月日星期几
let time = ref('')
//是否打开登录弹框
let isShowDialog = ref(false) let isShowDialog = ref(false)
//密码
let password = ref('') let password = ref('')
//定时更新时间
let interval = setInterval(() => {
let icnow = new Date()
time.value = `${icnow.getFullYear()}/${icnow.getMonth() + 1}/${icnow.getDate()} 星期${
days[icnow.getDay()]
}`
hour.value = icnow.getHours()
minute.value = icnow.getMinutes()
}, 1000)
//返回
function goBack() {
isShowDialog.value = false
}
//返回系统
function joinSys() {
userSystem.setLock(false)
}
//去登录
function backToLogin() {
location.hash = '#/login'
}
onUnmounted(() => {
password.value = ''
clearInterval(interval)
})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@i-size-ratio: 250;
.lockPage { .lockPage {
position: absolute; position: absolute;
left: 0; left: 0;
...@@ -93,13 +63,13 @@ onUnmounted(() => { ...@@ -93,13 +63,13 @@ onUnmounted(() => {
background-color: #000; background-color: #000;
z-index: 999; z-index: 999;
header { header {
height: 0.6rem; height: calc(0.6px * @i-size-ratio);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
div { div {
display: flex; display: flex;
width: 0.8rem; width: calc(0.8px * @i-size-ratio);
height: 100%; height: 100%;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
...@@ -112,11 +82,11 @@ onUnmounted(() => { ...@@ -112,11 +82,11 @@ onUnmounted(() => {
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
svg { svg {
width: 0.15rem; width: calc(0.15px * @i-size-ratio);
height: 0.15rem; height: calc(0.15px * @i-size-ratio);
} }
span { span {
font-size: 0.1rem; font-size: calc(0.1px * @i-size-ratio);
} }
} }
} }
...@@ -136,7 +106,7 @@ onUnmounted(() => { ...@@ -136,7 +106,7 @@ onUnmounted(() => {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 1.5rem; font-size: calc(1.5px * @i-size-ratio);
} }
} }
.overspread { .overspread {
...@@ -182,13 +152,11 @@ onUnmounted(() => { ...@@ -182,13 +152,11 @@ onUnmounted(() => {
input { input {
width: 320px; width: 320px;
height: 30px; height: 30px;
// font-size: 0.2rem;
// padding: 0.1rem;
} }
} }
.buttonList { .buttonList {
width: 320px; width: 320px;
height: 0.2rem; height: calc(0.2px * @i-size-ratio);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
......
/**
* 基本地址
*/
import { PROD, VITE_LOCATION_PREFIX } from '@/enums/env'
// 登录地址
export const LOGIN_PATH = VITE_LOCATION_PREFIX + '/login' + (PROD ? '' : '/')
// 首页地址
export const HOME_PATH = VITE_LOCATION_PREFIX + '/'
...@@ -11,21 +11,15 @@ export interface BrowserEnv extends ImportMetaEnv { ...@@ -11,21 +11,15 @@ export interface BrowserEnv extends ImportMetaEnv {
PROD: boolean PROD: boolean
// 应用名称 // 应用名称
VITE_APP_NAME: string VITE_APP_NAME: string
// location前缀
VITE_LOCATION_PREFIX: string
// 请求前缀 // 请求前缀
VITE_BASIC_URL: string VITE_BASIC_URL: string
// 超时时间 // 超时时间
VITE_TIME_OUT: number VITE_TIME_OUT: number
//是否开启顶部菜单
IS_SHOW_HEADER_MENU: boolean
} }
const env = import.meta.env as unknown as BrowserEnv const env = import.meta.env as unknown as BrowserEnv
export const { MODE, DEV, PROD } = env export const { MODE, DEV, PROD } = env
export const VITE_APP_NAME = env.VITE_APP_NAME || '' export const VITE_APP_NAME = env.VITE_APP_NAME || ''
export const VITE_LOCATION_PREFIX = env.VITE_LOCATION_PREFIX || ''
export const VITE_BASIC_URL = env.VITE_BASIC_URL || '' export const VITE_BASIC_URL = env.VITE_BASIC_URL || ''
export const VITE_TIME_OUT = Number(env.VITE_TIME_OUT) || 0 export const VITE_TIME_OUT = Number(env.VITE_TIME_OUT) || 0
export const IS_SHOW_HEADER_MENU = Boolean(env.IS_SHOW_HEADER_MENU) || true
export const useState = <T>(initialState: T) => {
const state = ref<T>(initialState)
const setState = (newState: T) => {
state.value = newState as any
}
return [state, setState] as const
}
import dayjs from 'dayjs'
export const useTime = () => {
let timer: any = null
const day = ref(dayjs())
const second = computed(() => day.value.second())
const minute = computed(() => day.value.minute())
const hour = computed(() => day.value.hour())
onMounted(() => {
timer = setInterval(() => {
day.value = dayjs()
}, 1000)
})
onUnmounted(() => {
clearInterval(timer)
})
return {
day: day,
second,
minute,
hour
}
}
import { Menu } from 'ant-design-vue' import { Menu } from 'ant-design-vue'
import { useMenuStore } from '@/store/modules' import { Icon } from '@iconify/vue2'
import { useRouter } from 'vue-router/composables' import { useRouter } from 'vue-router/composables'
import { useMenuStore } from '@/store/modules'
import { prefixCls } from '@/enums/const' import { prefixCls } from '@/enums/const'
// 顶级菜单 // 顶级菜单
...@@ -76,7 +77,7 @@ const SubMenu = defineComponent({ ...@@ -76,7 +77,7 @@ const SubMenu = defineComponent({
<span slot="title"> <span slot="title">
<MenuSpan item={item} /> <MenuSpan item={item} />
</span> </span>
{item?.children?.map((item: MenuRouteConfig) => { {item?.children?.map((item: any) => {
if (item.children) { if (item.children) {
return <SubMenu key={item.name} item={item} /> return <SubMenu key={item.name} item={item} />
} }
...@@ -114,9 +115,20 @@ const MenuSpan = (context: any) => { ...@@ -114,9 +115,20 @@ const MenuSpan = (context: any) => {
const { item } = context.props const { item } = context.props
return ( return (
<div> <div
{item?.meta?.icon ? <a-icon type={item.meta.icon} /> : null} style={{
<span>{item?.meta.title}</span> display: 'flex',
alignItems: 'center'
}}
>
{item?.meta?.icon ? <Icon icon={item.meta.icon} /> : null}
<span
style={{
marginLeft: '5px'
}}
>
{item?.meta.title}
</span>
</div> </div>
) )
} }
......
<template> <template>
<div :class="`${prefixCls}-headerBtnList`"> <div :class="`${prefixCls}-headerBtnList`">
<div class="foldButton" @click="configStore.toggleCollapsed"> <div class="foldButton" @click="configStore.toggleCollapsed">
<!-- <a-icon
class="triggerBtn"
:type="configStore.isCollapsed ? 'menu-unfold' : 'menu-fold'"
/> -->
<Icon <Icon
icon="icon-park-twotone:menu-fold-one" icon="icon-park-twotone:menu-fold-one"
:class="{ :class="{
...@@ -40,13 +36,10 @@ ...@@ -40,13 +36,10 @@
<img src="../../../assets/img/header.png" alt="" /> <img src="../../../assets/img/header.png" alt="" />
<span class="userInfoBox">{{ userStore?.userInfo?.userName }}</span> <span class="userInfoBox">{{ userStore?.userInfo?.userName }}</span>
<div class="userButton"> <div class="userButton">
<span @click="goSelfNews"> <Icon icon="mdi:user-outline" />个人信息 </span>
<span @click="goChangePwd"> <Icon icon="fluent:key-reset-20-filled" />修改密码 </span>
<span @click="configStore.setLock(true)"> <span @click="configStore.setLock(true)">
<Icon icon="ion:lock-closed-outline" />锁定屏幕 <Icon icon="ion:lock-closed-outline" />锁定屏幕
</span> </span>
<span @click="appStore.logout"> <Icon icon="ion:power-outline" />退出系统</span>
<span @click="logout"> <Icon icon="ion:power-outline" />退出系统 </span>
</div> </div>
</span> </span>
</div> </div>
...@@ -55,11 +48,12 @@ ...@@ -55,11 +48,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Icon } from '@iconify/vue2' import { Icon } from '@iconify/vue2'
import { prefixCls } from '@/enums/const' import { prefixCls } from '@/enums/const'
import { useUserStore, useConfigStore, useMenuStore } from '@/store/modules' import { useAppStore, useUserStore, useConfigStore, useMenuStore } from '@/store/modules'
import { useRouter } from 'vue-router/composables' import { useRouter } from 'vue-router/composables'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import NoticeList from './NoticeList.vue' import NoticeList from './NoticeList.vue'
import { useSystemNoticeStore } from '@/store/modules' import { useSystemNoticeStore } from '@/store/modules'
const appStore = useAppStore()
const menuStore = useMenuStore() const menuStore = useMenuStore()
const userStore = useUserStore() const userStore = useUserStore()
const configStore = useConfigStore() const configStore = useConfigStore()
...@@ -68,10 +62,6 @@ const visible = ref(false) ...@@ -68,10 +62,6 @@ const visible = ref(false)
const systemNoticeStore = useSystemNoticeStore() const systemNoticeStore = useSystemNoticeStore()
let information = ref(6) let information = ref(6)
function logout() {
router.push('/login')
}
const listData = ref([ const listData = ref([
{ {
key: '1', key: '1',
...@@ -130,32 +120,6 @@ let newsList = computed(() => { ...@@ -130,32 +120,6 @@ let newsList = computed(() => {
return listData return listData
}) })
function goChangePwd() {
menuStore.setSelectedMenu('changePwd')
menuStore.addVisitedMenu({
path: '/changePwd',
name: 'changePwd',
meta: {
title: '修改密码'
},
component: () => import('@/views/trades/changePwd/Index.vue')
})
router.push('/changePwd')
}
function goSelfNews() {
menuStore.setSelectedMenu('selfNews')
menuStore.addVisitedMenu({
path: '/selfNews',
name: 'selfNews',
meta: {
title: '修改个人信息'
},
component: () => import('@/views/trades/selfNews/Index.vue')
})
router.push('/selfNews')
}
//
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.@{prefixCls}-headerBtnList { .@{prefixCls}-headerBtnList {
......
...@@ -5,23 +5,32 @@ import Antd from 'ant-design-vue' ...@@ -5,23 +5,32 @@ import Antd from 'ant-design-vue'
import './themes/default.less' import './themes/default.less'
import moment from 'moment' import moment from 'moment'
import 'moment/locale/zh-cn' import 'moment/locale/zh-cn'
import 'dayjs/locale/zh-cn'
import { createHead, HeadVuePlugin } from '@vueuse/head'
import router from './router' import router from './router'
import './directives' import './directives'
import { useAppStore } from '@/store/modules' import { useAppStore } from '@/store/modules'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
import TimeDate from '@/components/TimeDate' import TimeDate from '@/components/TimeDate'
import Step from '@/components/Step' import Step from '@/components/Step'
import magnifier from '@/components/Magnifier/magnifier.vue' import magnifier from '@/components/Magnifier/magnifier.vue'
import { post } from '@/utils/remote/remote' import { post } from '@/utils/remote/remote'
import api from '@/utils/remote' import api from '@/utils/remote'
import queryEnum from '@/utils/remote/queryEnum' import queryEnum from '@/utils/remote/queryEnum'
import dayjs from 'dayjs'
dayjs.locale('zh-cn')
const isLogin = location.hash.startsWith('#/login')
// ********** 组件 ********** // ********** 组件 **********
Vue.use(Antd) Vue.use(Antd)
Vue.use(VXETable)
Vue.use(TimeDate) Vue.use(TimeDate)
Vue.use(Step) Vue.use(Step)
Vue.component('magnifier', magnifier) Vue.component('magnifier', magnifier)
// ********** 方法 ********** // ********** 方法 **********
const bus = new Vue() const bus = new Vue()
Vue.prototype.$bus = bus // 事件总线 Vue.prototype.$bus = bus // 事件总线
...@@ -32,13 +41,16 @@ Vue.prototype.$api = api ...@@ -32,13 +41,16 @@ Vue.prototype.$api = api
Vue.prototype.$queryEnum = queryEnum Vue.prototype.$queryEnum = queryEnum
Vue.prototype.$getTableFiled = (table: string, filed: string, index: string) => Vue.prototype.$getTableFiled = (table: string, filed: string, index: string) =>
table + '[' + index + ']' + '.' + filed table + '[' + index + ']' + '.' + filed
// ********** 插件 **********
const head = createHead({
title: isLogin ? '信贷系统 - 登录' : '信贷系统'
})
Vue.use(HeadVuePlugin, head)
Vue.use(head)
// ********** 其他 ********** // ********** 其他 **********
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.config.devtools = false Vue.config.devtools = false
import './apis/openapi'
new Vue({ new Vue({
pinia, pinia,
router, router,
...@@ -46,5 +58,5 @@ new Vue({ ...@@ -46,5 +58,5 @@ new Vue({
}) })
.$mount('#app') .$mount('#app')
.$nextTick(() => { .$nextTick(() => {
!location.hash.startsWith('#/login') && useAppStore() !isLogin && useAppStore()
}) })
...@@ -63,26 +63,23 @@ ...@@ -63,26 +63,23 @@
<script> <script>
import { prefixCls } from '@/enums/const' import { prefixCls } from '@/enums/const'
import api from '@/utils/remote' import { postLogin } from '@/apis'
export default { export default {
data() { data() {
return { return {
form: this.$form.createForm(this), form: this.$form.createForm(this),
prefixClsName: '' prefixClsName: prefixCls
} }
}, },
created() {
this.prefixClsName = prefixCls
},
methods: { methods: {
login() { login() {
this.form.validateFields(async (err, values) => { this.form.validateFields(async (err, values) => {
if (!err) { if (!err) {
let { data } = await api.post('/sso/login') let { data } = await postLogin(values)
localStorage.setItem('userId', data.userId) localStorage.setItem('userId', data.userId)
localStorage.setItem('token', data.token) localStorage.setItem('token', data.token)
location.hash = '/home' location.hash = '#/home'
} }
}) })
} }
......
import type Router from 'vue-router'
import createMenuGuard from './menu'
export default function createRouterGuard(router: Router) {
createMenuGuard(router)
return router
}
import type Router from 'vue-router'
import { useMenuStore } from '@/store/modules'
export default function createMenuGuard(router: Router) {
router.beforeEach((to, from, next) => {
const menuStore = useMenuStore()
if (!to.params?.$replace) {
menuStore.addVisitedMenu(to)
}
next()
})
}
...@@ -2,7 +2,6 @@ import Vue from 'vue' ...@@ -2,7 +2,6 @@ import Vue from 'vue'
import VueRouter from 'vue-router' import VueRouter from 'vue-router'
import type { RouteConfig } from 'vue-router' import type { RouteConfig } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts' import { setupLayouts } from 'virtual:generated-layouts'
import createRouterGuard from './guards'
Vue.use(VueRouter) Vue.use(VueRouter)
...@@ -38,10 +37,8 @@ export const pageRoutes: RouteConfig[] = [ ...@@ -38,10 +37,8 @@ export const pageRoutes: RouteConfig[] = [
} }
] ]
export const router = createRouterGuard( export const router = new VueRouter({
new VueRouter({ mode: 'hash',
mode: 'hash', routes: localRoutes.concat(setupLayouts(pageRoutes))
routes: localRoutes.concat(setupLayouts(pageRoutes)) })
})
)
export default router export default router
export * from './menu'
import { post } from '@/utils/remote'
export const queryMenu = async () => {
const { code, data } = await post<QueryMenuResponse>('/sso/menu/queryMenu')
if (code === '000000') {
return data
}
return []
}
import { router } from '@/router' import { router } from '@/router'
import { setupLayouts } from 'virtual:generated-layouts' import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages' import generatedRoutes from 'virtual:generated-pages'
import { queryMenu } from '@/server' import { postQueryMenu } from '@/apis'
import { useMenuStore, useConfigStore } from '@/store/modules'
export const useAppStore = defineStore('app', () => { export const useAppStore = defineStore('app', () => {
const userId = ref(localStorage.getItem('userId')) const userId = ref(localStorage.getItem('userId'))
const loading = ref(true) const loading = ref(true)
const menuStore = useMenuStore()
const configStore = useConfigStore()
if (!userId.value) { if (!userId.value) {
location.hash = '/login' location.hash = '#/login'
} }
router.addRoutes(setupLayouts(generatedRoutes)) router.addRoutes(setupLayouts(generatedRoutes))
queryMenu().then((r) => { function transformToMenu(item: Menu[]): any[] {
console.log(r) return item.map((i) => {
let obj = {
name: i.name,
meta: {
icon: i.icon,
title: i.title
}
}
if (i.type === 'menu') {
return { ...obj, path: i.path }
}
return {
...obj,
children: transformToMenu(i.children ?? [])
}
})
}
postQueryMenu().then((r) => {
if (r.data) {
const menu = transformToMenu(r.data)
menuStore.setMenu(menu)
loading.value = false
}
}) })
function logout() {
configStore.clear()
localStorage.removeItem('userId')
location.hash = '#/login'
}
return { return {
loading loading,
logout
} }
}) })
...@@ -23,7 +23,6 @@ export const useConfigStore = defineStore('config', { ...@@ -23,7 +23,6 @@ export const useConfigStore = defineStore('config', {
this.homeViewMode = this.homeViewMode === 'tile' ? 'tag' : 'tile' this.homeViewMode = this.homeViewMode === 'tile' ? 'tag' : 'tile'
}, },
clear() { clear() {
// localStorage.removeItem('config'); 清除localStorage
this.setLock(false) this.setLock(false)
} }
}, },
......
export * from './app' export * from './app'
export * from './system'
export * from './user' export * from './user'
export * from './config' export * from './config'
export * from './menu' export * from './menu'
......
export const useMenuStore = defineStore('menu', { export const useMenuStore = defineStore('menu', {
state: () => ({ state: () => ({
menuRoute: [] as any[], menuRoute: [] as any[],
menu: [] as MenuRouteConfig[], menu: [] as any[],
selectedMenu: '', selectedMenu: '',
openedMenu: [] as string[], openedMenu: [] as string[],
visitedMenu: [] as any[] visitedMenu: [] as any[]
...@@ -10,7 +10,7 @@ export const useMenuStore = defineStore('menu', { ...@@ -10,7 +10,7 @@ export const useMenuStore = defineStore('menu', {
setMenuRoute(menuRoute: any[]) { setMenuRoute(menuRoute: any[]) {
this.menuRoute = menuRoute this.menuRoute = menuRoute
}, },
setMenu(menu: MenuRouteConfig[]): void { setMenu(menu: any[]): void {
this.menu = menu this.menu = menu
}, },
setSelectedMenu(menuName: string): void { setSelectedMenu(menuName: string): void {
...@@ -19,7 +19,7 @@ export const useMenuStore = defineStore('menu', { ...@@ -19,7 +19,7 @@ export const useMenuStore = defineStore('menu', {
setOpenedMenu(menu: string[]): void { setOpenedMenu(menu: string[]): void {
this.openedMenu = menu this.openedMenu = menu
}, },
addVisitedMenu(menu: Object): void { addVisitedMenu(menu: any): void {
if (menu.meta.title && !this.visitedMenu.some((item) => item?.name === this.selectedMenu)) { if (menu.meta.title && !this.visitedMenu.some((item) => item?.name === this.selectedMenu)) {
this.visitedMenu.push(menu) this.visitedMenu.push(menu)
} }
......
export const useSystemStore = defineStore('system', {
state: () => ({
initFlag: false as boolean, // 是否完成初始化
refreshTokenFlag: true as boolean // 是否允许刷新token
}),
actions: {
setInitFlag(flag: boolean) {
this.initFlag = flag
},
setRefreshTokenFlag(flag: boolean) {
this.refreshTokenFlag = flag
}
},
persist: {
enabled: true,
strategies: [
{
storage: window.localStorage,
paths: ['initFlag']
}
]
}
})
export * from './tree' export * from './tree'
// 对象中的数字转字符串
export const handleNumberToString = (obj: Object) => {
if (typeof obj !== 'object' || Object.keys(obj).length === 0) {
return obj
}
const resObj = {}
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === 'number') {
resObj[key] = obj[key].toString()
} else {
resObj[key] = obj[key]
}
})
return resObj
}
...@@ -19,14 +19,7 @@ const remote = new axios({ ...@@ -19,14 +19,7 @@ const remote = new axios({
if (!data) { if (!data) {
throw new Error('请求出错') throw new Error('请求出错')
} }
const { responseCode, responseMsg, data: resData } = data
// 请求失败,抛出错误信息
if (responseCode === '999999') {
responseMsg && message.error(responseMsg)
throw new Error(responseMsg)
}
// 请求成功
// if (responseCode > 200 &&responseCode<) {
return data return data
} }
} }
...@@ -68,5 +61,5 @@ export function post<T>( ...@@ -68,5 +61,5 @@ export function post<T>(
} }
export default { export default {
request: remote.request as <T = any>(config: AxiosRequestConfig) => AxiosPromise<T> request: remote.request.bind(remote) as <T>(config: AxiosRequestConfig) => Promise<T>
} }
...@@ -25,12 +25,12 @@ interface getConfig { ...@@ -25,12 +25,12 @@ interface getConfig {
class remote { class remote {
instance: AxiosInstance instance: AxiosInstance
interceptors?: remoteInterceptors interceptors?: remoteInterceptors
constructor(config: remoteConfig) { constructor(config: remoteConfig) {
this.instance = axios.create(config) this.instance = axios.create(config)
this.interceptors = config.interceptors this.interceptors = config.interceptors
this.instance.interceptors.request.use( this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor, this.interceptors?.requestInterceptor as any,
this.interceptors?.requestErrorInterceptor this.interceptors?.requestErrorInterceptor
) )
this.instance.interceptors.response.use( this.instance.interceptors.response.use(
...@@ -39,21 +39,15 @@ class remote { ...@@ -39,21 +39,15 @@ class remote {
) )
} }
request<T>(config: remoteConfig): void { request<T>(config: remoteConfig): Promise<AxiosResponse<T>> {
this.instance.request<T>(config).then((res) => {}) return this.instance.request<T>(config)
} }
post<T>(config: postConfig): Promise<T> { post<T>(config: postConfig): Promise<AxiosResponse<T>> {
return this.instance.post<T>(config.url, config.data || {}, { ...config }) as any return this.instance.post<T>(config.url, config.data || {}, { ...config })
} }
// post<T = any>(config: remoteConfig): Promise<T> { get<T>(config: getConfig): Promise<AxiosResponse<T>> {
// return this.request<T>({ ...config, method: 'POST' }) as any; return this.instance.get<T>(config.url, { ...config })
// }
get<T>(config: getConfig): Promise<T> {
return this.instance.get<T>(config.url, { ...config }) as any
} }
// get<T>(config: remoteConfig): Promise<T> {
// return this.request<T>({ ...config, method: 'GET' }) as any;
// }
} }
export default remote export default remote
export function getToken() {
return window.localStorage.getItem('sso-token')
}
export function setToken(token: string | null) {
window.localStorage.setItem('sso-token', token!)
}
...@@ -35,6 +35,53 @@ declare global { ...@@ -35,6 +35,53 @@ declare global {
*/ */
type: 'dir' | 'menu' type: 'dir' | 'menu'
} }
export type PostLoginReqData = {
/**
* @title 密码
*/
password: string
/**
* @title 账号
*/
userId: string
}
export type PostLoginResData = {
/**
* @title token
*/
token: string
/**
* @title 账号
*/
userId: string
/**
* @title 用户名
*/
username: string
}
export type PostQueryMenuReqData = {
/**
* @title 菜单名称
* @description 英文名
*/
name: string
}
export type PostQueryMenuResData = {
/**
* @title 菜单数据
*/
data: Array<Menu>
/**
* @title 状态码
*/
responseCode: string
/**
* @title 返回信息
* @description 报错时提示该条信息
*/
responseMsg?: string
}
} }
export {} export {}
import type { RouteConfigSingleView } from 'vue-router/types/router'
declare global {
export interface MenuMeta {
title?: string
icon?: string
}
export type MenuRouteConfig = {
name: string
path?: string
meta?: MenuMeta
children?: MenuRouteConfig[]
}
}
export {}
declare global {
export enum ResponseCode {
SUCCESS = '000000',
ERROR = '999999'
}
export interface Request {}
export interface Response<T = any> {
code: ResponseCode
data?: T
}
export interface RequestMenu {
name: string // 菜单名称,唯一
title: string // 菜单标题
icon?: string // 菜单图标
path?: string // 路由路径
children?: RequestMenu[] // 子菜单
}
/**
* @url /sso/menu/queryMenu
* @method post
* @description 查询菜单
*/
export interface QueryMenuResponse extends Response<RequestMenu> {}
}
export {}
/// <reference types="vite/client" /> /// <reference types="vite/client" />
/// <reference types="vite-plugin-pages/client" /> /// <reference types="vite-plugin-pages/client" />
/// <reference types="vite-plugin-vue-layouts/client" /> /// <reference types="vite-plugin-vue-layouts/client" />
/// <reference types="openapi-axios/helpers" /> /// <reference types="@happygen/openapi-axios/helpers" />
declare module '*.vue' { declare module '*.vue' {
import type { DefineComponent } from 'vue' import type { DefineComponent } from 'vue'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment