977 lines
25 KiB
Vue

<template>
<view class="fullHeight workStationIndexPage">
<headers :navList="navList">
</headers>
<scroll-view class="smallHeight" scroll-y>
<view class="stations-nav">
<view class="headers_statistics">
<ul>
<li>
进行中
<span>{{ peddingNum }}</span>
</li>
<li class="item_center">
已完成
<span>{{ closeNum }}</span>
</li>
<li>
已延期
<span>{{ postponeNum }}</span>
</li>
</ul>
</view>
<view class="list_title">
<view class="list_h2">{{ listTitle }}</view>
<view class="list_btn">
<ul>
<li v-for="(item, index) in listNav" :class="[true ? 'nav'+index : '', opType == index+1 ? 'activeNav' : '']" :ref="'nav'+index" :key="index" @click="checkTab(index)">{{ item.name }}</li>
</ul>
</view>
</view>
</view>
<view class="card_box" v-if="cardList.length > 0">
<view class="card_list">
<view class="card_wrapper" v-for="(item, index) in cardList" :key="index">
<view class="card_item">
<view class="card_status">
<span class="card_date">{{ item.endDayNum }}天</span>
<!-- <span v-if="item.status == 0" class="card_action">审批</span> -->
<span v-if="item.taskLevel == 1" class="card_ordinary">一般</span>
<span v-if="item.taskLevel == 2" class="card_danger">重要</span>
</view>
<view class="card_wrap" @click="showCard(item,index)">
<view class="card_content">{{ item.taskTitle }}</view>
<view class="card_plan">
<view class="card_num">
子任务数量:
<span>{{ item.subtask.totalnum }}</span>
</view>
<view class="card_people" v-if="item.taskUserName">
<span v-for="(itm, idx) in item.peopleList" :key="idx">{{ itm }}</span>
<view class="more">...</view>
</view>
</view>
<view class="card_progress">
<view class="progress"><view class="progress_content" :style="{ width: item.subtask.completeratio + '%' }"></view></view>
<span>{{ item.subtask.completeratio }}%</span>
</view>
</view>
<view class="card_radio" :class="[true ? 'radio'+index : '']" :ref="'radio'+[index]" @click="checkFinish(item,index)">
<image v-if="item.taskState == 1" src="/static/workstation/card_radio_uncheck.png"></image>
<image v-else src="/static/workstation/card_radio_check.png"></image>
</view>
<view class="card_bottom" v-if="item.children.length > 0 && item.isShow">
<span></span>
<span></span>
</view>
</view>
<uni-transition ref="ani" :show="item.children.length > 0" :duration="1000">
<view class="card_detail" :class="[ item.isShow && item.children.length > 0 ?'card_show': '', item.isShow ? 'card'+index : '']" :style="{'height':item.height, 'padding': item.padding}" :ref="'card'+index">
<view class="card_top" v-if="item.children.length > 0">
<span></span>
<span></span>
</view>
<view class="detail_list">
<view class="detail_item" v-for="(item2, index2) in item.children" :key="index2">
<view class="detail_status">
<span>{{ item2.endDayNum }}</span>
</view>
<view class="flex">
<view class="detail_radio" @click="checkChild(item2,index)">
<span v-if="item2.subtaskState == 1" class="detail_uncheck"></span>
<span v-else><image src="/static/workstation/card_radio_check.png"></image></span>
</view>
<view class="detail_lable" @click="previewData(item)">
<view class="detail_text">{{ item2.subtaskTitle }}</view>
<view class="flex">
<view class="detail_progress">
<view class="progress"><view class="progress_content" :style="{ width: item2.progressRatio + '%' }"></view></view>
<span>{{ item2.progressRatio }}%</span>
</view>
<view class="detail_people">
<span>{{ item2.subtaskDistributeName.substring(0,1) }}</span>
<view class="more">...</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</uni-transition>
</view>
</view>
</view>
<view class="no-data" v-else>暂无数据</view>
<view class="add_btn" @click="addProject">
<span>+</span>
新建任务
</view>
</scroll-view>
<footers2></footers2>
<view class="finish_radio" :style="{'display': moveStyle.display, 'bottom': moveStyle.bottom, 'left': moveStyle.left, 'top': moveStyle.top}">
<image src="/static/workstation/card_radio_check.png"></image>
</view>
</view>
</template>
<script>
import footers2 from '../../../components/footers/footers2.vue';
import headers from '../headers.vue';
export default {
data() {
return {
listTitle: '任务列表',
listNav: [
{
name: '已完成'
},
{
name: '未完成'
}
],
navList: [
{
name: "任务清单"
},
{
name: "通知公告"
},
{
name: "工作日程"
}
],
peddingNum: '0',
closeNum: '0',
postponeNum: '0',
opType: 2,
ischeck: true,
cardList: [],
userInfo: "",
projectSn: "",
pageNo: 1,
pageSize: 100,
total: 0,
timer: null,
moveStyle:{
display: 'none',
bottom: 0,
left: 0,
top: null
}
};
},
components: {
footers2,
headers
},
onReady(){
// let query = uni.createSelectorQuery().in(this).select('.add_btn');
// console.log(query)
// query.boundingClientRect(data => {
// console.log(data);
// }).exec();
},
created(){
this.userInfo = JSON.parse(uni.getStorageSync('userInfo'))
this.projectSn = this.userInfo.sn
console.log(this.projectSn)
this.loadData()
this.selectWorkerTotal()
},
onReachBottom() {
console.log(1)
this.loadData()
},
methods: {
previewData(val){
uni.navigateTo({
url:'./editProject?id='+ val.id
})
},
loadData(callback){
let data = {
projectSn: this.projectSn,
pageNo: 1,
pageSize: 1000,
opType: this.opType
}
let _this = this
this.sendRequest({
url: "xmgl/workstationTaskRecord/selectWorkstationTaskPageList",
data: data,
method: "POST",
success(res){
// console.log(res.result.records)
_this.total = res.result.total
res.result.records.forEach(item=>{
let peopleArr = []
if (item.taskUserName){
item.taskUserName.split(',').forEach(itm=>{
peopleArr.push(itm.substring(0,1))
})
}
item.peopleList = peopleArr
item.children = []
item.isShow = false
})
_this.cardList = res.result.records
if(callback){
callback();
}
// console.log(_this.cardList)
}
})
// console.log(this.cardList)
},
selectWorkerTotal(){
let _this = this
this.sendRequest({
url: "xmgl/workstationTaskRecord/selectWorkstationTaskCount",
data: {projectSn: this.projectSn},
method: "POST",
success(res){
// console.log(res)
if(res.code == 200){
_this.peddingNum = res.result.notCompleteTaskNum
_this.closeNum = res.result.completeTaskNum
_this.postponeNum = res.result.overdueTaskNum
}
}
})
},
checkTab(index){
this.opType = index + 1
this.loadData()
},
checkChild(item, index){
console.log(item)
item.subtaskState = item.subtaskState == 1 ? 2 : 1
let allCheck = false
let _this = this
this.sendRequest({
url: "xmgl/workstationSubtask/edit",
data: {
// projectSn: this.projectSn,
id: item.id,
subtaskState: item.subtaskState,
taskId: item.taskId
},
method: "POST",
success(res){
// console.log(res)
let callback = ()=>{
_this.$nextTick(()=>{
_this.showCard(_this.cardList[index], index)
})
}
_this.loadData(callback)
}
})
// item.isCheck = !item.isCheck
// let allCheck = false
// for (let i = 0; i<this.cardList[index].children.length; i++){
// if(this.cardList[index].children[i].isCheck) {
// allCheck = true
// } else {
// allCheck = false;
// this.cardList[index].isFinish = false
// return;
// }
// }
// if(allCheck && !this.cardList[index].isFinish){
// this.checkFinish(this.cardList[index],index);
// }
},
showCard(item, index){
// console.log(item)
item.isShow = !item.isShow
let _this = this
this.sendRequest({
url: "xmgl/workstationSubtask/selectSubtaskList",
data: {taskId: item.id},
method: "POST",
success(res){
// console.log(res.result)
if(res.result.length> 0){
item.children = res.result
// console.log(_this.cardList)
// let query = uni.createSelectorQuery()
// let data = query.select('card'+index)
// data.boundingClientRect()
// query.exec(function(res){
// console.log(res)
// })
// console.log(data)
_this.$nextTick(()=>{
let height = 0
if(item.children.length > 0){
// console.log(this.$refs['card'+index][0], e)
if(item.isShow){
// let obj = uni.createSelectorQuery().select('.card'+index)
// obj.boundingClientRect(function(data) { // data - 各种参数
// height = data.height + 37
// item.height = height + 'px'
// console.log(item.height)
// that.movableBoxTop = data.top;
// }).exec()
// console.dir(_this)
// _this.$refs['card'+index][0].$el.style.padding = "20rpx 11px 36rpx 26rpx";
} else {
// console.log(1)
if(_this.timer){
_this.timer = null
}
// item.height = '0px'
// item.padding = 0
_this.timer = setTimeout(()=>{
item.children = []
},400)
}
}
})
} else {
if(uni.getStorageSync('attendee')){
uni.removeStorage({
key: 'attendee',
success: function (res) {
console.log('success');
}
})
}
uni.navigateTo({
url: './editProject?id='+item.id
})
}
}
})
// let data = uni.createSelectorQuery().select('card'+index)
// this.$nextTick(()=>{
// let height = 0
// if(item.children.length > 0){
// // console.log(this.$refs['card'+index][0], e)
// if(item.isShow){
// height = this.$refs['card'+index][0].$el.offsetHeight + 37
// this.$refs['card'+index][0].$el.style.height = height + 'px'
// } else {
// this.$refs['card'+index][0].$el.style.height = 0
// }
// }
// })
// console.log(this.$refs['card'+index][0], e)
},
addProject(){
if(uni.getStorageSync('attendee')){
uni.removeStorage({
key: 'attendee',
success: function (res) {
console.log('success');
}
})
}
uni.navigateTo({
url: './addProject'
})
},
checkFinish(item,index){
console.log(item)
item.taskState = item.taskState == 1 ? 2 : 1
let _this = this
this.sendRequest({
url: "xmgl/workstationTaskRecord/updateTaskRecord",
data: {
projectSn: this.projectSn,
id: item.id,
taskState: item.taskState
},
method: "POST",
success(res){
console.log(res)
if(res.code == 200){
for (let i = 0; i<_this.cardList[index].children.length; i++){
_this.cardList[index].children[i].subtaskState = item.taskState
}
if(item.taskState == 2){
_this.$nextTick(()=>{
let dom = _this.$refs['radio'+index][0].$el
_this.moveDom(dom,index)
setTimeout(()=>{
_this.loadData()
}, 1000)
})
} else {
_this.loadData()
}
}
}
})
// for (let i = 0; i<this.cardList[index].children.length; i++){
// if(item.isFinish) {
// this.cardList[index].children[i].isCheck = true
// } else {
// this.cardList[index].children[i].isCheck = false;
// }
// }
// console.log(this.$refs['radio'+index][0])
// if(item.isFinish){
// let dom = this.$refs['radio'+index][0].$el
// this.moveDom(dom,index)
// }
},
moveDom(dom,index){
let startData = {}
let targetData = {}
let moveData = {}
let getStartData = new Promise((res)=>{
let obj = uni.createSelectorQuery().select('.radio'+index)
obj.boundingClientRect(function(data) { // data - 各种参数
// console.log(JSON.stringify(data))
res(data)
// that.movableBoxTop = data.top;
}).exec()
}).then(data=>{
startData = data
let gettargetData = new Promise((res)=>{
let obj2 = uni.createSelectorQuery().select('.nav0')
obj2.boundingClientRect(function(data) { // data - 各种参数
// console.log(JSON.stringify(data))
res(data)
// that.movableBoxTop = data.top;
}).exec()
}).then(data=>{
console.log(data)
targetData = data
let getMoveData= new Promise((res)=>{
let obj3 = uni.createSelectorQuery().select('.finish_radio')
obj3.boundingClientRect(function(data) { // data - 各种参数
// console.log(JSON.stringify(data))
res(data)
// that.movableBoxTop = data.top;
}).exec()
}).then(data=>{
console.log(data)
moveData = data
var timer = null,
timer2 = null;
// moveDom.style.display = 'block';
this.moveStyle.display = 'block';
this.moveStyle.left = startData.left + 'px';
this.moveStyle.left = startData.top + 'px';
// moveDom.style.left = startDom.getBoundingClientRect().left + 'px';
// moveDom.style.top = startDom.getBoundingClientRect().top + 'px';
// 获取起始位置
var nStartX = startData.left,
nStartY = startData.top;
// var nStartX = startDom.getBoundingClientRect().left,
// nStartY = startDom.getBoundingClientRect().top;
// console.log(nStartX,nStartY)
// 获取终点位置
var nEndX = targetData.left,
nEndY = targetData.top,
// var nEndX = targetDom.getBoundingClientRect().left,
// nEndY = targetDom.getBoundingClientRect().top,
nTopX = nEndX - 8,
nTopY = nEndY - 8;
var a = ((nStartY - nEndY) * (nStartX - nTopX) - (nStartY - nTopY) * (nStartX - nEndX)) / ((nStartX * nStartX - nEndX * nEndX) * (nStartX - nTopX) - (nStartX * nStartX - nTopX * nTopX) * (nStartX - nEndX));
var b = ((nEndY - nStartY) - a * (nEndX * nEndX - nStartX * nStartX)) / (nEndX - nStartX);
var c = nStartY - a * nStartX * nStartX - b * nStartX;
var x = nStartX;
let _this = this
// console.log(nEndY, nEndX)
timer = setInterval(function() {
x+= 5;
var y = a * x * x + b * x + c;
if (x >= nEndX) {
x = nEndX;
y = nEndY;
_this.moveStyle.display = 'none'
clearInterval(timer);
}
// console.log( _this.moveStyle.left,_this.moveStyle.top)
_this.moveStyle.left = x + 'px';
_this.moveStyle.top = y + 'px';
}, 10)
// console.log(startData,targetData,moveData)
})
})
})
// let obj2 = uni.createSelectorQuery().select('.nav0')
// obj2.boundingClientRect(function(data) { // data - 各种参数
// // console.log(JSON.stringify(data))
// targetData = data
// // that.movableBoxTop = data.top;
// }).exec()
// let obj3 = uni.createSelectorQuery().select('.finish_radio')
// obj3.boundingClientRect(function(data) { // data - 各种参数
// // console.log(JSON.stringify(data))
// moveData = data
// // that.movableBoxTop = data.top;
// }).exec()
// let obj = uni.createSelectorQuery().select('.finish_radio')
// obj.boundingClientRect(function(data) { // data - 各种参数
// console.log(JSON.stringify(data))
// // that.movableBoxTop = data.top;
// }).exec()
// var startDom = dom;
// var targetDom = this.$refs['nav0'][0];
// var moveDom = document.querySelector('.finish_radio');
// console.log(targetDom)
}
},
};
</script>
<style lang="scss" scoped>
.smallHeight {
height: calc(100% - 54rpx);
box-sizing: border-box;
}
.flex {
display: flex;
}
.add_btn {
position: fixed;
right: 12rpx;
bottom: 124rpx;
// width: 84rpx;
// height: 84rpx;
width: 124rpx;
height: 124rpx;
display: flex;
font-size: 16rpx;
background: #fff;
border-radius: 50%;
border: 8rpx solid rgba(18, 127, 236, 0.08);
color: #127fec;
flex-direction: column;
align-items: center;
justify-content: center;
span {
font-size: 20rpx;
}
}
.workStationIndexPage {
padding-top: 220rpx;
box-sizing: border-box;
background: #f6f6f6;
:deep( .headers_box ){
// padding-bottom: 72rpx;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 2;
}
.stations-nav{
background: #127FEC;
padding-bottom: 60rpx;
border-radius: 0px 0px 40rpx 40rpx;
}
.headers_statistics {
margin-bottom: 30rpx;
ul {
display: flex;
align-items: center;
justify-content: center;
list-style: none;
width: 100%;
height: 54rpx;
padding: 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
border-top: 1px solid rgba(255, 255, 255, 0.2);
li {
flex: 1;
color: rgba(255, 255, 255, 0.6);
line-height: 54rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
span {
font-size: 36rpx;
color: #fff;
margin-left: 20rpx;
}
}
.item_center {
border-left: 1px solid rgba(255, 255, 255, 0.2);
border-right: 1px solid rgba(255, 255, 255, 0.2);
}
}
}
.list_title {
display: flex;
align-items: center;
justify-content: space-between;
.list_h2 {
color: #fff;
font-size: 30rpx;
font-weight: 500;
margin-left: 54rpx;
}
.list_btn {
margin-right: 30rpx;
ul {
list-style: none;
display: flex;
justify-content: center;
align-items: center;
border-radius: 12rpx;
background: rgba(255, 255, 255, 0.2);
padding: 0;
overflow: hidden;
li {
color: rgba(255, 255, 255, 0.6);
width: 120rpx;
height: 46rpx;
line-height: 46rpx;
font-size: 28rpx;
text-align: center;
}
.activeNav {
background: #fff;
color: #127fec;
}
}
}
}
.card_box {
margin-top: -40rpx;
padding-bottom: 48rpx;
.card_list {
.card_item {
width: 666rpx;
margin: 0 auto;
background: #fff;
border-radius: 16rpx;
padding: 64rpx 22rpx 18rpx 26rpx;
box-sizing: border-box;
box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.1);
position: relative;
margin-bottom: 18rpx;
.card_status {
position: absolute;
right: 0;
top: 0;
overflow: hidden;
border-radius: 0 16rpx 0 0;
span {
font-size: 24rpx;
line-height: 48rpx;
display: inline-block;
height: 48rpx;
padding: 0 52rpx 0 16rpx;
margin-right: -40rpx;
border-radius: 0 0 0 16rpx;
}
.card_date {
background: #f3f8f5;
color: #68d199;
}
.card_action {
background: #ffe8db;
color: #fe9b65;
}
.card_ordinary {
background: #9293ed;
color: #fff;
}
.card_danger {
background: #fa8686;
color: #fff;
}
}
.card_content {
font-size: 30rpx;
margin-bottom: 16rpx;
padding-left: 34rpx;
}
.card_plan {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24rpx;
margin-bottom: 8rpx;
padding-left: 34rpx;
.card_num {
color: #6c7178;
span {
color: #2f3548;
margin-left: 4rpx;
}
}
.card_people {
display: flex;
align-items: center;
span {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
background: rgba(18, 127, 236, 0.1);
color: #127fec;
display: inline-block;
text-align: center;
line-height: 44rpx;
margin-right: 8rpx;
}
.more {
width: 44rpx;
height: 44rpx;
line-height: 44rpx;
color: #127fec;
text-align: center;
}
}
}
.card_progress {
display: flex;
justify-content: space-between;
align-items: center;
color: #68d198;
font-size: 24rpx;
padding-left: 34rpx;
margin-bottom: 22rpx;
.progress {
background: rgba(108, 113, 120, 0.2);
width: 512rpx;
height: 6rpx;
border-radius: 4rpx;
overflow: hidden;
.progress_content {
background: #68d199;
border-radius: 4rpx;
height: 10rpx;
}
}
}
.card_radio {
position: absolute;
left: -24rpx;
top: 50%;
transform: translateY(-50%);
width: 64rpx;
height: 64rpx;
image {
width: 100%;
height: 100%;
}
}
.card_bottom {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
span {
display: block;
width: 20rpx;
height: 20rpx;
box-shadow: inset 0px 1px 3px 0px rgba(0, 0, 0, 0.5);
border-radius: 50%;
}
}
}
.card_detail {
width: 666rpx;
background: #fff;
margin: 0 auto;
box-sizing: border-box;
border-radius: 16rpx;
margin-bottom: 18rpx;
.card_top {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 24rpx;
span {
display: block;
width: 20rpx;
height: 20rpx;
box-shadow: inset 0px 1px 3px 0px rgba(0, 0, 0, 0.5);
border-radius: 50%;
position: relative;
}
span:after {
content: ' ';
display: block;
width: 4rpx;
height: 74rpx;
background: #127fec;
position: absolute;
top: -64rpx;
left: 50%;
transform: translateX(-50%);
}
}
.detail_list {
.card_bottom {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
span {
display: block;
width: 20rpx;
height: 20rpx;
box-shadow: inset 0px 1px 3px 0px rgba(0, 0, 0, 0.5);
border-radius: 50%;
}
}
.detail_item {
width: 614rpx;
margin: 0 auto;
background: rgba(16, 126, 238, 0.04);
position: relative;
border-radius: 16rpx;
margin-bottom: 18rpx;
box-sizing: border-box;
padding: 40rpx 40rpx 22rpx 22rpx;
.detail_status {
position: absolute;
top: 0;
right: 0;
span {
background: rgba(18, 127, 236, 0.44);
color: #fff;
display: inline-block;
width: 56rpx;
height: 36rpx;
border-radius: 0 0 0 20rpx;
font-size: 20rpx;
text-align: center;
line-height: 36rpx;
}
}
.detail_radio {
span {
width: 36rpx;
height: 36rpx;
display: block;
margin-top: 20rpx;
margin-right: 22rpx;
}
.detail_uncheck {
border: 1px solid rgba(108, 113, 120, 0.3);
border-radius: 50%;
box-sizing: border-box;
}
image {
width: 48rpx;
height: 48rpx;
}
}
.detail_lable {
flex: 1;
}
.detail_text {
font-size: 28rpx;
margin-bottom: 12rpx;
}
.detail_progress {
display: flex;
justify-content: space-between;
align-items: center;
color: #127fec;
font-size: 24rpx;
.progress {
background: rgba(108, 113, 120, 0.2);
width: 192rpx;
height: 6rpx;
border-radius: 4rpx;
overflow: hidden;
margin-right: 24rpx;
.progress_content {
background: #127fec;
border-radius: 4rpx;
height: 10rpx;
}
}
}
.detail_people {
flex: 1;
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 24rpx;
color: #127fec;
span {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
background: rgba(18, 127, 236, 0.1);
display: inline-block;
text-align: center;
line-height: 44rpx;
margin-right: 8rpx;
}
.more {
width: 44rpx;
height: 44rpx;
line-height: 44rpx;
color: #127fec;
text-align: center;
}
}
}
}
}
}
}
}
// .card_wrap:hover .card_detail{
// transform: rotateX(0deg) !important;
// padding: 20rpx 22rpx 36rpx 26rpx !important;
// opacity: 1 !important;
// height: auto !important;
// }
.card_show {
transform: rotateX(0deg) !important;
padding: 20rpx 22rpx 36rpx 26rpx !important;
// opacity: 1 !important;
height: auto !important;
}
.card_wrapper{
// transform-style: preserve-3d;
transition: height 1s linear;
// margin-bottom: 18rpx;
// transform-origin: top;
}
.card_detail {
// padding: 0;
// opacity: 0;
// height: 0;
transform-style: preserve-3d;
transform-origin: top;
transform: rotateX(90deg);
transition: all 0.5s ease;
}
.finish_radio{
position: absolute;
bottom: 0;
left: 0;
width: 64rpx;
height: 64rpx;
display: none;
image{
width: 100%;
height: 100%;
}
}
.no-data{
text-align: center;
width: 100%;
margin-top: 100px;
}
</style>