285 lines
7.1 KiB
Vue
285 lines
7.1 KiB
Vue
<template>
|
||
<el-dialog
|
||
v-model="visible"
|
||
:title="formData.id ? '修改' : '新增'"
|
||
width="800px"
|
||
:close-on-click-modal="false"
|
||
destroy-on-close
|
||
@close="handleClose"
|
||
>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="formRules"
|
||
label-width="120px"
|
||
class="form-content"
|
||
>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="班级名称" prop="companyId">
|
||
<el-select
|
||
v-model="formData.companyId"
|
||
filterable
|
||
clearable
|
||
placeholder="请选择班级"
|
||
style="width: 100%"
|
||
>
|
||
<el-option
|
||
v-for="item in companyList"
|
||
:key="item.id"
|
||
:label="item.companyName"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="学员编号" prop="employeeNo">
|
||
<el-input
|
||
v-model="formData.employeeNo"
|
||
placeholder="系统自动生成"
|
||
disabled
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="姓名" prop="realName">
|
||
<el-input
|
||
v-model="formData.realName"
|
||
placeholder="请输入姓名"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="身份证" prop="idCard">
|
||
<el-input
|
||
v-model="formData.idCard"
|
||
placeholder="请输入身份证号"
|
||
clearable
|
||
maxlength="18"
|
||
@input="handleIdCardInput"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="手机" prop="mobile">
|
||
<el-input
|
||
v-model="formData.mobile"
|
||
type="number"
|
||
placeholder="请输入手机号"
|
||
clearable
|
||
maxlength="11"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="允许进出" prop="inoutFlag">
|
||
<el-select
|
||
v-model="formData.inoutFlag"
|
||
clearable
|
||
placeholder="请选择"
|
||
style="width: 100%"
|
||
>
|
||
<el-option
|
||
v-for="item in yesNoDict"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-form-item label="备注" prop="remarks">
|
||
<el-input
|
||
v-model="formData.remarks"
|
||
type="textarea"
|
||
:rows="3"
|
||
placeholder="请输入备注"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="handleClose">取消</el-button>
|
||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch } from 'vue'
|
||
import { useDict } from '/@/hooks/dict'
|
||
import { useMessage } from '/@/hooks/message'
|
||
import { putObj } from '/@/api/professional/stayschool/outercompanyemployee'
|
||
|
||
// Props
|
||
interface Props {
|
||
modelValue: boolean
|
||
formData: {
|
||
id?: string
|
||
companyId?: string
|
||
companyName?: string
|
||
employeeNo?: string
|
||
realName?: string
|
||
idCard?: string
|
||
mobile?: string
|
||
inoutFlag?: string
|
||
remarks?: string
|
||
}
|
||
companyList: any[]
|
||
saveApi?: (data: any) => Promise<any> // 自定义保存 API 函数
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
modelValue: false,
|
||
formData: () => ({
|
||
id: '',
|
||
companyId: '',
|
||
companyName: '',
|
||
employeeNo: '',
|
||
realName: '',
|
||
idCard: '',
|
||
mobile: '',
|
||
inoutFlag: '',
|
||
remarks: ''
|
||
}),
|
||
companyList: () => [],
|
||
saveApi: undefined
|
||
})
|
||
|
||
// Emits
|
||
const emit = defineEmits<{
|
||
(e: 'update:modelValue', value: boolean): void
|
||
(e: 'success'): void
|
||
}>()
|
||
|
||
// 字典数据
|
||
const { yes_no_type: yesNoDict } = useDict('yes_no_type')
|
||
|
||
// 消息提示
|
||
const message = useMessage()
|
||
|
||
// 表单引用
|
||
const formRef = ref()
|
||
|
||
// 提交加载状态
|
||
const submitLoading = ref(false)
|
||
|
||
// 弹窗显示状态
|
||
const visible = ref(false)
|
||
|
||
watch(() => props.modelValue, (val) => {
|
||
visible.value = val
|
||
})
|
||
|
||
watch(visible, (val) => {
|
||
emit('update:modelValue', val)
|
||
})
|
||
|
||
// 表单验证规则
|
||
const formRules = {
|
||
companyId: [
|
||
{ required: true, message: '请选择班级', trigger: 'change' }
|
||
],
|
||
realName: [
|
||
{ required: true, message: '请填写姓名', trigger: 'blur' }
|
||
],
|
||
idCard: [
|
||
{ required: true, message: '请输入正确身份证', trigger: 'blur' },
|
||
{ min: 15, max: 18, message: '长度在 15 到 18 个字符', trigger: 'blur' },
|
||
{ pattern: /^(\d{15}|\d{17}[\dXx])$/, message: '身份证号格式不正确', trigger: 'blur' }
|
||
],
|
||
mobile: [
|
||
{ required: true, message: '请填写手机号', trigger: 'blur' },
|
||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||
],
|
||
inoutFlag: [
|
||
{ required: true, message: '请选择是否允许进出', trigger: 'change' }
|
||
]
|
||
}
|
||
|
||
// 关闭弹窗
|
||
const handleClose = () => {
|
||
visible.value = false
|
||
formRef.value?.resetFields()
|
||
}
|
||
|
||
// 身份证号输入限制:只允许数字和X/x,最大长度18
|
||
const handleIdCardInput = (value: string) => {
|
||
// 只保留数字和X/x
|
||
const filtered = value.replace(/[^\dXx]/g, '')
|
||
if (filtered !== value) {
|
||
props.formData.idCard = filtered
|
||
}
|
||
}
|
||
|
||
// 提交表单
|
||
const handleSubmit = async () => {
|
||
if (!formRef.value) return
|
||
|
||
await formRef.value.validate(async (valid: boolean) => {
|
||
if (valid) {
|
||
submitLoading.value = true
|
||
try {
|
||
// 设置班级名称
|
||
const selectedCompany = props.companyList.find(item => item.id === props.formData.companyId)
|
||
const submitData = {
|
||
...props.formData,
|
||
companyName: selectedCompany?.companyName || ''
|
||
}
|
||
|
||
if (props.formData.id) {
|
||
await putObj(submitData)
|
||
message.success('修改成功')
|
||
} else {
|
||
// 使用自定义保存函数
|
||
if (props.saveApi) {
|
||
await props.saveApi(submitData)
|
||
} else {
|
||
message.error('请提供保存 API 函数')
|
||
return
|
||
}
|
||
message.success('添加成功')
|
||
}
|
||
handleClose()
|
||
emit('success')
|
||
} catch (error: any) {
|
||
message.error(error?.msg || '操作失败')
|
||
} finally {
|
||
submitLoading.value = false
|
||
}
|
||
}
|
||
})
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.form-content {
|
||
:deep(.el-row) {
|
||
margin-bottom: 18px;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
|
||
:deep(.el-row .el-form-item) {
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
</style>
|
||
|