还原样式

This commit is contained in:
ywyonui 2025-08-29 15:23:48 +08:00
parent 68fd30a282
commit 833e0e9498
3 changed files with 555 additions and 323 deletions

View File

@ -1,143 +1,349 @@
<template>
<view class="js-qj-dk-edit">
<view class="dk-header">
<text class="dk-title">代课教师</text>
<view class="back-f8f8f8">
<view class="flex-row items-center justify-between py-15">
<view class="dk-title">
<BasicTitle line title="代课明细" :isBorder="false" />
</view>
<view @click="getPkkbList">
<BasicIcon type="refreshempty" size="25" />
</view>
</view>
<view class="dk-tabs mb-10" v-if="dkList && dkList.length">
<BasicTabs
class="type-tabs"
ref="tabsRef"
:list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
<view class="dk-card" v-if="curTabIndex === 0">
<view class="card-body">
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">
<BasicJsPicker
:customTrigger="true"
:defualtValue="[]"
@change="handleDkJsChange"
@change="changeJsByTy"
:parent-data="tyDk"
:defualtValue="tyDk.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view>
</view>
</view>
</view>
<view v-if="curTabIndex === 1">
<view v-for="(item, index) in kmDkList" :key="index">
<view class="dk-card" style="margin: 0">
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
</view>
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">
<BasicJsPicker
@change="changeJsByKm"
:parent-data="item"
:defualtValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view v-if="dkList.length > 0">
<view v-for="(item, index) in dkList" :key="index">
<view class="dk-card">
<view class="card-header">
<text class="applicant-name"
>{{ item.dktime }}{{ wdNameList[item.xq - 1] }}{{
item.jcmc
}}</text
>
<template #trigger>
<button class="add-btn" type="primary" size="mini">添加代课教师</button>
</template>
</BasicJsPicker>
</view>
<view class="dk-list">
<view
v-for="(item, index) in dkList"
:key="item.id"
class="dk-item"
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
</view>
<view class="info-row">
<text class="label">上课时间:</text>
<text class="value">{{ item.startTime }}-{{ item.endTime }}</text>
</view>
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value" v-if="curTabIndex === 2">
<BasicJsPicker
@change="changeJs"
:parent-data="item"
:defualtValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view>
<view v-else>{{ item.dkJsName }}</view>
</view>
</view>
</view>
</view>
</view>
<view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color"
>暂无数据</view
>
<view class="dk-info">
<text class="js-name">{{ item.jsxm }}</text>
<text class="course-info">{{ item.kcmc }} - {{ item.kcsj }}</text>
</view>
<view class="dk-actions">
<button
class="remove-btn"
size="mini"
@click="removeDkJs(index)"
>
删除
</button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import BasicJsPicker from '@/components/BasicJsPicker/Picker.vue'
import { getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
import { useUserStore } from "@/store/modules/user";
const { getJs } = useUserStore();
// Props
const props = defineProps({
modelValue: {
type: Array,
default: () => []
//
const props = withDefaults(
defineProps<{
data?: any;
}>(),
{
data: () => ({
jsId: "",
qjkstime: "", //
qjjstime: "", //
}),
}
})
);
// Emits
const emit = defineEmits(['update:modelValue'])
const wdNameList = ref<string[]>([
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
//
const dkList = ref<any[]>([])
const jsTypeMc: any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
//
const handleDkJsChange = (selectedItems: any[]) => {
console.log(selectedItems)
if (Array.isArray(selectedItems)) {
dkList.value = selectedItems
emit('update:modelValue', selectedItems)
}
//
const excludeIds = ref<any>([]);
if (props.data && props.data.jsId && props.data.jsId.length) {
excludeIds.value.push(props.data.jsId);
} else {
excludeIds.value.push(getJs.id);
}
//
const removeDkJs = (index: number) => {
dkList.value.splice(index, 1)
emit('update:modelValue', dkList.value)
}
const tyDk = ref<any>({});
// modelValue
watch(() => props.modelValue, (newVal) => {
if (Array.isArray(newVal)) {
dkList.value = newVal
const dkList = ref<any>([]);
const kmDkList = ref<any>([]);
const tabList = ref([
{ name: "统一设置", id: "tab-ty" },
{ name: "按排课设置", id: "tab-pk" },
{ name: "按节次设置", id: "tab-jc" },
]);
const curTabIndex = ref(0);
const switchTab = (index: number) => {
curTabIndex.value = index;
};
const getPkkbList = async () => {
const res = await getPkkbByJsRangeTimeApi({
jsId: props.data.jsId,
startTime: props.data.qjkstime,
endTime: props.data.qjjstime,
});
//
const srcData: any = {};
dkList.value.map((item: any) => {
const key = item.dktime + item.jcType + item.jc;
srcData[key] = {
dkJsId: item.dkJsId,
dkJsName: item.dkJsName,
};
});
const kmMap: any = {};
dkList.value = res.result.map((item: any) => {
item.dktime = item.kbtime.split(" ")[0];
item.njbjmx = item.bc + item.bjmc;
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const key = item.dktime + item.jcType + item.jc;
const src = srcData[key];
if (src) {
item.dkJsId = src.dkJsId;
item.dkJsName = src.dkJsName;
} else {
item.dkJsId = "";
item.dkJsName = "";
}
}, { deep: true, immediate: true })
kmMap[item.pkId] = kmMap[item.pkId] || {
pkMc: item.pkMc,
pkId: item.pkId,
};
return item;
});
// kmMapvalue
kmDkList.value = Object.values(kmMap);
};
const changeJsByTy = (selected: any, item: any) => {
item.dkJsId = selected.value;
item.dkJsName = selected.label;
const newList = dkList.value.map((dk: any) => {
return {
...dk,
dkJsId: item.dkJsId,
dkJsName: item.dkJsName,
};
});
dkList.value = newList;
const newKmList = kmDkList.value.map((km: any) => {
return {
...km,
dkJsId: item.dkJsId,
dkJsName: item.dkJsName,
};
});
kmDkList.value = newKmList;
};
const changeJsByKm = (selected: any, item: any) => {
item.dkJsId = selected.value;
item.dkJsName = selected.label;
//
const newList = dkList.value.map((dk: any) => {
if (dk.pkId === item.pkId) {
return { ...dk, dkJsId: item.dkJsId, dkJsName: item.dkJsName };
}
return dk;
});
dkList.value = newList;
};
const changeJs = (selected: any, item: any) => {
item.dkJsId = selected.value;
item.dkJsName = selected.label;
};
const validate = async () => {
//
if (!dkList.value || !dkList.value.length) {
await getPkkbList();
}
const list = dkList.value;
// true
if (!list || !list.length) {
return true;
}
//
for (let i = 0; i < list.length; i++) {
const item = list[i];
if (!item.dkJsId) {
return false;
}
}
return true;
};
// ref
const getDkList = () => {
return dkList.value;
};
//
defineExpose({
getPkkbList,
validate,
getDkList,
});
</script>
<style lang="scss" scoped>
.js-qj-dk-edit {
.dk-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.dk-tabs {
flex: 1 0 1px;
}
.dk-title {
font-size: 28rpx;
.dk-card {
background-color: #ffffff;
border-radius: 8px;
margin-bottom: 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.card-header {
padding: 12px 15px;
border-bottom: 1px solid #f0f0f0;
.applicant-name {
font-size: 16px;
font-weight: bold;
color: #333;
}
.add-btn {
background: #007aff;
color: #fff;
border: none;
border-radius: 6rpx;
}
}
.dk-list {
.dk-item {
.card-body {
padding: 15px;
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
background: #f8f9fa;
border-radius: 8rpx;
margin-bottom: 16rpx;
margin-bottom: 10px;
.dk-info {
flex: 1;
.js-name {
display: block;
font-size: 28rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
&:last-child {
margin-bottom: 0;
}
.course-info {
display: block;
font-size: 24rpx;
.label {
font-size: 14px;
color: #666;
width: 70px;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
display: flex;
.data {
flex: 1;
}
}
}
}
.dk-actions {
.remove-btn {
background: #ff3b30;
color: #fff;
border: none;
border-radius: 6rpx;
}
}
}
.card-footer {
padding: 12px 15px;
border-top: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
color: #888;
cursor: pointer;
.arrow {
font-size: 16px;
color: #ccc;
}
}
</style>

View File

@ -1,233 +1,259 @@
<template>
<view class="js-qj-edit">
<uni-forms ref="formRef" :model="formData" :rules="formRules">
<!-- 基本信息 -->
<view class="form-section">
<view class="section-title">基本信息</view>
<uni-forms-item label="请假类型" name="qjlx">
<uni-data-select
v-model="formData.qjlx"
:localdata="qjlxOptions"
placeholder="请选择请假类型"
/>
</uni-forms-item>
<uni-forms-item label="请假开始时间" name="qjkstime">
<uni-datetime-picker
v-model="formData.qjkstime"
type="datetime"
placeholder="请选择开始时间"
/>
</uni-forms-item>
<uni-forms-item label="请假结束时间" name="qjjstime">
<uni-datetime-picker
v-model="formData.qjjstime"
type="datetime"
placeholder="请选择结束时间"
/>
</uni-forms-item>
<uni-forms-item label="请假原因" name="qjyy">
<uni-easyinput
v-model="formData.qjyy"
type="textarea"
placeholder="请输入请假原因"
/>
</uni-forms-item>
</view>
<!-- 代课信息 -->
<view class="form-section">
<view class="section-title">代课信息</view>
<uni-forms-item label="代课方式" name="dkfs">
<uni-data-select
v-model="formData.dkfs"
:localdata="dkfsOptions"
placeholder="请选择代课方式"
@change="handleDkfsChange"
/>
</uni-forms-item>
<view v-if="formData.dkfs === '0'">
<JsQjDkEdit v-model="formData.dkList" />
</view>
</view>
<!-- 审批信息 -->
<view class="form-section">
<view class="section-title">审批信息</view>
<BasicLayout :fixed="false">
<view class="p-15">
<BasicForm @register="register">
<template #dkmx>
<JsQjDkEdit :data="formData" ref="dkRef" v-if="formData.dkfs === 0" />
</template>
<template #spcs>
<BasicSpCsMgr
:qjId="qjId"
v-model:approvers="formData.sprList"
v-model:ccPersons="formData.csrList"
/>
</template>
</BasicForm>
</view>
<!-- 操作按钮 -->
<view class="form-actions">
<button type="primary" @click="handleSubmit">提交申请</button>
<button @click="handleSave">保存草稿</button>
<template #bottom>
<view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5">
<u-button text="取消" class="ml-15 mr-7" :plain="true" @click="navigateBack" />
<u-button text="提交" class="mr-15 mr-7" type="primary" @click="submit" />
</view>
</uni-forms>
</view>
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from 'vue'
import { useCommonStore } from '@/store/modules/common'
import BasicSpCsMgr from '@/components/BasicSpCsMgr/index.vue'
import JsQjDkEdit from './jsQjDkEdit.vue'
import { findQjByIdApi, jsQjSqApi } from '@/api/base/jsQjApi'
import JsQjDkEdit from "./jsQjDkEdit.vue"
import BasicSpCsMgr from "@/components/BasicSpCsMgr/index.vue"
import { navigateBack } from "@/utils/uniapp";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { jsQjSqApi, jsQjCxtjApi } from "@/api/base/jsQjApi";
import { showToast } from "@/utils/uniapp";
import dayjs from "dayjs";
import { useUserStore } from "@/store/modules/user";
import { useDicStore } from "@/store/modules/dic";
// Props
const props = defineProps({
qjId: {
type: String,
default: ''
}
})
const { getJs, getUser } = useUserStore();
const { findByPid } = useDicStore();
// Emits
const emit = defineEmits(['submitSuccess'])
// Store
const commonStore = useCommonStore()
//
const formRef = ref(null)
const formData = reactive({
qjlx: '',
qjkstime: '',
qjjstime: '',
qjyy: '',
dkfs: '',
dkList: [],
//
const props = withDefaults(defineProps<{
data?: any
}>(), {
data: () => ({
id: "",
qjlx: "",
qjkstime: "",
qjjstime: "",
qjsc: "",
qjsy: "",
dkfs: 0,
sprList: [],
csrList: []
csrList: [],
})
});
//
const formRules = {
qjlx: {
rules: [{ required: true, errorMessage: '请选择请假类型' }]
},
qjkstime: {
rules: [{ required: true, errorMessage: '请选择开始时间' }]
},
qjjstime: {
rules: [{ required: true, errorMessage: '请选择结束时间' }]
},
qjyy: {
rules: [{ required: true, errorMessage: '请输入请假原因' }]
},
dkfs: {
rules: [{ required: true, errorMessage: '请选择代课方式' }]
}
}
let formData = ref<any>({
...props.data,
jsId: getJs.id,
});
//
const qjlxOptions = [
{ value: '病假', text: '病假' },
{ value: '事假', text: '事假' },
{ value: '其他', text: '其他' }
]
const dkRef = ref<any>(null);
const dkfsOptions = [
{ value: '0', text: '自行协调' },
{ value: '1', text: '教务处协调' },
{ value: '2', text: '无需代课' }
]
//
const handleDkfsChange = (value: string) => {
if (value !== '0') {
formData.dkList = []
}
}
//
const loadQjDetail = async () => {
if (!props.qjId) return
try {
const res = await findQjByIdApi(props.qjId)
if (res && res.result) {
Object.assign(formData, res.result)
}
} catch (error) {
console.error('加载请假详情失败:', error)
commonStore.showToast('加载详情失败')
}
}
//
const handleSubmit = async () => {
try {
await formRef.value.validate()
const submitData = {
...formData,
jsId: commonStore.userInfo.id
}
await jsQjSqApi(submitData)
commonStore.showToast('提交成功')
emit('submitSuccess')
} catch (error) {
console.error('提交失败:', error)
commonStore.showToast('提交失败')
}
}
//
const handleSave = async () => {
try {
// 稿
commonStore.showToast('保存成功')
} catch (error) {
console.error('保存失败:', error)
commonStore.showToast('保存失败')
}
}
// qjId
watch(() => props.qjId, (newVal) => {
if (newVal) {
loadQjDetail()
}
if (typeof props.data.dkfs === "string") {
nextTick(() => {
formData.value.dkfs = parseInt(props.data.dkfs);
})
onMounted(() => {
if (props.qjId) {
loadQjDetail()
}
})
const [register, { setValue, getValue }] = useForm({
schema: [
{
field: "qjlx",
label: "请假类型",
required: true,
component: "BasicPicker",
componentProps: {
api: findByPid,
param: { pid: 1007011432 },
rangeKey: "dictionaryValue",
savaKey: "dictionaryCode",
},
},
{
field: "qjkstime",
label: "开始时间",
component: "BasicDateTimes",
required: true,
componentProps: {
type: 'datetime',
change: (e: string) => changeKsTime(e)
},
},
{
field: "qjjstime",
label: "结束时间",
component: "BasicDateTimes",
required: true,
componentProps: {
type: 'datetime',
change: (e: string) => changeJsTime(e)
},
},
{
field: "qjsc",
label: "请假时长",
component: "BasicInput",
componentProps: {
disabled: true,
placeholder: "请输入选择开始时间和结束时间"
},
},
{
field: "qjsy",
label: "请假事由",
component: "BasicInput",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
},
},
{ interval: true },
{
field: "dkfs",
label: "代课方式",
component: "BasicCheckbox",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
data: [
{ value: 0, text: "自行协调" },
{ value: 1, text: "教科处协调" },
{ value: 2, text: "无须代课" },
],
change: (value: any) => {
formData.value.dkfs = value;
updateDk();
},
},
},
{ colSlot: "dkmx" },
{ interval: true },
{ colSlot: "spcs" },
],
});
const changeKsTime = (selectedTime?: string) => {
if (!selectedTime) {
return;
}
formData.value.qjkstime = selectedTime;
validateTime();
};
const changeJsTime = (selectedTime?: string) => {
if (!selectedTime) {
return;
}
formData.value.qjjstime = selectedTime;
validateTime();
};
const validateTime = () => {
const data = formData.value;
if (!data.qjkstime || !data.qjjstime) {
return false;
}
// 使dayjs
const ksTime = dayjs(data.qjkstime).valueOf();
const jsTime = dayjs(data.qjjstime).valueOf();
if (ksTime > jsTime) {
uni.showToast({
title: "请假开始时间不能大于请假结束时间!",
icon: "none",
});
return false;
}
//
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
setValue({ qjsc: data.qjsc });
updateDk();
return true;
}
const updateDk = () => {
if (dkRef.value) {
dkRef.value.getPkkbList();
}
};
//
setValue(props.data)
updateDk();
const submit = async () => {
const fd = await getValue();
if (!validateTime()) {
return;
}
const params = { ...fd };
// /
params.sprList = formData.value.sprList || [];
params.csrList = formData.value.csrList || [];
if (fd.dkfs === 0) {
const dkList = dkRef.value.getDkList();
if (!dkList.length) {
uni.showToast({
title: "请选择代课教师",
icon: "none",
});
return;
}
if (dkList.length) {
params.dkList = dkList.map((item: any) => {
const newItem = {...item};
newItem.jsId = item.dkJsId || item.jsId;
newItem.jsName = item.dkJsName || item.jsName;
newItem.pkkbId = item.id;
newItem.dktime = item.dktime + " 00:00:00";
newItem.id = "";
newItem.qjId = "";
return newItem;
});
} else {
params.dkList = [];
}
}
let submitApi = jsQjSqApi;
if (props.data && props.data.id) {
params.id = props.data.id;
submitApi = jsQjCxtjApi
} else {
params.id = null;
params.jsId = getJs.id;
params.jsName = getJs.jsxm;
}
uni.showLoading({ title: "提交中..." });
await submitApi(params).then(() => {
showToast({ title: "提交成功", icon: "success" });
uni.reLaunch({
url: "/pages/base/service/index"
});
});
uni.hideLoading();
};
</script>
<style lang="scss" scoped>
.js-qj-edit {
padding: 20rpx;
:deep(.global-bg-color) { background-color: #fff; }
/* 保持BasicForm区块背景统一 */
:deep(.white-bg-color) { background-color: #fff; }
.form-section {
margin-bottom: 30rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 20rpx;
color: #333;
}
}
.form-actions {
display: flex;
gap: 20rpx;
margin-top: 40rpx;
button {
flex: 1;
}
}
}
</style>

View File

@ -28,7 +28,7 @@ const qjData = ref<any>({});
//
const loadQjData = async () => {
try {
const result = await findQjById({ id: qjId.value });
const result:any = await findQjById({ id: qjId.value });
if (result.code === 1) {
qjData.value = result.data;
}
@ -37,7 +37,7 @@ const loadQjData = async () => {
}
};
onLoad((options) => {
onLoad((options:any) => {
if (options.qjId) {
qjId.value = options.qjId;
loadQjData();