style: 使用eslint、prettier
This commit is contained in:
parent
d06ac9e983
commit
0ea5217a9f
15
frontend/.editorconfig
Normal file
15
frontend/.editorconfig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*] # 表示所有文件适用
|
||||||
|
charset = utf-8 # 设置文件字符集为 utf-8
|
||||||
|
indent_style = space # 缩进风格(tab | space)
|
||||||
|
indent_size = 2 # 缩进大小
|
||||||
|
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||||
|
trim_trailing_whitespace = true # 去除行首的任意空白字符
|
||||||
|
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||||
|
|
||||||
|
[*.md] # 表示仅 md 文件适用以下规则
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
21
frontend/.eslintrc.js
Normal file
21
frontend/.eslintrc.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'plugin:vue/vue3-essential',
|
||||||
|
'eslint:recommended',
|
||||||
|
'@vue/prettier',
|
||||||
|
'plugin:prettier/recommended'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2020
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
|
'vue/multi-word-component-names': 'off', // 组件名称校验
|
||||||
|
'vue/valid-v-pre': 'off' // 自定指令校验
|
||||||
|
}
|
||||||
|
}
|
9
frontend/.prettierignore
Normal file
9
frontend/.prettierignore
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/dist/*
|
||||||
|
.local
|
||||||
|
.output.js
|
||||||
|
/node_modules/**
|
||||||
|
|
||||||
|
**/*.svg
|
||||||
|
**/*.sh
|
||||||
|
|
||||||
|
/public/*
|
9
frontend/.prettierrc
Normal file
9
frontend/.prettierrc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"useTabs": false,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"printWidth": 100,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"semi": false
|
||||||
|
}
|
2262
frontend/package-lock.json
generated
2262
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview --port 4173"
|
"preview": "vite preview --port 4173",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
|
||||||
|
"prettier": "prettier --write ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^3.2.12",
|
"ant-design-vue": "^3.2.12",
|
||||||
@ -17,7 +19,12 @@
|
|||||||
"vue-router": "^4.1.5"
|
"vue-router": "^4.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@vitejs/plugin-vue": "^3.0.3",
|
"@vitejs/plugin-vue": "^3.0.3",
|
||||||
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
|
"eslint": "^8.22.0",
|
||||||
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
"unplugin-vue-components": "^0.22.7",
|
"unplugin-vue-components": "^0.22.7",
|
||||||
"vite": "^3.0.9"
|
"vite": "^3.0.9"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterView } from "vue-router";
|
import { RouterView } from 'vue-router'
|
||||||
import { Spin } from "ant-design-vue";
|
import { Spin } from 'ant-design-vue'
|
||||||
import { userStore } from "./stores/user";
|
import { userStore } from './stores/user'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from 'vue-router'
|
||||||
import { computed } from "vue";
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute()
|
||||||
const cruPath = computed(() => {
|
const cruPath = computed(() => {
|
||||||
return route.path.substring(1, route.path.length).split("/");
|
return route.path.substring(1, route.path.length).split('/')
|
||||||
});
|
})
|
||||||
console.log(route.path, route.fullPath);
|
console.log(route.path, route.fullPath)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="crumb">
|
<div class="crumb">
|
||||||
<a-breadcrumb>
|
<a-breadcrumb>
|
||||||
<a-breadcrumb-item href="">Home</a-breadcrumb-item>
|
<a-breadcrumb-item href="">Home</a-breadcrumb-item>
|
||||||
<template v-for="path in cruPath">
|
<template v-for="path in cruPath" :key="path">
|
||||||
<a-breadcrumb-item>
|
<a-breadcrumb-item>
|
||||||
{{ path }}
|
{{ path }}
|
||||||
</a-breadcrumb-item>
|
</a-breadcrumb-item>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue'
|
||||||
import UserInfo from "@/components/layout/layout-info/layout-info.vue";
|
import UserInfo from '@/components/layout/layout-info/layout-info.vue'
|
||||||
import HeaderCrumb from "./header-crumb.vue";
|
import HeaderCrumb from './header-crumb.vue'
|
||||||
import { loadIconCpn } from "@/utils/loadCpn";
|
import { loadIconCpn } from '@/utils/loadCpn'
|
||||||
|
|
||||||
// 记录图标状态
|
// 记录图标状态
|
||||||
const collapsed = ref(false);
|
const collapsed = ref(false)
|
||||||
|
|
||||||
const emits = defineEmits(["changeFold"]);
|
const emits = defineEmits(['changeFold'])
|
||||||
|
|
||||||
// 修改图标状态同时传递参数给父组件让其变更菜单收缩
|
// 修改图标状态同时传递参数给父组件让其变更菜单收缩
|
||||||
const clickMenuFold = () => {
|
const clickMenuFold = () => {
|
||||||
collapsed.value = !collapsed.value;
|
collapsed.value = !collapsed.value
|
||||||
// 父组件需要绑定这个事件
|
// 父组件需要绑定这个事件
|
||||||
emits("changeFold", collapsed.value);
|
emits('changeFold', collapsed.value)
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue'
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router'
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
import SelectRole from "./select-role.vue";
|
import SelectRole from './select-role.vue'
|
||||||
|
|
||||||
const store = userStore();
|
const store = userStore()
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
const roleChangeRef = ref();
|
const roleChangeRef = ref()
|
||||||
|
|
||||||
const onClick = ({ key }) => {
|
const onClick = ({ key }) => {
|
||||||
if (key === "1") {
|
if (key === '1') {
|
||||||
// 点击切换角色
|
// 点击切换角色
|
||||||
roleChangeRef.value?.showModal();
|
roleChangeRef.value?.showModal()
|
||||||
} else {
|
} else {
|
||||||
store.$reset();
|
store.$reset()
|
||||||
router.push("/login");
|
router.push('/login')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from "vue";
|
import { ref, computed } from 'vue'
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
const store = userStore();
|
const store = userStore()
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false)
|
||||||
const visible = ref(false);
|
const visible = ref(false)
|
||||||
|
|
||||||
const currentRoleId = ref(store.userInfo.roles[0].id);
|
const currentRoleId = ref(store.userInfo.roles[0].id)
|
||||||
|
|
||||||
// 角色列表选项
|
// 角色列表选项
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
return store.userInfo.roles.map((role) => ({
|
return store.userInfo.roles.map((role) => ({
|
||||||
label: role.name,
|
label: role.name,
|
||||||
value: role.id,
|
value: role.id
|
||||||
}));
|
}))
|
||||||
});
|
})
|
||||||
|
|
||||||
const showModal = () => {
|
const showModal = () => {
|
||||||
visible.value = true;
|
visible.value = true
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
store.userSelectRole(currentRoleId.value);
|
store.userSelectRole(currentRoleId.value)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
visible.value = false;
|
visible.value = false
|
||||||
}, 1000);
|
}, 1000)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
visible.value = false;
|
visible.value = false
|
||||||
};
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
showModal,
|
showModal
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -44,13 +44,7 @@ defineExpose({
|
|||||||
<a-modal v-model:visible="visible" title="切换角色" @ok="handleOk">
|
<a-modal v-model:visible="visible" title="切换角色" @ok="handleOk">
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button key="back" @click="handleCancel">取消</a-button>
|
<a-button key="back" @click="handleCancel">取消</a-button>
|
||||||
<a-button
|
<a-button key="submit" type="primary" :loading="loading" @click="handleOk">确定</a-button>
|
||||||
key="submit"
|
|
||||||
type="primary"
|
|
||||||
:loading="loading"
|
|
||||||
@click="handleOk"
|
|
||||||
>确定</a-button
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
<span>选择角色:</span>
|
<span>选择角色:</span>
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router'
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
import { loadIconCpn } from "@/utils/loadCpn";
|
import { loadIconCpn } from '@/utils/loadCpn'
|
||||||
|
|
||||||
const store = userStore();
|
const store = userStore()
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
// 菜单点击事件
|
// 菜单点击事件
|
||||||
const menuClick = (menu) => {
|
const menuClick = (menu) => {
|
||||||
router.push(menu.path);
|
router.push(menu.path)
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -44,7 +44,7 @@ const menuClick = (menu) => {
|
|||||||
.logo {
|
.logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background: rgba(255, 255, 255, 0.3) url("@/assets/img/fastapi.svg");
|
background: rgba(255, 255, 255, 0.3) url('@/assets/img/fastapi.svg');
|
||||||
margin: 16px;
|
margin: 16px;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from 'vue'
|
||||||
|
|
||||||
import App from "./App.vue";
|
import App from './App.vue'
|
||||||
import router from "./router";
|
import router from './router'
|
||||||
import store from "./stores";
|
import store from './stores'
|
||||||
|
|
||||||
import { userStore } from "./stores/user";
|
import { userStore } from './stores/user'
|
||||||
|
|
||||||
import "normalize.css";
|
import 'normalize.css'
|
||||||
import "@/assets/css/base.css";
|
import '@/assets/css/base.css'
|
||||||
|
|
||||||
import "ant-design-vue/dist/antd.css";
|
import 'ant-design-vue/dist/antd.css'
|
||||||
import hasPermisson from "@/utils/directive";
|
import hasPermisson from '@/utils/directive'
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App)
|
||||||
hasPermisson(app);
|
hasPermisson(app)
|
||||||
app.use(store);
|
app.use(store)
|
||||||
|
|
||||||
userStore().loadRoleRouter();
|
userStore().loadRoleRouter()
|
||||||
app.use(router);
|
app.use(router)
|
||||||
|
|
||||||
app.mount("#app");
|
app.mount('#app')
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import { message } from "ant-design-vue";
|
import { message } from 'ant-design-vue'
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: '/',
|
||||||
redirect: "/main",
|
redirect: '/main'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: '/login',
|
||||||
meta: { title: "登录页" },
|
meta: { title: '登录页' },
|
||||||
component: () => import("@/views/login/login.vue"),
|
component: () => import('@/views/login/login.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "main",
|
name: 'main',
|
||||||
path: "/main",
|
path: '/main',
|
||||||
meta: { title: "主页" },
|
meta: { title: '主页' },
|
||||||
component: () => import("@/views/main/main.vue"),
|
component: () => import('@/views/main/main.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:pathMatch(.*)*",
|
path: '/:pathMatch(.*)*',
|
||||||
component: () => import("@/views/error/404.vue"),
|
component: () => import('@/views/error/404.vue')
|
||||||
},
|
}
|
||||||
];
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: routes,
|
routes: routes
|
||||||
});
|
})
|
||||||
|
|
||||||
// 导航守卫
|
// 导航守卫
|
||||||
router.beforeEach((to) => {
|
router.beforeEach((to) => {
|
||||||
// 修改页面标题
|
// 修改页面标题
|
||||||
if (to.meta.title) {
|
if (to.meta.title) {
|
||||||
document.title = to.meta.title;
|
document.title = to.meta.title
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to.path !== "/login") {
|
if (to.path !== '/login') {
|
||||||
if (userStore().token) {
|
if (userStore().token) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
message.warning("请登录");
|
message.warning('请登录')
|
||||||
return "/login";
|
return '/login'
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
export default router;
|
export default router
|
||||||
|
@ -1,38 +1,38 @@
|
|||||||
import request from "@/utils/request";
|
import request from '@/utils/request'
|
||||||
|
|
||||||
export function login(data) {
|
export function login(data) {
|
||||||
return request({
|
return request({
|
||||||
url: "/login",
|
url: '/login',
|
||||||
method: "post",
|
method: 'post',
|
||||||
data,
|
data
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
export function getUserInfo(uid) {
|
export function getUserInfo(uid) {
|
||||||
return request({
|
return request({
|
||||||
url: `/user/${uid}`,
|
url: `/user/${uid}`
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取权限信息
|
// 获取权限信息
|
||||||
export function getMenus(rid) {
|
export function getMenus(rid) {
|
||||||
return request({
|
return request({
|
||||||
url: `/role/${rid}/menu`,
|
url: `/role/${rid}/menu`
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改用户信息
|
// 修改用户信息
|
||||||
export function selectRole(rid) {
|
export function selectRole(rid) {
|
||||||
return request({
|
return request({
|
||||||
url: `/user/role/${rid}`,
|
url: `/user/role/${rid}`,
|
||||||
method: "put",
|
method: 'put'
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户列表
|
// 获取用户列表
|
||||||
export function getUsers() {
|
export function getUsers() {
|
||||||
return request({
|
return request({
|
||||||
url: "/user",
|
url: '/user'
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,4 @@ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
|||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
pinia.use(piniaPluginPersistedstate)
|
pinia.use(piniaPluginPersistedstate)
|
||||||
|
|
||||||
|
|
||||||
export default pinia
|
export default pinia
|
@ -1,32 +1,32 @@
|
|||||||
import { ref, computed } from "vue";
|
import { ref, computed } from 'vue'
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from 'pinia'
|
||||||
import { message } from "ant-design-vue";
|
import { message } from 'ant-design-vue'
|
||||||
|
|
||||||
import router from "@/router";
|
import router from '@/router'
|
||||||
import { loadRouter, loadDefaultMenu } from "@/utils/loadCpn";
|
import { loadRouter, loadDefaultMenu } from '@/utils/loadCpn'
|
||||||
import { getMenus, getUserInfo, login, selectRole } from "@/service/user";
|
import { getMenus, getUserInfo, login, selectRole } from '@/service/user'
|
||||||
|
|
||||||
export const userStore = defineStore(
|
export const userStore = defineStore(
|
||||||
"user",
|
'user',
|
||||||
() => {
|
() => {
|
||||||
const token = ref("");
|
const token = ref('')
|
||||||
const userInfo = ref({});
|
const userInfo = ref({})
|
||||||
const userMenus = ref([]);
|
const userMenus = ref([])
|
||||||
|
|
||||||
const selectKey = ref(null);
|
const selectKey = ref(null)
|
||||||
|
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false)
|
||||||
|
|
||||||
// getter
|
// getter
|
||||||
const accessToken = computed(() => "Bearer " + token.value);
|
const accessToken = computed(() => 'Bearer ' + token.value)
|
||||||
|
|
||||||
// setup store 不提供$reset 需要自己重置
|
// setup store 不提供$reset 需要自己重置
|
||||||
// https://github.com/vuejs/pinia/issues/1056
|
// https://github.com/vuejs/pinia/issues/1056
|
||||||
const $reset = () => {
|
const $reset = () => {
|
||||||
token.value = "";
|
token.value = ''
|
||||||
userInfo.value = {};
|
userInfo.value = {}
|
||||||
userMenus.value = [];
|
userMenus.value = []
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息 & 菜单路由
|
* 获取用户信息 & 菜单路由
|
||||||
@ -34,48 +34,48 @@ export const userStore = defineStore(
|
|||||||
*/
|
*/
|
||||||
const getUserData = async (uid) => {
|
const getUserData = async (uid) => {
|
||||||
// 2. 获取用户信息
|
// 2. 获取用户信息
|
||||||
const info = await getUserInfo(uid);
|
const info = await getUserInfo(uid)
|
||||||
userInfo.value = info.data;
|
userInfo.value = info.data
|
||||||
|
|
||||||
// 3. 获取权限信息
|
// 3. 获取权限信息
|
||||||
const menus = await getMenus(info.data.roles[0].id);
|
const menus = await getMenus(info.data.roles[0].id)
|
||||||
userMenus.value = menus.data;
|
userMenus.value = menus.data
|
||||||
|
|
||||||
// 3.1 加载权限
|
// 3.1 加载权限
|
||||||
loadRouter(menus.data);
|
loadRouter(menus.data)
|
||||||
|
|
||||||
// 3.2 默认跳转路由
|
// 3.2 默认跳转路由
|
||||||
const defaultMenu = loadDefaultMenu(menus.data);
|
const defaultMenu = loadDefaultMenu(menus.data)
|
||||||
|
|
||||||
selectKey.value = [defaultMenu.id];
|
selectKey.value = [defaultMenu.id]
|
||||||
// 4. 跳转
|
// 4. 跳转
|
||||||
if (defaultMenu.path) {
|
if (defaultMenu.path) {
|
||||||
router.push(defaultMenu.path);
|
router.push(defaultMenu.path)
|
||||||
} else {
|
} else {
|
||||||
router.push("/main");
|
router.push('/main')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const loginAction = async (data) => {
|
const loginAction = async (data) => {
|
||||||
// 1. 登录
|
// 1. 登录
|
||||||
const res = await login(data);
|
const res = await login(data)
|
||||||
token.value = res.data.token;
|
token.value = res.data.token
|
||||||
await getUserData(res.data.id);
|
await getUserData(res.data.id)
|
||||||
// 弹框提示登录成功
|
// 弹框提示登录成功
|
||||||
message.success("登录成功.");
|
message.success('登录成功.')
|
||||||
};
|
}
|
||||||
|
|
||||||
// loadRouter 刷新问题
|
// loadRouter 刷新问题
|
||||||
const loadRoleRouter = () => {
|
const loadRoleRouter = () => {
|
||||||
loadRouter(userMenus.value);
|
loadRouter(userMenus.value)
|
||||||
};
|
}
|
||||||
|
|
||||||
// 切换角色
|
// 切换角色
|
||||||
const userSelectRole = async (rid) => {
|
const userSelectRole = async (rid) => {
|
||||||
await selectRole(rid);
|
await selectRole(rid)
|
||||||
// 重新拿用户信息
|
// 重新拿用户信息
|
||||||
await getUserData(userInfo.value.id);
|
await getUserData(userInfo.value.id)
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
@ -87,10 +87,10 @@ export const userStore = defineStore(
|
|||||||
$reset,
|
$reset,
|
||||||
loginAction,
|
loginAction,
|
||||||
loadRoleRouter,
|
loadRoleRouter,
|
||||||
userSelectRole,
|
userSelectRole
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
persist: true,
|
persist: true
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
export default (app) => {
|
export default (app) => {
|
||||||
// 按钮权限
|
// 按钮权限
|
||||||
app.directive("per", {
|
app.directive('per', {
|
||||||
mounted(el, binding) {
|
mounted(el, binding) {
|
||||||
console.log(el, binding.value);
|
console.log(el, binding.value)
|
||||||
if (
|
if (
|
||||||
// 是否存在
|
// 是否存在
|
||||||
userStore().userInfo.permissions.indexOf(binding.value) === -1
|
userStore().userInfo.permissions.indexOf(binding.value) === -1
|
||||||
) {
|
) {
|
||||||
// 删除元素
|
// 删除元素
|
||||||
el.parentNode && el.parentNode.removeChild(el);
|
el.parentNode && el.parentNode.removeChild(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import moment from "moment";
|
import moment from 'moment'
|
||||||
|
|
||||||
export const formatTime = (value) => {
|
export const formatTime = (value) => {
|
||||||
return moment(value).format("YYYY-MM-DD HH:mm:ss");
|
return moment(value).format('YYYY-MM-DD HH:mm:ss')
|
||||||
};
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// 动态加载组件
|
// 动态加载组件
|
||||||
import * as icons from "@ant-design/icons-vue";
|
import * as icons from '@ant-design/icons-vue'
|
||||||
import router from "@/router";
|
import router from '@/router'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态加载antd icon
|
* 动态加载antd icon
|
||||||
@ -10,27 +10,27 @@ import router from "@/router";
|
|||||||
* template: 使用 <component :is="loadIconCpn("UserField")">
|
* template: 使用 <component :is="loadIconCpn("UserField")">
|
||||||
*/
|
*/
|
||||||
function loadIconCpn(iconName) {
|
function loadIconCpn(iconName) {
|
||||||
return icons[iconName];
|
return icons[iconName]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拿到views下所有.vue文件
|
// 拿到views下所有.vue文件
|
||||||
const modules = import.meta.glob("../views/**/**.vue");
|
const modules = import.meta.glob('../views/**/**.vue')
|
||||||
|
|
||||||
function loadRouter(menus) {
|
function loadRouter(menus) {
|
||||||
for (const menu of menus) {
|
for (const menu of menus) {
|
||||||
// type 为1 菜单组件
|
// type 为1 菜单组件
|
||||||
if (menu.type === 1 && menu.path !== "") {
|
if (menu.type === 1 && menu.path !== '') {
|
||||||
const cnpPath = `../views/main${menu.component}`;
|
const cnpPath = `../views/main${menu.component}`
|
||||||
|
|
||||||
router.addRoute("main", {
|
router.addRoute('main', {
|
||||||
path: menu.path,
|
path: menu.path,
|
||||||
name: menu.name,
|
name: menu.name,
|
||||||
// 映射取值
|
// 映射取值
|
||||||
component: modules[/* @vite-ignore */ cnpPath],
|
component: modules[/* @vite-ignore */ cnpPath],
|
||||||
meta: menu.meta,
|
meta: menu.meta
|
||||||
});
|
})
|
||||||
} else if (menu.children) {
|
} else if (menu.children) {
|
||||||
loadRouter(menu.children);
|
loadRouter(menu.children)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,8 +38,8 @@ function loadRouter(menus) {
|
|||||||
// 默认打开第一个
|
// 默认打开第一个
|
||||||
function loadDefaultMenu(menus) {
|
function loadDefaultMenu(menus) {
|
||||||
for (const menu of menus) {
|
for (const menu of menus) {
|
||||||
return menu.children.find((e) => e.type === 1);
|
return menu.children.find((e) => e.type === 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { loadIconCpn, loadRouter, loadDefaultMenu };
|
export { loadIconCpn, loadRouter, loadDefaultMenu }
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
import axios from "axios";
|
import axios from 'axios'
|
||||||
import { message } from "ant-design-vue";
|
import { message } from 'ant-design-vue'
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
export default (config) => {
|
export default (config) => {
|
||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
baseURL: import.meta.env.VITE_BASE_URL,
|
baseURL: import.meta.env.VITE_BASE_URL,
|
||||||
timeout: 10000,
|
timeout: 10000
|
||||||
});
|
})
|
||||||
|
|
||||||
instance.interceptors.request.use((config) => {
|
instance.interceptors.request.use((config) => {
|
||||||
userStore().isLoading = !userStore().isLoading;
|
userStore().isLoading = !userStore().isLoading
|
||||||
config.headers.Authorization = userStore().accessToken;
|
config.headers.Authorization = userStore().accessToken
|
||||||
return config;
|
return config
|
||||||
});
|
})
|
||||||
|
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(res) => {
|
(res) => {
|
||||||
userStore().isLoading = !userStore().isLoading;
|
userStore().isLoading = !userStore().isLoading
|
||||||
if (res.data.code !== 200) {
|
if (res.data.code !== 200) {
|
||||||
message.error(res.data.msg);
|
message.error(res.data.msg)
|
||||||
}
|
}
|
||||||
console.log(res.data);
|
console.log(res.data)
|
||||||
return res.data;
|
return res.data
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
userStore().isLoading = !userStore().isLoading;
|
userStore().isLoading = !userStore().isLoading
|
||||||
if (err.response.data?.msg) {
|
if (err.response.data?.msg) {
|
||||||
message.error(err.response.data.msg);
|
message.error(err.response.data.msg)
|
||||||
} else if (err.response.data?.detail) {
|
} else if (err.response.data?.detail) {
|
||||||
// 请求参数缺失
|
// 请求参数缺失
|
||||||
message.error(err.response.data?.detail[0].msg);
|
message.error(err.response.data?.detail[0].msg)
|
||||||
} else {
|
} else {
|
||||||
message.error(err.message);
|
message.error(err.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err)
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
return instance(config);
|
return instance(config)
|
||||||
};
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
const toHome = () => {
|
const toHome = () => {
|
||||||
router.push("/");
|
router.push('/')
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,43 +1,38 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { UserOutlined, LockOutlined } from "@ant-design/icons-vue";
|
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
|
||||||
import { ref, reactive, computed } from "vue";
|
import { ref, reactive, computed } from 'vue'
|
||||||
|
|
||||||
import { userStore } from "@/stores/user";
|
import { userStore } from '@/stores/user'
|
||||||
|
|
||||||
const store = userStore();
|
const store = userStore()
|
||||||
// 表单配置
|
// 表单配置
|
||||||
const rules = {
|
const rules = {
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: "请输入用户名", trigger: "blur" },
|
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||||
{ min: 5, max: 20, message: "5~20", trigger: "blur" },
|
{ min: 5, max: 20, message: '5~20', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||||
{ min: 6, max: 12, message: "6~12", trigger: "blur" },
|
{ min: 6, max: 12, message: '6~12', trigger: 'blur' }
|
||||||
],
|
]
|
||||||
};
|
}
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const formRef = ref();
|
const formRef = ref()
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
username: "admin",
|
username: 'admin',
|
||||||
password: "123456",
|
password: '123456'
|
||||||
});
|
})
|
||||||
// 计算属性 登录按钮是否可以点击
|
// 计算属性 登录按钮是否可以点击
|
||||||
const disabled = computed(() => {
|
const disabled = computed(() => {
|
||||||
return !(formData.username && formData.password);
|
return !(formData.username && formData.password)
|
||||||
});
|
})
|
||||||
|
|
||||||
// 事件
|
// 事件
|
||||||
const submitForm = (formEl) => {
|
const submitForm = (formEl) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return
|
||||||
formEl.validate().then(
|
formEl.validate().then(() => store.loginAction(formData))
|
||||||
(res) => {
|
}
|
||||||
store.loginAction(formData);
|
|
||||||
},
|
|
||||||
(err) => err
|
|
||||||
);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -47,10 +42,7 @@ const submitForm = (formEl) => {
|
|||||||
|
|
||||||
<a-form ref="formRef" :model="formData" :rules="rules">
|
<a-form ref="formRef" :model="formData" :rules="rules">
|
||||||
<a-form-item has-feedback name="username">
|
<a-form-item has-feedback name="username">
|
||||||
<a-input
|
<a-input v-model:value.trim="formData.username" placeholder="Username">
|
||||||
v-model:value.trim="formData.username"
|
|
||||||
placeholder="Username"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<UserOutlined style="color: rgba(0, 0, 0, 0.25)" />
|
<UserOutlined style="color: rgba(0, 0, 0, 0.25)" />
|
||||||
</template>
|
</template>
|
||||||
@ -90,7 +82,7 @@ const submitForm = (formEl) => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-image: url("@/assets/img/background.svg");
|
background-image: url('@/assets/img/background.svg');
|
||||||
}
|
}
|
||||||
.continer {
|
.continer {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import SiderMenu from "@/components/layout/sider-menu.vue";
|
import SiderMenu from '@/components/layout/sider-menu.vue'
|
||||||
import LayoutHeader from "@/components/layout/layout-header.vue";
|
import LayoutHeader from '@/components/layout/layout-header.vue'
|
||||||
|
|
||||||
// a-ayout-sider 折叠状态响应式数据
|
// a-ayout-sider 折叠状态响应式数据
|
||||||
const collapsed = ref(false);
|
const collapsed = ref(false)
|
||||||
|
|
||||||
// header组件 折叠按钮事件 触发a-layout-sider折叠
|
// header组件 折叠按钮事件 触发a-layout-sider折叠
|
||||||
const changeSiderFold = (subValue) => {
|
const changeSiderFold = (subValue) => {
|
||||||
collapsed.value = subValue;
|
collapsed.value = subValue
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -30,7 +30,7 @@ const changeSiderFold = (subValue) => {
|
|||||||
:style="{
|
:style="{
|
||||||
margin: '24px 16px',
|
margin: '24px 16px',
|
||||||
background: '#F0F2F5',
|
background: '#F0F2F5',
|
||||||
minHeight: '280px',
|
minHeight: '280px'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<router-view />
|
<router-view />
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
<script setup>
|
<script setup></script>
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>role</div>
|
<div>role</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
@ -1,39 +1,39 @@
|
|||||||
// 表格数据列 表头配置
|
// 表格数据列 表头配置
|
||||||
export const columns = [
|
export const columns = [
|
||||||
{
|
{
|
||||||
title: "序号",
|
title: '序号',
|
||||||
dataIndex: "index",
|
dataIndex: 'index',
|
||||||
key: "index",
|
key: 'index',
|
||||||
align: "center",
|
align: 'center',
|
||||||
customRender: ({ text, record, index }) => `${index + 1}`,
|
customRender: ({ index }) => `${index + 1}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "用户名",
|
title: '用户名',
|
||||||
dataIndex: "username",
|
dataIndex: 'username',
|
||||||
key: "username",
|
key: 'username'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "昵称",
|
title: '昵称',
|
||||||
dataIndex: "nickname",
|
dataIndex: 'nickname',
|
||||||
key: "nickname",
|
key: 'nickname'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: '状态',
|
||||||
dataIndex: "status",
|
dataIndex: 'status',
|
||||||
key: "status",
|
key: 'status'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "创建时间",
|
title: '创建时间',
|
||||||
dataIndex: "created",
|
dataIndex: 'created',
|
||||||
key: "created",
|
key: 'created'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "更新时间",
|
title: '更新时间',
|
||||||
dataIndex: "modified",
|
dataIndex: 'modified',
|
||||||
key: "modified",
|
key: 'modified'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: '操作',
|
||||||
key: "action",
|
key: 'action'
|
||||||
},
|
}
|
||||||
];
|
]
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { getUsers } from "@/service/user";
|
import { getUsers } from '@/service/user'
|
||||||
import { columns } from "./conf";
|
import { columns } from './conf'
|
||||||
import { formatTime } from "@/utils/format";
|
import { formatTime } from '@/utils/format'
|
||||||
|
|
||||||
import { ref, reactive, onMounted } from "vue";
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
|
||||||
import { PlusOutlined, SearchOutlined } from "@ant-design/icons-vue";
|
import { PlusOutlined, SearchOutlined } from '@ant-design/icons-vue'
|
||||||
|
|
||||||
// 列表数据
|
// 列表数据
|
||||||
const dataSource = ref([]);
|
const dataSource = ref([])
|
||||||
|
|
||||||
// 页面展示数据条数变化回调
|
// 页面展示数据条数变化回调
|
||||||
const pageSizeChange = (current, size) => {
|
const pageSizeChange = (current, size) => {
|
||||||
console.log(current, size, "展示数量变化");
|
console.log(current, size, '展示数量变化')
|
||||||
};
|
}
|
||||||
|
|
||||||
// 页码变化回调
|
// 页码变化回调
|
||||||
const pageChange = (page, pageSize) => {
|
const pageChange = (page, pageSize) => {
|
||||||
console.log(page, pageSize, "页码变化");
|
console.log(page, pageSize, '页码变化')
|
||||||
};
|
}
|
||||||
|
|
||||||
//分页
|
//分页
|
||||||
const pagination = reactive({
|
const pagination = reactive({
|
||||||
@ -26,22 +26,22 @@ const pagination = reactive({
|
|||||||
pageSize: 10, // 每页数量
|
pageSize: 10, // 每页数量
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
total: 200,
|
total: 200,
|
||||||
pageSizeOptions: ["10", "50", "100"],
|
pageSizeOptions: ['10', '50', '100'],
|
||||||
showTotal: (total) => `共${total}条数据`,
|
showTotal: (total) => `共${total}条数据`,
|
||||||
onShowSizeChange: pageSizeChange,
|
onShowSizeChange: pageSizeChange,
|
||||||
onChange: pageChange,
|
onChange: pageChange
|
||||||
});
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getPageData();
|
getPageData()
|
||||||
});
|
})
|
||||||
|
|
||||||
const getPageData = () => {
|
const getPageData = () => {
|
||||||
getUsers().then((res) => {
|
getUsers().then((res) => {
|
||||||
dataSource.value = res.data.items;
|
dataSource.value = res.data.items
|
||||||
pagination.total = res.data.total;
|
pagination.total = res.data.total
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -74,15 +74,11 @@ const getPageData = () => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 数据 -->
|
<!-- 数据 -->
|
||||||
<a-table
|
<a-table :columns="columns" :data-source="dataSource" :pagination="pagination">
|
||||||
:columns="columns"
|
|
||||||
:data-source="dataSource"
|
|
||||||
:pagination="pagination"
|
|
||||||
>
|
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<a-tag :color="record.status !== 9 ? 'green' : 'red'">
|
<a-tag :color="record.status !== 9 ? 'green' : 'red'">
|
||||||
{{ record.status !== 9 ? "正常" : "已删除" }}
|
{{ record.status !== 9 ? '正常' : '已删除' }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'created'">
|
<template v-else-if="column.key === 'created'">
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
import { fileURLToPath, URL } from "node:url";
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from 'vite'
|
||||||
import vue from "@vitejs/plugin-vue";
|
import vue from '@vitejs/plugin-vue'
|
||||||
import Components from "unplugin-vue-components/vite";
|
import Components from 'unplugin-vue-components/vite'
|
||||||
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
|
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
Components({
|
Components({
|
||||||
resolvers: [AntDesignVueResolver()],
|
resolvers: [AntDesignVueResolver()]
|
||||||
}),
|
})
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
// 代理
|
// 代理
|
||||||
"/api": {
|
'/api': {
|
||||||
target: "http://localhost:8000",
|
target: 'http://localhost:8000',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, ""),
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
},
|
},
|
||||||
"/socket.io": {
|
'/socket.io': {
|
||||||
target: "ws://localhost:5000",
|
target: 'ws://localhost:5000',
|
||||||
ws: true,
|
ws: true
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user