还原样式

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> <template>
<view class="js-qj-dk-edit"> <view class="back-f8f8f8">
<view class="dk-header"> <view class="flex-row items-center justify-between py-15">
<text class="dk-title">代课教师</text> <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 <BasicJsPicker
:customTrigger="true" @change="changeJsByTy"
:defualtValue="[]" :parent-data="tyDk"
@change="handleDkJsChange" :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>
<view class="card-body">
<view class="dk-list"> <view class="info-row">
<view <text class="label">排课名称:</text>
v-for="(item, index) in dkList" <text class="value">{{ item.pkMc }}</text>
:key="item.id" </view>
class="dk-item" <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> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from 'vue' import { getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi";
import BasicJsPicker from '@/components/BasicJsPicker/Picker.vue' import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
import { useUserStore } from "@/store/modules/user";
const { getJs } = useUserStore();
// Props //
const props = defineProps({ const props = withDefaults(
modelValue: { defineProps<{
type: Array, data?: any;
default: () => [] }>(),
{
data: () => ({
jsId: "",
qjkstime: "", //
qjjstime: "", //
}),
} }
}) );
// Emits const wdNameList = ref<string[]>([
const emit = defineEmits(['update:modelValue']) "周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
// const jsTypeMc: any = {
const dkList = ref<any[]>([]) ZAM: "早自习",
AM: "上午",
PM: "下午",
};
// //
const handleDkJsChange = (selectedItems: any[]) => { const excludeIds = ref<any>([]);
console.log(selectedItems)
if (Array.isArray(selectedItems)) { if (props.data && props.data.jsId && props.data.jsId.length) {
dkList.value = selectedItems excludeIds.value.push(props.data.jsId);
emit('update:modelValue', selectedItems) } else {
} excludeIds.value.push(getJs.id);
} }
// const tyDk = ref<any>({});
const removeDkJs = (index: number) => {
dkList.value.splice(index, 1)
emit('update:modelValue', dkList.value)
}
// modelValue const dkList = ref<any>([]);
watch(() => props.modelValue, (newVal) => {
if (Array.isArray(newVal)) { const kmDkList = ref<any>([]);
dkList.value = newVal
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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.js-qj-dk-edit { .dk-tabs {
.dk-header { flex: 1 0 1px;
display: flex; }
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.dk-title { .dk-card {
font-size: 28rpx; 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; font-weight: bold;
color: #333; color: #333;
} }
}
.add-btn { .card-body {
background: #007aff; padding: 15px;
color: #fff;
border: none;
border-radius: 6rpx;
}
}
.dk-list { .info-row {
.dk-item {
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
padding: 20rpx; margin-bottom: 10px;
background: #f8f9fa;
border-radius: 8rpx;
margin-bottom: 16rpx;
.dk-info { &:last-child {
flex: 1; margin-bottom: 0;
.js-name {
display: block;
font-size: 28rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
} }
.course-info { .label {
display: block; font-size: 14px;
font-size: 24rpx;
color: #666; color: #666;
} width: 70px;
flex-shrink: 0;
margin-right: 8px;
} }
.dk-actions { .value {
.remove-btn { font-size: 14px;
background: #ff3b30; color: #333;
color: #fff; flex: 1;
border: none; display: flex;
border-radius: 6rpx; .data {
} flex: 1;
} }
} }
} }
} }
.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> </style>

View File

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

View File

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