lion 3 years ago
parent 3c52374634
commit 3b08287552

@ -2,5 +2,5 @@
ENV = 'development'
# base api
VUE_APP_BASE_API = http://starter.ali251.langye.net
VUE_APP_UPLOAD_API = http://starter.ali251.langye.net/api/admin/upload-file
VUE_APP_BASE_API = http://h5.ali251.langye.net/
#VUE_APP_UPLOAD_API = http://starter.ali251.langye.net/api/admin/upload-file

@ -2,5 +2,6 @@
ENV = 'production'
# base api
VUE_APP_BASE_API = http://starter.ali251.langye.net
VUE_APP_UPLOAD_API =http://starter.ali251.langye.net/api/admin/upload-file
#VUE_APP_BASE_API = http://starter.ali251.langye.net
VUE_APP_BASE_API = http://h5.ali251.langye.net/
#VUE_APP_UPLOAD_API =http://starter.ali251.langye.net/api/admin/upload-file

@ -0,0 +1,19 @@
import request from '@/utils/request'
export function listProject(params) {
return request({
url: '/api/admin/pms/item',
method: 'get',
params:params
})
}
export function listStatus(params) {
return request({
url: '/api/admin/pms/status',
method: 'get',
params:params
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -26,6 +26,10 @@ export default {
default: () => {
}
},
stripe:{
type: Boolean,
default: false
},
headerRowStyle: {
type: Function,
default: () => {
@ -192,6 +196,7 @@ export default {
defaultExpandAll,
headerCellStyle,
headerRowStyle,
stripe,
rowStyle,
cellStyle,
indent,
@ -212,6 +217,7 @@ export default {
summary-method={summaryMethod}
header-row-style={headerRowStyle}
header-cell-style={headerCellStyle}
stripe={stripe}
row-style={rowStyle}
cell-style={cellStyle}
indent={indent}

@ -8,7 +8,7 @@ import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // no redirect whitelist
const whiteList = ['/login','/board'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// start progress bar

@ -40,6 +40,12 @@ export const constantRoutes = [{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/board',
component: () => import('@/views/board/board'),
hidden: true
},
{

@ -14,7 +14,7 @@ let loading ;
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000, // request timeout
timeout: 50000, // request timeout
isLoading:true
})

@ -0,0 +1,221 @@
<template>
<div class="boardwrap">
<div class="boardheader">
<img :src="boardLogo" alt="">
</div>
<div class="board">
<div class="boardselect">
<div class="changeboard">
<span :class="board=='status'?'active':''" @click="showBoard('status')"></span>
<span :class="board=='project'?'active':''" @click="showBoard('project')"></span>
</div>
<div>
<span>任务创建日期</span>
<el-date-picker
@change="boardTime"
v-model="daterange"
type="daterange"
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</div>
</div>
<div v-if="board=='status'">
<status :list="list" :waitNum="waitNum" :doingNum="doingNum" :doneNum="doneNum"></status>
</div>
<div v-else-if="board=='project'">
<project :list="proList"></project>
</div>
</div>
</div>
</template>
<script>
import {
listStatus
} from "@/api/board/board.js"
import {
listProject
} from "@/api/board/board.js"
import status from './components/status.vue'
import project from './components/project.vue'
export default {
components:{
status,
project
},
data() {
return {
boardLogo:require('@/assets/boardlogo.png'),
board:"status",
daterange:['',''],
list: [],
proList:[],
waitNum:0,
doingNum:0,
doneNum:0,
}
},
created() {
this.$nextTick(function(){
this.loadStatus()
this.loadProject()
// this.board = 'status'
})
},
methods: {
//
loadStatus() {
listStatus({
start_date:this.daterange[0],
end_date:this.daterange[1]
}).then(res => {
this.list = this.reloadStatus(res)
})
},
reloadStatus(arr) {
let newArr = []
let waitArr = []
let doingArr = []
let doneArr = []
this.waitNum = 0
this.doingNum = 0
this.doneNum = 0
for (var m of arr) {
if (m['wait']) {
waitArr.push(m)
}
if (m['doing']) {
doingArr.push(m)
}
if (m['done']) {
doneArr.push(m)
}
}
waitArr.map((wait,index) => {
this.waitNum = this.waitNum + wait['wait']['total']
doingArr.map((doing) => {
if(index==0){
this.doingNum = this.doingNum + doing['doing']['total']
}
if (wait['wait']['project_name'] === doing['doing']['project_name']) {
newArr.push({
project_name: wait['wait']['project_name'],
wait: wait['wait'],
doing: doing['doing']
})
}
})
})
newArr.map((newa,index)=>{
doneArr.map((done) => {
if(index==0){
this.doneNum = this.doneNum + done['done']['total']
}
if (newa['project_name'] === done['done']['project_name']) {
newa['done'] = done['done']
}
})
})
return newArr
},
//
loadProject(){
listProject({
start_date:this.daterange[0],
end_date:this.daterange[1]
}).then(res => {
this.proList = this.reloadProject(res)
})
},
reloadProject(arr){
let newArr = []
let name = ""
let num = -1
let oldArr = arr
for(let m of arr){
for (let item in m) {
if(name!=m.project_name){
name = m.project_name
num++
newArr[num] = {};
}else{
newArr[num]['project_name'] = m['project_name']
newArr[num][m['name']] = m
}
}
}
return newArr
},
//
showBoard(val){
this.board = val
},
boardTime(val){
if(val){
this.daterange=val
}else{
this.daterange=['','']
}
if(this.board=='status'){
this.loadStatus()
}else{
this.loadProject()
}
},
}
}
</script>
<style scoped>
.boardwrap{
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}
.boardheader{
background: #fff;
font-size: 0;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
}
.boardheader img{
width:20%;
max-width: 342px;
max-height: 100px;
}
.board{
padding:20px;
margin:30px;
background: #fff;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
border-radius: 10px;
}
.boardselect{
width:100%;
display: flex;
justify-content: space-between;
margin-bottom:20px
}
.boardselect .changeboard{
background: #f8f8f8;
border-radius: 20px;
}
.boardselect .changeboard span{
line-height: 40px;
padding:0 20px;
display: inline-block;
cursor: pointer;
}
.boardselect .changeboard span.active{
background-color: #d70c25;
color:#fff;
border-radius: 20px;
/* background: radial-gradient(circle at -30px center, transparent 40px, orange 0);
border-radius: 0 30px 30px 0; */
}
</style>

@ -0,0 +1,186 @@
<template>
<div>
<xy-table ref="xyTable" :stripe="true" :header-cell-style="headerStyle" :cell-style="cellStyle" :list="list"
:is-page="false" :table-item="tableColumn">
<template v-slot:btns>
<div></div>
</template>
</xy-table>
</div>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => []
}
// tableColumn: {
// type: Array,
// default: () => []
// }
},
data() {
return {
tableColumn:[
{
label: "项目",
prop: 'project_name',
align: 'left',
width:200,
fixed:"left"
},
]
}
},
created() {
this.$nextTick(function(){
this.creatCustom()
})
},
watch: {
list(val) {
this.$nextTick(function(){
this.creatCustom()
})
}
},
methods: {
headerStyle({
row,
column,
rowIndex,
columnIndex
}) {
return {
backgroundColor: '#d70c25!important',
color: '#fff',
border: "none",
lineHeight: "40px",
fontSize: "15px",
textAlign:"left"
}
},
cellStyle() {
return {
border: "none",
lineHeight: "40px",
fontSize: "15px"
}
},
creatCustom() {
this.tableColumn=[
{
label: "项目",
prop: 'project_name',
align: 'left',
width:200,
sortable: false,
fixed:"left"
}
]
if(this.list.length==0){
this.tableColumn=[]
return
}
// return
let that = this
for(let item in this.list[0]){
if (item != 'project_name') {
if (item == '合计') {
this.tableColumn.push({
label: item,
prop: item+'.total',
align: "left",
sortable: false,
fixed: 'right',
width: 220,
customFn:(cell)=>{
// let ingtotal = cell[item].design_total + cell[item].devel_total
let proPer = parseInt((cell[item].end_total/cell[item].total)*100)
proPer = isNaN(proPer)?0:proPer
return ( <div class="prototal">
<div class="proinfo">
{
!isNaN(proPer)?
<div>
<span class="fontColor">{cell[item].total}</span>
<span>/{cell[item].end_total}</span>
</div>
:""
}
{
cell[item].design_total>0?<div> {cell[item].design_total}个设计任务 </div>:""
}
{
cell[item].devel_total>0?<div> {cell[item].devel_total}个开发任务 </div>:""
}
</div>
<div class="progress">
<el-progress color="#d70c25" width={60} type="circle" percentage={proPer}></el-progress>
</div>
</div>
)
}
})
} else {
this.tableColumn.push({
label: item,
prop: item+'.devel_total',
align: "left",
sortable: false,
width: 180,
customFn:(cell)=>{
// let ingtotal = cell[item].design_total + cell[item].devel_total
let proPer = parseInt((cell[item].end_total/cell[item].total)*100)
return ( <div>
{
!isNaN(proPer)?
<div>
<span class="fontColor">{cell[item].total}</span>
<span>/{cell[item].end_total}</span>
</div>
:""
}
{
cell[item].design_total>0?<div> {cell[item].design_total}个设计任务 </div>:""
}
{
cell[item].devel_total>0?<div> {cell[item].devel_total}个开发任务 </div>:""
}
</div>
)
}
})
}
}
}
},
}
}
</script>
<style scoped>
.fontColor {
color: #d70c25;
font-size: 24px
}
.prototal{
display: flex;
justify-content: space-between;
vertical-align: middle;
}
.proinfo{
width:110px;
display: inline-block;
}
.progress{
/* vertical-align: super; */
display: inline-block;
margin-left: 20px;
}
</style>

@ -0,0 +1,349 @@
<template>
<div>
<xy-table ref="xyTable" :stripe="true" :header-cell-style="headerStyle" :cell-style="cellStyle" :list="list"
:is-page="false" :table-item="tableColumn">
<template v-slot:btns>
<div></div>
</template>
</xy-table>
</div>
</template>
<script>
// import render from '@/components/LxTableRender/render'
export default {
props: {
list: {
type: Array,
default: () => []
},
waitNum:{
type:Number,
default:0
},
doingNum:{
type:Number,
default:0
},
doneNum:{
type:Number,
default:0
}
},
data() {
return {
// list: [],
tableColumn: [{
label: "项目",
prop: 'project_name',
align: 'left',
sortable: false,
fixed: "left",
// width: 200
},
{
label: `未开始(${this.waitNum})`,
prop: 'wait.total',
align: 'center',
width: 240,
sortable: false,
customFn: (cell) => {
return this.customFunc(cell,'wait')
}
},
{
label: `进行中(${this.doingNum})`,
prop: 'doing.total',
align: 'center',
sortable: false,
width: 240,
customFn: (cell) => {
return this.customFunc(cell,'doing')
}
},
{
label: `已完成(${this.doneNum})`,
prop: 'done.total',
align: 'center',
sortable: false,
width: 240,
customFn: (cell) => {
return this.customFunc(cell,'done')
}
},
{
label: "已关闭",
prop: 'money',
align: 'center',
sortable: false,
width: 220,
},
{
label: "合计",
prop: 'total',
align: 'center',
sortable: false,
fixed:'left',
width:200,
customFn: (cell) => {
let totals = cell['wait']['total'] + cell['doing']['total'] + cell['done']['total']
let proPer = parseInt((cell['done'].total/totals)*100)
proPer = isNaN(proPer)?0:proPer
let designTotal=0
let develTotal = 0
let arrs = [cell['wait']['detail'],cell['doing']['detail'],cell['done']['detail']]
arrs.map((item,index)=>{
for (var k in item) {
designTotal = item[k]['type'] == 'ui' ? designTotal+1 : designTotal
develTotal = item[k]['type'] == 'devel' ? develTotal+1 : develTotal
}
})
return ( <div class="prototal">
< div class="proinfo">
{
!isNaN(proPer)?
<div>
<span class="fontColor">{totals}</span>
<span>/{cell['done']['total']}</span>
</div>
:""
}
{
designTotal>0?<div> {designTotal}个设计任务 </div>:""
}
{
develTotal>0?<div> {develTotal}个开发任务 </div>:""
}
</div>
<div class="progress">
<el-progress color="#d70c25" width={60} type="circle" percentage={proPer}></el-progress>
</div>
</div>
)
}
}
],
}
},
created() {
},
watch:{
waitNum(newval,oldval){
console.log(newval,oldval)
if(newval!=oldval){
this.waitNum = newval
this.tableColumn[1].label = `未开始(${this.waitNum})`
}
},
doingNum(newval,oldval){
if(newval!=oldval){
this.doingNum = newval
this.tableColumn[2].label = `进行中(${this.doingNum})`
}
},
doneNum(newval,oldval){
if(newval!=oldval){
this.doneNum = newval
this.tableColumn[3].label = `已完成(${this.doneNum})`
}
}
},
methods: {
headerStyle({
row,
column,
rowIndex,
columnIndex
}) {
return {
backgroundColor: '#d70c25!important',
color: '#fff',
border: "none",
lineHeight: "40px",
fontSize: "15px"
}
},
cellStyle() {
return {
border: "none",
lineHeight: "40px",
fontSize: "15px"
}
},
customFunc(cell,type) {
let wait = cell[type]['detail']
let copyWait = []
//
for (var k in wait) {
wait[k]['typeName'] = wait[k]['type'] == 'devel' ? "开发" : (wait[k]['type'] == 'ui' ? '设计' : '')
copyWait.push({
name: wait[k]['name'],
assignedTo: wait[k]['assignedTo'],
typeName: wait[k]['typeName'],
type:wait[k]['type']
})
}
//
let shareArr = []
copyWait = copyWait.map(function(item, index, arr) {
const i = copyWait.find(_item => item.assignedTo === _item.assignedTo);
if (i !== item) {
i.task.push(item.name);
if(i.typeName !== item.typeName){
i.otherTypeName = item.typeName
}
return undefined;
} else {
i.task = [i.task];
return i;
}
}).filter(item => item !== undefined);
console.log(copyWait)
return (
copyWait.map((item, index) => {
return ( <Poptip trigger = "hover"
placement = "right"
transfer >
<div class = "boardcard" >
<div class = "cardc" >
<span class = {
(item.task.length > 2 ? 'cardc3' : (item.task.length == 2 ? 'cardc2' : 'cardc1'))
} > {
item.task.length
} </span>
</div>
<div class = "cardinfo" >
<div class = "cardname" >
<span > {
item.assignedTo
} </span> <span class = "cardtype" > {
item.typeName ? item.typeName : "未知"
} {
item.otherTypeName?" "+item.otherTypeName:""
}</span>
</div> <div class = "cardfirst" > {
item.name
} </div>
</div>
</div>
<div slot = "content" >
<div > {
item.name
}
</div>
{
item.task.map((board, key) => {
return (
<div > {
board
}
</div>
)
})
}
</div>
</Poptip>
)
})
) //return
}
}
}
</script>
<style scoped>
.boardcard {
display: flex;
background: #fff;
box-shadow: 0 1px 11px rgb(215 12 37 / 25%);
border-radius: 5px;
padding: 10px;
font-size: 16px;
/* width: 200px; */
height: 66px;
margin: 10px 0;
cursor: pointer;
}
.cardc {
line-height: 50px;
margin-right: 10px;
}
.cardc span {
width: 28px;
height: 28px;
border-radius: 14px;
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
color: #fff;
line-height: 28px;
text-align: center;
font-size: 16px;
display: inline-block;
}
.cardc1 {
background-image: linear-gradient(to right, #47c77a, #3fb46d);
}
.cardc2 {
background-image: linear-gradient(to right, #f8b83b, #fe8a07);
}
.cardc3 {
background-image: linear-gradient(to right, #dc1b33, #ee5467);
}
.cardinfo {
text-align: left;
}
.cardname {
color: #d70c25;
}
.cardtype {
color: #333;
padding: 2px 10px;
border-radius: 15px;
border: 1px solid #d70c25;
margin-left: 5px
}
.cardfirst {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 160px;
margin-top: 3px;
}
.fontColor {
color: #d70c25;
font-size: 24px
}
.prototal{
display: flex;
justify-content: space-between;
vertical-align: middle;
}
.proinfo{
width:110px;
display: inline-block;
text-align: left;
}
.progress{
/* vertical-align: super; */
display: inline-block;
margin-left: 20px;
}
</style>
Loading…
Cancel
Save