wuheng hai 1 ano
pai
achega
c465c692a7

+ 3 - 1
src/locales/lang/en.ts

@@ -83,7 +83,9 @@ const locale: LocaleMessages<I18nType.Schema> = {
         _value: 'Lesson Management',
         _value: 'Lesson Management',
         group: 'class',
         group: 'class',
         classroom: 'classroom',
         classroom: 'classroom',
-        schedule: 'schedule'
+        schedule: 'schedule',
+        calendar: 'calendar',
+        student: 'group student'
       },
       },
       about: 'About'
       about: 'About'
     }
     }

+ 3 - 1
src/locales/lang/zh-cn.ts

@@ -83,7 +83,9 @@ const locale: LocaleMessages<I18nType.Schema> = {
         _value: '课程管理',
         _value: '课程管理',
         group: '班级管理',
         group: '班级管理',
         classroom: '教室管理',
         classroom: '教室管理',
-        schedule: '排课管理'
+        schedule: '排课管理',
+        calendar: '课程日历',
+        student: '班级学员'
       },
       },
       about: '关于'
       about: '关于'
     }
     }

+ 1 - 1
src/plugins/fast-crud/index.tsx

@@ -169,7 +169,7 @@ function install(app: App, options: FsSetupOpts = {}) {
           locale,
           locale,
           name: 'a-date-picker',
           name: 'a-date-picker',
           format: 'YYYY-MM-DD',
           format: 'YYYY-MM-DD',
-          valueFormat: 'YYYY-MM-DD hh:mm',
+          valueFormat: 'YYYY-MM-DD',
           vModel: 'value'
           vModel: 'value'
         }
         }
       },
       },

+ 22 - 0
src/router/modules/lesson.ts

@@ -25,6 +25,28 @@ const management: AuthRoute.Route = {
         icon: 'healthicons:i-schedule-school-date-time'
         icon: 'healthicons:i-schedule-school-date-time'
       }
       }
     },
     },
