一日常规
This commit is contained in:
parent
b8015b7a01
commit
43ea733eac
@ -46,7 +46,7 @@ export const gradeClassFindByGradeApi = async (params: any) => {
|
||||
};
|
||||
|
||||
export const cmsArticleFindPageApi = async (params: any) => {
|
||||
return await get("/api/cmsArticle/findPage", params);
|
||||
return await get("/api/cms/article/findPage", params);
|
||||
};
|
||||
//根据id查询部门
|
||||
export const deptFindAllGradeClassApi = async (param: { pid: number }) => {
|
||||
|
||||
34
src/api/base/student.ts
Normal file
34
src/api/base/student.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { get, post } from "@/utils/request";
|
||||
|
||||
/**
|
||||
* 根据年级ID和班级ID查询学生及家长信息
|
||||
*/
|
||||
export const findStudentInfoByNjAndBjApi = async (params: {
|
||||
njId?: string,
|
||||
bjIds?: string[]
|
||||
}) => {
|
||||
return await post("/api/xs/findByNjAndBj", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据学生ID列表查询学生及家长信息
|
||||
*/
|
||||
export const findStudentInfoByIdsApi = async (params: {
|
||||
xsIdList?: string
|
||||
}) => {
|
||||
return await post("/api/xs/findStudentInfoWithParentIds", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据学生身份证号查询学生信息
|
||||
*/
|
||||
export const findStudentBySfzhApi = async (sfzh: string) => {
|
||||
return await get("/api/xs/findXsBySfzh", { sfzh });
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据学生ID查询学生详情
|
||||
*/
|
||||
export const getStudentDetailByIdApi = async (id: string) => {
|
||||
return await get("/api/xs/getDetailById", { id });
|
||||
};
|
||||
@ -11,7 +11,7 @@
|
||||
<FormsItem v-bind="item">
|
||||
<template v-if="item.component && !item.slot">
|
||||
<BasicComponent
|
||||
v-bind="Object.assign({ ...attrs }, item, props.formsProps)"
|
||||
v-bind="Object.assign({ ...attrs }, item, item.componentProps, props.formsProps)"
|
||||
v-model="formModel.model[item.field]"
|
||||
:model="formModel.model"
|
||||
/>
|
||||
|
||||
@ -16,11 +16,15 @@
|
||||
<FormBasicSearchList v-bind="attrs" v-if="isShow('BasicSearchList')" v-model="newValue"/>
|
||||
<FormBasicDateTimes v-bind="attrs" v-if="isShow('BasicDateTimes')" v-model="newValue"/>
|
||||
<FormBasicTree v-bind="attrs" v-if="isShow('BasicTree')" v-model="newValue"/>
|
||||
<FormBasicNjBjPicker v-bind="attrs" v-if="isShow('BasicNjBjPicker')" v-model="newValue"/>
|
||||
<FormBasicXsPicker v-bind="attrs" v-if="isShow('BasicXsPicker')" v-model="newValue"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useAttrs} from "vue";
|
||||
import FormBasicNjBjPicker from "@/components/BasicNjBjPicker/index.vue";
|
||||
import FormBasicXsPicker from "@/components/BasicXsPicker/index.vue";
|
||||
|
||||
const attrs = useAttrs()
|
||||
|
||||
|
||||
3
src/components/BasicForm/type/useForm.d.ts
vendored
3
src/components/BasicForm/type/useForm.d.ts
vendored
@ -28,6 +28,8 @@ type Component =
|
||||
| 'BasicSearchList'
|
||||
| 'BasicDateTimes'
|
||||
| 'BasicTree'
|
||||
| 'BasicNjBjPicker'
|
||||
| 'BasicXsPicker'
|
||||
|
||||
interface FormsSchema {
|
||||
field?: string,
|
||||
@ -52,6 +54,7 @@ interface Methods {
|
||||
setValue: (e: any) => void,
|
||||
setDisabled: (e: boolean) => void,
|
||||
closeModel: () => void,
|
||||
resetFields: () => void,
|
||||
}
|
||||
|
||||
type FormOptions = {
|
||||
|
||||
193
src/components/BasicNjBjPicker/example.vue
Normal file
193
src/components/BasicNjBjPicker/example.vue
Normal file
@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<view class="example-container">
|
||||
<view class="section">
|
||||
<view class="section-title">基础用法</view>
|
||||
<BasicNjBjPicker
|
||||
v-model="basicValue"
|
||||
@change="onBasicChange"
|
||||
/>
|
||||
<view class="result">
|
||||
选中值: {{ JSON.stringify(basicValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">在 useForm 中使用</view>
|
||||
<BasicForm @register="register" />
|
||||
<view class="result">
|
||||
表单值: {{ JSON.stringify(formValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">自定义样式</view>
|
||||
<BasicNjBjPicker
|
||||
v-model="customValue"
|
||||
placeholder="请选择年级班级"
|
||||
:customStyle="{
|
||||
backgroundColor: '#e6f7ff',
|
||||
borderColor: '#1890ff',
|
||||
borderRadius: '8px',
|
||||
padding: '12px 16px'
|
||||
}"
|
||||
icon-arrow="right"
|
||||
icon-color="#1890ff"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">禁用状态</view>
|
||||
<BasicNjBjPicker
|
||||
v-model="disabledValue"
|
||||
:disabled="true"
|
||||
placeholder="已禁用"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">操作按钮</view>
|
||||
<view class="button-group">
|
||||
<button @click="resetBasic">重置基础选择器</button>
|
||||
<button @click="setBasicValue">设置基础选择器值</button>
|
||||
<button @click="resetForm">重置表单</button>
|
||||
<button @click="setFormValue">设置表单值</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { BasicNjBjPicker } from '@/components/BasicNjBjPicker'
|
||||
import { useForm } from '@/components/BasicForm/hooks/useForm'
|
||||
|
||||
// 基础用法
|
||||
const basicValue = ref(null)
|
||||
const customValue = ref(null)
|
||||
const disabledValue = ref({
|
||||
nj: { key: '1', title: '一年级' },
|
||||
bj: { key: '1-1', title: '1班' }
|
||||
})
|
||||
|
||||
const onBasicChange = (nj: any, bj: any) => {
|
||||
console.log('基础选择器变化:', nj, bj)
|
||||
}
|
||||
|
||||
// useForm 用法
|
||||
const [register, { getValue, setValue, resetFields }] = useForm({
|
||||
schema: [
|
||||
{
|
||||
field: 'classInfo',
|
||||
label: '选择班级',
|
||||
component: BasicNjBjPicker,
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请选择班级',
|
||||
customStyle: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '8px',
|
||||
padding: '12px 15px'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'studentName',
|
||||
label: '学生姓名',
|
||||
component: 'BasicInput',
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请输入学生姓名'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const formValue = ref({})
|
||||
|
||||
// 监听表单值变化
|
||||
watch(() => getValue(), (newVal) => {
|
||||
formValue.value = newVal
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
// 操作按钮方法
|
||||
const resetBasic = () => {
|
||||
basicValue.value = null
|
||||
}
|
||||
|
||||
const setBasicValue = () => {
|
||||
basicValue.value = {
|
||||
nj: { key: '2', title: '二年级' },
|
||||
bj: { key: '2-1', title: '1班' },
|
||||
njId: '2',
|
||||
bjId: '2-1',
|
||||
njmc: '二年级',
|
||||
bjmc: '1班'
|
||||
}
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
resetFields()
|
||||
}
|
||||
|
||||
const setFormValue = () => {
|
||||
setValue({
|
||||
classInfo: {
|
||||
nj: { key: '3', title: '三年级' },
|
||||
bj: { key: '3-1', title: '1班' },
|
||||
njId: '3',
|
||||
bjId: '3-1',
|
||||
njmc: '三年级',
|
||||
bjmc: '1班'
|
||||
},
|
||||
studentName: '张三'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.example-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
padding: 30rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.button-group button {
|
||||
flex: 1;
|
||||
min-width: 200rpx;
|
||||
height: 70rpx;
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 35rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
4
src/components/BasicNjBjPicker/index.ts
Normal file
4
src/components/BasicNjBjPicker/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import BasicNjBjPicker from './index.vue'
|
||||
|
||||
export { BasicNjBjPicker }
|
||||
export default BasicNjBjPicker
|
||||
216
src/components/BasicNjBjPicker/index.vue
Normal file
216
src/components/BasicNjBjPicker/index.vue
Normal file
@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<picker mode="multiSelector" :range="njBjRange" :value="curIndex" @change="onMultiChange"
|
||||
@columnchange="onColumnChange">
|
||||
<view class="picker-item" :style="customStyle">
|
||||
<text>{{ curNjBjLabel || placeholder }}</text>
|
||||
<uni-icons :type="iconArrow" size="14" :color="iconColor"></uni-icons>
|
||||
</view>
|
||||
</picker>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { findAllNjBjTreeApi } from "@/api/base/server";
|
||||
|
||||
// 接收外部传入属性并设置默认值
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue?: any,
|
||||
defaultValue?: any,
|
||||
customStyle?: any,
|
||||
iconArrow?: string,
|
||||
iconColor?: string,
|
||||
placeholder?: string,
|
||||
disabled?: boolean
|
||||
}>(), {
|
||||
modelValue: null,
|
||||
defaultValue: null,
|
||||
customStyle: {},
|
||||
iconArrow: "bottom",
|
||||
iconColor: "#666",
|
||||
placeholder: "选择班级",
|
||||
disabled: false
|
||||
});
|
||||
|
||||
// 定义一个上级传入的emit响应事件用于接收数据变更
|
||||
const emit = defineEmits(['change', 'update:modelValue'])
|
||||
|
||||
const bjList = ref<any>([]);
|
||||
const njBjRange = ref<any>([[], []]);
|
||||
const curIndex = ref([0, 0]);
|
||||
const curNjBjLabel = ref("");
|
||||
const isLoading = ref(false);
|
||||
|
||||
// 监听 modelValue 变化
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal && newVal.nj && newVal.bj) {
|
||||
setValueByData(newVal.nj, newVal.bj);
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// 根据数据设置选择器值
|
||||
const setValueByData = (nj: any, bj: any) => {
|
||||
if (!nj || !bj || !bjList.value.length) return;
|
||||
|
||||
const njIndex = bjList.value.findIndex((item: any) => item.key === nj.key);
|
||||
if (njIndex === -1) return;
|
||||
|
||||
const bjIndex = bjList.value[njIndex].children.findIndex((item: any) => item.key === bj.key);
|
||||
if (bjIndex === -1) return;
|
||||
|
||||
curIndex.value = [njIndex, bjIndex];
|
||||
curNjBjLabel.value = nj.title + " " + bj.title;
|
||||
rebuildNjBjList(njIndex);
|
||||
};
|
||||
|
||||
const rebuildNjBjList = (njIndex: number) => {
|
||||
if (!bjList.value[njIndex] || !bjList.value[njIndex].children) return;
|
||||
const bjRange = bjList.value[njIndex].children.map((bj: any) => bj.title);
|
||||
njBjRange.value[1] = bjRange;
|
||||
}
|
||||
|
||||
const onChange = (index: any) => {
|
||||
if (props.disabled) return;
|
||||
|
||||
curIndex.value = index;
|
||||
if (index.length === 2 && index[0] >= 0 && index[1] >= 0) {
|
||||
const selectedNj = bjList.value[index[0]];
|
||||
const selectedBj = bjList.value[index[0]].children[index[1]];
|
||||
|
||||
curNjBjLabel.value = selectedNj.title + " " + selectedBj.title;
|
||||
|
||||
// 发送数据给父组件
|
||||
const result = {
|
||||
nj: selectedNj,
|
||||
bj: selectedBj,
|
||||
njId: selectedNj.key,
|
||||
bjId: selectedBj.key,
|
||||
njmc: selectedNj.title,
|
||||
bjmc: selectedBj.title,
|
||||
njmcId: selectedNj.njmcId // 添加 njmcId 字段用于保存
|
||||
};
|
||||
|
||||
console.log('📤 发送班级数据给父组件:', result);
|
||||
console.log('🔍 班级数据字段映射:', {
|
||||
'selectedNj.njmcId': selectedNj.njmcId,
|
||||
'result.njmcId': result.njmcId,
|
||||
'selectedNj.key': selectedNj.key,
|
||||
'result.njId': result.njId
|
||||
});
|
||||
|
||||
emit("change", selectedNj, selectedBj);
|
||||
emit("update:modelValue", result);
|
||||
} else {
|
||||
curNjBjLabel.value = "";
|
||||
emit("change", null, null);
|
||||
emit("update:modelValue", null);
|
||||
}
|
||||
}
|
||||
|
||||
const onMultiChange = (e: any) => {
|
||||
const index = e.detail.value;
|
||||
onChange(index);
|
||||
}
|
||||
|
||||
const onColumnChange = (e: any) => {
|
||||
const column = e.detail.column;
|
||||
const index = e.detail.value;
|
||||
if (column == 0) {
|
||||
rebuildNjBjList(index);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
if (isLoading.value) return;
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const res = await findAllNjBjTreeApi();
|
||||
bjList.value = res.result || [];
|
||||
|
||||
if (bjList.value.length > 0) {
|
||||
const njRange = bjList.value.map((nj: any) => nj.title);
|
||||
const bjRange = bjList.value[0].children?.map((bj: any) => bj.title) || [];
|
||||
njBjRange.value = [njRange, bjRange];
|
||||
|
||||
// 如果有默认值,设置默认选择
|
||||
if (props.defaultValue) {
|
||||
setValueByData(props.defaultValue.nj, props.defaultValue.bj);
|
||||
} else {
|
||||
onChange([0, 0]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载年级班级数据失败:', error);
|
||||
uni.showToast({
|
||||
title: '加载数据失败',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 暴露方法给父组件
|
||||
const reset = () => {
|
||||
curIndex.value = [0, 0];
|
||||
curNjBjLabel.value = "";
|
||||
emit("change", null, null);
|
||||
emit("update:modelValue", null);
|
||||
};
|
||||
|
||||
const setValue = (nj: any, bj: any) => {
|
||||
setValueByData(nj, bj);
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
reset,
|
||||
setValue,
|
||||
loadData
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
|
||||
// 如果有默认值,在数据加载后设置
|
||||
if (props.defaultValue && props.defaultValue.length > 0) {
|
||||
curIndex.value = props.defaultValue;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.picker-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 7px 15px;
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
justify-content: space-between;
|
||||
min-height: 40px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background-color: #e6f7ff;
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
text {
|
||||
margin-right: 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 0 0 80%; // 内容占80%宽度
|
||||
max-width: 80%; // 确保最大宽度不超过80%
|
||||
}
|
||||
|
||||
// 箭头容器,确保箭头始终显示
|
||||
.uni-icons {
|
||||
flex: 0 0 auto; // 箭头不缩放,保持固定大小
|
||||
margin-left: 8px; // 与文字保持间距
|
||||
}
|
||||
}
|
||||
</style>
|
||||
283
src/components/BasicXsPicker/example.vue
Normal file
283
src/components/BasicXsPicker/example.vue
Normal file
@ -0,0 +1,283 @@
|
||||
<template>
|
||||
<view class="example-container">
|
||||
<view class="section">
|
||||
<view class="section-title">基础用法(单独使用)</view>
|
||||
<BasicXsPicker
|
||||
v-model="basicValue"
|
||||
:nj-id="'1'"
|
||||
:bj-id="'1-1'"
|
||||
@change="onBasicChange"
|
||||
/>
|
||||
<view class="result">
|
||||
选中值: {{ JSON.stringify(basicValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">与 BasicNjBjPicker 联动使用</view>
|
||||
<BasicNjBjPicker
|
||||
v-model="classValue"
|
||||
@change="onClassChange"
|
||||
placeholder="请选择年级班级"
|
||||
/>
|
||||
<BasicXsPicker
|
||||
v-model="studentValue"
|
||||
:nj-id="classValue?.njId"
|
||||
:bj-id="classValue?.bjId"
|
||||
@change="onStudentChange"
|
||||
placeholder="请选择学生"
|
||||
/>
|
||||
<view class="result">
|
||||
班级信息: {{ JSON.stringify(classValue) }}
|
||||
</view>
|
||||
<view class="result">
|
||||
学生信息: {{ JSON.stringify(studentValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">在 useForm 中使用</view>
|
||||
<BasicForm @register="register" />
|
||||
<view class="result">
|
||||
表单值: {{ JSON.stringify(formValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">多年级班级选择</view>
|
||||
<BasicXsPicker
|
||||
v-model="multiValue"
|
||||
:nj-ids="['1', '2']"
|
||||
:bj-ids="['1-1', '2-1']"
|
||||
@change="onMultiChange"
|
||||
placeholder="请选择学生(多班级)"
|
||||
/>
|
||||
<view class="result">
|
||||
选中值: {{ JSON.stringify(multiValue) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="section">
|
||||
<view class="section-title">操作按钮</view>
|
||||
<view class="button-group">
|
||||
<button @click="resetBasic">重置基础选择器</button>
|
||||
<button @click="setBasicValue">设置基础选择器值</button>
|
||||
<button @click="resetForm">重置表单</button>
|
||||
<button @click="setFormValue">设置表单值</button>
|
||||
<button @click="reloadStudents">重新加载学生数据</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { BasicNjBjPicker } from '@/components/BasicNjBjPicker'
|
||||
import { BasicXsPicker } from '@/components/BasicXsPicker'
|
||||
import { useForm } from '@/components/BasicForm/hooks/useForm'
|
||||
|
||||
// 基础用法
|
||||
const basicValue = ref(null)
|
||||
const multiValue = ref(null)
|
||||
|
||||
// 联动用法
|
||||
const classValue = ref<any>(null)
|
||||
const studentValue = ref<any>(null)
|
||||
|
||||
// useForm 用法
|
||||
const [register, { getValue, setValue, resetFields }] = useForm({
|
||||
schema: [
|
||||
{
|
||||
field: 'classInfo',
|
||||
label: '选择班级',
|
||||
component: 'BasicNjBjPicker',
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请选择班级'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'studentInfo',
|
||||
label: '选择学生',
|
||||
component: 'BasicXsPicker',
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请先选择班级',
|
||||
// 通过计算属性获取班级信息
|
||||
njId: () => getValue().classInfo?.njId,
|
||||
bjId: () => getValue().classInfo?.bjId
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'studentName',
|
||||
label: '学生姓名',
|
||||
component: 'BasicInput',
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请输入学生姓名'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const formValue = ref({})
|
||||
|
||||
// 监听表单值变化
|
||||
watch(() => getValue(), (newVal) => {
|
||||
formValue.value = newVal
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
// 基础功能测试
|
||||
const onBasicChange = (student: any) => {
|
||||
console.log('基础选择器变化:', student)
|
||||
uni.showToast({
|
||||
title: `选择了学生: ${student?.xsxm}`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
// 联动功能测试
|
||||
const onClassChange = (nj: any, bj: any) => {
|
||||
console.log('班级变化:', nj, bj)
|
||||
// 班级变化时清空学生选择
|
||||
studentValue.value = null
|
||||
uni.showToast({
|
||||
title: `选择了班级: ${nj?.title} ${bj?.title}`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
const onStudentChange = (student: any) => {
|
||||
console.log('学生变化:', student)
|
||||
uni.showToast({
|
||||
title: `选择了学生: ${student?.xsxm}`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
const onMultiChange = (student: any) => {
|
||||
console.log('多班级选择器变化:', student)
|
||||
uni.showToast({
|
||||
title: `选择了学生: ${student?.xsxm}`,
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
// 测试方法
|
||||
const resetBasic = () => {
|
||||
basicValue.value = null
|
||||
uni.showToast({
|
||||
title: '已重置',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const setBasicValue = () => {
|
||||
// 这里需要根据实际的学生数据设置
|
||||
basicValue.value = {
|
||||
xsId: '1',
|
||||
xsxm: '张三',
|
||||
njId: '1',
|
||||
bjId: '1-1',
|
||||
njmc: '一年级',
|
||||
bjmc: '1班'
|
||||
} as any
|
||||
uni.showToast({
|
||||
title: '已设置测试值',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
resetFields()
|
||||
uni.showToast({
|
||||
title: '表单已重置',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const setFormValue = () => {
|
||||
setValue({
|
||||
classInfo: {
|
||||
njId: '2',
|
||||
bjId: '2-1',
|
||||
njmc: '二年级',
|
||||
bjmc: '1班'
|
||||
},
|
||||
studentInfo: {
|
||||
xsId: '2',
|
||||
xsxm: '李四',
|
||||
njId: '2',
|
||||
bjId: '2-1',
|
||||
njmc: '二年级',
|
||||
bjmc: '1班'
|
||||
},
|
||||
studentName: '李四'
|
||||
})
|
||||
uni.showToast({
|
||||
title: '已设置表单值',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const reloadStudents = () => {
|
||||
// 这里可以调用组件的 reload 方法
|
||||
uni.showToast({
|
||||
title: '重新加载学生数据',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.example-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 40rpx;
|
||||
padding: 30rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
padding-bottom: 10rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8rpx;
|
||||
border-left: 4rpx solid #007aff;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.button-group button {
|
||||
flex: 1;
|
||||
min-width: 200rpx;
|
||||
height: 70rpx;
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 35rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
4
src/components/BasicXsPicker/index.ts
Normal file
4
src/components/BasicXsPicker/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import BasicXsPicker from './index.vue'
|
||||
|
||||
export { BasicXsPicker }
|
||||
export default BasicXsPicker
|
||||
816
src/components/BasicXsPicker/index.vue
Normal file
816
src/components/BasicXsPicker/index.vue
Normal file
@ -0,0 +1,816 @@
|
||||
<template>
|
||||
<!-- 选择器触发按钮 -->
|
||||
<view class="picker-item" :style="customStyle" @click="showPicker">
|
||||
<text>{{ curStudentLabel || displayPlaceholder }}</text>
|
||||
<uni-icons :type="iconArrow" size="14" :color="iconColor"></uni-icons>
|
||||
</view>
|
||||
|
||||
<!-- 弹窗选择器 -->
|
||||
<u-popup :show="showPopup" @close="showPopup=false">
|
||||
<view class="student-picker-container">
|
||||
<!-- 头部 -->
|
||||
<view class="popup-header">
|
||||
<view class="header-left" @click="handleCancel">
|
||||
<text class="cancel-text">取消</text>
|
||||
</view>
|
||||
<view class="header-center">
|
||||
<text class="header-title">请选择学生</text>
|
||||
</view>
|
||||
<view class="header-right" @click="handleConfirm">
|
||||
<text class="confirm-text">确定</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-section">
|
||||
<view class="search-box">
|
||||
<uni-icons type="search" size="16" color="#999" class="search-icon"></uni-icons>
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
class="search-input"
|
||||
placeholder="输入学生姓名查询"
|
||||
@input="onSearchInput"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 学生列表 -->
|
||||
<view class="student-list">
|
||||
<view
|
||||
v-for="(student, index) in filteredStudentList"
|
||||
:key="student.id || index"
|
||||
class="student-item"
|
||||
:class="{ selected: selectedStudent && selectedStudent.id === student.id }"
|
||||
@click="selectStudent(student)"
|
||||
>
|
||||
<text class="student-name">{{ student.xm }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="filteredStudentList.length === 0 && !isLoading" class="empty-state">
|
||||
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
|
||||
<text class="empty-text">
|
||||
{{ searchKeyword ? '未找到匹配的学生' : '暂无学生数据' }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="isLoading" class="loading-state">
|
||||
<uni-icons type="spinner-cycle" size="40" color="#007aff"></uni-icons>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { findStudentInfoByNjAndBjApi } from "@/api/base/student";
|
||||
|
||||
// 接收外部传入属性并设置默认值
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue?: any,
|
||||
defaultValue?: any,
|
||||
customStyle?: any,
|
||||
iconArrow?: string,
|
||||
iconColor?: string,
|
||||
placeholder?: string,
|
||||
disabled?: boolean,
|
||||
njId?: string,
|
||||
bjId?: string,
|
||||
njIds?: string[],
|
||||
bjIds?: string[],
|
||||
autoLoad?: boolean,
|
||||
classInfo?: any,
|
||||
studentData?: any[],
|
||||
range?: string[] // 参考 BasicPicker 的设计,直接传递选项数组
|
||||
}>(), {
|
||||
modelValue: null,
|
||||
defaultValue: null,
|
||||
customStyle: {},
|
||||
iconArrow: "bottom",
|
||||
iconColor: "#666",
|
||||
placeholder: "选择学生",
|
||||
disabled: false,
|
||||
njId: "",
|
||||
bjId: "",
|
||||
njIds: () => [],
|
||||
bjIds: () => [],
|
||||
autoLoad: true,
|
||||
classInfo: null,
|
||||
studentData: () => [],
|
||||
range: () => []
|
||||
});
|
||||
|
||||
// 定义一个上级传入的emit响应事件用于接收数据变更
|
||||
const emit = defineEmits(['change', 'update:modelValue', 'getClassInfo'])
|
||||
|
||||
const studentList = ref<any>([]);
|
||||
const studentRange = ref<string[]>([]);
|
||||
const curIndex = ref(0);
|
||||
const curStudentLabel = ref("");
|
||||
const isLoading = ref(false);
|
||||
const isUserSelecting = ref(false); // 标志用户是否正在选择
|
||||
|
||||
// 弹窗相关状态
|
||||
const showPopup = ref(false);
|
||||
const searchKeyword = ref("");
|
||||
const selectedStudent = ref<any>(null);
|
||||
const filteredStudentList = ref<any>([]);
|
||||
|
||||
// 辅助函数:安全地获取值
|
||||
const getValue = (value: any) => {
|
||||
return value;
|
||||
};
|
||||
|
||||
// 计算占位符文本
|
||||
const displayPlaceholder = computed(() => {
|
||||
// 如果没有年级班级信息,显示提示信息
|
||||
if (!props.njId && !props.bjId && (!props.njIds || props.njIds.length === 0) && (!props.bjIds || props.bjIds.length === 0)) {
|
||||
return "请先选择年级班级";
|
||||
}
|
||||
return props.placeholder;
|
||||
});
|
||||
|
||||
// 搜索过滤逻辑
|
||||
const filterStudents = (students: any[], keyword: string) => {
|
||||
if (!keyword.trim()) {
|
||||
return students;
|
||||
}
|
||||
return students.filter(student =>
|
||||
student.xm && student.xm.toLowerCase().includes(keyword.toLowerCase())
|
||||
);
|
||||
};
|
||||
|
||||
// 根据数据设置选择器值
|
||||
const setValueByData = (student: any) => {
|
||||
if (!student || !student.id || !studentList.value.length) return;
|
||||
|
||||
const studentIndex = studentList.value.findIndex((item: any) => item.id === student.id);
|
||||
if (studentIndex === -1) return;
|
||||
|
||||
curIndex.value = studentIndex;
|
||||
curStudentLabel.value = student.xm;
|
||||
};
|
||||
|
||||
// 显示选择器弹窗
|
||||
const showPicker = async () => {
|
||||
console.log('🖱️ 用户点击学生选择器');
|
||||
|
||||
// 设置用户选择标志
|
||||
isUserSelecting.value = true;
|
||||
|
||||
// 清空搜索关键词
|
||||
searchKeyword.value = "";
|
||||
|
||||
// 如果已经有学生数据,直接显示弹窗
|
||||
if (studentList.value.length > 0) {
|
||||
console.log('✅ 学生数据已存在,直接显示弹窗');
|
||||
filteredStudentList.value = studentList.value;
|
||||
showPopup.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果正在加载中,不重复加载
|
||||
if (isLoading.value) {
|
||||
console.log('⏳ 正在加载中,请稍候');
|
||||
return;
|
||||
}
|
||||
|
||||
// 直接尝试从父组件获取班级信息
|
||||
console.log('📞 尝试从父组件获取班级信息');
|
||||
|
||||
// 通过 emit 请求父组件提供班级信息
|
||||
emit('getClassInfo');
|
||||
|
||||
// 延迟一下,给父组件时间处理
|
||||
setTimeout(() => {
|
||||
console.log('⏰ 延迟检查是否获取到班级信息');
|
||||
console.log('🔍 当前 props.classInfo:', props.classInfo);
|
||||
|
||||
// 如果 props.classInfo 有值,直接使用
|
||||
if (props.classInfo && props.classInfo.njId && props.classInfo.bjId) {
|
||||
console.log('✅ 发现 props.classInfo,直接加载学生数据');
|
||||
loadStudentDataByClassInfo(props.classInfo);
|
||||
} else {
|
||||
console.log('❌ 没有获取到班级信息,尝试直接调用API');
|
||||
// 尝试直接调用API,使用默认的年级班级ID
|
||||
// 这里需要从全局状态或者其他地方获取班级信息
|
||||
// 暂时先显示提示
|
||||
uni.showToast({
|
||||
title: '请先选择年级班级',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// 暴露方法给父组件调用
|
||||
const loadStudentDataByClassInfo = async (classInfo: any) => {
|
||||
console.log('🔄 通过班级信息加载学生数据:', classInfo);
|
||||
|
||||
if (!classInfo || !classInfo.njId || !classInfo.bjId) {
|
||||
console.log('⚠️ 班级信息不完整,清空学生数据');
|
||||
clearStudentData();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isLoading.value = true;
|
||||
console.log('🚀 开始加载学生数据');
|
||||
|
||||
const params = {
|
||||
njId: classInfo.njId,
|
||||
bjIds: [classInfo.bjId]
|
||||
};
|
||||
|
||||
console.log('📤 发送API请求,参数:', params);
|
||||
const res = await findStudentInfoByNjAndBjApi(params);
|
||||
|
||||
if (res && res.result && res.result.length > 0) {
|
||||
console.log('✅ 学生数据加载成功:', res.result);
|
||||
studentList.value = res.result;
|
||||
studentRange.value = res.result.map((item: any) => item.xm || '');
|
||||
|
||||
// 更新过滤列表
|
||||
filteredStudentList.value = studentList.value;
|
||||
|
||||
// 如果有默认值,设置选中项
|
||||
if (props.modelValue) {
|
||||
const index = studentList.value.findIndex((item: any) => item.id === props.modelValue);
|
||||
if (index >= 0) {
|
||||
curIndex.value = index;
|
||||
curStudentLabel.value = studentRange.value[index];
|
||||
}
|
||||
} else {
|
||||
// 没有默认值时,不设置 curIndex,保持弹窗打开状态
|
||||
console.log('🎯 不自动选择,等待用户手动选择');
|
||||
curStudentLabel.value = "";
|
||||
}
|
||||
|
||||
// 如果弹窗已打开,显示学生列表
|
||||
if (showPopup.value) {
|
||||
console.log('📋 弹窗已打开,显示学生列表');
|
||||
}
|
||||
} else {
|
||||
console.log('⚠️ 没有找到学生数据');
|
||||
clearStudentData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 加载学生数据失败:', error);
|
||||
clearStudentData();
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 直接设置学生数据的方法
|
||||
const setStudentData = (data: any[]) => {
|
||||
console.log('🔄 直接设置学生数据:', data?.length, '个学生');
|
||||
|
||||
if (data && data.length > 0) {
|
||||
console.log('✅ 设置学生数据成功');
|
||||
studentList.value = data;
|
||||
studentRange.value = data.map((item: any) => item.xm || '');
|
||||
|
||||
// 更新过滤列表
|
||||
filteredStudentList.value = studentList.value;
|
||||
|
||||
console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项
|
||||
|
||||
// 如果有默认值,设置选中项
|
||||
if (props.modelValue) {
|
||||
const index = studentList.value.findIndex((item: any) => item.id === props.modelValue);
|
||||
if (index >= 0) {
|
||||
curIndex.value = index;
|
||||
curStudentLabel.value = studentRange.value[index];
|
||||
}
|
||||
}
|
||||
|
||||
console.log('🎯 学生选择器状态更新完成:', {
|
||||
studentListLength: studentList.value.length,
|
||||
studentRangeLength: studentRange.value.length,
|
||||
curIndex: curIndex.value,
|
||||
curStudentLabel: curStudentLabel.value
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ 学生数据为空,清空数据');
|
||||
clearStudentData();
|
||||
}
|
||||
};
|
||||
|
||||
// 清空学生数据
|
||||
const clearStudentData = () => {
|
||||
studentList.value = [];
|
||||
studentRange.value = [];
|
||||
filteredStudentList.value = [];
|
||||
curIndex.value = 0;
|
||||
curStudentLabel.value = "";
|
||||
selectedStudent.value = null;
|
||||
emit('update:modelValue', null);
|
||||
emit('change', null);
|
||||
};
|
||||
|
||||
// 搜索输入处理
|
||||
const onSearchInput = () => {
|
||||
console.log('🔍 搜索关键词:', searchKeyword.value);
|
||||
filteredStudentList.value = filterStudents(studentList.value, searchKeyword.value);
|
||||
};
|
||||
|
||||
// 选择学生
|
||||
const selectStudent = (student: any) => {
|
||||
console.log('🎯 选择学生:', student);
|
||||
selectedStudent.value = student;
|
||||
};
|
||||
|
||||
// 取消操作
|
||||
const handleCancel = () => {
|
||||
console.log('❌ 取消选择');
|
||||
showPopup.value = false;
|
||||
selectedStudent.value = null;
|
||||
};
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
console.log('✅ 确认选择:', selectedStudent.value);
|
||||
|
||||
if (props.disabled) {
|
||||
console.log('⏸️ 组件已禁用,跳过处理');
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedStudent.value) {
|
||||
const student = selectedStudent.value;
|
||||
console.log('✅ 选中的学生:', student);
|
||||
curStudentLabel.value = student.xm;
|
||||
|
||||
// 发送数据给父组件
|
||||
const result = {
|
||||
id: student.id,
|
||||
xsId: student.id, // 添加 xsId 字段,与 id 保持一致
|
||||
xm: student.xm,
|
||||
xsxm: student.xm, // 添加 xsxm 字段,与 xm 保持一致
|
||||
studentName: student.xm, // 添加 studentName 字段,与 xm 保持一致
|
||||
njId: student.njId,
|
||||
bjId: student.bjId,
|
||||
njmc: student.njmc,
|
||||
bjmc: student.bjmc,
|
||||
jzIds: student.jzIds,
|
||||
jzxm: student.jzxm,
|
||||
student: student
|
||||
};
|
||||
|
||||
console.log('📤 发送给父组件的数据:', result);
|
||||
console.log('🔍 学生数据字段映射:', {
|
||||
'student.id': student.id,
|
||||
'result.xsId': result.xsId,
|
||||
'student.xm': student.xm,
|
||||
'result.xsxm': result.xsxm,
|
||||
'result.studentName': result.studentName
|
||||
});
|
||||
emit("change", student);
|
||||
emit("update:modelValue", result);
|
||||
} else {
|
||||
console.log('❌ 未选择学生');
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
showPopup.value = false;
|
||||
selectedStudent.value = null;
|
||||
};
|
||||
|
||||
// 加载学生数据
|
||||
const loadStudentData = async () => {
|
||||
console.log('🔄 加载学生数据,年级班级:', {
|
||||
njId: props.njId,
|
||||
bjId: props.bjId,
|
||||
njIds: props.njIds,
|
||||
bjIds: props.bjIds,
|
||||
autoLoad: props.autoLoad
|
||||
});
|
||||
|
||||
if (isLoading.value) {
|
||||
console.log('⏳ 正在加载中,跳过');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有年级班级信息
|
||||
if (!props.njId && !props.bjId && (!props.njIds || props.njIds.length === 0) && (!props.bjIds || props.bjIds.length === 0)) {
|
||||
console.log('⚠️ 没有年级班级信息,清空数据');
|
||||
// 如果没有年级班级信息,清空学生列表并显示占位符
|
||||
studentList.value = [];
|
||||
studentRange.value = [];
|
||||
curStudentLabel.value = "";
|
||||
// 发送空值给父组件
|
||||
emit("change", null);
|
||||
emit("update:modelValue", null);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🚀 开始加载学生数据');
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const params: any = {};
|
||||
|
||||
// 设置查询参数
|
||||
if (props.njId) {
|
||||
params.njId = props.njId;
|
||||
} else if (props.njIds && props.njIds.length > 0) {
|
||||
params.njId = props.njIds[0]; // 取第一个年级ID
|
||||
}
|
||||
|
||||
if (props.bjId) {
|
||||
params.bjIds = [props.bjId];
|
||||
} else if (props.bjIds && props.bjIds.length > 0) {
|
||||
params.bjIds = props.bjIds;
|
||||
}
|
||||
|
||||
console.log('📤 发送API请求,参数:', params);
|
||||
const res = await findStudentInfoByNjAndBjApi(params);
|
||||
console.log('📥 API响应:', res);
|
||||
studentList.value = res.result || [];
|
||||
|
||||
if (studentList.value.length > 0) {
|
||||
console.log('✅ 成功加载学生数据,数量:', studentList.value.length);
|
||||
studentRange.value = studentList.value.map((student: any) => student.xm);
|
||||
|
||||
// 更新过滤列表
|
||||
filteredStudentList.value = studentList.value;
|
||||
|
||||
console.log('📋 学生选项列表:', studentRange.value);
|
||||
|
||||
// 如果有默认值,设置默认选择
|
||||
if (props.defaultValue) {
|
||||
console.log('🎯 设置默认值:', props.defaultValue);
|
||||
setValueByData(props.defaultValue);
|
||||
} else {
|
||||
console.log('🎯 不自动选择,等待用户手动选择');
|
||||
// 不自动选择第一个学生,让用户手动选择
|
||||
// 不设置 curIndex,保持弹窗打开状态
|
||||
curStudentLabel.value = "";
|
||||
}
|
||||
} else {
|
||||
console.log('❌ 没有加载到学生数据');
|
||||
studentRange.value = [];
|
||||
filteredStudentList.value = [];
|
||||
curStudentLabel.value = "";
|
||||
emit("change", null);
|
||||
emit("update:modelValue", null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 加载学生数据失败:', error);
|
||||
uni.showToast({
|
||||
title: '加载学生数据失败',
|
||||
icon: 'none'
|
||||
});
|
||||
studentList.value = [];
|
||||
studentRange.value = [];
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
console.log('🏁 loadStudentData 完成');
|
||||
}
|
||||
};
|
||||
|
||||
// 监听 modelValue 变化
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal && newVal.id) {
|
||||
setValueByData(newVal);
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// 监听年级班级变化,自动加载学生数据
|
||||
watch([() => props.njId, () => props.bjId, () => props.njIds, () => props.bjIds], (newValues, oldValues) => {
|
||||
console.log('👀 年级班级变化:', {
|
||||
newValues,
|
||||
oldValues,
|
||||
autoLoad: props.autoLoad
|
||||
});
|
||||
|
||||
if (props.autoLoad) {
|
||||
console.log('🔄 触发自动加载学生数据');
|
||||
loadStudentData();
|
||||
} else {
|
||||
console.log('⏸️ autoLoad 为 false,跳过加载');
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 监听 classInfo 变化,自动加载学生数据
|
||||
watch(() => props.classInfo, (newClassInfo, oldClassInfo) => {
|
||||
console.log('👀 classInfo 变化:', {
|
||||
newClassInfo,
|
||||
oldClassInfo
|
||||
});
|
||||
|
||||
if (newClassInfo && newClassInfo.njId && newClassInfo.bjId) {
|
||||
console.log('🔄 通过 classInfo 加载学生数据');
|
||||
loadStudentDataByClassInfo(newClassInfo);
|
||||
} else {
|
||||
console.log('⚠️ classInfo 不完整,清空学生数据');
|
||||
clearStudentData();
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 监听 studentData 变化,直接设置学生数据(参考 BasicPicker 的设计模式)
|
||||
watch(() => props.studentData, (newStudentData, oldStudentData) => {
|
||||
console.log('👀 studentData 变化:', {
|
||||
newStudentData,
|
||||
oldStudentData,
|
||||
newStudentDataLength: newStudentData?.length,
|
||||
oldStudentDataLength: oldStudentData?.length
|
||||
});
|
||||
|
||||
if (newStudentData && newStudentData.length > 0) {
|
||||
console.log('✅ 接收到学生数据,直接设置');
|
||||
console.log('📊 学生数据详情:', newStudentData.slice(0, 3)); // 只显示前3个学生
|
||||
|
||||
// 直接设置数据,参考 BasicPicker 的模式
|
||||
studentList.value = newStudentData;
|
||||
studentRange.value = newStudentData.map((item: any) => item.xm || ''); // 使用正确的字段名 xm
|
||||
|
||||
// 更新过滤列表
|
||||
filteredStudentList.value = studentList.value;
|
||||
|
||||
console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项
|
||||
|
||||
// 如果有默认值,设置选中项
|
||||
if (props.modelValue) {
|
||||
const index = studentList.value.findIndex((item: any) => item.id === props.modelValue);
|
||||
if (index >= 0) {
|
||||
curIndex.value = index;
|
||||
curStudentLabel.value = studentRange.value[index];
|
||||
}
|
||||
} else {
|
||||
// 没有默认值时,不设置 curIndex,保持弹窗打开状态
|
||||
curStudentLabel.value = "";
|
||||
}
|
||||
|
||||
console.log('🎯 学生选择器状态更新完成:', {
|
||||
studentListLength: studentList.value.length,
|
||||
studentRangeLength: studentRange.value.length,
|
||||
curIndex: curIndex.value,
|
||||
curStudentLabel: curStudentLabel.value
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ 学生数据为空,清空数据');
|
||||
clearStudentData();
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 监听 range 变化,直接设置学生数据(参考 BasicPicker 的设计模式)
|
||||
watch(() => props.range, (newRange, oldRange) => {
|
||||
console.log('👀 range 变化:', {
|
||||
newRange,
|
||||
oldRange,
|
||||
newRangeLength: newRange?.length,
|
||||
oldRangeLength: oldRange?.length
|
||||
});
|
||||
|
||||
if (newRange && newRange.length > 0) {
|
||||
console.log('✅ 接收到 range 数据,直接设置');
|
||||
|
||||
// 直接设置数据,参考 BasicPicker 的模式
|
||||
studentRange.value = newRange;
|
||||
|
||||
console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项
|
||||
|
||||
console.log('🎯 学生选择器状态更新完成:', {
|
||||
studentRangeLength: studentRange.value.length,
|
||||
curIndex: curIndex.value,
|
||||
curStudentLabel: curStudentLabel.value
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ range 数据为空,清空数据');
|
||||
clearStudentData();
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
// 暴露方法给父组件
|
||||
const reset = () => {
|
||||
curIndex.value = 0;
|
||||
curStudentLabel.value = "";
|
||||
emit("change", null);
|
||||
emit("update:modelValue", null);
|
||||
};
|
||||
|
||||
const setValue = (student: any) => {
|
||||
setValueByData(student);
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
loadStudentData();
|
||||
};
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
reset,
|
||||
setValue,
|
||||
reload,
|
||||
loadStudentData,
|
||||
loadStudentDataByClassInfo,
|
||||
setStudentData,
|
||||
showPicker
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
console.log('🚀 组件已挂载,props:', {
|
||||
njId: props.njId,
|
||||
bjId: props.bjId,
|
||||
autoLoad: props.autoLoad,
|
||||
classInfo: props.classInfo,
|
||||
studentData: props.studentData,
|
||||
range: props.range,
|
||||
studentDataLength: props.studentData?.length,
|
||||
rangeLength: props.range?.length
|
||||
});
|
||||
if (props.autoLoad) {
|
||||
loadStudentData();
|
||||
}
|
||||
});
|
||||
|
||||
// 监听 props 变化
|
||||
watch(() => [props.njId, props.bjId, props.njIds, props.bjIds], (newValues, oldValues) => {
|
||||
console.log('🔍 Props 变化监听:', {
|
||||
newValues,
|
||||
oldValues,
|
||||
props: {
|
||||
njId: props.njId,
|
||||
bjId: props.bjId,
|
||||
njIds: props.njIds,
|
||||
bjIds: props.bjIds
|
||||
}
|
||||
});
|
||||
}, { immediate: true, deep: true });
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.picker-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 7px 15px;
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 16px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
justify-content: space-between;
|
||||
min-height: 40px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background-color: #e6f7ff;
|
||||
border-color: #1890ff;
|
||||
}
|
||||
|
||||
text {
|
||||
margin-right: 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 0 0 80%; // 内容占80%宽度
|
||||
max-width: 80%; // 确保最大宽度不超过80%
|
||||
}
|
||||
|
||||
// 箭头容器,确保箭头始终显示
|
||||
.uni-icons {
|
||||
flex: 0 0 auto; // 箭头不缩放,保持固定大小
|
||||
margin-left: 8px; // 与文字保持间距
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗样式
|
||||
.student-picker-container {
|
||||
background-color: #fff;
|
||||
border-radius: 16px 16px 0 0;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header-left, .header-right {
|
||||
flex: 0 0 auto;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.cancel-text {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.confirm-text {
|
||||
color: #007aff;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.header-center {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.search-section {
|
||||
padding: 15px 20px;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 8px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.student-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.student-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:active {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: #e6f7ff;
|
||||
|
||||
.student-name {
|
||||
color: #007aff;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.student-name {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.empty-state, .loading-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.empty-text, .loading-text {
|
||||
margin-top: 15px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.loading-state {
|
||||
.loading-text {
|
||||
color: #007aff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -249,13 +249,20 @@ const sections = reactive<Section[]>([
|
||||
},
|
||||
{
|
||||
id: "r5",
|
||||
icon: "hc-fill",
|
||||
icon: "stxc",
|
||||
text: "食堂巡查",
|
||||
show: true,
|
||||
permissionKey: "routine-stxc", // 食堂巡查权限编码
|
||||
path: "/pages/view/routine/ShiTangXunCha/index",
|
||||
},
|
||||
|
||||
{
|
||||
id: "r5",
|
||||
icon: "yrcg",
|
||||
text: "一日常规",
|
||||
show: true,
|
||||
permissionKey: "routine-yrcg", // 一日常规权限编码
|
||||
path: "/pages/view/quantitativeAssessment/index/index",
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
@ -105,6 +105,7 @@ import {onShow} from "@dcloudio/uni-app";
|
||||
import {deptFindByPidApi, dicApi} from "@/api/system/dic";
|
||||
import {useForm} from "@/components/BasicForm/hooks/useForm";
|
||||
import {getUserViewApi} from "@/api/system/login";
|
||||
import {BasicNjBjPicker} from "@/components/BasicNjBjPicker";
|
||||
|
||||
function setItemValue() {
|
||||
console.log(444,value.value)
|
||||
@ -122,37 +123,18 @@ function setItemValue() {
|
||||
const [register, {getValue, setSchema, setValue}] = useForm({
|
||||
schema: [
|
||||
{
|
||||
field: "grade",
|
||||
label: "年级",
|
||||
component: "BasicPickerCheckbox",
|
||||
field: "classInfo",
|
||||
label: "年级班级",
|
||||
component: "BasicNjBjPicker",
|
||||
required: true,
|
||||
componentProps: {
|
||||
api: deptFindByPidApi,
|
||||
param: {pid: 1},
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id',
|
||||
ok: async (ysave: any, svalue: any, range: any) => {
|
||||
let res = await deptFindByPidApi({pid: svalue});
|
||||
setSchema([{
|
||||
field: "gradeClassId",
|
||||
componentProps: {
|
||||
range: res.result,
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id'
|
||||
}
|
||||
}])
|
||||
placeholder: "请选择年级班级",
|
||||
customStyle: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '8px',
|
||||
padding: '12px 15px'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
field: "gradeClassId",
|
||||
label: "班级",
|
||||
component: "BasicPickerCheckbox",
|
||||
required: true,
|
||||
componentProps: {
|
||||
// api: gradeClassFindAllsApi,
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -272,10 +254,12 @@ async function submit() {
|
||||
return;
|
||||
}
|
||||
let values = await getValue();
|
||||
if (values.gradeClassId) {
|
||||
|
||||
// 处理 classInfo 数据,提取 bjId
|
||||
if (values.classInfo && values.classInfo.bjId) {
|
||||
await evaluationSaveApi({
|
||||
itemList: itemList,
|
||||
gradeClassId: values.gradeClassId
|
||||
bjId: values.classInfo.bjId
|
||||
});
|
||||
showToast({title: "操作成功"});
|
||||
navigateBack({delta: 1})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<view class="p-15">
|
||||
<BasicForm @register="register"></BasicForm>
|
||||
<BasicForm @register="register" @getClassInfo="handleGetClassInfo"></BasicForm>
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="white-bg-color py-5" v-if="!isDisabled">
|
||||
@ -15,33 +15,29 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {useForm} from "@/components/BasicForm/hooks/useForm";
|
||||
import {deptFindByPidApi} from "@/api/system/dic";
|
||||
import {deptFindAllGradeClassApi, gradeClassFindAllsApi, readyToGoSaveApi} from "@/api/base/assesment";
|
||||
import {readyToGoSaveApi} from "@/api/base/assesment";
|
||||
import {navigateBack, showToast} from "@/utils/uniapp";
|
||||
import {useDataStore} from "@/store/modules/data";
|
||||
import {BasicNjBjPicker} from "@/components/BasicNjBjPicker";
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
const {getData} = useDataStore()
|
||||
|
||||
|
||||
const classData: any = ref([]);
|
||||
getClassData();
|
||||
|
||||
async function getClassData() {
|
||||
let res = await gradeClassFindAllsApi();
|
||||
classData.value = res.result;
|
||||
}
|
||||
|
||||
function reloadGrade(params) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < classData.value.length; i++) {
|
||||
if (classData.value[i].grade == params.grade) {
|
||||
arr.push(classData.value[i]);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
const isDisabled = ref(false)
|
||||
const studentPickerKey = ref(0) // 用于强制重新渲染学生选择器
|
||||
const studentPickerRef = ref<any>(null) // 学生选择器组件引用
|
||||
|
||||
// 处理学生选择器请求班级信息
|
||||
const handleGetClassInfo = async () => {
|
||||
|
||||
};
|
||||
|
||||
// 监听学生选择器的点击事件
|
||||
const handleStudentPickerClick = async () => {
|
||||
console.log('🖱️ 监听到学生选择器点击事件');
|
||||
await handleGetClassInfo();
|
||||
};
|
||||
|
||||
const [register, {getValue, setSchema, setValue, setDisabled}] = useForm({
|
||||
schema: [
|
||||
{
|
||||
@ -56,47 +52,32 @@ const [register, {getValue, setSchema, setValue, setDisabled}] = useForm({
|
||||
]
|
||||
}
|
||||
}, {
|
||||
field: "grade",
|
||||
label: "年级",
|
||||
component: "BasicPickerCheckbox",
|
||||
field: "classInfo",
|
||||
label: "年级班级",
|
||||
component: "BasicNjBjPicker",
|
||||
required: false,
|
||||
ifShow(item) {
|
||||
return getData._show;
|
||||
},
|
||||
componentProps: {
|
||||
api: deptFindByPidApi,
|
||||
param: {pid: 1},
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id',
|
||||
ok: async (ysave: any, svalue: any, range: any) => {
|
||||
let res = await deptFindByPidApi({pid: svalue});
|
||||
console.log(222, res)
|
||||
setSchema([{
|
||||
field: "gradeClassId",
|
||||
componentProps: {
|
||||
range: res.result,
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id'
|
||||
}
|
||||
}])
|
||||
placeholder: "请选择年级班级",
|
||||
customStyle: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: '8px',
|
||||
padding: '12px 15px'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
field: "gradeClassId",
|
||||
label: "班级",
|
||||
component: "BasicPickerCheckbox",
|
||||
field: "studentInfo",
|
||||
label: "学生",
|
||||
component: "BasicXsPicker",
|
||||
required: false,
|
||||
componentProps: {
|
||||
api: deptFindAllGradeClassApi,
|
||||
rangeKey: 'deptName',
|
||||
savaKey: 'id'
|
||||
placeholder: "请选择学生",
|
||||
key: studentPickerKey.value,
|
||||
ref: studentPickerRef,
|
||||
onClick: handleStudentPickerClick
|
||||
}
|
||||
}, {
|
||||
field: "studentName",
|
||||
label: "学生",
|
||||
component: "BasicInput",
|
||||
required: false,
|
||||
componentProps: {}
|
||||
},
|
||||
{
|
||||
field: "content",
|
||||
@ -175,6 +156,79 @@ const [register, {getValue, setSchema, setValue, setDisabled}] = useForm({
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
// 延迟启动监听,确保表单完全初始化
|
||||
setTimeout(() => {
|
||||
|
||||
// 使用 ref 来存储班级信息
|
||||
const classInfo = ref(null);
|
||||
|
||||
// 定期检查班级信息变化
|
||||
const checkClassInfo = async () => {
|
||||
try {
|
||||
const formValue = await getValue(false); // 不验证,只获取值
|
||||
const newClassInfo = formValue?.classInfo;
|
||||
|
||||
if (JSON.stringify(newClassInfo) !== JSON.stringify(classInfo.value)) {
|
||||
classInfo.value = newClassInfo;
|
||||
|
||||
if (newClassInfo && newClassInfo.njId && newClassInfo.bjId) {
|
||||
|
||||
// 先清空学生选择器的值
|
||||
setValue({ studentInfo: null });
|
||||
|
||||
// 强制重新渲染学生选择器
|
||||
studentPickerKey.value++;
|
||||
|
||||
// 更新学生选择器的配置
|
||||
setSchema([{
|
||||
field: 'studentInfo',
|
||||
componentProps: {
|
||||
placeholder: "请选择学生",
|
||||
njId: newClassInfo.njId,
|
||||
bjId: newClassInfo.bjId,
|
||||
key: studentPickerKey.value // 添加 key 强制重新渲染
|
||||
}
|
||||
}]);
|
||||
|
||||
// 使用 nextTick 确保组件更新
|
||||
nextTick(() => {
|
||||
|
||||
|
||||
});
|
||||
} else {
|
||||
|
||||
setValue({ studentInfo: null });
|
||||
setSchema([{
|
||||
field: 'studentInfo',
|
||||
componentProps: {
|
||||
placeholder: "请先选择年级班级"
|
||||
}
|
||||
}]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('⚠️ 获取表单值失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 立即检查一次
|
||||
checkClassInfo();
|
||||
|
||||
// 定期检查(每500ms)
|
||||
const interval = setInterval(checkClassInfo, 500);
|
||||
|
||||
// 组件卸载时清理
|
||||
const cleanup = () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
|
||||
// 在组件卸载时清理
|
||||
if (typeof onUnmounted === 'function') {
|
||||
onUnmounted(cleanup);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
if (/\.(jpg|jpeg|png|gif|bmp|webp|tiff|svg)$/i.test(getData.pic)) {
|
||||
getData['scfj'] = '照片'
|
||||
setSchema([{
|
||||
@ -195,9 +249,41 @@ if (/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/i.test(getData.pic)) {
|
||||
}
|
||||
}])
|
||||
}
|
||||
// 处理传入的数据,将 njId 和 bjId 转换为 classInfo 格式,将 xsId 转换为 studentInfo 格式
|
||||
const processFormData = (data: any) => {
|
||||
if (data.njId && data.bjId) {
|
||||
// 如果有 njId 和 bjId,构造 classInfo 对象
|
||||
data.classInfo = {
|
||||
njId: data.njId,
|
||||
bjId: data.bjId,
|
||||
nj: { key: data.njId, title: data.njmc || '' },
|
||||
bj: { key: data.bjId, title: data.bjmc || '' },
|
||||
njmc: data.njmc || '',
|
||||
bjmc: data.bjmc || '',
|
||||
njmcId: data.njmcId || '' // 添加 njmcId 字段
|
||||
};
|
||||
}
|
||||
|
||||
if (data.xsId) {
|
||||
// 如果有 xsId,构造 studentInfo 对象
|
||||
data.studentInfo = {
|
||||
xsId: data.xsId,
|
||||
xsxm: data.xsxm || data.studentName || '', // 兼容 xsxm 和 studentName
|
||||
studentName: data.studentName || data.xsxm || '', // 优先使用 studentName
|
||||
njId: data.njId || '',
|
||||
bjId: data.bjId || '',
|
||||
njmc: data.njmc || '',
|
||||
bjmc: data.bjmc || ''
|
||||
};
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
if (getData._show) {
|
||||
const processedData = processFormData(getData);
|
||||
setValue({})
|
||||
setValue(getData)
|
||||
setValue(processedData)
|
||||
setDisabled(true)
|
||||
isDisabled.value = true
|
||||
} else {
|
||||
@ -206,8 +292,35 @@ if (getData._show) {
|
||||
isDisabled.value = false;
|
||||
}
|
||||
|
||||
|
||||
async function submit() {
|
||||
let values = await getValue();
|
||||
|
||||
|
||||
|
||||
// 处理 classInfo 数据,提取 njId、bjId 和 njmcId
|
||||
if (values.classInfo) {
|
||||
values.njId = values.classInfo.njId;
|
||||
values.bjId = values.classInfo.bjId;
|
||||
values.njmc = values.classInfo.njmc;
|
||||
values.bjmc = values.classInfo.bjmc;
|
||||
values.njmcId = values.classInfo.njmcId; // 添加 njmcId 字段
|
||||
|
||||
// 删除 classInfo 字段,避免提交到后端
|
||||
delete values.classInfo;
|
||||
}
|
||||
|
||||
// 处理 studentInfo 数据,提取 xsId 和 studentName
|
||||
if (values.studentInfo) {
|
||||
values.xsId = values.studentInfo.xsId || values.studentInfo.id; // 兼容两种字段名
|
||||
values.studentName = values.studentInfo.studentName || values.studentInfo.xsxm || values.studentInfo.xm; // 优先使用 studentName
|
||||
|
||||
// 删除 studentInfo 字段,避免提交到后端
|
||||
delete values.studentInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
await readyToGoSaveApi({...values});
|
||||
showToast({title: "操作成功"});
|
||||
navigateBack({delta: 1});
|
||||
|
||||
@ -46,8 +46,8 @@ const [register, lhkh] = useLayout({
|
||||
},
|
||||
})
|
||||
console.log(111, getData.value)
|
||||
if (getData.value.gradeClassId) {
|
||||
lhkh.setParam({gradeClassId: getData.value.gradeClassId})
|
||||
if (getData.value.bjId) {
|
||||
lhkh.setParam({bjId: getData.value.bjId})
|
||||
lhkh.reload()
|
||||
}
|
||||
|
||||
|
||||
@ -1,29 +1,5 @@
|
||||
<template>
|
||||
<view class="w-full h-full main_bg flex-col">
|
||||
<view class="p-15">
|
||||
<view class="flex-row items-center justify-between">
|
||||
<view class="flex-row items-center">
|
||||
<view class="wi-120 he-120 r-50">
|
||||
<image class="wh-full"
|
||||
src="/static/base/logo.jpg"></image>
|
||||
</view>
|
||||
<view class="white-color ml-15">
|
||||
<view class="font-18">你好,{{ getUser.name }}!</view>
|
||||
</view>
|
||||
</view>
|
||||
<view @click="tuichu">
|
||||
<svg t="1726666280409" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="4480" width="25" height="25">
|
||||
<path
|
||||
d="M512.2 953.1c-99.6 0-199.7-33.3-282.2-101.7C42 695.6 15.9 416 171.7 228s435.5-214.1 623.4-58.3c53.8 44.6 95.2 99.5 123 163.1 7.5 17.2-0.3 37.3-17.6 44.9-17.2 7.5-37.3-0.3-44.9-17.6-23.5-53.8-58.5-100.2-104.1-137.9C592.6 90.3 356 112.5 224.1 271.5 92.3 430.5 114.4 667.1 273.5 799c159 131.8 395.6 109.7 527.5-49.3 19.7-23.8 36.4-49.8 49.6-77.4 8.1-17 28.5-24.1 45.4-16 17 8.1 24.1 28.5 16 45.4-15.6 32.6-35.3 63.4-58.6 91.4-87.4 105.5-213.9 160-341.2 160z"
|
||||
fill="#ffffff" p-id="4481"></path>
|
||||
<path
|
||||
d="M910.9 544.6H440.8c-18.8 0-34.1-15.3-34.1-34.1s15.3-34.1 34.1-34.1h470.1c18.8 0 34.1 15.3 34.1 34.1 0 18.9-15.3 34.1-34.1 34.1z"
|
||||
fill="#ffffff" p-id="4482"></path>
|
||||
</svg>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-full h-full flex-col">
|
||||
<view class="flex-1 back-F6F6F6 flex-col">
|
||||
<view class="px-15 pt-15">
|
||||
<BasicTitle title="我的应用" :isBorder="false" line/>
|
||||
@ -186,7 +162,7 @@ function videoplay(url: string) {
|
||||
|
||||
function onlhkh(data: any) {
|
||||
setData(data)
|
||||
navigateTo('/pages/view/quantitativeAssessment/index/details?gradeClassId=' + data.gradeClassId)
|
||||
navigateTo('/pages/view/quantitativeAssessment/index/details?bjId=' + data.bjId)
|
||||
}
|
||||
|
||||
function totzgg(data: any) {
|
||||
@ -203,16 +179,26 @@ function tuichu() {
|
||||
}
|
||||
|
||||
const thirdId: any = ref('');
|
||||
|
||||
|
||||
onShow(async () => {
|
||||
|
||||
|
||||
let res = await inspectItemFindAllsApi();
|
||||
inspectItems.value = res.result;
|
||||
await lhkh.reload()
|
||||
|
||||
|
||||
let userres = await getUserViewApi();
|
||||
|
||||
|
||||
if (userres && userres.result) {
|
||||
thirdId.value = userres.result.thirdId ? userres.result.thirdId : "";
|
||||
} else {
|
||||
thirdId.value = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
@ -240,14 +226,21 @@ const [sspregister, ssp] = useLayout({
|
||||
})
|
||||
|
||||
async function tokhpj() {
|
||||
|
||||
|
||||
if (thirdId.value) {
|
||||
|
||||
let res = await getSchedulingPlanByUserIdApi();
|
||||
|
||||
if (res.result && res.result.length > 0) {
|
||||
|
||||
navigateTo('/pages/view/quantitativeAssessment/assessment/assessment')
|
||||
} else {
|
||||
|
||||
showToast({title: "今日未分配!无法填报!"})
|
||||
}
|
||||
} else {
|
||||
|
||||
showToast({title: "未配置权限!"})
|
||||
}
|
||||
}
|
||||
@ -290,9 +283,4 @@ function tabsChange(index: any) {
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.main_bg {
|
||||
//background: #4651fa;
|
||||
background: url("@/static/base/top.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
BIN
src/static/base/home/stxc.png
Normal file
BIN
src/static/base/home/stxc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
src/static/base/home/yrcg.png
Normal file
BIN
src/static/base/home/yrcg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Loading…
x
Reference in New Issue
Block a user