diff --git a/SchoolApiDoc.md b/SchoolApiDoc.md new file mode 100644 index 0000000..612dbfc --- /dev/null +++ b/SchoolApiDoc.md @@ -0,0 +1,380 @@ +# 院校模块(School)后台接口文档 + +> 适用范围:后台管理(CRUD / 导入导出 / 聚合详情)。 +> +> 代码位置:`jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/school/controller/*` + +## 1. 基础约定(JEECG-Boot) + +### 1.1 基础地址 + +- 默认 `server.servlet.context-path` 为 `/jeecg-boot` +- 文档中接口地址以:`/jeecg-boot` + Controller 的 `@RequestMapping` 为准 + +示例: + +- `GET /jeecg-boot/school/school/list` + +### 1.2 认证 + +- 需要登录后调用(通常前端会在请求头携带 token) +- 权限控制使用 `@RequiresPermissions`(文档中会标注权限码) + +### 1.3 统一返回结构 + +接口统一返回:`org.jeecg.common.api.vo.Result`。 + +成功示例: + +```json +{ + "success": true, + "message": "", + "code": 200, + "result": {}, + "timestamp": 1700000000000 +} +``` + +失败示例: + +```json +{ + "success": false, + "message": "未找到对应数据", + "code": 500, + "result": null, + "timestamp": 1700000000000 +} +``` + +### 1.4 分页返回结构(MyBatis-Plus IPage) + +分页接口 `result` 为 `IPage`,常见字段示例: + +```json +{ + "success": true, + "code": 200, + "result": { + "records": [], + "total": 0, + "size": 10, + "current": 1, + "pages": 0 + } +} +``` + +### 1.5 导入 / 导出 + +- 导出:`GET /exportXls`,返回 Excel 文件流 +- 导入:`POST /importExcel`,`multipart/form-data`,上传字段名通常为 `file` + +## 2. 数据表与字段说明(摘要) + +> 下面仅列出接口当前代码中实体字段;若你按 `Task2_solution.md` 扩展了更多列,可继续在实体中补字段以支持后台维护。 + +### 2.1 学校主表(t_school) + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | Long | 主键ID | +| mainCode | String | 学校编码(唯一) | +| mainName | String | 学校主名称(官方全称) | +| shortName | String | 学校简称 | +| schoolIcon | String | 院校图标(URL) | +| createBy/createTime | String/Date | 创建人/创建时间 | +| updateBy/updateTime | String/Date | 更新人/更新时间 | + +### 2.2 学校详情(t_school_detail) + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | Long | 主键ID | +| schoolId | Long | 学校ID | +| introduction | String | 学校简介(大文本) | +| address | String | 地址 | +| contact | String | 联系电话 | +| website | String | 官网 | +| updateTime | Date | 更新时间 | + +### 2.3 学校名称(t_school_name) + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | Long | 主键ID | +| schoolId | Long | 学校ID | +| name | String | 名称(别名/曾用名/英文名) | +| nameType | Integer | 名称类型:1官方全称/2曾用名/3别名/4英文名称 | + +### 2.4 学校标签(t_school_tag) + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | Long | 主键ID | +| schoolId | Long | 学校ID | +| tagName | String | 标签名(985/211/双一流/…) | + +### 2.5 学院 / 专业(Task2 扩展表) + +- 学院:`t_school_college` +- 专业:`t_school_major` +- 专业标签:`t_school_major_tag` + +### 2.6 校区 / 宿舍 / 媒体 / 招生计划(Task2 扩展表) + +- 校区:`t_school_campus` +- 宿舍:`t_school_dorm` +- 媒体:`t_school_media`(biz_type + biz_id) +- 招生计划:`t_school_enroll_plan` + +## 3. 接口清单 + +> 说明:所有 `/list` 接口均支持 `pageNo` / `pageSize` 分页。 +> +> 对于使用 `QueryGenerator` 的 `/list`:可通过 query 参数传实体字段实现筛选(例如 `schoolId=1`、`majorName=计算机`)。 + +### 3.1 学校主表(SchoolController) + +Base:`/jeecg-boot/school/school` + +#### 3.1.1 分页列表(通用查询) + +- Method: `GET` +- Path: `/list` +- 权限:无(如需权限可自行加 `@RequiresPermissions`) +- Query: + - `pageNo`:默认 1 + - `pageSize`:默认 10 + - 其他:`t_school` 对应字段(例如 `mainName`、`mainCode` 等) + +#### 3.1.2 关键词搜索(编码/名称/简称/别名) + +- Method: `GET` +- Path: `/search` +- 权限:无 +- Query: + - `keyword`:可空 + - `pageNo`、`pageSize` + +#### 3.1.3 新增 + +- Method: `POST` +- Path: `/add` +- 权限:`school:school:add` +- Body(JSON): + +```json +{ + "mainCode": "10001", + "mainName": "示例大学", + "shortName": "示大", + "schoolIcon": "https://example.com/icon.png" +} +``` + +#### 3.1.4 修改 + +- Method: `PUT` or `POST` +- Path: `/edit` +- 权限:`school:school:edit` +- Body(JSON):必须包含 `id` + +#### 3.1.5 删除 + +- Method: `DELETE` +- Path: `/delete` +- 权限:`school:school:delete` +- Query:`id` + +#### 3.1.6 批量删除 + +- Method: `DELETE` +- Path: `/deleteBatch` +- 权限:`school:school:deleteBatch` +- Query:`ids`(逗号分隔 Long,例如:`1,2,3`) + +#### 3.1.7 按ID查询 + +- Method: `GET` +- Path: `/queryById` +- Query:`id` + +#### 3.1.8 全量聚合详情(按ID) + +- Method: `GET` +- Path: `/fullById` +- Query:`id` +- 返回:`SchoolFullVO`(主表 + detail + names + tags + colleges/majors/...) + +#### 3.1.9 全量聚合详情(按mainCode) + +- Method: `GET` +- Path: `/fullByMainCode` +- Query:`mainCode` + +#### 3.1.10 导出 + +- Method: `GET` +- Path: `/exportXls` +- 权限:`school:school:exportXls` +- Query:可带筛选条件(同 `/list`) + +#### 3.1.11 导入 + +- Method: `POST` +- Path: `/importExcel` +- 权限:`school:school:importExcel` +- Form-Data:`file=@xxx.xlsx` + +--- + +### 3.2 学校详情(SchoolDetailController) + +Base:`/jeecg-boot/school/detail` + +- `GET /list`(QueryGenerator) +- `POST /add`(权限:`school:detail:add`) +- `PUT|POST /edit`(权限:`school:detail:edit`) +- `DELETE /delete`(权限:`school:detail:delete`) +- `DELETE /deleteBatch`(权限:`school:detail:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:detail:exportXls`) +- `POST /importExcel`(权限:`school:detail:importExcel`) + +--- + +### 3.3 学校名称(SchoolNameController) + +Base:`/jeecg-boot/school/name` + +- `GET /list` +- `POST /add`(权限:`school:name:add`) +- `PUT|POST /edit`(权限:`school:name:edit`) +- `DELETE /delete`(权限:`school:name:delete`) +- `DELETE /deleteBatch`(权限:`school:name:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:name:exportXls`) +- `POST /importExcel`(权限:`school:name:importExcel`) + +--- + +### 3.4 学校标签(SchoolTagController) + +Base:`/jeecg-boot/school/tag` + +- `GET /list` +- `POST /add`(权限:`school:tag:add`) +- `PUT|POST /edit`(权限:`school:tag:edit`) +- `DELETE /delete`(权限:`school:tag:delete`) +- `DELETE /deleteBatch`(权限:`school:tag:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:tag:exportXls`) +- `POST /importExcel`(权限:`school:tag:importExcel`) + +--- + +### 3.5 学院(SchoolCollegeController) + +Base:`/jeecg-boot/school/college` + +- `GET /list` +- `POST /add`(权限:`school:college:add`) +- `PUT|POST /edit`(权限:`school:college:edit`) +- `DELETE /delete`(权限:`school:college:delete`) +- `DELETE /deleteBatch`(权限:`school:college:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:college:exportXls`) +- `POST /importExcel`(权限:`school:college:importExcel`) + +--- + +### 3.6 专业(SchoolMajorController) + +Base:`/jeecg-boot/school/major` + +- `GET /list` +- `POST /add`(权限:`school:major:add`) +- `PUT|POST /edit`(权限:`school:major:edit`) +- `DELETE /delete`(权限:`school:major:delete`) +- `DELETE /deleteBatch`(权限:`school:major:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:major:exportXls`) +- `POST /importExcel`(权限:`school:major:importExcel`) + +--- + +### 3.7 专业标签(SchoolMajorTagController) + +Base:`/jeecg-boot/school/majorTag` + +- `GET /list` +- `POST /add`(权限:`school:majorTag:add`) +- `PUT|POST /edit`(权限:`school:majorTag:edit`) +- `DELETE /delete`(权限:`school:majorTag:delete`) +- `DELETE /deleteBatch`(权限:`school:majorTag:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:majorTag:exportXls`) +- `POST /importExcel`(权限:`school:majorTag:importExcel`) + +--- + +### 3.8 校区(SchoolCampusController) + +Base:`/jeecg-boot/school/campus` + +- `GET /list` +- `POST /add`(权限:`school:campus:add`) +- `PUT|POST /edit`(权限:`school:campus:edit`) +- `DELETE /delete`(权限:`school:campus:delete`) +- `DELETE /deleteBatch`(权限:`school:campus:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:campus:exportXls`) +- `POST /importExcel`(权限:`school:campus:importExcel`) + +--- + +### 3.9 宿舍(SchoolDormController) + +Base:`/jeecg-boot/school/dorm` + +- `GET /list` +- `POST /add`(权限:`school:dorm:add`) +- `PUT|POST /edit`(权限:`school:dorm:edit`) +- `DELETE /delete`(权限:`school:dorm:delete`) +- `DELETE /deleteBatch`(权限:`school:dorm:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:dorm:exportXls`) +- `POST /importExcel`(权限:`school:dorm:importExcel`) + +--- + +### 3.10 媒体(SchoolMediaController) + +Base:`/jeecg-boot/school/media` + +- `GET /list` +- `POST /add`(权限:`school:media:add`) +- `PUT|POST /edit`(权限:`school:media:edit`) +- `DELETE /delete`(权限:`school:media:delete`) +- `DELETE /deleteBatch`(权限:`school:media:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:media:exportXls`) +- `POST /importExcel`(权限:`school:media:importExcel`) + +--- + +### 3.11 招生计划(SchoolEnrollPlanController) + +Base:`/jeecg-boot/school/enrollPlan` + +- `GET /list` +- `POST /add`(权限:`school:enrollPlan:add`) +- `PUT|POST /edit`(权限:`school:enrollPlan:edit`) +- `DELETE /delete`(权限:`school:enrollPlan:delete`) +- `DELETE /deleteBatch`(权限:`school:enrollPlan:deleteBatch`) +- `GET /queryById` +- `GET /exportXls`(权限:`school:enrollPlan:exportXls`) +- `POST /importExcel`(权限:`school:enrollPlan:importExcel`) + diff --git a/src/views/school/campus/components/SchoolCampusModal.vue b/src/views/school/campus/components/SchoolCampusModal.vue index 876eed8..b36e8e3 100644 --- a/src/views/school/campus/components/SchoolCampusModal.vue +++ b/src/views/school/campus/components/SchoolCampusModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/college/components/SchoolCollegeModal.vue b/src/views/school/college/components/SchoolCollegeModal.vue index 3921dff..b8a43a2 100644 --- a/src/views/school/college/components/SchoolCollegeModal.vue +++ b/src/views/school/college/components/SchoolCollegeModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/detail/components/SchoolDetailModal.vue b/src/views/school/detail/components/SchoolDetailModal.vue index 00f5024..946018d 100644 --- a/src/views/school/detail/components/SchoolDetailModal.vue +++ b/src/views/school/detail/components/SchoolDetailModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,13 +29,19 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } + setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter, }); isUpdate.value = !!data?.isUpdate; - if (unref(isUpdate)) { + if (data?.record) { await setFieldsValue({ ...data.record }); } setProps({ disabled: !data?.showFooter }); @@ -65,4 +71,3 @@ width: 100%; } - diff --git a/src/views/school/dorm/components/SchoolDormModal.vue b/src/views/school/dorm/components/SchoolDormModal.vue index 195d0ae..c49039e 100644 --- a/src/views/school/dorm/components/SchoolDormModal.vue +++ b/src/views/school/dorm/components/SchoolDormModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/enrollPlan/components/SchoolEnrollPlanModal.vue b/src/views/school/enrollPlan/components/SchoolEnrollPlanModal.vue index 38e04d3..ad244dc 100644 --- a/src/views/school/enrollPlan/components/SchoolEnrollPlanModal.vue +++ b/src/views/school/enrollPlan/components/SchoolEnrollPlanModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/major/components/SchoolMajorModal.vue b/src/views/school/major/components/SchoolMajorModal.vue index bc30be9..a074600 100644 --- a/src/views/school/major/components/SchoolMajorModal.vue +++ b/src/views/school/major/components/SchoolMajorModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/majorTag/components/SchoolMajorTagModal.vue b/src/views/school/majorTag/components/SchoolMajorTagModal.vue index 041d782..ccbf355 100644 --- a/src/views/school/majorTag/components/SchoolMajorTagModal.vue +++ b/src/views/school/majorTag/components/SchoolMajorTagModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/media/components/SchoolMediaModal.vue b/src/views/school/media/components/SchoolMediaModal.vue index b5f66cf..2483122 100644 --- a/src/views/school/media/components/SchoolMediaModal.vue +++ b/src/views/school/media/components/SchoolMediaModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/name/components/SchoolNameModal.vue b/src/views/school/name/components/SchoolNameModal.vue index cf88aa8..7511408 100644 --- a/src/views/school/name/components/SchoolNameModal.vue +++ b/src/views/school/name/components/SchoolNameModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } - diff --git a/src/views/school/school/SchoolList.vue b/src/views/school/school/SchoolList.vue index b318ea1..fdb5223 100644 --- a/src/views/school/school/SchoolList.vue +++ b/src/views/school/school/SchoolList.vue @@ -28,6 +28,7 @@ + @@ -40,10 +41,53 @@ import { listOrSearch, deleteOne, batchDelete, getImportUrl, getExportUrl } from './School.api'; import SchoolModal from './components/SchoolModal.vue'; import SchoolFullDrawer from './components/SchoolFullDrawer.vue'; + import SchoolSubManagerDrawer from './components/SchoolSubManagerDrawer.vue'; + + import { columns as detailColumns, searchFormSchema as detailSearchSchemas } from '../detail/SchoolDetail.data'; + import { list as detailList, deleteOne as detailDeleteOne, batchDelete as detailBatchDelete } from '../detail/SchoolDetail.api'; + import SchoolDetailModal from '../detail/components/SchoolDetailModal.vue'; + + import { columns as nameColumns, searchFormSchema as nameSearchSchemas } from '../name/SchoolName.data'; + import { list as nameList, deleteOne as nameDeleteOne, batchDelete as nameBatchDelete } from '../name/SchoolName.api'; + import SchoolNameModal from '../name/components/SchoolNameModal.vue'; + + import { columns as tagColumns, searchFormSchema as tagSearchSchemas } from '../tag/SchoolTag.data'; + import { list as tagList, deleteOne as tagDeleteOne, batchDelete as tagBatchDelete } from '../tag/SchoolTag.api'; + import SchoolTagModal from '../tag/components/SchoolTagModal.vue'; + + import { columns as collegeColumns, searchFormSchema as collegeSearchSchemas } from '../college/SchoolCollege.data'; + import { list as collegeList, deleteOne as collegeDeleteOne, batchDelete as collegeBatchDelete } from '../college/SchoolCollege.api'; + import SchoolCollegeModal from '../college/components/SchoolCollegeModal.vue'; + + import { columns as majorColumns, searchFormSchema as majorSearchSchemas } from '../major/SchoolMajor.data'; + import { list as majorList, deleteOne as majorDeleteOne, batchDelete as majorBatchDelete } from '../major/SchoolMajor.api'; + import SchoolMajorModal from '../major/components/SchoolMajorModal.vue'; + + import { columns as majorTagColumns, searchFormSchema as majorTagSearchSchemas } from '../majorTag/SchoolMajorTag.data'; + import { list as majorTagList, deleteOne as majorTagDeleteOne, batchDelete as majorTagBatchDelete } from '../majorTag/SchoolMajorTag.api'; + import SchoolMajorTagModal from '../majorTag/components/SchoolMajorTagModal.vue'; + + import { columns as campusColumns, searchFormSchema as campusSearchSchemas } from '../campus/SchoolCampus.data'; + import { list as campusList, deleteOne as campusDeleteOne, batchDelete as campusBatchDelete } from '../campus/SchoolCampus.api'; + import SchoolCampusModal from '../campus/components/SchoolCampusModal.vue'; + + import { columns as dormColumns, searchFormSchema as dormSearchSchemas } from '../dorm/SchoolDorm.data'; + import { list as dormList, deleteOne as dormDeleteOne, batchDelete as dormBatchDelete } from '../dorm/SchoolDorm.api'; + import SchoolDormModal from '../dorm/components/SchoolDormModal.vue'; + + import { columns as mediaColumns, searchFormSchema as mediaSearchSchemas } from '../media/SchoolMedia.data'; + import { list as mediaList, deleteOne as mediaDeleteOne, batchDelete as mediaBatchDelete } from '../media/SchoolMedia.api'; + import SchoolMediaModal from '../media/components/SchoolMediaModal.vue'; + + import { columns as enrollColumns, searchFormSchema as enrollSearchSchemas } from '../enrollPlan/SchoolEnrollPlan.data'; + import { list as enrollList, deleteOne as enrollDeleteOne, batchDelete as enrollBatchDelete } from '../enrollPlan/SchoolEnrollPlan.api'; + import SchoolEnrollPlanModal from '../enrollPlan/components/SchoolEnrollPlanModal.vue'; const [registerModal, { openModal }] = useModal(); const [registerDrawer, { openDrawer }] = useDrawer(); + const [registerSubDrawer, { openDrawer: openSubDrawer }] = useDrawer(); + const { tableContext, onExportXls, onImportXls } = useListPage({ tableProps: { title: '学校主表', @@ -90,6 +134,10 @@ openDrawer(true, { record }); } + function openSubManager(title: string, config: Recordable, record: Recordable) { + openSubDrawer(true, Object.assign({ title, record }, config)); + } + async function handleDelete(record: Recordable) { await deleteOne({ id: record.id }, handleSuccess); } @@ -121,6 +169,178 @@ label: '全量详情', onClick: handleFullDetail.bind(null, record), }, + { + label: '学校详情管理', + onClick: () => + openSubManager( + '学校详情管理', + { + fixedMode: 'schoolId', + columns: detailColumns, + searchSchemas: detailSearchSchemas, + listApi: detailList, + deleteOne: detailDeleteOne, + batchDelete: detailBatchDelete, + modalComponent: SchoolDetailModal, + }, + record + ), + }, + { + label: '学校名称管理', + onClick: () => + openSubManager( + '学校名称管理', + { + fixedMode: 'schoolId', + columns: nameColumns, + searchSchemas: nameSearchSchemas, + listApi: nameList, + deleteOne: nameDeleteOne, + batchDelete: nameBatchDelete, + modalComponent: SchoolNameModal, + }, + record + ), + }, + { + label: '学校标签管理', + onClick: () => + openSubManager( + '学校标签管理', + { + fixedMode: 'schoolId', + columns: tagColumns, + searchSchemas: tagSearchSchemas, + listApi: tagList, + deleteOne: tagDeleteOne, + batchDelete: tagBatchDelete, + modalComponent: SchoolTagModal, + }, + record + ), + }, + { + label: '学院管理', + onClick: () => + openSubManager( + '学院管理', + { + fixedMode: 'schoolId', + columns: collegeColumns, + searchSchemas: collegeSearchSchemas, + listApi: collegeList, + deleteOne: collegeDeleteOne, + batchDelete: collegeBatchDelete, + modalComponent: SchoolCollegeModal, + }, + record + ), + }, + { + label: '专业管理', + onClick: () => + openSubManager( + '专业管理', + { + fixedMode: 'schoolId', + columns: majorColumns, + searchSchemas: majorSearchSchemas, + listApi: majorList, + deleteOne: majorDeleteOne, + batchDelete: majorBatchDelete, + modalComponent: SchoolMajorModal, + getExtraDropDownActions: (r) => [ + { + label: '专业标签管理', + onClick: () => + openSubDrawer(true, { + title: '专业标签管理', + majorId: r.id, + ownerName: r.majorName || r.majorCode || String(r.id), + fixedMode: 'majorId', + columns: majorTagColumns, + searchSchemas: majorTagSearchSchemas, + listApi: majorTagList, + deleteOne: majorTagDeleteOne, + batchDelete: majorTagBatchDelete, + modalComponent: SchoolMajorTagModal, + }), + }, + ], + }, + record + ), + }, + { + label: '校区管理', + onClick: () => + openSubManager( + '校区管理', + { + fixedMode: 'schoolId', + columns: campusColumns, + searchSchemas: campusSearchSchemas, + listApi: campusList, + deleteOne: campusDeleteOne, + batchDelete: campusBatchDelete, + modalComponent: SchoolCampusModal, + }, + record + ), + }, + { + label: '宿舍管理', + onClick: () => + openSubManager( + '宿舍管理', + { + fixedMode: 'schoolId', + columns: dormColumns, + searchSchemas: dormSearchSchemas, + listApi: dormList, + deleteOne: dormDeleteOne, + batchDelete: dormBatchDelete, + modalComponent: SchoolDormModal, + }, + record + ), + }, + { + label: '媒体管理', + onClick: () => + openSubManager( + '媒体管理', + { + fixedMode: 'bizSchool', + bizType: 'school', + columns: mediaColumns, + searchSchemas: mediaSearchSchemas, + listApi: mediaList, + deleteOne: mediaDeleteOne, + batchDelete: mediaBatchDelete, + modalComponent: SchoolMediaModal, + }, + record + ), + }, + { + label: '招生计划管理', + onClick: () => + openSubManager( + '招生计划管理', + { + fixedMode: 'schoolId', + columns: enrollColumns, + searchSchemas: enrollSearchSchemas, + listApi: enrollList, + deleteOne: enrollDeleteOne, + batchDelete: enrollBatchDelete, + modalComponent: SchoolEnrollPlanModal, + }, + record + ), + }, { label: '删除', popConfirm: { diff --git a/src/views/school/school/components/SchoolSubManagerDrawer.vue b/src/views/school/school/components/SchoolSubManagerDrawer.vue new file mode 100644 index 0000000..7782fe1 --- /dev/null +++ b/src/views/school/school/components/SchoolSubManagerDrawer.vue @@ -0,0 +1,246 @@ + + + diff --git a/src/views/school/tag/components/SchoolTagModal.vue b/src/views/school/tag/components/SchoolTagModal.vue index ebb7e88..ecc5e12 100644 --- a/src/views/school/tag/components/SchoolTagModal.vue +++ b/src/views/school/tag/components/SchoolTagModal.vue @@ -21,7 +21,7 @@ const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); - const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ + const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({ schemas: formSchema, showActionButtonGroup: false, baseColProps: { span: 24 }, @@ -29,6 +29,11 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { await resetFields(); + const disabledFields: string[] = data?.dynamicDisabledFields || []; + for (const schema of formSchema) { + const field = String(schema.field); + updateSchema({ field, dynamicDisabled: disabledFields.includes(field) }); + } setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, @@ -65,4 +70,3 @@ width: 100%; } -