This commit is contained in:
Paidax
2024-07-24 15:10:07 +08:00
parent e2f6a9f4b1
commit 020b6c48ed
79 changed files with 7733 additions and 3760 deletions
@@ -0,0 +1,608 @@
<template>
<div class="slide-verify" :style="'width:' + canvaswidth + 'px'" onselectstart="return false;">
<!-- 图片加载遮蔽罩 -->
<div :class="isLoading ? 'img-loading' : ''" :style="'height:' + canvasheight + 'px'" v-if="isLoading"></div>
<!-- 认证成功后的文字提示 -->
<div class="success-hint" :style="'height:' + canvasheight + 'px'" v-if="verifySuccess">{{ successHint }}</div>
<!--前端生成-->
<template v-if="isFrontCheck">
<!--验证图片-->
<canvas ref="canvas" class="slide-canvas" :width="canvaswidth" :height="canvasheight"/>
<!--阻塞块-->
<canvas ref="block" class="slide-block" :width="canvaswidth" :height="canvasheight"/>
</template>
<!--后端生成-->
<template v-else>
<!--验证图片-->
<img ref="canvas" class="slide-canvas" :width="canvaswidth" :height="canvasheight"/>
<!--阻塞块-->
<img ref="block" :class="verifyFail ? 'slide-block verify-fail' : 'slide-block'"/>
</template>
<!--刷新按钮-->
<div class="refresh" @click="refresh"><i class="el-icon-refresh-right"></i>刷新</div>
<!-- 滑动条 -->
<div :class="getClass()">
<!--滑块-->
<div class="slider-box" :style="'width:' + sliderBoxWidth">
<!-- 按钮 -->
<div class="slider-button" id="slider-button" :style="'left:' + sliderButtonLeft">
<!-- 按钮图标 -->
<div class="slider-button-icon"></div>
</div>
</div>
<!--滑动条提示文字-->
<span class="slider-hint">{{ sliderhint }}</span>
</div>
</div>
</template>
<script>
function sum(x, y) {
return x + y;
}
function square(x) {
return x * x;
}
module.exports = {
props: {
// 阻塞块长度
blocklength: {
type: Number,
default: 42,
},
// 阻塞块弧度
blockradius: {
type: Number,
default: 10,
},
// 画布宽度
canvaswidth: {
type: Number,
default: 320,
},
// 画布高度
canvasheight: {
type: Number,
default: 155,
},
// 滑块操作提示
sliderhint: {
type: String,
default: '向右滑动',
},
// 可允许的误差范围小;为1时,则表示滑块要与凹槽完全重叠,才能验证成功。默认值为5,若为 -1 则不进行机器判断
accuracy: {
type: Number,
default: 3,
},
// 图片资源数组
imagelist: {
type: Array,
default: () => [],
},
},
data() {
return {
// 前端校验
isFrontCheck: false,
// 校验进行状态
verifyActive: false,
// 校验成功状态
verifySuccess: false,
// 校验失败状态
verifyFail: false,
// 阻塞块对象
blockObj: null,
// 图片画布对象
canvasCtx: null,
// 阻塞块画布对象
blockCtx: null,
// 阻塞块宽度
blockWidth: this.blocklength * 2,
// 阻塞块的横轴坐标
blockX: undefined,
// 阻塞块的纵轴坐标
blockY: undefined,
// 图片对象
image: undefined,
// 移动的X轴坐标
originX: undefined,
// 移动的Y轴做坐标
originY: undefined,
// 拖动距离数组
dragDistanceList: [],
// 滑块箱拖动宽度
sliderBoxWidth: 0,
// 滑块按钮距离左侧起点位置
sliderButtonLeft: 0,
// 鼠标按下状态
isMouseDown: false,
// 图片加载提示,防止图片没加载完就开始验证
isLoading: true,
// 时间戳,计算滑动时长
timestamp: null,
// 成功提示
successHint: '',
// 随机字符串
nonceStr: undefined,
};
},
mounted() {
this.init();
},
methods: {
getClass() {
let str = 'slider '
if(this.verifyActive) {
str += 'verify-active '
}
if(this.verifySuccess) {
str += 'verify-success '
}
if(this.verifyFail) {
str += 'verify-fail '
}
return str
},
/* 初始化*/
init() {
this.initDom();
this.bindEvents();
},
/* 初始化DOM对象*/
initDom() {
this.blockObj = this.$refs.block;
if (this.isFrontCheck) {
this.canvasCtx = this.$refs.canvas.getContext('2d');
this.blockCtx = this.blockObj.getContext('2d');
this.initImage();
} else {
this.getCaptcha();
}
},
/* 后台获取验证码*/
async getCaptcha() {
let self = this;
//取后端默认值
const response = await $.post('/captcha/get-captcha')
const data = response.data;
self.nonceStr = data.nonceStr;
self.$refs.block.src = data.blockSrc;
self.$refs.block.style.top = data.blockY + 'px';
self.$refs.canvas.src = data.canvasSrc;
self.isLoading = false;
},
/* 前端获取验证码*/
initImage() {
const image = this.createImage(() => {
this.drawBlock();
let {canvaswidth, canvasheight, blockX, blockY, blockradius, blockWidth} = this;
this.canvasCtx.drawImage(image, 0, 0, canvaswidth, canvasheight);
this.blockCtx.drawImage(image, 0, 0, canvaswidth, canvasheight);
// 将抠图防止最左边位置
let yAxle = blockY - blockradius * 2;
let ImageData = this.blockCtx.getImageData(blockX, yAxle, blockWidth, blockWidth);
this.blockObj.width = blockWidth;
this.blockCtx.putImageData(ImageData, 0, yAxle);
// 图片加载完关闭遮蔽罩
this.isLoading = false;
// 前端校验设置特殊值
this.nonceStr = 'loyer';
});
this.image = image;
},
/* 创建image对象*/
createImage(onload) {
const image = document.createElement('img');
image.crossOrigin = 'Anonymous';
image.onload = onload;
image.onerror = () => {
image.src = '/assets/platform/img/bjt.jpg';
};
image.src = this.getImageSrc();
return image;
},
/* 获取imgSrc*/
getImageSrc() {
const len = this.imagelist.length;
return len > 0 ? this.imagelist[this.getNonceByRange(0, len)] : `https://loyer.wang/view/ftp/wallpaper/${this.getNonceByRange(1, 1000)}.jpg`;
},
/* 根据指定范围获取随机数*/
getNonceByRange(start, end) {
return Math.round(Math.random() * (end - start) + start);
},
/* 绘制阻塞块*/
drawBlock() {
this.blockX = this.getNonceByRange(this.blockWidth + 10, this.canvaswidth - (this.blockWidth + 10));
this.blockY = this.getNonceByRange(10 + this.blockradius * 2, this.canvasheight - (this.blockWidth + 10));
this.draw(this.canvasCtx, 'fill');
this.draw(this.blockCtx, 'clip');
},
/* 绘制事件*/
draw(ctx, operation) {
const PI = Math.PI;
let {blockX: x, blockY: y, blocklength: l, blockradius: r} = this;
// 绘制
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI);
ctx.lineTo(x + l, y);
ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI);
ctx.lineTo(x + l, y + l);
ctx.lineTo(x, y + l);
ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true);
ctx.lineTo(x, y);
// 修饰
ctx.lineWidth = 2;
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
ctx.strokeStyle = 'rgba(255, 255, 255, 0.9)';
ctx.stroke();
ctx[operation]();
ctx.globalCompositeOperation = 'destination-over';
},
/* 事件绑定*/
bindEvents() {
// 监听鼠标按下事件
document.getElementById('slider-button').addEventListener('mousedown', (event) => {
this.startEvent(event.clientX, event.clientY);
});
// 监听鼠标移动事件
document.addEventListener('mousemove', (event) => {
this.moveEvent(event.clientX, event.clientY);
});
// 监听鼠标离开事件
document.addEventListener('mouseup', (event) => {
this.endEvent(event.clientX);
});
// 监听触摸开始事件
document.getElementById('slider-button').addEventListener('touchstart', (event) => {
this.startEvent(event.changedTouches[0].pageX, event.changedTouches[0].pageY);
});
// 监听触摸滑动事件
document.addEventListener('touchmove', (event) => {
this.moveEvent(event.changedTouches[0].pageX, event.changedTouches[0].pageY);
});
// 监听触摸离开事件
document.addEventListener('touchend', (event) => {
this.endEvent(event.changedTouches[0].pageX);
});
},
/* 校验图片是否存在*/
checkImgSrc() {
if (this.isFrontCheck) {
return true;
}
return !!this.$refs.canvas.src;
},
/* 滑动开始事件*/
startEvent(originX, originY) {
if (!this.checkImgSrc() || this.isLoading || this.verifySuccess) {
return;
}
this.originX = originX;
this.originY = originY;
this.isMouseDown = true;
this.timestamp = +new Date();
},
/* 滑动事件*/
moveEvent(originX, originY) {
if (!this.isMouseDown) {
return false;
}
const moveX = originX - this.originX;
const moveY = originY - this.originY;
if (moveX < 0 || moveX + 40 >= this.canvaswidth) {
return false;
}
this.sliderButtonLeft = moveX + 'px';
let blockLeft = (this.canvaswidth - 40 - 20) / (this.canvaswidth - 40) * moveX;
this.blockObj.style.left = blockLeft + 'px';
this.verifyActive = true;
this.sliderBoxWidth = moveX + 'px';
this.dragDistanceList.push(moveY);
},
/* 滑动结束事件*/
endEvent(originX) {
if (!this.isMouseDown) {
return false;
}
this.isMouseDown = false;
if (originX === this.originX) {
return false;
}
// 开始校验
this.isLoading = true;
// 校验结束
this.verifyActive = false;
// 滑动时长
this.timestamp = +new Date() - this.timestamp;
// 移动距离
const moveLength = parseInt(this.blockObj.style.left);
// 限制操作时长10S,超出判断失败
if (this.timestamp > 10000) {
this.verifyFailEvent();
} else
// 人为操作判定
if (!this.turingTest()) {
this.verifyFail = true;
this.$emit('again');
} else
// 是否前端校验
if (this.isFrontCheck) {
const accuracy = this.accuracy <= 1 ? 1 : this.accuracy > 10 ? 10 : this.accuracy; // 容错精度值
const spliced = Math.abs(moveLength - this.blockX) <= accuracy; // 判断是否重合
if (!spliced) {
this.verifyFailEvent();
} else {
// 设置特殊值,后台特殊处理,直接验证通过
this.$emit('success', {nonceStr: this.nonceStr, value: moveLength});
}
} else {
this.$emit('success', {nonceStr: this.nonceStr, value: moveLength});
}
},
/* 图灵测试*/
turingTest() {
const arr = this.dragDistanceList; // 拖动距离数组
const average = arr.reduce(sum) / arr.length; // 平均值
const deviations = arr.map((x) => x - average); // 偏离值
const stdDev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length); // 标准偏差
return average !== stdDev; // 判断是否人为操作
},
/* 校验成功*/
verifySuccessEvent() {
this.isLoading = false;
this.verifySuccess = true;
const elapsedTime = (this.timestamp / 1000).toFixed(1);
if (elapsedTime < 1) {
this.successHint = `仅仅${elapsedTime}S,你的速度快如闪电`;
} else if (elapsedTime < 2) {
this.successHint = `只用了${elapsedTime}S,这速度简直完美`;
} else {
this.successHint = `耗时${elapsedTime}S,争取下次再快一点`;
}
},
/* 校验失败*/
verifyFailEvent(msg) {
this.verifyFail = true;
this.$emit('fail', msg);
this.refresh();
},
/* 刷新图片验证码*/
refresh() {
// 延迟class的删除,等待动画结束
setTimeout(() => {
this.verifyFail = false;
}, 500);
this.isLoading = true;
this.verifyActive = false;
this.verifySuccess = false;
this.blockObj.style.left = 0;
this.sliderBoxWidth = 0;
this.sliderButtonLeft = 0;
if (this.isFrontCheck) {
// 刷新画布
let {canvaswidth, canvasheight} = this;
this.canvasCtx.clearRect(0, 0, canvaswidth, canvasheight);
this.blockCtx.clearRect(0, 0, canvaswidth, canvasheight);
this.blockObj.width = canvaswidth;
// 刷新图片
this.image.src = this.getImageSrc();
} else {
this.getCaptcha();
}
},
},
};
</script>
<style scoped>
.slide-verify {
position: relative;
}
/*图片加载样式*/
.img-loading {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 999;
animation: loading 1.5s infinite;
background-image: url(/assets/platform/img/captcha/loading.gif);
background-repeat: no-repeat;
background-position: center center;
background-size: 100px;
background-color: #737c8e;
border-radius: 5px;
}
@keyframes loading {
0% {
opacity: .7;
}
100% {
opacity: 9;
}
}
/*认证成功后的文字提示*/
.success-hint {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.8);
color: #2CD000;
font-size: large;
}
/*刷新按钮*/
.refresh-icon {
position: absolute;
right: 0;
top: 0;
width: 35px;
height: 35px;
cursor: pointer;
background: url("/assets/platform/img/captcha/refresh.svg") 0 -432px;
background-size: 35px 470px;
}
/*验证图片*/
.slide-canvas {
border-radius: 5px;
}
/*阻塞块*/
.slide-block {
position: absolute;
left: 0;
top: 0;
}
/*校验失败时的阻塞块样式*/
.slide-block.verify-fail {
transition: left 0.5s linear;
}
/*滑动条*/
.slider {
position: relative;
text-align: center;
width: 100%;
height: 40px;
line-height: 40px;
margin-top: 15px;
background: #f7f9fa;
color: #45494c;
border: 1px solid #e4e7eb;
border-radius: 5px;
}
/*滑动盒子*/
.slider-box {
position: absolute;
left: 0;
top: 0;
height: 40px;
border: 0 solid #1991FA;
background: #D1E9FE;
border-radius: 5px;
}
/*滑动按钮*/
.slider-button {
position: absolute;
top: 0;
left: 0;
width: 40px;
height: 40px;
background: #fff;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
cursor: pointer;
transition: background .2s linear;
border-radius: 5px;
}
/*鼠标悬浮时的按钮样式*/
.slider-button:hover {
background: #1991FA
}
/*鼠标悬浮时的按钮图标样式*/
.slider-button:hover .slider-button-icon {
/*background-position: 0 -13px*/
background-image: url("/assets/platform/img/captcha/white_right.svg");
}
/*滑动按钮图标*/
.slider-button-icon {
position: absolute;
top: 15px;
left: 13px;
width: 15px;
height: 13px;
background-image: url("/assets/platform/img/captcha/right.svg");
background-repeat: no-repeat;
background-position: center center;
}
/*校验时的按钮样式*/
.verify-active .slider-button {
height: 38px;
top: -1px;
border: 1px solid #1991FA;
}
/*校验时的滑动箱样式*/
.verify-active .slider-box {
height: 38px;
border-width: 1px;
}
/*校验成功时的滑动箱样式*/
.verify-success .slider-box {
height: 38px;
border: 1px solid #52CCBA;
background-color: #D2F4EF;
}
/*校验成功时的按钮样式*/
.verify-success .slider-button {
height: 38px;
top: -1px;
border: 1px solid #52CCBA;
background-color: #52CCBA !important;
}
/*校验成功时的按钮图标样式*/
.verify-success .slider-button-icon {
/*background-position: 0 0 !important;*/
background-image: url("/assets/platform/img/captcha/ok.svg");
}
/*校验失败时的滑动箱样式*/
.verify-fail .slider-box {
height: 38px;
border: 1px solid #f57a7a;
background-color: #fce1e1;
transition: width 0.5s linear;
}
/*校验失败时的按钮样式*/
.verify-fail .slider-button {
height: 38px;
top: -1px;
border: 1px solid #f57a7a;
background-color: #f57a7a !important;
transition: left 0.5s linear;
}
/*校验失败时的按钮图标样式*/
.verify-fail .slider-button-icon {
top: 14px;
/*background-position: 0 -82px !important;*/
background-image: url("/assets/platform/img/captcha/close.svg");
}
/*校验状态下的提示文字隐藏*/
.verify-active .slider-hint,
.verify-success .slider-hint,
.verify-fail .slider-hint {
display: none;
}
.refresh {
text-align: right;
font-size: 16px;
cursor: pointer;
}
</style>
@@ -37,11 +37,14 @@
</el-form-item>
<el-form-item prop="type" label="变更类型">
<dict-select v-model="formData.type" style="width: 100%" clearable placeholder="变更类型"
code="MemberChangeType" @change="typeChange"></dict-select>
<!-- <dict-select v-model="formData.type" style="width: 100%" clearable placeholder="变更类型"-->
<!-- code="MemberChangeType" @change="typeChange"></dict-select>-->
<el-select v-model="formData.type" style="width: 100%" clearable placeholder="变更类型" @change="typeChange">
<el-option v-for="item in userChangeTypeList" :label="item.name" :value="item.code" :key="item.id"></el-option>
</el-select>
</el-form-item>
<!--单位异动-->
<!--异动-->
<div v-if="formData.type==='1'">
<el-form-item prop="type" label="新&ensp;单&ensp;位">
<el-select v-model="formData.currentUnitId" style="width: 100%" filterable clearable
@@ -81,30 +84,102 @@
</el-form-item>
</el-col>
</el-row>
</div>
<!--离校 离退休-->
<div v-if="formData.type && !['1','7','8'].includes(formData.type)">
<div>
<el-form-item prop="updateMember" label="工会会员资格">
<el-switch
v-model="formData.updateMember"
active-text="移除"
inactive-text="添加">
</el-switch>
</el-form-item>
</div>
<el-form-item prop="updateWelfare" label="福利会员资格">
<el-switch
v-model="formData.updateWelfare"
active-text="移除"
inactive-text="添加">
</el-switch>
<div v-else-if="welfare_member&&['2'].includes(formData.type)">
<el-form-item prop="updateWelfareMember" label="福利会员">
<el-radio-group v-model="formData.updateWelfareMember" size="small">
<el-radio :label="true" border>享受福利</el-radio>
<el-radio :label="false" border>不享受福利</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="insertMember" label="工会会员">
<el-radio-group v-model="formData.insertMember" size="small">
<el-radio :label="true" border>成为会员</el-radio>
<el-radio :label="false" border>不成为会员</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div v-else-if="welfare_member&&['7'].includes(formData.type)">
<el-form-item prop="updateWelfareMember" label="福利会员">
<el-radio-group v-model="formData.updateWelfareMember" size="small">
<el-radio :label="true" border>享受福利</el-radio>
<el-radio :label="false" border>不享受福利</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div v-else-if="welfare_member&&['3','4','5','6','8'].includes(formData.type)">
<el-form-item prop="updateWelfare" label="福利会员">
<el-radio-group v-model="formData.updateWelfare" size="small">
<el-radio :label="true" border>取消享受福利</el-radio>
<el-radio :label="false" border>保留享受福利</el-radio>
</el-radio-group>
<!-- <span style="color: red">&emsp;&emsp;&emsp;温馨提醒:此操作将取消该教工正式会员资格</span>-->
</el-form-item>
<el-form-item prop="updateMember" label="工会会员">
<el-radio-group v-model="formData.updateMember" size="small">
<el-radio :label="true" border>取消会员资格</el-radio>
<el-radio :label="false" border>保留会员资格</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="updateUserState" label="是否改变在职状态" style="width: 100%"
v-if="welfare_member&&['3','4','5','6','8'].includes(formData.type)">
<dict-select v-model="formData.userState" style="width: 100%" clearable placeholder="变更类型"
code="userState"></dict-select>
</el-form-item>
<el-form-item prop="updateUserState" label="是否改变人员类型" style="width: 100%"
v-if="welfare_member&&['3','4','5','6','8'].includes(formData.type)">
<dict-select v-model="formData.personType" style="width: 100%" clearable
placeholder="人员类型"
code="UserType"></dict-select>
</el-form-item>
</div>
<div v-else-if="formData.type==='10'">
<el-form-item prop="oldIdCard" label="原身份证号" style="width: 100%">
<el-input v-model="formData.oldIdCard" readonly type="text"></el-input>
</el-form-item>
<el-form-item prop="idCard" label="新的身份证号" style="width: 100%">
<el-input v-model="formData.idCard" placeholder="请输入新的身份证号" type="text"></el-input>
</el-form-item>
</div>
<div v-else-if="formData.type==='11'">
<el-form-item prop="oldMobile" label="原手机号码" style="width: 100%">
<el-input v-model="formData.oldMobile" readonly type="text"></el-input>
</el-form-item>
<el-form-item prop="mobile" label="新的手机号码" style="width: 100%">
<el-input v-model="formData.mobile" placeholder="请输入新的手机号码" type="text"></el-input>
</el-form-item>
</div>
<div v-else-if="formData.type==='12'">
<el-form-item prop="oldEducation" label="原学历" style="width: 100%">
<el-input v-model="formData.oldEducation" readonly type="text"></el-input>
</el-form-item>
<el-form-item prop="education" label="新的学历" style="width: 100%">
<dict-select v-model="formData.education" style="width: 100%" clearable placeholder="请选择新的学历"
code="Education"></dict-select>
</el-form-item>
</div>
<!-- <div v-else-if="welfare_member&&['2','7'].includes(formData.type)">
<el-form-item prop="updateWelfareMember" label="是否享受福利">
<el-switch
v-model="formData.updateWelfareMember"
active-color="#13ce66"
inactive-color="#ff4949">
</el-switch>
<span style="color: red">&emsp;&emsp;&emsp;温馨提醒:此操作将该教工设为正式会员</span>
</el-form-item>
</div>-->
<el-form-item prop="remark" label="变化原因">
<el-input v-model="formData.remark" placeholder="变化原因" type="textarea" :rows="4"></el-input>
</el-form-item>
@@ -122,10 +197,11 @@
<script>
module.exports = {
components: {
'dict-select': httpVueLoader('/components/plugins/DictSelect.vue?v=1.0.0'),
},
props: {
userid: {type: String},
welfare_member: {type: Boolean, default: false},
welfare_member: {type: Boolean, default: true},
},
data() {
return {
@@ -136,18 +212,22 @@ module.exports = {
formData: {},
formRules: {
type: [{required: true, message: '必选', trigger: ['blur', 'change']}],
updateWelfareMember: [{required: true, message: '必选', trigger: ['blur', 'change']}],
updateMember: [{required: true, message: '必选', trigger: ['blur', 'change']}],
updateWelfare: [{required: true, message: '必选', trigger: ['blur', 'change']}],
currentUnitId: [{required: true, message: '必选', trigger: ['blur', 'change']}],
currentThreeUnitId: [{required: true, message: '请选择新三级单位', trigger: 'change'}]
currentThreeUnitId: [{required: true, message: '请选择新三级单位', trigger: 'change'}],
idCard: [{required: true, message: '必填', trigger: ['blur', 'change']}],
mobile: [{required: true, message: '必填', trigger: ['blur', 'change']}],
education: [{required: true, message: '必填', trigger: ['blur', 'change']}],
insertMember: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
unitOptions: [],
threeUnits: [],
isThreeUnit: false,
memberChangeTypeOptions: []
userChangeTypeList:[],
}
},
watch: {
@@ -157,16 +237,14 @@ module.exports = {
},
methods: {
typeChange() {
console.log(this.formData.type)
this.$set(this.formData, "updateWelfare", ['3', '5'].includes(this.formData.type))
this.$set(this.formData, "updateMember", ['3', '5'].includes(this.formData.type))
this.$set(this.formData, "updateWelfareMember", ['2','7'].includes(this.formData.type))
this.$set(this.formData, "updateWelfare", ['2', '3', '4', '5', '6', '8'].includes(this.formData.type))
this.$set(this.formData, "updateMember", ['2', '3', '4', '5', '6', '8'].includes(this.formData.type))
this.$set(this.formData, "insertMember", ['2'].includes(this.formData.type))
},
async doSubmit() {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.formData.type != 1) {
this.formData.userState = this.memberChangeTypeOptions.find(v => v.code === this.formData.type)?.name
}
this.submitLoading = true
this.$emit("submit", this.formData)
}
@@ -239,9 +317,13 @@ module.exports = {
originUnitId: resp.data.unitid,
originThreeUnitId: resp.data.threeUnitId,
originUnionId: resp.data.unionid,
// userState: resp.data.userState,
userState: resp.data.userState,
personType: resp.data.personType,
auditTime: moment().format('YYYY-MM-DD'),
notes: null
notes: null,
oldIdCard:resp.data.idcard,
oldMobile:resp.data.mobile,
oldEducation:resp.data.education
}
this.disabled = false
} else {
@@ -258,17 +340,19 @@ module.exports = {
if (resp.code === 0) {
this.unitOptions = resp.data
}
}
},
async getUserChangeType(){
const resp = await $.get('/platform/member/common/getUserChangType')
if (resp.code === 0){
this.userChangeTypeList = resp.data
}
},
},
async created() {
this.isThreeUnit = await getConfigKey('isThreeUnit') === 'true'
this.getUnits()
this.flush()
getDictOptions('MemberChangeType').then(res => {
this.memberChangeTypeOptions = res
})
await this.getUnits()
await this.flush()
await this.getUserChangeType()
// getUnits(null).then(res => this.unitOptions = res)
}
}
@@ -34,7 +34,7 @@
<script>
module.exports = {
components: {
'user-change-history': httpVueLoader('/components/userChangeHistory/userChangeHistory.vue?v=' + new Date().getTime()),
'user-change-history': httpVueLoader('/components/userChangeHistory/UserChangeHistory.vue?v=' + new Date().getTime()),
},
props: {
records: {type: Array, default: []},
@@ -84,16 +84,30 @@
<el-input v-model="formData.birthPlace" placeholder="出生地点"></el-input>
</el-form-item>
<el-form-item label="婚&emsp;&emsp;否">
<el-radio-group v-model="formData.marriage" size="small">
<el-form-item label="婚姻状况">
<dict-select v-model="formData.marriage" style="width: 100%" placeholder="请选择婚姻状况"
code="maritalStatus"></dict-select>
<!-- <el-radio-group v-model="formData.marriage" size="small">
<el-radio label="已婚" border></el-radio>
<el-radio label="未婚" border></el-radio>
</el-radio-group>
</el-radio-group>-->
</el-form-item>
</div>
<div class="is-flex">
<el-form-item prop="schoolTime" label="入校时间">
<el-date-picker style="width: 100%" v-model="formData.schoolTime" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" type="date"
placeholder="入校时间"></el-date-picker>
</el-form-item>
<el-form-item prop="startSalaryDate" label="起薪日期">
<el-date-picker style="width: 100%" v-model="formData.startSalaryDate" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" type="date"
placeholder="起薪日期"></el-date-picker>
</el-form-item>
</div>
<div class="is-flex">
<el-form-item prop="education" label="学&emsp;&emsp;历">
<dict-select v-model="formData.education" style="width: 100%" placeholder="请选择学历"
code="Education"></dict-select>
@@ -125,8 +139,10 @@
</el-select>
</el-form-item>
<el-form-item prop="political" label="政治面貌">
<el-input maxlength="100" placeholder="政治面貌"
v-model="formData.political"></el-input>
<dict-select v-model="formData.political" style="width: 100%" placeholder="请选择政治面貌"
code="JobTitle"></dict-select>
<!-- <el-input maxlength="100" placeholder="政治面貌"
v-model="formData.political"></el-input>-->
</el-form-item>
</div>
@@ -211,6 +227,17 @@
</el-form-item>
</div>
<div class="is-flex">
<el-form-item prop="renewTime" label="更新时间">
<el-date-picker style="width: 100%" v-model="formData.renewTime" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" type="date"
placeholder="更新时间"></el-date-picker>
</el-form-item>
<el-form-item prop="email" label="邮箱号">
<el-input v-model="formData.email" placeholder="邮箱号" maxlength="50"></el-input>
</el-form-item>
</div>
<div class="is-flex">
<el-form-item prop="householdType" label="户籍类型">
<dict-select
@@ -272,9 +299,9 @@
<!-- </el-form>-->
</el-tab-pane>
<el-tab-pane label="工作信息" :name="2">
<!-- <el-tab-pane label="工作信息" :name="2">
<!-- <el-form :model="formData" ref="form" :rules="formRules" label-width="140px" v-loading="loading">-->
&lt;!&ndash; <el-form :model="formData" ref="form" :rules="formRules" label-width="140px" v-loading="loading">&ndash;&gt;
<vi-title title="工作信息"></vi-title>
@@ -339,7 +366,7 @@
</el-tab-pane>
<el-tab-pane label="会员信息" :name="3">
<!-- <el-form :model="formData" ref="form" :rules="formRules" label-width="160px" v-loading="loading">-->
&lt;!&ndash; <el-form :model="formData" ref="form" :rules="formRules" label-width="160px" v-loading="loading">&ndash;&gt;
<vi-title title="会员信息"></vi-title>
<div class="is-flex">
@@ -428,8 +455,8 @@
</el-date-picker>
</el-form-item>
</div>
<!-- </el-form>-->
</el-tab-pane>
&lt;!&ndash; </el-form>&ndash;&gt;
</el-tab-pane>-->
<el-tab-pane label="家庭及社会信息" :name="4">
<!-- <el-form :model="formData" ref="form" :rules="formRules" label-width="120px" v-loading="loading">-->
@@ -521,12 +548,25 @@
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
<el-table-column prop="isCondolence" label="是否慰问" align="center" header-align="center">
<template slot-scope="scope">
<el-input placeholder="请输入单位" maxlength="100" v-model="scope.row.unit"
clearable></el-input>
<el-radio-group v-model="scope.row.isCondolence" size="mini">
<el-radio label="是">是</el-radio>
<el-radio label="否">否</el-radio>
</el-radio-group>
<!-- <el-input placeholder="请输入单位" maxlength="100" v-model="scope.row.unit"
clearable></el-input>-->
</template>
</el-table-column>
<el-table-column prop="condolenceTime" label="慰问时间" align="center" header-align="center">
<template slot-scope="scope">
<el-date-picker style="width: 100%" v-model="scope.row.condolenceTime" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" type="date"
placeholder="慰问时间"></el-date-picker>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
<template slot-scope="scope">
<el-input placeholder="请输入备注" maxlength="100" v-model="scope.row.remark"
@@ -555,192 +595,58 @@
</div>
<div v-else>
<el-form label-width="100px" v-loading="loading" label-position="left" label-suffix=":">
<el-row gutter="20">
<el-col :span="18">
<el-row gutter="20">
<el-col :span="8">
<el-form-item label="姓&emsp;&emsp;名">
{{ formData.username }}
</el-form-item>
</el-col>
<h3 style="text-align: center; letter-spacing: 6px;">工会会员登记表</h3>
<div style="text-align: right; letter-spacing: 2px;">填表日期:{{ moment(formData.applyTime).format('YYYY年MM月DD日') }}</div>
<el-col :span="8">
<el-form-item label="工&emsp;&emsp;号">
{{ formData.loginname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="性&emsp;&emsp;别">
{{ formData.sex }}
</el-form-item>
</el-col>
</el-row>
<el-row gutter="20">
<el-col :span="8">
<el-form-item label="所在科室">
{{ formData.threeUnitName }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="所在单位">
{{ formData.unitname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="所在工会">
{{ formData.unionname }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="政治面貌">
{{ formData.political }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入校时间">
{{ formData.schoolTime }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出生日期">
{{ formData.birthday }}
</el-form-item>
</el-col>
</el-row>
<el-row gutter="20">
<el-col :span="8">
<el-form-item label="籍&emsp;&emsp;贯">
{{ formData.hometown }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="民&emsp;&emsp;族">
{{ formData.nation }}
</el-form-item>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<el-image :src="APP_DOMAIN+FILE_STREAM_PREVIEW_ADDRESS + '?id=' +formData.avatar"
style="width: 180px;height: 180px;display: flex;justify-content: center;align-items: center;background-color: #f5f7fa">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline" style="font-size: 24px"></i>
</div>
</el-image>
</el-col>
</el-row>
<el-row gutter="20">
<el-col :span="6">
<el-form-item label="兴趣爱好">
{{ formData.hobby }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="婚&emsp;&emsp;否">
{{ formData.marriage }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="学&emsp;&emsp;历">
{{ formData.education }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="工&emsp;&emsp;资">
{{ formData.wage }}
</el-form-item>
</el-col>
</el-row>
<el-row gutter="20">
<el-col :span="6">
<el-form-item label="人事编制">
{{ formData.preparedBy }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="职&emsp;&emsp;务">
{{ formData.position }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="职&emsp;&emsp;称">
{{ formData.jobTitle }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="在职状态">
{{ formData.userState }}
</el-form-item>
</el-col>
</el-row>
<el-row gutter="20">
<el-col :span="6">
<el-form-item label="人员类型">
{{ formData.personType }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="手&ensp;机&ensp;号">
{{ formData.mobile }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="银行账号">
{{ formData.bank_number }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="身份证号">
{{ formData.idcard }}
</el-form-item>
</el-col>
</el-row>
<el-form-item label="个人简历">
<div v-html="formData.vita"></div>
</el-form-item>
<el-form-item label="家庭成员">
<el-table
v-if="formData.family&&formData.family.length"
:data="formData.family"
size="mini" border :header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="姓名">{{ formData.username}}</el-descriptions-item>
<el-descriptions-item label="性别">{{ formData.sex}}</el-descriptions-item>
<el-descriptions-item label="民族">{{ formData.nation}}</el-descriptions-item>
<el-descriptions-item label="学历">{{ formData.education}}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ formData.political}}</el-descriptions-item>
<el-descriptions-item label="婚姻状况">{{ formData.marriage}}</el-descriptions-item>
<el-descriptions-item label="身份证号码" span="2">{{ formData.idcard}}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ formData.mobile}}</el-descriptions-item>
<el-descriptions-item label="户口所在地" span="3">
<template slot="label">户口所在地</template>
<div class="text-left" v-html="formData.registeredResidence"></div>
</el-descriptions-item>
<el-descriptions-item label="现居住地" span="3">
<template slot="label">现居住地</template>
<div class="text-left" v-html="formData.homeAddress"></div>
</el-descriptions-item>
<el-descriptions-item label="工作部门(学院)及岗位" span="3">
<template slot="label">工作部门(学院)及岗位</template>
<div class="text-left">{{ formData.unitname + '' + (formData.jobTitle ? '、' + formData.jobTitle : "") }}</div>
</el-descriptions-item>
<el-descriptions-item label="简历" span="3">
<template slot="label">简历</template>
<div class="text-left" v-html="formData.vita"></div>
</el-descriptions-item>
<el-descriptions-item label="有何特长" span="3">
<template slot="label">有何特长</template>
<div class="text-left" v-html="formData.specialSkill"></div>
</el-descriptions-item>
</el-descriptions>
<vi-title title="家庭成员" class="mt20"></vi-title>
<el-table
v-if="formData.family&&formData.family.length"
:data="formData.family"
size="mini" border :header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center" header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="isCondolence" label="是否慰问" align="center" header-align="center">
</el-table-column>
<el-table-column prop="condolenceTime" label="慰问时间" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else description="暂无家庭成员信息"></el-empty>
</div>
</div>
</template>
@@ -1001,4 +907,9 @@ module.exports = {
.el-picker-panel {
z-index: 9999999 !important;
}
.el-descriptions-item__cell {
width: 200px;
text-align: center !important;
}
</style>
@@ -13,15 +13,16 @@
<van-field label="性别" :value="viewData.sex" left-icon="ellipsis"></van-field>
<van-field label="民族" left-icon="bar-chart-o" :value="viewData.nation"></van-field>
<van-field label="学历" left-icon="coupon-o" :value="viewData.education"></van-field>
<van-field label="学位" left-icon="comment-o" :value="viewData.academicDegree"></van-field>
<!-- <van-field label="学位" left-icon="comment-o" :value="viewData.academicDegree"></van-field>-->
<van-field label="政治面貌" left-icon="label-o" :value="viewData.political"></van-field>
<van-field :value="viewData.personType" label="人员类型" left-icon="label-o"></van-field>
<van-field label="身份证" left-icon="idcard" :value="viewData.idcard"></van-field>
<van-field label="婚否" left-icon="label-o" :value="viewData.marriage"></van-field>
<!-- <van-field :value="viewData.personType" label="人员类型" left-icon="label-o"></van-field>-->
<van-field label="身份证号码" left-icon="idcard" :value="viewData.idcard"></van-field>
<van-field label="联系电话" left-icon="phone-o" :value="viewData.mobile"></van-field>
<van-field label="户口所在地" left-icon="wap-home-o" :value="viewData.registeredResidence"></van-field>
<van-field label="现居住地" left-icon="home-o" :value="viewData.homeAddress"></van-field>
<van-field label="工作单位" left-icon="cluster-o" :value="viewData.unitname"></van-field>
<van-field label="职务" left-icon="debit-pay" :value="viewData.position"></van-field>
<van-field label="工作部门(学院)及岗位" left-icon="cluster-o" :value="viewData.unitname + '、' + viewData.jobTitle"></van-field>
<!-- <van-field label="职务" left-icon="debit-pay" :value="viewData.position"></van-field>-->
</van-cell-group>
</van-form>
<van-cell-group class="mt10 up_down">
@@ -31,7 +32,7 @@
<i class="van-icon van-icon-notes-o"></i>
</div>
<div class="van-cell__title van-field__label">
<span>个人工作简历</span>
<span>简历</span>
</div>
</div>
@@ -39,11 +40,10 @@
<van-field readonly>
<template #input>
<div v-html="viewData.position"></div>
<div v-html="viewData.vita"></div>
</template>
</van-field>
</div>
</van-cell-group>
<van-cell-group class="mt10 up_down">
@@ -53,7 +53,7 @@
<i class="van-icon van-icon-award-o"></i>
</div>
<div class="van-cell__title van-field__label">
<span>特长</span>
<span>有何特长</span>
</div>
</div>
<van-divider></van-divider>
@@ -74,7 +74,7 @@
<i class="van-icon van-icon-friends-o"></i>
</div>
<div class="van-cell__title van-field__label" style="width: auto">
<span>家庭主要成员及联系方式</span>
<span>家庭成员</span>
</div>
</div>
</div>
@@ -87,14 +87,16 @@
<span>成员{{ toChinesNum(i + 1) }}</span>
</div>
<van-form readonly input-align="right">
<van-field label="关系" :value="o.relation" left-icon="exchange"></van-field>
<van-field label="与本人关系" :value="o.relation" left-icon="exchange"></van-field>
<van-field label="姓名" :value="o.name" left-icon="user-o"></van-field>
<van-field label="联系方式" :value="o.mobile" left-icon="phone-o"></van-field>
<van-field label="是否慰问" :value="o.isCondolence" left-icon="shield-o"></van-field>
<van-field label="慰问时间" :value="o.condolenceTime" left-icon="guide-o"></van-field>
<van-field label="备注" :value="o.remark" left-icon="coupon-o"></van-field>
</van-form>
</div>
</div>
<div v-else style="height: 100px">
暂无家庭成员信息
</div>
</div>
@@ -102,9 +104,9 @@
<template v-if="unionAudit!=null">
<div class="van-cell-group__title mt20">
<div class="van-cell-group__title mt5">
<div class="van-sidebar-item van-sidebar-item--select">
院级工会审核信息
部门工会审核信息
</div>
</div>
<van-cell-group>
@@ -112,11 +114,17 @@
<van-field label="审核时间" :value="moment(unionAudit.auditTime).format('YYYY-MM-DD')" left-icon="clock-o"
readonly></van-field>
<van-field label="审核意见" left-icon="chat-o" :value="unionAudit.auditOpinion" readonly></van-field>
<van-field name="auditSign" left-icon="friends-o" label="签&emsp;&emsp;字">
<template #input>
<van-image width="200" height="100" :src="unionAudit.auditSign" v-if="unionAudit.auditSign"/>
<span v-else>暂无</span>
</template>
</van-field>
</van-cell-group>
</template>
<template v-if="schoolAudit!=null">
<div class="van-cell-group__title mt20">
<div class="van-cell-group__title mt5">
<div class="van-sidebar-item van-sidebar-item--select">
校工会审核信息
</div>
@@ -126,6 +134,12 @@
<van-field label="审核时间" :value="moment(schoolAudit.auditTime).format('YYYY-MM-DD')" left-icon="clock-o"
readonly></van-field>
<van-field label="审核意见" left-icon="chat-o" :value="schoolAudit.auditOpinion" readonly></van-field>
<van-field name="auditSign" left-icon="friends-o" label="签&emsp;&emsp;字">
<template #input>
<van-image width="200" height="100" :src="schoolAudit.auditSign" v-if="schoolAudit.auditSign"/>
<span v-else>暂无</span>
</template>
</van-field>
</van-cell-group>
</template>
@@ -205,4 +219,4 @@ module.exports = {
.van-sidebar-item--select::before {
left: 5px !important;
}
</style>
</style>
@@ -0,0 +1,220 @@
<template>
<div style="padding: 20px 50px">
<el-timeline>
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" style="width: 200px"
@click="location.href=temp_url"
icon="el-icon-download">下载模板
</el-button>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="上传文件" placement="top">
<el-card>
<el-form>
<el-form-item label="请选择更新模式" v-if="is_show_radio">
<el-radio-group v-model="importData.isFlag">
<el-radio-button label="true">清空更新</el-radio-button>
<el-radio-button label="false">追加</el-radio-button>
</el-radio-group>
</el-form-item>
<el-upload
name="file"
ref="upload"
:on-remove="(file, fileList) => {
importData.fileList = fileHandleRemove(file, fileList);
importResult={
errorCount:0,
successCount:0,
totalCount:0,
errorList:[]
}
}"
:on-change="(file, fileList) => {
importData.fileList = fileHandleChange(file, fileList,{type:['xls','xlsx']})
}"
:auto-upload="false"
:limit="1"
:file-list="importData.fileList">
<el-button size="medium" type="" icon="el-icon-upload"
style="width: 200px">选择文件
</el-button>
<div class="el-upload__tip" slot="tip" style="color: #F56C6C">
只能上传 xls/xlsx 文件
</div>
</el-upload>
</el-form>
</el-card>
</el-timeline-item>
<el-timeline-item placement="top" timestamp="导入结果">
<el-card shadow="never">
<p>总记录数:{{ errorInfoData.totalCount }}</p>
<p>成功数:<span class="text-success">{{ errorInfoData.successCount }}</span></p>
<p>错误数:<span class="text-danger">{{ errorInfoData.errorCount }}</span></p>
<el-link @click="exportErrors" type="primary" v-if="errorInfoData.errorCount>0">下载错误记录
</el-link>
</el-card>
</el-timeline-item>
</el-timeline>
<div style="text-align: right">
<span slot="footer" class="dialog-footer">
<!-- <el-button @click="importVisible = false" :disabled="importLoading">取 消</el-button>-->
<el-button type="primary" @click="doImport" :loading="importLoading">确 定</el-button>
</span>
</div>
</div>
</template>
<script>
module.exports = {
props: {
temp_url: {type: String},
post_url: {type: String},
project_id: {type: String, default: ''},
is_show_radio: {type: Boolean, default: false}
},
mounted() {
const s = document.createElement('script');
s.type = 'text/javascript';
s.src = '/assets/platform/js/xlsx.full.min.js';
document.body.appendChild(s);
},
data() {
return {
// importVisible: false,
importLoading: false,
importData: {
fileList: [],
isFlag: false
},
errorInfoData: {
totalCount: 0,
successCount: 0,
errorCount: 0,
errorList: 0,
},
}
},
methods: {
resetImportData() {
this.importData = {
fileList: [],
isFlag: false
}
this.errorInfoData = {
totalCount: 0,
successCount: 0,
errorCount: 0,
errorList: 0,
}
this.importLoading = false
},
doImport() {
if (this.importData.fileList.length === 0) {
this.$notify.error({
title: '错误',
message: '请选择文件!'
});
// this.notifyWarning("请选择文件!")
return
}
const data = new FormData();
data.append("isFlag", this.importData.isFlag)
data.append("projectId", this.project_id)
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name);
});
this.importLoading = true
$.ajax({
url: this.post_url,
type: "post",
data: data,
processData: false,
contentType: false,
success: (data) => {
this.importLoading = false
if (data.code === 0 && data.data === null) {
this.$notify.success("导入成功")
this.importVisible = false
this.$emit("flush")
} else {
this.$notify.warning("导入失败")
this.errorInfoData = data.data
}
},
error: (data) => {
this.$notify.warning("导入失败")
this.importLoading = false
}
});
this.importLoading = false
},
exportErrors() {
const data = this.errorInfoData.errorList
// 创建工作簿
const workbook = XLSX.utils.book_new();
// 创建工作表
const worksheet = XLSX.utils.json_to_sheet(data);
// 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 将工作簿转换为二进制对象
const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});
// 将二进制对象转换为Blob对象
const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
// 创建下载链接并设置相关属性
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = '错误记录.xlsx';
// 模拟点击下载链接
document.body.appendChild(link);
link.click();
// 清理下载链接
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
},
fileHandleRemove(file, fileList) {
return fileList;
},
fileHandleChange(file, fileList, {type, size}) {
const removeFile = () => {
fileList.splice(fileList.findIndex(v => v === file))
}
if (!file.size) {
this.$notify.warning('您选择的是空文件!')
removeFile()
}
if (type && type.length && !type.includes(file.name.split('.').pop().toLowerCase())) {
this.$notify.warning(`文件只能是 ${type.map(v => v.toUpperCase()).join('/')} 格式!`)
removeFile()
}
if (size && !file.size < size) {
this.$notify.warning(`文件大小不能超过 ${size / 1024 / 1024}MB!`)
removeFile()
}
return fileList;
},
}
}
</script>
<style>
.el-card__body {
padding: 25px;
}
</style>
@@ -0,0 +1,327 @@
<template>
<el-card style="margin: 20px" shadow="never" v-loading="loading">
<template #header v-if="!formData.zcid">
<h3 style="color: #1867b0">资产登记</h3>
</template>
<el-form :model="formData" :rules="ruleForm" label-width="120px" ref="AddForm"
class="formClass">
<el-descriptions :column="3" border class="table_fixed">
<el-descriptions-item label="资产名称">
<div slot="label" class="required-form-item">资产名称</div>
<el-form-item prop="zcmc" label-width="0">
<el-input placeholder="资产名称" v-model="formData.zcmc"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="单价">
<div slot="label" class="required-form-item">单价</div>
<el-form-item prop="zcdj" label-width="0">
<el-input-number :precision="2" placeholder="单价" style="width: 100%"
v-model="formData.zcdj">
</el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="数量">
<div slot="label" class="required-form-item">数量</div>
<el-form-item prop="sl" label-width="0">
<el-input-number :precision="2" placeholder="数量" style="width: 100%"
v-model="formData.sl">
</el-input-number>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产类型">
<div slot="label" class="required-form-item">资产类型</div>
<el-form-item prop="zcghlx" label-width="0">
<el-radio-group @change="zcghlxChange" v-model="formData.zcghlx">
<el-radio label="1">院级工会</el-radio>
<el-radio label="2">校工会</el-radio>
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产规格型号">
<el-form-item prop="zcxh" label-width="0">
<el-input placeholder="资产规格型号" v-model="formData.zcxh"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产所属类别">
<div slot="label" class="required-form-item">资产所属类别</div>
<el-form-item prop="contentCode" label-width="0">
<el-select @change="contentCodeChange" clearable placeholder="所属类别"
style="width: 100%" v-model="formData.contentCode">
<el-option :label="item.content+'('+item.contentCode+')'"
:value="item.contentCode"
v-for="item in lbList"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="厂家">
<el-form-item prop="zccj" label-width="0">
<el-input placeholder="厂家" v-model="formData.zccj"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="存放地点">
<el-form-item prop="zccfdmc" label-width="0">
<el-input placeholder="存放地点" v-model="formData.zccfdmc"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="购置日期">
<div slot="label" class="required-form-item">购置日期</div>
<el-form-item prop="zcgzrq" label-width="0">
<el-date-picker @change="zcrksjChange" placeholder="购置日期"
style="width: 100%" v-model="formData.zcgzrq"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="折旧到期时间">
<el-form-item prop="depreciationDate" label-width="0">
<el-date-picker disabled placeholder="折旧到期时间"
style="width: 100%"
v-model="formData.depreciationDate"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="资产编号">
<el-form-item prop="zcbh" label-width="0">
<el-input placeholder="不填为系统自动生成或自己编写"
v-model="formData.zcbh"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="分类号">
<el-form-item prop="zcgbflh" label-width="0">
<el-input placeholder="分类号" v-model="formData.zcgbflh"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="领用人">
<el-form-item prop="zclyrid" label-width="0">
<el-select :loading="loading"
:remote-method="searchLyr"
@change="zclyrChange"
clearable
filterable
placeholder="可输入姓名或者工资号查询"
remote
style="width: 100%"
v-model="formData.zclyrid">
<el-option :label="item.username+'-'+item.loginname"
:value="item.id"
v-for="item in LyrOption"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="领用工会">
<template v-if="formData.zcghlx==='2'">
<el-form-item prop="zclydwh" label-width="0">
<el-input :value="formData.zclydwh" disabled
></el-input>
</el-form-item>
</template>
<template v-else>
<el-form-item prop="zclydwhid" label-width="0">
<el-select @change="zclydwhidChange" clearable
filterable="true" placeholder="所属工会"
style="width: 100%"
v-model="formData.zclydwhid">
<el-option :label="item.unionname" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</el-form-item>
</template>
</el-descriptions-item>
<el-descriptions-item label="资产状态">
<el-form-item prop="zczt" label-width="0">
<dict-select v-model="formData.zczt" style="width: 100%" placeholder="请选择资产状态"
code="zczt"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="经费科目" span="1">
<el-form-item prop="fundingSubject" label-width="0">
<el-select clearable placeholder="请选择经费科目"
style="width: 100%"
v-model="formData.fundingSubject">
<el-option label="行政" value="行政"></el-option>
<el-option label="自筹" value="自筹"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<div style="float: right;margin: 20px 0" v-if="!formData.zcid">
<el-button @click="doSubmit" type="primary">确 定
</el-button>
</div>
</el-card>
</template>
<script>
module.exports = {
data() {
return {
loading: false,
lbList: [],
formData: {},
LyrOption: [],
ruleForm: {
zcmc: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcgg: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcdj: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcgzrq: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zclyrname: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcrksj: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcjfkh: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcjfkje: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcfph: [{required: true, message: '必填', trigger: ['blur', 'change']}],
sl: [{required: true, message: '必填', trigger: ['blur', 'change']}],
contentCode: [{required: true, message: '必填', trigger: ['blur', 'change']}],
zcghlx: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
unions: [],
}
},
components: {
'dict-select': httpVueLoader('/components/plugins/DictSelect.vue?v=1.0.0'),
},
methods: {
zclydwhidChange(val) {
const union = this.unions.find(v => v.id === val)
if (union) {
this.$set(this.formData, "zclydwh", union.unionname)
} else {
this.$set(this.formData, "zclydwh", null)
}
},
zcghlxChange(val) {
if (val === "2") {
this.$set(this.formData, "zclydwh", "工会")
} else {
this.$set(this.formData, "zclydwh", null)
this.$set(this.formData, "zclydwhid", null)
}
},
contentCodeChange() {
if (this.formData.zcgzrq) {
this.zcrksjChange(this.formData.zcgzrq)
} else {
this.$set(this.formData, "zcgzrq", null);
}
},
zcrksjChange(val) {
if (!this.formData.contentCode) {
this.$message.warning('请选择资产所属类别');
this.formData.zcgzrq = null
return
}
const lbList = clone(this.lbList)
const data = lbList.find(v => v.contentCode === this.formData.contentCode)
const depreciationDate = moment(val).add(data.depreciationYear, 'y').format('YYYY-MM-DD')
this.$set(this.formData, "depreciationDate", depreciationDate)
},
zclyrChange(val) {
const {
loginname,
unionname,
username,
unionid
} = this.LyrOption.find(v => v.id === val)
this.formData.zclyrgh = loginname
this.formData.zclydwhid = unionid
this.formData.zclyrname = username
if (this.formData.zcghlx === '2') {
this.formData.zclydwh = "工会"
} else {
this.formData.zclydwh = unionname
}
},
async searchLyr(query) {
if (query != '') {
this.loading = true;
this.LyrOption = await searchUser(query)
this.loading = false;
}
},
doSubmit() {
this.$refs["AddForm"].validate((valid) => {
if (valid) {
let url = this.formData.zcid ? "/platform/zcgl/zcdj/doEdit" : "/platform/zcgl/zcdj/doSubmit"
$.post(url, this.formData).then(resp => {
if (resp.code === 0) {
this.$refs.AddForm.resetFields()
this.$message.success(resp.msg);
} else {
this.$message.warning(resp.msg);
}
})
}
})
},
async findOne(id) {
this.loading = true;
const resp = await $.post("/platform/zcgl/zcdj/findOne", {id})
if (resp.code === 0) {
await this.searchLyr(resp.data.zclyrgh);
this.formData = resp.data;
}
this.loading = false
},
async findLb() {
const data = await $.post("/platform/zcgl/zclb/queryLb")
this.lbList = data.data
}
},
async created() {
await this.findLb();
this.unions = await getUnions(null)
},
}
</script>
<style>
.formClass .el-form-item {
margin-bottom: 0px !important;
}
.required-form-item::before {
content: '*';
color: #f56c6c;
margin-right: 3px;
}
</style>
@@ -0,0 +1,222 @@
<template>
<div>
<el-tabs tab-position="top" v-model="activeName" v-loading="loading">
<el-tab-pane label="基本信息" name="1" class="tabPane">
<el-descriptions :column="2" border class="table_fixed">
<el-descriptions-item label="资产编号">
{{ viewData.zcbh }}
</el-descriptions-item>
<el-descriptions-item label="名称">
{{ viewData.zcmc }}
</el-descriptions-item>
<el-descriptions-item label="单价">
{{ viewData.zcdj }}元
</el-descriptions-item>
<el-descriptions-item label="数量">
{{ viewData.sl }}
</el-descriptions-item>
<el-descriptions-item label="规格型号">
{{ viewData.zcxh }}
</el-descriptions-item>
<el-descriptions-item label="资产所属类别">
<template v-if="viewData.contentCode">
{{ viewData.content }}({{ viewData.contentCode }})
</template>
</el-descriptions-item>
<el-descriptions-item label="厂家">
{{ viewData.zccj }}
</el-descriptions-item>
<el-descriptions-item label="存放地名称">
{{ viewData.zccfdmc }}
</el-descriptions-item>
<el-descriptions-item label="购置日期">
{{ viewData.zcgzrq }}
</el-descriptions-item>
<el-descriptions-item label="折旧到期时间">
{{ viewData.depreciationDate }}
</el-descriptions-item>
<el-descriptions-item label="分类号">
{{ viewData.zcgbflh }}
</el-descriptions-item>
<el-descriptions-item label="领用人">
{{ viewData.zclyrname }}
</el-descriptions-item>
<el-descriptions-item label="领用工会">
{{ viewData.zclydwh }}
</el-descriptions-item>
<el-descriptions-item label="资产状态">
{{ viewData.zczt }}
</el-descriptions-item>
<el-descriptions-item label="经费科目">
{{ viewData.fundingSubject }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="盘点信息" name="2">
<el-table :data="viewData.bdData"
class="tabInfo"
header-align="center"
size="small"
style="width: 100%"
>
<el-table-column
align="center"
header-align="center"
label="院级工会"
prop="zcnowlydwh"
show-overflow-tooltip>
</el-table-column>
<!-- <el-table-column
align="center"
header-align="center"
label="账面价值"
prop="zmjz" show-overflow-tooltip>
</el-table-column>-->
<el-table-column
align="center"
header-align="center"
label="购置日期" prop="zcgzrq"
show-overflow-tooltip>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="责任人" prop="shrname"
show-overflow-tooltip>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="联系方式" prop="mobile"
show-overflow-tooltip>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="存放地点" prop="zcnowcfdmc"
show-overflow-tooltip>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="资产照片"
prop="zcfile"
width="250">
<template scope="{row}">
<span v-if="!row.zcfile">暂无</span>
<div v-else>
<file-upload :files.sync="row.zcfile"
view></file-upload>
</div>
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="盘点情况" prop="pdzt"
show-overflow-tooltip
width="100">
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="情况说明" prop="wpdzt"
show-overflow-tooltip
width="100">
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="使用情况"
prop="zczt" show-overflow-tooltip
width="100">
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="盘点时间" prop="zcbdsj"
show-overflow-tooltip>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane v-if="handle" :label="label" name="999">
<slot name="handle"></slot>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
module.exports = {
props: {
id: String,
handle: {
type: Boolean,
default: false,
},
label: {
type: String,
default: '审核'
},
panes: {
type: Array,
default: []
}
},
data() {
return {
loading: true,
viewData: {},
activeName: '1',
}
},
methods: {
hasPane(name) {
if (!this.handle) {
return true
}
return this.panes.includes(name)
},
async findOne(id) {
const resp = await $.get("/platform/zcgl/tzgl/findOne", {id})
if (resp.code === 0) {
const pdData = await $.post("/platform/zcgl/gdzcbg/queryChangeData", {zcid: id})
if (pdData.code === 0) {
pdData.data.forEach(v => {
if (v.zcfile) {
v.zcfile = JSON.parse(v.zcfile)
}
})
resp.data.bdData = pdData.data
} else {
resp.data.bdData = []
}
this.viewData = resp.data
} else {
}
this.loading = false
}
}
}
</script>
<style>
.tabPane .el-descriptions-item__label.is-bordered-label {
display: flex;
justify-content: center;
}
</style>