refactor: 合并 biz_support_unit/biz_execution_unit/biz_service_org 为 biz_org, 删除 2 张孤儿表, 改 biz_person.work_unit → org_id FK

主要改动:
- SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org
- SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type
- SQL: biz_meeting.support_unit_name → org_name
- SQL: biz_person.work_unit → org_id (FK)
- 后端: 新 BizOrg entity/mapper/service/controller
- 后端: BizProject/BizMeeting 字段重命名
- 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件
- 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id)
- 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub)
- 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits)
- 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步)
- 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名
- 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商)
- 前端: 全工程 execution → executor (company type / role / person unit_type)
This commit is contained in:
郭庆泰
2026-08-15 12:41:10 +08:00
commit cf5790229a
694 changed files with 102090 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import PortalLayout from '@/layout/PortalLayout.vue'
import AdminLayout from '@/layout/AdminLayout.vue'
const routes = [
// 公开门户(无登录)
{ path: '/', component: PortalLayout, children: [
{ path: '', name: 'home', component: () => import('@/views/portal/Home.vue'), meta: { title: '首页' } },
{ path: 'publicity', name: 'publicity', component: () => import('@/views/portal/Publicity.vue'), meta: { title: '项目公示' } },
{ path: 'publicity/:projectId', name: 'publicity-detail', component: () => import('@/views/portal/PublicityDetail.vue'), meta: { title: '公示详情' } },
{ path: 'support-letter/:annId', name: 'support-letter', component: () => import('@/views/portal/SupportLetter.vue'), meta: { title: '支持函详情' } },
{ path: 'invitation/:annId', name: 'invitation', component: () => import('@/views/portal/Invitation.vue'), meta: { title: '邀请函详情' } },
{ path: 'register-expert', name: 'register-expert', component: () => import('@/views/auth/RegisterExpert.vue'), meta: { title: '专家注册' } },
{ path: 'register-executor', name: 'register-executor', component: () => import('@/views/auth/RegisterExecutor.vue'), meta: { title: '执行单位(供应商)注册' } },
{ path: 'register-sponsor', name: 'register-sponsor', component: () => import('@/views/auth/RegisterSponsor.vue'), meta: { title: '赞助方注册' } },
{ path: 'login', name: 'login', component: () => import('@/views/auth/Login.vue'), meta: { title: '登录' } }
]
},
// 各角色后台(登录后)
// 后台管理员
{ path: '/admin', component: AdminLayout, meta: { role: 'admin' }, children: [
{ path: '', redirect: { name: 'admin-workbench' } },
{ path: 'workbench', name: 'admin-workbench', component: () => import('@/views/admin/Workbench.vue'), meta: { title: '工作台' } },
{ path: 'users', name: 'admin-users', component: () => import('@/views/admin/Users.vue'), meta: { title: '用户管理' } },
{ path: 'roles', name: 'admin-roles', component: () => import('@/views/admin/Roles.vue'), meta: { title: '角色管理' } },
{ path: 'projects', name: 'admin-projects', component: () => import('@/views/admin/Projects.vue'), meta: { title: '项目全览' } },
{ path: 'meetings', name: 'admin-meetings', component: () => import('@/views/admin/Meetings.vue'), meta: { title: '会议全览' } },
{ path: 'department', name: 'admin-department', component: () => import('@/views/admin/Department.vue'), meta: { title: '科室管理' } },
{ path: 'title', name: 'admin-title', component: () => import('@/views/admin/Title.vue'), meta: { title: '职称管理' } },
{ path: 'experts', name: 'admin-experts', component: () => import('@/views/admin/Experts.vue'), meta: { title: '专家管理' } },
{ path: 'orgs', name: 'admin-orgs', component: () => import('@/views/admin/Orgs.vue'), meta: { title: '公司管理' } },
{ path: 'account', name: 'admin-account', component: () => import('@/views/admin/Account.vue'), meta: { title: '账号信息' } }
]
},
{ path: '/leader', component: AdminLayout, meta: { role: 'leader' }, children: [
{ path: '', redirect: { name: 'leader-home' } },
{ path: 'home', name: 'leader-home', component: () => import('@/views/leader/Home.vue'), meta: { title: '工作台' } },
{ path: 'projects', name: 'leader-projects', component: () => import('@/views/leader/Projects.vue'), meta: { title: '项目列表' } },
{ path: 'meetings', name: 'leader-meetings', component: () => import('@/views/leader/Meetings.vue'), meta: { title: '会议列表' } },
{ path: 'account', name: 'leader-account', component: () => import('@/views/leader/Account.vue'), meta: { title: '账号信息' } }
]
},
{ path: '/manager', component: AdminLayout, meta: { role: 'manager' }, children: [
{ path: '', redirect: { name: 'manager-workbench' } },
{ path: 'workbench', name: 'manager-workbench', component: () => import('@/views/manager/Workbench.vue'), meta: { title: '工作台' } },
{ path: 'plans', name: 'manager-plans', component: () => import('@/views/manager/Plans.vue'), meta: { title: '项目策划方案' } },
{ path: 'projects', name: 'manager-projects', component: () => import('@/views/manager/Projects.vue'), meta: { title: '项目管理' } },
{ path: 'projects/new', name: 'manager-projects-new', component: () => import('@/views/manager/ProjectsNew.vue'), meta: { title: '新建项目' } },
{ path: 'projects/edit/:projectId', name: 'manager-projects-edit', component: () => import('@/views/manager/ProjectsNew.vue'), meta: { title: '编辑项目' } },
{ path: 'projects/detail/:projectId', name: 'manager-projects-detail', component: () => import('@/views/manager/ManagerProjectDetail.vue'), meta: { title: '项目详情' } },
{ path: 'meetings', name: 'manager-meetings', component: () => import('@/views/manager/Meetings.vue'), meta: { title: '会议管理' } },
{ path: 'meetings/new', name: 'manager-meetings-new', component: () => import('@/views/manager/MeetingNew.vue'), meta: { title: '新建会议' } },
{ path: 'experts', name: 'manager-experts', component: () => import('@/views/manager/Experts.vue'), meta: { title: '专家审核' } },
{ path: 'orgs', name: 'manager-orgs', component: () => import('@/views/manager/Orgs.vue'), meta: { title: '公司管理' } },
{ path: 'support-intent', name: 'manager-support-intent', component: () => import('@/views/manager/SupportIntent.vue'), meta: { title: '支持意向' } },
{ path: 'exec-intent', name: 'manager-exec-intent', component: () => import('@/views/manager/ExecIntent.vue'), meta: { title: '执行意向' } },
{ path: 'accounts', name: 'manager-accounts', component: () => import('@/views/manager/Accounts.vue'), meta: { title: '账号管理' } }
]
},
{ path: '/doctor', component: AdminLayout, meta: { role: 'doctor' }, children: [
{ path: '', redirect: { name: 'doctor-home' } },
{ path: 'home', name: 'doctor-home', component: () => import('@/views/doctor/Home.vue'), meta: { title: '首页' } },
{ path: 'meetings', name: 'doctor-meetings', component: () => import('@/views/doctor/Meetings.vue'), meta: { title: '我参与的会议' } },
{ path: 'projects', name: 'doctor-projects', component: () => import('@/views/doctor/Projects.vue'), meta: { title: '我报名的项目' } },
{ path: 'messages', name: 'doctor-messages', component: () => import('@/views/doctor/Messages.vue'), meta: { title: '消息通知' } },
{ path: 'submissions', name: 'doctor-submissions', component: () => import('@/views/doctor/Submissions.vue'), meta: { title: '我的项目设计投稿' } },
{ path: 'submission/new', name: 'doctor-submission-new', component: () => import('@/views/doctor/SubmissionNew.vue'), meta: { title: '新建项目设计投稿' } },
{ path: 'submission/detail/:subId', name: 'doctor-submission-detail', component: () => import('@/views/doctor/SubmissionDetail.vue'), meta: { title: '投稿详情' } },
{ path: 'submission/edit/:subId', name: 'doctor-submission-edit', component: () => import('@/views/doctor/SubmissionNew.vue'), meta: { title: '修改项目设计投稿' } },
{ path: 'account', name: 'doctor-account', component: () => import('@/views/doctor/Account.vue'), meta: { title: '账号信息' } }
]
},
{ path: '/executor', component: AdminLayout, meta: { role: 'executor' }, children: [
{ path: '', redirect: { name: 'executor-overview' } },
{ path: 'overview', name: 'executor-overview', component: () => import('@/views/executor/Overview.vue'), meta: { title: '首页' } },
{ path: 'meetings', name: 'executor-meetings', component: () => import('@/views/executor/Meetings.vue'), meta: { title: '会议执行' } },
{ path: 'projects', name: 'executor-projects', component: () => import('@/views/executor/Projects.vue'), meta: { title: '项目列表' } },
{ path: 'people', name: 'executor-people', component: () => import('@/views/executor/People.vue'), meta: { title: '人员管理' } },
{ path: 'account', name: 'executor-account', component: () => import('@/views/executor/Account.vue'), meta: { title: '账号信息' } },
{ path: 'labor', name: 'executor-labor', component: () => import('@/views/executor/Labor.vue'), meta: { title: '劳务凭证' } }
]
},
{ path: '/sponsor', component: AdminLayout, meta: { role: 'sponsor' }, children: [
{ path: '', redirect: { name: 'sponsor-home' } },
{ path: 'home', name: 'sponsor-home', component: () => import('@/views/sponsor/Home.vue'), meta: { title: '首页' } },
{ path: 'projects', name: 'sponsor-projects', component: () => import('@/views/sponsor/Projects.vue'), meta: { title: '项目管理' } },
{ path: 'my-projects', name: 'sponsor-my-projects', component: () => import('@/views/sponsor/SponsorProjects.vue'), meta: { title: '我的项目' } },
{ path: 'meetings', name: 'sponsor-meetings', component: () => import('@/views/sponsor/Meetings.vue'), meta: { title: '会议列表' } },
{ path: 'people', name: 'sponsor-people', component: () => import('@/views/sponsor/SponsorPeople.vue'), meta: { title: '人员管理' } },
{ path: 'people/new', name: 'sponsor-people-new', component: () => import('@/views/sponsor/NewPerson.vue'), meta: { title: '新建人员' } },
{ path: 'people/edit/:id', name: 'sponsor-people-edit', component: () => import('@/views/sponsor/NewPerson.vue'), meta: { title: '编辑人员' } },
{ path: 'people/detail/:id', name: 'sponsor-people-detail', component: () => import('@/views/sponsor/PersonDetail.vue'), meta: { title: '人员详情' } },
{ path: 'account', name: 'sponsor-account', component: () => import('@/views/sponsor/Account.vue'), meta: { title: '账号信息' } }
]
},
{ path: '/:pathMatch(.*)*', redirect: '/' }
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
router.beforeEach((to, from, next) => {
document.title = (to.meta?.title || 'BAHIM') + ' - BAHIM 项目管理系统'
const role = to.meta?.role
// 公开门户 & 登录/注册 不拦截
if (!role) return next()
const user = JSON.parse(localStorage.getItem('ry_user') || 'null')
if (!user) return next({ name: 'login', query: { redirect: to.fullPath } })
if (user.role !== role) return next({ name: 'login' })
next()
})
export default router