父组件,可渲染数据
<!--
组件:职称填报
created by hexiaobo
参数说明:
方法:
setProfessionValue:向父组件传id,
setProfessionLabel:向父组件传label,
-->
<template>
<div>
<el-row :gutter="40" style="margin-left: 0;">
<template v-if="data && data.length > 0">
<el-col :xs="24" :sm="12" :md="12" :lg="8" v-for="(item,index) in data" :key="index" style="padding-left: 0;">
<div class="zige-item card">
<el-popconfirm
title="确定删除吗?"
v-if="editAble"
@onConfirm="professionDel(item.id,index)"
>
<a class="del" slot="reference">
<i class="el-icon-delete"></i>
</a>
</el-popconfirm>
<div style="font-size: 20px;height: 60px;color: #333;padding-right: 30px;">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-shouye-jieyezhengshu"></use>
</svg>
{{item.professionName}}
</div>
<div style="font-size: 14px;line-height: 30px;">职称编号:{{item.professionNumber}}</div>
<div style="font-size: 14px;line-height: 30px;margin-bottom: 15px;">获取时间:{{$formats.YYYYMMDDByHoriLine(item.certificateGetDate)}}</div>
<a class="showFiles" @click="showFileImg(item.files)">查看附件</a>
</div>
</el-col>
</template>
<template v-else><el-col>暂无职称记录</el-col></template>
</el-row>
<!-- 查看附件 -->
<files-preview
:filesPreviewArr="this.filesPreviewArr"
:dialogVisible.sync="dialogVisible"
/>
<!--/. 查看附件 -->
<!-- 新增form -->
<div class="" v-if="data.length < 6 && editAble" style="margin-top: 1rem;">
<el-form ref="professionsHolderForm" :inline="true" :model="professionsHolderForm">
<el-form-item
label=""
:rules="[{ required: true, message: '请选择职称', trigger: 'change' }]"
prop="professionId"
>
<profession-picker
ref="professionPicker"
:data="professionsHolderForm.professionId"
@setProfessionValueFC="setProfessionValue"
@setProfessionLabelFC="setProfessionLabel" />
</el-form-item>
<el-form-item label=""
prop="professionNumber"
:rules="[{ required: true, message: '请输入证书号', trigger: 'blur' }]"
>
<el-input
v-model="professionsHolderForm.professionNumber"
placeholder="证书号"
></el-input>
</el-form-item>
<el-form-item label=""
prop="certificateGetDate"
:rules="[{ required: true, message: '请选择时间', trigger: 'blur' }]"
>
<el-date-picker
v-model="professionsHolderForm.certificateGetDate"
/>
</el-form-item>
<el-form-item>
<el-button type="success" @click="addTitles('professionsHolderForm')">新增</el-button>
</el-form-item>
<div style="padding: 20px 0 10px">
<el-form-item prop="files" :rules="[{ required: true, message: '请上传附件'}]">
<el-upload
class="upload-box"
:on-success="handleUploadSuccess"
:before-upload="beforeUpload"
:on-remove="handleFileRemove"
:headers = "headers"
ref="professionUploader"
:limit="4"
:on-exceed="handleExceed"
:action="$baseUrl.common + '/file'"
>
<el-button size="mini" type="primary">点击上传</el-button>
<div slot="tip" class="" style="display: inline-block;padding-left: 1rem;font-size: 12px;">
请上传jpg/png/pdf文件,不超过2M
</div>
</el-upload>
</el-form-item>
</div>
</el-form>
</div>
<!--/. 新增form -->
</div>
</template>
<script>
import Vue from "vue"
import {DatePicker,Dialog,Message,Carousel,CarouselItem} from "element-ui"
import ProfessionPicker from "./pickers/ProfessionPicker";
import FilesPreview from "./FilesPreview";
Vue.use(DatePicker);
Vue.use(Dialog);
Vue.use(Carousel);
Vue.use(CarouselItem);
export default {
name: "ProfessionalTitles",
components: {FilesPreview, ProfessionPicker},
data() {
return {
headers:{},
options: [],
filesPreviewArr: [], //附件查看数组
dialogVisible: false,
//职称暂存
professionsHolderForm: {
"professionId":"",
"professionName": "",
"files": [],
"professionNumber": "",
"certificateGetDate": "",
},
}
},
props: {
data: "",
editAble:{default:true},
width: {
default: "80%"
}
},
mounted() {
//this.getOptions();
this.headers ={Authorization : 'Bearer '+(sessionStorage.getItem('token') || '')}
},
methods: {
getOptions() {
this.$HTTP.get(this.$baseUrl.global + '/titles-option', {
params: {}
}).then(response => {
let data = response.data;
this.options = data.data;
})
},
//查看附件图片
showFileImg(files){
this.dialogVisible = true;
this.filesPreviewArr = files;
},
setProfessionValue(v){
this.professionsHolderForm.professionId = v;
},
setProfessionLabel(v){
//取最后一级
this.professionsHolderForm.professionName = v;
},
//新增职称
addTitles(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
//Message.success('新增成功');
if(this.isRepeat()){
this.$emit('professionAdd',this.professionsHolderForm);
this.professionsHolderForm = {
"professionId": "",
"files": [],
"professionName": "",
"professionNumber": "",
"certificateGetDate": ""
}
}
} else {
console.log('error submit!!');
return false;
}
});
},
//判断是否重复添加
isRepeat(){
let idArr = [],
data = this.data,
nowId = this.professionsHolderForm.professionId;
for(let i in data){
idArr.push(data[i].professionId);
}
if(idArr.includes(nowId)){
Message.warning('该职称已存在。');
return false;
}else{
return true;
}
},
//附件上传成功
handleUploadSuccess(response, file ,fileList){
console.log(file)
let data = response;
if(!data.code){
this.professionsHolderForm.files.push({
id:file.response.data,
name:file.name,
type:file.raw.type
});
this.$refs.professionsHolderForm.validateField('files')
}else{
Message.error(data.msg);
this.clearUploadeList()
}
},
//上传之前的检查
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'application/pdf';
const isLt = file.size / 1024 < 2000;
if (!isJPG) {
Message.error('请上传jpg/png/pdf文件');
return false;
}
if (!isLt) {
Message.error('图片大小不能超过 2M!');
return false;
}
return isJPG && isLt;
},
//删除数组中特定项
deleteItem(item, list){
for (var key in list) {
list[key].id === item ? list.splice(key, 1) : null;
}
},
//删除附件
handleFileRemove(file, fileList){
let id=file.response.data;
this.deleteItem(id,this.professionsHolderForm.files); //删除数组中特定id项
},
handleExceed(files, fileList) {
Message.warning("附件数量已到上限。");
},
//清空上传列表
clearUploadeList(){
this.$refs.professionUploader.clearFiles()
},
//删除职称
professionDel(id,index){
this.$emit("professionDel",id,index)
},
clearPicker(){
this.$refs.professionPicker.clearCascader();
},
clearForm(){
this.clearUploadeList();
this.clearPicker();
}
},
computed: {
},
watch: {
/*'professionsHolderForm.professionId':{
handler:function(newV){
if(newV){
this.$refs.professionsHolderForm.validateField('professionId')
}
}
}*/
}
}
</script>
<style scoped lang="scss">
.icon{
width: 1.4em;
height: 1.4em;
vertical-align: middle;
}
.card{
@extend %card;
height: 200px;
padding: 20px;
color: #6d7592;
}
.zige-item{
font-size: 14px;
line-height: 26px;
margin-bottom: .4rem;
width: 100%;
position: relative;
a.showFiles{
border-radius: 3px;
padding: 4px 10px;
background: $mainGraybg;
color: #737373;
}
.del{
position: absolute;
top: 7px;
height: 46px;
padding: 0 15px;
line-height: 46px;
font-size: 16px;
right: 7px;
&:hover{
background-color: $mainGraybg;
}
}
}
</style>
级联选择器:
<!--
组件:职称选择器
created by hexiaobo
参数说明:
-->
<template>
<el-cascader
v-model="dataHolder"
:options="options"
:style="'width:'+ width"
:props='{value:"id",label:"name",children:"list"}'
:show-all-levels="false"
placeholder="请选择职称"
ref="cascader"
@change="changeCascader"
>
</el-cascader>
</template>
<script>
import Vue from "vue"
import {Cascader} from "element-ui"
Vue.use(Cascader);
export default {
name: "ProfessionPicker",
data() {
return {
dataHolder: "",
options: [],
form: {}
}
},
props: {
data: {},
width: {
default: "100%"
}
},
mounted() {
if (sessionStorage.getItem("base_code")) {
this.options = JSON.parse(sessionStorage.getItem("base_code")).tcprofession;
} else {
this.getOptions();
}
},
methods: {
getOptions() {
this.$HTTP.get(this.$baseUrl.codeData + '/base_code.json')
.then(response => {
var obj = response.data;
sessionStorage.setItem("base_code", JSON.stringify(obj));
this.options = JSON.parse(sessionStorage.getItem("base_code")).tcprofession;
});
},
changeCascader(val) {
let nodesObj = this.$refs['cascader'].getCheckedNodes();
console.log(nodesObj);
this.form.label = nodesObj[0].pathLabels.join("-");
this.form.value = nodesObj[0].path;
//向父级传值
let lastId = this.form.value[this.form.value.length -1];
let lastLabel = this.form.label.split("-")[this.form.label.split("-").length -1];
this.$emit('setProfessionValueFC', lastId);
this.$emit('setProfessionLabelFC', lastLabel);
},
//清空数据
clearCascader(){
this.dataHolder ="";
this.form={
value:"",
label:""
}
},
//拿到末级code,造出全级数组
codeFormat(code){
let arr=[],
lv1 = code.substring(0,2)+'0';
arr.push(lv1,code);
return arr;
}
},
computed: {
},
watch: {
data:{
handler:function(nv,ov){
if(nv){
this.dataHolder = this.codeFormat(nv);
}
},
immediate:true
}
}
}
</script>
<style scoped lang="scss">
</style>
附件预览组件:
<!--
组件:附件预览
created by hexiaobo
参数说明:
方法:
-->
<template>
<div>
<el-dialog :visible.sync="dialogVisible" @close="close" width="100%" height="100%" style="height: 80%;top: 10%;width: 80%;left: 10%;">
<el-carousel height="500px" :autoplay="false">
<el-carousel-item v-for="file in filesPreviewArr" :key="file.id">
<template v-if="file.type === 'application/pdf'">
<a target="_blank" :href="$baseUrl.common + '/file/'+file.id" class="btn-main-theme btn-md">点击查看pdf文件</a>
<!--<iframe :src="$baseUrl.common + '/file/'+file.id" frameborder="0" style="width: 100%;height: 100%;"></iframe>-->
</template>
<template v-else>
<img style="max-height: 100%;width: auto;height: auto;max-width: 100%"
:src="$baseUrl.common + '/file/'+file.id" alt="file.name">
</template>
</el-carousel-item>
</el-carousel>
</el-dialog>
</div>
</template>
<script>
import Vue from "vue"
import {Carousel,CarouselItem} from "element-ui"
Vue.use(Carousel);
Vue.use(CarouselItem);
export default {
name: "FilesPreview",
components: {},
data() {
return {
//dialogVisible: false
}
},
props: {
filesPreviewArr: "",
dialogVisible:{
default:false
}
},
mounted() {
},
methods: {
close(){
this.$emit("update:dialogVisible",false);
}
},
computed: {
},
watch: {
}
}
</script>
<style scoped lang="scss">
.el-carousel__item{
@include display-flex();
@include justify-content(center);
@include align-items(center);
overflow: auto;
}
</style>