kllay vor 1 Tag
Ursprung
Commit
c8a0b0e3f2

+ 10 - 2
src/views/system/borrow/approval/curd.tsx

@@ -1,6 +1,7 @@
 import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery } from '@fast-crud/fast-crud';
 import * as api from './api';
 import { BorrowingReview, Switchspost } from './api';
+import { ElMessage } from 'element-plus';
 
 
 
@@ -48,8 +49,9 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 			toolbar:{show: false},
 			actionbar:{show:false},
 			rowHandle:{
+				fixed:'right',
+				width: 100,
 				show: true,
-				width: 330,
 				buttons: {
 					view: { show: false },
 					edit: { show: false },
@@ -60,9 +62,15 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					size: "small",
 					show: true,
 					click(context) {
+							// eslint-disable-next-line no-console
 						// console.log("click", context);
 						// alert(context);
-						BorrowingReview(1,'approve','同意借用');
+						try{
+							BorrowingReview(context.row.id,'approve','同意借用');
+							ElMessage.success('审判通过');
+						}catch(err){
+							ElMessage.error("系统错误!");
+						}
 					}
 				}
 				}

+ 115 - 37
src/views/system/borrow/component/ClassroomBorrow/index.vue

@@ -4,14 +4,20 @@
 			<div style="font-weight: bold; font-size: 18px; margin-bottom: 8px">课程信息</div>
 			<el-row :gutter="8" style="margin-bottom: 8px; align-items: center">
 				<el-col :span="6">
-					<el-select v-model="form.course_name" placeholder="请选择课程">
-						<el-option label="广告配音艺术" value="广告配音艺术" />
-						<!-- 这里可动态加载课程列表 -->
+					<el-select v-model="form.purpose" placeholder="请选择课程" @change="onCourseChange">
+						<el-option
+							v-for="course in weeklyCourses"
+							:key="course.id"
+							:label="`${course.classdetail} - ${course.teacher_name}`"
+							:value="course.classdetail"
+						/>
 					</el-select>
 				</el-col>
-				<el-col :span="3">
+				
+
+				<!-- <el-col :span="3">
 					<el-button>手动输入</el-button>
-				</el-col>
+				</el-col> -->
 				<el-col :span="6">
 					<el-input v-model="form.course_input" placeholder="请输入课程名称" />
 				</el-col>
@@ -19,10 +25,9 @@
 					<el-button type="primary">搜索</el-button>
 				</el-col>
 			</el-row>
-			<el-table :data="courseTableData" border style="width: 100%; margin-bottom: 12px">
-				<el-table-column prop="date" label="日期" />
-				<el-table-column v-for="col in courseTableCols" :key="col" :prop="col" :label="col" />
-			</el-table>
+			<div style="max-height: 400px; overflow-y: auto; border: 1px solid #eee; padding: 8px; margin-bottom:0px">
+				<timetablemanage />
+			</div>
 		</div>
 		<el-form :model="form" label-width="110px" label-position="top" :rules="rules" ref="formRef">
 			<el-row :gutter="16">
@@ -32,23 +37,23 @@
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
-					<el-form-item label="借用人" prop="borrower_name">
-						<el-input v-model="form.borrower_name" placeholder="请输入借用人" disabled />
+					<el-form-item label="借用人" prop="emergency_contact">
+						<el-input v-model="form.emergency_contact" placeholder="请输入借用人"  />
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
-					<el-form-item label="学号/工号" prop="user_code">
-						<el-input v-model="form.user_code" placeholder="请输入学号/工号" disabled />
+					<el-form-item label="学号/工号" prop="app_user_borrower">
+						<el-input v-model="form.app_user_borrower" placeholder="请输入学号/工号"  />
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
 					<el-form-item label="联系电话" prop="emergency_phone">
-						<el-input v-model="form.emergency_phone" placeholder="请输入联系电话" disabled />
+						<el-input v-model="form.emergency_phone" placeholder="请输入联系电话"  />
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
 					<el-form-item label="信用部门" prop="borrower_dept">
-						<el-input v-model="form.borrower_dept" placeholder="请输入信用部门" disabled />
+						<el-input v-model="form.borrower_dept" placeholder="请输入信用部门"  />
 					</el-form-item>
 				</el-col>
 				<el-col :span="4">
