Browse Source

no message

kllay 1 day ago
parent
commit
0662422aff

+ 1 - 59
src/views/system/device/crud.tsx

@@ -5,44 +5,6 @@ import { uploadFile } from './api';
 import { auth } from '/@/utils/authFunction';
 import { commonCrudConfig } from '/@/utils/commonCrud';
 
-export async function uploadRequestHandler(file: any) {
-	const formData = new FormData();
-	formData.append('image', file.file);
-  
-	const res = await uploadFile(formData);
-  
-	// ✅ 提取相对路径
-	const relativeUrl = res?.data?.image_url;
-	if (!relativeUrl) {
-		throw new Error('上传接口未返回 image_url');
-	}
-  
-	// ✅ 拼接完整 URL(根据你的服务器地址)
-	const baseUrl = import.meta.env.VITE_API_URL || 'http://58.34.94.147:8086/';
-	// const fullUrl = baseUrl.replace(/\/$/, '') + '/' + relativeUrl.replace(/^\//, '');
-	const fullUrl= "http://58.34.94.147:8086/media/files/3/c/3c711548de2284d59922379243a60bd8.png";
-  
-	
-	// ✅ 构造 response 对象,确保包含 url 字段
-	const response = {
-		url: fullUrl,
-		name: file.file.name,
-		...res.data
-	};
-
-	// ✅ 设置 file 对象
-	file.value = fullUrl;
-	file.url = fullUrl;
-	file.response = response;
-	file.fsRes = response;
-	// eslint-disable-next-line no-console
-	console.log('上传返回 response:', response);
-
-
-	return response;
-  }
-  
-
 
 export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
 	const pageRequest = async (query: UserPageQuery) => {
@@ -223,26 +185,6 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					form: {
 						component: { placeholder: '请输入是否可见' }
 					}
-					// type:"dict-radio",
-					// column: { 
-					// 	minWidth: 100,
-					// 	component: {
-					// 		name: 'fs-dict-switch',
-					// 		activeText: '',
-					// 		inactiveText: '',
-					// 		style: '--el-switch-on-color: var(--el-color-primary); --el-switch-off-color: #dcdfe6',
-					// 		onChange: compute((context) => {
-					// 			return () => {
-					// 				api.UpdateObj(context.row).then((res: APIResponseData) => {
-					// 					successMessage(res.msg as string);
-					// 				});
-					// 			};
-					// 		}),
-					// 	},
-					// },
-					// dict: dict({
-					// 	value: dictionary('button_device_is_visible'),
-					// }),
 
 				},
 				
@@ -333,7 +275,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 								type: 'form',
 								limit: 1,
 								accept: ".jpg,.png",
-								uploadRequest: uploadRequestHandler,
+								// uploadRequest: uploadRequestHandler,
 								// uploadRequest: async (file) => {
 								// // eslint-disable-next-line no-console
 								// // console.log("files::",file);

+ 27 - 14
src/views/system/deviceclass/crud.tsx

@@ -1,4 +1,4 @@
-import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery } from '@fast-crud/fast-crud';
+import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet,dict, UserPageQuery } from '@fast-crud/fast-crud';
 import * as api from './api';
 import { auth } from '/@/utils/authFunction';
 
@@ -22,17 +22,6 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 		return await api.AddObj(form);
 	};
 