+    {
+      name: 'lesson_calendar',
+      path: '/lesson/calendar',
+      component: 'self',
+      meta: {
+        title: '排课日历',
+        i18nTitle: 'message.routes.lesson.calendar',
+        requiresAuth: true,
+        icon: 'radix-icons:calendar'
+      }
+    },
+    {
+      name: 'lesson_student',
+      path: '/lesson/student',
+      component: 'self',
+      meta: {
+        title: '排课日历',
+        i18nTitle: 'message.routes.lesson.student',
+        requiresAuth: true,
+        icon: 'typcn:group'
+      }
+    },
     {
     {
       name: 'lesson_classroom',
       name: 'lesson_classroom',
       path: '/lesson/classroom',
       path: '/lesson/classroom',

+ 4 - 0
src/typings/page-route.d.ts

@@ -56,6 +56,8 @@ declare namespace PageRoute {
     | 'lesson_classroom'
     | 'lesson_classroom'
     | 'lesson_group'
     | 'lesson_group'
     | 'lesson_schedule'
     | 'lesson_schedule'
+    | 'lesson_calendar'
+    | 'lesson_student'
     | 'management'
     | 'management'
     | 'management_auth'
     | 'management_auth'
     | 'management_role'
     | 'management_role'
@@ -119,6 +121,8 @@ declare namespace PageRoute {
     | 'lesson_classroom'
     | 'lesson_classroom'
     | 'lesson_group'
     | 'lesson_group'
     | 'lesson_schedule'
     | 'lesson_schedule'
+    | 'lesson_calendar'
+    | 'lesson_student'
     | 'management_auth'
     | 'management_auth'
     | 'management_role'
     | 'management_role'
     | 'management_route'
     | 'management_route'

+ 2 - 0
src/typings/system.d.ts

@@ -397,6 +397,8 @@ declare namespace I18nType {
         group: string;
         group: string;
         classroom: string;
         classroom: string;
         schedule: string;
         schedule: string;
+        calendar: string;
+        student: string;
       };
       };
       about: string;
       about: string;
     };
     };

+ 2 - 0
src/views/index.ts

@@ -35,6 +35,8 @@ export const views: Record<
   lesson_classroom: () => import('./lesson/classroom/index.vue'),
   lesson_classroom: () => import('./lesson/classroom/index.vue'),
   lesson_group: () => import('./lesson/group/index.vue'),
   lesson_group: () => import('./lesson/group/index.vue'),
   lesson_schedule: () => import('./lesson/schedule/index.vue'),
   lesson_schedule: () => import('./lesson/schedule/index.vue'),
+  lesson_calendar: () => import('./lesson/calendar/index.vue'),
+  lesson_student: () => import('./lesson/student/index.vue'),
   management_auth: () => import('./management/auth/index.vue'),
   management_auth: () => import('./management/auth/index.vue'),
   management_role: () => import('./management/role/index.vue'),
   management_role: () => import('./management/role/index.vue'),
   management_route: () => import('./management/route/index.vue'),
   management_route: () => import('./management/route/index.vue'),

+ 40 - 0
src/views/lesson/calendar/api.ts

@@ -0,0 +1,40 @@
+import { request } from '@/service/request';
+
+export interface QueryScheduleParams {
+  studentId?: number | null;
+  classId?: number | null;
+  subjectId?: number | null;
+  teacherId?: number | null;
+  startTime?: string | null;
+  endTime?: string | null;
+  week?: number | null;
+  roomId?: number | null;
+  assistantId?: number | null;
+  categoryId?: number | null;
+}
+
+interface ScheduleResponse {
+  id?: number;
+  week?: number;
+  startTime?: string;
+  endTime?: string;
+  roomId?: number;
+  classroom?: string;
+  classId?: number;
+  assistantId?: number;
+  assistantName?: string;
+  teacherId?: number;
+  teacherName?: string;
+  categoryId?: number;
+  category?: string;
+  subjectsId?: number;
+  subjects?: string;
+  createTime?: string;
+  modifyTime?: string;
+  createUid?: number;
+  disabled?: string;
+}
+
+export function querySchedule(params: QueryScheduleParams): Promise<Service.RequestResult<ScheduleResponse[]>> {
+  return request.post(`/schedule/querySchedule`, params);
+}

+ 72 - 0
src/views/lesson/calendar/index.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="wh-full bg-white">
+    <div class="flex-col-center" style="width: 70%; margin: 0 auto; margin-top: 5%">
+      <n-calendar v-if="show" style="width: 100%" #="{ year, month, date }" @update:value="handleUpdateValue">
+        {{ year }}年{{ month }}月{{ date }}日 <br />
+        <n-tag v-if="dataList[`${year}-${doubleMonth(month)}-${date}`]" type="success">
+          共有课时:
+          {{ dataList[`${year}-${doubleMonth(month)}-${date}`] }}
+          节
+        </n-tag>
+        <n-tag v-else> 共有课时:0 节 </n-tag>
+      </n-calendar>
+
+      <n-modal v-model:show="showModal" preset="dialog" title="Dialog">
+        <template #header>
+          <div>当日课程详情</div>
+        </template>
+        <div style="margin-top: 2rem">
+          <n-timeline v-if="list.length > 0">
+            <n-timeline-item
+              v-for="item in list"
+              :key="item.id"
+              type="success"
+              :title="item.teacherName"
+              :content="item.category + '--' + item.subjects"
+              :time="item.startTime + ' - ' + item.endTime"
+            />
+          </n-timeline>
+        </div>
+        <template #action>
+          <n-button @click="showModal = false">关闭</n-button>
+        </template>
+      </n-modal>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { ref, reactive } from 'vue';
+import { querySchedule } from './api';
+const show = ref(false);
+const showModal = ref(false);
+const list = ref<any>([]);
+const allList = ref<any>({});
+const dataList = reactive<{ [index: string]: any }>({});
+function handleUpdateValue(_: number, { year, month, date }: { year: number; month: number; date: number }) {
+  if (dataList[`${year}-${doubleMonth(month)}-${date}`]) {
+    list.value = allList[`${year}-${doubleMonth(month)}-${date}`];
+    showModal.value = true;
+  }
+}
+function doubleMonth(month: number) {
+  return month < 10 ? `0${month}` : month;
+}
+querySchedule({}).then(response => {
+  response.data?.forEach(result => {
+    if (result.createTime) {
+      const key = result.createTime.split(' ')[0].toString();
+      if (!allList[key]) {
+        allList[key] = [];
+      }
+      allList[key].push(result);
+      if (dataList[key]) {
+        dataList[key] += dataList[key];
+      } else {
+        dataList[key] = 1;
+      }
+    }
+  });
+  show.value = true;
+});
+</script>
+<style scoped></style>

+ 2 - 2
src/views/lesson/group/api.ts

@@ -73,7 +73,7 @@ export async function queryAll(): Promise<UserList> {
  * @returns
  * @returns
  */
  */
 export function queryClassStudentById(classId: number): Promise<Service.RequestResult<ClassStudentParams[]>> {
 export function queryClassStudentById(classId: number): Promise<Service.RequestResult<ClassStudentParams[]>> {
-  return request.get(`/class/queryClassStudentById/${classId}`);
+  return request.get(`/class/queryClassStudentByGroupId/${classId}`);
 }
 }
 
 
 export interface ClassStudentParams {
 export interface ClassStudentParams {
@@ -120,5 +120,5 @@ export function getAll(): Promise<Service.RequestResult<StudentParams[]>> {
 }
 }
 
 
 export function submitGroupStudentForm(groupId: number, params?: number[]): Promise<Service.RequestResult<StudentRes>> {
 export function submitGroupStudentForm(groupId: number, params?: number[]): Promise<Service.RequestResult<StudentRes>> {
-  return request.post(`/class/submitGroupStudentForm/${groupId}`, params);
+  return request.post(`/class/groupStudent/${groupId}`, params);
 }
 }

+ 76 - 0
src/views/lesson/student/api.ts

@@ -0,0 +1,76 @@
+import { request } from '@/service/request';
+
+interface EasStudentQuery {
+  avatar?: string;
+  enrollmentDate?: Date | null;
+  gender?: string | null;
+  managerId?: number | null;
+  phone?: string | null;
+  studentName?: string | null;
+  studentId?: number | null;
+  admissionsId?: number | null;
+  type?: string | null;
+  admissionsName?: string | null;
+  managerName?: string | null;
+  groupId?: number | null;
+}
+
+interface GroupStudentsPojo {
+  studentId: number;
+  studentName: string;
+  avatar: string;
+  studentNumber: string;
+  managerName: string;
+  phone: string;
+  email: string;
+  gender: string;
+  enrollmentDate: string;
+  morning?: string;
+  afternoon?: string;
+  checkinDate: Date;
+  admissionsName: string;
+  scheduleId?: number;
+  category?: string;
+  subject?: string;
+  teacher?: string;
+  teacherPhone?: string;
+  groupId?: string;
+  groupName?: string;
+}
+
+export interface SubmitGroupStudentFormRes {
+  status: boolean;
+  msg: string;
+  data: Record<string, unknown>;
+  code: number;
+}
+
+export function queryClassStudent(params: EasStudentQuery): Promise<Service.RequestResult<GroupStudentsPojo>> {
+  return request.post(`/class/groupStudent`, params);
+}
+
+export function submitGroupStudentDelete(rowId: number): Promise<Service.RequestResult<SubmitGroupStudentFormRes>> {
+  return request.delete(`/class/groupStudent/${rowId}`);
+}
+
+interface EasEduCltRelation {
+  id?: number;
+  classId?: number;
+  studentId?: number;
+  createTime?: Date;
+  modifyTime?: Date;
+  createUid?: number;
+  type?: string;
+}
+
+/**
+ * 更新班级学员
+ * @param {string} groupId
+ * @param {array} params integer
+ * @returns
+ */
+export function submitGroupStudentUpdate(
+  params: EasEduCltRelation
+): Promise<Service.RequestResult<SubmitGroupStudentFormRes>> {
+  return request.put(`/class/groupStudent`, params);
+}

+ 126 - 0
src/views/lesson/student/crud.ts

@@ -0,0 +1,126 @@
+import type { CreateCrudOptionsRet } from '@fast-crud/fast-crud';
+import { dict } from '@fast-crud/fast-crud';
+import { queryClassStudent, submitGroupStudentUpdate, submitGroupStudentDelete } from './api';
+function curd(): CreateCrudOptionsRet {
+  return {
+    crudOptions: {
+      pagination: {
+        show: false
+      },
+      request: {
+        pageRequest: async ({ page, query }) => {
+          query.groupId = 1;
+          const { data } = await queryClassStudent(query);
+          return { records: data, total: 0, currentPage: page.offset, pageSize: page.limit };
+        },
+        addRequest: () => {},
+        editRequest: ({ form }) => {
+          return submitGroupStudentUpdate(form);
+        },
+        delRequest: ({ row }) => {
+          return submitGroupStudentDelete(Number(row.id));
+        }
+      },
+      toolbar: {
+        show: true
+      },
+      actionbar: {
+        show: false
+      },
+      columns: {
+        id: {
+          title: 'ID',
+          type: 'number',
+          search: { show: false },
+          show: false
+        },
+        studentId: {
+          title: '学生ID',
+          type: 'number',
+          search: { show: true },
+          column: {
+            editable: {
+              disabled: true
+            }
+          }
+        },
+        studentName: {
+          title: '学生姓名',
+          type: 'text',
+          search: { show: true },
+          column: {
+            editable: {
+              disabled: false
+            }
+          }
+        },
+        avatar: {
+          title: '头像',
+          type: 'image'
+        },
+        studentNumber: {
+          title: '学生学号',
+          type: 'text',
+          search: { show: true }
+        },
+        managerName: {
+          title: '班主任姓名',
+          type: 'text'
+        },
+        phone: {
+          title: '手机号码',
+          type: 'text',
+          search: { show: true }
+        },
+        email: {
+          title: '电子邮箱',
+          type: 'text',
+          search: { show: true }
+        },
+        gender: {
+          title: '性别',
+          type: 'dict-select',
+          dict: dict({
+            data: [
+              { value: 'M', label: '男' },
+              { value: 'F', label: '女' }
+            ]
+          }),
+          column: {
+            resizable: true,
+            width: 50
+          },
+          search: { show: true }
+        },
+        enrollmentDate: {
+          title: '入学日期',
+          type: 'easDate'
+        },
+        type: {
+          title: '类别',
+          type: 'dict-select',
+          dict: dict({
+            data: [
+              { value: '正式', label: '正式' },
+              { value: '旁听', label: '旁听' },
+              { value: '留级', label: '留级' },
+              { value: '休学', label: '休学' },
+              { value: '暂停', label: '暂停' },
+              { value: '其他', label: '其他' }
+            ]
+          }),
+          column: {
+            resizable: true,
+            width: 60
+          },
+          search: { show: true }
+        },
+        admissionsName: {
+          title: '招生负责人',
+          type: 'text'
+        }
+      }
+    }
+  };
+}
+export default curd;

+ 19 - 0
src/views/lesson/student/index.vue

@@ -0,0 +1,19 @@
+<template>
+  <div class="h-full bg-white">
+    <fs-crud ref="crudRef" v-bind="crudBinding" />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted } from 'vue';
+import { useFs } from '@fast-crud/fast-crud';
+import createCrudOptions from './crud';
+
+const { crudRef, crudBinding, crudExpose } = useFs({ createCrudOptions });
+
+onMounted(() => {
+  crudExpose.doRefresh();
+});
+</script>
+
+<style scoped></style>