学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject
页面结构和路由
<template>
<div class="dashboard-container">
<div class="app-container">
<div class="edit-form">
<el-form ref="userForm" label-width="220px">
<!-- 姓名 部门 -->
<el-row>
<el-col :span="12">
<el-form-item label="姓名" prop="username">
<el-input size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!-- 工号 入职时间 -->
<el-row>
<el-col :span="12">
<el-form-item label="工号" prop="workNumber">
<el-input size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!--手机 聘用形式 -->
<el-row>
<el-col :span="12">
<el-form-item label="手机" prop="mobile">
<el-input size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="部门" prop="departmentId">
<!-- 放置及联部门组件 -->
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="聘用形式" prop="formOfEmployment">
<el-select size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="入职时间" prop="timeOfEntry">
<el-date-picker
size="mini"
type="date"
value-format="yyyy-MM-dd"
class="inputW"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="转正时间">
<el-date-picker size="mini" type="date" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!-- 员工照片 -->
<el-row>
<el-col :span="12">
<el-form-item label="员工头像">
<!-- 放置上传图片 -->
</el-form-item>
</el-col>
</el-row>
<!-- 保存个人信息 -->
<el-row type="flex">
<el-col :span="12" style="margin-left: 220px">
<el-button size="mini" type="primary">保存更新</el-button>
</el-col>
</el-row>
</el-form>
</div>
</div>
</div>
</template>
<script>
export default {}
</script>
<style scoped lang="scss">
.edit-form {
background: #fff;
padding: 20px;
.inputW {
width: 380px;
}
}
</style>
{
path: '/employee/detail', // 员工详情的地址
component: () => import('@/views/employee/detail.vue'),
hidden: true, // 表示隐藏在左侧菜单
meta: {
title: '员工详情'
}
}
数据和校验
<template>
<div class="dashboard-container">
<div class="app-container">
<div class="edit-form">
<el-form
ref="userForm"
:model="userInfo"
:rules="rules"
label-width="220px"
>
<!-- 姓名 部门 -->
<el-row>
<el-col :span="12">
<el-form-item label="姓名" prop="username">
<el-input v-model="userInfo.username" size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!-- 工号 入职时间 -->
<el-row>
<el-col :span="12">
<el-form-item label="工号" prop="workNumber">
<!-- 工号是系统生成的 禁用这个组件 -->
<el-input v-model="userInfo.workNumber" disabled size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!--手机 聘用形式 -->
<el-row>
<el-col :span="12">
<el-form-item label="手机" prop="mobile">
<el-input v-model="userInfo.mobile " size="mini" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="部门" prop="departmentId">
<!-- 放置及联部门组件 -->
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="聘用形式" prop="formOfEmployment">
<el-select v-model="userInfo.formOfEmployment" size="mini" class="inputW">
<el-option label="正式" :value="1" />
<el-option label="非正式" :value="2" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="入职时间" prop="timeOfEntry">
<el-date-picker
v-model="userInfo.timeOfEntry"
size="mini"
type="date"
value-format="yyyy-MM-dd"
class="inputW"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="转正时间" prop="correctionTime">
<el-date-picker v-model="userInfo.correctionTime" size="mini" type="date" class="inputW" />
</el-form-item>
</el-col>
</el-row>
<!-- 员工照片 -->
<el-row>
<el-col :span="12">
<el-form-item label="员工头像">
<!-- 放置上传图片 -->
</el-form-item>
</el-col>
</el-row>
<!-- 保存个人信息 -->
<el-row type="flex">
<el-col :span="12" style="margin-left: 220px">
<el-button size="mini" type="primary" @click="saveData">保存更新</el-button>
</el-col>
</el-row>
</el-form>
</div
</div
>
</div>
</div></template>
<script>
export default {
data() {
return {
userInfo: {
username: '', // 员工名字
mobile: '', // 员工手机号
formOfEmployment: null, // 员工聘用形式
workNumber: '', // 员工工号
departmentId: null, // 员工部门id
timeOfEntry: '', // 员工入职时间
correctionTime: '' // 员工转正日期
},
rules: {
username: [
{ required: true, message: '请输入员工姓名', trigger: 'blur' },
{ min: 1, max: 4, message: '长度在 1 到 4 个字符', trigger: 'blur' }
], mobile: [
{ required: true, message: '请输入电话号码', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/,
message: '手机号格式不正确',
trigger: 'blur' }
], formOfEmployment: [{
required: true, message: '请输入聘用形式', trigger: 'blur'
}], departmentId: [{
required: true, message: '请输入部门', trigger: 'blur'
}], timeOfEntry: [{
required: true, message: '请选择入职时间', trigger: 'blur'
}], correctionTime: [{
required: true, message: '请选择转正时间', trigger: 'blur'
}, {
validator: (rule, value, callback) => {
if (this.userInfo.timeOfEntry) {
if (new Date(this.userInfo.timeOfEntry) > new Date(value)) {
callback(new Error('转正时间不能小于入职时间'))
return
}
}
callback()
}
}]
}
}
}, methods: {
saveData() {
this.$refs.userForm.validate()
}
}
}
</script>
<style scoped lang="scss">
.edit-form {
background: #fff;
padding: 20px;
.inputW {
width: 380px;
}
}
</style>
封装部门级联组件
<template>
<!-- element-ui级联组件 -->
<el-cascader separator="-" :props="props" :options="treeData" size="mini" />
</template>
<script>
import { getDepartment } from '@/api/department'
import { transListToTreeData } from '@/utils/index'
export default {
data () {
return {
treeData: [], // 赋值给级联组件的options
props: {
label: 'name', // 要展示的字段
value: 'id' // 要存储的字段
}
}
},
created () {
this.getDepartment()
},
methods: {
async getDepartment () {
// 将组织架构的数据转化为树形赋值给treeData
this.treeData = transListToTreeData(await getDepartment(), 0)
}
}
}
</script>
<el-row>
<el-col :span="12">
<el-form-item label="部门" prop="departmentId">
<!-- 放置及联部门组件 -->
<select-tree class="inputW" />
</el-form-item>
</el-col>
</el-row>
Cascader级联组件的特性
options为一个树形结构的数据源
props可以设置数据源中的字段如label(展示)value(存取)
separator为展示的分隔符
级联组件-双向绑定
<!-- element-ui级联组件 -->
<el-cascader
:value="value"
separator="-"
:props="props"
:options="treeData"
size="mini"
@change="changeValue"
/>
props: {
value: {
type: Number, // 存储的是部门的id
default: null
}
}
changeValue (list) {
// 取到数组的最后一个值
if (list.length > 0) {
// 将最后一位的id取出来 传出去
this.$emit('input', list[list.length - 1])
} else {
// 如果长度为0 说明值为空
this.$emit('input', null)
}
}
<!-- 放置及联部门组件 -->
<select-tree v-model="userInfo.departmentId" class="inputW" />
新增员工
/**
*
* 增加员工
*
*/
export function addEmployee (data) {
return request({
url: '/sys/user',
method: 'POST',
data
})
}
saveData() {
this.$refs.userForm.validate(async isOk => {
// 如果校验成功
if (isOk) {
await addEmployee(this.userInfo)
this.$message.success('新增员工成功')
// 跳转到员工页面
this.$router.push('/employee')
}
})
}
编辑员工-查看员工
/**
*
* 获取-员工-基本信息
*
*/
export function getEmployeeDetail (id) {
return request({
url: `/sys/user/${id}`,
method: 'GET'
})
}
{
path: '/employee/detail/:id?', // 员工详情的地址
component: () => import('@/views/employee/detail.vue'),
hidden: true, // 表示隐藏在左侧菜单
meta: {
title: '员工详情'
}
}
created() {
this.$route.params.id && this.getEmployeeDetail()
}
async getEmployeeDetail() {
this.userInfo = await getEmployeeDetail(this.$route.params.id)
}
<el-button
size="mini"
type="text"
@click="$router.push(`/employee/detail/${row.id}`)"
>查看</el-button
>
编辑员工-保存
/**
*
* 修改-员工-基本信息
*
*/
export function updateEmployee (data) {
return request({
url: `/sys/user/${data.id}`,
method: 'PUT',
data
})
}
<el-input v-model="userInfo.mobile" :disabled="!!$route.params.id" size="mini" class="inputW" />
saveData() {
this.$refs.userForm.validate(async isOk => {
// 如果校验成功
if (isOk) {
// 判断是否编辑模式
if (this.$route.params.id) {
await updateEmployee(this.userInfo)
this.$message.success('修改员工信息成功')
} else {
// 新增模式
await addEmployee(this.userInfo)
this.$message.success('新增员工成功')
}
// 跳转到员工页面
this.$router.push('/employee')
}
})
}
上传员工头像封装
<template>
<!-- (自动上传)action是上传地址 人资项目不需要 人资项目(手动上传) -->
<!-- show-file-list不展示列表 -->
<el-upload
class="avatar-uploader"
action=""
:show-file-list="false"
:before-upload="beforeAvatarUpload"
>
<img v-if="value" :src="value" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon" />
</el-upload>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
}
},
methods: {
// 检查函数 判断文件的类型还有大小 return true(继续上传)/false(停止上传)
beforeAvatarUpload (file) {
const isJPG = [
'image/jpeg',
'image/png',
'image/gif',
'image/bmp'
].includes(file.type)
const isLt2M = file.size / 1024 / 1024 < 5
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG PNG GIF BMP 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 5MB!')
}
return isJPG && isLt2M
}
}
}
</script>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<!-- 员工照片 -->
<el-row>
<el-col :span="12">
<el-form-item label="员工头像">
<!-- 放置上传图片 -->
<imageUpload v-model="userInfo.staffPhoto" />
</el-form-item>
</el-col>
</el-row>