-	/**
-	 * 懒加载
-	 * @param row
-	 * @returns {Promise<unknown>}
-	 */
-	// const loadContentMethod = (tree: any, treeNode: any, resolve: Function) => {
-	// 	pageRequest({ pcode: tree.code }).then((res: APIResponseData) => {
-	// 		resolve(res.data);
-	// 	});
-	// };
-
 	return {
 		crudOptions: {
 			request: {
@@ -40,6 +29,21 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 				addRequest,
 				getDetail,
 			},
+			toolbar:{
+				show:false,
+			},
+			rowHandle:{
+				buttons:{
+					remove:{
+						show:false,
+					},
+					edit:{
+						show:false,
+					}
+
+				}
+
+			},
 			actionbar: {
 				buttons: {
 					add: {
@@ -100,7 +104,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					},
 					form: {
 						component: { placeholder: '请填写设备描述' },
-						rules: [{ required: true, message: '请填写设备描述' }],
+						rules: [{ required: false, message: '请填写设备描述' }],
 					},
 				},
 				parent:{
@@ -127,10 +131,16 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 				},
 				status:{
 					title: '状态',
-					type: 'input',
+					type: 'dict-select',
 					column: {
 						minWidth: 120,
 					},
+					dict: dict({
+						data: [
+							{ label: '启用', value: true },
+							{ label: '禁用', value: false },
+						],
+					}),
 					form: {
 						component: { placeholder: '请填写状态' },
 						rules: [{ required: true, message: '请填写状态' }],
@@ -139,10 +149,13 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 				tenant:{
 					title: '租户',
 					type: 'input',
+					value: 1,
 					column: {
+						show:false,
 						minWidth: 120,
 					},
 					form: {
+						show:false,
 						component: { placeholder: '请填写租户' },
 						rules: [{ required: false, message: '请填写租户' }],
 					},

+ 15 - 11
src/views/system/devicelabel/crud.tsx

@@ -17,17 +17,6 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 		return await api.AddObj(form);
 	};
 
-	/**
-	 * 懒加载
-	 * @param row
-	 * @returns {Promise<unknown>}
-	 */
-	// const loadContentMethod = (tree: any, treeNode: any, resolve: Function) => {
-	// 	pageRequest({ pcode: tree.code }).then((res: APIResponseData) => {
-	// 		resolve(res.data);
-	// 	});
-	// };
-
 	return {
 		crudOptions: {
 			request: {
@@ -41,6 +30,21 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					},
 				},
 			},
+			toolbar:{
+				show:false,
+			},
+			rowHandle:{
+				buttons:{
+					remove:{
+						show:false,
+					},
+					edit:{
+						show:false,
+					}
+
+				}
+
+			},
 			pagination: {
 				show: false,
 			},		

+ 17 - 0
src/views/system/suppliermanage/crud.tsx

@@ -37,6 +37,21 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
                     }					
                 }
             },
+			rowHandle: {
+				fixed:'right',
+				width: 100,
+				buttons: {
+					view: {
+						type: 'text',
+					},
+					edit: {
+						show: false,
+					},
+					remove: {
+						show: false,
+					},
+				},
+			},
 			columns: {
 				_index: {
 					title: '序号',
@@ -186,6 +201,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					title: '租户id',
 					type: 'dict-select',
 					column: {
+						show:false,
 						minWidth: 120,
 					},
 					dict: dict({
@@ -201,6 +217,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 				status: {
 					title: '状态',
 					type: 'dict-select',
+					status:true,
 					search: { show: false },
 					dict: dict({
 						data: [

+ 165 - 0
src/views/system/timetablemanage/AdditionDialog/index.vue

@@ -0,0 +1,165 @@
+<template>
+  <el-dialog v-model="visible" :title="isEdit ? '编辑课程' : '添加课程'" width="500px">
+    <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
+      <el-form-item label="上课日期" prop="class_date">
+        <el-date-picker v-model="form.class_date" type="date" value-format="YYYY-MM-DD" />
+      </el-form-item>
+
+      <el-form-item label="时间段" prop="time">
+        <el-select v-model="form.time" placeholder="选择时间段">
+          <el-option label="上午" :value="1" />
+          <el-option label="下午" :value="2" />
+          <el-option label="晚上" :value="3" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="课程名称" prop="classdetail">
+        <el-input v-model="form.classdetail" />
+      </el-form-item>
+
+      <el-form-item label="教师" prop="teacher">
+      <el-select v-model="form.teacher" placeholder="请选择教师">
+        <el-option
+          v-for="teacher in teacherList"
+          :key="teacher.id"
+          :label="teacher.name"
+          :value="teacher.id"
+        />
+      </el-select>
+    </el-form-item>
+
+
+      <el-form-item label="学期" prop="semester">
+        <el-input-number v-model="form.semester" :min="1" />
+      </el-form-item>
+
+      <el-form-item label="年级" prop="grade">
+        <el-input-number v-model="form.grade" :min="1" />
+      </el-form-item>
+
+      <el-form-item label="班级编码" prop="class_number">
+        <el-input-number v-model="form.class_number" :min="1" :max="10" />
+      </el-form-item>
+
+      <el-form-item label="教室" prop="classroom">
+        <el-input v-model="form.classroom" />
+      </el-form-item>
+
+      <el-form-item label="总课时" prop="total_lessons">
+        <el-input-number v-model="form.total_lessons" :min="1" />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button @click="close">取消</el-button>
+      <el-button type="primary" @click="save">保存</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, defineExpose,onMounted } from 'vue';
+import {AddObj,getTeacherList,UpdateObj} from '../api';
+import { ElMessage } from 'element-plus';
+
+const teacherList = ref<any[]>([]);
+const emit = defineEmits(['saved']);
+async function fetchTeachers() {
+  const result = await getTeacherList();
+  teacherList.value = result.data;
+}
+
+onMounted(() => {
+  fetchTeachers(); 
+});
+
+
+const formRef = ref();
+const rules = {
+  class_date: [
+    { required: true, message: '请选择上课日期', trigger: 'change' },
+  ],
+  teacher: [
+    { required: true, message: '请选择老师', trigger: 'change' },
+  ],
+  classdetail: [
+    { required: true, message: '请填写课程名称', trigger: 'change' },
+  ],
+  classroom: [
+    { required: true, message: '请填写教室', trigger: 'change' },
+  ],
+};
+
+
+const visible = ref(false);
+const isEdit = ref(false);
+const form = ref({
+  class_date: '',
+  time: 1,
+  classdetail: '',
+  teacher: null,
+  semester: 1,
+  grade: 1,
+  class_number: 1,
+  classroom: '',
+  total_lessons: 48
+});
+
+function open(data?: any) {
+  if (data) {
+    form.value = { ...data };
+    isEdit.value = true;
+  } else {
+    form.value = {
+      class_date: '',
+      time: 1,
+      classdetail: '',
+      teacher: null,
+      semester: 1,
+      grade: 1,
+      class_number: 1,
+      classroom: '',
+      total_lessons: 48
+    };
+    isEdit.value = false;
+  }
+  visible.value = true;
+}
+
+function close() {
+  visible.value = false;
+}
+
+async function save() {
+  try {
+    formRef.value?.validate(async (valid: boolean) => {
+      if (valid) {
+      const isEdit = !!form.value.id;
+      // eslint-disable-next-line no-console
+      console.log('保存课程:', form.value);
+      if (isEdit) {
+          await UpdateObj(form.value);
+      }else{
+          await AddObj(form.value); 
+      }
+      visible.value = false;
+      ElMessage.success(isEdit ? '编辑成功' : '创建成功');
+      emit('saved');
+      }else {
+        ElMessage.success('表单校验未通过!');
+      }
+    });
+  } catch (error) {
+      // eslint-disable-next-line no-console
+      console.error('保存失败', error);
+      ElMessage.error('保存失败!');
+  }
+}
+
+
+
+defineExpose({ open });
+
+
+
+</script>

+ 37 - 50
src/views/system/timetablemanage/api.ts

@@ -1,10 +1,12 @@
 import { AddReq, UserPageQuery } from '@fast-crud/fast-crud';
 import { request } from '/@/utils/service';
 
-export const apiPrefix = '/api/system/manageclass/';
+export const apiPrefix = '/api/system/manageclass/week_schedule/';
+export const apiTimetable='/api/system/manageclass/';
+
 export function GetList(query: UserPageQuery) {
 	return request({
-		url: apiPrefix+'?user_type=1',
+		url: apiPrefix+'?week_offset=1',
 		method: 'get',
 		params: query,
 	});
@@ -18,19 +20,26 @@ export function GetObj(id: InfoReq) {
 
 export function AddObj(obj: AddReq) {
 	return request({
-		url: apiPrefix,
+		url: apiTimetable,
 		method: 'post',
 		data: obj,
 	});
 }
 
-// export function UpdateObj(obj: EditReq) {
-// 	return request({
-// 		url: apiPrefix + obj.id + '/',
-// 		method: 'put',
-// 		data: obj,
-// 	});
-// }
+export function UpdateObj(obj: EditReq) {
+	return request({
+		url: apiTimetable + obj.id + '/',
+		method: 'put',
+		data: obj,
+	});
+}
+
+export function getTeacherList(){
+	return request({
+        url: '/api/system/app_user/?user_type=1',
+        method: 'get',
+    });
+}
 
 // export function DelObj(id: DelReq) {
 // 	return request({
@@ -39,54 +48,32 @@ export function AddObj(obj: AddReq) {
 // 		data: { id },
 // 	});
 // }
-export function GetPermission() {
+export function GetPermission(week_offset:number) {
+
     return request({
-        url: apiPrefix,
+        url: apiPrefix +"?week_offset="+week_offset,
         method: 'get',
     });
 }
 
 
-  export async function getScheduleData(weekNum: number): Promise<any[]> {
-	const result = await GetPermission()
-	const rawList = result.data 
-  
-	// 初始化课表结构:10 节课 × 7 天
-	const table: any[] = Array.from({ length: 10 }, (_, i) => ({
-		id: i + 1,
-		day1: '',
-		day2: '',
-		day3: '',
-		day4: '',
-		day5: '',
-		day6: '',
-		day7: ''
-	}))
-  
-	// 映射 weekday(星期一到星期日)为 day1~day7
-	const dayMap: Record<number, string> = {
-		1: 'day1',
-		2: 'day2',
-		3: 'day3',
-		4: 'day4',
-		5: 'day5',
-		6: 'day6',
-		7: 'day7'
-	}
-  
-	// 填充课程内容
-	for (const item of rawList) {
-		const dayKey = dayMap[item.datetime] 
-		const periodIndex = item.class_number - 1 
-		const content = `${item.classdetail} (${item.teacher_name}) 班级:${item.classroom}`
-  
-		if (table[periodIndex] && dayKey) {
-			table[periodIndex][dayKey] = content
+export async function getScheduleData(result:object): Promise<any[]> {
+	const schedule = result.data.schedule;
+	const timeLabels = result.data.time_labels; 
+	const weekDays = ['day1', 'day2', 'day3', 'day4', 'day5', 'day6', 'day7'];
+
+	const table: any[] = timeLabels.map((label, timeIndex) => {
+		const row: any = { timeLabel: label };
+		for (let day = 1; day <= 7; day++) {
+		const classes = schedule[day]?.[timeIndex + 1] || [];
+			row[`day${day}`] = classes;
 		}
-	}
+		return row;
+	});
+  
+	return table;
+  }
   
-	return table
-  } 
 
   
   

+ 148 - 73
src/views/system/timetablemanage/index.vue

@@ -8,56 +8,59 @@
 				<span class="week-display">{{ displayWeek }} 周</span>
 				<el-button type="primary" icon="el-icon-arrow-right" @click="nextWeek" circle
 							:disabled="currentWeek + weekOffset >= totalWeeks" >></el-button>
+
+				</div>
+				<div>
+					<el-button type="success" icon="el-icon-plus" @click="openDialog()">添加课程</el-button>
 				</div>
+
 			</div>
 
-				<el-table
-				:data="scheduleData"
-				style="width: 100%; background-color: white"
-				:header-cell-style="headerStyle"
+			<el-table :data="scheduleData" style="width: 100%; background-color: white" :header-cell-style="headerStyle">
+			
+			<el-table-column label="时间段" width="100">
+				<template #default="scope">
+				{{ scope.row.timeLabel }}
+				</template>
+			</el-table-column>
+			<!-- 星期一至星期日列 -->
+			<el-table-column
+				v-for="(day, index) in weekDates"
+				:key="index"
+				:label="day"
+				min-width="160"
+			>
+			<template #default="scope">
+				<div
+					:style="{
+					backgroundColor: columnColorMap[index],
+					padding: '6px',
+					borderRadius: '4px',
+					whiteSpace: 'pre-line',
+					minHeight: '40px'
+					}"
 				>
-				<!-- 节次列 -->
-				<el-table-column label="节次" width="80">
-					<template #default="scope">
-					{{ getPeriodLabel(scope.$index) }}
-					</template>
-				</el-table-column>
-
-				<!-- 时间段列 -->
-				<el-table-column label="时间" width="140">
-					<template #default="scope">
-					{{ getTimeSlot(scope.$index) }}
-					</template>
-				</el-table-column>
-
-				<!-- 周一至周日列 -->
-				<el-table-column
-					v-for="(day, index) in weekDates"
-					:key="index"
-					:label="day"
-					min-width="120">
-					<template #default="scope">
-						<div
-						:style="{
-							backgroundColor: columnColorMap[index],
-							padding: '6px',
-							borderRadius: '4px',
-							minHeight: '40px'
-						}"
-						>
-						{{ getSchedule(scope.row, index) }}
-
-						</div>
-
-					</template>
-				</el-table-column>
-
-				</el-table>
+					<div
+					v-for="course in scope.row[`day${index + 1}`]"
+					:key="course.id"
+					style="margin-bottom: 4px; cursor: pointer"
+					@click.stop="openDialogEdit(course)"
+					>
+						{{ course.classdetail }} 老师:({{ course.teacher_name }}) 班级:{{ course.classroom }}
+					</div>
+				</div>
+			</template>
+
+			</el-table-column>
+			</el-table>
+
 
 
 
 		</div>
 		<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
+
+		<AdditionDialog ref="dialogRef" @saved="loadData"  />
 		
 	</fs-page>
 </template>
@@ -73,6 +76,7 @@ import { computed, onMounted, ref } from 'vue';
 import { GetPermission,getScheduleData } from './api';
 import { createCrudOptions } from './crud';
 import { handleColumnPermission } from '/@/utils/columnPermission';
+import AdditionDialog from './AdditionDialog/index.vue';
 
 
 
@@ -100,16 +104,95 @@ const columnColorMap: string[] = [
 
 
 
+const timeLabels = ref<string[]>([]); // 从接口获取
+
+function getTimeSlot(index: number): string {
+  return timeLabels.value[index] || '—';
+}
+
+function getPeriodLabel(index: number): string {
+  return `时间段`;
+}
+
+
 const displayWeek = computed(() => currentWeek.value + weekOffset.value)
 
 
-const weekDates = computed(() => {
-  const monday = dayjs().startOf('isoWeek').add(weekOffset.value, 'week')
-  return Array.from({ length: 7 }, (_, i) => {
-    const date = monday.add(i, 'day')
-    return `${['周一','周二','周三','周四','周五','周六','周日'][i]} (${date.format('MM.DD')})`
-  })
-})
+const dialogRef = ref();
+
+function openDialog(data?: any) {
+  dialogRef.value.open(data);
+}
+
+
+
+const selectedCourses = ref<any[]>([]);
+const courseSelectVisible = ref(false);
+
+function editCourse(course: any) {
+  courseSelectVisible.value = false;
+  openDialog(course);
+}
+
+
+function openDialogEdit(course?: any) {
+	// eslint-disable-next-line no-console
+	console.log('course:::::', course);
+	if (!course) {
+		// 新建
+		dialogRef.value.open({
+		class_date: dayjs().format('YYYY-MM-DD'),
+		time: 1,
+		class_number: 1
+		});
+	} else {	
+		dialogRef.value.open(course);
+	}
+}
+
+
+// function handleCellClick(row: any, dayIndex: number) {
+// 	const classText = row[`day${dayIndex + 1}`];
+// 	// eslint-disable-next-line no-console
+// 	console.log('classText:::::', classText);
+// 	const timeIndex = timeLabels.value.indexOf(row.timeLabel) + 1;
+// 	if (!classText || classText.length === 0) {
+// 		openDialog({
+//         class_date: dayjs().startOf('isoWeek').add(dayIndex, 'day').format('YYYY-MM-DD'),
+//         time: timeIndex,
+//       });
+// 	}
+// 	else if (classText.length === 1) {
+//       openDialog(classText[0]);
+//     } else {
+// 		selectedCourses.value = classText;
+// 		courseSelectVisible.value = true;
+//     }
+
+//   } else {
+
+//     openDialog({
+//       class_date: dayjs().startOf('isoWeek').add(dayIndex, 'day').format('YYYY-MM-DD'),
+//       time: timeLabels.value.indexOf(row.timeLabel) + 1,
+//       classdetail: '高等数学',
+//       teacher: 13,
+//       semester: 1,
+//       grade: 1,
+//       class_number: row.id,
+//       classroom: 'A101',
+//       total_lessons: 48
+//     });
+//   }
+// }
+
+
+// const weekDates = computed(() => {
+//   const monday = dayjs().startOf('isoWeek').add(weekOffset.value, 'week')
+//   return Array.from({ length: 7 }, (_, i) => {
+//     const date = monday.add(i, 'day')
+//     return `${['周一','周二','周三','周四','周五','周六','周日'][i]} (${date.format('MM.DD')})`
+//   })
+// })
 
 function nextWeek() {
   if (currentWeek.value + weekOffset.value < totalWeeks.value){
@@ -129,39 +212,31 @@ const headerStyle = {
   textAlign: 'center'              
 }
 
-const timeSlots = [
-  '08:15 - 08:55',
-  '09:00 - 09:40',
-  '09:50 - 10:30',
-  '10:40 - 11:20',
-  '11:25 - 12:05',
-  '13:30 - 14:10',
-  '14:20 - 15:00',
-  '15:10 - 15:50',
-  '16:00 - 16:40',
-  '16:50 - 17:30'
-]
-function getTimeSlot(index: number): string {
-  return timeSlots[index] || '—'
-}
 
 
-const periodLabels = [
-  '第一节', '第二节', '第三节', '第四节', '第五节',
-  '第六节', '第七节', '第八节', '第九节', '第十节'
-]
-function getPeriodLabel(index: number): string {
-  return periodLabels[index] || `第${index + 1}节`
-}
+// const periodLabels = [
+//   '第一节', '第二节', '第三节', '第四节', '第五节',
+//   '第六节', '第七节', '第八节', '第九节', '第十节'
+// ]
+// function getPeriodLabel(index: number): string {
+//   return periodLabels[index] || `第${index + 1}节`
+// }
 
 
 const scheduleData = ref<any[]>([])
+
+const weekDates = ref<string[]>([]);
+
 async function loadData() {
-  // eslint-disable-next-line no-console
-  console.log(currentWeek.value + weekOffset.value);
-  scheduleData.value = await getScheduleData(currentWeek.value + weekOffset.value)
+  const result = await GetPermission(weekOffset.value);
+  timeLabels.value = result.data.time_labels;
+  weekDates.value = result.data.week_labels_with_date;
+//   scheduleData.value = await getScheduleData(weekOffset.value);
+	scheduleData.value = await getScheduleData(result);
 }
 
+
+
 function getSchedule(row: any, index: number) {
   return row[`day${index + 1}`] || ''
 }