diff --git a/.env.development b/.env.development index ab8609f..f8eaae4 100644 --- a/.env.development +++ b/.env.development @@ -8,3 +8,7 @@ VITE_PUBLIC_PATH = / VITE_ROUTER_HISTORY = "hash" VITE_API_BASEURL = "http://192.168.2.33:5199/api" +# 接口地址 +# VITE_API_BASEURL = "http://localhost:5199/api" +#数据中心后台地址 +VITE_API_USERCENTER_URL = "https://dca.w.23544.com:8843/api" diff --git a/.env.production b/.env.production index 84e6086..ca7f985 100644 --- a/.env.production +++ b/.env.production @@ -10,4 +10,10 @@ VITE_CDN = false # 是否启用gzip压缩或brotli压缩(分两种情况,删除原始文件和不删除原始文件) # 压缩时不删除原始文件的配置:gzip、brotli、both(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认) # 压缩时删除原始文件的配置:gzip-clear、brotli-clear、both-clear(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认) -VITE_COMPRESSION = "none" \ No newline at end of file +VITE_COMPRESSION = "none" + + +# 接口地址 +VITE_API_BASEURL = "http://localhost:5199/api" +#数据中心后台地址 +VITE_API_USERCENTER_URL = "https://dcb.23544.com/api" \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100644 index 5ee2d16..0000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -# shellcheck source=./_/husky.sh -. "$(dirname "$0")/_/husky.sh" - -PATH="/usr/local/bin:$PATH" - -npx --no-install commitlint --edit "$1" \ No newline at end of file diff --git a/.husky/common.sh b/.husky/common.sh deleted file mode 100644 index 5f0540b..0000000 --- a/.husky/common.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -command_exists () { - command -v "$1" >/dev/null 2>&1 -} - -# Workaround for Windows 10, Git Bash and Pnpm -if command_exists winpty && test -t 1; then - exec < /dev/tty -fi diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100644 index 6e229ea..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" -. "$(dirname "$0")/common.sh" - -[ -n "$CI" ] && exit 0 - -PATH="/usr/local/bin:$PATH" - -# Perform lint check on files in the staging area through .lintstagedrc configuration -pnpm exec lint-staged \ No newline at end of file diff --git a/src/api/enum.ts b/src/api/enum.ts index 21e3c72..055735b 100644 --- a/src/api/enum.ts +++ b/src/api/enum.ts @@ -7,7 +7,7 @@ import type { Res } from "@/utils/http/types"; * @return {object} */ export function getenum(type) { - return http.request>("get", `public/enum/${type}`); + return http.request>("get", `Public/enum/${type}`); } /** * @description 获取枚举对象 @@ -15,5 +15,5 @@ export function getenum(type) { * @return {object} */ export function getenumDic(type) { - return http.request>("get", `public/enum/${type}/Dic`); + return http.request>("get", `Public/enum/${type}/Dic`); } diff --git a/src/api/exam.ts b/src/api/exam.ts new file mode 100644 index 0000000..10250c0 --- /dev/null +++ b/src/api/exam.ts @@ -0,0 +1,24 @@ +import { http } from "@/utils/http"; +// import type { Res } from "@/utils/http/types"; + +/** + * @description 导入表单 + * @return {object} + */ +export function ImportExamInfo(id: number, file: File) { + let formData = new FormData(); + formData.append("eId", id.toString()); + formData.append("file", file); + return http.request( + "post", + `ExamClassInfo/Import`, + { + data: formData + }, + { + headers: { + "Content-Type": "application/x-www-form-urlencoded" + } + } + ); +} diff --git a/src/api/hTable.ts b/src/api/hTable.ts index 038394e..e29d581 100644 --- a/src/api/hTable.ts +++ b/src/api/hTable.ts @@ -11,13 +11,9 @@ export class hTableAPI { PageList(data = {}) { return http.request>("post", `${this.url}/PageList`, { data }); } - Info(tag = {}) { - const pUrl = `${this.url}/Info`; + Info(tag) { + const pUrl = `${this.url}/${tag}`; let getUrl = pUrl; - for (const key in tag) { - const el = tag[key]; - getUrl += (getUrl === pUrl ? "?" : "&") + key + "=" + el; - } return http.request>("get", getUrl); } edit(data) { @@ -32,3 +28,4 @@ export class hTableAPI { }); } } + diff --git a/src/api/menu.ts b/src/api/menu.ts index e6db80f..17ba631 100644 --- a/src/api/menu.ts +++ b/src/api/menu.ts @@ -30,3 +30,10 @@ export function MenuAll() { export function Edit(info: MenuItem) { return http.request>("post", `Menu/Edit`, { data: info }); } +/** + * @description 获取所有的菜单 + * @return {object} + */ +export function Del(ids: number[]) { + return http.request>("post", `Menu/Del`, { data: ids }); +} diff --git a/src/api/school.ts b/src/api/school.ts index 4891252..8f8e2b6 100644 --- a/src/api/school.ts +++ b/src/api/school.ts @@ -28,10 +28,3 @@ export function getregion(r) { return http.request>("get", `address/${r}/region`); } -/** - * @description 编辑学校 - * @return {void} - */ -export function EditSchool(data: any) { - return http.request>("post", `School/Edit`, { data }); -} diff --git a/src/api/userCenter.ts b/src/api/userCenter.ts new file mode 100644 index 0000000..d9abc2e --- /dev/null +++ b/src/api/userCenter.ts @@ -0,0 +1,186 @@ +import { ComboModel } from "@/components/hTable/hTable"; +import { http } from "@/utils/http"; +import type { Res, ResPage } from "@/utils/http/types"; +/** + * @description 获取枚举下拉 + * @param {string} type 枚举类型 type=StatusEnum + * @return {object} + */ +export function getPageUserList(data: any) { + return http.request>( + "post", + `userCenter/back/users/getpageuserlist`, + { + data + } + ); +} +/** + * @description 编辑学校 + * @return {void} + */ +export function EditSchool(data: any) { + return http.request>("post", `userCenter/back/schools/add`, { + data + }); +} +/** + * @description 获取学校 + * @return {void} + */ +export function getSchoolData() { + return http.request>( + "get", + `userCenter/public/getschooldata` + ); +} +/** + * @description 获取职位列表 + * @return {void} + */ +export function getPositionList(data: any) { + return http.request>( + "post", + `userCenter/back/positions/getpositionlist`, + { data } + ); +} +/** + * @description 云校下拉框数据 + * @return {object} + */ +export function cloudSchoolCombo() { + let data = { + ValueName: "Id", + TextName: "Name" + }; + return http.request>( + "post", + `userCenter/back/cloudschool/querycombo`, + { + data + } + ); +} +/** + * @description 获取用户信息 + * @return {object} + */ +export function getUserInfo(id) { + return http.request>( + "get", + `userCenter/back/users/getuserinfo?id=${id}` + ); +} + +/** + * @description 添加班级 + * @return {object} + */ +export function addClasses(info: any) { + return http.request>("post", `userCenter/back/classes/addclass`, { + data: info + }); +} + +/** + * @description 添加班级 + * @return {object} + */ +export function editUser(data: any) { + return http.request>("post", `userCenter/back/users/edituser`, { + data + }); +} + +/** + * @description 添加班级 + * @return {object} + */ +export function getClassCombo(info: any) { + return http.request>("post", `userCenter/public/getclasscombo`, { + data: info + }); +} + +/** + * @description 获取科目 + * @return {object} + */ +export function getSubjectData() { + return http.request>("get", `userCenter/public/getsubjectdata`); +} +/** + * @description 获取职位列表 + * @return {object} + */ +export function getPositions(data) { + return http.request>("post", `userCenter/back/positions/positions`, { + data + }); +} + +//--------------------------interface---------------------------- + +/** + * 职位信息 + */ +export interface Position { + userId: number; + id: number; + name: string; + schoolId: number; + enable: boolean; + endTime: string | null; + schoolName: string; + graduationYear: number; + grade: string; + classId: number; + className: string; + subjectId: number; + subjectName: string; + positionType: number; + positionLevel: number; + status: boolean; +} + +/** + * 用户详细信息 + */ +export interface UserDetail { + id: number; + templateId: number; + phone: string; + edited: boolean; + userType: number; + cloudSchoolId: number; + account: string; + studentId: string; + realName: string; + sex: number; + subjectLevel: any; + birthDate: string; + residence: string; + national: string; + headImage: string; + idCard: string | null; + pid: number; + pname: string; + cid: number; + cname: string; + rid: number; + rname: string; + wx: string; + isPerfectInfo: number; + level: number; + state: number; + meetingAccount: string | null; + gkSubject: string | null; + glSubject: string | null; + gSubject1: string | null; + gSubject2: string | null; + thirdPartyId: string | null; + pointPenSN: string | null; + subjectLevels: null; + positions: Position[]; +} diff --git a/src/components/hTable/hTable.ts b/src/components/hTable/hTable.ts index 45fb491..f000c78 100644 --- a/src/components/hTable/hTable.ts +++ b/src/components/hTable/hTable.ts @@ -1,68 +1,98 @@ export interface Dialog { - /* 对话框是否可见 */ + /** 对话框是否可见 */ visible: boolean; - /* 是否显示关闭按钮 */ + /** 是否显示关闭按钮 */ close: boolean; - /* 对话框标题 */ + /** 对话框标题 */ title: string; - /* 对话框宽度 */ + /** 对话框宽度 */ width: string; /**自定义弹窗数据 */ custom: { - /* 自定义对话框高度 */ + /** 自定义对话框高度 */ height: string; - /* 自定义对话框数据 */ + /** 自定义对话框数据 */ data: any[]; - /* 自定义组件路径 */ + /** 自定义组件路径 */ src?: string; - /* 自定义配置项 */ + /** 自定义配置项 */ custom: Record; - /* 自定义对话框是否可见 */ + /** 自定义对话框是否可见 */ visible: boolean; - /* 异步加载组件 */ + /** 异步加载组件 */ component: any; }; edit: { - /* 编辑项ID */ + /** 编辑项ID */ id: number; - /* 编辑对话框标题 */ + /** 编辑对话框标题 */ title: string; - /* 编辑对话框是否可见 */ + /** 编辑对话框是否可见 */ visible: boolean; row?: any; tagData?: any; }; } -/* 按钮自定义配置 */ +/** 按钮自定义配置 */ export interface ButtonCustomConfig { - /* 弹出框标题 */ + /** 弹出框标题 */ title: string; - /* 组件路径 */ + /** 组件路径 */ src: string; - /* 弹框宽度 */ + /** 弹框宽度 */ width: string; - /* 弹框高度 */ + /** 弹框高度 */ height: string; } -/* 操作按钮配置 */ +/** 操作按钮配置 */ export interface OperationButton { - /* 是否为头部按钮 */ + /** 是否为头部按钮 */ topBtn: boolean; - /* 是否显示 */ + /** 按钮权限码 */ + perms?: string; + /** 是否显示 */ show?: boolean; - /* 按钮文本 */ + /** 按钮文本 */ label: string; - /* 按钮类型 */ - btnType: "add" | "edit" | "del" | "custom"; - /* 按钮样式 */ - btnStyle?: "success" | "danger"; - /* 自定义按钮配置 */ + /** 按钮点击事件 + * @tips btnType 为空时触发 + * @param obj 当前按钮配置对象 + * @param row 当前行数据 + * @param handleReloadPaged 父表单刷新函数 + */ + click?: (obj, row, handleReloadPaged: (reload: boolean) => void) => void; + /** 按钮类型 */ + btnType?: "add" | "edit" | "del" | "custom"; + /** 按钮样式 */ + btnStyle?: "success" | "info" | "primary" | "danger" | "warning"; + /** 自定义按钮配置 */ custom?: ButtonCustomConfig; } -/* 字段设置项 */ +/** 类型判断枚举 */ +export enum ConditionalType { + Equal, + Like, + GreaterThan, + GreaterThanOrEqual, + LessThan, + LessThanOrEqual, + In, + NotIn, + LikeLeft, + LikeRight, + NoEqual, + IsNullOrEmpty, + IsNot, + NoLike, + EqualNull, + InLike, + Range +} + +/** 字段设置项 */ export interface FieldSetting { /**map 时Value的取值的属性 */ mapValue?: string; @@ -77,49 +107,44 @@ export interface FieldSetting { * @returns 预期返回有效图片地址url */ imgUrl?: (value: any, row: any) => string; - /* 数据源 */ + /** 数据源 */ datasource?: ComboModel[]; } -///* 表格列配置 */ +///** 表格列配置 */ //export interface TableEditColumn {} export interface ComboModel { - Value: any; - Text: string; + value: any; + text: string; } -/* 表格列配置 */ +/** 表格列配置 */ export interface TableColumn { - /* 显示标签 */ + /** 显示标签 */ label: string; - /* 是否可搜索 */ + /** 是否可搜索 */ search: boolean; - /* 搜索类型 */ - searchType?: - | "Equal" - | "NoEqual" - | "Like" - | "GreaterThan" - | "LessThan" - | "NoLike"; - /* 是否允许添加 */ - add: boolean; - /* 是否允许修改 */ + /** 搜索类型 */ + searchType?: ConditionalType; + /** 是否允许添加 [false]*/ + add?: boolean; + /** 是否允许修改 [false]*/ edit?: boolean; - /* 列宽度 */ + /** 列宽度 [auto]*/ width?: string; - /* 字段类型 */ - type?: string; + /** 字段类型 */ + type?: "string" | "dropdown" | "switch" | "img" | "datetime" | "textarea"; /** 是否多选 */ multiple?: boolean; /** 编辑时显示列 */ editShow?: boolean; + /**校验规则 */ rules?: any | Array; /** 显示列 */ show?: boolean; - /* 字段设置 */ + /** 字段设置 */ setting?: FieldSetting; - /* 修改时的编辑值 */ + /** 修改时的编辑值 */ valueE?: Array | string | number | boolean | Date; - /* 查询值 */ + /** 查询值 */ value?: Array | string | number | boolean | Date; /** textarea编辑时的行数 */ editRows?: number; @@ -129,55 +154,67 @@ export interface TableColumn { custom?: (row: any) => string; } -/* 分页数据 */ +/** 分页数据 */ export interface PageData { - /* 总条数 */ + /** 总条数 */ total: number; } -/* 搜索条件 */ +/** 分页数据 */ +export interface ConditionalModel { + /** 字段名称 */ + FieldName: string; + /** 字段查询值 */ + FieldValue: string; + /** 查询方式 */ + ConditionalType?: ConditionalType; + /** C#类型名称 */ + CSharpTypeName?: string; +} + +/** 搜索条件 */ export interface SearchConditions { - /* 是否显示搜索 */ + /** 是否显示搜索 */ show: boolean; - /* 当前页码 */ + /** 当前页码 */ PageIndex: number; - /* 每页大小 */ + /** 每页大小 */ PageSize: number; - /* 排序字段 */ + /** 排序字段 */ OrderBy: string; - /* 默认查询条件 */ - defaultConditions: any[]; - /* 查询条件 */ + /** 默认查询条件 */ + defaultConditions: ConditionalModel[]; + /** 查询条件 */ Conditions: any[]; } -/* 表格配置 */ +/** 表格配置 */ export interface TableConfig { - /* 搜索回调函数 */ + /** 搜索回调函数 */ searchCallback?: (s: SearchConditions) => void; - /* 新增/修改回调函数 */ + /** 新增/修改回调函数 */ editCallback?: (from: any) => void; - /* API地址 */ + /** API地址 */ apiUrl: string; - /* 是否显示选择列 */ + /** 是否显示选择列 */ selectColumn: boolean; - /* 搜索配置 */ + /** 搜索配置 */ search: SearchConditions; - /* 是否显示操作列 */ + /** 是否显示操作列 */ operationColumn: boolean; - /* 操作按钮配置 */ + /** 操作按钮配置 */ operationColumnData: OperationButton[]; - /* 列配置 */ + /** 列配置 */ column: Record; - /* 表格数据 */ + /** 表格数据 */ data: any[]; /**显示头部操作按钮 */ operationTop?: boolean; - /* 分页数据 */ + /** 分页数据 */ pageData: PageData; - /* 选中行 */ + /** 选中行 */ selectRows: any[]; - /* 是否显示边框 */ + /** 是否显示边框 */ border: boolean; /**是否显示 */ show?: boolean; diff --git a/src/components/hTable/hTableEdit.vue b/src/components/hTable/hTableEdit.vue index 8da9a3a..19dce09 100644 --- a/src/components/hTable/hTableEdit.vue +++ b/src/components/hTable/hTableEdit.vue @@ -75,10 +75,10 @@ function handleSubmitForm() { } editData.value.loading = true; - let form = {}; + let form: any = {}; if (editData.value.isedit) { form = props.row; - } + } else form.id = 0; for (const key in column.value) { const element = column.value[key]; if (element.valueE !== null && element.valueE !== "") { @@ -116,9 +116,9 @@ function handleResetForm() { function fetchInitData() {} function fetchFormData() { editData.value.loading = false; - handleResetForm(); if (editData.value.isedit) { - Api.Info({ id: props.id }).then(res => { + handleResetForm(); + Api.Info(props.id).then(res => { if (res.code === 200) { editData.value.frorm = res.data; for (const key in column.value) { @@ -154,11 +154,11 @@ function fetchFormData() {
@@ -169,12 +169,12 @@ function fetchFormData() { clearable filterable :placeholder="o.label" - style="width: 100%" + class="elWidth" @change="o.change" >
- +
@@ -215,3 +221,9 @@ function fetchFormData() { + diff --git a/src/components/hTable/index.vue b/src/components/hTable/index.vue index 9ad6ee4..b95d652 100644 --- a/src/components/hTable/index.vue +++ b/src/components/hTable/index.vue @@ -16,7 +16,7 @@ import { import { Search } from "@element-plus/icons-vue"; import { ElMessage, ElMessageBox } from "element-plus"; import { defineAsyncComponent, AsyncComponentLoader } from "vue"; -import { Dialog, TableColumn, TableConfig } from "./hTable"; +import { ConditionalType, Dialog, TableColumn, TableConfig } from "./hTable"; import hTableEdit from "./hTableEdit.vue"; import { hTableAPI } from "@/api/hTable"; import { getenum } from "@/api/enum"; @@ -108,7 +108,8 @@ function intdata() { // 处理 column 的属性 for (const key in table.value.column) { const element = table.value.column[key]; - + if (element.add === undefined) element.add = false; + if (element.edit === undefined) element.edit = false; // Vue 3 中直接赋值即可,不需要 $set if (element.valueE === undefined) element.valueE = element.multiple ? [] : ""; @@ -274,17 +275,19 @@ function handleReloadPaged(reload = true) { let data: any = { ConditionalType: 0 }; if (table.value.column[name].type === "datetime") { // data.CSharpTypeName = 'DateTime' - data.ConditionalType = 8; // '2023-10-07%' + data.ConditionalType = ConditionalType.LikeLeft; // '2023-10-07%' } else if (table.value.column[name].type === "switch") { data.CSharpTypeName = "Boolean"; } else if (table.value.column[name].type === "string") { - data.ConditionalType = "Like"; - } + data.ConditionalType = ConditionalType.Like; + } else data.ConditionalType = ConditionalType.Equal; + data.FieldName = name.charAt(0).toUpperCase() + name.slice(1); data.FieldValue = table.value.column[name].value.toString(); if (table.value.column[name].searchType != undefined) { - data.ConditionalType = table.value.column[name].searchType || 0; + let v: number = table.value.column[name].searchType || 0; + data.ConditionalType = v; } table.value.search.Conditions.push(data); } @@ -559,7 +562,14 @@ function fetchPagedData() { -
+
{ getTopMenu(true); // query、params模式路由传参数的标签页不在此处处理 if (route && route.meta?.title) { - if (isAllEmpty(route.parentId) && route.meta?.backstage) { + if ( + isAllEmpty(route.parentId) && + route.meta?.backstage && + route.children + ) { // 此处为动态顶级路由(目录) const { path, name, meta } = route.children[0]; useMultiTagsStoreHook().handleTags("push", { diff --git a/src/router/modules/home.ts b/src/router/modules/home.ts index ff03d20..1cc1a4f 100644 --- a/src/router/modules/home.ts +++ b/src/router/modules/home.ts @@ -20,15 +20,6 @@ export default { title: "首页", showLink: VITE_HIDE_HOME === "true" ? false : true } - }, - { - path: "/school", - name: "school", - component: () => import("@/views/school/index.vue"), - meta: { - title: "学校", - showLink: true - } } ] } satisfies RouteConfigsTable; diff --git a/src/utils/auth.ts b/src/utils/auth.ts index c6d54c5..eb306ab 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -84,8 +84,7 @@ export function setToken(data: DataInfo) { permissions }); } - - if (data.userName && data.roles) { + if (data.userName && data.permissions) { const { userName, roles } = data; setUserKey({ avatar: data?.avatar ?? "", @@ -129,7 +128,7 @@ export const formatToken = (token: string): string => { /** 是否有按钮级别的权限(根据登录接口返回的`permissions`字段进行判断)*/ export const hasPerms = (value: string | Array): boolean => { - if (!value) return false; + if (!value) return true; const allPerms = "*:*:*"; const { permissions } = useUserStoreHook(); if (!permissions) return false; diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index bfd306b..31c201a 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -13,6 +13,62 @@ import { stringify } from "qs"; import NProgress from "../progress"; import { getToken, formatToken } from "@/utils/auth"; import { useUserStoreHook } from "@/store/modules/user"; +// import { string } from "vue-types"; +import router from "@/router"; + +/**请求后端的地址 未配置则访问BaseURL */ +const apiServiceConfig = { + userCenter: import.meta.env.VITE_API_USERCENTER_URL, + usercenter: import.meta.env.VITE_API_USERCENTER_URL +}; + +function setAPIUrl(c: PureHttpRequestConfig): void { + let url = c.url; + let token = url.startsWith("/") ? url.split("/")[1] : url.split("/")[0]; + if (apiServiceConfig[token] != null) { + c.url = url.replaceAll(token, ""); + c.baseURL = apiServiceConfig[token]; + } else c.baseURL = import.meta.env.VITE_API_BASEURL; +} + +const snakeToCamel = (str: string): string => { + // 处理蛇形命名(user_id → userId) + let result = str.replace(/_([a-zA-Z0-9])/g, (_, letter) => + letter.toUpperCase() + ); + + // 处理大驼峰命名(UserName → userName) + if (result.length > 0) { + result = result.charAt(0).toLowerCase() + result.slice(1); + } + + // 特殊场景:处理连续下划线(__type → Type) + result = result.replace(/^_+/, ""); + + return result; +}; + +/** + * 递归转换对象/数组的键名为小驼峰格式 + */ +const convertKeysToCamelCase = (data: any): T => { + if (Array.isArray(data)) { + return data.map(item => convertKeysToCamelCase(item)) as unknown as T; + } + + if (data !== null && typeof data === "object") { + return Object.keys(data).reduce((result, key) => { + const camelKey = snakeToCamel(key); + const value = data[key]; + return { + ...result, + [camelKey]: convertKeysToCamelCase(value) + }; + }, {}) as T; + } + + return data as T; +}; // 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1 const defaultConfig: AxiosRequestConfig = { @@ -64,6 +120,9 @@ class PureHttp { async (config: PureHttpRequestConfig): Promise => { // 开启进度条动画 NProgress.start(); + if (config.url.indexOf("http") === -1) { + setAPIUrl(config); + } // 优先判断post/get等方法是否传入回调,否则执行初始化设置等回调 if (typeof config.beforeRequestCallback === "function") { config.beforeRequestCallback(config); @@ -124,6 +183,7 @@ class PureHttp { const $config = response.config; // 关闭进度条动画 NProgress.done(); + response.data = convertKeysToCamelCase(response.data); // 优先判断post/get等方法是否传入回调,否则执行初始化设置等回调 if (typeof $config.beforeResponseCallback === "function") { $config.beforeResponseCallback(response); @@ -140,6 +200,12 @@ class PureHttp { $error.isCancelRequest = Axios.isCancel($error); // 关闭进度条动画 NProgress.done(); + if (error.response?.status === 403) { + // 跳转到403页面 + router.push({ + path: "/error/403" + }); + } // 所有的响应异常 区分来源为取消请求/非取消请求 return Promise.reject($error); } diff --git a/src/utils/http/types.d.ts b/src/utils/http/types.d.ts index f7870e8..7eb9427 100644 --- a/src/utils/http/types.d.ts +++ b/src/utils/http/types.d.ts @@ -18,6 +18,14 @@ export interface PureHttpError extends AxiosError { isCancelRequest?: boolean; } +export type ResPage = { + code: number; + data: { + data: T; + total: number; + }; + message: string; +}; export type Res = { code: number; data: T; diff --git a/src/utils/rules.ts b/src/utils/rules.ts new file mode 100644 index 0000000..3f6f515 --- /dev/null +++ b/src/utils/rules.ts @@ -0,0 +1,28 @@ +export const ruleRequired = [ + { required: true, message: "不能为空", trigger: "blur" } +]; +export const ruleRequiredNumber = [ + { required: true, message: "不能为空", trigger: "blur" }, + { + pattern: /^\d*\.?\d+$/, + message: "请输入正确数字", + trigger: "blur" + } +]; +export const rulePassword = [ + { required: true, message: "不能为空", trigger: "blur" }, + { min: 6, message: "长度必须大于5", trigger: "blur" } +]; +export const ruleAccount = [ + { required: true, message: "不能为空", trigger: "blur" }, + { min: 13, message: "长度必须大于12", trigger: "blur" } +]; + +export const rulePhone = [ + { required: true, message: "手机号不能为空", trigger: "blur" }, + { + pattern: /^1[3-9]\d{9}$/, + message: "请输入正确的手机号", + trigger: "blur" + } +]; diff --git a/src/views/admin/index.vue b/src/views/admin/index.vue index db4fa4f..feebb3d 100644 --- a/src/views/admin/index.vue +++ b/src/views/admin/index.vue @@ -1,9 +1,15 @@ + + diff --git a/src/views/class/edit.vue b/src/views/class/edit.vue new file mode 100644 index 0000000..8da2f5f --- /dev/null +++ b/src/views/class/edit.vue @@ -0,0 +1,347 @@ + + + + + diff --git a/src/views/class/index.vue b/src/views/class/index.vue new file mode 100644 index 0000000..6adb60e --- /dev/null +++ b/src/views/class/index.vue @@ -0,0 +1,190 @@ + + + diff --git a/src/views/exam/classDetails.vue b/src/views/exam/classDetails.vue new file mode 100644 index 0000000..1e300cc --- /dev/null +++ b/src/views/exam/classDetails.vue @@ -0,0 +1,143 @@ + + + diff --git a/src/views/exam/index.vue b/src/views/exam/index.vue new file mode 100644 index 0000000..5cd7edd --- /dev/null +++ b/src/views/exam/index.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/exam/userDetails.vue b/src/views/exam/userDetails.vue new file mode 100644 index 0000000..2e0fd78 --- /dev/null +++ b/src/views/exam/userDetails.vue @@ -0,0 +1,147 @@ + + + diff --git a/src/views/grade/index.vue b/src/views/grade/index.vue new file mode 100644 index 0000000..d6a6ec0 --- /dev/null +++ b/src/views/grade/index.vue @@ -0,0 +1,136 @@ + + + diff --git a/src/views/menu/index.vue b/src/views/menu/index.vue index 91a83c7..265f1c6 100644 --- a/src/views/menu/index.vue +++ b/src/views/menu/index.vue @@ -17,26 +17,47 @@ class="menu-tree" > @@ -57,7 +78,7 @@ - - diff --git a/src/views/permission/button/perms.vue b/src/views/permission/button/perms.vue deleted file mode 100644 index 8fce6da..0000000 --- a/src/views/permission/button/perms.vue +++ /dev/null @@ -1,109 +0,0 @@ - - - diff --git a/src/views/permission/page/index.vue b/src/views/permission/page/index.vue deleted file mode 100644 index d65d03f..0000000 --- a/src/views/permission/page/index.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - diff --git a/src/views/school/SchoolEdit.vue b/src/views/school/SchoolEdit.vue index a37f44d..5e48c40 100644 --- a/src/views/school/SchoolEdit.vue +++ b/src/views/school/SchoolEdit.vue @@ -90,8 +90,6 @@
- 创建学校会生成一个默认管理员账号 -

@@ -107,7 +105,8 @@
+ + diff --git a/src/views/student/index.vue b/src/views/student/index.vue new file mode 100644 index 0000000..eb8322f --- /dev/null +++ b/src/views/student/index.vue @@ -0,0 +1,855 @@ + + + + + diff --git a/src/views/teacher/edit.vue b/src/views/teacher/edit.vue new file mode 100644 index 0000000..924716f --- /dev/null +++ b/src/views/teacher/edit.vue @@ -0,0 +1,555 @@ + + + + diff --git a/src/views/teacher/index.vue b/src/views/teacher/index.vue new file mode 100644 index 0000000..9f81387 --- /dev/null +++ b/src/views/teacher/index.vue @@ -0,0 +1,859 @@ + + + + + diff --git a/src/views/teacher/positionForm.vue b/src/views/teacher/positionForm.vue new file mode 100644 index 0000000..bf01612 --- /dev/null +++ b/src/views/teacher/positionForm.vue @@ -0,0 +1,522 @@ + + + + +