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' {
AppContainer: typeof import('./src/layouts/components/AppContainer/components/AppContainer.vue')['default']
AppLoading: typeof import('./src/layouts/components/AppContainer/components/AppLoading.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']
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']
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']
Upload: typeof import('./src/components/Upload/components/Upload.vue')['default']
}
......
......@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>信贷系统</title>
<title></title>
</head>
<body>
<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[] = [
title: '首页',
path: '/home',
type: 'menu',
icon: 'el-icon-s-home'
icon: 'material-symbols:home'
},
{
id: '2',
name: 'Trade',
title: '交易管理',
type: 'dir',
icon: 'el-icon-s-tools',
icon: 'mdi:form',
children: [
{
id: 'T1001',
......
......@@ -9,6 +9,7 @@ module.exports = defineConfig({
printer: {
axiosImport: 'import axios from \'@/utils/remote\';',
prettier: fs.readJsonSync(path.resolve(__dirname, '.prettierrc.json')),
responseTypeName: 'Promise',
},
openAPIs: [
{
......
......@@ -16,6 +16,31 @@
"description": "",
"tags": [],
"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": {
"200": {
"description": "成功",
......@@ -58,6 +83,83 @@
},
"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": {
......
This diff is collapsed.
......@@ -32,10 +32,12 @@
"vue": "2.7.14",
"vue-router": "3.6.5",
"vue2-editor": "^2.10.3",
"vxe-table": "^3.6.13",
"xe-utils": "^3.5.11",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@happygen/openapi-axios": "^0.1.3",
"@happygen/openapi-axios": "^0.1.5",
"@iconify/vue2": "^2.1.0",
"@types/lodash": "^4.14.195",
"@types/mockjs": "^1.0.7",
......
......@@ -44,14 +44,20 @@ dependencies:
vue2-editor:
specifier: ^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:
specifier: ^0.18.5
version: 0.18.5
devDependencies:
'@happygen/openapi-axios':
specifier: ^0.1.3
version: 0.1.3(vitest@0.33.0)
specifier: ^0.1.5
version: 0.1.5(vitest@0.33.0)
'@iconify/vue2':
specifier: ^2.1.0
version: 2.1.0(vue@2.7.14)
......@@ -1584,8 +1590,8 @@ packages:
dev: true
optional: true
/@happygen/openapi-axios@0.1.3(vitest@0.33.0):
resolution: {integrity: sha512-EfH1G5uFSIuEdE5gcTYStYoEzk8Pii9Y1Cqgmu+UhQJ0NOUI3Ifc+CqgWbj/WCbreL+IQw1uBTI8Yvi4w8bMJg==}
/@happygen/openapi-axios@0.1.5(vitest@0.33.0):
resolution: {integrity: sha512-DTknLJVCI0eoh7d64JEdwMmP5Dshyn604LUTb38WS26E2fRO1cnS9ZhQ0ENA2ARAsUBPi71+U5QfG2ginrL7Uw==}
engines: {node: '>=14.21'}
hasBin: true
dependencies:
......@@ -5256,6 +5262,16 @@ packages:
'@vue/shared': 3.3.4
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:
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
dependencies:
......@@ -5365,6 +5381,10 @@ packages:
optional: true
dev: true
/xe-utils@3.5.11:
resolution: {integrity: sha512-lyKc/lTBga1Zb63p+FED8mtxLnYIjSS8PVJM1N64NGdCu/3d1XubaVeke2p91RHssP0ExVAl2LUqZYperoz76Q==}
dev: false
/xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'}
......
<template>
<a-config-provider :locale="zhCN">
<router-view />
<Lock v-show="configStore.isLock" />
<TheModal />
<MagnifierDialogVue />
<div>
<router-view />
<TheLock v-if="configStore.isLock" />
<TheModal />
<TheMagnifierDialogVue />
</div>
</a-config-provider>
</template>
<script setup lang="ts">
import zhCN from 'ant-design-vue/lib/locale/zh_CN'
import Lock from '@/components/Lock'
import MagnifierDialogVue from '@/components/Magnifier/magnifierDialog.vue'
import TheModal from '@/components/Modal/index.vue'
import TheLock from '@/components/TheLock'
import TheMagnifierDialogVue from '@/components/Magnifier/magnifierDialog.vue'
import TheModal from '@/components/TheModal/index.vue'
import { useConfigStore } from '@/store/modules'
const configStore = useConfigStore()
</script>
<style>
.main {
height: 100vh;
width: 100vw;
}
</style>
......@@ -14,31 +14,34 @@ import axios from '@/utils/remote'
const request = axios.request
export type PostQueryMenuResData = {
/**
* @title 菜单数据
*/
data: Array<Menu>
/**
* @title 状态码
*/
responseCode: string
/**
* @title 返回信息
* @description 报错时提示该条信息
*/
responseMsg?: string
/**
* @title 未命名接口
* @description
*/
export async function postLogin(
data?: PostLoginReqData,
config?: AxiosRequestConfig
): Promise<PostLoginResData> {
return request({
url: `/sso/login`,
method: POST,
data,
...config
})
}
/**
* @title 查询菜单
* @description
*/
export async function postQueryMenu(
data?: PostQueryMenuReqData,
config?: AxiosRequestConfig
): AxiosPromise<PostQueryMenuResData> {
): Promise<PostQueryMenuResData> {
return request({
url: `/sso/menu/queryMenu`,
method: POST,
data,
...config
})
}
......@@ -55,7 +55,6 @@
</template>
<script>
import { post } from '@/utils/remote'
import { handleNumberToString } from '@/utils'
export default {
name: 'magnifierDialog',
......@@ -183,12 +182,11 @@ export default {
post(
this.tablePostUrl,
{
...handleNumberToString(params)
...params
},
(res) => {
this.data = res.data
this.pagination.total = res[this.totalNumber]
//
},
(res) => {},
{
......
......@@ -16,7 +16,7 @@
<div class="loginDialog" v-if="isShowDialog">
<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>
<div class="rowInput">
......@@ -29,59 +29,29 @@
/>
</div>
<div class="buttonList">
<span class="back" @click="goBack()"> 返回 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="backToLogin" @click="backToLogin()">返回登录</span>
<span class="joinSystem" @click="joinSys()">进入系统</span>
<span class="back" @click="isShowDialog = false">返回</span>
<span class="backToLogin" @click="appStore.logout()">返回登录</span>
<span class="joinSystem" @click="userSystem.setLock(false)">进入系统</span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { Icon } from '@iconify/vue2'
import { useConfigStore } from '@/store/modules'
import { ref, onUnmounted } from 'vue'
import { useUserStore } from '@/store/modules'
import { useAppStore, useUserStore, useConfigStore } from '@/store/modules'
import { useTime } from '@/hooks/utils'
const appStore = useAppStore()
const userSystem = useConfigStore()
const userStore = useUserStore()
//周数组
const days: Array<string> = ['日', '一', '二', '三', '四', '五', '六']
//时间
let hour = ref(new Date().getHours())
//秒
let minute = ref(new Date().getMinutes())
//总时间 年月日星期几
let time = ref('')
//是否打开登录弹框
const { day, hour, minute } = useTime()
const time = computed(() => day.value.format('YYYY/MM/DD dddd'))
let isShowDialog = ref(false)
//密码
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>
<style lang="less" scoped>
@i-size-ratio: 250;
.lockPage {
position: absolute;
left: 0;
......@@ -93,13 +63,13 @@ onUnmounted(() => {
background-color: #000;
z-index: 999;
header {
height: 0.6rem;
height: calc(0.6px * @i-size-ratio);
display: flex;
justify-content: center;
align-items: center;
div {
display: flex;
width: 0.8rem;
width: calc(0.8px * @i-size-ratio);
height: 100%;
flex-direction: column;
justify-content: center;
......@@ -112,11 +82,11 @@ onUnmounted(() => {
align-items: center;
cursor: pointer;
svg {
width: 0.15rem;
height: 0.15rem;
width: calc(0.15px * @i-size-ratio);
height: calc(0.15px * @i-size-ratio);
}
span {
font-size: 0.1rem;
font-size: calc(0.1px * @i-size-ratio);
}
}
}
......@@ -136,7 +106,7 @@ onUnmounted(() => {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5rem;
font-size: calc(1.5px * @i-size-ratio);
}
}
.overspread {
......@@ -182,13 +152,11 @@ onUnmounted(() => {
input {
width: 320px;
height: 30px;
// font-size: 0.2rem;
// padding: 0.1rem;
}
}
.buttonList {
width: 320px;
height: 0.2rem;
height: calc(0.2px * @i-size-ratio);
display: flex;
justify-content: space-between;
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 {
PROD: boolean
// 应用名称
VITE_APP_NAME: string
// location前缀
VITE_LOCATION_PREFIX: string
// 请求前缀
VITE_BASIC_URL: string
// 超时时间
VITE_TIME_OUT: number
//是否开启顶部菜单
IS_SHOW_HEADER_MENU: boolean
}
const env = import.meta.env as unknown as BrowserEnv
export const { MODE, DEV, PROD } = env
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_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 { useMenuStore } from '@/store/modules'
import { Icon } from '@iconify/vue2'
import { useRouter } from 'vue-router/composables'
import { useMenuStore } from '@/store/modules'
import { prefixCls } from '@/enums/const'
// 顶级菜单
......@@ -76,7 +77,7 @@ const SubMenu = defineComponent({
<span slot="title">
<MenuSpan item={item} />
</span>
{item?.children?.map((item: MenuRouteConfig) => {
{item?.children?.map((item: any) => {
if (item.children) {
return <SubMenu key={item.name} item={item} />
}
......@@ -114,9 +115,20 @@ const MenuSpan = (context: any) => {
const { item } = context.props
return (
<div>
{item?.meta?.icon ? <a-icon type={item.meta.icon} /> : null}
<span>{item?.meta.title}</span>
<div
style={{
display: 'flex',
alignItems: 'center'
}}
>
{item?.meta?.icon ? <Icon icon={item.meta.icon} /> : null}
<span
style={{
marginLeft: '5px'
}}
>
{item?.meta.title}
</span>
</div>
)
}
......
<template>
<div :class="`${prefixCls}-headerBtnList`">
<div class="foldButton" @click="configStore.toggleCollapsed">
<!-- <a-icon
class="triggerBtn"
:type="configStore.isCollapsed ? 'menu-unfold' : 'menu-fold'"
/> -->
<Icon
icon="icon-park-twotone:menu-fold-one"
:class="{
......@@ -40,13 +36,10 @@
<img src="../../../assets/img/header.png" alt="" />
<span class="userInfoBox">{{ userStore?.userInfo?.userName }}</span>
<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)">
<Icon icon="ion:lock-closed-outline" />锁定屏幕
</span>
<span @click="logout"> <Icon icon="ion:power-outline" />退出系统 </span>
<span @click="appStore.logout"> <Icon icon="ion:power-outline" />退出系统</span>
</div>
</span>
</div>
......@@ -55,11 +48,12 @@
<script lang="ts" setup>
import { Icon } from '@iconify/vue2'
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 { computed, ref } from 'vue'
import NoticeList from './NoticeList.vue'
import { useSystemNoticeStore } from '@/store/modules'
const appStore = useAppStore()
const menuStore = useMenuStore()
const userStore = useUserStore()
const configStore = useConfigStore()
......@@ -68,10 +62,6 @@ const visible = ref(false)
const systemNoticeStore = useSystemNoticeStore()
let information = ref(6)
function logout() {
router.push('/login')
}
const listData = ref([
{
key: '1',
......@@ -130,32 +120,6 @@ let newsList = computed(() => {
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>
<style lang="less" scoped>
.@{prefixCls}-headerBtnList {
......
......@@ -5,23 +5,32 @@ import Antd from 'ant-design-vue'
import './themes/default.less'
import moment from 'moment'
import 'moment/locale/zh-cn'
import 'dayjs/locale/zh-cn'
import { createHead, HeadVuePlugin } from '@vueuse/head'
import router from './router'
import './directives'
import { useAppStore } from '@/store/modules'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
import TimeDate from '@/components/TimeDate'
import Step from '@/components/Step'
import magnifier from '@/components/Magnifier/magnifier.vue'
import { post } from '@/utils/remote/remote'
import api from '@/utils/remote'
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(VXETable)
Vue.use(TimeDate)
Vue.use(Step)
Vue.component('magnifier', magnifier)
// ********** 方法 **********
const bus = new Vue()
Vue.prototype.$bus = bus // 事件总线
......@@ -32,13 +41,16 @@ Vue.prototype.$api = api
Vue.prototype.$queryEnum = queryEnum
Vue.prototype.$getTableFiled = (table: string, filed: string, index: string) =>
table + '[' + index + ']' + '.' + filed
// ********** 插件 **********
const head = createHead({
title: isLogin ? '信贷系统 - 登录' : '信贷系统'
})
Vue.use(HeadVuePlugin, head)
Vue.use(head)
// ********** 其他 **********
Vue.config.productionTip = false
Vue.config.devtools = false
import './apis/openapi'
new Vue({
pinia,
router,
......@@ -46,5 +58,5 @@ new Vue({
})
.$mount('#app')
.$nextTick(() => {
!location.hash.startsWith('#/login') && useAppStore()
!isLogin && useAppStore()
})
......@@ -63,26 +63,23 @@
<script>
import { prefixCls } from '@/enums/const'
import api from '@/utils/remote'
import { postLogin } from '@/apis'
export default {
data() {
return {
form: this.$form.createForm(this),
prefixClsName: ''
prefixClsName: prefixCls
}
},
created() {
this.prefixClsName = prefixCls
},
methods: {
login() {
this.form.validateFields(async (err, values) => {
if (!err) {
let { data } = await api.post('/sso/login')
let { data } = await postLogin(values)
localStorage.setItem('userId', data.userId)
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'
import VueRouter from 'vue-router'
import type { RouteConfig } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import createRouterGuard from './guards'
Vue.use(VueRouter)
......@@ -38,10 +37,8 @@ export const pageRoutes: RouteConfig[] = [
}
]
export const router = createRouterGuard(
new VueRouter({
mode: 'hash',
routes: localRoutes.concat(setupLayouts(pageRoutes))
})
)
export const router = new VueRouter({
mode: 'hash',
routes: localRoutes.concat(setupLayouts(pageRoutes))
})
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 { setupLayouts } from 'virtual:generated-layouts'
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', () => {
const userId = ref(localStorage.getItem('userId'))
const loading = ref(true)
const menuStore = useMenuStore()
const configStore = useConfigStore()
if (!userId.value) {
location.hash = '/login'
location.hash = '#/login'
}
router.addRoutes(setupLayouts(generatedRoutes))
queryMenu().then((r) => {
console.log(r)
function transformToMenu(item: Menu[]): any[] {
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 {
loading
loading,
logout
}
})
......@@ -23,7 +23,6 @@ export const useConfigStore = defineStore('config', {
this.homeViewMode = this.homeViewMode === 'tile' ? 'tag' : 'tile'
},
clear() {
// localStorage.removeItem('config'); 清除localStorage
this.setLock(false)
}
},
......
export * from './app'
export * from './system'
export * from './user'
export * from './config'
export * from './menu'
......
export const useMenuStore = defineStore('menu', {
state: () => ({
menuRoute: [] as any[],
menu: [] as MenuRouteConfig[],
menu: [] as any[],
selectedMenu: '',
openedMenu: [] as string[],
visitedMenu: [] as any[]
......@@ -10,7 +10,7 @@ export const useMenuStore = defineStore('menu', {
setMenuRoute(menuRoute: any[]) {
this.menuRoute = menuRoute
},
setMenu(menu: MenuRouteConfig[]): void {
setMenu(menu: any[]): void {
this.menu = menu
},
setSelectedMenu(menuName: string): void {
......@@ -19,7 +19,7 @@ export const useMenuStore = defineStore('menu', {
setOpenedMenu(menu: string[]): void {
this.openedMenu = menu
},
addVisitedMenu(menu: Object): void {
addVisitedMenu(menu: any): void {
if (menu.meta.title && !this.visitedMenu.some((item) => item?.name === this.selectedMenu)) {
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 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({
if (!data) {
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
}
}
......@@ -68,5 +61,5 @@ export function post<T>(
}
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 {
class remote {
instance: AxiosInstance
interceptors?: remoteInterceptors
constructor(config: remoteConfig) {
this.instance = axios.create(config)
this.interceptors = config.interceptors
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptor as any,
this.interceptors?.requestErrorInterceptor
)
this.instance.interceptors.response.use(
......@@ -39,21 +39,15 @@ class remote {
)
}
request<T>(config: remoteConfig): void {
this.instance.request<T>(config).then((res) => {})
request<T>(config: remoteConfig): Promise<AxiosResponse<T>> {
return this.instance.request<T>(config)
}
post<T>(config: postConfig): Promise<T> {
return this.instance.post<T>(config.url, config.data || {}, { ...config }) as any
post<T>(config: postConfig): Promise<AxiosResponse<T>> {
return this.instance.post<T>(config.url, config.data || {}, { ...config })
}
// post<T = any>(config: remoteConfig): Promise<T> {
// return this.request<T>({ ...config, method: 'POST' }) as any;
// }
get<T>(config: getConfig): Promise<T> {
return this.instance.get<T>(config.url, { ...config }) as any
get<T>(config: getConfig): Promise<AxiosResponse<T>> {
return this.instance.get<T>(config.url, { ...config })
}
// get<T>(config: remoteConfig): Promise<T> {
// return this.request<T>({ ...config, method: 'GET' }) as any;
// }
}
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 {
*/
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 {}
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-plugin-pages/client" />
/// <reference types="vite-plugin-vue-layouts/client" />
/// <reference types="openapi-axios/helpers" />
/// <reference types="@happygen/openapi-axios/helpers" />
declare module '*.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