zhengkaixin пре 1 година
родитељ
комит
5e83beac97

+ 167 - 0
src/projects/business/apis/Master/annual.js

@@ -0,0 +1,167 @@
+import request from '$project/utils/request'
+import request2 from '$project/utils/request2'
+
+import Qs from 'qs';
+
+/**
+ * 考勤相关
+ * @param params
+ */
+
+//获取考勤记录
+export function pageList(params) {
+	return request({
+		url: '/mobile/workAttendance/pageList',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//获取考勤记录
+export function statistics(params) {
+	return request({
+		url: '/mobile/workAttendance/statistics',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+//获取申请补卡详情
+export function getApplyInfo(params) {
+	return request({
+		url: '/mobile/workAttendance/detailPatchCard',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//申请补卡提交
+export function postPatchCard(params) {
+	return request({
+		url: '/mobile/workAttendance/postPatchCard',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+export function supplementWorkDetail(params) {
+	return request({
+		url: '/mobile/workAttendance/supplementWorkDetail',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+export function supplementWorkSubmit(params) {
+	return request({
+		url: '/mobile/workAttendance/supplementWorkSubmit',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//获取时间段
+export function patchCard(params) {
+	return request({
+		url: '/mobile/workAttendance/patchCard',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//获取审核人列表
+export function getApprovalList(params) {
+	return request({
+		url: '/mobile/workAttendance/approvalList',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//获取补卡审批列表
+export function getVerifyList(params) {
+	return request({
+		url: '/mobile/workAttendance/adminListPatchCard',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+//补卡审批
+export function doVerify(params) {
+	return request({
+		url: '/mobile/workAttendance/approvalPatchCard',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}
+
+
+//获取考勤统计时段列表
+export function getAttednanceTimeList(params) {
+	return request({
+		url: '/mobile/workAttendance/findAttendancePeriod',
+		params: params,
+		method: 'get',
+	})
+}
+
+//获取考勤列表数据
+export function getAttednance(params) {
+	return request({
+		url: '/mobile/workAttendance/workAttendanceStat',
+		params: params,
+		method: 'get',
+	})
+}
+
+//获取考勤统计人员更多
+export function getPersonList(params) {
+	return request({
+		url: '/mobile/workAttendance/workAttendanceStatByCompanyId',
+		params: params,
+		method: 'get',
+	})
+}
+
+//获取考勤统计公司列表
+export function getCompanyList(params) {
+	return request({
+		url: '/mobile/workAttendance/workAttendanceStatCompanyList',
+		params: params,
+		method: 'get',
+	})
+}
+
+//获取考勤人员列表
+export function getNewPrsonList(params) {
+	return request({
+		url: '/mobile/workAttendance/workAttendanceStatByCompanyIdAndDate',
+		params: params,
+		method: 'get',
+	})
+}
+export function xsyWorkAttendanceStatNumByCompanyIdAndDate(params) {
+	return request({
+		url: '/mobile/workAttendance/xsyWorkAttendanceStatNumByCompanyIdAndDate',
+		params: params,
+		method: 'post',
+	})
+}
+//获取考勤具体详情id
+export function getBusinessId(id) {
+	return request({
+		url: '/mobile/workAttendance/getBusinessId',
+		params: {
+			id: id
+		},
+		method: 'get',
+	})
+}
+
+//添加备注
+export function addRemark(params) {
+	return request({
+		url: '/mobile/workAttendance/addRemarkForAttendance',
+		data: Qs.stringify(params),
+		method: 'post',
+	})
+}

+ 377 - 0
src/projects/business/views/Master/Annual/Apply.vue

@@ -0,0 +1,377 @@
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle"></top-header>
+
+		<div class="mui-content vongi-wordcard">
+			<div class="mui-content-padded vongi-wordcard-padded">
+				<h5>当前打卡班次</h5>
+				<h3>{{tjForm.workAttendanceDate}}<span v-text="tjForm.workAttendanceTime"></span></h3>
+			</div>
+		<div class="mui-content-padded">
+			<form class="mui-input-group">
+				<div class="mui-input-row">
+					<label><span class="colorfe616c"></span>审批人</label>
+					<div class="" >
+						<span class="mui-btn mui-btn-block" type='button' >{{examinePerson.name}}</span>
+					</div>
+				</div>
+				<div class="mui-input-row" v-if="false">
+					<label><span class="colorfe616c">*</span>选择打卡类型</label>
+					<div class="mui-navigate-right" @click="selectType">
+						<span class="mui-btn mui-btn-block" v-text="typeName"></span>
+					</div>
+				</div>
+			</form>
+		</div>
+			<div class="mui-content-padded">
+				<h5><span class="colorfe616c">*</span>申请理由</h5>
+				<div class="mui-input-row">
+					<textarea v-model="tjForm.reason" rows="5" placeholder="请输入"></textarea>
+				</div>
+			</div>
+			<div class="mui-content-padded">
+				<h5>上传照片(最多上传5张照片)</h5>
+				<div class="fyy-upphoto">
+					<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in picList">
+						<img :src="item" v-viewer />
+						<a class="mui-icon mui-icon-closeempty" @click="delPic(item)"></a>
+					</div>
+					<div class="mui-col-xs-3" @click="chooseImage">
+						<a><span class="mui-icon mui-icon-plusempty"></span></a>
+					</div>
+				</div>
+			</div>
+			
+			
+			<div class="vongi-btn">
+			 
+				
+				<button class="mui-btn "  style="width: 50%;" :class="examinePerson.name?'mui-btn-success':'mui-btn-grey'"  type="submit" @click="submit(0)">
+					<i icon="mui-icon mui-icon-compose"></i>保存草稿
+				</button>
+				<button class="mui-btn "  style="width: 50%;" :class="examinePerson.name?'mui-btn-primary':'mui-btn-grey'"  type="submit" @click="submit(1)">
+					提交
+				</button>
+				 
+			</div>
+		</div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	
+	import * as API_sp from '@/apis-xsy/xsy'
+	require('$project/assets/js/mui.picker.min.js');
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	import * as WxJsApi from '$project/utils/wxJsApi'
+	import * as types from '$project/store/mutation-types'
+	export default {
+		name: 'MasterAnnualApply',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '补卡申请',
+				id:"",
+				isLoading: false,
+				examinePerson:{},
+				subForm: {
+					formId: "applyWork",
+					workAttendanceId: this.$route.query.id
+				},
+				tjForm: {
+					workAttendanceDate: '',
+					workAttendanceTime: this.$route.query.time,
+					type: '2', //外勤打卡/补卡(1/2)
+					reason: '补卡申请',
+					id: this.$route.query.id,
+					imageUrl: '',
+					longitude: '',
+					latitude: '',
+					formId: "applyWork",
+				},
+				//typeName: '',
+				approvalPersonName: '刘攀',
+				personList: [],
+				picList: [],
+			}
+		},
+		created() {
+			this.id=this.$route.query.sid
+			
+		},
+		methods: {
+			//获取详情
+			getDetail() {
+				if(!this.id){
+					return 
+				}
+				this.isLoading = true;
+				API_Attendance.supplementWorkDetail( {
+					id: this.id
+				},).then(response => {
+					this.tjForm.ids=this.id;
+					this.tjForm = {
+						... this.tjForm ,
+						...response
+						
+					};
+					if(response.imageUrl){
+						this.picList=response.imageUrl.split(",")
+					}
+			
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//获取详情
+			getTime() {
+				this.isLoading = true;
+				API_Attendance.patchCard(this.subForm).then(response => {
+
+					this.tjForm.workAttendanceDate = response.workAttendanceDate;
+					this.tjForm.workAttendanceTime = response.workAttendanceTime;
+
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//获取审核人列表
+			getPsersonList() {
+				this.isLoading = true;
+                //补卡1,外出2,出差3 ,请假4
+                var parameter={type:1};
+                API_Attendance.getApprovalList(parameter).then(response => {
+
+					this.personList = response.data;
+
+					this.isLoading = false;
+
+					//设置默认审核人
+					this.setDefaultExaminePerson();
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//微信选择图片
+			chooseImage() {
+				WxJsApi.chooseImage().then(res => {
+					var localData = res.localData;
+
+					if (localData.indexOf('data:image') != 0) {
+						//判断是否有这样的头部
+						localData = 'data:image/jpeg;base64,' + localData
+					}
+					localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg')
+					this.imgBase64 = localData;
+					//显示裁剪图片
+					//_this.showCropper(field);
+					this.uploadpic();
+				}).catch(error => {
+					mui.toast(error);
+				})
+			},
+			//上传图片
+			uploadpic() {
+				this.isLoading = true;
+				WxJsApi.uploadPic(this.imgBase64).then(response => {
+					this.isLoading = false;
+
+					this.picList.push(response);
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//选择审核人
+			selectPerson() {
+				var _this = this;
+				var picker = new mui.PopPicker();
+				picker.setData(_this.syPersonList);
+				if (this.default_examine_person) {
+					picker.pickers[0].setSelectedValue(this.default_examine_person);
+				}
+				picker.show(function(selectItems) {
+					_this.tjForm.approvalPersonId = selectItems[0].value;
+					_this.approvalPersonName = selectItems[0].text;
+					_this.set_default_examine_person(selectItems[0].value);
+				})
+			},
+			//设置默认审核人
+			setDefaultExaminePerson() {
+				if (this.default_examine_person) {
+					for (var i = 0; i < this.syPersonList.length; i++) {
+						if (this.syPersonList[i].value == this.default_examine_person) {
+							this.tjForm.approvalPersonId = this.default_examine_person;
+							this.approvalPersonName = this.syPersonList[i].text;
+						}
+					}
+				}
+			},
+			//类型选择
+			selectType() {
+				var picker = new mui.PopPicker();
+				if (this.tjForm.type = 2) {
+					var data = [{
+						value: '2',
+						text: '补卡'
+					}]
+				} else {
+					var data = [{
+						value: '1',
+						text: '外勤打卡'
+					}]
+				}
+				picker.setData(data);
+				var _this = this;
+				picker.show(function(selectItems) {
+					_this.tjForm.type = selectItems[0].value;
+					//_this.typeName = selectItems[0].text;
+				})
+			},
+			//表单检测
+			checkFrom() {
+				if (!this.tjForm.type) {
+					mui.toast('请选择打卡类型');
+					return false;
+				} else if (false) {
+					mui.toast('请选择审批人');
+					return false;
+				} else if (!this.tjForm.reason) {
+					mui.toast('请输入申请内容');
+					return false;
+				} else {
+					return true;
+				}
+			},
+			//提交
+			submit(status) {
+								this.tjForm.draft=status;
+
+				if(!this.examinePerson.name){
+					return;
+				}
+				this.tjForm.imageUrl = this.picList.join(',');
+				if (this.checkFrom()) {
+					this.isLoading = true;
+					API_Attendance.supplementWorkSubmit(this.tjForm).then(response => {
+						this.isLoading = false;
+						if(status){
+							mui.toast('提交成功');
+							this.$router.replace({
+								name: "XsyApprovalInfo",
+								query:{id:response.id,formId:'applyWork'}
+							})
+						}else{
+							mui.toast('保存成功');
+							this.tjForm.ids=response.id;
+							this.id=response.id
+						}
+					
+						
+						
+						
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			//删除图片
+			delPic(item) {
+				let picList = this.picList;
+				let index = picList.indexOf(item);
+				if (index > -1) {
+					picList.splice(index, 1);
+				}
+				this.picList = picList;
+			},
+			getExaminePerson(){
+				API_sp.examinePerson(this.subForm.formId).then(response => {
+					this.examinePerson=response
+				}).catch(error => {
+					
+					mui.toast(error);
+				})
+			},
+			asynCallBack() {
+
+			},
+			...mapMutations({
+				set_default_examine_person: types.SET_DEFAULT_EXAMINE_PERSON,
+			})
+		},
+		mounted() {
+			//获取微信配置
+			WxJsApi.getWxConfig();
+			//this.getTime();
+			this.getExaminePerson();
+			this.getDetail();
+		},
+		destroyed() {},
+		computed: {
+			syPersonList: {
+				// getter
+				get: function() {
+					let list = [];
+					this.personList.forEach(function(item, index) {
+						list.push({
+							value: item.id,
+							text: item.personName
+						});
+					})
+					return list;
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			typeName: {
+				// getter
+				get: function() {
+					if (this.tjForm.type == '1') {
+						return '外勤打卡';
+					} else if (this.tjForm.type == '2') {
+						return '补卡';
+					} else {
+						return '无';
+					}
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				default_examine_person: 'default_examine_person'
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style src="$project/assets/css/mui.picker.min.css"></style>
+<style scoped>
+</style>

+ 195 - 0
src/projects/business/views/Master/Annual/Info.vue

@@ -0,0 +1,195 @@
+<template>
+	<div>
+		
+		<div class="mui-content vongi-wordcard">
+			 
+
+			<div class="mui-content-padded vongi-wordcard-center">
+				<ul class="mui-table-view">
+					 
+					 
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请班次</div>
+						<span class="colorf6f448" v-text="detail.attendanceDate"></span>
+					</li>
+				 
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请时间</div>
+						<span v-text="detail.createTime"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请理由</div>
+						<span class="colorf8b155" v-text="detail.reason"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">相关照片</div>
+					</li>
+					<li class="mui-table-view-cell mui-media fyy-upphoto">
+						<div class="mui-col-xs-3" v-for="(item,index) in picList">
+							<img :src="item" v-viewer />
+						</div>
+					</li>
+
+				</ul>
+			</div>
+            
+			
+			<!-- <div v-if="detail.status && detail.status=='2' && detail.personId==person_data.id" class="fyy-scon-botton">
+				<div class="examine-btn examine-btn1-blue" @click="resetApply">重新申请</div>
+			</div> -->
+
+			<!-- <div v-if="can_remark" class="fyy-scon-botton">
+				<div class="examine-btn examine-btn1-blue" @click="openFromVisible=true">填写意见</div>
+			</div> -->
+		</div>
+
+	 
+ 		
+
+ 	</div>
+</template>
+
+<script>
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	export default {
+		name: 'MasterAnnualInfo',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '打卡详情',
+
+				isLoading: false,
+
+				subForm: {
+					id: this.$route.query.id
+				},
+				detail: {},
+
+				can_remark: this.$route.query.remark,
+				remarkForm: {
+					id: this.$route.query.id,
+					remark: ''
+				},
+				openFromVisible: false
+			}
+		},
+		created() {
+
+		},
+		methods: {
+			//重新申请
+			resetApply(){
+				this.$router.push({
+					name: 'MasterAnnualApply',
+					query: {
+						id: this.$route.query.applyId
+					}
+				})
+			},
+            //获取状态颜色
+            getColor(status) {
+                var color = '';
+                if (status == '0') {
+                    color = '#4fc5f7';
+                } else if (status == '1') {
+                    color = '#55f868';
+                } else if (status == '2') {
+                    color = '#fe616c';
+                }
+                return 'color:' + color + ';border-color:' + color + ';';
+            },
+			//获取详情
+			getDetail() {
+				this.isLoading = true;
+				API_Attendance.supplementWorkDetail(this.subForm).then(response => {
+
+					this.detail = response;
+
+					this.remarkForm.remark = response.remark;
+					this.detail.text="补卡申请"
+					this.$emit('getInfo',this.detail);
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//领导添加备注
+			addRemark() {
+				if (!this.remarkForm.remark) {
+					mui.toast('请填写意见');
+				} else {
+					this.isLoading = true;
+					API_Attendance.addRemark(this.remarkForm).then(response => {
+						this.isLoading = false;
+
+						this.openFromVisible = false;
+						mui.toast('提交成功');
+						this.getDetail();
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			//获取详情
+			this.getDetail();
+		},
+		destroyed() {},
+		computed: {
+			picList: {
+				// getter
+				get: function() {
+					if (this.detail && this.detail.imageUrl) {
+						return this.detail.imageUrl.split(',');
+					} else {
+						return [];
+					}
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				person_data: 'person_data',
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped>
+	.status_r {
+		color: #fe616c !important;
+		border: 1px solid #fe616c !important;
+	}
+
+	.status_a {
+		color: #05c8af !important;
+		border: 1px solid #05c8af !important;
+	}
+
+	.examine-btn1-blue {
+		background-color: #3385FF;
+	}
+</style>

+ 465 - 0
src/projects/business/views/Master/Annual/LeaveForm.vue

@@ -0,0 +1,465 @@
+<template>
+	<div>
+
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle"></top-header>
+
+		<div class="mui-content vongi-wordcard">
+			<div class="mui-content-padded">
+				<form class="mui-input-group">
+					<div class="mui-input-row">
+						<label><span class="colorfe616c">*</span>请假类型</label>
+						<div class="mui-navigate-right" @click="selectType">
+							<button class="mui-btn mui-btn-block" type='button' v-text="typeName">请选择</button>
+						</div>
+					</div>
+                    <div class="mui-input-row">
+                        <label><span class="colorfe616c">*</span>开始日期</label>
+                        <div class="mui-navigate-right" @click="selectStartTime()">
+                            <button class="mui-btn mui-btn-block" type='button' v-text="tjForm.startTime+(tjForm.startTimeQuantum!=''?(tjForm.startTimeQuantum=='1'?'下午上班':'上午上班'):'')">请选择</button>
+                        </div>
+                    </div>
+                    <div class="mui-input-row">
+                        <label><span class="colorfe616c">*</span>结束日期</label>
+                        <div class="mui-navigate-right" @click="selectEndTime()">
+                            <button class="mui-btn mui-btn-block" type='button' v-text="tjForm.endTime+(tjForm.endTimeQuantum!=''?(tjForm.endTimeQuantum=='1'?'下午下班':'上午下班'):'')">请选择</button>
+                        </div>
+                    </div>
+				</form>
+			</div>
+			<div class="mui-content-padded vongi-qingjia-date">
+				 <h5 v-if="false&&tjForm.leaveType==4">可调休剩余时长<span class="color4fc5f7">{{workOverTime}}小时</span></h5>
+				<form class="mui-input-group">
+
+					<div class="mui-input-row">
+						<label><span class="colorfe616c"></span>请假时长</label>
+						<div  >
+							<button class="mui-btn mui-btn-block" type='button' v-text="daytime?daytime+'天':''" > </button>
+ 						</div>
+					</div>
+                    <div class="mui-input-row">
+                        <label><span class="colorfe616c"></span>审批人</label>
+                        <div class=" " >
+						<span class="mui-btn mui-btn-block" type='button' >{{examinePerson.name}}</span>
+						
+                          
+                        </div>
+                    </div>
+				</form>
+			</div>
+			<div class="mui-content-padded">
+				<h5><span class="colorfe616c">*</span>请假事由</h5>
+				<div class="mui-input-row">
+					<textarea id="textarea" rows="5" v-model="tjForm.reason" :placeholder="reasonDefault"></textarea>
+				</div>
+			</div>
+
+			<div class="mui-content-padded" v-if="tjForm.leaveType!=6" >
+				<h5>上传照片(最多上传5张照片)</h5>
+				<div class="fyy-upphoto">
+					<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in picList" :key="index">
+						<img :src="item" v-viewer />
+						<a class="mui-icon mui-icon-closeempty" @click="delPic(item)"></a>
+					</div>
+					<div class="mui-col-xs-3" @click="chooseImage">
+						<a><span class="mui-icon mui-icon-plusempty"></span></a>
+					</div>
+				</div>
+			</div>
+
+			<div class="mui-content-padded mui-h6">注:<br/>
+			1、病假须上传医院证明。<br/>
+			2、请假事由中须写明请假去向。<br/>
+				<span  v-if="tjForm.leaveType==6" style="color:red" >3、丧假事由不需要上传照片,销假只需要上传火化纸质证明。</span><br/>
+			</div>
+			<div class="vongi-btn">
+				<button class="mui-btn "  style="width: 50%;" :class="examinePerson.name?'mui-btn-success':'mui-btn-grey'"  type="submit" @click="submit(0)">
+					<i icon="mui-icon mui-icon-compose"></i>保存草稿
+				</button>
+				<button class="mui-btn "  style="width: 50%;" :class="examinePerson.name?'mui-btn-primary':'mui-btn-grey'"  type="submit" @click="submit(1)">
+					提交
+				</button>
+			</div>
+		</div>
+		<loading :visible="isLoading"></loading>
+
+	</div>
+</template>
+
+
+<script>
+	import * as API_sp from '@/apis-xsy/xsy'
+	require('$project/assets/js/mui.picker.min.js');
+	import * as API_Leave from '@/apis/Master/leave'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	import * as WxJsApi from '$project/utils/wxJsApi'
+	import * as types from '$project/store/mutation-types'
+    import {
+        daysDistance
+    } from '$project/utils'
+
+	export default {
+		name: 'MasterAnnualLeaveForm',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				examinePerson:{},
+				pageTitle: '请假',
+				daytime:'',
+				isLoading: false,
+				leaveTypeList: [],
+ 				approvedList: [],
+                workOverTime:0,
+				typeName: '请选择',
+				approvalPersonName: '请选择',
+				id:"",
+				tjForm: {
+					startTime: '请选择',
+					endTime: '请选择',
+                    startTimeQuantum: '',
+                    endTimeQuantum: '',
+					leaveType: '',
+					imageUrl: '',
+					reason: '',
+					personId: '',
+					draft:0,
+                    approvedPersonPopedomId: '',
+					remark: '',
+					formId: "yearLeaveWork",
+				},
+				reasonDefault: '请假申请',
+				picList: [],
+			}
+		},
+		created() {
+			this.id=this.$route.query.id
+			
+		},
+		methods: {
+			//info
+			getDetail() {
+				if(!this.id){
+					return
+				}
+			    this.isLoading = true;
+			    API_Leave.detail({
+			        id: this.id
+			    }).then(response => {
+			        this.tjForm = {
+						... this.tjForm ,
+						...response
+						
+					};
+					
+					this.tjForm.id=this.id
+					this.tjForm.leaveType=response.type;
+					this.typeName=response.typeName;
+					this.daytime=response.days;
+					if(response.imageUrl){
+						this.picList=response.imageUrl.split(",")
+					}
+			        this.isLoading = false;
+					 this.getExaminePerson();
+			    }).catch(error => {
+			        this.isLoading = false;
+			        mui.toast(error);
+			    })
+			},
+			getExaminePerson(){
+				var obj={
+					formId:this.tjForm.formId,
+					days:this.daytime
+				}
+				if(this.tjForm.leaveType){
+					obj.leaveType=this.tjForm.leaveType
+				}
+				API_sp.examinePersonObj(obj).then(response => {
+					this.examinePerson=response
+				}).catch(error => {
+					
+					mui.toast(error);
+				})
+			},
+			//审批类型
+			getLeaveTypeList() {
+				API_Leave.leaveTypeList().then(response => {
+
+					for (var i in response) {
+						var mod = response[i]
+						mod.text = mod.name
+						this.leaveTypeList.push(mod)
+					}
+				}).catch(error => {
+					mui.toast(error);
+				})
+			},
+			
+			//微信选择图片
+			chooseImage() {
+				WxJsApi.chooseImage().then(res => {
+					var localData = res.localData;
+
+					if (localData.indexOf('data:image') != 0) {
+						//判断是否有这样的头部
+						localData = 'data:image/jpeg;base64,' + localData
+					}
+					localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg')
+					this.imgBase64 = localData;
+					//显示裁剪图片
+					//_this.showCropper(field);
+					this.uploadpic();
+				}).catch(error => {
+					mui.toast(error);
+				})
+			},
+			//上传图片
+			uploadpic() {
+				this.isLoading = true;
+				WxJsApi.uploadPic(this.imgBase64).then(response => {
+					this.isLoading = false;
+
+					this.picList.push(response);
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			 
+			//选择时间
+			selectStartTime() {
+				var _this = this;
+
+				var startTime = _this.tjForm.startTime == '请选择' ? null : _this.tjForm.startTime;
+
+				var endDate = null;
+
+				if (_this.tjForm.endTime != '请选择') {
+					endDate = new Date(_this.tjForm.endTime);
+				}
+
+				var picker = new mui.DtPicker({
+					"type": "hour",
+					"beginYear": 2020,
+					"endYear": 2040,
+					"endDate": endDate,
+                    "value": startTime,
+
+                    "customData":{"h":[{"text":"上午","value":"0"},{"text":"下午","value":"1"}]}
+
+
+                });
+				var _mui=mui;
+				picker.show(function(selectItems) {
+                    var year = selectItems.y.value;
+                    var month = selectItems.m.value;
+                    var day = selectItems.d.value;
+                    var curDate = year + "-" + month + "-" + day;
+
+                    if(curDate==_this.tjForm.endTime&&_this.tjForm.endTimeQuantum=='0'&&selectItems.h.value=='1'){
+                        //debugger
+                        _mui.alert('开始日期必须大于结束日期');
+                        return false;
+                    }
+
+					_this.tjForm.startTime = curDate;
+
+                    _this.tjForm.startTimeQuantum =  selectItems.h.value;
+                    _this.updatePersonByTime();
+                });
+			},
+			//选择时间
+			selectEndTime() {
+
+				var _this = this;
+
+				if (_this.tjForm.startTime == '请选择') {
+					mui.toast('请选择开始日期');
+					return;
+				}
+				var beginDate = new Date(_this.tjForm.startTime);
+                var endTime = _this.tjForm.endTime == '请选择' ? null : _this.tjForm.endTime;
+
+				var picker = new mui.DtPicker({
+					"type": "hour",
+					"beginYear": 2020,
+					"endYear": 2040,
+					"beginDate": beginDate,
+                    "value":endTime,
+
+                    "customData":{"h":[{"text":"上午","value":"0"},{"text":"下午","value":"1"}]}
+                });
+                var _mui=mui;
+				picker.show(function(selectItems) {
+
+                    var year = selectItems.y.value;
+                    var month = selectItems.m.value;
+                    var day = selectItems.d.value;
+                    var curDate = year + "-" + month + "-" + day;
+
+                    if(curDate==_this.tjForm.startTime&&_this.tjForm.startTimeQuantum=='1'&&selectItems.h.value=='0'){
+                        //debugger
+                        _mui.alert('结束日期不能小于开始日期');
+                        return false;
+                    }
+
+                    _this.tjForm.endTime = curDate;
+                    _this.tjForm.endTimeQuantum =  selectItems.h.value;
+                    _this.updatePersonByTime();
+ 				});
+			},
+			//根据时间 -调整审批人
+			updatePersonByTime(){
+			    if(this.tjForm.startTime=='请选择'||this.tjForm.endTime=='请选择'){
+			        return;
+				}
+              var i=  daysDistance(this.tjForm.startTime,this.tjForm.endTime);
+              var day=i+(this.tjForm.endTimeQuantum-this.tjForm.startTimeQuantum)*0.5+0.5
+				this.daytime=day;
+				this.getExaminePerson();
+
+
+			},
+			//类型选择
+			selectType() {
+				var picker = new mui.PopPicker();
+
+				picker.setData(this.leaveTypeList);
+				var _this = this;
+				picker.show(function(selectItems) {
+					_this.tjForm.leaveType = selectItems[0].value;
+					_this.typeName = selectItems[0].text;
+					_this.getExaminePerson()
+				})
+			},
+            checkWorkOverTime(){
+               return this.daytime*8 <this.workOverTime;
+			},
+			//表单检测
+			checkFrom() {
+				if (!this.tjForm.leaveType) {
+					mui.toast('请选择请假类型');
+					return false;
+				} else if (false) {
+					mui.toast('请选择审批人');
+					return false;
+				} else if (this.tjForm.startTime== '请选择') {
+					mui.toast('请选择开始日期');
+					return false;
+				} else if (this.tjForm.endTime== '请选择') {
+					mui.toast('请选择结束日期');
+					return false;
+				}else if (false&&this.tjForm.leaveType==4&&!this.checkWorkOverTime()) {
+                    mui.toast("调休剩余时长小于请假时长");
+                    return false;
+                }
+
+				else if (!this.tjForm.reason) {
+					mui.toast('请输入请假理由');
+					return false;
+				} else {
+					return true;
+				}
+			},
+			//删除图片
+			delPic(item) {
+				let picList = this.picList;
+				let index = picList.indexOf(item);
+				if (index > -1) {
+					picList.splice(index, 1);
+				}
+				this.picList = picList;
+			},
+			//提交
+			submit(status) {
+				
+				if(!this.examinePerson.name){
+					return;
+				}
+				this.tjForm.draft=status;
+				this.tjForm.reason = this.tjForm.reason ? this.tjForm.reason : this.reasonDefault;
+				if (this.checkFrom()) {
+					if(this.tjForm.leaveType==6){
+						this.picList=[]
+					}
+					this.tjForm.imageUrl = this.picList.join(',');
+					this.isLoading = true;
+					this.tjForm.days=this.daytime;
+					
+					var startTime=this.tjForm.startTime;
+					this.tjForm.startTime=this.tjForm.startTime+" 00:00:00"
+					
+					var endTime=this.tjForm.endTime;
+					this.tjForm.endTime=this.tjForm.endTime+" 00:00:00"
+					
+					this.tjForm.activityId=this.examinePerson.processActivityId
+					API_Leave.save(this.tjForm).then(response => {
+						this.isLoading = false;
+						
+						
+						if(this.tjForm.draft){
+							mui.toast("提交成功");
+							this.$router.replace({
+								name: "XsyApprovalInfo",
+								query:{id:response.id,formId:'yearLeaveWork'}
+							})
+						}else{
+							this.tjForm.startTime=startTime;
+							this.tjForm.endTime=endTime;
+							mui.toast("保存成功");
+							this.id=response.id
+							this.tjForm.id=response.id;
+							//this.getDetail();
+						}			 
+						
+					}).catch(error => {
+						this.tjForm.startTime=startTime;
+						this.tjForm.endTime=endTime;
+						
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			asynCallBack() {
+
+			},
+			...mapMutations({
+				set_default_examine_person: types.SET_DEFAULT_EXAMINE_PERSON,
+			})
+		},
+		mounted() {
+			//获取微信配置
+			WxJsApi.getWxConfig();
+            this.getExaminePerson();
+			this.getDetail();
+			this.getLeaveTypeList();
+
+
+		},
+		destroyed() {},
+		computed: {
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				default_examine_person: 'default_examine_person'
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style src="$project/assets/css/mui.picker.min.css"></style>
+
+<style>
+</style>

+ 294 - 0
src/projects/business/views/Master/Annual/LeaveInfo.vue

@@ -0,0 +1,294 @@
+<template>
+<div>
+    
+	<header class="mui-bar mui-bar-nav">
+			<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left" v-if="!$route.query.token"></a>
+			<h1 class="mui-title">{{pageTitle}}</h1>
+		</header>
+		
+   <form class="mui-input-group margin10">
+       <!--<div class="mui-input-row">-->
+           <!--<label>身份证号</label>-->
+           <!--<span v-text="detail.idCard">420400200002020101</span>-->
+       <!--</div>-->
+   
+       <div class="mui-input-row">
+           <label>请假时间</label>
+   
+           <span v-if="detail.startTime==detail.endTime&&detail.startTimeQuantum=='0'&&detail.endTimeQuantum=='1'">自{{detail.startTime}}</span>
+           <span v-else-if="detail.startTime==detail.endTime">自{{detail.startTime}}{{(detail.startTimeQuantum!=''?(detail.startTimeQuantum=='1'?'下午':'上午'):'')}}</span>
+           <span  v-else >自{{detail.startTime}}{{(detail.startTimeQuantum!=''?(detail.startTimeQuantum=='1'?'下午':'上午'):'')}}
+               <br />至{{detail.endTime}}{{(detail.endTimeQuantum!=''?(detail.endTimeQuantum=='1'?'下午':'上午'):'')}}</span>
+       </div>
+       <div class="mui-input-row">
+           <label>请假时长</label>
+           <span v-text="detail.days"></span>
+       </div>
+       <div class="mui-input-row">
+           <label>请假事由</label>
+           <span v-text="detail.reason">家中有事,需要会老家一趟家中有事,需要会老家一趟家中有事,需要会老家一趟家中有事,需要会老家一趟。</span>
+       </div>
+       
+	   <div class="mui-input-row  vongi-wordcard">
+	   		   <div class="mui-content-padded" >
+	   		   		  <h5>上传图片</h5>
+	   		   
+	   		   		  <div class="fyy-upphoto">
+	   		   		  	<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in picList">
+	   		   		  		<img :src="item" v-viewer />
+	   		   		  	
+	   		   		  	</div>
+	   		   		  
+	   		   		  </div>
+	   		   </div>
+	   </div>
+	   
+	   
+       <div class="mui-input-row">
+           <label>申请时间</label>
+           <span v-text="detail.createTime">2020-04-27 12:00:00</span>
+       </div>
+	   <div class="mui-input-row  vongi-wordcard">
+		   <div class="mui-content-padded" v-if="detail.status==1&&detail.enableCancel&&opAction" >
+		   		  <h5>销假凭证<a  v-if="detail.type==6" style="color:red" >(销假只需要上传火化纸质证明)</a></h5>
+		   
+		   		  <div class="fyy-upphoto">
+		   		  	<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in picList2">
+		   		  		<img :src="item" v-viewer />
+		   		  		<a class="mui-icon mui-icon-closeempty" @click="delPic(item)"></a>
+		   		  	</div>
+		   		  	<div class="mui-col-xs-3" @click="chooseImage">
+		   		  		<a style="width: 60px;"><span class="mui-icon mui-icon-plusempty" 
+						style=" padding: 20px 18px 11px 0;"></span></a>
+		   		  	</div>
+		   		  </div>
+		   </div>
+		  
+		   
+	   </div>
+	
+	  
+	  <div class="mui-input-row  vongi-wordcard" v-if="detail.cancelImages">
+	  		   <div class="mui-content-padded" >
+	  		   		  <h5>销假凭证</h5>
+	  		   
+	  		   		  <div class="fyy-upphoto">
+	  		   		  	<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in detail.cancelImages.split(',')">
+	  		   		  		<img :src="item" v-viewer />
+	  		   		  	
+	  		   		  	</div>
+	  		   		  
+	  		   		  </div>
+	  		   </div>
+	  </div>
+	  <div class="mui-input-row"v-if="detail.cancelTime">
+	      <label>销假时间</label>
+	      <span v-text="detail.cancelTime">2020-04-27 12:00:00</span>
+	  </div>
+	   <div class="vongi-btn"  v-if="detail.enableCancel&&opAction">
+	   	<button class="mui-btn  mui-btn-primary "  type="button" @click="submit()">
+	   		申请销假
+	   	</button>
+	   </div>
+	
+   </form>
+
+
+    <loading :visible="isLoading"></loading>
+
+</div>
+</template>
+
+<script>
+	import * as WxJsApi from '$project/utils/wxJsApi'
+	
+import * as API_Leave from '@/apis/Master/leave'
+import Common from '$project/components/Common.vue'
+import Loading from '$project/components/Loading.vue'
+import ExamineDetail from '$project/components/ExamineDetail.vue'
+
+import TopHeader from '$project/components/TopHeader.vue'
+ import {
+    mapGetters,
+    mapMutations
+} from 'vuex'
+import {
+    daysDistance
+} from '$project/utils'
+export default {
+    name: 'MasterAnnualLeaveInfo',
+    components: {
+        Common,
+        Loading,
+        TopHeader,ExamineDetail
+    },
+    data() {
+        return {
+			opAction:false,
+            pageTitle: '请假详情',
+            daytime:'',
+            isLoading: false,
+            id: this.$route.query.id,
+            detail: {},
+            status: ['待审核', '已批准', '已拒绝'],
+            statusColor: ['', 'mui-btn-success', 'mui-btn-danger'],
+			picList2:[],
+        }
+    },
+    created() {
+		this.opAction=this.$route.query.opAction
+    },
+    methods: {
+		//删除图片
+		delPic(item) {
+			let picList = this.picList2;
+			let index = picList.indexOf(item);
+			if (index > -1) {
+				picList.splice(index, 1);
+			}
+			this.picList2 = picList;
+		},
+		//微信选择图片
+		chooseImage() {
+			WxJsApi.chooseImage().then(res => {
+				var localData = res.localData;
+		
+				if (localData.indexOf('data:image') != 0) {
+					//判断是否有这样的头部
+					localData = 'data:image/jpeg;base64,' + localData
+				}
+				localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg')
+				this.imgBase64 = localData;
+				//显示裁剪图片
+				//_this.showCropper(field);
+				this.uploadpic();
+			}).catch(error => {
+				mui.toast(error);
+			})
+		},
+		//上传图片
+		uploadpic() {
+			this.isLoading = true;
+			WxJsApi.uploadPic(this.imgBase64).then(response => {
+				this.isLoading = false;
+		
+				this.picList2.push(response);
+			}).catch(error => {
+				this.isLoading = false;
+				mui.toast(error);
+			})
+		},
+		allowExamine(op){
+			this.$emit('allowExamine',op);	
+		},
+        //获取状态颜色
+        getColor(status) {
+            var color = '';
+            if (status == '0') {
+                color = '#4fc5f7';
+            } else if (status == '1') {
+                color = '#55f868';
+            } else if (status == '2') {
+                color = '#fe616c';
+            }
+            return 'color:' + color + ';border-color:' + color + ';';
+        },
+        //info
+        getDetail() {
+            this.isLoading = true;
+            API_Leave.detail({
+                id: this.id
+            }).then(response => {
+                this.detail = response;
+                var startTime=this.detail.startTime.replace('年','/').replace('月','/').replace('日','');
+                var endTime=this.detail.endTime.replace('年','/').replace('月','/').replace('日','');
+
+                var i=  daysDistance(startTime,endTime);
+                var day=i+(this.detail.endTimeQuantum-this.detail.startTimeQuantum)*0.5+0.5
+                this.daytime=day+'天';
+				this.detail.sp=true
+				this.detail.text=this.detail.typeName+"申请"
+				if(this.detail.cancelStatus!=5){
+					this.detail.statusName=this.detail.mergeStatusN;
+				}
+				this.$emit('getInfo',this.detail);
+				
+                this.isLoading = false;
+            }).catch(error => {
+                this.isLoading = false;
+                mui.toast(error);
+            })
+        },
+		//提交
+		submit() {
+			if(this.picList2.length==0){
+				mui.toast("请上传销假凭证");
+				return
+			}
+ 			if (true) {
+				var obj={
+					imageUrl:this.picList2.join(','),
+					id:this.id,
+					formId:'leaveCancelWork'
+				}
+ 				this.isLoading = true;
+			 
+				API_Leave.cancelLeaveSubmit(obj).then(response => {
+					this.isLoading = false;
+					mui.toast("提交成功");
+						this.getDetail();				 
+					
+				}).catch(error => {
+				
+					
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			}
+		},
+        asynCallBack() {
+
+        },
+		update() {
+			this.detail.sp=false;
+			this.getDetail();
+		 
+		}
+    },
+    mounted() {
+		if(this.opAction){
+			//获取微信配置
+			WxJsApi.getWxConfig();
+		}
+        this.getDetail();
+
+    },
+    destroyed() {},
+    computed: {
+        picList: {
+            // getter
+            get: function () {
+                if (this.detail && this.detail.imageUrl) {
+                    return this.detail.imageUrl.split(',');
+                } else {
+                    return [];
+                }
+            },
+            // setter
+            set: function (newValue) {
+                console.log(newValue)
+            }
+        },
+        ...mapGetters({
+            openId: 'wx_openid',
+            token: 'token',
+        })
+    },
+
+}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style>
+</style>

+ 74 - 0
src/projects/business/views/Master/Annual/LeaveInfoCancel.vue

@@ -0,0 +1,74 @@
+<template>
+<div>
+		<Info   ref="myinfo"></Info>
+		<div class="vongi-btn">
+			<button class="mui-btn  mui-btn-primary "  type="submit" @click="submit()">
+				提交
+			</button>
+		</div>
+ 		<loading :visible="isLoading"></loading>
+</div>
+</template>
+
+<script>
+	import Info from '@/views-xsy/Approval/Info.vue'
+	
+	import * as API from '@/apis-xsy/applyclass'
+	import * as API_sp from '@/apis-xsy/xsy'
+
+	import  Common from '$project/components/Common.vue'
+	 
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	
+	export default {
+		name: '',
+		components: {
+			Common,
+			Loading,
+			TopHeader,Info
+		},
+		data() {
+			return {
+				pageTitle: '申请调班详情',
+				showApprovalBl:false,
+				allowExamineBl:false,
+				isLoading: false,
+				subForm: {
+					procinstActUserIds: '',
+					content: '',
+					status: ''
+				},
+			}
+		},
+		created() {
+			
+	
+		},
+		methods: { 
+			submit(){},
+			 
+			 
+			 
+			asynCallBack() {
+	
+			},
+		
+		},
+		mounted() {
+		
+		},
+		destroyed() {},
+	
+	}
+</script>
+
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/xsy.css"></style>
+<style>
+</style>

+ 181 - 0
src/projects/business/views/Master/Annual/LeaveList.vue

@@ -0,0 +1,181 @@
+<template>
+	<div>
+
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle" :routeName="'Master'"></top-header>
+
+		<div class="mui-content">
+			<div class="mui-content-padded vongi-work">
+				<ul class="mui-table-view vongi-qingjia">
+					<li class="mui-table-view-cell" v-for="mod in recordList" @click="detail(mod.id,mod.enableCancel,mod.status)">
+						<h4>
+							{{mod.title}}
+							<span v-text="mod.createTime">12:00</span>
+						</h4>
+						 
+						<button class="mui-btn   mui-btn-outlined" :class="{'mui-btn-primary':mod.status==0,
+						'mui-btn-danger':mod.status==2||mod.status==3,
+						'mui-btn-success':mod.status==1||mod.status==4}"  v-text="mod.enableCancel||mod.cancelStatus!=5?mod.mergeStatusN:mod.statusN"  ></button>
+							
+					</li>
+
+				</ul>
+			</div>
+			<div class="fyy-footer">
+				<div class="bindfyy-btn"><button type="submit" class="mui-btn mui-btn-primary " @click="save()">写请假条</button></div>
+			</div>
+		</div>
+		<NullList :remark="'暂无请假记录'" v-if="!recordList.length"></NullList>
+
+
+		<loading :visible="isLoading"></loading>
+
+	</div>
+</template>
+
+
+<script>
+	import * as API_Leave from '@/apis/Master/leave'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import isReachBottom from '$project/utils/isReachBottom'
+	import NullList from '$project/components/NullList.vue'
+
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	export default {
+		name: 'MasterAnnualLeaveList',
+		components: {
+			Common,
+			Loading,
+			TopHeader,
+			NullList
+		},
+		data() {
+			return {
+				pageTitle: '请假记录',
+
+				isLoading: false,
+
+				listForm: {
+					pageIndex: 1,
+					pageSize: 20,
+					//	token: '',
+					totalPage: 1,
+					result: 0,
+				},
+				recordList: [],
+				status: ['待审核', '已批准','已退回', '已拒绝','无需审批'],
+			}
+		},
+		created() {
+			//this.listForm.openId = this.openId;
+			//this.listForm.result = this.$route.query.result != null ? this.$route.query.result : 0;
+		},
+		methods: {
+			//info
+			detail(id,bl,stauts) {
+				if(stauts==-99){
+					this.$router.push({
+						name: 'MasterAnnualLeaveForm',
+						query: {
+							id:id
+						}
+					})
+				}else{
+					var routeName="XsyApprovalInfo";
+					
+					this.$router.push({
+						name: routeName,
+						query: {
+							id: id,
+							formId:'yearLeaveWork',
+							opAction:bl
+						}
+					})
+				}
+				
+			},
+			save() {
+				this.$router.push({
+					name: 'MasterAnnualLeaveForm',
+					query: {
+
+					}
+				})
+			},
+			//获取列表
+			getList() {
+				this.isLoading = true;
+				API_Leave.pageList(this.listForm).then(response => {
+					if (response) {
+						if (this.listForm.pageIndex == 1) {
+							this.recordList = response.data;
+							this.listForm.pageIndex = response.pageNumber;
+							this.listForm.totalPage = response.totalPage;
+						} else {
+							this.recordList = [
+								...this.recordList,
+								...response.data
+							];
+						}
+					}
+					this.listForm.pageIndex++;
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//下拉事件
+			handleScrool() {
+				if (isReachBottom()) {
+					console.log('到达底部')
+					if (this.listForm.pageIndex <= this.listForm.totalPage && this.isLoading == false) {
+						this.getList();
+					} else {
+						return;
+					}
+				}
+			},
+
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			this.getList();
+			//监控下拉加载事件
+			var _this = this;
+			window.addEventListener('scroll', _this.handleScrool);
+		},
+		destroyed() {
+			//销毁监听事件
+			var _this = this;
+			window.removeEventListener('scroll', _this.handleScrool);
+		},
+		computed: {
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+			})
+		},
+		//keepalive监控判断
+		beforeRouteLeave(to, from, next) {
+			console.log(to.name);
+			if (['MasterAnnualLeaveInfo'].indexOf(to.name) > -1) {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', ['MasterAnnualLeaveList'])
+			} else {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', [])
+			}
+			next()
+		},
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style>
+</style>

+ 213 - 0
src/projects/business/views/Master/Annual/List.vue

@@ -0,0 +1,213 @@
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle" :rightLink="rightLink" :doRightLink="doRightLink"></top-header>
+
+		<div class="mui-content">
+			<div class="mui-content-padded vongi-work">
+				<!-- <h5>2020-09-28</h5> -->
+				<ul class="mui-table-view">
+					<li v-for="(item,index) in recordList" class="mui-table-view-cell">
+						{{item.recordTime}}
+						<div class="mui-media-body">
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='1' && item.status=='1'" @click="goToInfo(item.supplementWorkId)">{{item.type=='1'?'已外勤打卡':'已补卡'}}</button>
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status=='3'" @click="goToInfo(item.supplementWorkId)">已拒绝</button>
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status=='0'" @click="goToInfo(item.supplementWorkId)">审核中</button>
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status===null" @click="applybk(item.id,item.recordTime)">申请补卡</button>
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status==='6'" @click="applybk(item.id,item.recordTime)">申请补卡</button>
+							<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status==='-99'" @click="applybk2(item.id,item.recordTime,item.supplementWorkId)">草稿中</button>
+							
+							<span :style="'color:'+statusColor[item.result]" v-text="status[item.result]">缺卡</span>
+						</div>
+					</li>
+				</ul>
+			</div>
+		</div>
+		<NullList :remark="'暂无考勤记录'" v-if="!recordList.length"></NullList>
+		<!--弹窗-->
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import isReachBottom from '$project/utils/isReachBottom'
+	import NullList from '$project/components/NullList.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	export default {
+		name: 'MasterAnnualList',
+		components: {
+			Common,
+			Loading,
+			TopHeader,
+			NullList
+		},
+		data() {
+			return {
+				//pageTitle: '考勤记录',
+
+				isLoading: false,
+
+				listForm: {
+					pageIndex: 1,
+					pageSize: 20,
+					totalPage: 1,
+					result: 0,
+				},
+				recordList: [],
+				status: ['缺卡', '正常', '迟到', '早退', '请假','出差'],
+				statusColor: ['#fe616c', '#05c8af', '#f6f448', '#f6f448', '#f6f448', '#f6f448'],
+
+				rightLink: {
+					show: true,
+					icon: 'icon-shijian',
+					style: 'font-size:14px;color:#000;',
+					title: '缺卡记录'
+				},
+			}
+		},
+		created() {
+			this.listForm.openId = this.openId;
+			this.listForm.result = this.$route.query.result != null ? this.$route.query.result : 0;
+		},
+		methods: {
+			//申请补卡
+			applybk(id,time) {
+				this.$router.push({
+					name: 'MasterAnnualApply',
+					query: {
+						id: id,
+						time:time,
+					
+					}
+				})
+			},
+			//申请补卡
+			applybk2(id,time,sid) {
+				this.$router.push({
+					name: 'MasterAnnualApply',
+					query: {
+						id: id,
+						time:time,
+						sid:sid
+					}
+				})
+			},
+			//跳转申请补卡详情
+			goToInfo(id) {
+				this.$router.push({
+					name: 'XsyApprovalInfo',
+					query: {
+						id: id,
+						formId:'applyWork'
+					}
+				})
+			},
+			//获取列表
+			getList() {
+				this.isLoading = true;
+				API_Attendance.pageList(this.listForm).then(response => {
+					if (response) {
+						if (this.listForm.pageIndex == 1) {
+							this.recordList = response.data;
+							this.listForm.pageIndex = response.pageNumber;
+							this.listForm.totalPage = response.totalPage;
+						} else {
+							this.recordList = [
+								...this.recordList,
+								...response.data
+							];
+						}
+					}
+					this.listForm.pageIndex++;
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//下拉事件
+			handleScrool() {
+				if (isReachBottom()) {
+					console.log('到达底部')
+					if (this.listForm.pageIndex <= this.listForm.totalPage && this.isLoading == false) {
+						this.getList();
+					} else {
+						return;
+					}
+				}
+			},
+			//右上角点击事件
+			doRightLink() {
+				this.listForm.pageIndex = 1;
+				this.listForm.result = this.listForm.result == 1 ? 0 : 1;
+				this.getList();
+			},
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			this.getList();
+			//监控下拉加载事件
+			var _this = this;
+			window.addEventListener('scroll', _this.handleScrool);
+		},
+		destroyed() {
+			//销毁监听事件
+			var _this = this;
+			window.removeEventListener('scroll', _this.handleScrool);
+		},
+		computed: {
+			pageTitle: {
+				// getter
+				get: function() {
+					if (this.listForm.result) {
+						return '缺卡记录';
+					} else {
+						return '考勤记录';
+					}
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+			})
+		},
+		watch: {
+			'listForm.result': function(newVal, oldVal) {
+				if (newVal == 0) {
+					this.rightLink.title = '缺卡记录';
+				} else {
+					this.rightLink.title = '考勤记录';
+				}
+			}
+		},
+		//keepalive监控判断
+		beforeRouteLeave(to, from, next) {
+			console.log(to.name);
+			if (['MasterAnnualInfo', 'MasterAnnualApply'].indexOf(to.name) > -1) {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', ['MasterAnnualList'])
+			} else {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', [])
+			}
+			next()
+		},
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped>
+</style>

+ 427 - 0
src/projects/business/views/Master/Annual/Sign.vue

@@ -0,0 +1,427 @@
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle" :rightLink="rightLink" :doRightLink="doRightLink"></top-header>
+
+		<div class="mui-content vongi-wordcard">
+
+			<div class="mui-content-padded">
+				<form class="mui-input-group">
+					<div class="mui-input-row">
+						<label><span class="colorfe616c">*</span>考勤类型</label>
+						<div class="mui-navigate-right" @click="selectType">
+							<button class="mui-btn mui-btn-block" type='button' v-text="attendanceTypeName"></button>
+						</div>
+					</div>
+				</form>
+			</div>
+			<div v-if="tjForm.workAttendanceDate" class="mui-content-padded vongi-wordcard-padded">
+				<h5>当前打卡班次</h5>
+				<h3>{{tjForm.workAttendanceDate}}<span v-text="tjForm.workAttendanceTime"></span></h3>
+			</div>
+			<!-- <div class="mui-content-padded">
+				<form class="mui-input-group">
+					<div class="mui-input-row" @click="selectPerson">
+						<label><span class="colorfe616c">*</span>审批人</label>
+						<div class="mui-navigate-right">
+							<button class="mui-btn mui-btn-block" type='button' v-text="approvalPersonName"></button>
+						</div>
+					</div>
+				</form>
+			</div> -->
+			<div class="mui-content-padded">
+				<h5><span class="colorfe616c">*</span>定位</h5>
+				<button class="vongi-yidi-location" @click="getPoint">{{tjForm.address}}<span class="mui-icon mui-icon-location"></span></button>
+			</div>
+			<div class="mui-content-padded">
+				<h5><span class="colorfe616c">*</span>备注</h5>
+				<div class="mui-input-row">
+					<textarea v-model="tjForm.content" rows="5" placeholder="请输入"></textarea>
+				</div>
+			</div>
+			<div class="mui-content-padded">
+				<h5>上传照片(最多上传5张照片)</h5>
+				<div class="fyy-upphoto">
+					<div class="mui-col-xs-3 fyy-upphoto-close" v-for="(item,index) in picList">
+						<img :src="item" v-viewer />
+						<a class="mui-icon mui-icon-closeempty" @click="delPic(item)"></a>
+					</div>
+					<div class="mui-col-xs-3" @click="chooseImage">
+						<a><span class="mui-icon mui-icon-plusempty"></span></a>
+					</div>
+				</div>
+			</div>
+			<div class="vongi-btn">
+				<button class="mui-btn mui-btn-primary" type="button" @click="submit">
+					提交
+				</button>
+			</div>
+		</div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	require('$project/assets/js/mui.picker.min.js');
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	import * as WxJsApi from '$project/utils/wxJsApi'
+	import MapLoader from '$project/utils/AMap'
+	import * as types from '$project/store/mutation-types'
+	export default {
+		name: 'MasterAnnualSign',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '外勤打卡',
+
+				isLoading: false,
+
+				subForm: {
+					workAttendanceId: '',
+					attendanceType: '',
+				},
+				attendanceType: '3',
+				tjForm: {
+					alarmConfigId: '',
+					workAttendanceDate: '',
+					workAttendanceTime: '',
+					type: '1', //外勤打卡/补卡(1/2)
+					content: '外勤打卡申请',
+					approvalPersonId: '',
+					workAttendanceId: '',
+					photoFile: '',
+					longitude: 112.276527,
+					latitude: 30.306427,
+					address: '定位中……',
+					attendanceType: ''
+				},
+				//typeName: '',
+				approvalPersonName: '',
+				personList: [],
+				picList: [],
+
+				rightLink: {
+					show: true,
+					icon: 'icon-shijian',
+					style: 'font-size:14px;color:#000;',
+					title: '考勤记录'
+				},
+
+				typeStatusList: [{
+						value: '2',
+						text: '外出'
+					},
+					{
+						value: '3',
+						text: '出差'
+					}
+				],
+			}
+		},
+		created() {},
+		methods: {
+			//获取详情
+			getTime() {
+				this.subForm.attendanceType = this.attendanceType;
+				this.isLoading = true;
+				API_Attendance.patchCard(this.subForm).then(response => {
+
+					this.tjForm.workAttendanceDate = response.workAttendanceDate;
+					this.tjForm.workAttendanceTime = response.workAttendanceTime;
+					this.tjForm.alarmConfigId = response.alarmConfigId;
+
+					this.isLoading = false;
+				}).catch(error => {
+
+					this.tjForm.workAttendanceDate = '';
+					this.tjForm.workAttendanceTime = '';
+					this.tjForm.alarmConfigId = '';
+
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//获取审核人列表
+			getPsersonList() {
+				this.isLoading = true;
+                //补卡1,外出2,出差3 ,请假4
+                var parameter={type:this.attendanceType};
+				API_Attendance.getApprovalList(parameter).then(response => {
+
+					this.personList = response.data;
+
+					this.isLoading = false;
+
+					//设置默认审核人
+					this.setDefaultExaminePerson();
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//微信选择图片
+			chooseImage() {
+				WxJsApi.chooseImage().then(res => {
+					var localData = res.localData;
+
+					if (localData.indexOf('data:image') != 0) {
+						//判断是否有这样的头部
+						localData = 'data:image/jpeg;base64,' + localData
+					}
+					localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg')
+					this.imgBase64 = localData;
+					//显示裁剪图片
+					//_this.showCropper(field);
+					this.uploadpic();
+				}).catch(error => {
+					mui.toast(error);
+				})
+			},
+			//上传图片
+			uploadpic() {
+				this.isLoading = true;
+				WxJsApi.uploadPic(this.imgBase64).then(response => {
+					this.isLoading = false;
+
+					this.picList.push(response);
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//选择审核人
+			selectPerson() {
+				var _this = this;
+				var picker = new mui.PopPicker();
+				picker.setData(_this.syPersonList);
+				if (this.default_examine_person) {
+					picker.pickers[0].setSelectedValue(this.default_examine_person);
+				}
+				picker.show(function(selectItems) {
+					_this.tjForm.approvalPersonId = selectItems[0].value;
+					_this.approvalPersonName = selectItems[0].text;
+					_this.set_default_examine_person(selectItems[0].value);
+				})
+			},
+			//设置默认审核人
+			setDefaultExaminePerson() {
+				if (this.default_examine_person) {
+					for (var i = 0; i < this.syPersonList.length; i++) {
+						if (this.syPersonList[i].value == this.default_examine_person) {
+							this.tjForm.approvalPersonId = this.default_examine_person;
+							this.approvalPersonName = this.syPersonList[i].text;
+						}
+					}
+				}
+			},
+			//表单检测
+			checkFrom() {
+				if (!this.tjForm.alarmConfigId) {
+					mui.toast('无考勤配置');
+					return false;
+				} else if (!this.tjForm.type) {
+					mui.toast('请选择打卡类型');
+					return false;
+				}
+				/* else if (!this.tjForm.approvalPersonId) {
+					mui.toast('请选择审批人');
+					return false;
+				} */
+				else if (!this.tjForm.content) {
+					mui.toast('请输入申请内容');
+					return false;
+				} else if (!this.tjForm.address) {
+					mui.toast('暂未获取到您的位置');
+					return false;
+				} else {
+					return true;
+				}
+			},
+			//提交
+			submit() {
+				this.tjForm.attendanceType = this.attendanceType;
+				this.tjForm.photoFile = this.picList.join(',');
+				if (this.tjForm.address == '定位中……') {
+					this.tjForm.address = '';
+				}
+				if (this.checkFrom()) {
+					this.isLoading = true;
+					API_Attendance.postPatchCard(this.tjForm).then(response => {
+						this.isLoading = false;
+
+						mui.toast('提交成功');
+						this.$router.push({
+							name: 'Master',
+							query: {}
+						})
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			//删除图片
+			delPic(item) {
+				let picList = this.picList;
+				let index = picList.indexOf(item);
+				if (index > -1) {
+					picList.splice(index, 1);
+				}
+				this.picList = picList;
+			},
+			//获取经纬度
+			getPoint() {
+				this.isLoading = true;
+				WxJsApi.getLocation().then((res) => {
+					this.isLoading = false;
+					this.tjForm.latitude = parseFloat(res.latitude);
+					this.tjForm.longitude = parseFloat(res.longitude);
+
+					console.log(this.tjForm)
+
+					//获取定位地址
+					this.getPositionByLonLats()
+				}).catch(error => {
+
+                    this.isLoading = false;
+                    console.log(error)
+                    WxJsApi.addSysLog(error)
+                })
+			},
+			//获取定位地址
+			getPositionByLonLats() {
+				var _this = this;
+				MapLoader().then(AMap => {
+					var lnglatXY = [_this.tjForm.longitude, _this.tjForm.latitude];
+					AMap.service('AMap.Geocoder', function() {
+						let geocoder = new AMap.Geocoder({});
+						geocoder.getAddress(lnglatXY, function(status, result) {
+							console.log(lnglatXY);
+							console.log(status, result);
+							if (status === 'complete' && result.info === 'OK') {
+								var address = result.regeocode.formattedAddress;
+								console.log(address);
+								_this.tjForm.address = address;
+							} else {
+								_this.tjForm.address = '无法获取定位';
+							}
+						});
+					});
+				}).catch(error => {
+					console.log(error)
+				})
+			},
+			//选择考勤类型
+			selectType() {
+				var _this = this;
+				var picker = new mui.PopPicker();
+				picker.setData(_this.typeStatusList);
+				picker.pickers[0].setSelectedValue(this.attendanceType);
+				picker.show(function(selectItems) {
+					_this.attendanceType = selectItems[0].value;
+					//_this.approvalPersonName = selectItems[0].text;
+					_this.getTime();
+				})
+			},
+			//右上角点击事件
+			doRightLink() {
+				this.$router.push({
+					name: 'MasterAnnualList'
+				})
+			},
+			asynCallBack() {
+
+			},
+			...mapMutations({
+				set_default_examine_person: types.SET_DEFAULT_EXAMINE_PERSON,
+			})
+		},
+		mounted() {
+			if (['2', '3'].indexOf(this.person_data.workStatus) == -1) {
+				mui.toast('您当前工作状态无法进行外勤打卡');
+				this.$router.go(-1);
+			} else {
+				//获取微信配置
+				WxJsApi.getWxConfig(['chooseImage', 'getLocalImgData', 'getLocation']);
+				//获取经纬度
+				this.getPoint();
+				this.getTime();
+				//this.getPsersonList();
+			}
+		},
+		destroyed() {},
+		computed: {
+			syPersonList: {
+				// getter
+				get: function() {
+					let list = [];
+					this.personList.forEach(function(item, index) {
+						list.push({
+							value: item.id,
+							text: item.personName
+						});
+					})
+					return list;
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			typeName: {
+				// getter
+				get: function() {
+					if (this.tjForm.type == '1') {
+						return '外勤打卡';
+					} else if (this.tjForm.type == '2') {
+						return '补卡';
+					} else {
+						return '无';
+					}
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			attendanceTypeName: {
+				// getter
+				get: function() {
+					for (var i = 0; i < this.typeStatusList.length; i++) {
+						if (this.typeStatusList[i]['value'] == this.attendanceType) {
+							return this.typeStatusList[i]['text'];
+						}
+					}
+					return '';
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				default_examine_person: 'default_examine_person',
+				person_data: 'person_data',
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/mui.picker.min.css"></style>
+<style scoped>
+</style>

+ 256 - 0
src/projects/business/views/Master/Annual/Statistic.vue

@@ -0,0 +1,256 @@
+<!--workStatus:1-工作,2-外出,3-出差,4-休假-->
+<!--result:0-缺卡,1-正常,2-迟到,3-早退, 4-出差,5-请假-->
+<!--type:0=设备打卡,1=外勤打卡、2=补卡-->
+<!--status:0:无操作, 1:机器打卡记录,2:请假审批详情,3:外勤打卡、补卡审批详情-->
+
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle"></top-header>
+		
+		<div class="mui-content vongi-admin-kqtj">
+			<ul class="mui-table-view" style="margin-bottom: 10px;"  >
+			 					<li class="mui-table-view-cell " style="text-align: center;"  >
+			 						<span class="mui-icon mui-icon mui-icon-arrowleft" @click="optMonth(0)"></span>	{{year}}.{{(month>9?"":"0")}}{{month}}	<span class="mui-icon mui-icon mui-icon-arrowright" @click="optMonth(1)"></span>
+			 					</li>
+			</ul>
+			
+			<div class="vongi-index flew-sp flew-items" style="margin-bottom: 10px;">
+				<div class="vongi-index-top">
+					<div class="mui-media-object mui-pull-left">
+						<img :src="person_data?(person_data.faceImageUrl+'?x-oss-process=image/resize,h_50,m_lfit'):''">
+					</div>
+					<div class="mui-media-body">
+						<h3 v-if="person_data">{{person_data.name}}</h3>
+ 					</div>
+				</div>
+				<div class="vongi-index-right flew-items flew-sp">
+					
+					应出勤<a class="mui-pull-right" >{{obj.attendanceDays}}</a>天 / 实出勤<a class="mui-pull-right" >{{obj.totalAttendanceDays}}</a>天
+				</div>
+			</div>
+			
+			
+			 <ul class="mui-table-view"> 
+					
+			        <li class="mui-table-view-cell mui-collapse"  v-for="(it,index) in recordList"  v-if="it.list.length" >
+			            <a class="mui-navigate-right" href="#">{{it.name}}
+						<span style="float: right;  margin-right: 20px; color: rgba(136, 136, 136, 100); ">{{it.list.length}}次</span></a>
+			            <div class="mui-content-padded vongi-work">
+			               
+							<ul class="mui-table-view">
+								<li v-for="(item,index) in it.list" class="mui-table-view-cell">
+									{{item.recordTime}}
+									<div class="mui-media-body">
+										<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='1' && item.status=='1'" @click="goToInfo(item.supplementWorkId)">{{item.type=='1'?'已外勤打卡':'已补卡'}}</button>
+										<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status=='3'" @click="goToInfo(item.supplementWorkId)">已拒绝</button>
+										<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status=='0'" @click="goToInfo(item.supplementWorkId)">审核中</button>
+										<button type="button" class="mui-btn mui-btn-primary" v-if="item.result=='0' && item.status===null" @click="applybk(item.id,item.recordTime)">申请补卡</button>
+										<span :style="'color:'+statusColor[item.result]" v-text="status[item.result]">缺卡</span>
+									</div>
+								</li>
+							</ul>
+			            </div>
+			        </li>
+				 
+					
+			    </ul>
+
+		</div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	require('$project/assets/js/mui.picker.min.js');
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import isReachBottom from '$project/utils/isReachBottom'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	import {
+		currentTimeStamp,
+		parseUnixTime
+	} from '$project/utils'
+	export default {
+		name: 'MasterAnnualStatistic',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '考勤统计',
+				year:0,
+				month:1,
+				
+				listForm:{
+					date: '2021-06',
+				},
+				isLoading: false,
+				obj:{},
+				recordList: [],
+				status: ['缺卡', '正常', '迟到', '早退', '请假','出差'],
+				statusColor: ['#fe616c', '#05c8af', '#f6f448', '#f6f448', '#f6f448', '#f6f448'],
+				
+				rightLink: {
+					show: true,
+					icon: 'icon-shijian',
+					style: 'font-size:14px;color:#000;',
+					title: '缺卡记录'
+				},
+
+			}
+		},
+		created() {
+			 this.month= new Date().getMonth()+1;
+			 this.year= new Date().getYear()+1900;
+		},
+		methods: {
+			optMonth(opt){
+				
+				if(opt){
+					if( this.month==12){
+						 this.month=1;
+						  this.year++;
+					}else{
+						 this.month++;
+					}
+				}else{
+					if( this.month==1){
+						 this.month=12;
+						  this.year--;
+					}else{
+						 this.month--;
+					}
+				}
+				this.getList();
+			},
+			//申请补卡
+			applybk(id,time) {
+				this.$router.push({
+					name: 'MasterAnnualApply',
+					query: {
+						id: id,
+						time:time
+					}
+				})
+			},
+			//跳转申请补卡详情
+			goToInfo(id) {
+				this.$router.push({
+					name: 'XsyApprovalInfo',
+					query: {
+						id: id,
+						formId:'applyWork'
+					}
+				})
+			},
+			//获取列表
+			getList() {
+				this.isLoading = true;
+				var obj={
+					date:this.year+"-"+(this.month>9?"":"0")+this.month
+				}
+				this.recordList=[];
+				API_Attendance.statistics(obj).then(response => {
+					var status=this.status
+					//this.recordList = response.list;
+					var recordList=[
+						{
+														 result:"1",
+														 name:status[1],
+														 list:[],
+						}
+					]
+					
+					response.list.forEach(function(item, index) {
+						var bl=true;
+						
+						 for(var i in recordList){
+							 var it=recordList[i];
+							 if(it.result==item.result){
+								 bl=false;
+								 it.list.push(item);
+								 break
+							 }
+						 }
+						 if(bl){
+							 var my={
+								 result:item.result,
+								 name:status[item.result],
+								 list:[],
+							 }
+							 my.list.push(item)
+							 recordList.push(my)
+						 }
+						 
+						 
+					})
+					this.recordList=recordList;
+					console.log(this.recordList)
+					this.obj=response;
+					
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			}, 
+			 
+			//选择日期
+			selectData() {
+				var _this = this;
+				var picker = new mui.DtPicker({
+					"type": "date",
+					"beginYear": 2020,
+					"endYear": 2040,
+					"endDate": new Date(),
+					"value": _this.subForm.queryDate
+				});
+				picker.show(function(rs) {
+					_this.subForm.queryDate = rs.text;
+					//获取公司列表
+					_this.getCompanyList();
+					picker.dispose();
+				});
+			},
+		 
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			//获取列表
+		//	this.getCompanyList();
+			this.getList();
+		},
+		destroyed() {
+			
+		},
+		computed: {
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				person_data: 'person_data',
+				person_popedom: 'person_popedom',
+			})
+		},
+		
+	}
+</script>
+<style scoped src="$project/assets/css/xpgj.css"></style>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped>
+	.colorAAA {
+		color: #AAAAAA;
+	}
+</style>

+ 489 - 0
src/projects/business/views/Master/Annual/StatisticList.vue

@@ -0,0 +1,489 @@
+<!--workStatus:1-工作,2-外出,3-出差,4-休假-->
+<!--result:0-缺卡,1-正常,2-迟到,3-早退, 4-出差,5-请假-->
+<!--type:0=设备打卡,1=外勤打卡、2=补卡-->
+<!--status:0:无操作, 1:机器打卡记录,2:请假审批详情,3:外勤打卡、补卡审批详情-->
+
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle"></top-header>
+
+		<div class="mui-content vongi-admin-kqtj">
+			<div class="fyy-temper-date vongi-flxtop">
+				<a class="mui-col-xs-12" @click="selectData">{{subForm.queryDate}}<span class="mui-icon iconfont icon-xiajiantou"></span></a>
+			</div>
+			<div class="vongi-flxtop vongi-kqtj-tab ">
+				<div class="vongi-top-bread vongi-bread">
+					<a @click="filter('',1)" :class="[''].indexOf(subForm.resultN)>-1?'mui-active':''">全部</a>
+					<a @click="filter('1',workCount)" :class="['1'].indexOf(subForm.resultN)>-1?'mui-active':''">正常({{workCount}})</a>
+					<a @click="filter('2',lateCount)" :class="['2'].indexOf(subForm.resultN)>-1?'mui-active':''">迟到({{lateCount}})</a>
+					<a @click="filter('3',leaveEarlyCount)" :class="['3'].indexOf(subForm.resultN)>-1?'mui-active':''">早退({{leaveEarlyCount}})</a>
+					<a @click="filter('0',absentCount)" :class="['0'].indexOf(subForm.resultN)>-1?'mui-active':''">缺卡({{absentCount}})</a>
+					<a @click="filter('4',businessCount)" :class="['4'].indexOf(subForm.resultN)>-1?'mui-active':''">出差({{businessCount}})</a>
+					<a @click="filter('5',vacationCount)" :class="['5'].indexOf(subForm.resultN)>-1?'mui-active':''">请假({{vacationCount}})</a>
+<!-- 					<a @click="filter('6',outCount)" :class="['6'].indexOf(subForm.resultN)>-1?'mui-active':''">外出({{outCount}})</a>
+ -->					<button @click="menuShow=true" type="button" class="mui-btn mui-icon mui-icon-arrowdown"></button>
+				</div>
+				<div v-if="menuShow" class="vongi-top-bread-list">
+					<div class="vongi-top-bread flew">
+						<a @click="filter('',1)" :class="[''].indexOf(subForm.resultN)>-1?'mui-active':''">全部</a>
+						<a @click="filter('1',workCount)" :class="['1'].indexOf(subForm.resultN)>-1?'mui-active':''">正常({{workCount}})</a>
+						<a @click="filter('2',lateCount)" :class="['2'].indexOf(subForm.resultN)>-1?'mui-active':''">迟到({{lateCount}})</a>
+						<a @click="filter('3',leaveEarlyCount)" :class="['3'].indexOf(subForm.resultN)>-1?'mui-active':''">早退({{leaveEarlyCount}})</a>
+						<a @click="filter('0',absentCount)" :class="['0'].indexOf(subForm.resultN)>-1?'mui-active':''">缺卡({{absentCount}})</a>
+						<a @click="filter('4',businessCount)" :class="['4'].indexOf(subForm.resultN)>-1?'mui-active':''">出差({{businessCount}})</a>
+						<a @click="filter('5',vacationCount)" :class="['5'].indexOf(subForm.resultN)>-1?'mui-active':''">请假({{vacationCount}})</a>
+<!-- 						<a @click="filter('6',outCount)" :class="['6'].indexOf(subForm.resultN)>-1?'mui-active':''">外出({{outCount}})</a>
+ -->						<button @click="menuShow=false" type="button" class="mui-btn mui-icon mui-icon-arrowup"></button>
+					</div>
+				</div>
+			</div>
+			<!-- <div class="vongi-bread vongi-kqtj-tab vongi-flxtop">
+				<a @click="filter('',1)" :class="[''].indexOf(subForm.resultN)>-1?'mui-active':''">全部</a>
+				<a @click="filter('1',workCount)" :class="['1'].indexOf(subForm.resultN)>-1?'mui-active':''">正常({{workCount}})</a>
+				<a @click="filter('2',lateCount)" :class="['2'].indexOf(subForm.resultN)>-1?'mui-active':''">迟到({{lateCount}})</a>
+				<a @click="filter('3',leaveEarlyCount)" :class="['3'].indexOf(subForm.resultN)>-1?'mui-active':''">早退({{leaveEarlyCount}})</a>
+				<a @click="filter('0',absentCount)" :class="['0'].indexOf(subForm.resultN)>-1?'mui-active':''">缺卡({{absentCount}})</a>
+				<a @click="filter('4',businessCount)" :class="['4'].indexOf(subForm.resultN)>-1?'mui-active':''">出差({{businessCount}})</a>
+				<a @click="filter('5',vacationCount)" :class="['5'].indexOf(subForm.resultN)>-1?'mui-active':''">请假({{vacationCount}})</a>
+				<a @click="filter('6',outCount)" :class="['6'].indexOf(subForm.resultN)>-1?'mui-active':''">外出({{outCount}})</a>
+			</div> -->
+			<div class="vongi-kqtj-center vongi-tab-top">
+				<div class="vongi-bread">
+					<template v-for="(item,index) in navList">
+						<a :class="navCanClick(item,index)?'color4fc5f7':''" @click="reloadItem(item,index)" v-text="item.name"></a>
+						<span v-if="index!=navList.length-1" class="mui-icon mui-icon-forward"></span>
+					</template>
+				</div>
+				<ul v-if="!isLast" class="mui-table-view margin10">
+					<li v-for="(item,index) in companyList" class="mui-table-view-cell">
+						<a class="mui-navigate-right" @click="reloadNext(item)">{{item.name}}({{item.number}})</a>
+					</li>
+				</ul>
+				<!--部门-->
+				<div class="vongi-work" >
+					<div v-if="recordList.length>0" class="mui-content-padded">
+						<h5 class="flew-items"><span class="iconfont icon-guanliyuan color4fc5f7"></span>组织人员</h5>
+					</div>
+					<div class="vongi-kqtj-list">
+						<div v-for="(item,index) in recordList" class="mui-card">
+							<div class="mui-card-header">
+								{{index+1}}.{{item.name}}
+								<button type="button" class="mui-btn  mui-btn-royal mui-btn-outlined" :style="setColor(item.workStatus,'workStatus')"
+								 @click="goToStatusInfo(item.workStatus,item.statusId)">{{item.workStatusN}}<span v-if="['2','3','4'].indexOf(item.workStatus)>-1"
+									 class="mui-icon mui-icon-forward"></span></button>
+							</div>
+							<div class="mui-card-content">
+								<div class="mui-card-content-inner flew">
+									<div @click="getBusinessId(iten.status, iten.id)" v-for="(iten,indy) in item.list" class="mui-col-xs-3 vongi-center vongi-clasadmin-ma">
+										<p v-text="iten.time"></p>
+										<a :class="'mui-media-body '+(iten.result!='0'?'mui-navigate-right ':'')" :style="setColor(iten.result,'result')">
+											<span v-if="iten.result!='0'" :class="'iconfont '+(iten.status=='1'?'icon-_renlianshibie ':(iten.status=='3'?'icon-shouji ':'')) +'color4fc5f7'"></span>
+											{{iten.remark}}
+										</a>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+
+				<!-- <div class="vongi-clasadmin vongi-kqtj-bot">
+					<div class="vongi-clasadmin-list">
+						<div @click="filter('1',workCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','1'].indexOf(subForm.resultN)>-1?'color55f868':'colorAAA'" v-text="workCount"></span>
+							<div class="mui-media-body">正常</div>
+						</div>
+						<div @click="filter('2',lateCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','2'].indexOf(subForm.resultN)>-1?'colorf8b155':'colorAAA'" v-text="lateCount"></span>
+							<div class="mui-media-body">迟到</div>
+						</div>
+						<div @click="filter('3',leaveEarlyCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','3'].indexOf(subForm.resultN)>-1?'colorf8b155':'colorAAA'" v-text="leaveEarlyCount"></span>
+							<div class="mui-media-body">早退</div>
+						</div>
+						<div @click="filter('0',absentCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','0'].indexOf(subForm.resultN)>-1?'colorfe616c':'colorAAA'" v-text="absentCount"></span>
+							<div class="mui-media-body">缺卡</div>
+						</div>
+						<div @click="filter('4',businessCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','4'].indexOf(subForm.resultN)>-1?'colorda94f8':'colorAAA'" v-text="businessCount"></span>
+							<div class="mui-media-body">出差</div>
+						</div>
+						<div @click="filter('5',vacationCount)" class="vongi-clasadmin-ma mui-col-xs-2">
+							<span :class="['','5'].indexOf(subForm.resultN)>-1?'colorda94f8':'colorAAA'" v-text="vacationCount"></span>
+							<div class="mui-media-body">请假</div>
+						</div>
+					</div>
+				</div> -->
+			</div>
+
+		</div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	require('$project/assets/js/mui.picker.min.js');
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import isReachBottom from '$project/utils/isReachBottom'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	import {
+		currentTimeStamp,
+		parseUnixTime
+	} from '$project/utils'
+	export default {
+		name: 'MasterAnnualStatisticList',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '考勤统计',
+
+				isLoading: false,
+
+				subForm: {
+					queryDate: '',
+					alarmConfigId: '',
+					companyId: '',
+					pageIndex: 1,
+					pageSize: 10,
+					totalPage: 1,
+					resultN: ''
+				},
+				absentCount: 0,
+				workCount: 0,
+				leaveEarlyCount: 0,
+				lateCount: 0,
+				businessCount: 0,
+				vacationCount: 0,
+				outCount: 0,
+				recordList: [],
+
+				companyList: [],
+				isLast: false,
+				nowLevel: 0,
+				navList: [{
+					name: '首页',
+					id: '',
+					hasNext: true,
+				}],
+
+				menuShow: false,
+
+			}
+		},
+		created() {
+			this.subForm.queryDate = parseUnixTime(currentTimeStamp(), '{y}-{m}-{d}');
+		},
+		methods: {
+			//获取公司列表
+			getCompanyList() {
+				//切换公司人员选第一页
+				this.subForm.pageIndex = 1;
+
+				this.isLoading = true;
+				API_Attendance.getCompanyList(this.subForm).then(response => {
+					this.isLoading = false;
+					//xsyWorkAttendanceStatNumByCompanyIdAndDate
+					this.companyList = response.list;
+					//如果只有一条数据,自动点到里面一层
+					if (this.companyList.length == 1 && this.nowLevel == 0) {
+						this.reloadNext(this.companyList[0]);
+					} else {
+						this.getPersonList();
+					}
+
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//获取下级公司列表
+			reloadNext(item) {
+				if (!this.isLast) {
+					this.subForm.companyId = item.id;
+					this.nowLevel++;
+					this.getCompanyList();
+					this.navList.push(item);
+
+					this.isLast = !item.hasNext;
+				}
+			},
+			//获取人员列表
+			getPersonList() {
+				this.isLoading = true;
+				API_Attendance.getNewPrsonList(this.subForm).then(response => {
+					this.isLoading = false;
+					
+					
+					if (response.groupList.length > 0) {
+						if (this.subForm.pageIndex == 1) {
+							this.recordList = response.groupList[0].personList;
+							//this.subForm.pageIndex = response.groupList[0].pageNumber;
+							//this.subForm.totalPage = response.groupList[0].totalPage;
+							this.isLoading = true;
+							
+								API_Attendance.xsyWorkAttendanceStatNumByCompanyIdAndDate(this.subForm).then(response2 => {
+									//this.recordList = response.groupList;
+									this.absentCount = response2.absentCount;
+									this.workCount = response2.workCount;
+									this.leaveEarlyCount = response2.leaveEarlyCount;
+									this.lateCount = response2.lateCount;
+									
+									this.businessCount = response2.businessCount;
+									this.vacationCount = response2.vacationCount;
+									//this.outCount = response2.outCount;
+									this.isLoading = false;
+									
+								})
+							
+						} else {
+							this.recordList = [
+								...this.recordList,
+								...response.groupList[0].personList
+							];
+						}
+
+						this.subForm.pageIndex = response.groupList[0].pageNumber;
+						this.subForm.totalPage = response.groupList[0].totalPage;
+					}
+					this.subForm.pageIndex++;
+
+					
+
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//面包屑选择加载
+			reloadItem(item, index) {
+				this.navList = this.navList.slice(0, index + 1);
+				this.nowLevel = index;
+				this.subForm.companyId = item.id;
+				this.getCompanyList();
+				this.isLast = !item.hasNext;
+			},
+			//判断面包屑是否可点击
+			navCanClick(item, index) {
+				if (index > 0) {
+					if (index == this.nowLevel) {
+						return false;
+					} else {
+						return true;
+					}
+				} else {
+					return true;
+				}
+			},
+			//选择日期
+			selectData() {
+				var _this = this;
+				var picker = new mui.DtPicker({
+					"type": "date",
+					"beginYear": 2020,
+					"endYear": 2040,
+					"endDate": new Date(),
+					"value": _this.subForm.queryDate
+				});
+				picker.show(function(rs) {
+					_this.subForm.queryDate = rs.text;
+					//获取公司列表
+					_this.getCompanyList();
+					picker.dispose();
+				});
+			},
+			//获取跳转详情的id
+			getBusinessId(status, id) {
+				if (status != '0') {
+					this.isLoading = true;
+					API_Attendance.getBusinessId(id).then(response => {
+						this.isLoading = false;
+
+						this.goToInfo(status, response.id);
+
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			//跳转到详情页
+			goToInfo(status, id) {
+				if (status != '0') {
+					if (status == '1') {
+						//设备打卡
+						this.$router.push({
+							name: 'MasterAnnualTemperatureInfo',
+							query: {
+								id: id
+							}
+						})
+					} else if (status == '2') {
+						//请假详情
+						this.$router.push({
+							name: 'MasterAnnualLeaveInfo',
+							query: {
+								id: id
+							}
+						})
+					} else if (status == '3') {
+						//外勤、补卡详情
+						this.$router.push({
+							name: 'MasterAnnualInfo',
+							query: {
+								id: id,
+								remark: 1,
+							}
+						})
+					}
+				}
+			},
+			goToStatusInfo(workStatus, statusId) {
+				if (statusId) {
+					if (workStatus == '2') {
+						//外出
+						this.$router.push({
+							name: 'MasterEgressInfo',
+							query: {
+								id: statusId,
+								remark: 1,
+							}
+						})
+					} else if (workStatus == '3') {
+						//出差
+						this.$router.push({
+							name: 'MasterBusinessTravelInfo',
+							query: {
+								id: statusId,
+								remark: 1,
+							}
+						})
+					} else if (workStatus == '4') {
+						//休假
+						this.$router.push({
+							name: 'MasterAnnualLeaveInfo',
+							query: {
+								id: statusId,
+								remark: 1,
+							}
+						})
+					}
+				} else {
+					if (workStatus != '1') {
+						mui.toast('无记录');
+					}
+				}
+			},
+			//下拉事件
+			handleScrool() {
+				if (isReachBottom()) {
+					console.log('到达底部')
+					if (this.subForm.pageIndex <= this.subForm.totalPage && this.isLoading == false) {
+						this.getPersonList();
+					} else {
+						return;
+					}
+				}
+			},
+			//过滤筛选条件
+			filter(status, num) {
+				if (num > 0) {
+					if (this.subForm.resultN == status) {
+						this.subForm.resultN = '';
+					} else {
+						this.subForm.resultN = status;
+					}
+					this.subForm.pageIndex = 1;
+					this.getPersonList();
+					this.menuShow = false;
+				}
+			},
+			//设置颜色
+			setColor(value, type) {
+				var color = '';
+				if (type == 'result') {
+					if (value == '0') {
+						color = '#FF6666'
+					} else if (value == '1') {
+						color = '#389E0D;'
+					} else if (value == '2') {
+						color = '#FF8800;'
+					} else if (value == '3') {
+						color = '#FF8800;'
+					} else if (value == '4') {
+						color = '#FF8800;'
+					}
+				} else if (type == 'workStatus') {
+					if (value == '1') {
+						color = '#3385FF';
+					} else if (value == '2') {
+						color = '#FF8800';
+					} else if (value == '3') {
+						color = '#FF8800';
+					} else if (value == '4') {
+						color = '#8855FF';
+					}
+				}
+
+				return 'border-color:' + color + ';color:' + color + '; ';
+			},
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			//获取列表
+			this.getCompanyList();
+			//监控下拉加载事件
+			var _this = this;
+			window.addEventListener('scroll', _this.handleScrool);
+		},
+		destroyed() {
+			//销毁监听事件
+			var _this = this;
+			window.removeEventListener('scroll', _this.handleScrool);
+		},
+		computed: {
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				person_data: 'person_data',
+				person_popedom: 'person_popedom',
+			})
+		},
+		//keepalive监控判断
+		beforeRouteLeave(to, from, next) {
+			console.log(to.name);
+			if (['MasterEgressInfo', 'MasterBusinessTravelInfo', 'MasterAnnualTemperatureInfo', 'MasterAnnualLeaveInfo',
+					'MasterAnnualInfo'
+				].indexOf(to.name) > -1) {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', ['MasterAnnualStatisticList'])
+			} else {
+				this.$store.commit('SET_KEEP_ALIVE_COMPONENTS', [])
+			}
+			next()
+		},
+	}
+</script>
+
+<style scoped src="$project/assets/css/sczpfyy.css"></style>
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style src="$project/assets/css/mui.picker.min.css"></style>
+<style scoped>
+	.colorAAA {
+		color: #AAAAAA;
+	}
+</style>

+ 117 - 0
src/projects/business/views/Master/Annual/TemperatureInfo.vue

@@ -0,0 +1,117 @@
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="pageTitle" :rightLink="rightLink" :doRightLink="doRightLink"></top-header>
+
+		<div class="mui-content fyy-detail-content mui-fullscreen">
+			<div class="mui-content-padded fyynew-detail">
+				<div class="fyynew-detail-photo">
+					<div class="fyynew-detail-region">
+						<img :src="detail.faceImage">
+					</div>
+				</div>
+				<div class="fyynew-detail-title" :style="detail.fever?'background: rgba(254,97,108,0.6);':'background: rgba(5,200,175,0.6);'"
+				 v-text="detail.fever?'检测异常':'检测正常'"></div>
+				<div class="fyynew-detail-wendu" :style="'background-color:'+detail.fever?'#fe616c':'#05c8af'" v-text="detail.temperature"></div>
+				<div class="fyynew-detail-text">
+					<h4 v-text="detail.personName"></h4>
+					<ul class="mui-table-view fyy-view">
+						<li class="mui-table-view-cell">
+							<label>检测时间</label>
+							<span v-text="detail.recordTime"></span>
+						</li>
+						<li class="mui-table-view-cell">
+							<label>设备名称</label>
+							<span v-text="detail.deviceName"></span>
+						</li>
+					</ul>
+				</div>
+			</div>
+		</div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	import * as API_Health from '@/apis/Common/health'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	export default {
+		name: 'MasterAnnualTemperatureInfo',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '详情',
+
+				isLoading: false,
+
+				rightLink: {
+					show: true,
+					icon: 'icon-tongji',
+					style: 'font-size:14px',
+					title: '健康统计'
+				},
+
+				detail: {},
+
+				subForm: {
+					id: this.$route.query.id
+				},
+			}
+		},
+		created() {
+
+		},
+		methods: {
+			//获取详情
+			getInfo() {
+				this.isLoading = true;
+				API_Health.getTemperatureInfo(this.subForm).then(response => {
+					this.detail = response;
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//右上角点击事件
+			doRightLink() {
+				this.$router.push({
+					name: 'CommonHealthCert',
+					query: {
+						personId: this.detail.personId
+					}
+				})
+			},
+			asynCallBack() {},
+		},
+		mounted() {
+			this.getInfo();
+		},
+		destroyed() {},
+		computed: {
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+				person_data: 'person_data',
+                person_popedom: 'person_popedom',
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style scoped src="$project/assets/css/sczpfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped>
+</style>

+ 241 - 0
src/projects/business/views/Master/Annual/VerifyInfo.vue

@@ -0,0 +1,241 @@
+<template>
+	<div>
+		<common @asynCallBack="asynCallBack"></common>
+		<top-header :pageTitle="(detail.typeN?detail.typeN:'')+pageTitle"></top-header>
+
+		<div class="mui-content vongi-wordcard">
+			<div class="mui-content-padded vongi-wordcard-top">
+				<div v-show="detail.faceImageUrl" class="mui-media-object mui-pull-left">
+					<img :src="detail.faceImageUrl" v-viewer>
+				</div>
+				<div v-show="detail.personName" class="mui-media-body">
+					<font v-text="detail.personName"></font>
+					<p class='mui-ellipsis'><span class="colorfe616c" v-text="detail.typeN"></span>申请</p>
+				</div>
+				<button type="button" :class="'mui-btn mui-btn-success mui-btn-outlined '+(detail.status>0?(detail.status==1?'status_a':'status_r'):'')">
+					{{detail.status>0?(detail.status==1?'已同意':'已拒绝'):'未审核'}}
+				</button>
+			</div>
+
+			<div class="mui-content-padded vongi-wordcard-center">
+				<ul class="mui-table-view">
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请类型</div>
+						<span v-text="detail.typeN"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">所在部门</div>
+						<span v-text="detail.companyName"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请班次</div>
+						<span class="colorf6f448" v-text="detail.fillAttendanceDayAndTime"></span>
+					</li>
+					<li v-if="detail.address" class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">打卡地点</div>
+						<span v-text="detail.address"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请时间</div>
+						<span v-text="detail.createTime"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">申请理由</div>
+						<span class="colorf8b155" v-text="detail.content"></span>
+					</li>
+					<li class="mui-table-view-cell mui-media">
+						<div class="mui-media-body">相关照片</div>
+					</li>
+					<li class="mui-table-view-cell mui-media fyy-upphoto">
+						<div class="mui-col-xs-3" v-for="(item,index) in picList">
+							<img :src="item" v-viewer />
+						</div>
+					</li>
+				</ul>
+			</div>
+
+            <div class="vongi-slot mui-content-padded vongi-wordcard-center">
+                <div v-for="(item,index) in detail.list" class="vongi-slot-block">
+                    <div class="vongi-slot-img"><img :src="item.faceImageUrl"></div>
+                    <div class="vongi-slot-content">
+                        <h4>审批人{{index+1}}<span class="mui-pull-right mui-h5 color999" v-text="item.time"></span></h4>
+                        <p>{{item.name}} <span class="color55f868" :style="getColor(item.status)" v-text="item.statusN"></span></p>
+						<p v-if="item.approvalContent" v-text="item.approvalContent"></p>
+					</div>
+                </div>
+            </div>
+
+
+            <div v-if="detail.status=='0' && detail.approvalEnable" class="fyy-scon-botton">
+				<div class="examine-btn examine-btn1" @click="openFrom('2')">拒绝</div>
+				<div class="examine-btn examine-btn2" @click="openFrom('1')">通过</div>
+			</div>
+
+
+		</div>
+
+		<!-- 审批弹窗 -->
+		<div v-show="openFromVisible" class="mui-popup mui-popup-in vongi-mui-pop">
+			<div class="mui-popup-inner vongi-pop-inner">
+				<div class="mui-popup-title">填写意见</div>
+				<div class="mui-popup-input">
+					<textarea  v-model="subForm.content" rows="3" placeholder="请输入"></textarea>
+				</div>
+			</div>
+			<div class="mui-popup-buttons"><span class="mui-popup-button mui-popup-button-bold" @click="doAction">提交</span></div>
+		</div>
+		<div v-show="openFromVisible" @click="openFromVisible=false"  class="mui-popup-backdrop mui-active"></div>
+
+		<loading :visible="isLoading"></loading>
+	</div>
+</template>
+
+<script>
+	import * as API_Attendance from '@/apis/Master/annual'
+	import Common from '$project/components/Common.vue'
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	export default {
+		name: 'MasterAnnualVerifyInfo',
+		components: {
+			Common,
+			Loading,
+			TopHeader
+		},
+		data() {
+			return {
+				pageTitle: '申请详情',
+
+				isLoading: false,
+
+				id: this.$route.query.id,
+				detail: {},
+
+				//审批内容弹窗显示
+				openFromVisible: false,
+				selectIdList: [],
+				subForm: {
+					ids: '',
+					content: '',
+					status: ''
+				},
+			}
+		},
+		created() {
+
+		},
+		methods: {
+            //获取状态颜色
+            getColor(status) {
+                var color = '';
+                if (status == '0') {
+                    color = '#4fc5f7';
+                } else if (status == '1') {
+                    color = '#55f868';
+                } else if (status == '2') {
+                    color = '#fe616c';
+                }
+                return 'color:' + color + ';border-color:' + color + ';';
+            },
+			//获取详情
+			getDetail() {
+				this.isLoading = true;
+				API_Attendance.getApplyInfo({
+					id: this.id
+				}).then(response => {
+
+					this.detail = response;
+
+					this.isLoading = false;
+				}).catch(error => {
+					this.isLoading = false;
+					mui.toast(error);
+				})
+			},
+			//显示内容表单
+			openFrom(status) {
+				this.selectIdList = [this.id];
+				if (!this.selectIdList.length) {
+					mui.toast('请选择要处理的信息');
+				} else {
+					this.subForm.status = status;
+					this.subForm.content = status == 1 ? '同意' : '拒绝';
+					this.openFromVisible = true;
+					//直接点击处理,不需要弹窗理由框,又需要弹窗理由框了
+					//this.doAction();
+				}
+			},
+			//检测表单
+			checkForm() {
+				if (!this.subForm.ids) {
+					mui.toast('请选择要处理的信息');
+					return false;
+				} else {
+					return true;
+				}
+			},
+			//同意拒绝
+			doAction() {
+				this.subForm.ids = this.selectIdList.join(',');
+				if (this.checkForm()) {
+					this.isLoading = true;
+					API_Attendance.doVerify(this.subForm).then(response => {
+						this.isLoading = false;
+
+						this.openFromVisible = false;
+						this.getDetail();
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			asynCallBack() {
+
+			},
+		},
+		mounted() {
+			//获取详情
+			this.getDetail();
+		},
+		destroyed() {},
+		computed: {
+			picList: {
+				// getter
+				get: function() {
+					if (this.detail && this.detail.fillAttendanceFilesUrl) {
+						return this.detail.fillAttendanceFilesUrl.split(',');
+					} else {
+						return [];
+					}
+				},
+				// setter
+				set: function(newValue) {
+					console.log(newValue)
+				}
+			},
+			...mapGetters({
+				openId: 'wx_openid',
+				token: 'token',
+			})
+		}
+	}
+</script>
+
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped>
+	.status_r {
+		color: #fe616c !important;
+		border: 1px solid #fe616c !important;
+	}
+
+	.status_a {
+		color: #05c8af !important;
+		border: 1px solid #05c8af !important;
+	}
+</style>

+ 136 - 0
src/projects/business/views/Master/Annual/VerifyLeaveInfo.vue

@@ -0,0 +1,136 @@
+<template>
+<div>
+		<Info @allowExamine="allowExamine" ref="myinfo"></Info>
+		<div class="mui-content vongi-qingjiadt">
+			 
+			<div class="fyy-scon-botton" v-if="allowExamineBl">
+				<div class="examine-btn examine-btn1" @click="openFrom('3')">拒绝</div>
+				<div class="examine-btn examine-btn2" @click="openFrom('1')">通过</div>
+			</div>
+		</div>
+		<!--弹窗-->
+		<div class="mui-popup mui-popup-in vongi-mui-pop"  v-show="showApprovalBl">
+			<div class="mui-popup-inner vongi-pop-inner">
+				<div class="mui-popup-title">审核意见</div>
+				<div class="mui-popup-input">
+					<textarea id="textarea" rows="3" v-model="subForm.content" placeholder="可输入审核意见"></textarea>
+				</div>
+			</div>
+			<div class="mui-popup-buttons">
+				<span class="mui-popup-button"  @click="showApprovalBl=false">取消</span>
+			<span class="mui-popup-button mui-popup-button-bold" @click="doAction">提交</span></div>
+		</div>
+		<div class="mui-popup-backdrop mui-active" v-show="showApprovalBl"></div>
+		<loading :visible="isLoading"></loading>
+</div>
+</template>
+
+<script>
+	import Info from './LeaveInfo.vue'
+	
+	import * as API from '@/apis-xsy/applyclass'
+	import * as API_sp from '@/apis-xsy/xsy'
+
+	import  Common from '$project/components/Common.vue'
+	 
+	import Loading from '$project/components/Loading.vue'
+	import TopHeader from '$project/components/TopHeader.vue'
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+	
+	export default {
+		name: '',
+		components: {
+			Common,
+			Loading,
+			TopHeader,Info
+		},
+		data() {
+			return {
+				pageTitle: '申请详情',
+				showApprovalBl:false,
+				allowExamineBl:false,
+				isLoading: false,
+				subForm: {
+					procinstActUserIds: '',
+					content: '',
+					status: ''
+				},
+			}
+		},
+		created() {
+			
+	
+		},
+		methods: { 
+			allowExamine(bl){
+				 
+				if(bl==""){
+					 this.allowExamineBl=false;
+					return
+				}
+				 if(bl==this.$route.query.procinstActUserId){
+					 this.allowExamineBl=true;
+				 }else{
+					 this.allowExamineBl=false;
+				 }
+			
+			},
+			//同意拒绝
+			doAction() {
+				this.subForm.procinstActUserIds =this.$route.query.procinstActUserId;
+				if (this.checkForm()) {
+					this.isLoading = true;
+					API.examineSubmit(this.subForm).then(response => {
+						this.isLoading = false;
+			
+						this.showApprovalBl = false;
+						this.$refs.myinfo.update();
+						mui.toast("操作成功");
+						 
+					}).catch(error => {
+						this.isLoading = false;
+						mui.toast(error);
+					})
+				}
+			},
+			//检测表单
+			checkForm() {
+				if (false) {
+					mui.toast('请选择要处理的信息');
+					return false;
+				} else {
+					return true;
+				}
+			},
+		    openFrom(status) {
+		    	if (false) {
+		    		mui.toast('请选择要处理的信息');
+		    	} else {
+		    		this.subForm.status = status;
+		    		this.subForm.content = status == 1 ? '同意' : '拒绝';
+		    		this.showApprovalBl = true;
+		    		//直接点击处理,不需要弹窗理由框,又需要弹窗理由框了
+		    		//this.doAction();
+		    	}
+		    },
+			asynCallBack() {
+	
+			},
+		
+		},
+		mounted() {
+		
+		},
+		destroyed() {},
+	
+	}
+</script>
+
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/xsy.css"></style>
+<style>
+</style>

+ 49 - 0
src/projects/business/views/Master/Annual/VerifyLeaveList.vue

@@ -0,0 +1,49 @@
+<template>
+	<div>
+			 <ListSp formId="2" ></ListSp>
+	</div>
+</template>
+
+
+<script>
+	
+	
+	 import  ListSp from '@/components/Approval/ListSp.vue'
+	 
+	
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+
+	export default {
+		name: '',
+		components: {
+			ListSp
+		},
+		data() { 
+			return{
+				
+			}
+		},
+		created() {
+			 
+		},
+		methods: {  
+		
+		},
+	mounted() {
+		 
+	},
+
+	
+	}
+</script>
+
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/xsy.css"></style>
+<style>
+	
+
+</style>

+ 49 - 0
src/projects/business/views/Master/Annual/VerifyList.vue

@@ -0,0 +1,49 @@
+<template>
+	<div>
+			 <ListSp formId="4" ></ListSp>
+	</div>
+</template>
+
+
+<script>
+	
+	
+	 import  ListSp from '@/components/Approval/ListSp.vue'
+	 
+	
+	import {
+		mapGetters,
+		mapMutations
+	} from 'vuex'
+
+	export default {
+		name: '',
+		components: {
+			ListSp
+		},
+		data() { 
+			return{
+				
+			}
+		},
+		created() {
+			 
+		},
+		methods: {  
+		
+		},
+	mounted() {
+		 
+	},
+
+	
+	}
+</script>
+
+<style src="$project/assets/css/iconfont.css"></style>
+<style scoped src="$project/assets/css/xpwyfyy.css"></style>
+<style src="$project/assets/css/xsy.css"></style>
+<style>
+	
+
+</style>

+ 2 - 1
src/utils/request.js

@@ -20,7 +20,8 @@ if (process.env.VUE_APP_NODE_NAME == 'devlopment') {
 		// BACKEND_URL='http://192.168.33.90:8086/shinestar-server';
 		
 		//BACKEND_URL="https://ykt-test.xiaoxinda.com/shinestar-server/"
-		BACKEND_URL='http://223.75.170.44:6060/shinestar-server';
+		BACKEND_URL='http://111.4.58.15:6060/shinestar-server';
+		
 	//	BACKEND_URL='http://192.168.11.120:8086/shinestar-server';
 		
 		

+ 2 - 2
src/utils/storage.js

@@ -54,8 +54,8 @@ export const getOpenId = () => get('wx_openid')
 
 export const setOpenId = (data) => set('wx_openid', data)
 if (process.env.VUE_APP_NODE_NAME == 'devlopment') {
-	//setOpenId("oHjCawigqi8SEAwutwkQ-VEgdp3k")//zkx
-	setOpenId("oHjCawo-Twp2YRfuIT2Z9X4ayAtQ")//ys
+	setOpenId("oHjCawigqi8SEAwutwkQ-VEgdp3k")//zkx
+	//setOpenId("oHjCawo-Twp2YRfuIT2Z9X4ayAtQ")//ys
 	
 }
 export const getUserId = () => get('ali_openid')

+ 163 - 107
yarn.lock

@@ -1601,8 +1601,8 @@ alphanum-sort@^1.0.0:
 
 amdefine@>=0.0.4:
   version "1.0.1"
-  resolved "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
-  integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
+  resolved "https://registry.npmmirror.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+  integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==
 
 ansi-colors@^3.0.0:
   version "3.2.4"
@@ -1634,6 +1634,11 @@ ansi-regex@^5.0.0:
   resolved "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
   integrity sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U=
 
+ansi-regex@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+  integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
 ansi-styles@^2.2.1:
   version "2.2.1"
   resolved "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -1686,9 +1691,9 @@ arch@^2.1.1:
   integrity sha1-DFK75zRLtPomDEQ9LLrZwA/y8L8=
 
 are-we-there-yet@~1.1.2:
-  version "1.1.5"
-  resolved "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
-  integrity sha1-SzXClE8GKov82mZBB2A1D+nd/CE=
+  version "1.1.7"
+  resolved "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
+  integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==
   dependencies:
     delegates "^1.0.0"
     readable-stream "^2.0.6"
@@ -1717,8 +1722,8 @@ arr-union@^3.1.0:
 
 array-find-index@^1.0.1:
   version "1.0.2"
-  resolved "https://registry.npm.taobao.org/array-find-index/download/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
-  integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
+  resolved "https://registry.npmmirror.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+  integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==
 
 array-flatten@1.1.1:
   version "1.1.1"
@@ -1936,8 +1941,8 @@ bindings@^1.5.0:
 
 block-stream@*:
   version "0.0.9"
-  resolved "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
-  integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+  resolved "https://registry.npmmirror.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+  integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==
   dependencies:
     inherits "~2.0.0"
 
@@ -2269,16 +2274,16 @@ camel-case@3.0.x:
 
 camelcase-keys@^2.0.0:
   version "2.1.0"
-  resolved "https://registry.npm.taobao.org/camelcase-keys/download/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
-  integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
+  resolved "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+  integrity sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==
   dependencies:
     camelcase "^2.0.0"
     map-obj "^1.0.0"
 
 camelcase@^2.0.0:
   version "2.1.1"
-  resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
-  integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
+  resolved "https://registry.npmmirror.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+  integrity sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==
 
 camelcase@^5.0.0, camelcase@^5.3.1:
   version "5.3.1"
@@ -2513,8 +2518,8 @@ coa@^2.0.2:
 
 code-point-at@^1.0.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
-  integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
+  resolved "https://registry.npmmirror.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+  integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
 
 collection-visit@^1.0.0:
   version "1.0.0"
@@ -2664,8 +2669,8 @@ console-browserify@^1.1.0:
 
 console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
-  integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
+  resolved "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+  integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
 
 consolidate@^0.15.1:
   version "0.15.1"
@@ -2804,8 +2809,8 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
 
 cross-spawn@^3.0.0:
   version "3.0.1"
-  resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
-  integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI=
+  resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+  integrity sha512-eZ+m1WNhSZutOa/uRblAc9Ut5MQfukFrFMtPSm3bZCA888NmMd5AWXWdgRZ80zd+pTk1P2JrGjg9pUPTvl2PWQ==
   dependencies:
     lru-cache "^4.0.1"
     which "^1.2.9"
@@ -3012,8 +3017,8 @@ csso@^4.0.2:
 
 currently-unhandled@^0.4.1:
   version "0.4.1"
-  resolved "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
-  integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
+  resolved "https://registry.npmmirror.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+  integrity sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==
   dependencies:
     array-find-index "^1.0.1"
 
@@ -3780,8 +3785,8 @@ find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
 
 find-up@^1.0.0:
   version "1.1.2"
-  resolved "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz?cache=0&sync_timestamp=1597170071453&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
-  integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+  resolved "https://registry.npmmirror.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==
   dependencies:
     path-exists "^2.0.0"
     pinkie-promise "^2.0.0"
@@ -3904,8 +3909,8 @@ fsevents@~2.1.2:
 
 fstream@^1.0.0, fstream@^1.0.12:
   version "1.0.12"
-  resolved "https://registry.npm.taobao.org/fstream/download/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
-  integrity sha1-Touo7i1Ivk99DeUFRVVI6uWTIEU=
+  resolved "https://registry.npmmirror.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+  integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
   dependencies:
     graceful-fs "^4.1.2"
     inherits "~2.0.0"
@@ -3919,8 +3924,8 @@ function-bind@^1.1.1:
 
 gauge@~2.7.3:
   version "2.7.4"
-  resolved "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
-  integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
+  resolved "https://registry.npmmirror.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+  integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==
   dependencies:
     aproba "^1.0.3"
     console-control-strings "^1.0.0"
@@ -4124,8 +4129,8 @@ has-symbols@^1.0.1:
 
 has-unicode@^2.0.0:
   version "2.0.1"
-  resolved "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
-  integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
+  resolved "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+  integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
 
 has-value@^0.3.1:
   version "0.3.1"
@@ -4463,13 +4468,13 @@ imurmurhash@^0.1.4:
 
 in-publish@^2.0.0:
   version "2.0.1"
-  resolved "https://registry.npm.taobao.org/in-publish/download/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c"
-  integrity sha1-lIsaU1yAMFYc6lIvc/ePS+NX4Aw=
+  resolved "https://registry.npmmirror.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c"
+  integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==
 
 indent-string@^2.1.0:
   version "2.1.0"
-  resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
-  integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
+  resolved "https://registry.npmmirror.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+  integrity sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==
   dependencies:
     repeating "^2.0.0"
 
@@ -4682,13 +4687,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
 
 is-finite@^1.0.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/is-finite/download/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
-  integrity sha1-kEE1x3+0LAZB1qobzbxNqo2ggvM=
+  resolved "https://registry.npmmirror.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+  integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
 
 is-fullwidth-code-point@^1.0.0:
   version "1.0.0"
-  resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
-  integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
+  resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==
   dependencies:
     number-is-nan "^1.0.0"
 
@@ -4812,8 +4817,8 @@ is-typedarray@~1.0.0:
 
 is-utf8@^0.2.0:
   version "0.2.1"
-  resolved "https://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
-  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+  resolved "https://registry.npmmirror.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+  integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==
 
 is-windows@^1.0.2:
   version "1.0.2"
@@ -4879,8 +4884,8 @@ jquery@^3.5.1:
 
 js-base64@^2.1.8:
   version "2.6.4"
-  resolved "https://registry.npm.taobao.org/js-base64/download/js-base64-2.6.4.tgz?cache=0&sync_timestamp=1599897619557&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-base64%2Fdownload%2Fjs-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
-  integrity sha1-9OaGxd4eofhn28rT1G2WlCjfmMQ=
+  resolved "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
+  integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
 
 js-message@1.0.5:
   version "1.0.5"
@@ -5051,8 +5056,8 @@ lines-and-columns@^1.1.6:
 
 load-json-file@^1.0.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
-  integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+  resolved "https://registry.npmmirror.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==
   dependencies:
     graceful-fs "^4.1.2"
     parse-json "^2.2.0"
@@ -5129,7 +5134,12 @@ lodash.uniq@^4.5.0:
   resolved "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
   integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 
-lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@~4.17.10:
+lodash@^4.0.0:
+  version "4.17.21"
+  resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@~4.17.10:
   version "4.17.20"
   resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336097104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
   integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=
@@ -5155,8 +5165,8 @@ loose-envify@^1.0.0:
 
 loud-rejection@^1.0.0:
   version "1.6.0"
-  resolved "https://registry.npm.taobao.org/loud-rejection/download/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
-  integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
+  resolved "https://registry.npmmirror.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+  integrity sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==
   dependencies:
     currently-unhandled "^0.4.1"
     signal-exit "^3.0.0"
@@ -5262,8 +5272,8 @@ memory-fs@^0.5.0:
 
 meow@^3.7.0:
   version "3.7.0"
-  resolved "https://registry.npm.taobao.org/meow/download/meow-3.7.0.tgz?cache=0&sync_timestamp=1598693287069&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmeow%2Fdownload%2Fmeow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
-  integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
+  resolved "https://registry.npmmirror.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+  integrity sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==
   dependencies:
     camelcase-keys "^2.0.0"
     decamelize "^1.1.2"
@@ -5394,7 +5404,12 @@ minimatch@^3.0.4, minimatch@~3.0.2:
   dependencies:
     brace-expansion "^1.1.7"
 
-minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
+minimist@^1.1.3, minimist@^1.2.6:
+  version "1.2.8"
+  resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+minimist@^1.2.0, minimist@^1.2.5:
   version "1.2.5"
   resolved "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
   integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=
@@ -5459,7 +5474,14 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
+"mkdirp@>=0.5 0", mkdirp@^0.5.0:
+  version "0.5.6"
+  resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+  integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+  dependencies:
+    minimist "^1.2.6"
+
+mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
   version "0.5.5"
   resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
   integrity sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=
@@ -5520,11 +5542,16 @@ mz@^2.4.0:
     object-assign "^4.0.1"
     thenify-all "^1.0.0"
 
-nan@^2.12.1, nan@^2.13.2:
+nan@^2.12.1:
   version "2.14.1"
   resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
   integrity sha1-174036MQW5FJTDFHCJMV7/iHSwE=
 
+nan@^2.13.2:
+  version "2.20.0"
+  resolved "https://registry.npmmirror.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3"
+  integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -5571,8 +5598,8 @@ node-forge@^0.10.0:
 
 node-gyp@^3.8.0:
   version "3.8.0"
-  resolved "https://registry.npm.taobao.org/node-gyp/download/node-gyp-3.8.0.tgz?cache=0&sync_timestamp=1597202624819&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-gyp%2Fdownload%2Fnode-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
-  integrity sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=
+  resolved "https://registry.npmmirror.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+  integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
   dependencies:
     fstream "^1.0.0"
     glob "^7.0.3"
@@ -5632,8 +5659,8 @@ node-releases@^1.1.61:
 
 node-sass@^4.12.0:
   version "4.14.1"
-  resolved "https://registry.npm.taobao.org/node-sass/download/node-sass-4.14.1.tgz?cache=0&sync_timestamp=1589682128498&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-sass%2Fdownload%2Fnode-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5"
-  integrity sha1-mch+wu+3BH7WOPtMnbfzpC4iF7U=
+  resolved "https://registry.npmmirror.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5"
+  integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==
   dependencies:
     async-foreach "^0.1.3"
     chalk "^1.1.1"
@@ -5655,8 +5682,8 @@ node-sass@^4.12.0:
 
 "nopt@2 || 3":
   version "3.0.6"
-  resolved "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz?cache=0&sync_timestamp=1597649936800&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
-  integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+  resolved "https://registry.npmmirror.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+  integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==
   dependencies:
     abbrev "1"
 
@@ -5718,8 +5745,8 @@ npm-run-path@^4.0.0:
 
 "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0:
   version "4.1.2"
-  resolved "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
-  integrity sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=
+  resolved "https://registry.npmmirror.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+  integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
   dependencies:
     are-we-there-yet "~1.1.2"
     console-control-strings "~1.1.0"
@@ -5740,8 +5767,8 @@ num2fraction@^1.2.2:
 
 number-is-nan@^1.0.0:
   version "1.0.1"
-  resolved "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-  integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+  resolved "https://registry.npmmirror.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+  integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
 
 oauth-sign@~0.9.0:
   version "0.9.0"
@@ -5905,18 +5932,18 @@ os-browserify@^0.3.0:
 
 os-homedir@^1.0.0:
   version "1.0.2"
-  resolved "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
-  integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+  resolved "https://registry.npmmirror.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+  integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==
 
 os-tmpdir@^1.0.0:
   version "1.0.2"
-  resolved "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
-  integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+  resolved "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+  integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
 
 osenv@0:
   version "0.1.5"
-  resolved "https://registry.npm.taobao.org/osenv/download/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
-  integrity sha1-hc36+uso6Gd/QW4odZK18/SepBA=
+  resolved "https://registry.npmmirror.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+  integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
   dependencies:
     os-homedir "^1.0.0"
     os-tmpdir "^1.0.0"
@@ -6017,8 +6044,8 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5:
 
 parse-json@^2.2.0:
   version "2.2.0"
-  resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1598130878813&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
-  integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
+  resolved "https://registry.npmmirror.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==
   dependencies:
     error-ex "^1.2.0"
 
@@ -6074,8 +6101,8 @@ path-dirname@^1.0.0:
 
 path-exists@^2.0.0:
   version "2.1.0"
-  resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
-  integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+  resolved "https://registry.npmmirror.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==
   dependencies:
     pinkie-promise "^2.0.0"
 
@@ -6121,8 +6148,8 @@ path-to-regexp@0.1.7:
 
 path-type@^1.0.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/path-type/download/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
-  integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
+  resolved "https://registry.npmmirror.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==
   dependencies:
     graceful-fs "^4.1.2"
     pify "^2.0.0"
@@ -6737,16 +6764,16 @@ raw-body@2.4.0:
 
 read-pkg-up@^1.0.1:
   version "1.0.1"
-  resolved "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
-  integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
+  resolved "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==
   dependencies:
     find-up "^1.0.0"
     read-pkg "^1.0.0"
 
 read-pkg@^1.0.0:
   version "1.1.0"
-  resolved "https://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
-  integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+  resolved "https://registry.npmmirror.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==
   dependencies:
     load-json-file "^1.0.0"
     normalize-package-data "^2.3.2"
@@ -6762,7 +6789,7 @@ read-pkg@^5.1.1:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=
@@ -6775,6 +6802,19 @@ read-pkg@^5.1.1:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@^2.0.6:
+  version "2.3.8"
+  resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+  integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
 readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@@ -6802,8 +6842,8 @@ readdirp@~3.4.0:
 
 redent@^1.0.0:
   version "1.0.0"
-  resolved "https://registry.npm.taobao.org/redent/download/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
-  integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
+  resolved "https://registry.npmmirror.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+  integrity sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==
   dependencies:
     indent-string "^2.1.0"
     strip-indent "^1.0.1"
@@ -6905,8 +6945,8 @@ repeat-string@^1.6.1:
 
 repeating@^2.0.0:
   version "2.0.1"
-  resolved "https://registry.npm.taobao.org/repeating/download/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
-  integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
+  resolved "https://registry.npmmirror.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+  integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==
   dependencies:
     is-finite "^1.0.0"
 
@@ -7056,8 +7096,8 @@ safe-regex@^1.1.0:
 
 sass-graph@2.2.5:
   version "2.2.5"
-  resolved "https://registry.npm.taobao.org/sass-graph/download/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
-  integrity sha1-qYHIdEa4MZ2W3OBnHkh4eb0kwug=
+  resolved "https://registry.npmmirror.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
+  integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==
   dependencies:
     glob "^7.0.0"
     lodash "^4.0.0"
@@ -7100,8 +7140,8 @@ schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6
 
 scss-tokenizer@^0.2.3:
   version "0.2.3"
-  resolved "https://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
-  integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE=
+  resolved "https://registry.npmmirror.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
+  integrity sha512-dYE8LhncfBUar6POCxMTm0Ln+erjeczqEvCJib5/7XNkdw1FkUGgwMPY360FY0FgPWQxHWCx29Jl3oejyGLM9Q==
   dependencies:
     js-base64 "^2.1.8"
     source-map "^0.4.2"
@@ -7135,8 +7175,8 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.3.0:
 
 semver@~5.3.0:
   version "5.3.0"
-  resolved "https://registry.npm.taobao.org/semver/download/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
-  integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
+  resolved "https://registry.npmmirror.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+  integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==
 
 send@0.17.1:
   version "0.17.1"
@@ -7393,8 +7433,8 @@ source-map-url@^0.4.0:
 
 source-map@^0.4.2:
   version "0.4.4"
-  resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
-  integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
+  resolved "https://registry.npmmirror.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+  integrity sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==
   dependencies:
     amdefine ">=0.0.4"
 
@@ -7580,14 +7620,23 @@ strict-uri-encode@^1.0.0:
 
 string-width@^1.0.1:
   version "1.0.2"
-  resolved "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
-  integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
+  resolved "https://registry.npmmirror.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==
   dependencies:
     code-point-at "^1.0.0"
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
 
-"string-width@^1.0.2 || 2", string-width@^2.0.0:
+"string-width@^1.0.2 || 2 || 3 || 4":
+  version "4.2.3"
+  resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
+string-width@^2.0.0:
   version "2.1.1"
   resolved "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
   integrity sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=
@@ -7671,10 +7720,17 @@ strip-ansi@^6.0.0:
   dependencies:
     ansi-regex "^5.0.0"
 
+strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 strip-bom@^2.0.0:
   version "2.0.0"
-  resolved "https://registry.npm.taobao.org/strip-bom/download/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
-  integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+  resolved "https://registry.npmmirror.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==
   dependencies:
     is-utf8 "^0.2.0"
 
@@ -7690,8 +7746,8 @@ strip-final-newline@^2.0.0:
 
 strip-indent@^1.0.1:
   version "1.0.1"
-  resolved "https://registry.npm.taobao.org/strip-indent/download/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
-  integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
+  resolved "https://registry.npmmirror.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+  integrity sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==
   dependencies:
     get-stdin "^4.0.1"
 
@@ -7761,8 +7817,8 @@ tapable@^1.0.0, tapable@^1.1.3:
 
 tar@^2.0.0:
   version "2.2.2"
-  resolved "https://registry.npm.taobao.org/tar/download/tar-2.2.2.tgz?cache=0&sync_timestamp=1597445446483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftar%2Fdownload%2Ftar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
-  integrity sha1-DKiEhWLHKZuLRG/2pNYM27I+3EA=
+  resolved "https://registry.npmmirror.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
+  integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
   dependencies:
     block-stream "*"
     fstream "^1.0.12"
@@ -7939,13 +7995,13 @@ tough-cookie@~2.5.0:
 
 trim-newlines@^1.0.0:
   version "1.0.0"
-  resolved "https://registry.npm.taobao.org/trim-newlines/download/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
-  integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
+  resolved "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+  integrity sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==
 
 "true-case-path@^1.0.2":
   version "1.0.3"
-  resolved "https://registry.npm.taobao.org/true-case-path/download/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
-  integrity sha1-+BO1qMhrQNpZYGcisUTjIleZ9H0=
+  resolved "https://registry.npmmirror.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
+  integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==
   dependencies:
     glob "^7.1.2"
 
@@ -8552,11 +8608,11 @@ which@^2.0.1:
     isexe "^2.0.0"
 
 wide-align@^1.1.0:
-  version "1.1.3"
-  resolved "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
-  integrity sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=
+  version "1.1.5"
+  resolved "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
+  integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
   dependencies:
-    string-width "^1.0.2 || 2"
+    string-width "^1.0.2 || 2 || 3 || 4"
 
 worker-farm@^1.7.0:
   version "1.7.0"