Browse Source

代码生成:增加主子表 inner 模式的示例

YunaiV 1 năm trước cách đây
mục cha
commit
6c405ba420
24 tập tin đã thay đổi với 422 bổ sung2239 xóa
  1. 53 0
      src/api/infra/demo/demo03/inner/index.ts
  2. 0 57
      src/api/infra/demo11/index.ts
  3. 0 95
      src/api/infra/demo12/index.ts
  4. 56 58
      src/views/infra/demo/demo03/inner/Demo03StudentForm.vue
  5. 100 0
      src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue
  6. 51 0
      src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue
  7. 72 0
      src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue
  8. 55 0
      src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue
  9. 35 55
      src/views/infra/demo/demo03/inner/index.vue
  10. 0 58
      src/views/infra/demo04/DemoStudentAddressForm.vue
  11. 0 39
      src/views/infra/demo04/DemoStudentAddressList.vue
  12. 0 96
      src/views/infra/demo04/DemoStudentContactForm.vue
  13. 0 70
      src/views/infra/demo04/DemoStudentContactList.vue
  14. 0 132
      src/views/infra/demo04/DemoStudentForm.vue
  15. 0 184
      src/views/infra/demo04/index.vue
  16. 0 183
      src/views/infra/demo11/Demo11StudentForm.vue
  17. 0 174
      src/views/infra/demo11/components/Demo11StudentContactForm.vue
  18. 0 122
      src/views/infra/demo11/components/Demo11StudentTeacherForm.vue
  19. 0 183
      src/views/infra/demo12/Demo12StudentForm.vue
  20. 0 148
      src/views/infra/demo12/components/Demo12StudentContactList.vue
  21. 0 155
      src/views/infra/demo12/components/Demo12StudentTeacherForm.vue
  22. 0 148
      src/views/infra/demo12/components/Demo12StudentTeacherList.vue
  23. 0 278
      src/views/infra/demo12/index.vue
  24. 0 4
      src/views/infra/testDemo/index.vue

+ 53 - 0
src/api/infra/demo/demo03/inner/index.ts

@@ -0,0 +1,53 @@
+import request from '@/config/axios'
+
+export interface Demo03StudentVO {
+  id: number
+  name: string
+  sex: number
+  birthday: Date
+  description: string
+}
+
+// 查询学生分页
+export const getDemo03StudentPage = async (params) => {
+  return await request.get({ url: `/infra/demo03-student/page`, params })
+}
+
+// 查询学生详情
+export const getDemo03Student = async (id: number) => {
+  return await request.get({ url: `/infra/demo03-student/get?id=` + id })
+}
+
+// 新增学生
+export const createDemo03Student = async (data: Demo03StudentVO) => {
+  return await request.post({ url: `/infra/demo03-student/create`, data })
+}
+
+// 修改学生
+export const updateDemo03Student = async (data: Demo03StudentVO) => {
+  return await request.put({ url: `/infra/demo03-student/update`, data })
+}
+
+// 删除学生
+export const deleteDemo03Student = async (id: number) => {
+  return await request.delete({ url: `/infra/demo03-student/delete?id=` + id })
+}
+
+// 导出学生 Excel
+export const exportDemo03Student = async (params) => {
+  return await request.download({ url: `/infra/demo03-student/export-excel`, params })
+}
+
+// ==================== 子表(学生课程) ====================
+
+// 获得学生课程列表
+export const getDemo03CourseListByStudentId = async (studentId) => {
+  return await request.get({ url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId })
+}
+
+// ==================== 子表(学生班级) ====================
+
+// 获得学生班级
+export const getDemo03GradeByStudentId = async (studentId) => {
+  return await request.get({ url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId })
+}

+ 0 - 57
src/api/infra/demo11/index.ts

@@ -1,57 +0,0 @@
-import request from '@/config/axios'
-
-export interface Demo11StudentVO {
-  id: number
-  name: string
-  description: string
-  birthday: Date
-  sex: number
-  enabled: boolean
-  avatar: string
-  video: string
-  memo: string
-}
-
-// 查询学生列表
-export const getDemo11StudentPage = async (params) => {
-  return await request.get({ url: `/infra/demo11-student/page`, params })
-}
-
-// 查询学生详情
-export const getDemo11Student = async (id: number) => {
-  return await request.get({ url: `/infra/demo11-student/get?id=` + id })
-}
-
-// 新增学生
-export const createDemo11Student = async (data: Demo11StudentVO) => {
-  return await request.post({ url: `/infra/demo11-student/create`, data })
-}
-
-// 修改学生
-export const updateDemo11Student = async (data: Demo11StudentVO) => {
-  return await request.put({ url: `/infra/demo11-student/update`, data })
-}
-
-// 删除学生
-export const deleteDemo11Student = async (id: number) => {
-  return await request.delete({ url: `/infra/demo11-student/delete?id=` + id })
-}
-
-// 导出学生 Excel
-export const exportDemo11Student = async (params) => {
-  return await request.download({ url: `/infra/demo11-student/export-excel`, params })
-}
-
-// ==================== 子表(学生联系人) ====================
-
-// 获得学生联系人列表
-export const getDemo11StudentContactListByStudentId = async (studentId) => {
-  return await request.get({ url: `/infra/demo11-student/demo11-student/list-by-student-id?studentId=` + studentId })
-}
-
-// ==================== 子表(学生班主任) ====================
-
-// 获得学生班主任
-export const getDemo11StudentTeacherByStudentId = async (studentId) => {
-  return await request.get({ url: `/infra/demo11-student/demo11-student/get-by-student-id?studentId=` + studentId })
-}

+ 0 - 95
src/api/infra/demo12/index.ts

@@ -1,95 +0,0 @@
-import request from '@/config/axios'
-
-export interface Demo12StudentVO {
-  id: number
-  name: string
-  description: string
-  birthday: Date
-  sex: number
-  enabled: boolean
-  avatar: string
-  video: string
-  memo: string
-}
-
-// 查询学生列表
-export const getDemo12StudentPage = async (params) => {
-  return await request.get({ url: `/infra/demo12-student/page`, params })
-}
-
-// 查询学生详情
-export const getDemo12Student = async (id: number) => {
-  return await request.get({ url: `/infra/demo12-student/get?id=` + id })
-}
-
-// 新增学生
-export const createDemo12Student = async (data: Demo12StudentVO) => {
-  return await request.post({ url: `/infra/demo12-student/create`, data })
-}
-
-// 修改学生
-export const updateDemo12Student = async (data: Demo12StudentVO) => {
-  return await request.put({ url: `/infra/demo12-student/update`, data })
-}
-
-// 删除学生
-export const deleteDemo12Student = async (id: number) => {
-  return await request.delete({ url: `/infra/demo12-student/delete?id=` + id })
-}
-
-// 导出学生 Excel
-export const exportDemo12Student = async (params) => {
-  return await request.download({ url: `/infra/demo12-student/export-excel`, params })
-}
-
-// ==================== 子表(学生联系人) ====================
-
-// 获得学生联系人分页
-export const getDemo12StudentContactPage = async (params) => {
-  return await request.get({ url: `/infra/demo12-student/demo12-student-contact/page`, params })
-}
-// 新增学生联系人
-export const createDemo12StudentContact = async (data) => {
-  return await request.post({ url: `/infra/demo12-student/demo12-student-contact/create`, data })
-}
-
-// 修改学生联系人
-export const updateDemo12StudentContact = async (data) => {
-  return await request.put({ url: `/infra/demo12-student/demo12-student-contact/update`, data })
-}
-
-// 删除学生联系人
-export const deleteDemo12StudentContact = async (id: number) => {
-  return await request.delete({ url: `/infra/demo12-student/demo12-student-contact/delete?id=` + id })
-}
-
-// 获得学生联系人
-export const getDemo12StudentContact = async (id: number) => {
-  return await request.get({ url: `/infra/demo12-student/demo12-student-contact/get?id=` + id })
-}
-
-// ==================== 子表(学生班主任) ====================
-
-// 获得学生班主任分页
-export const getDemo12StudentTeacherPage = async (params) => {
-  return await request.get({ url: `/infra/demo12-student/demo12-student-teacher/page`, params })
-}
-// 新增学生班主任
-export const createDemo12StudentTeacher = async (data) => {
-  return await request.post({ url: `/infra/demo12-student/demo12-student-teacher/create`, data })
-}
-
-// 修改学生班主任
-export const updateDemo12StudentTeacher = async (data) => {
-  return await request.put({ url: `/infra/demo12-student/demo12-student-teacher/update`, data })
-}
-
-// 删除学生班主任
-export const deleteDemo12StudentTeacher = async (id: number) => {
-  return await request.delete({ url: `/infra/demo12-student/demo12-student-teacher/delete?id=` + id })
-}
-
-// 获得学生班主任
-export const getDemo12StudentTeacher = async (id: number) => {
-  return await request.get({ url: `/infra/demo12-student/demo12-student-teacher/get?id=` + id })
-}

