feat: 修改路由,增加创建页面

This commit is contained in:
wangzhengkun 2022-08-11 23:13:35 +08:00
parent c7dec45022
commit 635e441f68
16 changed files with 211 additions and 103 deletions

View file

@ -24,8 +24,8 @@ export interface ReqPage {
}
export interface CommonModel {
id: number;
CreatedAt: string;
UpdatedAt: string;
CreatedAt?: string;
UpdatedAt?: string;
}
// * 登录模块

View file

@ -1,19 +0,0 @@
{
"code": 200,
"items": [
{
"ID": 11232,
"name": "admin",
"email": "admin@fit2cloud.com",
"createdAt": "2022-08-10T00:00:20+08:00"
},
{
"ID": 11222232,
"name": "admin2",
"email": "admin2@fit2cloud.com",
"createdAt": "2022-08-10T00:00:20+08:00"
}
],
"total": 100,
"msg": ""
}

View file

@ -29,31 +29,29 @@
import { ref, computed, onMounted } from 'vue';
import { RouteRecordRaw, useRoute } from 'vue-router';
import { MenuStore } from '@/store/modules/menu';
import { AuthStore } from '@/store/modules/auth';
import { handleRouter } from '@/utils/util';
import { loadingSvg } from '@/utils/svg';
import Logo from './components/Logo.vue';
import SubItem from './components/SubItem.vue';
import { routes } from '@/routers/router';
import Logo from './components/logo.vue';
import SubItem from './components/sub-item.vue';
import { menuList } from '@/routers/router';
const route = useRoute();
const menuStore = MenuStore();
const authStore = AuthStore();
onMounted(async () => {
//
menuStore.setMenuList(routes);
const dynamicRouter = handleRouter(routes);
authStore.setAuthRouter(dynamicRouter);
menuStore.setMenuList(menuList);
});
const activeMenu = computed((): string => route.path);
// const activeMenu = computed((): string => route.path);
const activeMenu = computed(() => {
const { meta, path } = route;
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
});
const isCollapse = computed((): boolean => menuStore.isCollapse);
const routerMenus = computed((): RouteRecordRaw[] => menuStore.menuList);
// aside
const screenWidth = ref<number>(0);
// aside
const listeningWindow = () => {
window.onresize = () => {
return (() => {

View file

@ -1,7 +1,8 @@
<template>
<el-icon class="back-button" @click="jump">
<!-- <el-icon class="back-button" @click="jump">
<Back />
</el-icon>
</el-icon> -->
<el-page-header :content="header" @back="jump" />
</template>
<script setup lang="ts">
@ -11,6 +12,7 @@ const props = defineProps({
path: String,
name: String,
to: Object,
header: String,
});
function jump() {
const { path, name, to } = props;
@ -27,13 +29,13 @@ function jump() {
</script>
<style lang="scss">
.back-button {
cursor: pointer;
margin-right: 10px;
font-weight: 600;
// .back-button {
// cursor: pointer;
// margin-right: 10px;
// font-weight: 600;
&:active {
transform: scale(0.85);
}
}
// &:active {
// transform: scale(0.85);
// }
// }
</style>

View file

@ -2,5 +2,3 @@
// * 首页地址(默认)
export const HOME_URL: string = '/home/index';
// * 高德地图key
export const MAP_KEY: string = '';

View file

@ -0,0 +1,23 @@
import i18n from '@/lang';
import { FormItemRule } from 'element-plus';
interface CommonRule {
required: FormItemRule;
name: FormItemRule;
}
export const Rules: CommonRule = {
required: {
required: true,
message: i18n.global.t('commons.rule.required'),
trigger: 'blur',
},
name: {
type: 'regexp',
min: 1,
max: 30,
message: i18n.global.t('commons.rule.commonName'),
trigger: 'blur',
pattern: '/^[a-zA-Z0-9\u4e00-\u9fa5]{1}[a-zA-Z0-9_.\u4e00-\u9fa5-]{0,30}$/',
},
};

View file

@ -28,6 +28,14 @@ export default {
rule: {
username: 'Please enter a username',
password: 'Please enter a password',
required: 'Please enter the required fields',
commonName: 'Support English, Chinese, numbers, .-_, length 1-30',
},
},
business: {
user: {
username: 'Username',
email: 'Email',
},
},
menu: {

View file

@ -28,6 +28,14 @@ export default {
rule: {
username: '请输入用户名',
password: '请输入密码',
required: '请填写必填项',
commonName: '支持英文、中文、数字、.-_,长度1-30',
},
},
business: {
user: {
username: '用户名',
email: '邮箱',
},
},
menu: {

View file

@ -2,13 +2,25 @@
<div class="main-box">
<div class="content-container__header" v-if="slots.header || header">
<slot name="header">
<back-button :path="backPath" :name="backName" :to="backTo" v-if="showBack"></back-button>
{{ header }}
<back-button
:path="backPath"
:name="backName"
:to="backTo"
:header="header"
v-if="showBack"
></back-button>
<!-- {{ header }} -->
</slot>
</div>
<div class="content-container__toolbar" v-if="slots.toolbar">
<slot name="toolbar"></slot>
</div>
<div class="content-container_form">
<slot name="form"> </slot>
<div class="form-button">
<slot name="button"></slot>
</div>
</div>
<slot></slot>
</div>
</template>
@ -44,4 +56,13 @@ const showBack = computed(() => {
@include flex-row(space-between, center);
margin-bottom: 10px;
}
.content-container_form {
text-align: -webkit-center;
width: 80%;
margin-left: 10%;
.form-button {
float: right;
}
}
</style>

View file

@ -1,9 +1,7 @@
import router from '@/routers/router';
import NProgress from '@/config/nprogress';
import { HOME_URL } from '@/config/config';
import { GlobalStore } from '@/store';
import { AxiosCanceler } from '@/api/helper/axios-cancel';
import { AuthStore } from '@/store/modules/auth';
const axiosCanceler = new AxiosCanceler();
@ -12,13 +10,10 @@ const axiosCanceler = new AxiosCanceler();
* */
router.beforeEach((to, from, next) => {
NProgress.start();
// * 在跳转路由之前,清除所有的请求
axiosCanceler.removeAllPending();
// * 判断当前路由是否需要访问权限
if (!to.matched.some((record) => record.meta.requiresAuth)) return next();
// * 判断是否有Token
const globalStore = GlobalStore();
if (!globalStore.isLogin) {
next({
@ -27,19 +22,7 @@ router.beforeEach((to, from, next) => {
NProgress.done();
return;
}
const authStore = AuthStore();
// * Dynamic Router(动态路由,根据后端返回的菜单数据生成的一维数组)
const dynamicRouter = authStore.dynamicRouter;
// * Static Router(静态路由,必须配置首页地址,否则不能进首页获取菜单、按钮权限等数据)获取数据的时候会loading所有配置首页地址也没问题
const staticRouter = [HOME_URL, '/error/403'];
const routerList = dynamicRouter.concat(staticRouter);
// * 如果访问的地址没有在路由表中重定向到403页面
if (routerList.indexOf(to.path) !== -1) return next();
next({
path: '/error/403',
});
return next();
});
router.afterEach(() => {

View file

@ -7,17 +7,27 @@ const demoRouter = {
component: Layout,
redirect: '/demos/table',
meta: {
icon: 'apple',
title: 'menu.demo',
},
children: [
{
path: '/demos/table',
name: 'table',
name: 'Table',
component: () => import('@/views/demos/table/index.vue'),
meta: {
keepAlive: true,
requiresAuth: true,
key: 'table',
},
},
{
path: '/demos/table/:op',
name: 'DemoCreate',
props: true,
hidden: true,
component: () => import('@/views/demos/table/operate/index.vue'),
meta: {
activeMenu: '/demos/table',
keepAlive: true,
},
},
],

View file

@ -8,7 +8,8 @@ const errorRouter = {
{
path: '403',
name: '403',
component: () => import('@/components/ErrorMessage/403.vue'),
hidden: true,
component: () => import('@/components/error-message/403.vue'),
meta: {
requiresAuth: true,
title: '403页面',
@ -18,7 +19,8 @@ const errorRouter = {
{
path: '404',
name: '404',
component: () => import('@/components/ErrorMessage/404.vue'),
hidden: true,
component: () => import('@/components/error-message/404.vue'),
meta: {
requiresAuth: false,
title: '404页面',
@ -28,7 +30,8 @@ const errorRouter = {
{
path: '500',
name: '500',
component: () => import('@/components/ErrorMessage/500.vue'),
hidden: true,
component: () => import('@/components/error-message/500.vue'),
meta: {
requiresAuth: false,
title: '500页面',

View file

@ -3,6 +3,24 @@ import { Layout } from '@/routers/constant';
const modules = import.meta.globEager('./modules/*.ts');
const homeRouter: RouteRecordRaw = {
path: '/',
component: Layout,
redirect: '/home/index',
meta: {
keepAlive: true,
title: 'menu.home',
icon: 'home-filled',
},
children: [
{
path: '/home/index',
name: 'home',
component: () => import('@/views/home/index.vue'),
},
],
};
export const routerArray: RouteRecordRaw[] = [];
export const rolesRoutes = [
@ -19,30 +37,23 @@ rolesRoutes.forEach((item) => {
const menu = item as RouteRecordRaw;
routerArray.push(menu);
});
export const menuList: RouteRecordRaw[] = [];
rolesRoutes.forEach((item) => {
let menuItem = JSON.parse(JSON.stringify(item));
let menuChildren: RouteRecordRaw[] = [];
menuItem.children.forEach((child: any) => {
if (child.hidden == null || child.hidden == false) {
menuChildren.push(child);
}
});
menuItem.children = menuChildren as RouteRecordRaw[];
menuList.push(menuItem);
});
menuList.unshift(homeRouter);
export const routes: RouteRecordRaw[] = [
// {
// path: '/',
// redirect: { name: 'login' },
// },
{
path: '/',
component: Layout,
redirect: '/home/index',
meta: {
keepAlive: true,
requiresAuth: true,
title: 'menu.home',
key: 'home',
icon: 'home-filled',
},
children: [
{
path: '/home/index',
name: 'home',
component: () => import('@/views/home/index.vue'),
},
],
},
homeRouter,
{
path: '/login',
name: 'login',
@ -63,7 +74,6 @@ const router = createRouter({
history: createWebHashHistory(),
routes: routes as RouteRecordRaw[],
strict: false,
// 切换页面,滚动到最顶部
scrollBehavior: () => ({ left: 0, top: 0 }),
});

View file

@ -2,7 +2,7 @@
<LayoutContent :header="'样例'">
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
<template #toolbar>
<el-button type="primary">{{ $t('commons.button.create') }}</el-button>
<el-button type="primary" @click="openOperate({})">{{ $t('commons.button.create') }}</el-button>
<el-button type="primary" plain>{{ '其他操作' }}</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="batchDelete">{{
$t('commons.button.delete')
@ -35,6 +35,9 @@ import { User } from '@/api/interface/user';
import { deleteUser, getUserList } from '@/api/modules/user';
import { onMounted, reactive, ref } from '@vue/runtime-core';
import { useDeleteData } from '@/hooks/use-delete-data';
import i18n from '@/lang';
import { useRouter } from 'vue-router';
const router = useRouter();
const data = ref();
const selects = ref<any>([]);
const paginationConfig = reactive({
@ -48,7 +51,7 @@ const userSearch = reactive({
});
const buttons = [
{
label: '编辑',
label: i18n.global.t('commons.button.edit'),
click: edit,
},
// {
@ -79,10 +82,30 @@ function edit(row: User.User) {
console.log(row);
}
// interface OperateOpen {
// acceptParams: (params: any) => void;
// }
// const operateRef = ref<OperateOpen>();
const openOperate = (row: User.User) => {
console.log(row);
// let title = 'commons.button.create';
// if (row != null) {
// title = 'commons.button.edit';
// }
// let params = {
// titke: title,
// row: row,
// };
// operateRef.value!.acceptParams(params);
router.push({ name: 'DemoCreate', params: { op: 'create' } });
// router.push({ name: 'operate', params: { operate: 'create' } });
};
const batchDelete = async () => {
let ids: Array<number> = [];
selects.value.forEach((item: User.User) => {
ids.push(item.ID);
ids.push(item.id);
});
await useDeleteData(deleteUser, { ids: ids }, 'commons.msg.delete');
};

View file

@ -1,4 +1,44 @@
<template>
<div></div>
<LayoutContent :header="$t('commons.button.' + op)" :back-name="'Table'">
<template #form>
<el-form ref="ruleFormRef" label-position="left" :model="demoForm" :rules="rules" label-width="140px">
<el-form-item :label="$t('business.user.username')" prop="username">
<el-input v-model="demoForm.username" />
</el-form-item>
<el-form-item :label="$t('business.user.email')" prop="email">
<el-input v-model="demoForm.email" />
</el-form-item>
</el-form>
<div style="float: right">
<el-button>{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary">{{ $t('commons.button.create') }}</el-button>
</div>
</template>
</LayoutContent>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { User } from '@/api/interface/user';
import LayoutContent from '@/layout/layout-content.vue';
import { FormInstance, FormRules } from 'element-plus';
import { reactive, ref } from 'vue';
import { Rules } from '@/global/form-rues';
const ruleFormRef = ref<FormInstance>();
interface OperateProps {
op: string;
id?: number;
}
withDefaults(defineProps<OperateProps>(), {
op: 'create',
});
const demoForm = reactive<User.User>({
id: 0,
username: '',
email: '',
});
const rules = reactive<FormRules>({
username: [Rules.required, Rules.name],
email: [Rules.required],
});
</script>