@@ -66,11 +71,16 @@
 						<el-input v-model="form.applicant_remark" placeholder="请输入备注" />
 					</el-form-item>
 				</el-col>
+				<el-col :span="8">
+					<el-form-item label="预计归还时间" prop="expected_end_time">
+						<el-date-picker v-model="form.expected_end_time" type="datetime" placeholder="请选择预计归还时间" style="width: 100%" />
+					</el-form-item>
+				</el-col>
 			</el-row>
 			<div style="margin: 16px 0 8px 0; font-weight: bold">借用明细表</div>
 			<el-table :data="form.items" border style="width: 100%; margin-bottom: 12px">
 				<el-table-column type="index" label="序号" width="60" />
-				<el-table-column prop="device_name" label="设备分类" />
+				<el-table-column prop="remark" label="设备分类" />
 				<el-table-column prop="quantity" label="借用数量" />
 				<el-table-column prop="location" label="存放仓库" />
 				<el-table-column label="操作" width="80">
@@ -95,48 +105,108 @@
 
 <script setup lang="ts">
 import { ref, watch, defineProps, defineEmits, onMounted, computed } from 'vue';
-import SelectDeviceDialog from '../CommonBorrow/SelectDeviceDialog/index.vue';
+import SelectDeviceDialog from '../SpecialBorrow/SelectDeviceDialog/index.vue';
+import timetablemanage from '../../../timetablemanage/index.vue';
+import * as apis from '../../../timetablemanage/api';
+import { provide } from 'vue';
+import dayjs from 'dayjs';
+import { ElMessage } from 'element-plus';
+
+
+provide('isEmbedded', true);
+provide('onCourseSelected', handleCourseSelected);
+
 const props = defineProps<{ visible: boolean; modelValue?: any }>();
 const emit = defineEmits(['update:visible', 'update:modelValue', 'submit']);
 const visible = ref(props.visible);
 const formRef = ref();
 
+
+function handleCourseSelected({ course_name, expected_start_time }) {
+  form.value.purpose = course_name;
+  form.value.expected_start_time = expected_start_time;
+}
+
+
+const weeklyCourses = ref<any[]>([]);
+
+async function fetchWeeklySchedule() {
+  const res = await apis.GetCurrentWeekList();
+  	// eslint-disable-next-line no-console
+	// console.log("res.data:::",res.data)
+  const schedule = res.data.schedule;
+
+  const courseMap = new Map<string, any>();
+
+  for (const dayKey in schedule) {
+    const daySchedule = schedule[dayKey];
+    for (const timeKey in daySchedule) {
+      const courses = daySchedule[timeKey];
+      for (const course of courses) {
+        if (!courseMap.has(course.classdetail)) {
+          courseMap.set(course.classdetail, course);
+        }
+      }
+    }
+  }
+
+  weeklyCourses.value = Array.from(courseMap.values());
+}
+
+function onCourseChange(selectedName: string) {
+  const selectedCourse = weeklyCourses.value.find(c => c.classdetail === selectedName);
+  if (selectedCourse) {
+    form.value.expected_start_time = `${selectedCourse.class_date} ${getStartTime(selectedCourse.time)}`;
+    form.value.teacher_name = selectedCourse.teacher_name;
+    form.value.classroom = selectedCourse.classroom;
+  }
+}
+
+function getStartTime(time: number): string {
+  const timeMap = {
+    1: '09:00',
+    2: '14:00',
+    3: '19:00'
+  };
+  return timeMap[time] || '09:00';
+}
+
+
+
+
 const form = ref({
 	application_no: '',
-	borrower_name: '',
+	emergency_contact: '',
+	purpose:'',
 	emergency_phone: '',
-	user_code: '',
+	app_user_borrower: 1,
 	borrower_dept: '',
-	team_members_count: '',
+	team_type: 1,
+	team_members_count: 1,
 	team_members: '',
+	expected_start_time:'',
+    expected_end_time: "",
 	applicant_remark: '',
+	return_location:'',
 	items: [],
-	course_name: '',
+	borrow_type:1,
 	course_input: '',
 });
 const showSelectDeviceDialog = ref(false);
 const isViewMode = computed(() => props.modelValue?.mode === 'view');