+ 56 - 58
src/views/infra/demo12/components/Demo12StudentContactForm.vue → src/views/infra/demo/demo03/inner/Demo03StudentForm.vue

@@ -10,31 +10,10 @@
       <el-form-item label="名字" prop="name">
         <el-input v-model="formData.name" placeholder="请输入名字" />
       </el-form-item>
-      <el-form-item label="简介" prop="description">
-        <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
-      </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="formData.birthday"
-          type="date"
-          value-format="x"
-          placeholder="选择出生日期"
-        />
-      </el-form-item>
       <el-form-item label="性别" prop="sex">
-        <el-select v-model="formData.sex" placeholder="请选择性别">
-          <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-radio-group v-model="formData.enabled">
+        <el-radio-group v-model="formData.sex">
           <el-radio
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
             :key="dict.value"
             :label="dict.value"
           >
@@ -42,16 +21,27 @@
           </el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item label="头像" prop="avatar">
-        <UploadImg v-model="formData.avatar" />
-      </el-form-item>
-      <el-form-item label="附件" prop="video">
-        <UploadFile v-model="formData.video" />
+      <el-form-item label="出生日期" prop="birthday">
+        <el-date-picker
+          v-model="formData.birthday"
+          type="date"
+          value-format="x"
+          placeholder="选择出生日期"
+        />
       </el-form-item>
-      <el-form-item label="备注" prop="memo">
-        <Editor v-model="formData.memo" height="150px" />
+      <el-form-item label="简介" prop="description">
+        <Editor v-model="formData.description" height="150px" />
       </el-form-item>
     </el-form>
+    <!-- 子表的表单 -->
+    <el-tabs v-model="subTabsName">
+      <el-tab-pane label="学生课程" name="demo03Course">
+        <Demo03CourseForm ref="demo03CourseFormRef" :student-id="formData.id" />
+      </el-tab-pane>
+      <el-tab-pane label="学生班级" name="demo03Grade">
+        <Demo03GradeForm ref="demo03GradeFormRef" :student-id="formData.id" />
+      </el-tab-pane>
+    </el-tabs>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
@@ -59,8 +49,10 @@
   </Dialog>
 </template>
 <script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo12StudentApi from '@/api/infra/demo12'
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+import Demo03CourseForm from './components/Demo03CourseForm.vue'
+import Demo03GradeForm from './components/Demo03GradeForm.vue'
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -71,40 +63,35 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
   id: undefined,
-  studentId: undefined,
   name: undefined,
-  description: undefined,
-  birthday: undefined,
   sex: undefined,
-  enabled: undefined,
-  avatar: undefined,
-  video: undefined,
-  memo: undefined
+  birthday: undefined,
+  description: undefined
 })
 const formRules = reactive({
-  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
   name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
+  sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }],
   birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
+  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
 })
 const formRef = ref() // 表单 Ref
 
+/** 子表的表单 */
+const subTabsName = ref('demo03Course')
+const demo03CourseFormRef = ref()
+const demo03GradeFormRef = ref()
+
 /** 打开弹窗 */
