日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

10 员工管理

發布時間:2024/1/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10 员工管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1封裝一個通用的工具欄


目標:封裝一個通用的工具欄供大家使用

1.1通用工具欄的組件結構

在后續的業務開發中,經常會用到一個類似下圖的工具欄,作為公共組件,進行一下封裝

組件 src/components/PageTools/index.vue

1

2 定義插槽:

3 插槽里邊有一個固定的圖標, 用div包住:里邊有圖標+ 具名插槽

4 定義一個變量控制插槽是否顯示

// 組件可以顯示 左側內容 也可以顯示右側內容 如果左側內容不傳 圖標應該不顯示

用一個變量倆控制 是不是顯示

5 el-row 兩端對齊

測試:

或者 具名插槽的另一種寫法:

<template><el-card class="page-tools"><el-row type="flex"justify="space-between"align="middle"><el-col><div v-if="showBefore"class="before"><i class="el-icon-info"/><!-- 定義前面得插槽 --><slot name="before"/></div></el-col><el-col><el-row type="flex"justify="end"><!-- 定義后面的插槽 --><slot name="after"/></el-row></el-col></el-row></el-card> </template> ? <script> export default {props: {showBefore: {type: Boolean,default: false} ?} } </script> ? <style lang='scss'> .page-tools {margin: 10px0;.before {line-height: 34px;i {margin-right: 5px;color: #409eff;}display: inline-block;padding: 0px10px;border-radius: 3px;border: 1pxsolidrgba(145, 213, 255, 1);background: rgba(230, 247, 255, 1);}} </style>

?

1.2 組件統一注冊

為了方便所有的頁面都可以不用引用該組件,可以進行 全局注冊

提供注冊入口 src/componets/index.js

// 該文件負責所有的公共的組件的全局注冊 Vue.use import PageTools from './PageTools' export default {install(Vue) {// 注冊全局的通用欄組件對象Vue.component('PageTools', PageTools)} } 在入口處進行注冊 src/main.js import Component from '@/components' Vue.use(Component) // 注冊自己的插件

提交代碼

本節任務: 封裝一個通用的工具欄

2員工列表頁面的基本布局和結構


目標:實現員工列表頁面的基本布局和結構

結構代碼 src/employees/index.vue

<template><div class="dashboard-container"><div class="app-container"><page-tools :show-before="true"><span slot="before">共166條記錄</span><template slot="after"><el-button size="small" type="warning">導入</el-button><el-button size="small" type="danger">導出</el-button><el-button size="small" type="primary">新增員工</el-button></template></page-tools><!-- 放置表格和分頁 --><el-card><el-table border><el-table-column label="序號" sortable="" /><el-table-column label="姓名" sortable="" /><el-table-column label="工號" sortable="" /><el-table-column label="聘用形式" sortable="" /><el-table-column label="部門" sortable="" /><el-table-column label="入職時間" sortable="" /><el-table-column label="賬戶狀態" sortable="" /><el-table-column label="操作" sortable="" fixed="right" width="280"><template><el-button type="text" size="small">查看</el-button><el-button type="text" size="small">轉正</el-button><el-button type="text" size="small">調崗</el-button><el-button type="text" size="small">離職</el-button><el-button type="text" size="small">角色</el-button><el-button type="text" size="small">刪除</el-button></template></el-table-column></el-table><!-- 分頁組件 --><el-row type="flex" justify="center" align="middle" style="height: 60px"><el-pagination layout="prev, pager, next" /></el-row></el-card></div></div> </template> 1 sortable="" 可以排序 2 分頁居中, 用el-row套上, 對el-row 設置居中對齊<el-row type="flex" justify="center" align="middle" style="height: 60px"><el-pagination layout="prev, pager, next" /></el-row>

提交代碼

本節任務:員工列表頁面的基本布局和結構

2.1員工列表數據請求和分頁加載


目標實現員工數據的加載和分頁請求

首先,封裝員工的加載請求 src/api/employees.js

/*** 獲取員工的綜合列表數據* ***/ export function getEmployeeList(params) {return request({url: '/sys/user',params}) }

然后,實現加載數據和分頁的邏輯

import { getEmployeeList } from '@/api/employees' export default {data() {return {loading: false,list: [], // 接數據的page: {page: 1, // 當前頁碼size: 10,total: 0 // 總數}}},created() {this.getEmployeeList()},methods: {changePage(newPage) {this.page.page = newPagethis.getEmployeeList()},async getEmployeeList() {this.loading = trueconst { total, rows } = await getEmployeeList(this.page)this.page.total = totalthis.list = rowsthis.loading = false}} }

綁定表格

<el-card v-loading="loading"><el-table border :data="list"><el-table-column label="序號" sortable="" type="index" /><el-table-column label="姓名" sortable="" prop="username" /><el-table-column label="工號" sortable="" prop="workNumber" /><el-table-column label="聘用形式" sortable="" prop="formOfEmployment" /><el-table-column label="部門" sortable="" prop="departmentName" /><el-table-column label="入職時間" sortable="" prop="timeOfEntry" /><el-table-column label="賬戶狀態" sortable="" prop="enableState" /><el-table-column label="操作" sortable="" fixed="right" width="280"><template><el-button type="text" size="small">查看</el-button><el-button type="text" size="small">轉正</el-button><el-button type="text" size="small">調崗</el-button><el-button type="text" size="small">離職</el-button><el-button type="text" size="small">角色</el-button><el-button type="text" size="small">刪除</el-button></template></el-table-column></el-table><!-- 分頁組件 --><el-row type="flex" justify="center" align="middle" style="height: 60px"><el-paginationlayout="prev, pager, next":page-size="page.size":current-page="page.page":total="page.total"@current-change="changePage"/></el-row></el-card> 控制遮罩層 v-loading="loading"

提交代碼

本節任務員工列表數據請求和分頁加載

2.2員工列表中的數據進行格式化


目標:將列表中的內容進行格式化

2.2.1利用列格式化屬性處理聘用形式

上小節中,列表中的 聘用形式/ 入職時間賬戶狀態需要進行顯示內容的處理

那么聘用形式中1代表什么含義,這實際上是我們需要的枚舉數據,該數據的存放文件位于我們提供的資源/枚舉中,可以將枚舉下的文件夾放于src/api文件夾下

針對聘用形式,可以使用el-table-columnformatter屬性進行設置

import EmployeeEnum from '@/api/constant/employees'<!-- 格式化聘用形式 --><el-table-column label="聘用形式" sortable :formatter="formatEmployment" />// 格式化聘用形式formatEmployment(row, column, cellValue, index) {// 要去找 1所對應的值const obj = EmployeeEnum.hireType.find(item => item.id === cellValue)return obj ? obj.value : '未知'}

2.2.2過濾器解決時間格式的處理

針對入職時間,我們可以采用作用域插槽進行處理

<el-table-column label="入職時間" sortable prop="timeOfEntry"><template slot-scope="obj">{{obj.row.timeOfEntry | 過濾器}}</template></el-table-column> 問題來了,過濾器從哪里呢?

資源/過濾器中,我們提供了若干工具方法,我們可以將其轉化成過濾器,首先將其拷貝到src

main.js中將工具方法轉化成過濾器

import * as filters from '@/filters' // 引入工具類// 注冊全局的過濾器 Object.keys(filters).forEach(key => {// 注冊過濾器Vue.filter(key, filters[key]) })

好了,現在可以愉快的用過濾器的方式使用工具類的方法了 <el-table-column label="入職時間" sortable="" align="center"><!-- 作用域插槽 --><template slot-scope="{ row }">{{ row.timeOfEntry | formatDate }}</template></el-table-column>

2.2.3 最后一項,賬戶狀態,可以用開關組件switch進行顯示

<el-table-column label="賬戶狀態" align="center" sortable="" prop="enableState"><template slot-scope="{ row }"><!-- 根據當前狀態來確定 是否打開開關 --><el-switch :value="row.enableState === 1" /></template></el-table-column>

<el-switch :value="row.enableState === 1" /> :vlaue = 1 開,不等于1 關

提交代碼

本節任務 員工列表中的數據進行格式化

2.3刪除員工功能


目標實現刪除員工的功能

首先封裝 刪除員工的請求

/*** 刪除員工接口* ****/export function delEmployee(id) {return request({url: `/sys/user/${id}`,method: 'delete'}) }

刪除功能

<template slot-scope="{ row }"><el-button type="text" size="small">查看</el-button><el-button type="text" size="small">轉正</el-button><el-button type="text" size="small">調崗</el-button><el-button type="text" size="small">離職</el-button><el-button type="text" size="small">角色</el-button><el-button type="text" size="small" @click="deleteEmployee(row.id)">刪除</el-button></template> // 刪除員工async deleteEmployee(id) {try {await this.$confirm('您確定刪除該員工嗎')await delEmployee(id)this.getEmployeeList()this.$message.success('刪 除員工成功')} catch (error) {console.log(error)}}

提交代碼

本節任務: 刪除員工功能

2.4新增員工功能-彈層-校驗-部門


目標:實現新增員工的功能

2.4.1新建員工彈層組件

當我們點擊新增員工時,我們需要一個類似的彈層

類似組織架構的組件,同樣新建一個彈層組件 src/views/employees/components/add-employee.vue

<template><el-dialog title="新增員工" :visible="showDialog"><!-- 表單 --><el-form label-width="120px"><el-form-item label="姓名"><el-input style="width:50%" placeholder="請輸入姓名" /></el-form-item><el-form-item label="手機"><el-input style="width:50%" placeholder="請輸入手機號" /></el-form-item><el-form-item label="入職時間"><el-date-picker style="width:50%" placeholder="請選擇入職時間" /></el-form-item><el-form-item label="聘用形式"><el-select style="width:50%" placeholder="請選擇" /></el-form-item><el-form-item label="工號"><el-input style="width:50%" placeholder="請輸入工號" /></el-form-item><el-form-item label="部門"><el-input style="width:50%" placeholder="請選擇部門" /></el-form-item><el-form-item label="轉正時間"><el-date-picker style="width:50%" placeholder="請選擇轉正時間" /></el-form-item></el-form><!-- footer插槽 --><template v-slot:footer><el-row type="flex" justify="center"><el-col :span="6"><el-button size="small">取消</el-button><el-button type="primary" size="small">確定</el-button></el-col></el-row></template></el-dialog> </template><script> export default {props: {showDialog: {type: Boolean,default: false}} } </script><style></style>

2.4.2 引用彈出層,點擊彈出

父組件中引用,彈出層

import AddDemployee from './components/add-employee'<!-- 放置新增組件 --><add-employee :show-dialog.sync="showDialog" /><!-- 放置新增組件 --><add-employee :show-dialog.sync="showDialog" /><el-button icon="plus" type="primary" size="small" @click="showDialog = true">新增員工</el-button>

2.4.3新增員工的表單校驗

封裝新增員工api src/api/employees.js

/** *** 新增員工的接口* **/ export function addEmployee(data) {return request({method: 'post',url: '/sys/user',data}) }

針對員工屬性,添加校驗規則

import EmployeeEnum from '@/api/constant/employees'data() {return {EmployeeEnum, // 在data中定義數據// 表單數據treeData: [], // 定義數組接收樹形數據showTree: false, // 控制樹形的顯示或者隱藏loading: false, // 控制樹的顯示或者隱藏進度條formData: {username: '',mobile: '',formOfEmployment: '',workNumber: '',departmentName: '',timeOfEntry: '',correctionTime: ''},rules: {username: [{ required: true, message: '用戶姓名不能為空', trigger: 'blur' }, {min: 1, max: 4, message: '用戶姓名為1-4位'}],mobile: [{ required: true, message: '手機號不能為空', trigger: 'blur' }, {pattern: /^1[3-9]\d{9}$/, message: '手機號格式不正確', trigger: 'blur'}],formOfEmployment: [{ required: true, message: '聘用形式不能為空', trigger: 'blur' }],workNumber: [{ required: true, message: '工號不能為空', trigger: 'blur' }],departmentName: [{ required: true, message: '部門不能為空', trigger: 'change' }],timeOfEntry: [{ required: true, message: '入職時間', trigger: 'blur' }]}}}

綁定數據和規則校驗

<el-form :model="formData" :rules="rules" label-width="120px"><el-form-item label="姓名" prop="username"><el-input v-model="formData.username" style="width:50%" placeholder="請輸入姓名" /></el-form-item><el-form-item label="手機" prop="mobile"><el-input v-model="formData.mobile" style="width:50%" placeholder="請輸入手機號" /></el-form-item><el-form-item label="入職時間" prop="timeOfEntry"><el-date-picker v-model="formData.timeOfEntry" style="width:50%" placeholder="請選擇日期" /></el-form-item><el-form-item label="聘用形式" prop="formOfEmployment"><el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="請選擇" /></el-form-item><el-form-item label="工號" prop="workNumber"><el-input v-model="formData.workNumber" style="width:50%" placeholder="請輸入工號" /></el-form-item><el-form-item label="部門" prop="departmentName"><el-input v-model="formData.departmentName" style="width:50%" placeholder="請選擇部門" /></el-form-item><el-form-item label="轉正時間" prop="correctionTime"><el-date-picker v-model="formData.correctionTime" style="width:50%" placeholder="請選擇日期" /></el-form-item></el-form>

2.4.4 加載部門數據轉化樹形

聘用形式和選擇部門的處理

員工的部門是從樹形部門中選擇一個部門

獲取部門數據,轉化樹形

import { getDepartments } from '@/api/departments' import { transListToTreeData } from '@/utils'data () {return {// 表單數據treeData: [], // 定義數組接收樹形數據showTree: false, // 控制樹形的顯示或者隱藏loading: false, // 控制樹的顯示或者隱藏進度條}},methods: {async getDepartments() {this.showTree = truethis.loading = trueconst { depts } = await getDepartments()// depts是數組 但不是樹形this.treeData = transListToTreeData(depts, '')this.loading = false},}

點擊部門賦值表單數據

選擇部門,賦值表單數據

<el-form-item label="部門" prop="departmentName"><el-input v-model="formData.departmentName" style="width:50%" placeholder="請選擇部門" @focus="getDepartments" /><!-- 放置一個tree組件 --><el-treev-if="showTree"v-loading="loading":data="treeData"default-expand-all="":props="{ label: 'name' }"@node-click="selectNode"/></el-form-item>

點擊部門時觸發

selectNode(node) {this.formData.departmentName = node.namethis.showTree = false} :default-expand-all="true" 默認展開 :props="{ label: 'name' }" 與數據字段 對應

展示部門有點卡頓,可以用loading進度條

部門的校驗改為change, 我們不想鼠標一離開就校驗, 不能用blur

2.4.5聘用形式

<el-form-item label="聘用形式" prop="formOfEmployment"><el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="請選擇"><!-- 遍歷只能遍歷組件的數據 --><el-option v-for="item in EmployeeEnum.hireType" :key="item.id" :label="item.value" :value="item.id" /></el-select></el-form-item>

引入枚舉 進行展示使用

存放的是1,2 :value="item.id

展示的是正式和非正式 :label="item.value"

2.2.6新增員工功能-確定-取消


調用新增接口

// 點擊確定時 校驗整個表單async btnOK() {try {await this.$refs.addEmployee.validate()// 調用新增接口await addEmployee(this.formData) // 新增員工// 告訴父組件更新數據// this.$parent 可以直接調用到父組件的實例 實際上就是父組件this// this.$emitthis.$parent.getEmployeeList()this.$parent.showDialog = false} catch (error) {console.log(error)}},btnCancel() {// 重置原來的數據this.formData = {username: '',mobile: '',formOfEmployment: '',workNumber: '',departmentName: '',timeOfEntry: '',correctionTime: ''}this.$refs.addEmployee.resetFields() // 重置校驗結果this.$emit('update:showDialog', false)} 新增員工的功能和組織架構的功能極其類似,這里不做過多闡述 // 告訴父組件更新數據// this.$parent 可以直接調用到父組件的實例 實際上就是父組件this// this.$emitthis.$parent.getEmployeeList()this.$parent.showDialog = false

提交代碼

本節任務 新增員工功能和彈層

3員工導入組件封裝


目標:封裝一個導入excel數據的文件

首先封裝一個類似的組件,首先需要注意的是,類似功能,vue-element-admin已經提供了,我們只需要改造即可 代碼地址

類似功能性的組件,我們只需要會使用和封裝即可

excel導入功能需要使用npm包xlsx,所以需要安裝xlsx插件

$ npm i xlsx 將vue-element-admin提供的導入功能新建一個組件,位置: src/components/UploadExcel

注冊全局的導入excel組件

import PageTools from './PageTools' import UploadExcel from './UploadExcel' export default {install(Vue) {Vue.component('PageTools', PageTools) // 注冊工具欄組件Vue.component('UploadExcel', UploadExcel) // 注冊導入excel組件} }

測試、:

現在與需求不一樣的是: 樣式和布局

修改樣式和布局

<template><div class="upload-excel"><div class="btn-upload"><el-button :loading="loading" size="mini" type="primary" @click="handleUpload">點擊上傳</el-button></div><input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"><div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"><i class="el-icon-upload" /><span>將文件拖到此處</span></div></div> </template> <style scoped lang="scss"> .upload-excel {display: flex;justify-content: center;margin-top: 100px;.excel-upload-input{display: none;z-index: -9999;}.btn-upload , .drop{border: 1px dashed #bbb;width: 350px;height: 160px;text-align: center;line-height: 160px;}.drop{line-height: 80px;color: #bbb;i {font-size: 60px;display: block;}} } </style>

提交代碼

本節任務:員工導入組件封裝

3.1 員工的導入


目標:實現員工的導入

建立公共導入的頁面路由

新建一個公共的導入頁面,掛載路由 src/router/index.js

{path: '/import',component: Layout,hidden: true, // 隱藏在左側菜單中children: [{path: '', // 二級路由path什么都不寫 表示二級默認路由component: () => import('@/views/import')}]},

創建import路由組件 src/views/import/index.vue

<template><!-- 公共導入組件 --> <upload-excel :on-success="success" /> </template>

解析:

需要傳一個 onSuccess

如果我們用這個組件傳了onSuccess,他就會傳出一個對象 this.excelData. 對象里邊有header,result

獲取到的數據是中文, 我們要再方法中轉化成英文

分析excel導入代碼,封裝接口

封裝導入員工的api接口 /** ** 封裝一個導入員工的接口** ***/export function importEmployee(data) {return request({url: '/sys/user/batch',method: 'post',data}) }

實現excel導入

獲取導入的excel數據, 導入excel接口

async success({ header, results }) {// 如果是導入員工const userRelations = {'入職日期': 'timeOfEntry','手機號': 'mobile','姓名': 'username','轉正日期': 'correctionTime','工號': 'workNumber'}const arr = []results.forEach(item => {const userInfo = {}Object.keys(item).forEach(key => {userInfo[userRelations[key]] = item[key]})arr.push(userInfo) })await importEmployee(arr) // 調用導入接口this.$router.back()} 為了讓這個頁面可以服務更多的導入功能,我們可以在頁面中用參數來判斷,是否是導入員工 data() {return {type: this.$route.query.type}},

當excel中有日期格式的時候,實際轉化的值為一個數字,我們需要一個方法進行轉化

formatDate(numb, format) {const time = new Date((numb - 1) * 24 * 3600000 + 1)time.setYear(time.getFullYear() - 70)const year = time.getFullYear() + ''const month = time.getMonth() + 1 + ''const date = time.getDate() - 1 + ''if (format && format.length === 1) {return year + format + month + format + date}return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)} 需要注意, 導入的手機號不能和之前的存在的手機號重復

邏輯判斷

async success({ header, results }) {if (this.type === 'user') {const userRelations = {'入職日期': 'timeOfEntry','手機號': 'mobile','姓名': 'username','轉正日期': 'correctionTime','工號': 'workNumber'}const arr = []// 遍歷所有的數組results.forEach(item => {// 需要將每一個條數據里面的中文都換成英文const userInfo = {}Object.keys(item).forEach(key => {// key是當前的中文名 找到對應的英文名if (userRelations[key] === 'timeOfEntry' || userRelations[key] === 'correctionTime') {userInfo[userRelations[key]] = new Date(this.formatDate(item[key], '/')) // 只有這樣, 才能入庫return}userInfo[userRelations[key]] = item[key]})// 最終userInfo變成了全是英文arr.push(userInfo)})await importEmployee(arr)this.$message.success('導入成功')}this.$router.back() // 回到上一頁},formatDate(numb, format) {const time = new Date((numb - 1) * 24 * 3600000 + 1)time.setYear(time.getFullYear() - 70)const year = time.getFullYear() + ''const month = time.getMonth() + 1 + ''const date = time.getDate() - 1 + ''if (format && format.length === 1) {return year + format + month + format + date}return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)}

員工頁面跳轉

<el-button type="warning" size="small" @click="$router.push('/import?type=user')">導入</el-button>

目標: 實現員工的導入

員工導出excel功能


目標: 實現將員工數據導出功能

日常業務中,我們經常遇到excel導出功能, 怎么使用呢

Excel 的導入導出都是依賴于js-xlsx來實現的。

在 js-xlsx的基礎上又封裝了Export2Excel.js來方便導出數據。

安裝excel所需依賴和按需加載

由于 Export2Excel不僅依賴js-xlsx還依賴file-saver和script-loader。

所以你先需要安裝如下命令:

npm install xlsx file-saver -S npm install script-loader -S -D

由于js-xlsx體積還是很大的,導出功能也不是一個非常常用的功能,所以使用的時候建議使用懶加載。使用方法如下:

import('@/vendor/Export2Excel').then(excel => {excel.export_json_to_excel({header: tHeader, //表頭 必填data, //具體數據 必填filename: 'excel-list', //非必填autoWidth: true, //非必填bookType: 'xlsx' //非必填}) })

excel導出參數的介紹

vue-element-admin提供了導出的功能模塊,在課程資源/excel導出目錄下,放置到src目錄下

參數

參數

說明

類型

可選值

默認值

header

導出數據的表頭

Array

/

[]

data

導出的具體數據

Array

/

[[]]

filename

導出文件名

String

/

excel-list

autoWidth

單元格是否要自適應寬度

Boolean

true / false

true

bookType

導出文件類型

String

xlsx, csv, txt, more

xlsx

excel導出基本的結構

我們最重要的一件事,就是把表頭和數據進行相應的對應

因為數據中的key是英文,想要導出的表頭是中文的話,需要將中文和英文做對應

const headers = {'手機號': 'mobile','姓名': 'username','入職日期': 'timeOfEntry','聘用形式': 'formOfEmployment','轉正日期': 'correctionTime','工號': 'workNumber','部門': 'departmentName'}

然后,完成導出代碼

// 導出excel數據exportData() {// 做操作// 表頭對應關系const headers = {'姓名': 'username','手機號': 'mobile','入職日期': 'timeOfEntry','聘用形式': 'formOfEmployment','轉正日期': 'correctionTime','工號': 'workNumber','部門': 'departmentName'}// 懶加載import('@/vendor/Export2Excel').then(async excel => {const { rows } = await getEmployeeList({ page: 1, size: this.page.total })const data = this.formatJson(headers, rows)excel.export_json_to_excel({header: Object.keys(headers),data,filename: '員工信息表',autoWidth: true,bookType: 'xlsx'})// 獲取所有的數據// excel.export_json_to_excel({// header: ['姓名', '薪資'],// data: [['張三', 12000], ['李四', 5000]],// filename: '員工薪資表',// autoWidth: true,// bookType: 'csv'// })})},// 該方法負責將數組轉化成二維數組formatJson(headers, rows) {// 首先遍歷數組// [{ username: '張三'},{},{}] => [[’張三'],[],[]]return rows.map(item => {return Object.keys(headers).map(key => {if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') {return formatDate(item[headers[key]]) // 返回格式化之前的時間} else if (headers[key] === 'formOfEmployment') {var en = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]])return en ? en.value : '未知'}return item[headers[key]]}) // => ["張三", "13811","2018","1", "2018", "10002"]})// return data// return rows.map(item => {// // item是對象 => 轉化成只有值的數組 => 數組值的順序依賴headers {username: '張三' }// // Object.keys(headers) => ["姓名", "手機號",...]// return Object.keys(headers).map(key => {// return item[headers[key]]// }) // / 得到 ['張三',’129‘,’dd‘,'dd']// })}

導出時間格式的處理

formatJson(headers, rows) {return rows.map(item => {// item是一個對象 { mobile: 132111,username: '張三' }// ["手機號", "姓名", "入職日期" 。。]return Object.keys(headers).map(key => {// 需要判斷 字段if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') {// 格式化日期return formatDate(item[headers[key]])} else if (headers[key] === 'formOfEmployment') {const obj = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]])return obj ? obj.value : '未知'}return item[headers[key]]})// ["132", '張三’, ‘’,‘’,‘’d]})// return rows.map(item => Object.keys(headers).map(key => item[headers[key]]))// 需要處理時間格式問題}

擴展 復雜表頭的導出

當需要導出復雜表頭的時候,vue-element-admin同樣支持該類操作

vue-element-admin 提供的導出方法中有 multiHeadermerges 的參數

參數

說明

類型

可選值

默認值

multiHeader

復雜表頭的部分

Array

/

[[]]

merges

需要合并的部分

Array

/

[]

multiHeader里面是一個二維數組,里面的一個元素是一行表頭,假設你想得到一個如圖的結構

mutiHeader應該這樣定義

const multiHeader = [['姓名', '主要信息', '', '', '', '', '部門']]

multiHeader中的一行表頭中的字段的個數需要和真正的列數相等,假設想要跨列,多余的空間需要定義成空串

它主要對應的是標準的表頭

const header = ['姓名', '手機號', '入職日期', '聘用形式', '轉正日期', '工號', '部門']

如果,我們要實現其合并的效果, 需要設定merges選項

const merges = ['A1:A2', 'B1:F1', 'G1:G2']

merges的順序是沒關系的,只要配置這兩個屬性,就可以導出復雜表頭的excel了

exportData() {const headers = {'姓名': 'username','手機號': 'mobile','入職日期': 'timeOfEntry','聘用形式': 'formOfEmployment','轉正日期': 'correctionTime','工號': 'workNumber','部門': 'departmentName'}// 導出excelimport('@/vendor/Export2Excel').then(async excel => {// excel是引入文件的導出對象// 導出 header從哪里來// data從哪里來// 現在沒有一個接口獲取所有的數據// 獲取員工的接口 頁碼 每頁條數 100 1 10000const { rows } = await getEmployeeList({ page: 1, size: this.page.total })const data = this.formatJson(headers, rows) // 返回的data就是 要導出的結構const multiHeader = [['姓名', '主要信息', '', '', '', '', '部門']]const merges = ['A1:A2', 'B1:F1', 'G1:G2']excel.export_json_to_excel({header: Object.keys(headers),data,filename: '員工資料表',multiHeader, // 復雜表頭merges // 合并選項})// excel.export_json_to_excel({// header: ['姓名', '工資'],// data: [['張三', 3000], ['李四', 5000]],// filename: '員工工資表'// })// [{ username: '張三',mobile: 13112345678 }] => [[]]// 要轉化 數據結構 還要和表頭的順序對應上// 要求轉出的標題是中文})},// 將表頭數據和數據進行對應// [{}] => [[]]formatJson(headers, rows) {return rows.map(item => {// item是一個對象 { mobile: 132111,username: '張三' }// ["手機號", "姓名", "入職日期" 。。]return Object.keys(headers).map(key => {// 需要判斷 字段if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') {// 格式化日期return formatDate(item[headers[key]])} else if (headers[key] === 'formOfEmployment') {const obj = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]])return obj ? obj.value : '未知'}return item[headers[key]]})// ["132", '張三’, ‘’,‘’,‘’d]})// return rows.map(item => Object.keys(headers).map(key => item[headers[key]]))// 需要處理時間格式問題}

提交代碼

本節任務實現將員工數據導出功能

員工詳情頁創建和布局


目標:創建員工詳情的主要布局頁面和基本布局

詳情頁的基本布局和路由

建立詳情頁路由

{path: 'detail/:id', // query傳參 動態路由傳參component: () => import('@/views/employees/detail'),hidden: true, // 不在左側菜單顯示meta: {title: '員工詳情' // 標記當前路由規則的中文名稱 后續在做左側菜單時 使用}}

建立基本架構

<div class="dashboard-container"><div class="app-container"><el-card><el-tabs><el-tab-pane label="登錄賬戶設置"><!-- 放置表單 --><el-form label-width="120px" style="margin-left: 120px; margin-top:30px"><el-form-item label="姓名:"><el-input style="width:300px" /></el-form-item><el-form-item label="密碼:"><el-input style="width:300px" type="password" /></el-form-item><el-form-item><el-button type="primary">更新</el-button></el-form-item></el-form></el-tab-pane><el-tab-pane label="個人詳情" /><el-tab-pane label="崗位信息" /></el-tabs></el-card></div></div>

列表跳轉到詳情

<el-button type="text" size="small" @click="$router.push(`/employees/detail/${obj.row.id}`)">查看</el-button>

讀取和保存用戶信息的接口

加載個人基本信息 > 該接口已經在之前提供過了 src/api/user.js

/** ** 獲取某個用戶的基本信息** ***/ export function getUserDetailById(id) {return request({url: `/sys/user/${id}`}) }

保存個人基本信息 src/api/employees.js

/** *** 保存員工的基本信息* **/ export function saveUserDetailById(data) {return request({url: `/sys/user/${data.id}`,method: 'put',data}) }

實現用戶名和密碼的修改

注意:這里有個缺陷,接口中讀取的是后端的密文,我們并不能解密,所以當我們沒有任何修改就保存時,會校驗失敗,因為密文超過了規定的12位長度,為了真的修改密碼,我們設定了一個臨時的字段 password2,用它來存儲我們的修改值,最后保存的時候,把password2傳給password

用戶名和密碼的修改 src/views/employees/detail.vue

import { getUserDetailById } from '@/api/user' import { saveUserDetailById } from '@/api/employees' export default {data() {return {userId: this.$route.params.id, // 這樣可以后面直接通過 this.userId進行獲取數據userInfo: {// 專門存放基本信息username: '',password2: ''},rules: {username: [{ required: true, message: '姓名不能為空', trigger: 'blur' }],password2: [{ required: true, message: '密碼不能為空', trigger: 'blur' },{ min: 6, max: 9, message: '密碼長度6-9位', trigger: 'blur' }]}}},created() {this.getUserDetailById()},methods: {async getUserDetailById() {this.userInfo = await getUserDetailById(this.userId)},async saveUser() {try {// 校驗await this.$refs.userForm.validate()await saveUserDetailById({ ...this.userInfo, password: this.userInfo.password2 }) // 將新密碼的值替換原密碼的值this.$message.success('保存成功')} catch (error) {console.log(error)}}} }

綁定表單數據

<!-- 放置表單 --><el-form ref="userForm" :model="userInfo" :rules="rules" label-width="120px" style="margin-left: 120px; margin-top:30px"><el-form-item label="姓名:" prop="username"><el-input v-model="userInfo.username" style="width:300px" /></el-form-item><el-form-item label="新密碼:" prop="password2"><el-input v-model="userInfo.password2" style="width:300px" type="password" /></el-form-item><el-form-item><el-button type="primary" @click="saveUser">更新</el-button></el-form-item></el-form>

提交代碼

個人組件和崗位組件封裝


封裝個人詳情組件

我們將員工個人信息分為三部分,賬戶,個人, 崗位,這個小節我們對個人組件和崗位組件進行封裝

封裝個人組件 src/views/employees/components/user-info.vue

<template><div class="user-info"><!-- 個人信息 --><el-form label-width="220px"><!-- 工號 入職時間 --><el-row class="inline-info"><el-col :span="12"><el-form-item label="工號"><el-input v-model="userInfo.workNumber" class="inputW" /></el-form-item></el-col><el-col :span="12"><el-form-item label="入職時間"><el-date-pickerv-model="userInfo.timeOfEntry"type="date"class="inputW"value-format="YYYY-MM-DD"/></el-form-item></el-col></el-row><!-- 姓名 部門 --><el-row class="inline-info"><el-col :span="12"><el-form-item label="姓名"><el-input v-model="userInfo.username" class="inputW" /></el-form-item></el-col><el-col :span="12"><el-form-item label="部門"><el-input v-model="userInfo.departmentName" class="inputW" /></el-form-item></el-col></el-row><!--手機 聘用形式 --><el-row class="inline-info"><el-col :span="12"><el-form-item label="手機"><el-input v-model="userInfo.mobile" /></el-form-item></el-col><el-col :span="12"><el-form-item label="聘用形式"><el-select v-model="userInfo.formOfEmployment" class="inputW"><el-optionv-for="item in EmployeeEnum.hireType":key="item.id":label="item.value":value="item.id"/></el-select></el-form-item></el-col></el-row><!-- 員工照片 --><el-row class="inline-info"><el-col :span="12"><el-form-item label="員工頭像"><!-- 放置上傳圖片 --></el-form-item></el-col></el-row><!-- 保存個人信息 --><el-row class="inline-info" type="flex" justify="center"><el-col :span="12"><el-button type="primary" @click="saveUser">保存更新</el-button><el-button @click="$router.back()">返回</el-button></el-col></el-row></el-form><!-- 基礎信息 --><el-form label-width="220px"><div class="block"><div class="title">基礎信息</div><el-form-item label="最高學歷"><el-select v-model="formData.theHighestDegreeOfEducation" class="inputW2"><el-optionv-for="item in EmployeeEnum.highestDegree":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><!-- 個人頭像 --><!-- 員工照片 --><el-form-item label="員工照片"><!-- 放置上傳圖片 --></el-form-item><el-form-item label="國家/地區"><el-select v-model="formData.nationalArea" class="inputW2"><el-optionv-for="item in EmployeeEnum.isOverseas":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="護照號"><el-input v-model="formData.passportNo" placeholder="正規護照格式" class="inputW" /></el-form-item><el-form-item label="身份證號"><el-input v-model="formData.idNumber" placeholder="正規身份證格式" class="inputW" /></el-form-item><el-form-item label="籍貫"><el-input v-model="formData.nativePlace" placeholder="籍貫地址" class="inputW5" /></el-form-item><el-form-item label="民族"><el-input v-model="formData.nation" placeholder="請輸入民族" class="inputW2" /></el-form-item><el-form-item label="婚姻狀況"><el-select v-model="formData.maritalStatus" class="inputW2"><el-optionv-for="item in EmployeeEnum.maritaStatus":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="生日"><el-input v-model="formData.birthday" placeholder="示例 0323" class="inputW" /></el-form-item><el-form-item label="年齡"><el-input v-model="formData.age" type="number" class="inputW2" /></el-form-item><el-form-item label="星座"><el-select v-model="formData.constellation" class="inputW2"><el-optionv-for="item in EmployeeEnum.constellation":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="血型"><el-select v-model="formData.bloodType" class="inputW2"><el-optionv-for="item in EmployeeEnum.bloodType":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="戶籍所在地"><el-input v-model="formData.domicile" class="inputW5" /></el-form-item><el-form-item label="政治面貌"><el-input v-model="formData.politicalOutlook" class="inputW2" /></el-form-item><el-form-item label="入黨時間"><el-date-pickerv-model="formData.timeToJoinTheParty"type="date"placeholder="選擇日期"class="inputW"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="存檔機構"><el-input v-model="formData.archivingOrganization" placeholder="請輸入" /></el-form-item><el-form-item label="子女狀態"><el-input v-model="formData.stateOfChildren" placeholder="請輸入" /></el-form-item><el-form-item label="子女有無商業險"><el-radio-group v-model="formData.doChildrenHaveCommercialInsurance"><el-radio label="1">有</el-radio><el-radio label="2">無</el-radio></el-radio-group></el-form-item><el-form-item label="有無違法違紀狀態"><el-input v-model="formData.isThereAnyViolationOfLawOrDiscipline" placeholder="請輸入" /></el-form-item><el-form-item label="有無重大病史"><el-input v-model="formData.areThereAnyMajorMedicalHistories" placeholder="請輸入" /></el-form-item></div><!-- 通訊信息 --><div class="block"><div class="title">通訊信息</div><el-form-item label="QQ"><el-input v-model="formData.qq" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="微信"><el-input v-model="formData.wechat" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="現居住地"><el-input v-model="formData.placeOfResidence" placeholder="請輸入" /></el-form-item><el-form-item label="通訊地址"><el-input v-model="formData.postalAddress" placeholder="請輸入" /></el-form-item><el-form-item label="聯系手機"><el-input v-model="formData.contactTheMobilePhone" placeholder="11位字符" maxlength="11" class="inputW" @change.native="handlePhone(2)" /></el-form-item><el-form-item label="個人郵箱"><el-input v-model="formData.personalMailbox" placeholder="請輸入" type="mail" class="inputW" /></el-form-item><el-form-item label="緊急聯系人"><el-input v-model="formData.emergencyContact" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="緊急聯系電話"><el-input v-model="formData.emergencyContactNumber" placeholder="11位字符" class="inputW" /></el-form-item></div><!-- 賬號信息 --><div class="block"><div class="title">賬號信息</div><el-form-item label="社保電腦號"><el-input v-model="formData.socialSecurityComputerNumber" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="公積金賬號"><el-input v-model="formData.providentFundAccount" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="銀行卡號"><el-input v-model="formData.bankCardNumber" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="開戶行"><el-input v-model="formData.openingBank" placeholder="請輸入" class="inputW" /></el-form-item></div><!-- 教育信息 --><div class="block"><div class="title">教育信息</div><el-form-item label="學歷類型"><el-select v-model="formData.educationalType" placeholder="請選擇"><el-optionv-for="item in EmployeeEnum.educationType":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="畢業學校"><el-input v-model="formData.graduateSchool" placeholder="請輸入" class="inputW2" /></el-form-item><el-form-item label="入學時間"><el-date-picker v-model="formData.enrolmentTime" type="data" placeholder="請輸入時間" class="inputW" value-format="yyyy-MM-dd" /></el-form-item><el-form-item label="畢業時間"><el-date-picker v-model="formData.graduationTime" type="data" placeholder="請輸入時間" class="inputW" value-format="yyyy-MM-dd" /></el-form-item><el-form-item label="專業"><el-input v-model="formData.major" placeholder="請輸入" class="inputW" /></el-form-item></div><!-- 從業信息 --><div class="block"><div class="title">從業信息</div><el-form-item label="上家公司"><el-input v-model="formData.homeCompany" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="職稱"><el-input v-model="formData.title" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="有無競業限制"><el-input v-model="formData.isThereAnyCompetitionRestriction" placeholder="請輸入" style="width:80%" /></el-form-item><el-form-item label="備注"><el-input v-model="formData.remarks" type="textarea" placeholder="請輸入備注" style="width:80%" /></el-form-item><!-- 保存員工信息 --><el-row class="inline-info" type="flex" justify="center"><el-col :span="12"><el-button type="primary" @click="savePersonal">保存更新</el-button><el-button @click="$router.back()">返回</el-button></el-col></el-row></div></el-form></div></template> 本章節個人數據過于 繁雜,龐大,同學們在開發期間,拷貝代碼即可,我們只寫關鍵部位的代碼

定義user-info的數據

import EmployeeEnum from '@/api/constant/employees'export default {data() {return {userId: this.$route.params.id,EmployeeEnum, // 員工枚舉數據userInfo: {},formData: {userId: '',username: '', // 用戶名sex: '', // 性別mobile: '', // 手機companyId: '', // 公司iddepartmentName: '', // 部門名稱// onTheJobStatus: '', // 在職狀態 nodateOfBirth: '', // 出生日期timeOfEntry: '', // 入職時間theHighestDegreeOfEducation: '', // 最高學歷nationalArea: '', // 國家passportNo: '', // 護照號idNumber: '', // 身份證號idCardPhotoPositive: '', // 身份證照正idCardPhotoBack: '', // 身份證照正nativePlace: '', // 籍貫nation: '', // 民族englishName: '', // 英文名字maritalStatus: '', // 婚姻狀況staffPhoto: '', // 員工照片birthday: '', // 生日zodiac: '', // 屬相age: '', // 年齡constellation: '', // 星座bloodType: '', // 血型domicile: '', // 戶籍所在地politicalOutlook: '', // 政治面貌timeToJoinTheParty: '', // 入黨時間archivingOrganization: '', // 存檔機構stateOfChildren: '', // 子女狀態doChildrenHaveCommercialInsurance: '1', // 保險狀態isThereAnyViolationOfLawOrDiscipline: '', // 違法違紀狀態areThereAnyMajorMedicalHistories: '', // 重大病史qq: '', // QQwechat: '', // 微信residenceCardCity: '', // 居住證城市dateOfResidencePermit: '', // 居住證辦理日期residencePermitDeadline: '', // 居住證截止日期placeOfResidence: '', // 現居住地postalAddress: '', // 通訊地址contactTheMobilePhone: '', // 聯系手機personalMailbox: '', // 個人郵箱emergencyContact: '', // 緊急聯系人emergencyContactNumber: '', // 緊急聯系電話socialSecurityComputerNumber: '', // 社保電腦號providentFundAccount: '', // 公積金賬號bankCardNumber: '', // 銀行卡號openingBank: '', // 開戶行educationalType: '', // 學歷類型graduateSchool: '', // 畢業學校enrolmentTime: '', // 入學時間graduationTime: '', // 畢業時間major: '', // 專業graduationCertificate: '', // 畢業證書certificateOfAcademicDegree: '', // 學位證書homeCompany: '', // 上家公司title: '', // 職稱resume: '', // 簡歷isThereAnyCompetitionRestriction: '', // 有無競業限制proofOfDepartureOfFormerCompany: '', // 前公司離職證明remarks: '' // 備注}}} }

在detail.vue組件中,注冊并使用

<el-tab-pane label="個人詳情"><!-- 放置個人詳情 --><component :is="userComponent" /><!-- <user-info /> --></el-tab-pane>

在以上代碼中,我們使用了動態組件component,它通過 is屬性來綁定需要顯示在該位置的組件,is屬性可以直接為注冊組件的組件名稱即可

1動態組件最大的作用: 切換組件

is必須是變量

2

3 設置文本框的寬度

3

<el-form-item label="現合同開始時間"><el-date-pickerv-model="formData.currentContractStartTime"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/> </el-form-item>

elementui的el-date-picker組件:format和value-format屬性運用

format:

顯示在輸入框中的格式(默認為yyyy-MM-dd HH:mm:ss)

value-format:

可選,綁定值的格式(不指定則綁定值默認為 Date 對象)

eg↓

<el-date-pickerv-model="searchParams.dateChar"@change="dateChange":clearable="false"type="datetimerange"size="small"format="yyyy年-MM月-dd日 HH時:mm分" value-format="yyyy-MM-dd HH:mm"range-separator="至"start-placeholder="開始日期"end-placeholder="結束日期"></el-date-picker>

format 👇

value-format👇

日期格式👇

4

<el-form-item label="子女有無商業險"><el-radio-group v-model="formData.doChildrenHaveCommercialInsurance"><el-radio label="1">有</el-radio><el-radio label="2">無</el-radio></el-radio-group></el-form-item>

封裝崗位組件

同理,封裝崗位組件

封裝崗位組件 src/views/employee/components/job-info.vue

<template> <div class="job-info"><!-- 基礎信息 --><el-form label-width="220px"><div class="block"><div class="title">基礎信息</div><el-form-item label="崗位"><el-input v-model="formData.post" placeholder="請輸入" class="inputW" /></el-form-item><!-- <el-form-item label="轉正日期"><el-date-pickerv-model="formData.dateOfCorrection"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item> --><el-form-item label="轉正狀態"><el-select v-model="formData.stateOfCorrection" placeholder="請選擇" disabled><el-optionv-for="item in EmployeeEnum.stateOfCorrection":key="item.value":value="item.value"/></el-select></el-form-item><el-form-item label="職級"><el-input v-model="formData.rank" class="inputW" /></el-form-item><el-form-item label="轉正評價"><el-input v-model="formData.correctionEvaluation" type="textarea" placeholder="1-300位字符" /></el-form-item><el-form-item label="匯報對象"><el-select v-model="formData.reportId" filterable placeholder="請選擇" class="inputW"><el-option v-for="item in depts" :key="item.id" :label="item.username" :value="item.id" /></el-select></el-form-item><el-form-item label="HRBP"><el-select v-model="formData.hrbp" filterable placeholder="請選擇" class="inputW"><el-option v-for="item in depts" :key="item.id" :label="item.username" :value="item.id" class="inputW" /></el-select></el-form-item><el-form-item class="formInfo" label="調整司齡(天):"><el-input v-model="formData.adjustmentAgedays" type="number" placeholder="請輸入" class="inputW" /></el-form-item><el-form-item label="首次參加工作時間"><el-date-pickerv-model="formData.workingTimeForTheFirstTime"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="調整工齡"><el-input v-model="formData.adjustmentOfLengthOfService" placeholder="0.00年" class="inputW" disabled /></el-form-item></div><!-- 合同信息 --><div class="block"><div class="title">合同信息</div><el-form-item class="formInfo" label="首次合同開始時間:"><el-date-pickerv-model="formData.initialContractStartTime"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="首次合同結束時間"><el-date-pickerv-model="formData.firstContractTerminationTime"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="現合同開始時間"><el-date-pickerv-model="formData.currentContractStartTime"type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="現合同結束時間"><el-date-pickerv-model="formData.closingTimeOfCurrentContract "type="date"placeholder="選擇日期"value-format="yyyy-MM-dd"/></el-form-item><el-form-item label="合同期限"><el-select v-model="formData.contractPeriod" class="filter-item"><el-optionv-for="item in EmployeeEnum.contractPeriod":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="續簽次數"><el-select v-model="formData.renewalNumber" class="filter-item"><el-optionv-for="item in EmployeeEnum.renewalCount":key="item.id":label="item.value":value="item.id"/></el-select></el-form-item></div><!-- 招聘信息 --><div class="block"><div class="title">招聘信息</div><el-form-item label="其他招聘渠道"><el-select v-model="formData.otherRecruitmentChannels" placeholder="請選擇"><el-optionv-for="item in EmployeeEnum.resumeSource":key="item.id":label="item.value":value="item.value"/></el-select></el-form-item><el-form-item label="招聘渠道"><el-select v-model="formData.recruitmentChannels" placeholder="請選擇"><el-optionv-for="item in EmployeeEnum.resumeSource":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="社招/校招"><el-select v-model="formData.socialRecruitment" placeholder="請選擇"><el-optionv-for="item in EmployeeEnum.hireSourceType":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="推薦企業/人"><el-input v-model="formData.recommenderBusinessPeople" placeholder="請輸入" class="infoPosition inputW" /></el-form-item></div><!-- 從業信息 --><el-form-item><el-button type="primary" @click="saveJob">保存更新</el-button><el-button @click="$router.back()">返回</el-button></el-form-item></el-form></div></template>

定義崗位數據

import EmployeeEnum from '@/api/constant/employees'export default {data() {return {userId: this.$route.params.id,depts: [],EmployeeEnum,formData: {adjustmentAgedays: '', // 調整司齡天adjustmentOfLengthOfService: '', // 調整工齡天closingTimeOfCurrentContract: '', // 現合同結束時間companyId: '', // 公司IDcontractDocuments: '', // 合同文件contractPeriod: '', // 合同期限correctionEvaluation: '', // 轉正評價currentContractStartTime: '', // 現合同開始時間firstContractTerminationTime: '', // 首次合同結束時間hrbp: '', // HRBPinitialContractStartTime: '', // 首次合同開始時間otherRecruitmentChannels: '', // 其他招聘渠道post: '', // 崗位rank: null, // 職級recommenderBusinessPeople: '', // 推薦企業人recruitmentChannels: '', // 招聘渠道renewalNumber: '', // 續簽次數reportId: '', // 匯報對象reportName: null, // 匯報對象socialRecruitment: '', // 社招校招stateOfCorrection: '', // 轉正狀態taxableCity: '', // 納稅城市userId: '', // 員工IDworkMailbox: '', // 工作郵箱workingCity: '', // 工作城市workingTimeForTheFirstTime: '' // 首次參加工作時間}}} }

在detail.vue組件中,注冊并使用

<el-tab-pane label="崗位詳情"><!-- 放置崗位詳情 --><component :is="JobInfo" /></el-tab-pane>

本節任務:完成個人組件和崗位組件封裝

員工個人信息和崗位信息-讀取-保存


目標:實現個人信息的崗位信息的讀取和校驗,保存

讀取個人保存個人信息

這個環節里面大部分都是繁雜的屬性和重復的過程,所以該環節直接將過程代碼拷貝到項目中即可

封裝 讀取個人信息 保存個人信息 讀取崗位信息 保存崗位信息

/** ** 讀取用戶詳情的基礎信息* **/ export function getPersonalDetail(id) {return request({url: `/employees/${id}/personalInfo`}) }/** ** 更新用戶詳情的基礎信息* **/ export function updatePersonal(data) {return request({url: `/employees/${data.userId}/personalInfo`,method: 'put',data}) }/** *** 獲取用戶的崗位信息** ****/ export function getJobDetail(id) {return request({url: `/employees/${id}/jobs`}) }/*** 保存崗位信息* ****/ export function updateJob(data) {return request({url: `/employees/${data.userId}/jobs`,method: 'put',data}) }

讀取,保存個人信息 user-info 需要注意:這里的保存實際上分成了兩個接口,這是接口的設計,我們只能遵守

import { getPersonalDetail, updatePersonal, saveUserDetailById } from '@/api/employees' import { getUserDetailById } from '@/api/user'created() {this.getPersonalDetail()this.getUserDetailById()},methods: {async getPersonalDetail() {this.formData = await getPersonalDetail(this.userId) // 獲取員工數據},async savePersonal() {await updatePersonal({ ...this.formData, id: this.userId })this.$message.success('保存成功')},async saveUser() {// 調用父組件await saveUserDetailById(this.userInfo)this.$message.success('保存成功')},async getUserDetailById() {this.userInfo = await getUserDetailById(this.userId)}}

讀取保存崗位信息

讀取,保存崗位信息 job-info

import { getEmployeeSimple, updateJob, getJobDetail } from '@/api/employees'created() {this.getJobDetail()this.getEmployeeSimple()},methods: {async getJobDetail() {this.formData = await getJobDetail(this.userId)},// 獲取員工列表async getEmployeeSimple() {this.depts = await getEmployeeSimple()},// 保存崗位信息async saveJob() {await updateJob(this.formData)this.$message.success('保存崗位信息成功')}}

提交代碼

本節任務 實現個人信息的崗位信息的讀取和校驗,保存

配置騰訊云Cos


目標: 配置一個騰訊云cos

由于上課的開發的特殊性,我們不希望把所有的圖片都上傳到我們自己的官方服務器上,這里我們可以采用一個騰訊云的圖片方案

上邊圖的意思就是說,我們找一個可以免費上傳圖片的服務器,幫我們 代管圖片,我們在自己的數據庫里只保存一個地址就行, 這其實也是很多項目的處理方案,會有一個 公共的文件服務器

第一步,我們必須先擁有一個騰迅云的開發者賬號(小心騰訊云的廣告電話)

請按照騰訊云的注冊方式,注冊自己的賬號

第二步,實名認證

選擇個人賬戶

填寫個人身份信息

下一步,掃描二維碼授權

手機端授權

點擊領取免費產品

選擇對象存儲COS

我們免費擁有 6個月的50G流量的對象存儲空間使用權限,足夠我們上傳用戶頭像的使用了

點擊0元試用,開通服務

到這一步,賬號的部分就操作完畢,接下來,我們需要來創建一個存儲圖片的存儲桶

登錄 對象存儲控制臺 ,創建存儲桶。設置存儲桶的權限為 公有讀,私有寫

設置cors規則

AllowHeader 需配成*,如下圖所示。

因為我們本身沒有域名,所以這里設置成 *,僅限于測試,正式環境的話,這里需要配置真實的域名地址

到這里,我們的騰訊云存儲桶就設置好了。

封裝上傳圖片組件-上傳組件需求分析


目標 梳理整個的上傳過程

初始化cos對象參數

名稱

描述

SecretId

開發者擁有的項目身份識別 ID,用以身份認證,可在 API 密鑰管理 頁面獲取

SecretKey

開發者擁有的項目身份密鑰,可在 API 密鑰管理 頁面獲取

注意,上述的參數我們在本次開發過程中,直接將參數放置在前端代碼中存儲,但是騰訊云本身是不建議這么做的,因為 敏感信息放在前端很容易被捕獲,由于我們本次是測試研發,所以這個過程可以忽略
正確的做法應該是,通過網站調用接口換取敏感信息

相關文檔

實例化 上傳sdk

var cos = new COS({SecretId: 'COS_SECRETID', // 身份識別 IDSecretKey: 'COS_SECRETKEY', // 身份密鑰 }); 到目前為止,我們上傳圖片準備的內容就已經OK,接下來,我們在 src/componets 新建一個 ImageUpload 組件

該組件需要滿足什么要求呢?

  • 可以顯示傳入的圖片地址

  • 可以刪除傳入的圖片地址

  • 可以上傳圖片到云服務器

  • 上傳到騰訊云之后,可以返回圖片地址,顯示

  • 上傳成功之后,可以回調成功函數

  • 這個上傳組件簡單嗎?

    no ! ! !

    看似需求很明確,但是它真正的實現很復雜,我們通過一個圖來看一下

    從上圖中,我們可以看到,實際上是有兩種場景的,本地場景和已經上傳的場景

    下個章節,針對這個場景我們進行開發

    封裝上傳組件-代碼實現


    目標實現上傳組件的代碼部分

    JavaScript SDK 需瀏覽器支持基本的 HTML5 特性(支持 IE10 以上瀏覽器),以便支持 ajax 上傳文件和計算文件 MD5 值。

    新建文件上傳組件

    安裝JavaScript SDK

    $ npm i cos-js-sdk-v5 --save

    新建上傳圖片組件 src/components/ImageUpload/index.vue

    上傳組件,我們可以沿用element的el-upload組件,并且采用照片墻的模式 list-type="picture-card"

    放置el-upload組件

    <template><el-upload list-type="picture-card"><i class="el-icon-plus" /></el-upload> </template>

    全局注冊組件

    import PageTools from './PageTools' import UploadExcel from './UploadExcel' import ImageUpload from './ImageUpload' export default {install(Vue) {Vue.component('PageTools', PageTools) // 注冊工具欄組件Vue.component('UploadExcel', UploadExcel) // 注冊導入excel組件Vue.component('ImageUpload', ImageUpload) // 注冊導入上傳組件} }

    點擊圖片進行預覽

    限定上傳的圖片數量和action

    <template><el-upload list-type="picture-card" :limit="1" action="#"></el-upload> </template> action為什么給#, 因為前面我們講過了,我們要上傳到騰訊云,需要自定義的上傳方式,action給個#防止報錯

    預覽

    <el-upload:on-preview="preview":file-list="fileList"list-type="picture-card"action="#":limit="1">data() {return {fileList: [], // 圖片地址設置為數組 showDialog: false, // 控制顯示彈層imgUrl: ''}},preview(file) {// 這里應該彈出一個層 層里是點擊的圖片地址this.imgUrl = file.urlthis.showDialog = true},

    預覽彈層

    <el-dialog title="圖片" :visible.sync="showDialog"><img :src="imgUrl" style="width:100%" alt=""></el-dialog>

    根據上傳數量控制上傳按鈕

    控制上傳顯示

    沒有圖片顯示加號,只要有圖片就不顯示加號

    computed: {// 設定一個計算屬性 判斷是否已經上傳完了一張fileComputed() {return this.fileList.length === 1}},<el-upload:on-preview="preview":file-list="fileList"list-type="picture-card"action="#":limit="1":class="{disabled: fileComputed }"><style> .disabled .el-upload--picture-card {display: none } </style>

    刪除圖片和添加圖片

    刪除文件

    <el-upload:on-preview="preview":on-remove="handleRemove":file-list="fileList"list-type="picture-card":on-change="changeFile"action="#":limit="1":class="{disabled: fileComputed }">handleRemove(file) {// file是點擊刪除的文件//fileList 刪過之后的文件// 將原來的文件給排除掉了 剩下的就是最新的數組了this.fileList = this.fileList.filter(item => item.uid !== file.uid)},

    刪除文件之后,要添加文件

    添加文件

    // 修改文件時觸發// 此時可以用fileList 因為該方法會進來很多遍 不能每次都去push// fileList因為fileList參數是當前傳進來的最新參數 我們只需要將其轉化成數組即可 需要轉化成一個新的數組// [] => [...fileList] [] => fileList.map()// 上傳成功之后 還會進來 需要實現上傳代碼的邏輯 這里才會成功changeFile(file, fileList) {this.fileList = fileList.map(item => item)}

    上傳之前檢查

    控制上傳圖片的類型和上傳大小, 如果不滿足條件 返回false上傳就會停止 <el-upload:on-preview="preview":on-remove="handleRemove":file-list="fileList"list-type="picture-card":on-change="changeFile":before-upload="beforeUpload"action="#":limit="1":class="{disabled: fileComputed }">beforeUpload(file) {// 要開始做文件上傳的檢查了// 文件類型 文件大小const types = ['image/jpeg', 'image/gif', 'image/bmp', 'image/png']if (!types.includes(file.type)) {this.$message.error('上傳圖片只能是 JPG、GIF、BMP、PNG 格式!')return false}// 檢查大小const maxSize = 5 * 1024 * 1024if (maxSize < file.size) {this.$message.error('圖片大小最大不能超過5M')return false}return true}

    上傳動作調用上傳騰訊云

    上傳動作為el-upload的http-request屬性

    <el-uploadlist-type="picture-card":file-list="fileList":on-preview="preview":on-remove="handleRemove":on-change="changeFile":before-upload="beforeUpload":http-request="upload"action="#":class="{disabled: fileComputed}">// 自定義上傳動作 有個參數 有個file對象,是我們需要上傳到騰訊云服務器的內容upload(params) {console.log(params.file)} 我們需要在該方法中,調用騰訊云的上傳方法

    騰訊云文檔地址

    身份ID和密鑰可以通過騰訊云平臺獲取

    登錄 訪問管理控制臺 ,獲取您的項目 SecretId 和 SecretKey。

    實現代碼

    import COS from 'cos-js-sdk-v5'const cos = new COS({SecretId: 'XXX', // 身份識別 IDSecretKey: 'XXX' // 身份密鑰})// 進行上傳操作upload(params) {// console.log(params.file)if (params.file) {// 執行上傳操作cos.putObject({Bucket: 'shuiruohanyu-106-1302806742', // 存儲桶Region: 'ap-beijing', // 地域Key: params.file.name, // 文件名Body: params.file, // 要上傳的文件對象StorageClass: 'STANDARD' // 上傳的模式類型 直接默認 標準模式即可// 上傳到騰訊云 =》 哪個存儲桶 哪個地域的存儲桶 文件 格式 名稱 回調}, function(err, data) {// data返回數據之后 應該如何處理console.log(err || data)})}}

    上傳成功之后處理返回數據

    如何處理返回成功的返回數據

    確定要上傳記錄id

    beforeUpload(file) {// 先檢查文件類型const types = ['image/jpeg', 'image/gif', 'image/bmp', 'image/png']if (!types.some(item => item === file.type)) {// 如果不存在this.$message.error('上傳圖片只能是 JPG、GIF、BMP、PNG 格式!')return false // 上傳終止}// 檢查文件大小 5M 1M = 1024KB 1KB = 1024Bconst maxSize = 5 * 1024 * 1024if (file.size > maxSize) {// 超過了限制的文件大小this.$message.error('上傳的圖片大小不能大于5M')return false}// 已經確定當前上傳的就是當前的這個file了 + this.currentFileUid = file.uidreturn true // 最后一定要return true}, 處理返回數據

    吧本地的地址變成上傳cos之后的地址

    // 進行上傳操作upload(params) {// console.log(params.file)if (params.file) {// 執行上傳操作cos.putObject({Bucket: 'shuiruohanyu-106-1302806742', // 存儲桶Region: 'ap-beijing', // 地域Key: params.file.name, // 文件名Body: params.file, // 要上傳的文件對象StorageClass: 'STANDARD' // 上傳的模式類型 直接默認 標準模式即可// 上傳到騰訊云 =》 哪個存儲桶 哪個地域的存儲桶 文件 格式 名稱 回調}, (err, data) => {// data返回數據之后 應該如何處理console.log(err || data)// data中有一個statusCode === 200 的時候說明上傳成功if (!err && data.statusCode === 200) {// 此時說明文件上傳成功 要獲取成功的返回地址// fileList才能顯示到上傳組件上 此時我們要將fileList中的數據的url地址變成 現在上傳成功的地址// 目前雖然是一張圖片 但是請注意 我們的fileList是一個數組// 需要知道當前上傳成功的是哪一張圖片this.fileList = this.fileList.map(item => {// 去找誰的uid等于剛剛記錄下來的idif (item.uid === this.currentFileUid) {// 將成功的地址賦值給原來的url屬性return { url: 'http://' + data.Location, upload: true }// upload 為true 表示這張圖片已經上傳完畢 這個屬性要為我們后期應用的時候做標記// 保存 => 圖片有大有小 => 上傳速度有快又慢 =>要根據有沒有upload這個標記來決定是否去保存}return item})// 將上傳成功的地址 回寫到了fileList中 fileList變化 =》 upload組件 就會根據fileList的變化而去渲染視圖}})}} 我們在fileList中設置了屬性為upload為true的屬性,表示該圖片已經上傳成功了,如果fileList還有upload不為true的數據,那就表示該圖片還沒有上傳完畢

    上傳的進度條顯示

    為了再上傳圖片過程中顯示進度條,我們可以使用element-ui的進度條顯示當前的上傳進度

    放置進度條

    <el-progress v-if="showPercent" style="width: 180px" :percentage="percent" />

    定義一個變量percent來控制 進度多少

    上傳之前 顯示, 上傳之后 隱藏

    通過騰訊云sdk監聽上傳進度

    cos.putObject({// 配置Bucket: 'laogao-1302806742', // 存儲桶名稱Region: 'ap-guangzhou', // 存儲桶地域Key: params.file.name, // 文件名作為keyStorageClass: 'STANDARD', // 此類寫死Body: params.file, // 將本地的文件賦值給騰訊云配置// 進度條onProgress: (params) => {this.percent = params.percent * 100}}

    完整代碼

    <template><div><!-- 放置一個上傳組件 --><!-- action這里不寫上傳地址 因為我們是調用騰訊云cos 不是一個地址可以搞定的 要用自定義的上傳 --><el-upload:on-preview="preview":on-remove="handleRemove":on-change="changeFile":before-upload="beforeUpload":file-list="fileList":http-request="upload"list-type="picture-card"action="#":limit="1":class="{disabled: fileComputed }"><i class="el-icon-plus" /></el-upload><!-- 進度條 --><el-progress v-if="showPercent" style="width: 180px" :percentage="percent" /><!-- 放置一個彈層 --><!-- sync修飾符自動將彈層關閉了 --><el-dialog title="圖片" :visible.sync="showDialog"><img :src="imgUrl" style="width:100%" alt=""></el-dialog></div> </template><script> import COS from 'cos-js-sdk-v5' // 引入騰訊云的包 // 需要實例化 const cos = new COS({SecretId: 'AKID0mqfEWqlUzIbeSkGRL6c7ML6c0B93To9',SecretKey: 'JFwNZdeRF2iOp03FFsGNDm44vWFitmNF' }) // 實例化的包 已經具有了上傳的能力 可以上傳到該賬號里面的存儲桶了 export default {data() {return {fileList: [],showDialog: false, // 控制圖片的顯示或者隱藏imgUrl: '', // 存儲點擊的圖片地址currentFileUid: '', // 用一個變量 記住當前上傳的圖片idpercent: 0,showPercent: false // 默認不顯示進度條}},computed: {// 設定一個計算屬性 判斷是否已經上傳完了一張fileComputed() {return this.fileList.length === 1}},methods: {preview(file) {// 這里應該彈出一個層 層里是點擊的圖片地址this.imgUrl = file.urlthis.showDialog = true},handleRemove(file) {// file是點擊刪除的文件// 將原來的文件給排除掉了 剩下的就是最新的數組了this.fileList = this.fileList.filter(item => item.uid !== file.uid)},// 修改文件時觸發// 此時可以用fileList 因為該方法會進來很多遍 不能每次都去push// fileList因為fileList參數是當前傳進來的最新參數 我們只需要將其轉化成數組即可 需要轉化成一個新的數組// [] => [...fileList] [] => fileList.map()// 上傳成功之后 還會進來 需要實現上傳代碼的邏輯 這里才會成功changeFile(file, fileList) {this.fileList = fileList.map(item => item)},beforeUpload(file) {// 要開始做文件上傳的檢查了// 文件類型 文件大小const types = ['image/jpeg', 'image/gif', 'image/bmp', 'image/png']if (!types.includes(file.type)) {this.$message.error('上傳圖片只能是 JPG、GIF、BMP、PNG 格式!')return false}// 檢查大小const maxSize = 5 * 1024 * 1024if (maxSize < file.size) {this.$message.error('圖片大小最大不能超過5M')return false}// file.uidthis.currentFileUid = file.uid // 記住當前的uidthis.showPercent = truereturn true},// 自定義上傳動作 有個參數 有個file對象,是我們需要上傳到騰訊云服務器的內容upload(params) {if (params.file) {// 上傳文件到騰訊云cos.putObject({// 配置Bucket: 'laogao-1302806742', // 存儲桶名稱Region: 'ap-guangzhou', // 存儲桶地域Key: params.file.name, // 文件名作為keyStorageClass: 'STANDARD', // 此類寫死Body: params.file, // 將本地的文件賦值給騰訊云配置// 進度條onProgress: (params) => {this.percent = params.percent * 100}}, (err, data) => {// 需要判斷錯誤與成功if (!err && data.statusCode === 200) {// 如果沒有失敗表示成功了// 此時認為上傳成功了// this.currentFileUid// 仍然有個小問題, 比如此時我們正在上傳,但是調用了保存,保存在上傳過程中進行,// 此時上傳還沒有完成 此時可以這樣做 : 給所有上傳成功的圖片 加一個屬性 upload: truethis.fileList = this.fileList.map(item => {if (item.uid === this.currentFileUid) {// upload為true表示 該圖片已經成功上傳到服務器,地址已經是騰訊云的地址了 就不可以執行保存了return { url: 'http://' + data.Location, upload: true } // 將本地的地址換成騰訊云地址}return item})setTimeout(() => {this.showPercent = false // 隱藏進度條this.percent = 0 // 進度歸0}, 2000)// 將騰訊云地址寫入到fileList上 ,保存的時候 就可以從fileList中直接獲取圖片地址// 此時注意,我們應該記住 當前上傳的是哪個圖片 上傳成功之后,將圖片的地址賦值回去}})}}} } </script><style> .disabled .el-upload--picture-card {display: none } </style> 上傳動作中,用到了上個小節中,我們注冊的騰訊云cos的 存儲桶名稱地域名稱

    通過上面的代碼,我們會發現,我們把上傳之后的圖片信息都給了fileList數據,那么在應用時,就可以直接獲取該實例的fileList數據即可

    提交代碼

    本節任務 完成上傳組件的封裝

    在員工詳情中應用上傳組件


    目標:應用封裝好的上傳組件

    將員工的頭像和證件照賦值給上傳組件

    user-info.vue中放置上傳組件

    員工頭像

    <!-- 員工照片 --><el-row class="inline-info"><el-col :span="12"><el-form-item label="員工頭像"><!-- 放置上傳圖片 --><image-upload ref="staffPhoto" /></el-form-item></el-col></el-row>

    讀取時賦值頭像

    // 讀取上半部分的內容async getUserDetailById() {this.userInfo = await getUserDetailById(this.userId)if (this.userInfo.staffPhoto) {// 這里我們賦值,同時需要給賦值的地址一個標記 upload: truethis.$refs.staffPhoto.fileList = [{ url: this.userInfo.staffPhoto, upload: true }]}},

    員工證件照

    <el-form-item label="員工照片"><!-- 放置上傳圖片 --><!-- ref不要重名 --><image-upload ref="myStaffPhoto" /></el-form-item>

    讀取時賦值照片

    // 讀取下半部分內容async getPersonalDetail() {this.formData = await getPersonalDetail(this.userId)if (this.formData.staffPhoto) {this.$refs.myStaffPhoto.fileList = [{ url: this.formData.staffPhoto, upload: true }]}},

    保存時處理頭像和證件照的保存

    當點擊保存更新時,獲取圖片的內容

    async saveUser() {// 去讀取 員工上傳的頭像const fileList = this.$refs.staffPhoto.fileList // 讀取上傳組件的數據if (fileList.some(item => !item.upload)) {// 如果此時去找 upload為false的圖片 找到了說明 有圖片還沒有上傳完成this.$message.warning('您當前還有圖片沒有上傳完成!')return}// 通過合并 得到一個新對象await saveUserDetailById({ ...this.userInfo, staffPhoto: fileList && fileList.length ? fileList[0].url : '' })this.$message.success('保存基本信息成功')}, 上面代碼中,upload如果為true,表示該圖片已經完成上傳,以此來判斷圖片是否已經上傳完成

    保存時讀取頭像

    async savePersonal() {const fileList = this.$refs.myStaffPhoto.fileListif (fileList.some(item => !item.upload)) {// 如果此時去找 upload為false的圖片 找到了說明 有圖片還沒有上傳完成this.$message.warning('您當前還有圖片沒有上傳完成!')return}await updatePersonal({ ...this.formData, staffPhoto: fileList && fileList.length ? fileList[0].url : '' })this.$message.success('保存基礎信息成功')}

    提交代碼

    本節任務 : 在員工詳情中應用上傳組件

    員工列表顯示圖片


    目標:在員工列表中心顯示圖片

    員工的頭像可以在列表項中添加一列來進行顯示 <el-table-column label="頭像" align="center"><template slot-scope="{row}"><imgslot="reference"v-imageerror="require('@/assets/common/bigUserHeader.png')":src="row.staffPhoto "style="border-radius: 50%; width: 100px; height: 100px; padding: 10px"alt=""></template> </el-table-column> 我們嘗試用之前的指令來處理圖片的異常問題,但是發現只有兩三張圖片能顯示

    這是因為有的員工的頭像的地址為空,給img賦值空的src不能觸發錯誤事件,針對這一特點,我們需要對指令進行升級

    插入節點的鉤子里面判斷空, 然后在組件更新之后的鉤子中同樣判斷空

    export const imageerror = {inserted(dom, options) {// 圖片異常的邏輯// 監聽img標簽的錯誤事件 因為圖片加載失敗 會觸發 onerror事件dom.src = dom.src || options.valuedom.onerror = function() {// 圖片失敗 賦值一個默認的圖片dom.src = options.value}},componentUpdated(dom, options) {dom.src = dom.src || options.value} }

    這樣我們可以看到每個用戶的頭像了,如果沒有頭像則顯示默認圖片

    任務:員工列表顯示圖片

    圖片地址生成二維碼


    目標 將圖片地址生成二維碼顯示

    我們想完成這樣一個功能,當我們擁有頭像地址時,將頭像地址生成一個二維碼,用手機掃碼來訪問

    首先,需要安裝生成二維碼的插件

    $ npm i qrcode qrcode的用法是

    QrCode.toCanvas(dom, info) dom為一個canvas的dom對象, info為轉化二維碼的信息

    我們嘗試將canvas標簽放到dialog的彈層中

    <el-dialog title="二維碼" :visible.sync="showCodeDialog" @opened="showQrCode" @close="imgUrl=''"><el-row type="flex" justify="center"><canvas ref="myCanvas" /></el-row></el-dialog>

    在點擊員工的圖片時,顯示彈層,并將圖片地址轉化成二維碼

    showQrCode(url) {// url存在的情況下 才彈出層if (url) {this.showCodeDialog = true // 數據更新了 但是我的彈層會立刻出現嗎 ?頁面的渲染是異步的!!!!// 有一個方法可以在上一次數據更新完畢,頁面渲染完畢之后this.$nextTick(() => {// 此時可以確認已經有ref對象了QrCode.toCanvas(this.$refs.myCanvas, url) // 將地址轉化成二維碼// 如果轉化的二維碼后面信息 是一個地址的話 就會跳轉到該地址 如果不是地址就會顯示內容})} else {this.$message.warning('該用戶還未上傳頭像')}}

    打印員工信息


    目標 完成個人信息和工作信息的打印功能

    新建打印頁面及路由

    創建頁面組件

    <template><div class="dashboard-container" id="myPrint"><div class="app-container"><el-card><el-breadcrumb separator="/" class="titInfo "><el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item><el-breadcrumb-item><router-link :to="{'path':'/employees'}">員工管理</router-link></el-breadcrumb-item><el-breadcrumb-item>打印</el-breadcrumb-item></el-breadcrumb><div v-if="type === 'personal'"><h2 class="centInfo">員工信息表</h2><table cellspacing="0" width="100%" class="tableList"><tr class="title"><td colspan="8" class="centInfo">基本信息</td></tr><tr><th style="width:10%">姓名</th><td colspan="6" style="width:80%">{{ formData.username }}</td><td rowspan="5" style="width:10%"><img style="width:155px;height:218px" :src="formData.staffPhoto"></td></tr><tr><th>性別</th><td colspan="6">{{ formData.sex }}</td></tr><tr><th>手機</th><td colspan="6">{{ formData.mobile }}</td></tr><tr><th>出生日期</th><td colspan="6">{{ formData.dateOfBirth | formatDate }}</td></tr><tr><th>最高學歷</th><td colspan="6">{{ formData.theHighestDegreeOfEducation }}</td></tr><tr><th style="width:10%">是否可編輯</th><td style="width:35%">{{ formData.isItEditable }}</td><th style="width:10%">是否隱藏號碼</th><td colspan="5" style="width:45%">{{ formData.doYouHideNumbers }}</td></tr><tr><th>國家地區</th><td>{{ formData.nationalArea }}</td><th>護照號</th><td colspan="5">{{ formData.passportNo }}</td></tr><tr><th>身份證號</th><td>{{ formData.idNumber }}</td><th>身份證照片</th><td colspan="5">{{ formData.iDCardPhoto }}</td></tr><tr><th>籍貫</th><td>{{ formData.nativePlace }}</td><th>民族</th><td colspan="5">{{ formData.nation }}</td></tr><tr><th>英文名</th><td>{{ formData.englishName }}</td><th>婚姻狀況</th><td colspan="5">{{ formData.maritalStatus }}</td></tr><tr><th>員工照片</th><td>{{ formData.staffPhoto }}</td><th>生日</th><td colspan="5">{{ formData.birthday }}</td></tr><tr><th>屬相</th><td>{{ formData.zodiac }}</td><th>年齡</th><td colspan="5">{{ formData.age }}</td></tr><tr><th>星座</th><td>{{ formData.constellation }}</td><th>血型</th><td colspan="5">{{ formData.bloodType }}</td></tr><tr><th>戶籍所在地</th><td>{{ formData.domicile }}</td><th>政治面貌</th><td colspan="5">{{ formData.politicalOutlook }}</td></tr><tr><th>入黨時間</th><td>{{ formData.timeToJoinTheParty }}</td><th>存檔機構</th><td colspan="5">{{ formData.archivingOrganization }}</td></tr><tr><th>子女狀態</th><td>{{ formData.stateOfChildren }}</td><th>子女有無商業保險</th><td colspan="5">{{ formData.doChildrenHaveCommercialInsurance }}</td></tr><tr><th>有無違法違紀行為</th><td>{{ formData.isThereAnyViolationOfLawOrDiscipline }}</td><th>有無重大病史</th><td colspan="5">{{ formData.areThereAnyMajorMedicalHistories }}</td></tr><tr class="title"><td colspan="8" class="centInfo">通訊信息</td></tr><tr><th>QQ</th><td>{{ formData.qQ }}</td><th>微信</th><td colspan="5">{{ formData.weChat }}</td></tr><tr><th>居住證城市</th><td>{{ formData.residenceCardCity }}</td><th>居住證辦理日期</th><td colspan="5">{{ formData.dateOfResidencePermit }}</td></tr><tr><th>居住證截止日期</th><td>{{ formData.residencePermitDeadline }}</td><th>現居住地</th><td colspan="5">{{ formData.placeOfResidence }}</td></tr><tr><th>通訊地址</th><td>{{ formData.postalAddress }}</td><th>聯系手機</th><td colspan="5">{{ formData.contactTheMobilePhone }}</td></tr><tr><th>個人郵箱</th><td>{{ formData.personalMailbox }}</td><th>緊急聯系人</th><td colspan="5">{{ formData.emergencyContact }}</td></tr><tr><th>緊急聯系電話</th><td colspan="7">{{ formData.emergencyContactNumber }}</td></tr><tr class="title"><td colspan="8" class="centInfo">賬號信息</td></tr><tr><th>社保電腦號</th><td>{{ formData.socialSecurityComputerNumber }}</td><th>公積金賬號</th><td colspan="5">{{ formData.providentFundAccount }}</td></tr><tr><th>銀行卡號</th><td>{{ formData.bankCardNumber }}</td><th>開戶行</th><td colspan="5">{{ formData.openingBank }}</td></tr><tr class="title"><td colspan="8" class="centInfo">教育信息</td></tr><tr><th>學歷類型</th><td>{{ formData.educationalType }}</td><th>畢業學校</th><td colspan="5">{{ formData.graduateSchool }}</td></tr><tr><th>入學時間</th><td>{{ formData.enrolmentTime }}</td><th>畢業時間</th><td colspan="5">{{ formData.graduationTime }}</td></tr><tr><th>專業</th><td>{{ formData.major }}</td><th>畢業證書</th><td colspan="5">{{ formData.graduationCertificate }}</td></tr><tr><th>學位證書</th><td colspan="7">{{ formData.certificateOfAcademicDegree }}</td></tr><tr class="title"><td colspan="8" class="centInfo">從業信息</td></tr><tr><th>上家公司</th><td>{{ formData.homeCompany }}</td><th>職稱</th><td colspan="5">{{ formData.title }}</td></tr><tr><th>簡歷</th><td>{{ formData.resume }}</td><th>有無競業限制</th><td colspan="5">{{ formData.isThereAnyCompetitionRestriction }}</td></tr><tr><th>前公司離職證明</th><td>{{ formData.proofOfDepartureOfFormerCompany }}</td><th>備注</th><td colspan="5">{{ formData.remarks }}</td></tr></table><div class="foot">簽字:___________日期:___________</div></div><div v-else><h2 class="centInfo">崗位信息表</h2><table cellspacing="0" width="100%" class="tableList"><tr class="title"><td colspan="4" class="centInfo">基本信息</td></tr><tr><th style="width:10%">姓名</th><td style="width:40%">{{ formData.username }}</td><th style="width:10%">入職日期</th><td style="width:40%">{{ formData.dateOfEntry }}</td></tr><tr><th>部門</th><td>{{ formData.departmentName }}</td><th>崗位</th><td>{{ formData.post }}</td></tr><tr><th>工作郵箱</th><td>{{ formData.workMailbox }}</td><th>工號</th><td>{{ formData.workNumber }}</td></tr><tr><th>轉正日期</th><td>{{ formData.dateOfCorrection }}</td><th>轉正狀態</th><td>{{ formData.stateOfCorrection }}</td></tr><tr><th>職級</th><td>{{ formData.rank }}</td><th>匯報對象</th><td>{{ formData.reportName }}</td></tr><tr><th>HRBP</th><td>{{ formData.hRBP }}</td><th>聘用形式</th><td>{{ formData.formOfEmployment }}</td></tr><tr><th>管理形式</th><td>{{ formData.formOfManagement }}</td><th>調整司齡</th><td>{{ formData.adjustmentAgedays }}</td></tr><tr><th>司齡</th><td>{{ formData.ageOfDivision }}</td><th>首次參加工作時間</th><td>{{ formData.workingTimeForTheFirstTime }}</td></tr><tr><th>調整工齡天</th><td>{{ formData.adjustmentOfLengthOfService }}</td><th>工齡</th><td>{{ formData.workingYears }}</td></tr><tr><th>納稅城市</th><td>{{ formData.taxableCity }}</td><th>轉正評價</th><td>{{ formData.correctionEvaluation }}</td></tr><tr class="title"><td colspan="4" class="centInfo">合同信息</td></tr><tr><th>首次合同開始時間</th><td>{{ formData.initialContractStartTime }}</td><th>首次合同結束時間</th><td>{{ formData.firstContractTerminationTime }}</td></tr><tr><th>現合同開始時間</th><td>{{ formData.currentContractStartTime }}</td><th>現合同結束時間</th><td>{{ formData.closingTimeOfCurrentContract }}</td></tr><tr><th>合同期限</th><td>{{ formData.contractPeriod }}</td><th>合同文件</th><td>{{ formData.contractDocuments }}</td></tr><tr><th>續簽次數</th><td colspan="3">{{ formData.renewalNumber }}</td></tr><tr class="title"><td colspan="4" class="centInfo">招聘信息</td></tr><tr><th>其他招聘渠道</th><td>{{ formData.otherRecruitmentChannels }}</td><th>招聘渠道</th><td>{{ formData.recruitmentChannels }}</td></tr><tr><th>社招校招</th><td>{{ formData.socialRecruitment }}</td><th>推薦企業人</th><td>{{ formData.recommenderBusinessPeople }}</td></tr></table><div class="foot">簽字:___________日期:___________</div></div></el-card></div></div> </template><script> import { getPersonalDetail, getJobDetail } from '@/api/employees' import { getUserDetailById } from '@/api/user' export default {data() {return {formData: {},userId: this.$route.params.id,type: this.$route.query.type // 打印類型}},// 創建完畢狀態created() {this.type === 'personal' ? this.getPersonalDetail() : this.getJobDetail()},// 組件更新methods: {async getPersonalDetail() {this.formData = await getPersonalDetail(this.userId) // 獲取個人基本信息},async getJobDetail() {const userInfo = await getUserDetailById(this.userId)const jobInfo = await getJobDetail(this.userId) // 獲取個人基本信息this.formData = { ...userInfo, ...jobInfo }}} } </script><style lang="scss"> .foot {padding: 30px 0;text-align: right; } </style>

    該頁面內容實際上就是讀取個人和詳情的接口數據,根據傳入的type類型決定顯示個人還是崗位

    type為personal時顯示個人,為job時顯示崗位

    新建打印頁面路由

    {path: 'print/:id', // 二級默認路由component: () => import('@/views/employees/print'), // 按需加載hidden: true,meta: {title: '打印', // 標記當前路由規則的中文名稱 后續在做左側菜單時 使用icon: 'people'}}

    完成詳情到打印的跳轉

    個人

    <el-row type="flex" justify="end"><el-tooltip content="打印個人基本信息"><router-link :to="`/employees/print/${userId}?type=personal`"><i class="el-icon-printer" /></router-link></el-tooltip></el-row>

    崗位

    <el-row type="flex" justify="end"><el-tooltip content="打印崗位信息"><router-link :to="`/employees/print/${userId}?type=job`"><i class="el-icon-printer" /></router-link></el-tooltip></el-row>

    利用vue-print-nb進行打印

    首先,打印功能我們借助一個比較流行的插件

    $ npm i vue-print-nb 它的用法是

    首先注冊該插件

    import Print from 'vue-print-nb' Vue.use(Print);

    使用v-print指令的方式進行打印

    <el-row type="flex" justify="end"><el-button v-print="printObj" size="small" type="primary">打印</el-button></el-row>printObj: {id: 'myPrint'}

    最終,我們看到的效果

    提交代碼

    本節任務打印員工信息

    通用的工具欄供大家使用

    總結

    以上是生活随笔為你收集整理的10 员工管理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。