-// 课程表模拟数据
-const courseTableCols = ['08:00-08:45', '08:55-09:40', '09:50-10:35', '10:45-11:30', '11:40-12:25'];
-const courseTableData = [
-	{ date: '周一', '08:00-08:45': '', '08:55-09:40': '', '09:50-10:35': '', '10:45-11:30': '', '11:40-12:25': '' },
-	{ date: '周二', '08:00-08:45': '', '08:55-09:40': '', '09:50-10:35': '', '10:45-11:30': '', '11:40-12:25': '' },
-	{ date: '周三', '08:00-08:45': '', '08:55-09:40': '', '09:50-10:35': '', '10:45-11:30': '', '11:40-12:25': '' },
-	{ date: '周四', '08:00-08:45': '', '08:55-09:40': '', '09:50-10:35': '', '10:45-11:30': '', '11:40-12:25': '' },
-	{ date: '周五', '08:00-08:45': '', '08:55-09:40': '', '09:50-10:35': '', '10:45-11:30': '', '11:40-12:25': '' },
-];
-
-// 自动填充用户信息
+
+
 onMounted(() => {
 	try {
 		const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
 		if (userInfo) {
-			form.value.borrower_name = userInfo.username || '';
-			form.value.user_code = userInfo.dept_info?.dept_id || '';
+			form.value.emergency_contact = userInfo.username || '';
+			form.value.app_user_borrower = Number(userInfo.dept_info?.dept_id )|| 1;
 			form.value.emergency_phone = userInfo.mobile || '';
 			form.value.borrower_dept = userInfo.dept_info?.dept_name || '';
 		}
-	} catch (e) {}
+	} catch (e) {console.error(e)}
+	fetchWeeklySchedule();
 });
 
 watch(
@@ -157,9 +227,9 @@ function onDeviceSelected(devices) {
 	form.value.items.push(
 		...devices.map((d) => ({
 			device: d.id,
-			device_name: d.name,
+			remark: d.category_name,
 			quantity: 1,
-			location: d.location,
+			location: d.warehouse,
 		}))
 	);
 }
@@ -169,11 +239,19 @@ function removeItem(index) {
 function onCancel() {
 	emit('update:visible', false);
 }
+
+const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
 function onSave() {
 	formRef.value.validate((valid) => {
 		if (valid) {
+			const firstLocation = form.value.items[0]?.location || '';
+            form.value.return_location = firstLocation;
+			// form.value.expected_start_time = now;
+			form.value.expected_end_time = dayjs(form.value.expected_end_time).format('YYYY-MM-DD HH:mm:ss')|| now;
+			form.value.team_members_count=Number(form.team_members_count)||1;
 			emit('submit', { ...form.value });
 			emit('update:visible', false);
+			ElMessage.success("添加成功!");
 		}
 	});
 }

+ 3 - 1
src/views/system/borrow/component/SpecialBorrow/index.vue

@@ -100,6 +100,7 @@
 import { ref, watch, defineProps, defineEmits, onMounted } from 'vue';
 import SelectDeviceDialog from './SelectDeviceDialog/index.vue';
 import dayjs from 'dayjs';
+import { ElMessage } from 'element-plus';
 
 const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
 
@@ -194,7 +195,6 @@ function addItem() {
 	showSelectDeviceDialog.value = true;
 }
 function onDeviceSelected(devices) {
-	// 假设 form.value.items 已存在
 	form.value.items.push(
 		...devices.map((d) => ({
 			device: d.id,
@@ -220,8 +220,10 @@ function onSubmit() {
 			form.team_members_count=Number(form.team_members_count)||1;
 			emit('submit', { ...form.value });
 			emit('update:visible', false);
+			ElMessage.success("添加成功!");
 		}
 	});
+	
 }
 
 </script>

+ 0 - 36
src/views/system/borrow/workflow/WorkflowDialog/index.vue

@@ -71,11 +71,6 @@
 							:value="item.id"
 						/>
 						</el-select>
-
-						<!-- <el-select v-model="form.condition.equipment" placeholder="请选择">
-							<el-option label="贵重设备" value="贵重设备" />
-							<el-option label="普通设备" value="普通设备" />
-						</el-select> -->
 					</el-form-item>
 				</el-col>
 				<el-col :span="8">
@@ -430,37 +425,6 @@ async function onSave() {
 	await api.AddFirstObj(stepPayload);
 	}
 
-
-
-	// const selectedRoleNames = form.steps
-    // .flatMap(step => step.roles.map(role => role.name))
-    // .filter(name => !!name);
-	// const selectedPassTypes = form.steps
-	// .flatMap(step => step.roles.map(role => role.passType));
-
-	// //组装审核接口
-	// const firstpayload={
-	// 	workflow: String(workflowId),
-	// 	step_name: String(selectedRoleNames),
-	// 	step_order: 1,
-	// 	step_type: String(selectedPassTypes),
-	// 	description:"由指导老师进行初审",
-	// 	approvers: [1],  // 指定审核人ID列表,可选
-	// 	approver_roles: [1],  // 审核角色ID列表,可选
-	// 	approver_depts: [],  // 审核部门ID列表,可选
-	// 	approval_conditions: {  // 审核条件,可以为空
-	// 		required_fields: [],  // 必填字段
-	// 		value_ranges: {}  // 字段值范围限制
-	// 	},
-	// 	timeout_hours: 24,  // 超时时间(小时)
-	// 	timeout_action: "auto_reject",  // 超时处理:auto_approve=自动通过,auto_reject=自动拒绝,escalate=升级处理
-	// 	is_active: true  // 是否启用:true=启用,false=禁用
-
-	// };
-	// // eslint-disable-next-line no-console
-	// console.log(firstpayload);
-	// await api.AddFirstObj(firstpayload);
-
 	ElMessage.success('保存成功');
 	emit('success');
 	visible.value = false;

+ 9 - 0
src/views/system/device/api.ts

@@ -34,6 +34,15 @@ export function UpdateObj(obj: EditReq) {
 	});
 }
 
+
+export function UpdateObjStatus(obj: EditReq) {
+	return request({
+		url: apiPrefix + obj.id + '/change_status/',
+		method: 'post',
+		data: obj
+	});
+}
+
 export function DelObj(id: DelReq) {
 	return request({
 		url: apiPrefix + id + '/',

+ 52 - 26
src/views/system/device/crud.tsx

@@ -142,21 +142,43 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 						rules: [{ required: true, message: '请输入设备名称' }]
 					}
 				},
-				status: {
-					title: '设备状态',
-					type: 'dict-select',
-					search: { show: false },
-					dict: dict({
-						data: [
-							{ label: '在借', value: 1 },
-							{ label: '空闲', value: 2 },
-						],
-					}),
-					column: { minWidth: 100 },
-					form: {
-						component: { placeholder: '请选择设备状态' },
-						rules: [{ required: true, message: '请选择设备状态' }],
-					},
+				// statusss: {
+				// 	title: '设备状态',
+				// 	type: 'dict-select',
+				// 	search: { show: false },
+				// 	dict: dict({
+				// 		data: [
+				// 			{ label: '在借', value: 1 },
+				// 			{ label: '空闲', value: 2 },
+				// 		],
+				// 	}),
+				// 	column: { minWidth: 100 },
+				// 	form: {
+				// 		component: { placeholder: '请选择设备状态' },
+				// 		rules: [{ required: true, message: '请选择设备状态' }],
+				// 	},
+				// },
+				"inventory.borrowed_quantity":{
+						title: '设备状态',
+						type: 'dict-select',
+						search: { show: false },
+						dict: dict({
+							data: [
+								{ label: '在借', value: 1 },
+								{ label: '空闲', value: 0 },
+							],
+							getData: (dict) => {
+								return (value) => {
+									return value > 0 ? '在借' : '空闲';
+								}
+							}
+						}),
+						column: { show:true, minWidth: 100 },
+						form: {
+							show:false,
+							component: { placeholder: '请选择设备状态' },
+							rules: [{ required: true, message: '请选择设备状态' }],
+						},
 				},
 				borrowed_quantity:{
 					title:"已借出",
@@ -219,9 +241,9 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 						component: { placeholder: '请选择库存仓库' }
 					}
 				},
-				is_visible:{
+				status:{
 					title:'是否可见',
-					type: 'dict-radio',
+					type: 'dict-switch',
 					column: {
 						minWidth: 90,
 						component: {
@@ -231,7 +253,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 							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) => {
+									api.UpdateObjStatus(context.row).then((res:APIResponseData) => {
 										successMessage(res.msg as string);
 									});
 								};
@@ -239,7 +261,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 						},
 					},
 					dict: dict({
-						data: dictionary('button_status_bool'),
+						data: dictionary('device_button_status_bool'),
 					}),
 
 				},
@@ -362,17 +384,21 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 										...ret.data
 									};
 								},
-								valueBuilder({ row, key }) {
-									return row[key] ? [row[key]] : [];
-								},
-								valueResolve({ form, key }) {
-									form[key] = Array.isArray(form[key]) ? form[key][0] : form[key];
-								}
+							
 								
 
 								
 							}