-const open = async (type: string, id?: number, studentId: number) => {
+const open = async (type: string, id?: number) => {
   dialogVisible.value = true
   dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
-  formData.value.studentId = studentId
   // 修改时,设置数据
   if (id) {
     formLoading.value = true
     try {
-      formData.value = await Demo12StudentApi.getDemo12StudentContact(id)
+      formData.value = await Demo03StudentApi.getDemo03Student(id)
     } finally {
       formLoading.value = false
     }
@@ -117,15 +104,31 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成
 const submitForm = async () => {
   // 校验表单
   await formRef.value.validate()
+  // 校验子表单
+  try {
+    await demo03CourseFormRef.value.validate()
+  } catch (e) {
+    subTabsName.value = 'demo03Course'
+    return
+  }
+  try {
+    await demo03GradeFormRef.value.validate()
+  } catch (e) {
+    subTabsName.value = 'demo03Grade'
+    return
+  }
   // 提交请求
   formLoading.value = true
   try {
-    const data = formData.value
+    const data = formData.value as unknown as Demo03StudentApi.Demo03StudentVO
+    // 拼接子表的数据
+    data.demo03Courses = demo03CourseFormRef.value.getData()
+    data.demo03Grade = demo03GradeFormRef.value.getData()
     if (formType.value === 'create') {
-      await Demo12StudentApi.createDemo12StudentContact(data)
+      await Demo03StudentApi.createDemo03Student(data)
       message.success(t('common.createSuccess'))
     } else {
-      await Demo12StudentApi.updateDemo12StudentContact(data)
+      await Demo03StudentApi.updateDemo03Student(data)
       message.success(t('common.updateSuccess'))
     }
     dialogVisible.value = false
@@ -140,15 +143,10 @@ const submitForm = async () => {
 const resetForm = () => {
   formData.value = {
     id: undefined,
-    studentId: undefined,
     name: undefined,
-    description: undefined,
-    birthday: undefined,
     sex: undefined,
-    enabled: undefined,
-    avatar: undefined,
-    video: undefined,
-    memo: undefined
+    birthday: undefined,
+    description: undefined
   }
   formRef.value?.resetFields()
 }

+ 100 - 0
src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue

@@ -0,0 +1,100 @@
+<template>
+  <el-form
+    ref="formRef"
+    :model="formData"
+    :rules="formRules"
+    v-loading="formLoading"
+    label-width="0px"
+    :inline-message="true"
+  >
+    <el-table :data="formData" class="-mt-10px">
+      <el-table-column label="序号" type="index" width="100" />
+       <el-table-column label="名字" min-width="150">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
+            <el-input v-model="row.name" placeholder="请输入名字" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="分数" min-width="150">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.score`" :rules="formRules.score" class="mb-0px!">
+            <el-input v-model="row.score" placeholder="请输入分数" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" fixed="right" label="操作" width="60">
+        <template #default="{ $index }">
+          <el-button @click="handleDelete($index)" link>—</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-form>
+  <el-row justify="center" class="mt-3">
+    <el-button @click="handleAdd" round>+ 添加学生课程</el-button>
+  </el-row>
+</template>
+<script setup lang="ts">
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+
+const props = defineProps<{
+  studentId: undefined // 学生编号(主表的关联字段)
+}>()
+const formLoading = ref(false) // 表单的加载中
+const formData = ref([])
+const formRules = reactive({
+  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
+  score: [{ required: true, message: '分数不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 监听主表的关联字段的变化,加载对应的子表数据 */
+watch(
+  () => props.studentId,
+  async (val) => {
+    // 1. 重置表单
+    formData.value = []
+    // 2. val 非空,则加载数据
+    if (!val) {
+      return;
+    }
+    try {
+      formLoading.value = true
+      formData.value = await Demo03StudentApi.getDemo03CourseListByStudentId(val)
+    } finally {
+      formLoading.value = false
+    }
+  },
+  { immediate: true }
+)
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  const row = {
+    id: undefined,
+    studentId: undefined,
+    name: undefined,
+    score: undefined
+  }
+  row.studentId = props.studentId
+  formData.value.push(row)
+}
+
+/** 删除按钮操作 */
+const handleDelete = (index) => {
+  formData.value.splice(index, 1)
+}
+
+/** 表单校验 */
+const validate = () => {
+  return formRef.value.validate()
+}
+
+/** 表单值 */
+const getData = () => {
+  return formData.value
+}
+
+defineExpose({ validate, getData })
+</script>

+ 51 - 0
src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue

@@ -0,0 +1,51 @@
+<template>
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="名字" align="center" prop="name" />
+      <el-table-column label="分数" align="center" prop="score" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+    </el-table>
+  </ContentWrap>
+</template>
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const props = defineProps<{
+  studentId: undefined // 学生编号(主表的关联字段)
+}>()
+const loading = ref(false) // 列表的加载中
+const list = ref([]) // 列表的数据
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    list.value = await Demo03StudentApi.getDemo03CourseListByStudentId(props.studentId)
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 72 - 0
src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue

@@ -0,0 +1,72 @@
+<template>
+  <el-form
+    ref="formRef"
+    :model="formData"
+    :rules="formRules"
+    label-width="100px"
+    v-loading="formLoading"
+  >
+     <el-form-item label="名字" prop="name">
+      <el-input v-model="formData.name" placeholder="请输入名字" />
+    </el-form-item>
+    <el-form-item label="班主任" prop="teacher">
+      <el-input v-model="formData.teacher" placeholder="请输入班主任" />
+    </el-form-item>
+  </el-form>
+</template>
+<script setup lang="ts">
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+
+const props = defineProps<{
+  studentId: undefined // 学生编号(主表的关联字段)
+}>()
+const formLoading = ref(false) // 表单的加载中
+const formData = ref([])
+const formRules = reactive({
+  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
+  teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 监听主表的关联字段的变化,加载对应的子表数据 */
+watch(
+  () => props.studentId,
+  async (val) => {
+    // 1. 重置表单
+    formData.value = {
+      id: undefined,
+      studentId: undefined,
+      name: undefined,
+      teacher: undefined,
+    }
+    // 2. val 非空,则加载数据
+    if (!val) {
+      return;
+    }
+    try {
+      formLoading.value = true
+      const data = await Demo03StudentApi.getDemo03GradeByStudentId(val)
+      if (!data) {
+        return
+      }
+      formData.value = data
+    } finally {
+      formLoading.value = false
+    }
+  },
+  { immediate: true }
+)
+
+/** 表单校验 */
+const validate = () => {
+  return formRef.value.validate()
+}
+
+/** 表单值 */
+const getData = () => {
+  return formData.value
+}
+
+defineExpose({ validate, getData })
+</script>

+ 55 - 0
src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue

@@ -0,0 +1,55 @@
+<template>
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column label="名字" align="center" prop="name" />
+      <el-table-column label="班主任" align="center" prop="teacher" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+    </el-table>
+  </ContentWrap>
+</template>
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const props = defineProps<{
+  studentId: undefined // 学生编号(主表的关联字段)
+}>()
+const loading = ref(false) // 列表的加载中
+const list = ref([]) // 列表的数据
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await Demo03StudentApi.getDemo03GradeByStudentId(props.studentId)
+    if (!data) {
+      return
+    }
+    list.value.push(data)
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 35 - 55
src/views/infra/demo11/index.vue → src/views/infra/demo/demo03/inner/index.vue

@@ -17,16 +17,6 @@
           class="!w-240px"
         />
       </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="queryParams.birthday"
-          value-format="YYYY-MM-DD"
-          type="date"
-          placeholder="选择出生日期"
-          clearable
-          class="!w-240px"
-        />
-      </el-form-item>
       <el-form-item label="性别" prop="sex">
         <el-select
           v-model="queryParams.sex"
@@ -42,21 +32,6 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-select
-          v-model="queryParams.enabled"
-          placeholder="请选择是否有效"
-          clearable
-          class="!w-240px"
-        >
-          <el-option
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
       <el-form-item label="创建时间" prop="createTime">
         <el-date-picker
           v-model="queryParams.createTime"
@@ -75,7 +50,7 @@
           type="primary"
           plain
           @click="openForm('create')"
-          v-hasPermi="['infra:demo11-student:create']"
+          v-hasPermi="['infra:demo03-student:create']"
         >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
@@ -84,7 +59,7 @@
           plain
           @click="handleExport"
           :loading="exportLoading"
-          v-hasPermi="['infra:demo11-student:export']"
+          v-hasPermi="['infra:demo03-student:export']"
         >
           <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
@@ -95,9 +70,26 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <!-- 子表的列表 -->
+      <el-table-column type="expand">
+        <template #default="scope">
+          <el-tabs model-value="demo03Course">
+            <el-tab-pane label="学生课程" name="demo03Course">
+              <Demo03CourseList :student-id="scope.row.id" />
+            </el-tab-pane>
+            <el-tab-pane label="学生班级" name="demo03Grade">
+              <Demo03GradeList :student-id="scope.row.id" />
+            </el-tab-pane>
+          </el-tabs>
+        </template>
+      </el-table-column>
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="简介" align="center" prop="description" />
+      <el-table-column label="性别" align="center" prop="sex">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
+        </template>
+      </el-table-column>
       <el-table-column
         label="出生日期"
         align="center"
@@ -105,19 +97,7 @@
         :formatter="dateFormatter"
         width="180px"
       />
-      <el-table-column label="性别" align="center" prop="sex">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
-        </template>
-      </el-table-column>
-      <el-table-column label="是否有效" align="center" prop="enabled">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
-        </template>
-      </el-table-column>
-      <el-table-column label="头像" align="center" prop="avatar" />
-      <el-table-column label="附件" align="center" prop="video" />
-      <el-table-column label="备注" align="center" prop="memo" />
+      <el-table-column label="简介" align="center" prop="description" />
       <el-table-column
         label="创建时间"
         align="center"
@@ -131,7 +111,7 @@
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['infra:demo11-student:update']"
+            v-hasPermi="['infra:demo03-student:update']"
           >
             编辑
           </el-button>
@@ -139,7 +119,7 @@
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['infra:demo11-student:delete']"
+            v-hasPermi="['infra:demo03-student:delete']"
           >
             删除
           </el-button>
@@ -156,32 +136,32 @@
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <Demo11StudentForm ref="formRef" @success="getList" />
+  <Demo03StudentForm ref="formRef" @success="getList" />
 </template>
 
 <script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
 import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
-import * as Demo11StudentApi from '@/api/infra/demo11'
-import Demo11StudentForm from './Demo11StudentForm.vue'
+import * as Demo03StudentApi from '@/api/infra/demo/demo03/inner'
+import Demo03StudentForm from './Demo03StudentForm.vue'
+import Demo03CourseList from './components/Demo03CourseList.vue'
+import Demo03GradeList from './components/Demo03GradeList.vue'
 
-defineOptions({ name: 'InfraDemo11Student' })
+defineOptions({ name: 'Demo03Student' })
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
 const loading = ref(true) // 列表的加载中
-const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
+const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   name: null,
-  birthday: null,
-  birthday: [],
   sex: null,
-  enabled: null,
+  description: null,
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
@@ -191,7 +171,7 @@ const exportLoading = ref(false) // 导出的加载中
 const getList = async () => {
   loading.value = true
   try {
-    const data = await Demo11StudentApi.getDemo11StudentPage(queryParams)
+    const data = await Demo03StudentApi.getDemo03StudentPage(queryParams)
     list.value = data.list
     total.value = data.total
   } finally {
@@ -223,7 +203,7 @@ const handleDelete = async (id: number) => {
     // 删除的二次确认
     await message.delConfirm()
     // 发起删除
-    await Demo11StudentApi.deleteDemo11Student(id)
+    await Demo03StudentApi.deleteDemo03Student(id)
     message.success(t('common.delSuccess'))
     // 刷新列表
     await getList()
@@ -237,7 +217,7 @@ const handleExport = async () => {
     await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
-    const data = await Demo11StudentApi.exportDemo11Student(queryParams)
+    const data = await Demo03StudentApi.exportDemo03Student(queryParams)
     download.excel(data, '学生.xls')
   } catch {
   } finally {

+ 0 - 58
src/views/infra/demo04/DemoStudentAddressForm.vue

@@ -1,58 +0,0 @@
-<template>
-  <el-form
-    ref="formRef"
-    :model="formData"
-    :rules="formRules"
-    label-width="100px"
-    v-loading="formLoading"
-  >
-    <el-form-item label="子字段 1" prop="field1">
-      <el-input v-model="formData.field1" placeholder="请输入字段 1" />
-    </el-form-item>
-    <el-form-item label="子字段 2" prop="field2">
-      <el-input v-model="formData.field2" placeholder="请输入字段 2" />
-    </el-form-item>
-    <el-form-item label="子字段 3" prop="field3">
-      <el-input v-model="formData.field3" placeholder="请输入字段 3" />
-    </el-form-item>
-  </el-form>
-</template>
-<script setup lang="ts">
-const props = defineProps<{
-  studentId: undefined // 学生编号
-}>()
-const formLoading = ref(false) // 表单的加载中
-const formData = ref({})
-const formRules = reactive({
-  field1: [required]
-})
-const formRef = ref() // 表单 Ref
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  (val) => {
-    if (val) {
-      formData.value = {
-        field2: '番茄',
-        field3: '西瓜'
-      }
-    } else {
-      formData.value = {}
-    }
-  },
-  { immediate: true }
-)
-
-/** 表单校验 */
-const validate = () => {
-  return formRef.value.validate()
-}
-
-/** 表单值 **/
-const getData = () => {
-  return formData.value
-}
-
-defineExpose({ validate, getData })
-</script>

+ 0 - 39
src/views/infra/demo04/DemoStudentAddressList.vue

@@ -1,39 +0,0 @@
-<template>
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="手机" align="center" prop="mobile" />
-    </el-table>
-  </ContentWrap>
-</template>
-
-<script setup lang="ts">
-const props = defineProps<{
-  studentId: undefined // 学生编号
-}>()
-const loading = ref(true) // 列表的加载中
-const list = ref([]) // 列表的数据
-
-// TODO 芋艿:暂时没改
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    // const data = await DemoStudentApi.getDemoStudentPage(queryParams)
-    list.value = [
-      {
-        id: props.studentId,
-        mobile: '88888'
-      }
-    ]
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
-</script>

+ 0 - 96
src/views/infra/demo04/DemoStudentContactForm.vue

@@ -1,96 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="字段 1" prop="field1">
-        <el-input v-model="formData.field1" placeholder="请输入字段 1" />
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import * as DemoStudentApi from '@/api/infra/demo02'
-import DemoStudentContactForm from './DemoStudentContactForm.vue'
-import DemoStudentAddressForm from './DemoStudentAddressForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined
-})
-const formRules = reactive({
-  field2: [required]
-})
-const formRef = ref() // 表单 Ref
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    // debugger
-    formLoading.value = true
-    try {
-      // formData.value = await DemoStudentApi.getDemoStudent(id)
-      formData.value = {
-        id: id,
-        field1: '1',
-        field2: '22',
-        field3: '333'
-      }
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as DemoStudentApi.DemoStudentVO
-    if (formType.value === 'create') {
-      // await DemoStudentApi.createDemoStudent(data) // TODO 芋艿:临时去掉
-      message.success(t('common.createSuccess'))
-    } else {
-      await DemoStudentApi.updateDemoStudent(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 70
src/views/infra/demo04/DemoStudentContactList.vue

@@ -1,70 +0,0 @@
-<template>
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-button type="primary" plain @click="openForm('create')">
-      <Icon icon="ep:plus" class="mr-5px" /> 新增
-    </el-button>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="手机" align="center" prop="mobile" />
-    </el-table>
-  </ContentWrap>
-
-  <!-- 表单弹窗:添加/修改 -->
-  <DemoStudentContactForm ref="formRef" @success="getList" />
-</template>
-
-<script setup lang="ts">
-import DemoStudentContactForm from './DemoStudentContactForm.vue'
-
-const props = defineProps<{
-  studentId: undefined // 学生编号
-}>()
-const loading = ref(false) // 列表的加载中
-const total = ref(0) // 列表的总页数
-const list = ref([]) // 列表的数据
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  studentId: undefined
-})
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  (val) => {
-    queryParams.studentId = val
-    handleQuery()
-  },
-  { immediate: false }
-)
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    // const data = await DemoStudentApi.getDemoStudentPage(queryParams)
-    list.value = [
-      {
-        id: props.studentId,
-        mobile: '15601691300'
-      }
-    ]
-    total.value = 10
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
-}
-</script>

+ 0 - 132
src/views/infra/demo04/DemoStudentForm.vue

@@ -1,132 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="字段 1" prop="field1">
-        <el-input v-model="formData.field1" placeholder="请输入字段 1" />
-      </el-form-item>
-      <el-form-item label="字段 2" prop="field2">
-        <el-input v-model="formData.field2" placeholder="请输入字段 2" />
-      </el-form-item>
-      <el-form-item label="字段 3" prop="field3">
-        <el-input v-model="formData.field3" placeholder="请输入字段 3" />
-      </el-form-item>
-    </el-form>
-    <!-- 子表的表单 -->
-    <el-tabs v-model="subTabsName">
-      <el-tab-pane label="联系人信息" name="DemoStudentContact">
-        <DemoStudentContactForm ref="demoStudentContactFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-      <el-tab-pane label="地址信息" name="DemoStudentAddress">
-        <DemoStudentAddressForm ref="demoStudentAddressFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-    </el-tabs>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import * as DemoStudentApi from '@/api/infra/demo02'
-import DemoStudentContactForm from './DemoStudentContactForm.vue'
-import DemoStudentAddressForm from './DemoStudentAddressForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined
-})
-const formRules = reactive({
-  field2: [required]
-})
-const formRef = ref() // 表单 Ref
-
-/** 子表的表单 */
-const demoStudentContactFormRef = ref()
-const demoStudentAddressFormRef = ref()
-const subTabsName = ref('DemoStudentContact')
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    // debugger
-    formLoading.value = true
-    try {
-      // formData.value = await DemoStudentApi.getDemoStudent(id)
-      formData.value = {
-        id: id,
-        field1: '1',
-        field2: '22',
-        field3: '333'
-      }
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 校验子表单
-  try {
-    await demoStudentContactFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'DemoStudentContact'
-    return
-  }
-  try {
-    await demoStudentAddressFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'DemoStudentAddress'
-    return
-  }
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as DemoStudentApi.DemoStudentVO
-    // 拼接子表的数据
-    data.demoStudentContacts = demoStudentContactFormRef.value.getData()
-    data.demoStudentAddress = demoStudentAddressFormRef.value.getData()
-    if (formType.value === 'create') {
-      await DemoStudentApi.createDemoStudent(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await DemoStudentApi.updateDemoStudent(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 184
src/views/infra/demo04/index.vue

@@ -1,184 +0,0 @@
-<template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
-      <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" plain @click="openForm('create')">
-          <Icon icon="ep:plus" class="mr-5px" /> 新增
-        </el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['infra:demo-student:export']"
-        >
-          <Icon icon="ep:download" class="mr-5px" /> 导出
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table
-      v-loading="loading"
-      :data="list"
-      :stripe="true"
-      :show-overflow-tooltip="true"
-      highlight-current-row
-      @current-change="handleCurrentChange"
-    >
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="操作" align="center">
-        <template #default="scope">
-          <el-button link type="primary" @click="openForm('update', scope.row.id)">
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-            v-hasPermi="['infra:demo-student:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
-
-  <!-- 子列表 -->
-  <ContentWrap>
-    <el-tabs model-value="DemoStudentContact">
-      <el-tab-pane label="联系人信息" name="DemoStudentContact">
-        <DemoStudentContactList :student-id="currentRow.id" />
-      </el-tab-pane>
-      <el-tab-pane label="地址信息" name="DemoStudentAddress">
-        <DemoStudentAddressList :student-id="currentRow.id" />
-      </el-tab-pane>
-    </el-tabs>
-  </ContentWrap>
-
-  <!-- 表单弹窗:添加/修改 -->
-  <DemoStudentForm ref="formRef" @success="getList" />
-</template>
-
-<script setup lang="ts">
-import download from '@/utils/download'
-import * as DemoStudentApi from '@/api/infra/demo02'
-import DemoStudentForm from './DemoStudentForm.vue'
-import DemoStudentContactList from './DemoStudentContactList.vue'
-import DemoStudentAddressList from './DemoStudentAddressList.vue'
-
-defineOptions({ name: 'InfraDemoStudent' })
-
-const message = useMessage() // 消息弹窗
-const { t } = useI18n() // 国际化
-
-const loading = ref(true) // 列表的加载中
-const total = ref(0) // 列表的总页数
-const list = ref([]) // 列表的数据
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10
-})
-const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
-const currentRow = ref({}) // 选中行
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    // const data = await DemoStudentApi.getDemoStudentPage(queryParams)
-    list.value = [
-      {
-        id: 1
-      },
-      {
-        id: 10
-      }
-    ]
-    total.value = 10
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  handleQuery()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-// const demoStudentContactFormRef = ref()
-const openForm = (type: string, id?: number) => {
-  // console.log(demoStudentContactFormRef, 'xx demoStudentContactFormRef xx')
-  // demoStudentContactFormRef.value.validate()
-  formRef.value.open(type, id)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await DemoStudentApi.deleteDemoStudent(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await DemoStudentApi.exportDemoStudent(queryParams)
-    download.excel(data, '学生.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
-
-/** 选中行操作 */
-const handleCurrentChange = (row) => {
-  console.log(currentRow.value, '==== currentRow.value ====')
-  console.log(row, '==== row ====')
-  currentRow.value = row
-}
-
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
-</script>

+ 0 - 183
src/views/infra/demo11/Demo11StudentForm.vue

@@ -1,183 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="名字" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入名字" />
-      </el-form-item>
-      <el-form-item label="简介" prop="description">
-        <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
-      </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="formData.birthday"
-          type="date"
-          value-format="x"
-          placeholder="选择出生日期"
-        />
-      </el-form-item>
-      <el-form-item label="性别" prop="sex">
-        <el-select v-model="formData.sex" placeholder="请选择性别">
-          <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-radio-group v-model="formData.enabled">
-          <el-radio
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-            :key="dict.value"
-            :label="dict.value"
-          >
-            {{ dict.label }}
-          </el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="头像">
-        <UploadImg v-model="formData.avatar" />
-      </el-form-item>
-      <el-form-item label="附件" prop="video">
-        <UploadFile v-model="formData.video" />
-      </el-form-item>
-      <el-form-item label="备注" prop="memo">
-        <Editor v-model="formData.memo" height="150px" />
-      </el-form-item>
-    </el-form>
-    <!-- 子表的表单 -->
-    <el-tabs v-model="subTabsName">
-      <el-tab-pane label="学生联系人" name="demo11StudentContact">
-        <Demo11StudentContactForm ref="demo11StudentContactFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-      <el-tab-pane label="学生班主任" name="demo11StudentTeacher">
-        <Demo11StudentTeacherForm ref="demo11StudentTeacherFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-    </el-tabs>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo11StudentApi from '@/api/infra/demo11'
-import Demo11StudentContactForm from './components/Demo11StudentContactForm.vue'
-import Demo11StudentTeacherForm from './components/Demo11StudentTeacherForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined,
-  name: undefined,
-  description: undefined,
-  birthday: undefined,
-  sex: undefined,
-  enabled: undefined,
-  avatar: undefined,
-  video: undefined,
-  memo: undefined
-})
-const formRules = reactive({
-  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
-  birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
-})
-const formRef = ref() // 表单 Ref
-
-/** 子表的表单 */
-const subTabsName = ref('demo11StudentContact')
-const demo11StudentContactFormRef = ref()
-const demo11StudentTeacherFormRef = ref()
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await Demo11StudentApi.getDemo11Student(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 校验子表单
-  try {
-    await demo11StudentContactFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'demo11StudentContact'
-    return
-  }
-  try {
-    await demo11StudentTeacherFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'demo11StudentTeacher'
-    return
-  }
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as Demo11StudentApi.Demo11StudentVO
-    // 拼接子表的数据
-    data.demo11StudentContacts = demo11StudentContactFormRef.value.getData()
-    data.demo11StudentTeacher = demo11StudentTeacherFormRef.value.getData()
-    if (formType.value === 'create') {
-      await Demo11StudentApi.createDemo11Student(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await Demo11StudentApi.updateDemo11Student(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined,
-    name: undefined,
-    description: undefined,
-    birthday: undefined,
-    sex: undefined,
-    enabled: undefined,
-    avatar: undefined,
-    video: undefined,
-    memo: undefined
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 174
src/views/infra/demo11/components/Demo11StudentContactForm.vue

@@ -1,174 +0,0 @@
-<template>
-  <el-form
-    ref="formRef"
-    :model="formData"
-    :rules="formRules"
-    v-loading="formLoading"
-    label-width="0px"
-    :inline-message="true"
-  >
-    <el-table :data="formData" class="-mt-10px">
-      <el-table-column label="序号" type="index" width="100" />
-      <el-table-column label="名字" width="150">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!">
-            <el-input v-model="row.name" placeholder="请输入名字" />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="简介" width="200">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.description`" :rules="formRules.description" class="mb-0px!">
-            <el-input v-model="row.description" type="textarea" placeholder="请输入简介" />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="出生日期" width="150">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!">
-            <el-date-picker
-              v-model="row.birthday"
-              type="date"
-              value-format="x"
-              placeholder="选择出生日期"
-            />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="性别" width="150">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.sex`" :rules="formRules.sex" class="mb-0px!">
-            <el-select v-model="row.sex" placeholder="请选择性别">
-                <el-option
-                  v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                />
-            </el-select>
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="是否有效" width="150">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.enabled`" :rules="formRules.enabled" class="mb-0px!">
-            <el-radio-group v-model="row.enabled">
-                <el-radio
-                  v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-                  :key="dict.value"
-                  :label="dict.value"
-                >
-                  {{ dict.label }}
-                </el-radio>
-            </el-radio-group>
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="头像" width="200">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.avatar`" :rules="formRules.avatar" class="mb-0px!">
-            <UploadImg v-model="row.avatar" />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="附件" width="200">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.video`" :rules="formRules.video" class="mb-0px!">
-            <UploadFile v-model="row.video" />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column label="备注" width="400">
-        <template #default="{ row, $index }">
-          <el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!">
-            <Editor v-model="row.memo" height="150px" />
-          </el-form-item>
-        </template>
-      </el-table-column>
-      <el-table-column align="center" fixed="right" label="操作" width="60">
-        <template #default="{ $index }">
-          <el-button @click="handleDelete($index)" link>—</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-  </el-form>
-  <el-row justify="center" class="mt-3">
-    <el-button @click="handleAdd" round>+ 添加学生联系人</el-button>
-  </el-row>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo11StudentApi from '@/api/infra/demo11'
-
-const props = defineProps<{
-  studentId: undefined // 学生编号(主表的关联字段)
-}>()
-const formLoading = ref(false) // 表单的加载中
-const formData = ref([])
-const formRules = reactive({
-  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
-  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
-  birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
-})
-const formRef = ref() // 表单 Ref
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  async (val) => {
-    // 情况一:val 为空,说明是新增,则置空
-    if (!val) {
-      formData.value = []
-      return;
-    }
-    // 情况二:val 非空,说明是修改,则加载数据
-    try {
-      formLoading.value = true
-      formData.value = await Demo11StudentApi.getDemo11StudentContactListByStudentId(val)
-    } finally {
-      formLoading.value = false
-    }
-  },
-  { immediate: true }
-)
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  const row = {
-    id: undefined,
-    studentId: undefined,
-    name: undefined,
-    description: undefined,
-    birthday: undefined,
-    sex: undefined,
-    enabled: undefined,
-    avatar: undefined,
-    video: undefined,
-    memo: undefined
-  }
-  row.studentId = props.studentId
-  formData.value.push(row)
-}
-
-/** 删除按钮操作 */
-const handleDelete = (index) => {
-  formData.value.splice(index, 1)
-}
-
-/** 表单校验 */
-const validate = () => {
-  return formRef.value.validate()
-}
-
-/** 表单值 */
-const getData = () => {
-  return formData.value
-}
-
-defineExpose({ validate, getData })
-</script>

+ 0 - 122
src/views/infra/demo11/components/Demo11StudentTeacherForm.vue

@@ -1,122 +0,0 @@
-<template>
-  <el-form
-    ref="formRef"
-    :model="formData"
-    :rules="formRules"
-    label-width="100px"
-    v-loading="formLoading"
-  >
-    <el-form-item label="名字" prop="name">
-      <el-input v-model="formData.name" placeholder="请输入名字" />
-    </el-form-item>
-    <el-form-item label="简介" prop="description">
-      <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
-    </el-form-item>
-    <el-form-item label="出生日期" prop="birthday">
-      <el-date-picker
-        v-model="formData.birthday"
-        type="date"
-        value-format="x"
-        placeholder="选择出生日期"
-      />
-    </el-form-item>
-    <el-form-item label="性别" prop="sex">
-      <el-select v-model="formData.sex" placeholder="请选择性别">
-        <el-option
-          v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-          :key="dict.value"
-          :label="dict.label"
-          :value="dict.value"
-        />
-      </el-select>
-    </el-form-item>
-    <el-form-item label="是否有效" prop="enabled">
-      <el-radio-group v-model="formData.enabled">
-        <el-radio
-          v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-          :key="dict.value"
-          :label="dict.value"
-          >
-          {{ dict.label }}
-        </el-radio>
-      </el-radio-group>
-    </el-form-item>
-    <el-form-item label="头像" prop="avatar">
-      <UploadImg v-model="formData.avatar" />
-    </el-form-item>
-    <el-form-item label="附件" prop="video">
-      <UploadFile v-model="formData.video" />
-    </el-form-item>
-    <el-form-item label="备注" prop="memo">
-      <Editor v-model="formData.memo" height="150px" />
-    </el-form-item>
-  </el-form>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo11StudentApi from '@/api/infra/demo11'
-
-const props = defineProps<{
-  studentId: undefined // 学生编号(主表的关联字段)
-}>()
-const formLoading = ref(false) // 表单的加载中
-const formData = ref([])
-const formRules = reactive({
-  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
-  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
-  birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
-})
-const formRef = ref() // 表单 Ref
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  async (val) => {
-    // 1. 重置表单
-    formData.value = {
-      id: undefined,
-      studentId: undefined,
-      name: undefined,
-      description: undefined,
-      birthday: undefined,
-      sex: undefined,
-      enabled: undefined,
-      avatar: undefined,
-      video: undefined,
-      memo: undefined,
-    }
-    // 2. val 非空,则加载数据
-    if (!val) {
-      return;
-    }
-    try {
-      formLoading.value = true
-      const data = await Demo11StudentApi.getDemo11StudentTeacherByStudentId(val)
-      if (!data) {
-        return
-      }
-      formData.value = data
-    } finally {
-      formLoading.value = false
-    }
-  },
-  { immediate: true }
-)
-
-/** 表单校验 */
-const validate = () => {
-  return formRef.value.validate()
-}
-
-/** 表单值 */
-const getData = () => {
-  return formData.value
-}
-
-defineExpose({ validate, getData })
-</script>

+ 0 - 183
src/views/infra/demo12/Demo12StudentForm.vue

@@ -1,183 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="名字" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入名字" />
-      </el-form-item>
-      <el-form-item label="简介" prop="description">
-        <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
-      </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="formData.birthday"
-          type="date"
-          value-format="x"
-          placeholder="选择出生日期"
-        />
-      </el-form-item>
-      <el-form-item label="性别" prop="sex">
-        <el-select v-model="formData.sex" placeholder="请选择性别">
-          <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-radio-group v-model="formData.enabled">
-          <el-radio
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-            :key="dict.value"
-            :label="dict.value"
-          >
-            {{ dict.label }}
-          </el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="头像" prop="avatar">
-        <UploadImg v-model="formData.avatar" />
-      </el-form-item>
-      <el-form-item label="附件" prop="video">
-        <UploadFile v-model="formData.video" />
-      </el-form-item>
-      <el-form-item label="备注" prop="memo">
-        <Editor v-model="formData.memo" height="150px" />
-      </el-form-item>
-    </el-form>
-    <!-- 子表的表单 -->
-    <el-tabs v-model="subTabsName">
-      <el-tab-pane label="学生联系人" name="demo12StudentContact">
-        <Demo12StudentContactForm ref="demo12StudentContactFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-      <el-tab-pane label="学生班主任" name="demo12StudentTeacher">
-        <Demo12StudentTeacherForm ref="demo12StudentTeacherFormRef" :student-id="formData.id" />
-      </el-tab-pane>
-    </el-tabs>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo12StudentApi from '@/api/infra/demo12'
-import Demo12StudentContactForm from './components/Demo12StudentContactForm.vue'
-import Demo12StudentTeacherForm from './components/Demo12StudentTeacherForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined,
-  name: undefined,
-  description: undefined,
-  birthday: undefined,
-  sex: undefined,
-  enabled: undefined,
-  avatar: undefined,
-  video: undefined,
-  memo: undefined
-})
-const formRules = reactive({
-  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
-  birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
-})
-const formRef = ref() // 表单 Ref
-
-/** 子表的表单 */
-const subTabsName = ref('demo12StudentContact')
-const demo12StudentContactFormRef = ref()
-const demo12StudentTeacherFormRef = ref()
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await Demo12StudentApi.getDemo12Student(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 校验子表单
-  try {
-    await demo12StudentContactFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'demo12StudentContact'
-    return
-  }
-  try {
-    await demo12StudentTeacherFormRef.value.validate()
-  } catch (e) {
-    subTabsName.value = 'demo12StudentTeacher'
-    return
-  }
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as Demo12StudentApi.Demo12StudentVO
-    // 拼接子表的数据
-    data.demo12StudentContacts = demo12StudentContactFormRef.value.getData()
-    data.demo12StudentTeacher = demo12StudentTeacherFormRef.value.getData()
-    if (formType.value === 'create') {
-      await Demo12StudentApi.createDemo12Student(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await Demo12StudentApi.updateDemo12Student(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined,
-    name: undefined,
-    description: undefined,
-    birthday: undefined,
-    sex: undefined,
-    enabled: undefined,
-    avatar: undefined,
-    video: undefined,
-    memo: undefined
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 148
src/views/infra/demo12/components/Demo12StudentContactList.vue

@@ -1,148 +0,0 @@
-<template>
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-button
-      type="primary"
-      plain
-      @click="openForm('create')"
-      v-hasPermi="['infra:demo12-student:create']"
-    >
-      <Icon icon="ep:plus" class="mr-5px" /> 新增
-    </el-button>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="学生编号" align="center" prop="studentId" />
-      <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="简介" align="center" prop="description" />
-      <el-table-column
-        label="出生日期"
-        align="center"
-        prop="birthday"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="性别" align="center" prop="sex">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
-        </template>
-      </el-table-column>
-      <el-table-column label="是否有效" align="center" prop="enabled">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
-        </template>
-      </el-table-column>
-      <el-table-column label="头像" align="center" prop="avatar" />
-      <el-table-column label="附件" align="center" prop="video" />
-      <el-table-column label="备注" align="center" prop="memo" />
-      <el-table-column
-        label="创建时间"
-        align="center"
-        prop="createTime"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center">
-        <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm('update', scope.row.id)"
-            v-hasPermi="['infra:demo12-student:update']"
-          >
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-            v-hasPermi="['infra:demo12-student:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
-
-    <!-- 表单弹窗:添加/修改 -->
-    <Demo12StudentContactForm ref="formRef" @success="getList" />
-</template>
-
-<script setup lang="ts">
-import { DICT_TYPE } from '@/utils/dict'
-import * as Demo12StudentApi from '@/api/infra/demo12'
-import Demo12StudentContactForm from './Demo12StudentContactForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const props = defineProps<{
-  studentId: undefined // 学生编号(主表的关联字段)
-}>()
-const loading = ref(false) // 列表的加载中
-const list = ref([]) // 列表的数据
-const total = ref(0) // 列表的总页数
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  studentId: undefined
-})
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  (val) => {
-    queryParams.studentId = val
-    handleQuery()
-  },
-  { immediate: false }
-)
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await Demo12StudentApi.getDemo12StudentContactPage(queryParams)
-    list.value = data.list
-    total.value = data.total
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  if (!props.studentId) {
-    message.error('请选择一个学生')
-    return
-  }
-  formRef.value.open(type, id, props.studentId)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await Demo12StudentApi.deleteDemo12StudentContact(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-</script>

+ 0 - 155
src/views/infra/demo12/components/Demo12StudentTeacherForm.vue

@@ -1,155 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="名字" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入名字" />
-      </el-form-item>
-      <el-form-item label="简介" prop="description">
-        <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
-      </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="formData.birthday"
-          type="date"
-          value-format="x"
-          placeholder="选择出生日期"
-        />
-      </el-form-item>
-      <el-form-item label="性别" prop="sex">
-        <el-select v-model="formData.sex" placeholder="请选择性别">
-          <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-radio-group v-model="formData.enabled">
-          <el-radio
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-            :key="dict.value"
-            :label="dict.value"
-          >
-            {{ dict.label }}
-          </el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="头像" prop="avatar">
-        <UploadImg v-model="formData.avatar" />
-      </el-form-item>
-      <el-form-item label="附件" prop="video">
-        <UploadFile v-model="formData.video" />
-      </el-form-item>
-      <el-form-item label="备注" prop="memo">
-        <Editor v-model="formData.memo" height="150px" />
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import * as Demo12StudentApi from '@/api/infra/demo12'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined,
-  studentId: undefined,
-  name: undefined,
-  description: undefined,
-  birthday: undefined,
-  sex: undefined,
-  enabled: undefined,
-  avatar: undefined,
-  video: undefined,
-  memo: undefined
-})
-const formRules = reactive({
-  studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }],
-  name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
-  description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
-  birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
-  sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
-  enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
-  avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
-  memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }]
-})
-const formRef = ref() // 表单 Ref
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number, studentId: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  formData.value.studentId = studentId
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await Demo12StudentApi.getDemo12StudentTeacher(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value
-    if (formType.value === 'create') {
-      await Demo12StudentApi.createDemo12StudentTeacher(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await Demo12StudentApi.updateDemo12StudentTeacher(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined,
-    studentId: undefined,
-    name: undefined,
-    description: undefined,
-    birthday: undefined,
-    sex: undefined,
-    enabled: undefined,
-    avatar: undefined,
-    video: undefined,
-    memo: undefined
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 148
src/views/infra/demo12/components/Demo12StudentTeacherList.vue

@@ -1,148 +0,0 @@
-<template>
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-button
-      type="primary"
-      plain
-      @click="openForm('create')"
-      v-hasPermi="['infra:demo12-student:create']"
-    >
-      <Icon icon="ep:plus" class="mr-5px" /> 新增
-    </el-button>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="学生编号" align="center" prop="studentId" />
-      <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="简介" align="center" prop="description" />
-      <el-table-column
-        label="出生日期"
-        align="center"
-        prop="birthday"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="性别" align="center" prop="sex">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
-        </template>
-      </el-table-column>
-      <el-table-column label="是否有效" align="center" prop="enabled">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
-        </template>
-      </el-table-column>
-      <el-table-column label="头像" align="center" prop="avatar" />
-      <el-table-column label="附件" align="center" prop="video" />
-      <el-table-column label="备注" align="center" prop="memo" />
-      <el-table-column
-        label="创建时间"
-        align="center"
-        prop="createTime"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center">
-        <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm('update', scope.row.id)"
-            v-hasPermi="['infra:demo12-student:update']"
-          >
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-            v-hasPermi="['infra:demo12-student:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
-
-    <!-- 表单弹窗:添加/修改 -->
-    <Demo12StudentTeacherForm ref="formRef" @success="getList" />
-</template>
-
-<script setup lang="ts">
-import { DICT_TYPE } from '@/utils/dict'
-import * as Demo12StudentApi from '@/api/infra/demo12'
-import Demo12StudentTeacherForm from './Demo12StudentTeacherForm.vue'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const props = defineProps<{
-  studentId: undefined // 学生编号(主表的关联字段)
-}>()
-const loading = ref(false) // 列表的加载中
-const list = ref([]) // 列表的数据
-const total = ref(0) // 列表的总页数
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  studentId: undefined
-})
-
-/** 监听主表的关联字段的变化,加载对应的子表数据 */
-watch(
-  () => props.studentId,
-  (val) => {
-    queryParams.studentId = val
-    handleQuery()
-  },
-  { immediate: false }
-)
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await Demo12StudentApi.getDemo12StudentTeacherPage(queryParams)
-    list.value = data.list
-    total.value = data.total
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  if (!props.studentId) {
-    message.error('请选择一个学生')
-    return
-  }
-  formRef.value.open(type, id, props.studentId)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await Demo12StudentApi.deleteDemo12StudentTeacher(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-</script>

+ 0 - 278
src/views/infra/demo12/index.vue

@@ -1,278 +0,0 @@
-<template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
-      <el-form-item label="名字" prop="name">
-        <el-input
-          v-model="queryParams.name"
-          placeholder="请输入名字"
-          clearable
-          @keyup.enter="handleQuery"
-          class="!w-240px"
-        />
-      </el-form-item>
-      <el-form-item label="出生日期" prop="birthday">
-        <el-date-picker
-          v-model="queryParams.birthday"
-          value-format="YYYY-MM-DD"
-          type="date"
-          placeholder="选择出生日期"
-          clearable
-          class="!w-240px"
-        />
-      </el-form-item>
-      <el-form-item label="性别" prop="sex">
-        <el-select
-          v-model="queryParams.sex"
-          placeholder="请选择性别"
-          clearable
-          class="!w-240px"
-        >
-          <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="是否有效" prop="enabled">
-        <el-select
-          v-model="queryParams.enabled"
-          placeholder="请选择是否有效"
-          clearable
-          class="!w-240px"
-        >
-          <el-option
-            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="创建时间" prop="createTime">
-        <el-date-picker
-          v-model="queryParams.createTime"
-          value-format="YYYY-MM-DD HH:mm:ss"
-          type="daterange"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-240px"
-        />
-      </el-form-item>
-      <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button
-          type="primary"
-          plain
-          @click="openForm('create')"
-          v-hasPermi="['infra:demo12-student:create']"
-        >
-          <Icon icon="ep:plus" class="mr-5px" /> 新增
-        </el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleExport"
-          :loading="exportLoading"
-          v-hasPermi="['infra:demo12-student:export']"
-        >
-          <Icon icon="ep:download" class="mr-5px" /> 导出
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table
-      v-loading="loading"
-      :data="list"
-      :stripe="true"
-      :show-overflow-tooltip="true"
-      highlight-current-row
-      @current-change="handleCurrentChange"
-    >
-      <el-table-column label="编号" align="center" prop="id" />
-      <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="简介" align="center" prop="description" />
-      <el-table-column
-        label="出生日期"
-        align="center"
-        prop="birthday"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="性别" align="center" prop="sex">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" />
-        </template>
-      </el-table-column>
-      <el-table-column label="是否有效" align="center" prop="enabled">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
-        </template>
-      </el-table-column>
-      <el-table-column label="头像" align="center" prop="avatar" />
-      <el-table-column label="附件" align="center" prop="video" />
-      <el-table-column label="备注" align="center" prop="memo" />
-      <el-table-column
-        label="创建时间"
-        align="center"
-        prop="createTime"
-        :formatter="dateFormatter"
-        width="180px"
-      />
-      <el-table-column label="操作" align="center">
-        <template #default="scope">
-          <el-button
-            link
-            type="primary"
-            @click="openForm('update', scope.row.id)"
-            v-hasPermi="['infra:demo12-student:update']"
-          >
-            编辑
-          </el-button>
-          <el-button
-            link
-            type="danger"
-            @click="handleDelete(scope.row.id)"
-            v-hasPermi="['infra:demo12-student:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
-
-  <!-- 表单弹窗:添加/修改 -->
-  <Demo12StudentForm ref="formRef" @success="getList" />
-  <!-- 子表的列表 -->
-  <ContentWrap>
-    <el-tabs model-value="demo12StudentContact">
-      <el-tab-pane label="学生联系人" name="demo12StudentContact">
-        <Demo12StudentContactList :student-id="currentRow.id" />
-      </el-tab-pane>
-      <el-tab-pane label="学生班主任" name="demo12StudentTeacher">
-        <Demo12StudentTeacherList :student-id="currentRow.id" />
-      </el-tab-pane>
-    </el-tabs>
-  </ContentWrap>
-</template>
-
-<script setup lang="ts">
-import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
-import { dateFormatter } from '@/utils/formatTime'
-import download from '@/utils/download'
-import * as Demo12StudentApi from '@/api/infra/demo12'
-import Demo12StudentForm from './Demo12StudentForm.vue'
-import Demo12StudentContactList from './components/Demo12StudentContactList.vue'
-import Demo12StudentTeacherList from './components/Demo12StudentTeacherList.vue'
-
-defineOptions({ name: 'InfraDemo12Student' })
-
-const message = useMessage() // 消息弹窗
-const { t } = useI18n() // 国际化
-
-const loading = ref(true) // 列表的加载中
-const total = ref(0) // 列表的总页数
-const list = ref([]) // 列表的数据
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  name: null,
-  birthday: null,
-  birthday: [],
-  sex: null,
-  enabled: null,
-  createTime: []
-})
-const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await Demo12StudentApi.getDemo12StudentPage(queryParams)
-    list.value = data.list
-    total.value = data.total
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  handleQuery()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await Demo12StudentApi.deleteDemo12Student(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await Demo12StudentApi.exportDemo12Student(queryParams)
-    download.excel(data, '学生.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
-
-/** 选中行操作 */
-const currentRow = ref({}) // 选中行
-const handleCurrentChange = (row) => {
-  currentRow.value = row
-}
-
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
-</script>

+ 0 - 4
src/views/infra/testDemo/index.vue

@@ -1,4 +0,0 @@
-<template>
-  <div>index</div>
-</template>
-<script lang="ts" setup></script>