356 lines
10 KiB
Vue
356 lines
10 KiB
Vue
<template>
|
|
<el-dialog :title="getDialogTitle()" v-model="dialogVisible" width="500px" append-to-body>
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
|
<el-form-item label="姓名" prop="name">
|
|
<template v-if="mode === 'edit'">
|
|
<el-input v-model="form.name" disabled class="w-full" />
|
|
</template>
|
|
<template v-else>
|
|
<el-select
|
|
v-model="form.name"
|
|
filterable
|
|
remote
|
|
reserve-keyword
|
|
placeholder="请输入姓名"
|
|
:remote-method="queryTeachers"
|
|
:loading="loading"
|
|
clearable
|
|
class="w-full"
|
|
@change="handleTeacherSelect"
|
|
@focus="handleFocus"
|
|
>
|
|
<el-option v-for="item in teacherOptions" :key="item.value" :label="item.label" :value="item.value" :data-info="item" />
|
|
</el-select>
|
|
</template>
|
|
</el-form-item>
|
|
<el-form-item label="手机号码" prop="phone">
|
|
<el-input v-model="form.phone" placeholder="请输入手机号码" clearable />
|
|
</el-form-item>
|
|
<el-form-item label="性别" prop="sex">
|
|
<el-radio-group v-model="form.sex">
|
|
<el-radio :label="0">男</el-radio>
|
|
<el-radio :label="1">女</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
<el-form-item label="备注" prop="remark">
|
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<div class="dialog-footer">
|
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref, reactive, computed, watch, onMounted } from 'vue';
|
|
import { getTeacherList } from '@/api/xsssgly/dormManager';
|
|
import { addDormManager, updateDormManager } from '@/api/ssglyxx/dormManager/index';
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
export default defineComponent({
|
|
name: 'AdminDialog',
|
|
props: {
|
|
modelValue: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
mode: {
|
|
type: String,
|
|
default: 'add'
|
|
},
|
|
admin: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
type: {
|
|
type: String,
|
|
default: 'school'
|
|
}
|
|
},
|
|
emits: ['update:modelValue', 'submit'],
|
|
setup(props, { emit }) {
|
|
const loading = ref(false);
|
|
const teacherOptions = ref<any[]>([]);
|
|
|
|
// 根据类型获取对话框标题
|
|
const getDialogTitle = () => {
|
|
const typeText =
|
|
{
|
|
'school': '全校',
|
|
'campus': '校区',
|
|
'area': '宿舍区',
|
|
'building': '宿舍楼'
|
|
}[props.type] || '';
|
|
|
|
return props.mode === 'add' ? `新增${typeText}管理员` : `编辑${typeText}管理员`;
|
|
};
|
|
|
|
// 对话框可见性
|
|
const dialogVisible = computed({
|
|
get: () => props.modelValue,
|
|
set: (val) => {
|
|
emit('update:modelValue', val);
|
|
}
|
|
});
|
|
|
|
const formRef = ref();
|
|
const form = reactive({
|
|
id: null,
|
|
name: '',
|
|
phone: '',
|
|
remark: '',
|
|
nickName: '',
|
|
sex: 0,
|
|
userId: null // 存储选中的用户ID
|
|
});
|
|
|
|
const rules = {
|
|
name: [{ required: true, message: '请选择姓名', trigger: 'change' }],
|
|
phone: [
|
|
{ required: true, message: '请输入手机号码', trigger: 'blur' },
|
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
|
],
|
|
sex: [{ required: true, message: '请选择性别', trigger: 'change' }]
|
|
};
|
|
|
|
// 使用真实API查询教师用户
|
|
const queryTeachers = async (query: string) => {
|
|
loading.value = true;
|
|
try {
|
|
const res = await getTeacherList(
|
|
query,
|
|
(() => {
|
|
switch (props.type) {
|
|
case 'school':
|
|
return '1';
|
|
case 'campus':
|
|
return '2';
|
|
case 'area':
|
|
return '3';
|
|
case 'building':
|
|
return '4';
|
|
default:
|
|
return '1';
|
|
}
|
|
})()
|
|
);
|
|
if (res.code === 200 && res.data) {
|
|
teacherOptions.value = res.data.map((item: any) => {
|
|
return {
|
|
value: item.value,
|
|
label: item.label,
|
|
username: item.username,
|
|
nickName: item.label,
|
|
userId: item.value, // 直接使用API返回的value作为userId
|
|
phonenumber: item.phonenumber, // 保存手机号码
|
|
sex: item.sex // 保存性别
|
|
};
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('获取教师数据失败', error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 监听admin属性变化,更新表单
|
|
watch(
|
|
() => props.admin,
|
|
(newVal) => {
|
|
if (newVal) {
|
|
Object.assign(form, newVal);
|
|
// 如果没有性别值,设置默认值0
|
|
if (form.sex === undefined) {
|
|
form.sex = 0;
|
|
} else {
|
|
// 确保性别值为数字类型
|
|
form.sex = Number(form.sex);
|
|
}
|
|
}
|
|
},
|
|
{ deep: true, immediate: true }
|
|
);
|
|
|
|
// 选择教师后处理逻辑
|
|
const handleTeacherSelect = (value: any) => {
|
|
const selectedTeacher = teacherOptions.value.find((item) => item.value === value);
|
|
if (selectedTeacher) {
|
|
form.userId = selectedTeacher.userId;
|
|
// 自动填充手机号码和性别
|
|
form.phone = selectedTeacher.phonenumber || '';
|
|
// 确保性别值为数字类型
|
|
form.sex = selectedTeacher.sex !== undefined ? Number(selectedTeacher.sex) : 0;
|
|
form.nickName = selectedTeacher.nickName;
|
|
form.name = selectedTeacher.label;
|
|
// form.id = selectedTeacher.userId;
|
|
form.remark = '';
|
|
console.log('选中教师信息:', selectedTeacher, '转换后性别值:', form.sex);
|
|
}
|
|
};
|
|
|
|
// 处理下拉框获得焦点事件
|
|
const handleFocus = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const res = await getTeacherList(
|
|
'',
|
|
(() => {
|
|
switch (props.type) {
|
|
case 'school':
|
|
return '1';
|
|
case 'campus':
|
|
return '2';
|
|
case 'area':
|
|
return '3';
|
|
case 'building':
|
|
return '4';
|
|
default:
|
|
return '1';
|
|
}
|
|
})()
|
|
);
|
|
if (res.code === 200 && res.data) {
|
|
teacherOptions.value = res.data.map((item: any) => {
|
|
return {
|
|
value: item.value,
|
|
label: item.label,
|
|
username: item.username,
|
|
userId: item.value,
|
|
nickName: item.label,
|
|
phonenumber: item.phonenumber, // 保存手机号码
|
|
sex: item.sex // 保存性别
|
|
};
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('获取教师数据失败', error);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 页面加载时预加载一些教师数据
|
|
onMounted(async () => {
|
|
try {
|
|
const res = await getTeacherList(
|
|
'',
|
|
(() => {
|
|
switch (props.type) {
|
|
case 'school':
|
|
return '1';
|
|
case 'campus':
|
|
return '2';
|
|
case 'area':
|
|
return '3';
|
|
case 'building':
|
|
return '4';
|
|
default:
|
|
return '1';
|
|
}
|
|
})()
|
|
);
|
|
if (res.code === 200 && res.data) {
|
|
teacherOptions.value = res.data.map((item: any) => {
|
|
return {
|
|
value: item.value,
|
|
label: item.label,
|
|
username: item.username,
|
|
userId: item.value,
|
|
nickName: item.label,
|
|
phonenumber: item.phonenumber, // 保存手机号码
|
|
sex: item.sex // 保存性别
|
|
};
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('初始化教师数据失败', error);
|
|
}
|
|
});
|
|
|
|
// 提交表单
|
|
const submitForm = async () => {
|
|
formRef.value?.validate(async (valid: boolean) => {
|
|
if (!valid) return;
|
|
// 字段映射
|
|
const payload: any = {
|
|
id: form.id,
|
|
managerName: form.nickName || form.name,
|
|
gender: String(form.sex),
|
|
userId: form.userId,
|
|
phone: form.phone,
|
|
remark: form.remark,
|
|
// 下面字段可根据props.type补充
|
|
managerType: (() => {
|
|
switch (props.type) {
|
|
case 'school':
|
|
return '1';
|
|
case 'campus':
|
|
return '2';
|
|
case 'area':
|
|
return '3';
|
|
case 'building':
|
|
return '4';
|
|
default:
|
|
return '1';
|
|
}
|
|
})(),
|
|
managerLevel: (() => {
|
|
switch (props.type) {
|
|
case 'school':
|
|
return 1;
|
|
case 'campus':
|
|
return 2;
|
|
case 'area':
|
|
return 3;
|
|
case 'building':
|
|
return 4;
|
|
default:
|
|
return 1;
|
|
}
|
|
})()
|
|
};
|
|
console.log(payload);
|
|
try {
|
|
if (props.mode === 'add') {
|
|
await addDormManager(payload);
|
|
ElMessage.success('新增成功');
|
|
} else if (props.mode === 'edit') {
|
|
await updateDormManager(payload);
|
|
ElMessage.success('修改成功');
|
|
}
|
|
emit('submit', { ...form }); // 通知父组件刷新
|
|
dialogVisible.value = false;
|
|
} catch (e) {
|
|
ElMessage.error(props.mode === 'add' ? '新增失败' : '修改失败');
|
|
}
|
|
});
|
|
};
|
|
|
|
return {
|
|
dialogVisible,
|
|
form,
|
|
formRef,
|
|
loading,
|
|
teacherOptions,
|
|
rules,
|
|
getDialogTitle,
|
|
queryTeachers,
|
|
handleTeacherSelect,
|
|
handleFocus,
|
|
submitForm
|
|
};
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dialog-footer {
|
|
text-align: right;
|
|
}
|
|
</style>
|