-						}
+						},
+						
+					},
+					valueBuilder({ row, key }) {
+						return row[key] ? [row[key]] : [];
+					},
+					valueResolve({ form, key }) {
+						// eslint-disable-next-line no-console
+						console.log("form[key]:::",form[key]);
+						form[key] = Array.isArray(form[key]) ? form[key][0] : form[key];
 					}
 					// form: {
 					// 	// component: { placeholder: '请上传图片' },

+ 8 - 1
src/views/system/timetablemanage/api.ts

@@ -6,7 +6,7 @@ export const apiTimetable='/api/system/manageclass/';
 
 export function GetList(query: UserPageQuery) {
 	return request({
-		url: apiPrefix+'?week_offset=1',
+		url: apiPrefix+'?week_offset=0',
 		method: 'get',
 		params: query,
 	});
@@ -34,6 +34,13 @@ export function UpdateObj(obj: EditReq) {
 	});
 }
 
+export function GetCurrentWeekList() {
+	return request({
+		url: apiPrefix+'?week_offset=0',
+		method: 'get',
+	});
+}
+
 export function getTeacherList(){
 	return request({
         url: '/api/system/app_user/?user_type=1',

+ 44 - 14
src/views/system/timetablemanage/index.vue

@@ -1,5 +1,6 @@
 <template>
-	<fs-page>
+	<!-- <fs-page> -->
+		<div>
 	
 		<div class="schedule-wrapper">
 			<div class="header">
@@ -44,7 +45,7 @@
 					v-for="course in scope.row[`day${index + 1}`]"
 					:key="course.id"
 					style="margin-bottom: 4px; cursor: pointer"
-					@click.stop="openDialogEdit(course)"
+					@click.stop="openDialogEdit(course, scope.row.timeLabel, index)"
 					>
 						{{ course.classdetail }} 老师:({{ course.teacher_name }}) 班级:{{ course.classroom }}
 					</div>
@@ -62,7 +63,8 @@
 
 		<AdditionDialog ref="dialogRef" @saved="loadData"  />
 		
-	</fs-page>
+	<!-- </fs-page> -->
+   </div>
 </template>
 
 <script lang="ts" setup name="timetablemanage">
@@ -77,6 +79,10 @@ import { GetPermission,getScheduleData } from './api';
 import { createCrudOptions } from './crud';
 import { handleColumnPermission } from '/@/utils/columnPermission';
 import AdditionDialog from './AdditionDialog/index.vue';
+import { inject } from 'vue';
+
+const isEmbedded = inject('isEmbedded', false);
+const onCourseSelected = inject('onCourseSelected', () => {});
 
 
 
@@ -135,21 +141,45 @@ function editCourse(course: any) {
 }
 
 
-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 {	
+// 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 openDialogEdit(course?: any, timeLabel?: string, dayIndex?: number) {
+  const courseName = course?.classdetail || '';
+  const dateLabel = weekDates.value[dayIndex]; 
+  const dateMatch = dateLabel.match(/\d{4}-\d{2}-\d{2}/);
+  const dateStr = dateMatch ? dateMatch[0] : dayjs().format('YYYY-MM-DD');
+  const timeStr = timeLabel?.split('-')[0] || '09:00';
+  const expectedStartTime = `${dateStr} ${timeStr}:00`;
+
+  if (isEmbedded && typeof onCourseSelected === 'function') {
+	try {
+      onCourseSelected({
+		course_name: courseName,
+		expected_start_time: expectedStartTime
+      	});
 		dialogRef.value.open(course);
-	}
+    } catch (e) {
+      console.warn('onCourseSelected failed:', e);
+    }
+  } else {
+    dialogRef.value.open(course);
+  }
 }
 
 
+
 function nextWeek() {
   if (currentWeek.value + weekOffset.value < totalWeeks.value){
 	weekOffset.value++;