- 在任务列表组件中添加验收按钮选项 - 根据任务类型区分验收状态(1表示待验收,2表示已完成) - 更新任务状态显示文本为更清晰的描述 - 移除任务页面图标的固定颜色 - 修复更新检查中的APK下载链接问题 - 更新版本记录至5.1.1
401 lines
9.0 KiB
Vue
401 lines
9.0 KiB
Vue
<template>
|
||
<view class="task-list-container">
|
||
<!-- 任务列表 -->
|
||
<view class="task-list">
|
||
<uni-swipe-action>
|
||
<uni-swipe-action-item
|
||
v-for="(task, index) in taskList"
|
||
:key="task.taskId"
|
||
:right-options="getSwipeOptions(task)"
|
||
@click="handleSwipeClick($event, index)"
|
||
>
|
||
<view
|
||
class="task-item"
|
||
@click="handleTaskClick(task)"
|
||
>
|
||
<!-- 任务完成checkbox -->
|
||
<view v-if="config.showCheckbox && task.status === 0" class="task-checkbox">
|
||
<view v-if="task.state === 0" class="checkbox-container" @click.stop="handleTaskComplete(task)">
|
||
<view
|
||
class="custom-checkbox"
|
||
:class="{ 'checked': checkboxStates[task.taskId] }"
|
||
>
|
||
<uni-icons
|
||
v-if="checkboxStates[task.taskId]"
|
||
type="checkmarkempty"
|
||
size="16"
|
||
color="#fff"
|
||
></uni-icons>
|
||
</view>
|
||
</view>
|
||
<view v-else-if="task.state === 1" class="checkbox-container">
|
||
<uni-icons type="checkmarkempty" size="20" color="#999"></uni-icons>
|
||
</view>
|
||
<view v-else-if="task.state === 2" class="checkbox-container">
|
||
<uni-icons type="checkmarkempty" size="20" color="#52c41a"></uni-icons>
|
||
</view>
|
||
<view v-else class="checkbox-container">
|
||
<view class="custom-checkbox disabled">
|
||
<uni-icons type="checkmarkempty" size="16" color="#999"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 任务内容 -->
|
||
<view class="task-content">
|
||
<view class="task-title" :class="{ 'single-line': isSingleLine(task.taskTitle) }">{{ task.taskTitle || '未命名任务' }}</view>
|
||
<view class="task-status" :class="getStatusClass(task.state)">
|
||
{{ getStatusText(task.state) }}
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 置顶标识 -->
|
||
<view v-if="task.ownRank === 1" class="top-badge">
|
||
<uni-icons type="arrow-up" size="12" color="#007aff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</uni-swipe-action-item>
|
||
</uni-swipe-action>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view v-if="taskList.length === 0 && !loading" class="empty-state">
|
||
<u-empty :text="config.emptyText || '暂无任务'" mode="list"></u-empty>
|
||
</view>
|
||
|
||
<!-- 加载更多 -->
|
||
<u-load-more
|
||
:status="loadMoreStatus"
|
||
@loadmore="$emit('loadMore')"
|
||
></u-load-more>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'TaskList',
|
||
props: {
|
||
// 任务列表数据
|
||
taskList: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
// 加载状态
|
||
loading: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 加载更多状态
|
||
loadMoreStatus: {
|
||
type: String,
|
||
default: 'more' // more, loading, noMore
|
||
},
|
||
// 配置对象
|
||
config: {
|
||
type: Object,
|
||
default: () => ({
|
||
showCheckbox: true, // 是否显示checkbox
|
||
canComplete: true, // 是否可以完成任务
|
||
canDelete: true, // 是否可以删除任务
|
||
canTop: true, // 是否可以置顶任务
|
||
emptyText: '暂无任务', // 空状态文本
|
||
detailPage: '/pages/workbench/task/reportTaskDetail' // 详情页面路径
|
||
})
|
||
}
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
checkboxStates: {} // 存储checkbox的状态
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
// 获取左划操作选项
|
||
getSwipeOptions(task) {
|
||
const options = []
|
||
// 置顶功能
|
||
if (this.config.canTop) {
|
||
if (task.ownRank === 1) {
|
||
// 已置顶,显示取消置顶
|
||
options.push({
|
||
text: '取消置顶',
|
||
style: {
|
||
backgroundColor: '#999',
|
||
color: '#fff'
|
||
}
|
||
})
|
||
} else {
|
||
// 未置顶,显示置顶
|
||
options.push({
|
||
text: '置顶',
|
||
style: {
|
||
backgroundColor: '#007aff',
|
||
color: '#fff'
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// 删除功能
|
||
if (this.config.canDelete) {
|
||
options.push({
|
||
text: '删除',
|
||
style: {
|
||
backgroundColor: '#ff4757',
|
||
color: '#fff'
|
||
}
|
||
})
|
||
|
||
if (task.state !== 2) {
|
||
options.push({
|
||
text: '验收',
|
||
style: {
|
||
backgroundColor: '#00b300',
|
||
color: '#fff'
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
return options
|
||
},
|
||
|
||
// 处理左划操作点击
|
||
handleSwipeClick(e, index) {
|
||
const { content, position } = e
|
||
|
||
if (!content) {
|
||
console.error('Invalid swipe event:', e)
|
||
return
|
||
}
|
||
|
||
const task = this.taskList[index]
|
||
if (!task) {
|
||
console.error('Task not found at index:', index)
|
||
return
|
||
}
|
||
|
||
if (content.text === '置顶') {
|
||
this.$emit('setTaskTop', task, 1)
|
||
} else if (content.text === '取消置顶') {
|
||
this.$emit('setTaskTop', task, 0)
|
||
} else if (content.text === '删除') {
|
||
this.$emit('deleteTask', task)
|
||
} else if (content.text == '验收') {
|
||
this.$emit('completeTask', task)
|
||
}
|
||
},
|
||
|
||
// 处理任务完成
|
||
handleTaskComplete(task) {
|
||
if (!this.config.canComplete) return
|
||
console.log('handleTaskComplete called, task:', task)
|
||
console.log('task.status:', task.status, 'task.state:', task.state)
|
||
|
||
// 只有单任务(status为0)且状态为0(进行中)的任务才能完成
|
||
if (task.status !== 0 && (task.state == 0 || task.state == 1)) {
|
||
console.log('Task cannot be completed, status:', task.status, 'state:', task.state)
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '该任务当前状态无法完成',
|
||
showCancel: false
|
||
})
|
||
return
|
||
}
|
||
|
||
// 先设置checkbox为选中状态
|
||
this.$set(this.checkboxStates, task.taskId, true)
|
||
|
||
console.log('Showing confirmation modal')
|
||
uni.showModal({
|
||
title: '确认完成',
|
||
content: `确定要将任务"${task.taskTitle}"标记为完成吗?`,
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.$emit('completeTask', task)
|
||
// 清除checkbox状态
|
||
this.$set(this.checkboxStates, task.taskId, false)
|
||
} else {
|
||
// 用户取消,重置checkbox状态为false
|
||
console.log('用户取消,重置checkbox状态')
|
||
this.$set(this.checkboxStates, task.taskId, false)
|
||
console.log('checkbox状态已重置:', this.checkboxStates[task.taskId])
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 跳转到任务详情页面
|
||
handleTaskClick(task) {
|
||
this.$emit('taskClick', task)
|
||
},
|
||
|
||
// 获取状态文本
|
||
getStatusText(state) {
|
||
const statusMap = {
|
||
15: '申请延期',
|
||
0: '进行中',
|
||
1: '待验收',
|
||
2: '已完成'
|
||
}
|
||
return statusMap[state] || '未知状态'
|
||
},
|
||
|
||
// 获取状态样式类
|
||
getStatusClass(state) {
|
||
const classMap = {
|
||
15: 'status-pending',
|
||
0: 'status-processing',
|
||
1: 'status-waiting',
|
||
2: 'status-completed'
|
||
}
|
||
return classMap[state] || 'status-unknown'
|
||
},
|
||
|
||
// 判断是否为单行文字
|
||
isSingleLine(text) {
|
||
if (!text) return true
|
||
// 估算文字长度,假设每个中文字符约等于2个英文字符
|
||
const estimatedLength = text.replace(/[\u4e00-\u9fa5]/g, 'aa').length
|
||
// 如果估算长度小于等于20个字符,认为是单行
|
||
return estimatedLength <= 20
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.task-list-container {
|
||
min-height: 100vh;
|
||
background-color: #f5f5f5;
|
||
padding-bottom: 120rpx;
|
||
}
|
||
|
||
.task-list {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.task-item {
|
||
box-sizing: border-box;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
position: relative;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.task-checkbox {
|
||
margin-right: 20rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.checkbox-container {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.custom-checkbox {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
border: 2rpx solid #ddd;
|
||
border-radius: 6rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #fff;
|
||
transition: all 0.2s ease;
|
||
|
||
&.checked {
|
||
background-color: $im-primary;
|
||
border-color: $im-primary;
|
||
}
|
||
|
||
&.disabled {
|
||
background-color: #f5f5f5;
|
||
border-color: #ddd;
|
||
}
|
||
}
|
||
|
||
.task-content {
|
||
flex: 1;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.task-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
flex: 1;
|
||
margin-right: 20rpx;
|
||
line-height: 1.4;
|
||
height: 88rpx; /* 固定高度 */
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
|
||
/* 单行文字时垂直居中 */
|
||
&.single-line {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
-webkit-line-clamp: 1;
|
||
}
|
||
}
|
||
|
||
.task-status {
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
box-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.1);
|
||
|
||
&.status-pending {
|
||
background-color: #fff2e8;
|
||
color: #fa8c16;
|
||
}
|
||
|
||
&.status-processing {
|
||
background-color: #e6f7ff;
|
||
color: #1890ff;
|
||
}
|
||
|
||
&.status-waiting {
|
||
background-color: #fff7e6;
|
||
color: #fa8c16;
|
||
}
|
||
|
||
&.status-completed {
|
||
background-color: #f6ffed;
|
||
color: #52c41a;
|
||
}
|
||
}
|
||
|
||
.top-badge {
|
||
position: absolute;
|
||
top: 8rpx;
|
||
right: 8rpx;
|
||
background-color: rgba($im-primary, 0.1);
|
||
border: 1rpx solid $im-primary;
|
||
border-radius: 50%;
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 2rpx 6rpx rgba($im-primary, 0.2);
|
||
}
|
||
|
||
.empty-state {
|
||
padding: 100rpx 20rpx;
|
||
text-align: center;
|
||
}
|
||
</style> |