[plugin:vite:import-analysis] Failed to resolve import "./EmployeeDialog.vue" from "src/views/emp/EmpIndex.vue". Does the file exist? D:/JavaCode/VueCode/NodeCode/emp-management/vue-management/src/views/emp/EmpIndex.vue:108:28 15 | import { ref, reactive, onMounted } from 'vue' 16 | import { ElMessage, ElMessageBox } from 'element-plus' 17 | import EmployeeDialog from './EmployeeDialog.vue' 整理一份EmployeeDialog.vue的内容加入到刚才的项目中
时间: 2025-07-19 14:24:57 浏览: 11
<think>我们之前已经有一个员工对话框的模板,现在需要将其整理成一个单独的EmployeeDialog.vue组件,并集成到刚才的项目中。
注意:在之前的EmpIndex.vue中已经引用了EmployeeDialog组件,因此我们需要创建这个组件。
我们将根据之前提供的对话框代码,结合Vue3的Composition API和Element Plus进行编写。
步骤:
1. 创建EmployeeDialog.vue文件
2. 将之前对话框的模板复制过来,并调整代码为Vue3的语法
3. 定义props:接收dialogVisible(使用v-model)、title、employee(当前员工对象)、deptList(部门列表)
4. 定义emits:用于关闭对话框和提交表单数据
5. 实现表单验证规则
6. 实现头像上传功能
7. 实现工作经历条目的添加和删除
注意:由于在父组件中已经通过v-model绑定了dialogVisible,所以子组件中需要通过emit('update:modelValue')来更新
下面给出EmployeeDialog.vue的完整代码:</think>下面是根据您提供的对话框代码整理的 `EmployeeDialog.vue` 组件,已适配 Vue3 和 Element Plus:
```vue
<template>
<el-dialog v-model="visible" :title="title" width="800px">
<el-form
ref="employeeFormRef"
:model="employee"
:rules="rules"
label-width="80px"
class="employee-form"
>
<!-- 基本信息 - 第一行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<el-input
v-model="employee.username"
placeholder="请输入员工用户名,2-20个字"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input
v-model="employee.name"
placeholder="请输入员工姓名,2-10个字"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="性别" prop="gender">
<el-select
v-model="employee.gender"
placeholder="请选择性别"
style="width: 100%;"
>
<el-option
v-for="gender in genders"
:key="gender.value"
:label="gender.name"
:value="gender.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号" prop="phone">
<el-input
v-model="employee.phone"
placeholder="请输入员工手机号"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第三行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="职位" prop="job">
<el-select
v-model="employee.job"
placeholder="请选择职位"
style="width: 100%;"
>
<el-option
v-for="job in jobs"
:key="job.value"
:label="job.name"
:value="job.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="薪资" prop="salary">
<el-input
v-model="employee.salary"
placeholder="请输入员工薪资"
type="number"
min="0"
>
<template #append>¥</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 第四行 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="部门" prop="deptId">
<el-select
v-model="employee.deptId"
placeholder="请选择部门"
style="width: 100%;"
>
<el-option
v-for="dept in deptList"
:key="dept.id"
:label="dept.name"
:value="dept.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入职日期" prop="entryDate">
<el-date-picker
v-model="employee.entryDate"
type="date"
style="width: 100%;"
placeholder="选择日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第五行 - 头像上传 -->
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="头像">
<el-upload
class="avatar-uploader"
action="/api/upload"
:headers="headers"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="employee.image" :src="employee.image" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
</el-row>
<!-- 工作经历 -->
<!-- 第六行 - 添加按钮 -->
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="工作经历">
<el-button type="success" size="small" @click="addExprItem">
<el-icon><Plus /></el-icon>添加工作经历
</el-button>
</el-form-item>
</el-col>
</el-row>
<!-- 工作经历列表 -->
<div v-for="(expr, index) in employee.exprList" :key="index" class="expr-item">
<el-row :gutter="20">
<el-col :span="10">
<el-form-item
:prop="`exprList[${index}].exprDate`"
:rules="exprDateRules"
label="时间"
label-width="80px"
>
<el-date-picker
v-model="expr.exprDate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100%;"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
:prop="`exprList[${index}].company`"
:rules="companyRules"
label="公司"
label-width="60px"
>
<el-input
placeholder="请输入公司名称"
v-model="expr.company"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
:prop="`exprList[${index}].job`"
:rules="jobRules"
label="职位"
label-width="60px"
>
<el-input
placeholder="请输入职位"
v-model="expr.job"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="2">
<el-form-item label-width="0px">
<el-button
type="danger"
@click="delExprItem(index)"
:icon="Minus"
circle
/>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<!-- 底部按钮 -->
<template #footer>
<span class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submitForm">保存</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Minus } from '@element-plus/icons-vue'
// 定义Props
const props = defineProps({
modelValue: Boolean, // 控制对话框显示
title: String, // 对话框标题
employee: Object, // 员工数据
deptList: Array // 部门列表
})
// 定义Emits
const emit = defineEmits(['update:modelValue', 'submit'])
// 计算属性 - 控制对话框显示
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
// 表单引用
const employeeFormRef = ref(null)
// 性别选项
const genders = [
{ name: '男', value: 1 },
{ name: '女', value: 0 }
]
// 职位选项
const jobs = [
{ name: '部门经理', value: 1 },
{ name: '主管', value: 2 },
{ name: '员工', value: 3 },
{ name: '实习生', value: 4 }
]
// 头像上传请求头(假设从store获取token)
const headers = {
token: localStorage.getItem('token') || ''
}
// 表单验证规则
const rules = reactive({
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在2到20个字符', trigger: 'blur' }
],
name: [
{ required: true, message: '请输入姓名', trigger: 'blur' },
{ min: 2, max: 10, message: '长度在2到10个字符', trigger: 'blur' }
],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
],
job: [
{ required: true, message: '请选择职位', trigger: 'change' }
],
salary: [
{ required: true, message: '请输入薪资', trigger: 'blur' },
{ pattern: /^\d+(\.\d{1,2})?$/, message: '请输入有效的金额', trigger: 'blur' }
],
deptId: [
{ required: true, message: '请选择部门', trigger: 'change' }
],
entryDate: [
{ required: true, message: '请选择入职日期', trigger: 'change' }
]
})
// 工作经历验证规则
const exprDateRules = [
{ required: true, message: '请选择工作日期范围', trigger: 'change' }
]
const companyRules = [
{ required: true, message: '请输入公司名称', trigger: 'blur' }
]
const jobRules = [
{ required: true, message: '请输入职位', trigger: 'blur' }
]
// 添加工作经历
const addExprItem = () => {
props.employee.exprList.push({
exprDate: '',
company: '',
job: ''
})
}
// 删除工作经历
const delExprItem = (index) => {
props.employee.exprList.splice(index, 1)
}
// 头像上传成功处理
const handleAvatarSuccess = (response) => {
if (response.code === 1) {
props.employee.image = response.data
ElMessage.success('头像上传成功')
} else {
ElMessage.error(response.msg || '头像上传失败')
}
}
// 头像上传前校验
const beforeAvatarUpload = (file) => {
const isImage = file.type.startsWith('image/')
const isLt2M = file.size / 1024 / 1024 < 2
if (!isImage) {
ElMessage.error('只能上传图片文件!')
return false
}
if (!isLt2M) {
ElMessage.error('图片大小不能超过2MB!')
return false
}
return true
}
// 关闭对话框
const close = () => {
visible.value = false
}
// 提交表单
const submitForm = () => {
if (!employeeFormRef.value) return
employeeFormRef.value.validate((valid) => {
if (valid) {
// 验证工作经历日期格式
let hasInvalidExpr = false
for (const expr of props.employee.exprList) {
if (!Array.isArray(expr.exprDate) || expr.exprDate.length !== 2) {
ElMessage.error('请为所有工作经历选择完整的日期范围')
hasInvalidExpr = true
break
}
}
if (!hasInvalidExpr) {
emit('submit', props.employee)
close()
}
} else {
ElMessage.error('请填写完整的表单信息')
}
})
}
// 监听员工数据变化,确保有工作经历数组
watch(() => props.employee, (newVal) => {
if (newVal && !newVal.exprList) {
newVal.exprList = []
}
}, { immediate: true, deep: true })
</script>
<style scoped>
.avatar-uploader {
display: inline-block;
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader:hover {
border-color: var(--el-color-primary);
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
text-align: center;
line-height: 120px;
}
.avatar {
width: 120px;
height: 120px;
display: block;
object-fit: cover;
}
.expr-item {
margin-bottom: 15px;
padding: 10px;
border: 1px solid #ebeef5;
border-radius: 4px;
background-color: #fafafa;
}
.employee-form {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px;
}
</style>
```
### 组件功能说明
1. **双向绑定对话框显示**:
- 使用 `computed` 实现 `v-model` 双向绑定
- 通过 `emit('update:modelValue')` 通知父组件更新
2. **表单验证**:
- 使用 Element Plus 的表单验证规则
- 包含基本字段验证(用户名、姓名、手机号等)
- 动态验证工作经历字段
3. **头像上传功能**:
- 支持图片预览
- 上传前验证文件类型和大小
- 上传成功后将图片URL保存到员工数据
4. **工作经历管理**:
- 动态添加/删除工作经历条目
- 每个条目包含日期范围、公司名称和职位
- 条目验证确保数据完整性
5. **数据初始化**:
- 监听员工数据变化,确保工作经历数组存在
- 使用 `watch` 确保数据正确初始化
6. **样式优化**:
- 头像上传区域样式美化
- 工作经历条目添加边框和背景
- 表单区域添加滚动条防止内容溢出
### 使用方法
在父组件中引入并使用该对话框组件:
```vue
<template>
<!-- 其他内容 -->
<EmployeeDialog
v-model="dialogVisible"
:title="dialogTitle"
:employee="currentEmployee"
:dept-list="deptList"
@submit="handleSubmit"
/>
</template>
<script setup>
import EmployeeDialog from './EmployeeDialog.vue'
// 控制对话框显示
const dialogVisible = ref(false)
const dialogTitle = ref('')
const currentEmployee = ref(null)
const deptList = ref([]) // 部门列表数据
// 处理表单提交
const handleSubmit = (employeeData) => {
// 调用API保存员工数据
console.log('提交员工数据:', employeeData)
}
</script>
```
### 注意事项
1. **头像上传**:
- 需要后端提供 `/api/upload` 接口
- 响应格式应为 `{ code: 1, data: '图片URL' }` 或 `{ code: 0, msg: '错误信息' }`
2. **部门列表**:
- `deptList` 应为数组,格式:`[{ id: 1, name: '技术部' }, ...]`
3. **工作经历**:
- 工作经历日期范围使用数组格式:`['2020-01-01', '2022-12-31']`
4. **表单验证**:
- 确保所有必填字段都设置了验证规则
- 工作经历的验证规则是动态添加的
阅读全文
相关推荐



















