已完成“组织与权限”优化:
基础数据拆分为:组织机构、学年学期、教学场所。 人员档案拆分为:教师档案、学生档案。 基础数据、教师、学生、用户权限均支持 Excel 模板下载、批量导入和导出。 导入按编码/工号/学号/账号新增或更新;整批校验,失败不写入,限制 2000 条、10 MB。 用户列表新增密码重置,包含双重确认、最低 8 位校验和服务端权限保护。 导入严格执行角色及学院数据范围校验,并保护当前超级管理员账号。 保留旧地址重定向,原有入口不会失效。
This commit is contained in:
1 parent
662aa1051f
commit
022e79c48d
13 files changed
+2133
-59
No files matched your search
@@ -0,0 +1,38 @@
|
||||
import type { AxiosRequestConfig } from 'axios'
|
||||
import http from './http'
|
||||
|
||||
function responseFileName(header: string | undefined, fallback: string) {
|
||||
if (!header) return fallback
|
||||
const encoded = header.match(/filename\*=UTF-8''([^;]+)/i)?.[1]
|
||||
if (encoded) return decodeURIComponent(encoded)
|
||||
const plain = header.match(/filename="?([^";]+)"?/i)?.[1]
|
||||
return plain || fallback
|
||||
}
|
||||
|
||||
export async function downloadApiFile(
|
||||
path: string,
|
||||
fallbackName: string,
|
||||
config?: AxiosRequestConfig,
|
||||
) {
|
||||
const response = await http.get(path, {
|
||||
...config,
|
||||
responseType: 'blob',
|
||||
})
|
||||
const url = URL.createObjectURL(response.data)
|
||||
const anchor = document.createElement('a')
|
||||
anchor.href = url
|
||||
anchor.download = responseFileName(response.headers['content-disposition'], fallbackName)
|
||||
document.body.appendChild(anchor)
|
||||
anchor.click()
|
||||
anchor.remove()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
export async function importExcel(path: string, file: File) {
|
||||
const form = new FormData()
|
||||
form.append('file', file)
|
||||
return http.post(path, form, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
timeout: 60000,
|
||||
})
|
||||
}
|
||||
@@ -49,11 +49,23 @@ const navigationGroups = computed<NavigationGroup[]>(() => [
|
||||
items: [
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin']),
|
||||
{ path: '/base-data', label: '基础数据' },
|
||||
{ path: '/base-data/organization', label: '组织机构' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin']),
|
||||
{ path: '/base-data/terms', label: '学年学期' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin']),
|
||||
{ path: '/base-data/facilities', label: '教学场所' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor']),
|
||||
{ path: '/personnel', label: '人员档案' },
|
||||
{ path: '/teachers', label: '教师档案' },
|
||||
),
|
||||
...whenVisible(
|
||||
hasAnyRole(['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor']),
|
||||
{ path: '/students', label: '学生档案' },
|
||||
),
|
||||
...whenVisible(auth.isSuperAdmin, { path: '/users', label: '用户与权限' }),
|
||||
],
|
||||
|
||||
+42
-3
@@ -23,16 +23,55 @@ const router = createRouter({
|
||||
},
|
||||
{
|
||||
path: 'base-data',
|
||||
name: 'base-data',
|
||||
redirect: '/base-data/organization',
|
||||
},
|
||||
{
|
||||
path: 'base-data/organization',
|
||||
name: 'organization-data',
|
||||
component: () => import('../views/BaseDataView.vue'),
|
||||
meta: { roles: ['SuperAdmin', 'AcademicAdmin'] },
|
||||
meta: {
|
||||
roles: ['SuperAdmin', 'AcademicAdmin'],
|
||||
baseGroup: 'organization',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'base-data/terms',
|
||||
name: 'term-data',
|
||||
component: () => import('../views/BaseDataView.vue'),
|
||||
meta: {
|
||||
roles: ['SuperAdmin', 'AcademicAdmin'],
|
||||
baseGroup: 'terms',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'base-data/facilities',
|
||||
name: 'facility-data',
|
||||
component: () => import('../views/BaseDataView.vue'),
|
||||
meta: {
|
||||
roles: ['SuperAdmin', 'AcademicAdmin'],
|
||||
baseGroup: 'facilities',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'personnel',
|
||||
name: 'personnel',
|
||||
redirect: '/teachers',
|
||||
},
|
||||
{
|
||||
path: 'teachers',
|
||||
name: 'teachers',
|
||||
component: () => import('../views/PersonnelView.vue'),
|
||||
meta: {
|
||||
roles: ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor'],
|
||||
registry: 'teachers',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'students',
|
||||
name: 'students',
|
||||
component: () => import('../views/PersonnelView.vue'),
|
||||
meta: {
|
||||
roles: ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin', 'Counselor'],
|
||||
registry: 'students',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Loaded 3 of 13 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user