禅道bug修复
This commit is contained in:
parent
4617310fe2
commit
60d9138ba2
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name" : "兰坪实名制",
|
||||
"appid" : "__UNI__FA2378B",
|
||||
"appid" : "__UNI__517BDE0",
|
||||
"description" : "兰坪实名制",
|
||||
"versionName" : "1.0.11",
|
||||
"versionCode" : 111,
|
||||
|
|
@ -102,33 +102,33 @@
|
|||
"icons" : {
|
||||
"ios" : {
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
"app@2x" : "",
|
||||
"app@3x" : "",
|
||||
"spotlight@2x" : "",
|
||||
"notification@2x" : "",
|
||||
"notification@3x" : "",
|
||||
"settings@2x" : "",
|
||||
"settings@3x" : "",
|
||||
"spotlight@3x" : ""
|
||||
},
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"appstore" : "",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
"app" : "",
|
||||
"app@2x" : "",
|
||||
"notification" : "",
|
||||
"notification@2x" : "",
|
||||
"proapp@2x" : "",
|
||||
"settings" : "",
|
||||
"settings@2x" : "",
|
||||
"spotlight" : "",
|
||||
"spotlight@2x" : ""
|
||||
}
|
||||
},
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
"hdpi" : "",
|
||||
"xhdpi" : "",
|
||||
"xxhdpi" : "",
|
||||
"xxxhdpi" : ""
|
||||
}
|
||||
},
|
||||
"splashscreen" : {
|
||||
|
|
|
|||
1188
pages/login.vue
1188
pages/login.vue
File diff suppressed because it is too large
Load Diff
|
|
@ -1,368 +1,390 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar class="u-navbar" title="日计划制定" placeholder @leftClick="leftClick" leftIconColor="#fff"
|
||||
bgColor="#00337A" :titleStyle="{ color: '#FFF', fontSize: '32rpx' }" />
|
||||
<!-- Project Header -->
|
||||
<view class="project-header">
|
||||
<text class="project-title">{{proName}}</text>
|
||||
<!-- <view class="completion-rates">
|
||||
<view class="container">
|
||||
<u-navbar
|
||||
class="u-navbar"
|
||||
title="日计划制定"
|
||||
placeholder
|
||||
@leftClick="leftClick"
|
||||
leftIconColor="#fff"
|
||||
bgColor="#00337A"
|
||||
:titleStyle="{ color: '#FFF', fontSize: '32rpx' }"
|
||||
/>
|
||||
<!-- Project Header -->
|
||||
<view class="project-header">
|
||||
<text class="project-title">{{ proName }}</text>
|
||||
<!-- <view class="completion-rates">
|
||||
<text>作业计划完成率:70%</text>
|
||||
<text>月作业计划完成率:70%</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Total Plan Input -->
|
||||
<view class="total-plan">
|
||||
<text>计划作业人数:</text>
|
||||
<input type="number" v-model="totalPlan" class="total-input" />
|
||||
</view>
|
||||
<!-- Total Plan Input -->
|
||||
<view class="total-plan">
|
||||
<text>计划作业人数:</text>
|
||||
<input type="number" v-model="totalPlan" class="total-input" />
|
||||
</view>
|
||||
|
||||
<!-- Project Table -->
|
||||
<view class="table-container">
|
||||
<view class="table-header">
|
||||
<text class="col-index">序号</text>
|
||||
<text class="col-name">项目名称</text>
|
||||
<text class="col-desc">项目描述</text>
|
||||
<text class="col-completion">本日计划完成量</text>
|
||||
</view>
|
||||
<!-- Project Table -->
|
||||
<view class="table-container">
|
||||
<view class="table-header">
|
||||
<text class="col-index">序号</text>
|
||||
<text class="col-name">项目名称</text>
|
||||
<text class="col-desc">项目描述</text>
|
||||
<text class="col-completion">本日计划完成量</text>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view v-for="(item, index) in tableData" :key="index" class="table-row">
|
||||
<text class="col-index">{{ index + 1 }}</text>
|
||||
<text class="col-name">{{ item.taskName }}</text>
|
||||
<view class="col-desc">
|
||||
<text>{{ item.taskContent }}</text>
|
||||
</view>
|
||||
<view class="col-completion">
|
||||
<input type="number" v-model="item.completeNumDay" class="completion-input" />
|
||||
</view>
|
||||
<view class="table-body">
|
||||
<view v-for="(item, index) in tableData" :key="index" class="table-row">
|
||||
<text class="col-index">{{ index + 1 }}</text>
|
||||
<text class="col-name">{{ item.taskName }}</text>
|
||||
<view class="col-desc">
|
||||
<text>{{ item.taskContent }}</text>
|
||||
</view>
|
||||
<view class="col-completion">
|
||||
<input type="number" v-model="item.completeNumDay" class="completion-input" />
|
||||
</view>
|
||||
|
||||
<input type="hidden" name="totalId" :value="item.totalId" class="hidden-input">
|
||||
<input type="hidden" name="contentId" :value="item.contentId" class="hidden-input">
|
||||
<input type="hidden" name="monthId" :value="item.monthId" class="hidden-input">
|
||||
<input type="hidden" name="monthContentId" :value="item.monthContentId" class="hidden-input">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<input type="hidden" name="totalId" :value="item.totalId" class="hidden-input" />
|
||||
<input type="hidden" name="contentId" :value="item.contentId" class="hidden-input" />
|
||||
<input type="hidden" name="monthId" :value="item.monthId" class="hidden-input" />
|
||||
<input type="hidden" name="monthContentId" :value="item.monthContentId" class="hidden-input" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Save Button -->
|
||||
<view class="save-button-container">
|
||||
<button type="primary" @click="saveData">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
<!-- Save Button -->
|
||||
<view class="save-button-container">
|
||||
<button type="primary" @click="saveData">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
function getTomorrowDate() {
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const year = tomorrow.getFullYear();
|
||||
const month = String(tomorrow.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(tomorrow.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
function getTomorrowDate() {
|
||||
const today = new Date()
|
||||
const tomorrow = new Date(today)
|
||||
tomorrow.setDate(tomorrow.getDate() + 1)
|
||||
const year = tomorrow.getFullYear()
|
||||
const month = String(tomorrow.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(tomorrow.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
import config from '@/config'
|
||||
import config from '@/config'
|
||||
|
||||
export default {
|
||||
onLoad(options) {
|
||||
console.log('Received parameters:', options); // { proId: '...', currentDate: '...' }
|
||||
// 将接收到的参数保存到 data 或其他地方
|
||||
this.proId = decodeURIComponent(options.proId);
|
||||
this.proName = decodeURIComponent(options.proName);
|
||||
this.id = decodeURIComponent(options.id);
|
||||
this.currentDate = '2024-11-02';
|
||||
// 其他初始化逻辑...
|
||||
this.getListTable()
|
||||
},
|
||||
export default {
|
||||
onLoad(options) {
|
||||
console.log('Received parameters:', options) // { proId: '...', currentDate: '...' }
|
||||
// 将接收到的参数保存到 data 或其他地方
|
||||
this.proId = decodeURIComponent(options.proId)
|
||||
this.proName = decodeURIComponent(options.proName)
|
||||
this.id = decodeURIComponent(options.id)
|
||||
this.currentDate = this.$moment().format('YYYY-MM-DD')
|
||||
// 其他初始化逻辑...
|
||||
this.getListTable()
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
proId: '',
|
||||
currentDate: '',
|
||||
proName: '',
|
||||
totalPlan: '',
|
||||
tableData: [],
|
||||
needPersonNum: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
proId: '',
|
||||
currentDate: '',
|
||||
proName: '',
|
||||
totalPlan: '',
|
||||
tableData: [],
|
||||
needPersonNum: '',
|
||||
id: ''
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getListTable() {
|
||||
let param = {
|
||||
proId: this.proId,
|
||||
day: this.currentDate,
|
||||
id: this.id
|
||||
}
|
||||
uni.request({
|
||||
url: config.lpBmwUrl + '/bmw/workPlanDay/getPlanDetailById',
|
||||
method: 'post',
|
||||
data: JSON.stringify(param),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
'Authorization': uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划制定', res)
|
||||
if (res.data.code == 200) {
|
||||
this.needPersonNum = res.data.data.needPersonNum;
|
||||
this.tableData = res.data.data.contentList;
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg);
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getListTable() {
|
||||
uni.request({
|
||||
url: config.realAppUrl + '/AppPlan/selectPlanContentByPro',
|
||||
method: 'post',
|
||||
data: JSON.stringify({ proId: this.proId }),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
Authorization: uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
let param = {
|
||||
proId: this.proId,
|
||||
day: this.currentDate,
|
||||
id: res.data.data[0].id + ''
|
||||
}
|
||||
|
||||
saveData() {
|
||||
const planWorkNum = Number(this.totalPlan) || 0;
|
||||
const needPersonNum = Number(this.needPersonNum) || 0;
|
||||
console.log('param查询月计划参数', param)
|
||||
|
||||
if (planWorkNum > needPersonNum) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '计划作业人数不能大于预估投入人员数'
|
||||
});
|
||||
return;
|
||||
}
|
||||
let isValid = true;
|
||||
let errorMessage = '';
|
||||
uni.request({
|
||||
url: config.lpBmwUrl + '/bmw/workPlanDay/getPlanDetailById',
|
||||
method: 'post',
|
||||
data: JSON.stringify(param),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
Authorization: uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划制定', res)
|
||||
if (res.data.code == 200) {
|
||||
this.needPersonNum = res.data.data.needPersonNum
|
||||
this.tableData = res.data.data.contentList
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
this.tableData.forEach((item, index) => {
|
||||
const totalNum = item.totalNum;
|
||||
console.log("totalNum",totalNum)
|
||||
|
||||
const completeNumAllDay = Number(item.completeNumDay) || 0;
|
||||
console.log("completeNumAllDay",completeNumAllDay)
|
||||
|
||||
const completeNumDay = item.completeNumDay;
|
||||
console.log("completeNumDay",completeNumDay)
|
||||
|
||||
if (completeNumDay + completeNumAllDay > totalNum) {
|
||||
isValid = false;
|
||||
errorMessage += `第 ${index + 1} 行: 本日计划完成量 + 本月已定计划量 不能大于 本月计划量\n`;
|
||||
}
|
||||
});
|
||||
saveData() {
|
||||
const planWorkNum = Number(this.totalPlan) || 0
|
||||
const needPersonNum = Number(this.needPersonNum) || 0
|
||||
|
||||
if (!isValid) {
|
||||
uni.showModal({
|
||||
title: '验证错误',
|
||||
content: errorMessage,
|
||||
showCancel: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (planWorkNum > needPersonNum) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '计划作业人数不能大于预估投入人员数'
|
||||
})
|
||||
return
|
||||
}
|
||||
let isValid = true
|
||||
let errorMessage = ''
|
||||
|
||||
// 收集所有数据
|
||||
const members = this.tableData.map(item => ({
|
||||
taskName: item.taskName,
|
||||
taskContent: item.taskContent,
|
||||
totalNum: item.totalNum,
|
||||
completeNum: item.completeNum,
|
||||
completeNumMonth: item.completeNumMonth,
|
||||
completeNumAllMonth: item.completeNumAllMonth,
|
||||
completeNumAllDay: item.completeNumAllDay,
|
||||
completeNumDay: item.completeNumDay,
|
||||
monthId: item.monthId,
|
||||
monthContentId: item.monthContentId,
|
||||
totalId: item.totalId,
|
||||
contentId: item.contentId
|
||||
}));
|
||||
this.tableData.forEach((item, index) => {
|
||||
const totalNum = item.totalNum
|
||||
console.log('totalNum', totalNum)
|
||||
|
||||
const allData = {
|
||||
totalId: this.tableData[0]?.totalId || '',
|
||||
day: this.currentDate,
|
||||
monthId: this.tableData[0]?.monthId || '',
|
||||
needPersonNum: this.needPersonNum,
|
||||
planWorkNum: this.totalPlan,
|
||||
contentList: members
|
||||
};
|
||||
const completeNumAllDay = Number(item.completeNumDay) || 0
|
||||
console.log('completeNumAllDay', completeNumAllDay)
|
||||
|
||||
console.log("allData:", allData);
|
||||
// 提交数据
|
||||
this.uploadData(allData);
|
||||
},
|
||||
uploadData(data) {
|
||||
const completeNumDay = item.completeNumDay
|
||||
console.log('completeNumDay', completeNumDay)
|
||||
|
||||
// 检查计划作业人数是否为空
|
||||
if (this.totalPlan === null || this.totalPlan <= 0) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '请填写有效的计划作业人数'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (completeNumDay + completeNumAllDay > totalNum) {
|
||||
isValid = false
|
||||
errorMessage += `第 ${index + 1} 行: 本日计划完成量 + 本月已定计划量 不能大于 本月计划量\n`
|
||||
}
|
||||
})
|
||||
|
||||
// 检查本日计划完成量是否为空
|
||||
const incompleteTasks = this.tableData.filter(item => item.completeNumDay == null || item.completeNumDay < 0);
|
||||
if (incompleteTasks.length > 0) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '请确保所有任务都有有效的本日计划完成量'
|
||||
});
|
||||
return;
|
||||
}
|
||||
console.log("data",data)
|
||||
|
||||
uni.request({
|
||||
url: config.lpBmwUrl + '/bmw/workPlanDay/add',
|
||||
method: 'post',
|
||||
data: JSON.stringify(data),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
'Authorization': uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划制定', res)
|
||||
if (res.data.code == 200) {
|
||||
// 模拟保存成功后提示用户
|
||||
uni.showToast({
|
||||
icon: 'success',
|
||||
title: '保存成功',
|
||||
duration: 2000, // 提示框显示时间,单位为毫秒
|
||||
success: () => {
|
||||
setTimeout(() => {
|
||||
this.leftClick(); // 在提示框消失后返回上一级页面
|
||||
}, 2000); // 确保与duration一致
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg);
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
if (!isValid) {
|
||||
uni.showModal({
|
||||
title: '验证错误',
|
||||
content: errorMessage,
|
||||
showCancel: false
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
// 收集所有数据
|
||||
const members = this.tableData.map(item => ({
|
||||
taskName: item.taskName,
|
||||
taskContent: item.taskContent,
|
||||
totalNum: item.totalNum,
|
||||
completeNum: item.completeNum,
|
||||
completeNumMonth: item.completeNumMonth,
|
||||
completeNumAllMonth: item.completeNumAllMonth,
|
||||
completeNumAllDay: item.completeNumAllDay,
|
||||
completeNumDay: item.completeNumDay,
|
||||
monthId: item.monthId,
|
||||
monthContentId: item.monthContentId,
|
||||
totalId: item.totalId,
|
||||
contentId: item.contentId
|
||||
}))
|
||||
|
||||
// 返回
|
||||
leftClick() {
|
||||
console.log('返回')
|
||||
uni.navigateBack({
|
||||
delta: 1 // 返回
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const allData = {
|
||||
totalId: this.tableData[0]?.totalId || '',
|
||||
day: this.currentDate,
|
||||
monthId: this.tableData[0]?.monthId || '',
|
||||
needPersonNum: this.needPersonNum,
|
||||
planWorkNum: this.totalPlan,
|
||||
contentList: members
|
||||
}
|
||||
|
||||
console.log('allData:', allData)
|
||||
// 提交数据
|
||||
this.uploadData(allData)
|
||||
},
|
||||
uploadData(data) {
|
||||
// 检查计划作业人数是否为空
|
||||
if (this.totalPlan === null || this.totalPlan <= 0) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '请填写有效的计划作业人数'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查本日计划完成量是否为空
|
||||
const incompleteTasks = this.tableData.filter(item => item.completeNumDay == null || item.completeNumDay < 0)
|
||||
if (incompleteTasks.length > 0) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '请确保所有任务都有有效的本日计划完成量'
|
||||
})
|
||||
return
|
||||
}
|
||||
console.log('data', data)
|
||||
|
||||
uni.request({
|
||||
url: config.lpBmwUrl + '/bmw/workPlanDay/add',
|
||||
method: 'post',
|
||||
data: JSON.stringify(data),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
Authorization: uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划制定', res)
|
||||
if (res.data.code == 200) {
|
||||
// 模拟保存成功后提示用户
|
||||
uni.showToast({
|
||||
icon: 'success',
|
||||
title: '保存成功',
|
||||
duration: 2000, // 提示框显示时间,单位为毫秒
|
||||
success: () => {
|
||||
setTimeout(() => {
|
||||
this.leftClick() // 在提示框消失后返回上一级页面
|
||||
}, 2000) // 确保与duration一致
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 返回
|
||||
leftClick() {
|
||||
console.log('返回')
|
||||
uni.navigateBack({
|
||||
delta: 1 // 返回
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: 30rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.container {
|
||||
padding: 30rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.project-header {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.project-header {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.project-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.completion-rates {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.completion-rates {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.total-plan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.total-plan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.total-input {
|
||||
width: 200rpx;
|
||||
height: 60rpx;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0 20rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.total-input {
|
||||
width: 200rpx;
|
||||
height: 60rpx;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0 20rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.table-container {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
background-color: #f5f5f5;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.table-header {
|
||||
display: flex;
|
||||
background-color: #f5f5f5;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.table-body {
|
||||
background-color: #fff;
|
||||
}
|
||||
.table-body {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
border-bottom: 1px solid #ddd;
|
||||
align-items: center;
|
||||
}
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
border-bottom: 1px solid #ddd;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 隔行变色 */
|
||||
.table-row:nth-child(even) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
/* 隔行变色 */
|
||||
.table-row:nth-child(even) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.table-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.table-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.col-index {
|
||||
width: 80rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.col-index {
|
||||
width: 80rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.col-name {
|
||||
width: 200rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.col-name {
|
||||
width: 200rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.col-desc {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.col-desc {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.col-completion {
|
||||
width: 200rpx;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
.col-completion {
|
||||
width: 200rpx;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.completion-input {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0 10rpx;
|
||||
box-sizing: border-box;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.completion-input {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0 10rpx;
|
||||
box-sizing: border-box;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: #fff;
|
||||
}
|
||||
input {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* 确保隐藏输入字段 */
|
||||
.hidden-input {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
/* 确保隐藏输入字段 */
|
||||
.hidden-input {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,377 +1,399 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<u-navbar class="u-navbar" title="日计划管理" placeholder @leftClick="leftClick" leftIconColor="#fff"
|
||||
bgColor="#00337A" :titleStyle="{ color: '#FFF', fontSize: '32rpx' }" />
|
||||
<!-- Header -->
|
||||
<view class="header">
|
||||
<view class="date-section">
|
||||
<picker mode="date" :value="currentDate" @change="onDateChange">
|
||||
<view class="date-picker">
|
||||
<image src="@/static/realName/attendance.png" class="calendar-icon"></image>
|
||||
<text>{{currentDate}}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="progress-section">
|
||||
<text class="reminder-text">请于每日18:00点前提交明日计划</text>
|
||||
<button class="primary-btn" @click="developDailyPlan">制定日计划</button>
|
||||
</view>
|
||||
<view class="project-title">
|
||||
<text>{{proName}}</text>
|
||||
</view>
|
||||
<view class="completion-rate">
|
||||
<text>作业计划完成率:{{totalComplete}}%</text>
|
||||
<text>月完成计划完成率:{{monthComplete}}%</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="container">
|
||||
<u-navbar
|
||||
class="u-navbar"
|
||||
title="日计划管理"
|
||||
placeholder
|
||||
@leftClick="leftClick"
|
||||
leftIconColor="#fff"
|
||||
bgColor="#00337A"
|
||||
:titleStyle="{ color: '#FFF', fontSize: '32rpx' }"
|
||||
/>
|
||||
<!-- Header -->
|
||||
<view class="header">
|
||||
<view class="date-section">
|
||||
<picker mode="date" :value="currentDate" @change="onDateChange">
|
||||
<view class="date-picker">
|
||||
<image src="@/static/realName/attendance.png" class="calendar-icon"></image>
|
||||
<text>{{ currentDate }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="progress-section">
|
||||
<text class="reminder-text">请于每日18:00点前提交明日计划</text>
|
||||
<button class="primary-btn" @click="developDailyPlan">制定日计划</button>
|
||||
</view>
|
||||
<view class="project-title">
|
||||
<text>{{ proName }}</text>
|
||||
</view>
|
||||
<view class="completion-rate">
|
||||
<text>作业计划完成率:{{ totalComplete }}%</text>
|
||||
<text>月完成计划完成率:{{ monthComplete }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="task-list">
|
||||
<block v-for="(task, index) in taskList" :key="index">
|
||||
<view class="task-item">
|
||||
<view class="task-header">
|
||||
<text class="timestamp">{{ task.day }}</text>
|
||||
<view :class="['status', getStatusClass(task)]">{{ getTaskStatusText(task) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="metrics-container">
|
||||
<view class="metric-row">
|
||||
<text class="metric-item">总计划数量:{{ task.totalNum }}</text>
|
||||
<text class="metric-item">月计划数量:{{ task.completeNumMonth }}</text>
|
||||
<text class="metric-item">计划数量:{{ task.planCompleteNumDay }}</text>
|
||||
</view>
|
||||
<view class="metric-row">
|
||||
<text class="metric-item">累计完成作业量:{{ task.completeNumDay }}</text>
|
||||
<text class="metric-item">月累计完成作业量:{{ task.completeNumAllMonth }}</text>
|
||||
<text class="metric-item">作业人数:{{ task.planWorkNum }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="actions">
|
||||
<button class="action-btn" @click="detailsPlan(task)" >详情</button>
|
||||
<button class="action-btn" @click="uploadPlan(task)" v-if="task.path == null || task.path === '' " >完成电子上传</button>
|
||||
<button class="action-btn" @click="editPlan(task)" v-if="task.path == null || task.path === '' " >完成情况修改</button>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<view class="task-list">
|
||||
<block v-for="(task, index) in taskList" :key="index">
|
||||
<view class="task-item">
|
||||
<view class="task-header">
|
||||
<text class="timestamp">{{ task.day }}</text>
|
||||
<view :class="['status', getStatusClass(task)]">{{ getTaskStatusText(task) }}</view>
|
||||
</view>
|
||||
<view class="metrics-container">
|
||||
<view class="metric-row">
|
||||
<text class="metric-item">总计划数量:{{ task.totalNum }}</text>
|
||||
<text class="metric-item">月计划数量:{{ task.completeNumMonth }}</text>
|
||||
<text class="metric-item">计划数量:{{ task.planCompleteNumDay }}</text>
|
||||
</view>
|
||||
<view class="metric-row">
|
||||
<text class="metric-item">累计完成作业量:{{ task.completeNumDay }}</text>
|
||||
<text class="metric-item">月累计完成作业量:{{ task.completeNumAllMonth }}</text>
|
||||
<text class="metric-item">作业人数:{{ task.planWorkNum }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="actions">
|
||||
<button class="action-btn" @click="detailsPlan(task)">详情</button>
|
||||
<button class="action-btn" @click="uploadPlan(task)" v-if="task.path == null || task.path === ''">
|
||||
完成电子上传
|
||||
</button>
|
||||
<button class="action-btn" @click="editPlan(task)" v-if="task.path == null || task.path === ''">
|
||||
完成情况修改
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// 定义一个不依赖于Vue实例的日期格式化函数
|
||||
function formatDate(date) {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
// 定义一个不依赖于Vue实例的日期格式化函数
|
||||
function formatDate(date) {
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
import config from '@/config'
|
||||
import config from '@/config'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentDate: formatDate(new Date()),
|
||||
proId:uni.getStorageSync('realNameUser').proId,
|
||||
proName: '',
|
||||
taskList: [],
|
||||
totalComplete: '0.00',
|
||||
monthComplete: '0.00',
|
||||
id:'',
|
||||
dayId:'',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 如果需要在组件创建后再次设置currentDate为最新的当前日期,可以在这里做
|
||||
this.currentDate = formatDate(new Date());
|
||||
this.getListData()
|
||||
},
|
||||
onLoad() {
|
||||
// this.getListData()
|
||||
},
|
||||
methods: {
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentDate: formatDate(new Date()),
|
||||
proId: uni.getStorageSync('realNameUser').proId,
|
||||
proName: '',
|
||||
taskList: [],
|
||||
totalComplete: '0.00',
|
||||
monthComplete: '0.00',
|
||||
id: '',
|
||||
dayId: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 如果需要在组件创建后再次设置currentDate为最新的当前日期,可以在这里做
|
||||
this.currentDate = formatDate(new Date())
|
||||
this.getListData()
|
||||
},
|
||||
onLoad() {
|
||||
// this.getListData()
|
||||
},
|
||||
methods: {
|
||||
onDateChange(e) {
|
||||
this.currentDate = e.detail.value
|
||||
this.getListData()
|
||||
},
|
||||
|
||||
onDateChange(e) {
|
||||
this.currentDate = e.detail.value
|
||||
this.getListData()
|
||||
},
|
||||
developDailyPlan() {
|
||||
uni.navigateTo({
|
||||
//制定日计划
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/develop?proId=${encodeURIComponent(
|
||||
this.proId
|
||||
)}&proName=${encodeURIComponent(this.proName)}&id=${encodeURIComponent(this.id)}`
|
||||
})
|
||||
},
|
||||
|
||||
developDailyPlan() {
|
||||
uni.navigateTo({ //制定日计划
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/develop?proId=${encodeURIComponent(this.proId)}&proName=${encodeURIComponent(this.proName)}&id=${encodeURIComponent(this.id)}`
|
||||
})
|
||||
},
|
||||
|
||||
editPlan(){
|
||||
uni.navigateTo({ //修改日计划
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/edit?dayId=${encodeURIComponent(this.dayId)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
editPlan() {
|
||||
uni.navigateTo({
|
||||
//修改日计划
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/edit?dayId=${encodeURIComponent(
|
||||
this.dayId
|
||||
)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
|
||||
uploadPlan() {
|
||||
uni.navigateTo({ //完成情况上传
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/upload?dayId=${encodeURIComponent(this.dayId)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
detailsPlan() {
|
||||
uni.navigateTo({ //日计划详情
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/details?dayId=${encodeURIComponent(this.dayId)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
uploadPlan() {
|
||||
uni.navigateTo({
|
||||
//完成情况上传
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/upload?dayId=${encodeURIComponent(
|
||||
this.dayId
|
||||
)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
detailsPlan() {
|
||||
uni.navigateTo({
|
||||
//日计划详情
|
||||
url: `/pages/realName/workbench/dailyPlanManagement/details?dayId=${encodeURIComponent(
|
||||
this.dayId
|
||||
)}&id=${encodeURIComponent(this.id)}&proName=${encodeURIComponent(this.proName)}`
|
||||
})
|
||||
},
|
||||
|
||||
// 返回
|
||||
leftClick() {
|
||||
console.log('返回')
|
||||
uni.navigateBack({
|
||||
delta: 1 // 返回
|
||||
});
|
||||
},
|
||||
getListData() {
|
||||
let param = {
|
||||
proId: this.proId,
|
||||
date: this.currentDate
|
||||
}
|
||||
uni.request({
|
||||
url: config.realAppUrl + '/AppPlan/selectDayPlan',
|
||||
method: 'post',
|
||||
data: JSON.stringify(param),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
'Authorization': uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划管理', res)
|
||||
if (res.data.code == 200) {
|
||||
this.taskList = res.data.data;
|
||||
const firstProName = res.data.data.length > 0 ? res.data.data[0].proName : null;
|
||||
this.proName = firstProName
|
||||
this.totalComplete = this.overallCompletionRate()
|
||||
this.monthComplete = this.monthlyCompletionRate()
|
||||
this.id = res.data.data[0].id
|
||||
this.dayId = res.data.data[0].dayId
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg);
|
||||
this.taskList = '';
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
getStatusClass(task) {
|
||||
var planCompleteNumDay = task.planCompleteNumDay;
|
||||
var completeNumDay = task.completeNumDay;
|
||||
var status = ""
|
||||
if (planCompleteNumDay > completeNumDay) {
|
||||
status = "进行中";
|
||||
} else {
|
||||
status = "已结束";
|
||||
}
|
||||
switch (status) {
|
||||
case '进行中':
|
||||
return 'in-progress';
|
||||
case '已结束':
|
||||
return 'completed';
|
||||
default:
|
||||
return 'not-started';
|
||||
}
|
||||
},
|
||||
|
||||
getTaskStatusText(task) {
|
||||
var planCompleteNumDay = task.planCompleteNumDay;
|
||||
var completeNumDay = task.completeNumDay;
|
||||
var status = ""
|
||||
if (planCompleteNumDay > completeNumDay) {
|
||||
status = "进行中";
|
||||
} else {
|
||||
status = "已结束";
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case '未开始':
|
||||
return '未开始';
|
||||
case '进行中':
|
||||
return '进行中';
|
||||
case '已结束':
|
||||
return '已结束';
|
||||
default:
|
||||
return '未开始';
|
||||
}
|
||||
},
|
||||
// 返回
|
||||
leftClick() {
|
||||
console.log('返回')
|
||||
uni.navigateBack({
|
||||
delta: 1 // 返回
|
||||
})
|
||||
},
|
||||
getListData() {
|
||||
let param = {
|
||||
proId: this.proId,
|
||||
date: this.currentDate
|
||||
}
|
||||
|
||||
// 作业计划完成率 = (累计完成作业量 / 总计划数量) * 100%
|
||||
overallCompletionRate() {
|
||||
let totalPlan = 0;
|
||||
let completedWork = 0;
|
||||
console.log('param查询参数', param)
|
||||
uni.request({
|
||||
url: config.realAppUrl + '/AppPlan/selectDayPlan',
|
||||
method: 'post',
|
||||
data: JSON.stringify(param),
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
Authorization: uni.getStorageSync('realNameToken')
|
||||
},
|
||||
success: res => {
|
||||
console.log('日计划管理', res)
|
||||
if (res.data.code == 200) {
|
||||
this.taskList = res.data.data
|
||||
const firstProName = res.data.data.length > 0 ? res.data.data[0].proName : null
|
||||
this.proName = firstProName
|
||||
this.totalComplete = this.overallCompletionRate()
|
||||
this.monthComplete = this.monthlyCompletionRate()
|
||||
this.id = res.data.data[0].id
|
||||
this.dayId = res.data.data[0].dayId
|
||||
} else {
|
||||
uni.$u.toast(res.data.msg)
|
||||
this.taskList = ''
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
getStatusClass(task) {
|
||||
var planCompleteNumDay = task.planCompleteNumDay
|
||||
var completeNumDay = task.completeNumDay
|
||||
var status = ''
|
||||
if (planCompleteNumDay > completeNumDay) {
|
||||
status = '进行中'
|
||||
} else {
|
||||
status = '已结束'
|
||||
}
|
||||
switch (status) {
|
||||
case '进行中':
|
||||
return 'in-progress'
|
||||
case '已结束':
|
||||
return 'completed'
|
||||
default:
|
||||
return 'not-started'
|
||||
}
|
||||
},
|
||||
|
||||
this.taskList.forEach(task => {
|
||||
if (task.completeNumDay && task.planCompleteNumDay) {
|
||||
totalPlan += parseFloat(task.planCompleteNumDay);
|
||||
completedWork += parseFloat(task.completeNumDay);
|
||||
}
|
||||
});
|
||||
getTaskStatusText(task) {
|
||||
var planCompleteNumDay = task.planCompleteNumDay
|
||||
var completeNumDay = task.completeNumDay
|
||||
var status = ''
|
||||
if (planCompleteNumDay > completeNumDay) {
|
||||
status = '进行中'
|
||||
} else {
|
||||
status = '已结束'
|
||||
}
|
||||
|
||||
return totalPlan > 0 ? ((completedWork / totalPlan) * 100).toFixed(2) : '0.00';
|
||||
},
|
||||
switch (status) {
|
||||
case '未开始':
|
||||
return '未开始'
|
||||
case '进行中':
|
||||
return '进行中'
|
||||
case '已结束':
|
||||
return '已结束'
|
||||
default:
|
||||
return '未开始'
|
||||
}
|
||||
},
|
||||
|
||||
// 月完成计划完成率 = (月累计完成作业量 / 总计划数量) * 100%
|
||||
monthlyCompletionRate() {
|
||||
let totalPlan = 0;
|
||||
let completedWorkInMonth = 0;
|
||||
// 作业计划完成率 = (累计完成作业量 / 总计划数量) * 100%
|
||||
overallCompletionRate() {
|
||||
let totalPlan = 0
|
||||
let completedWork = 0
|
||||
|
||||
this.taskList.forEach(task => {
|
||||
if (task.completeNumAllMonth && task.completeNumMonth) {
|
||||
totalPlan += parseFloat(task.completeNumAllMonth);
|
||||
completedWorkInMonth += parseFloat(task.completeNumMonth);
|
||||
}
|
||||
});
|
||||
return totalPlan > 0 ? ((completedWorkInMonth / totalPlan) * 100).toFixed(2) : '0.00';
|
||||
}
|
||||
},
|
||||
}
|
||||
this.taskList.forEach(task => {
|
||||
if (task.completeNumDay && task.planCompleteNumDay) {
|
||||
totalPlan += parseFloat(task.planCompleteNumDay)
|
||||
completedWork += parseFloat(task.completeNumDay)
|
||||
}
|
||||
})
|
||||
|
||||
return totalPlan > 0 ? ((completedWork / totalPlan) * 100).toFixed(2) : '0.00'
|
||||
},
|
||||
|
||||
// 月完成计划完成率 = (月累计完成作业量 / 总计划数量) * 100%
|
||||
monthlyCompletionRate() {
|
||||
let totalPlan = 0
|
||||
let completedWorkInMonth = 0
|
||||
|
||||
this.taskList.forEach(task => {
|
||||
if (task.completeNumAllMonth && task.completeNumMonth) {
|
||||
totalPlan += parseFloat(task.completeNumAllMonth)
|
||||
completedWorkInMonth += parseFloat(task.completeNumMonth)
|
||||
}
|
||||
})
|
||||
return totalPlan > 0 ? ((completedWorkInMonth / totalPlan) * 100).toFixed(2) : '0.00'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.header {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.date-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.date-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.date-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.date-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.calendar-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.progress-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.progress-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.reminder-text {
|
||||
color: #ff4d4f;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.reminder-text {
|
||||
color: #ff4d4f;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
background-color: #0099ff;
|
||||
color: #fff;
|
||||
padding: 0rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.primary-btn {
|
||||
background-color: #0099ff;
|
||||
color: #fff;
|
||||
padding: 0rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.project-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.completion-rate {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.completion-rate {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.task-item {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.task-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.task-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.timestamp {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 4rpx 20rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 4rpx 20rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.not-started {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
.not-started {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.in-progress {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
.in-progress {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
.completed {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
.completed {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.metrics-container {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.metrics-container {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.metric-row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.metric-row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.metric-item {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 26rpx;
|
||||
padding: 0rpx 22rpx;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
.action-btn {
|
||||
font-size: 26rpx;
|
||||
padding: 0rpx 22rpx;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.action-btn.danger {
|
||||
color: #fff;
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
</style>
|
||||
.action-btn.danger {
|
||||
color: #fff;
|
||||
background-color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue