完善部分设备管理
This commit is contained in:
parent
440117b417
commit
09f7175f82
|
|
@ -14,3 +14,9 @@ export function getWorkbench() {
|
|||
export function getDictData(params: any) {
|
||||
return request.get({ url: '/config/dict', params })
|
||||
}
|
||||
|
||||
// 真的字典数据
|
||||
export function getDictList(params: any) {
|
||||
return request.get({ url: '/setting.dict.dict_data/lists', params })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 资产信息列表
|
||||
export function infoLists(params?: Record<string, any>) {
|
||||
return request.get({ url: '/info/list', params })
|
||||
}
|
||||
|
||||
// 资产信息详情
|
||||
export function infoDetail(params: Record<string, any>) {
|
||||
return request.get({ url: '/info/detail', params })
|
||||
}
|
||||
|
||||
// 资产信息新增
|
||||
export function infoAdd(params: Record<string, any>) {
|
||||
return request.post({ url: '/info/add', params })
|
||||
}
|
||||
|
||||
// 资产信息编辑
|
||||
export function infoEdit(params: Record<string, any>) {
|
||||
return request.post({ url: '/info/edit', params })
|
||||
}
|
||||
|
||||
// 资产信息删除
|
||||
export function infoDelete(params: Record<string, any>) {
|
||||
return request.post({ url: '/info/del', params })
|
||||
}
|
||||
|
|
@ -37,5 +37,5 @@ export function taskCourseList(params: Record<string, any>) {
|
|||
|
||||
// 班级教学任务教师列表
|
||||
export function taskTeacherList(params: Record<string, any>) {
|
||||
return request.get({ url: '/task', params })
|
||||
return request.get({ url: '/task/teacher', params })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ export function timeCurrentSemester() {
|
|||
return request.get({ url: '/time/currentSemester' })
|
||||
}
|
||||
|
||||
// 获取下一学期信息
|
||||
export function timeNextSemester() {
|
||||
return request.get({ url: '/time/nextSemester' })
|
||||
}
|
||||
|
||||
// 获取刷新配置
|
||||
export function timeRefreshConfig() {
|
||||
return request.get({ url: '/time/refreshConfig' })
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { reactive, toRaw } from 'vue'
|
||||
|
||||
import { getDictData } from '@/api/app'
|
||||
import { getDictList } from '@/api/app'
|
||||
|
||||
interface Options {
|
||||
[propName: string]: {
|
||||
|
|
@ -51,13 +51,13 @@ export function useDictOptions<T = any>(options: Options) {
|
|||
// dict: any[]
|
||||
// }>(['dict'])
|
||||
|
||||
export function useDictData<T = any>(dict: string) {
|
||||
export function useDictData<T = any>(id: number) {
|
||||
const dictData: any = reactive({})
|
||||
const refresh = async () => {
|
||||
const data = await getDictData({
|
||||
type: dict
|
||||
const data = await getDictList({
|
||||
type_id: id
|
||||
})
|
||||
Object.assign(dictData, data)
|
||||
Object.assign(dictData, data.lists)
|
||||
}
|
||||
refresh()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
<template>
|
||||
<div class="edit-popup">
|
||||
<popup
|
||||
ref="popupRef"
|
||||
:title="popupTitle"
|
||||
:async="true"
|
||||
width="550px"
|
||||
:clickModalClose="true"
|
||||
@confirm="handleSubmit"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
|
||||
<el-form-item label="唯一标识" prop="id">
|
||||
<el-input v-model="formData.id" placeholder="请输入唯一标识" />
|
||||
</el-form-item>
|
||||
<el-form-item label="资产名称" prop="assetName">
|
||||
<el-input v-model="formData.assetName" placeholder="请输入资产名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="model">
|
||||
<el-input v-model="formData.model" placeholder="请输入规格型号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input v-model="formData.brand" placeholder="请输入品牌" />
|
||||
</el-form-item>
|
||||
<el-form-item label="资产类别" prop="category">
|
||||
<el-input v-model="formData.category" placeholder="请输入资产类别" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否为固定资产" prop="isFixedAsset">
|
||||
<el-input v-model="formData.isFixedAsset" placeholder="请输入是否为固定资产" />
|
||||
</el-form-item>
|
||||
<el-form-item label="非固定资产库存信息ID" prop="consumableId">
|
||||
<el-input v-model="formData.consumableId" placeholder="请输入非固定资产库存信息ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="资产描述" prop="description">
|
||||
<el-input
|
||||
v-model="formData.description"
|
||||
placeholder="请输入资产描述"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</popup>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { infoEdit, infoAdd, infoDetail } from '@/api/asset/info'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
import type { PropType } from 'vue'
|
||||
defineProps({
|
||||
dictData: {
|
||||
type: Object as PropType<Record<string, any[]>>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['success', 'close'])
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
||||
const mode = ref('add')
|
||||
const popupTitle = computed(() => {
|
||||
return mode.value == 'edit' ? '编辑资产信息' : '新增资产信息'
|
||||
})
|
||||
|
||||
const formData = reactive({
|
||||
id: '',
|
||||
assetName: '',
|
||||
model: '',
|
||||
brand: '',
|
||||
category: '',
|
||||
isFixedAsset: '',
|
||||
consumableId: '',
|
||||
description: '',
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
id: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入唯一标识',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
assetName: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入资产名称',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
model: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入规格型号',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
brand: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入品牌',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
category: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入资产类别',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
isFixedAsset: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入是否为固定资产',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
consumableId: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入非固定资产库存信息ID',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await formRef.value?.validate()
|
||||
const data: any = { ...formData }
|
||||
mode.value == 'edit' ? await infoEdit(data) : await infoAdd(data)
|
||||
popupRef.value?.close()
|
||||
feedback.msgSuccess('操作成功')
|
||||
emit('success')
|
||||
}
|
||||
|
||||
const open = (type = 'add') => {
|
||||
mode.value = type
|
||||
popupRef.value?.open()
|
||||
}
|
||||
|
||||
const setFormData = async (data: Record<string, any>) => {
|
||||
for (const key in formData) {
|
||||
if (data[key] != null && data[key] != undefined) {
|
||||
//@ts-ignore
|
||||
formData[key] = data[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getDetail = async (row: Record<string, any>) => {
|
||||
const data = await infoDetail({
|
||||
id: row.id
|
||||
})
|
||||
setFormData(data)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
setFormData,
|
||||
getDetail
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
<template>
|
||||
<div class="index-lists">
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||
<el-form-item label="资产名称" prop="assetName">
|
||||
<el-input class="w-[280px]" v-model="queryParams.assetName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="model">
|
||||
<el-input class="w-[280px]" v-model="queryParams.model" />
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input class="w-[280px]" v-model="queryParams.brand" />
|
||||
</el-form-item>
|
||||
<el-form-item label="资产类别" prop="category">
|
||||
<el-select
|
||||
v-model="queryParams.category"
|
||||
class="w-[280px]"
|
||||
clearable
|
||||
>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option
|
||||
v-for="(item, index) in dictData.asset_classification"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否为固定资产" prop="isFixedAsset">
|
||||
<el-input class="w-[280px]" v-model="queryParams.isFixedAsset" />
|
||||
</el-form-item>
|
||||
<el-form-item label="非固定资产库存信息ID" prop="consumableId">
|
||||
<el-input class="w-[280px]" v-model="queryParams.consumableId" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||
<el-button @click="resetParams">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never">
|
||||
<div>
|
||||
<el-button v-perms="['info:add']" type="primary" @click="handleAdd()">
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
新增
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
class="mt-4"
|
||||
size="large"
|
||||
v-loading="pager.loading"
|
||||
:data="pager.lists"
|
||||
>
|
||||
<el-table-column label="资产名称" prop="assetName" min-width="100" />
|
||||
<el-table-column label="规格型号" prop="model" min-width="100" />
|
||||
<el-table-column label="品牌" prop="brand" min-width="100" />
|
||||
<el-table-column label="资产类别" prop="category" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<dict-value :options="dictData.asset_classification" :value="row.category" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否为固定资产" prop="isFixedAsset" min-width="100" />
|
||||
<el-table-column label="非固定资产库存信息ID" prop="consumableId" min-width="100" />
|
||||
<el-table-column label="资产描述" prop="description" min-width="100" />
|
||||
<el-table-column label="记录创建时间" prop="createdTime" min-width="100" />
|
||||
<el-table-column label="最后更新时间" prop="updatedTime" min-width="100" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-perms="['info:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-perms="['info:del']"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex justify-end mt-4">
|
||||
<pagination v-model="pager" @change="getLists" />
|
||||
</div>
|
||||
</el-card>
|
||||
<edit-popup
|
||||
v-if="showEdit"
|
||||
ref="editRef"
|
||||
:dict-data="dictData"
|
||||
@success="getLists"
|
||||
@close="showEdit = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup name="info">
|
||||
import { infoDelete, infoLists } from '@/api/asset/info'
|
||||
import { useDictData } from '@/hooks/useDictOptions'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
import EditPopup from './edit.vue'
|
||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||
const showEdit = ref(false)
|
||||
const queryParams = reactive({
|
||||
assetName: '',
|
||||
model: '',
|
||||
brand: '',
|
||||
category: '',
|
||||
isFixedAsset: '',
|
||||
consumableId: '',
|
||||
})
|
||||
|
||||
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||
fetchFun: infoLists,
|
||||
params: queryParams
|
||||
})
|
||||
|
||||
const { dictData } = useDictData<{
|
||||
asset_classification: any[]
|
||||
}>(7)
|
||||
|
||||
|
||||
const handleAdd = async () => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('add')
|
||||
}
|
||||
|
||||
const handleEdit = async (data: any) => {
|
||||
showEdit.value = true
|
||||
await nextTick()
|
||||
editRef.value?.open('edit')
|
||||
editRef.value?.getDetail(data)
|
||||
}
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
await feedback.confirm('确定要删除?')
|
||||
await infoDelete({ id })
|
||||
feedback.msgSuccess('删除成功')
|
||||
getLists()
|
||||
}
|
||||
|
||||
getLists()
|
||||
</script>
|
||||
|
|
@ -182,9 +182,9 @@
|
|||
<el-option
|
||||
v-for="(item, index) in optionsData.dictType"
|
||||
:key="index"
|
||||
:label="item.dictName"
|
||||
:value="item.dictType"
|
||||
:disabled="!item.dictStatus"
|
||||
:label="item.name"
|
||||
:value="item.type"
|
||||
:disabled="!item.status"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -93,11 +93,11 @@
|
|||
<div class="index-info">
|
||||
<div class="index-details">
|
||||
<div class="flex justify-center" style="font-size: 12px">
|
||||
{{ getRowStartTime(row) }}
|
||||
{{ row.startTime }}
|
||||
</div>
|
||||
<div class="flex justify-center" style="font-size: 6px">——</div>
|
||||
<div class="flex justify-center" style="font-size: 12px">
|
||||
{{ getRowEndTime(row) }}
|
||||
{{ row.endTime }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -111,26 +111,26 @@
|
|||
min-width="80"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row, $index }">
|
||||
<template #default="{ row }">
|
||||
<div
|
||||
:class="[
|
||||
'time-slot-cell',
|
||||
isTimeSlotSelected($index, day.value, row[day.value]) ? 'time-slot-selected' : '',
|
||||
row[day.value] ? '' : 'empty-slot'
|
||||
isTimeSlotSelected(row.section, day.value) ? 'time-slot-selected' : '',
|
||||
getScheduledClass(row.section, day.value) ? '' : 'empty-slot'
|
||||
]"
|
||||
@click="handleTimeSlotClick($index, day.value, row[day.value])"
|
||||
@click="handleTimeSlotClick(row, day.value)"
|
||||
>
|
||||
<!-- 如果有课程信息,显示课程 -->
|
||||
<div v-if="row[day.value]" class="course-info">
|
||||
<div class="course-name">{{ row[day.value].courseName || '课程' }}</div>
|
||||
<div v-if="getScheduledClass(row.section, day.value)" class="course-info">
|
||||
<div class="course-name">{{ getScheduledClass(row.section, day.value)?.courseName || '课程' }}</div>
|
||||
<div class="course-details">
|
||||
<div>教师: {{ row[day.value].teacherName || '未知' }}</div>
|
||||
<div>教室: {{ row[day.value].classroomName || '未知' }}</div>
|
||||
<div>教师: {{ getScheduledClass(row.section, day.value)?.teacherName || '未知' }}</div>
|
||||
<div>教室: {{ getScheduledClass(row.section, day.value)?.classroomName || '未知' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 空时间段显示可选状态 -->
|
||||
<div v-else class="empty-slot-content">
|
||||
<el-icon v-if="isTimeSlotSelected($index, day.value, row[day.value])" class="check-icon">
|
||||
<el-icon v-if="isTimeSlotSelected(row.section, day.value)" class="check-icon">
|
||||
<Check />
|
||||
</el-icon>
|
||||
<span v-else class="empty-text">点击选择</span>
|
||||
|
|
@ -157,9 +157,9 @@
|
|||
<div v-else class="space-y-4 max-h-[700px] overflow-y-auto">
|
||||
<el-card
|
||||
v-for="item in getCourseLists.lists"
|
||||
:key="`course-${item.id}`"
|
||||
:key="`course-${item.courseId}`"
|
||||
shadow="hover"
|
||||
:class="['cursor-pointer transition-all duration-200', selectedCourseId === item.id ? 'selected-card' : 'hover:bg-blue-50']"
|
||||
:class="['cursor-pointer transition-all duration-200', selectedCourseId === item.courseId ? 'selected-card' : 'hover:bg-blue-50']"
|
||||
@click="handleCourseClick(item)"
|
||||
>
|
||||
<div class="p-0">
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
课程:{{ item.courseName }}
|
||||
</h4>
|
||||
</div>
|
||||
<el-tag v-if="selectedCourseId === item.id" size="small" type="info">
|
||||
<el-tag v-if="selectedCourseId === item.courseId" size="small" type="info">
|
||||
共{{ item.totalWeeks }}周
|
||||
</el-tag>
|
||||
</div>
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
<span>总学时: {{ item.totalHours }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedCourseId === item.id"
|
||||
v-if="selectedCourseId === item.courseId"
|
||||
class="pt-3 border-t border-gray-100"
|
||||
>
|
||||
<div class="text-xs text-gray-700">
|
||||
|
|
@ -310,9 +310,9 @@ import { Check } from '@element-plus/icons-vue'
|
|||
|
||||
import { classLists } from '@/api/class'
|
||||
import { configLists } from '@/api/config'
|
||||
import { courseAvailableRooms, courseAvailableSlots, courseSchedule } from '@/api/course'
|
||||
import { courseAvailableRooms, courseAvailableSlots, courseSchedule, courseScheduleList } from '@/api/course'
|
||||
import { taskLists } from '@/api/task'
|
||||
import { timeCurrentSemester } from '@/api/time'
|
||||
import { timeNextSemester } from '@/api/time'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
|
@ -347,7 +347,7 @@ interface ClassroomItem {
|
|||
// 选中时间段类型
|
||||
interface SelectedTimeSlot {
|
||||
id: number
|
||||
rowIndex: number
|
||||
section: number
|
||||
dayOfWeek: number
|
||||
startTime: string
|
||||
endTime: string
|
||||
|
|
@ -373,6 +373,34 @@ interface ClassItem {
|
|||
maxStudentCount: number
|
||||
}
|
||||
|
||||
// 排课数据类型
|
||||
interface ScheduledClass {
|
||||
id: number
|
||||
semesterId: number
|
||||
date: string
|
||||
timeSlotId: number
|
||||
classroomId: number
|
||||
classroomName: string
|
||||
courseId: number
|
||||
courseName: string
|
||||
classId: number
|
||||
teacherId: number
|
||||
teacherName: string
|
||||
createTime: string
|
||||
updateTime: string
|
||||
}
|
||||
|
||||
// 时间段数据类型
|
||||
interface TimeSlot {
|
||||
id: number
|
||||
slotCode: string
|
||||
dayOfWeek: number
|
||||
startTime: string
|
||||
endTime: string
|
||||
slotName: string
|
||||
section: number
|
||||
}
|
||||
|
||||
// 星期数组
|
||||
const weekDays: WeekDay[] = [
|
||||
{ label: '星期一', value: 1 },
|
||||
|
|
@ -390,17 +418,10 @@ const classSearchLoading = ref(false)
|
|||
const classSearchTimer = ref<number | null>(null)
|
||||
const activeTab = ref('course')
|
||||
|
||||
// 时间段数据
|
||||
const getTimeData = ref<{
|
||||
lists: Array<{
|
||||
timeSlotId: number
|
||||
classId: number
|
||||
classroomId: number
|
||||
courseId: number
|
||||
semesterId: number
|
||||
teacherId: number
|
||||
}>
|
||||
}>({ lists: [] })
|
||||
// 所有时间段基础数据
|
||||
const allTimeSlots = ref<TimeSlot[]>([])
|
||||
// 已排课数据
|
||||
const scheduledClasses = ref<ScheduledClass[]>([])
|
||||
|
||||
// 课程列表数据 - 明确类型
|
||||
const getCourseLists = ref<{ lists: CourseItem[] }>({ lists: [] })
|
||||
|
|
@ -412,7 +433,7 @@ const selectedCourseId = ref<number | null>(null)
|
|||
// 选中的课程完整对象
|
||||
const selectedCourse = computed(() => {
|
||||
if (!selectedCourseId.value) return null
|
||||
return getCourseLists.value.lists.find(item => item.id === selectedCourseId.value) || null
|
||||
return getCourseLists.value.lists.find(item => item.courseId === selectedCourseId.value) || null
|
||||
})
|
||||
|
||||
// 选中的课程名称
|
||||
|
|
@ -468,9 +489,7 @@ const currentWeekDateInfo = computed(() => {
|
|||
if (isNaN(startDate.getTime())) return '日期格式错误'
|
||||
|
||||
// 计算当前周第一天的日期(星期一)
|
||||
// startDate可能是学期开始日期,我们需要根据周数计算
|
||||
const weekStartDate = new Date(startDate)
|
||||
// 将开始日期调整到星期一
|
||||
const dayOfWeek = weekStartDate.getDay() // 0 = 周日, 1 = 周一, ..., 6 = 周六
|
||||
const daysToMonday = dayOfWeek === 0 ? -6 : 1 - dayOfWeek // 调整到星期一
|
||||
|
||||
|
|
@ -527,8 +546,11 @@ const queryParams = reactive({
|
|||
|
||||
// 周数变化处理
|
||||
const handleWeekChange = () => {
|
||||
// 周数变化时,可以在这里处理相关逻辑
|
||||
console.log('周数变化为:', selectedWeekNumber.value)
|
||||
// 周数变化时重新获取排课数据
|
||||
if (queryParams.classId && queryParams.semesterId) {
|
||||
fetchScheduledClasses()
|
||||
}
|
||||
}
|
||||
|
||||
// 班级变化处理
|
||||
|
|
@ -542,6 +564,7 @@ const handleClassChange = async () => {
|
|||
if (queryParams.classId && queryParams.semesterId) {
|
||||
await fetchCourseLists()
|
||||
await fetchRoomLists()
|
||||
await fetchScheduledClasses()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -555,6 +578,7 @@ const handleSemesterChange = async () => {
|
|||
|
||||
if (queryParams.classId && queryParams.semesterId) {
|
||||
await fetchCourseLists()
|
||||
await fetchScheduledClasses()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -604,7 +628,7 @@ const fetchConfigLists = async () => {
|
|||
|
||||
const fetchSemester = async () => {
|
||||
try {
|
||||
const res = await timeCurrentSemester()
|
||||
const res = await timeNextSemester()
|
||||
if (res) {
|
||||
queryParams.semesterId = res.id
|
||||
}
|
||||
|
|
@ -653,7 +677,8 @@ const fetchCourseLists = async () => {
|
|||
|
||||
// 课程点击处理(切换选中/取消选中)
|
||||
const handleCourseClick = (course: CourseItem) => {
|
||||
selectedCourseId.value = selectedCourseId.value === course.id ? null : course.id
|
||||
selectedCourseId.value = selectedCourseId.value === course.courseId ? null : course.courseId
|
||||
console.log('课程ID', selectedCourseId)
|
||||
selectedWeekNumber.value = 1
|
||||
activeTab.value = 'course'
|
||||
}
|
||||
|
|
@ -696,16 +721,66 @@ const handleClassroomClick = (classroom: ClassroomItem) => {
|
|||
activeTab.value = 'classroom'
|
||||
}
|
||||
|
||||
// 获取已排课数据
|
||||
const fetchScheduledClasses = async () => {
|
||||
if (!queryParams.classId || !queryParams.semesterId) return
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await courseScheduleList({
|
||||
classId: queryParams.classId,
|
||||
semesterId: queryParams.semesterId
|
||||
})
|
||||
scheduledClasses.value = res
|
||||
} catch (err) {
|
||||
console.error('获取排课数据失败', err)
|
||||
feedback.msgError('获取排课数据失败')
|
||||
scheduledClasses.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取时间段基础数据
|
||||
const fetchTimeSlots = async () => {
|
||||
try {
|
||||
const res = await courseAvailableSlots()
|
||||
allTimeSlots.value = res
|
||||
} catch (err) {
|
||||
console.error('获取时间段数据失败', err)
|
||||
feedback.msgError('获取时间段数据失败')
|
||||
allTimeSlots.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 根据节次和星期几获取对应的排课信息
|
||||
const getScheduledClass = (section: number, dayOfWeek: number) => {
|
||||
// 找到对应的时间段ID
|
||||
const timeSlot = allTimeSlots.value.find(
|
||||
slot => slot.section === section && slot.dayOfWeek === dayOfWeek
|
||||
)
|
||||
|
||||
if (!timeSlot) return null
|
||||
|
||||
// 找到该时间段的排课信息
|
||||
return scheduledClasses.value.find(item => item.timeSlotId === timeSlot.id) || null
|
||||
}
|
||||
|
||||
// 处理时间段点击
|
||||
const handleTimeSlotClick = (rowIndex: number, dayOfWeek: number, cellData: any) => {
|
||||
const row = tableData.value[rowIndex]
|
||||
const id = cellData?.id || Date.now()
|
||||
const startTime = getRowStartTime(row)
|
||||
const endTime = getRowEndTime(row)
|
||||
const handleTimeSlotClick = (row: any, dayOfWeek: number) => {
|
||||
// 找到对应的时间段
|
||||
const timeSlot = allTimeSlots.value.find(
|
||||
slot => slot.section === row.section && slot.dayOfWeek === dayOfWeek
|
||||
)
|
||||
|
||||
if (!timeSlot) return
|
||||
|
||||
// 获取该时间段的排课信息
|
||||
const scheduledClass = getScheduledClass(row.section, dayOfWeek)
|
||||
|
||||
// 取消选中(点击已选中的时间段)
|
||||
if (selectedTimeSlot.value &&
|
||||
selectedTimeSlot.value.rowIndex === rowIndex &&
|
||||
selectedTimeSlot.value.section === row.section &&
|
||||
selectedTimeSlot.value.dayOfWeek === dayOfWeek) {
|
||||
selectedTimeSlot.value = null
|
||||
return
|
||||
|
|
@ -713,32 +788,28 @@ const handleTimeSlotClick = (rowIndex: number, dayOfWeek: number, cellData: any)
|
|||
|
||||
// 设置选中的时间段
|
||||
selectedTimeSlot.value = {
|
||||
id,
|
||||
rowIndex,
|
||||
id: timeSlot.id,
|
||||
section: row.section,
|
||||
dayOfWeek,
|
||||
startTime,
|
||||
endTime,
|
||||
hasCourse: !!cellData,
|
||||
courseData: cellData
|
||||
startTime: row.startTime,
|
||||
endTime: row.endTime,
|
||||
hasCourse: !!scheduledClass,
|
||||
courseData: scheduledClass
|
||||
}
|
||||
|
||||
// 自动选中对应课程(基于courseId精准匹配)
|
||||
if (cellData && cellData.courseId) {
|
||||
const targetCourse = getCourseLists.value.lists.find(item => item.courseId === cellData.courseId)
|
||||
if (scheduledClass && scheduledClass.courseId) {
|
||||
const targetCourse = getCourseLists.value.lists.find(item => item.courseId === scheduledClass.courseId)
|
||||
if (targetCourse) {
|
||||
selectedCourseId.value = targetCourse.id
|
||||
// 如果有课程,设置默认周数为第1周
|
||||
if (targetCourse.totalWeeks > 0) {
|
||||
selectedWeekNumber.value = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断时间段是否被选中
|
||||
const isTimeSlotSelected = (rowIndex: number, dayOfWeek: number, cellData: any) => {
|
||||
const isTimeSlotSelected = (section: number, dayOfWeek: number) => {
|
||||
return selectedTimeSlot.value &&
|
||||
selectedTimeSlot.value.rowIndex === rowIndex &&
|
||||
selectedTimeSlot.value.section === section &&
|
||||
selectedTimeSlot.value.dayOfWeek === dayOfWeek
|
||||
}
|
||||
|
||||
|
|
@ -752,7 +823,7 @@ const getSelectedTimeSlotText = () => {
|
|||
const slot = selectedTimeSlot.value
|
||||
if (!slot) return ''
|
||||
const dayText = weekDays.find(day => day.value === slot.dayOfWeek)?.label || ''
|
||||
return `第${slot.rowIndex + 1}节 ${dayText} ${slot.startTime}-${slot.endTime}`
|
||||
return `第${slot.section}节 ${dayText} ${slot.startTime}-${slot.endTime}`
|
||||
}
|
||||
|
||||
// 安排课程
|
||||
|
|
@ -776,8 +847,8 @@ const handleScheduleCourse = async () => {
|
|||
})
|
||||
|
||||
feedback.msgSuccess('排课成功')
|
||||
// 刷新课表数据
|
||||
await getTimeLists()
|
||||
// 刷新排课数据
|
||||
await fetchScheduledClasses()
|
||||
// 清空选中状态,提升用户体验
|
||||
clearSelectedTimeSlot()
|
||||
selectedCourseId.value = null
|
||||
|
|
@ -797,12 +868,15 @@ const handleRemoveCourse = async () => {
|
|||
}
|
||||
|
||||
try {
|
||||
// TODO: 调用移除课程API
|
||||
// 示例:await removeCourse({ timeSlotId: selectedTimeSlot.value.id })
|
||||
|
||||
feedback.msgSuccess('课程移除成功')
|
||||
await getTimeLists()
|
||||
clearSelectedTimeSlot()
|
||||
// 调用移除课程API,假设API需要排课记录的ID
|
||||
if (selectedTimeSlot.value.courseData && selectedTimeSlot.value.courseData.id) {
|
||||
// 这里需要替换为实际的删除API
|
||||
// await removeCourse({ id: selectedTimeSlot.value.courseData.id })
|
||||
|
||||
feedback.msgSuccess('课程移除成功')
|
||||
await fetchScheduledClasses()
|
||||
clearSelectedTimeSlot()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('移除课程失败', error)
|
||||
feedback.msgError('移除课程失败,请稍后重试')
|
||||
|
|
@ -823,64 +897,40 @@ const { pager, getLists } = usePaging({
|
|||
size: 7
|
||||
})
|
||||
|
||||
// 请求数据列表
|
||||
const getTimeLists = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await courseAvailableSlots()
|
||||
allLists.value = res
|
||||
return Promise.resolve(res)
|
||||
} catch (err) {
|
||||
console.error('获取时间段列表失败', err)
|
||||
return Promise.reject(err)
|
||||
} finally {
|
||||
loading.value = false
|
||||
// 处理表格数据,按节次分组,构建星期矩阵
|
||||
const tableData = computed(() => {
|
||||
// 创建节次到时间段的映射
|
||||
const sectionMap = new Map<number, { section: number; startTime: string; endTime: string }>()
|
||||
|
||||
// 收集所有唯一的节次及其时间信息
|
||||
allTimeSlots.value.forEach(slot => {
|
||||
if (!sectionMap.has(slot.section)) {
|
||||
sectionMap.set(slot.section, {
|
||||
section: slot.section,
|
||||
startTime: slot.startTime.slice(0, -3), // 去除秒数
|
||||
endTime: slot.endTime.slice(0, -3) // 去除秒数
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 转换为数组并按节次排序
|
||||
return Array.from(sectionMap.values()).sort((a, b) => a.section - b.section)
|
||||
})
|
||||
|
||||
// 初始化时获取数据
|
||||
const initData = async () => {
|
||||
await fetchTimeSlots()
|
||||
await fetchClassLists('')
|
||||
await fetchConfigLists()
|
||||
|
||||
// 如果有默认的班级和学期,获取排课数据
|
||||
if (queryParams.classId && queryParams.semesterId) {
|
||||
await fetchScheduledClasses()
|
||||
}
|
||||
}
|
||||
|
||||
// 处理表格数据,按节次分组,构建星期矩阵
|
||||
const tableData = computed(() => {
|
||||
const timeSlotMap = new Map<string, Record<number, any>>()
|
||||
allLists.value.forEach((item) => {
|
||||
const key = `${item.startTime}-${item.endTime}`
|
||||
if (!timeSlotMap.has(key)) {
|
||||
timeSlotMap.set(key, {})
|
||||
}
|
||||
const slotGroup = timeSlotMap.get(key)!
|
||||
slotGroup[item.dayOfWeek] = item
|
||||
})
|
||||
|
||||
return Array.from(timeSlotMap.values()).sort((a, b) => {
|
||||
const aTime = Object.values(a)[0]?.startTime || ''
|
||||
const bTime = Object.values(b)[0]?.startTime || ''
|
||||
return aTime.localeCompare(bTime)
|
||||
})
|
||||
})
|
||||
|
||||
const getRowBaseInfo = (row: Record<number, any>) => {
|
||||
return Object.values(row).find((item) => item) || {}
|
||||
}
|
||||
|
||||
const getRowStartTime = (row: Record<number, any>) => {
|
||||
const baseInfo = getRowBaseInfo(row)
|
||||
const start = baseInfo?.startTime
|
||||
if (start == null) return ''
|
||||
const s = String(start)
|
||||
return s.length > 3 ? s.slice(0, -3) : ''
|
||||
}
|
||||
|
||||
const getRowEndTime = (row: Record<number, any>) => {
|
||||
const baseInfo = getRowBaseInfo(row)
|
||||
const end = baseInfo?.endTime
|
||||
if (end == null) return ''
|
||||
const s = String(end)
|
||||
return s.length > 3 ? s.slice(0, -3) : ''
|
||||
}
|
||||
|
||||
// 初始化时获取数据
|
||||
getTimeLists()
|
||||
fetchClassLists('')
|
||||
fetchConfigLists()
|
||||
// 初始化数据
|
||||
initData()
|
||||
</script>
|
||||
<style scoped>
|
||||
:deep(.first-column) {
|
||||
|
|
|
|||
|
|
@ -75,8 +75,7 @@ const formData = reactive({
|
|||
sort: 0,
|
||||
status: 1,
|
||||
remark: '',
|
||||
typeId: 0,
|
||||
type_id: 0
|
||||
typeId: 0
|
||||
})
|
||||
|
||||
const rules = {
|
||||
|
|
@ -98,6 +97,7 @@ const rules = {
|
|||
|
||||
const handleSubmit = async () => {
|
||||
await formRef.value?.validate()
|
||||
console.log(formData)
|
||||
mode.value == 'edit' ? await dictDataEdit(formData) : await dictDataAdd(formData)
|
||||
popupRef.value?.close()
|
||||
emit('success')
|
||||
|
|
@ -117,7 +117,8 @@ const setFormData = (data: Record<any, any>) => {
|
|||
if (data[key] != null && data[key] != undefined) {
|
||||
//@ts-ignore
|
||||
formData[key] = data[key]
|
||||
formData.typeId = data.type_id
|
||||
console.log('data:', data)
|
||||
console.log('formData:', formData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ import { configDetail, configLists } from '@/api/config'
|
|||
import { courseDetail } from '@/api/course'
|
||||
import { taskAdd, taskCourseList, taskDetail, taskEdit, taskTeacherList } from '@/api/task'
|
||||
import { teacherDetail } from '@/api/teacher'
|
||||
import { timeCurrentSemester } from '@/api/time'
|
||||
import { timeNextSemester } from '@/api/time'
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import feedback from '@/utils/feedback'
|
||||
defineProps({
|
||||
|
|
@ -285,7 +285,7 @@ const fetchConfigLists = async () => {
|
|||
}
|
||||
const fetchSemester = async () => {
|
||||
try {
|
||||
const res = await timeCurrentSemester()
|
||||
const res = await timeNextSemester()
|
||||
if (res) {
|
||||
formData.semesterId = res.id
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ import { configLists } from '@/api/config'
|
|||
import { courseLists } from '@/api/course'
|
||||
import { taskDelete, taskLists, taskSearch } from '@/api/task'
|
||||
import { teacherLists } from '@/api/teacher'
|
||||
import { timeCurrentSemester } from '@/api/time'
|
||||
import { timeNextSemester } from '@/api/time'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ const queryParams = reactive({
|
|||
semesterId: '',
|
||||
courseId: '',
|
||||
teacherId: '',
|
||||
classId: '',
|
||||
classId: Number(route.query.classId) || null,
|
||||
weeklyHours: '',
|
||||
totalWeeks: '',
|
||||
createdBy: '',
|
||||
|
|
@ -205,9 +205,13 @@ const fetchConfigLists = async () => {
|
|||
}
|
||||
const fetchSemester = async () => {
|
||||
try {
|
||||
const res = await timeCurrentSemester()
|
||||
const res = await timeNextSemester()
|
||||
console.log('res',res)
|
||||
if (res) {
|
||||
queryParams.semesterId = res.id
|
||||
console.log('semesterId',queryParams.semesterId)
|
||||
await getClassDetail()
|
||||
await getLists()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取学期信息失败', error)
|
||||
|
|
@ -266,13 +270,14 @@ onBeforeUnmount(() => {
|
|||
const getClassDetail = async () => {
|
||||
try {
|
||||
console.log('route.query.classId', route.query.classId)
|
||||
const res = await classDetail({
|
||||
id: Number(route.query.classId),
|
||||
semesterId: queryParams.semesterId
|
||||
})
|
||||
const res = await classDetail({id: Number(route.query.classId)})
|
||||
classData.classCode = res.classCode
|
||||
classData.className = res.className
|
||||
const progressRes = await taskSearch({ classId: Number(route.query.classId) })
|
||||
console.log('queryParams.semesterId',queryParams.semesterId)
|
||||
const progressRes = await taskSearch({
|
||||
classId: Number(route.query.classId),
|
||||
semesterId: queryParams.semesterId
|
||||
})
|
||||
console.log('progressRes', progressRes)
|
||||
classData.classProgress = progressRes.arrangementProgress || '暂无进度信息'
|
||||
} catch (err) {
|
||||
|
|
@ -314,8 +319,6 @@ const handleDelete = async (id: number) => {
|
|||
}
|
||||
|
||||
fetchConfigLists()
|
||||
getClassDetail()
|
||||
fetchCourseLists('')
|
||||
fetchTeacherLists('')
|
||||
getLists()
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ import type { PropType } from 'vue'
|
|||
|
||||
import { courseAdd, courseDetail, courseEdit, courseUploadFile } from '@/api/course'
|
||||
import { typeLists } from '@/api/courseType'
|
||||
|
||||
import { requirementLists } from '@/api/requirement'
|
||||
|
||||
import Popup from '@/components/popup/index.vue'
|
||||
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
|
|
|||
Loading…
Reference in New Issue