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-column的formatter屬性進行設置
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 提供的導出方法中有 multiHeader和merges 的參數
參數 | 說明 | 類型 | 可選值 | 默認值 |
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'}最終,我們看到的效果
提交代碼
本節任務打印員工信息
通用的工具欄供大家使用
總結
- 上一篇: 风袖第一阶段小程序wx.request封
- 下一篇: 零知识证明在区块链中的应用