Files
im-uniapp/pages/workbench/task/task.vue

532 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="task-container">
<!-- 搜索栏 -->
<view class="search-bar">
<view class="search-container">
<view class="task-type-button-container">
<view class="task-type-button" @click="toggleTaskTypePanel">
<u-icon name="list" :color="$im-primary" size="18"></u-icon>
</view>
<!-- 悬浮任务类型面板 -->
<view v-if="showTaskTypePanel" class="task-type-panel">
<view class="task-type-option" @click="switchTaskType('received')">
<uni-icons type="checkmarkempty" v-if="taskType === 'received'" size="16" :color="$im-primary"></uni-icons>
<text>发布给我的任务</text>
</view>
<view class="task-type-option" @click="switchTaskType('published')">
<uni-icons type="checkmarkempty" v-if="taskType === 'published'" size="16" :color="$im-primary"></uni-icons>
<text>我发布的任务</text>
</view>
</view>
</view>
<view class="search-input">
<u-search
v-model="searchKeyword"
placeholder="搜索任务名称"
:show-action="false"
@search="handleSearch"
@clear="handleClear"
></u-search>
</view>
<view class="add-button" @click="createTask">
<u-icon name="plus" :color="$im-primary" size="18"></u-icon>
</view>
</view>
</view>
<!-- 任务列表组件 -->
<TaskList
:task-list="taskList"
:loading="loading"
:load-more-status="loadMoreStatus"
:config="taskListConfig"
@setTaskTop="handleSetTaskTop"
@deleteTask="handleDeleteTask"
@completeTask="handleCompleteTask"
@taskClick="handleTaskClick"
@loadMore="handleLoadMore"
/>
</view>
</template>
<script>
import TaskList from './components/TaskList.vue'
import { listTaskWork, listTaskCreate, delTask, updateTask } from '@/api/oa/task.js'
export default {
components: {
TaskList
},
data() {
return {
searchKeyword: '',
showTaskTypePanel: false, // 是否显示任务类型面板
taskType: 'received', // 任务类型received-发布给我的任务, published-我发布的任务
taskList: [], // 任务列表数据
loading: false, // 加载状态
loadMoreStatus: 'more', // 加载更多状态
queryParams: {
pageNum: 1,
pageSize: 10,
taskTitle: ''
},
total: 0, // 总数量
taskListConfig: {
showCheckbox: true, // 是否显示checkbox
canComplete: true, // 是否可以完成任务
canDelete: false, // 是否可以删除任务
canTop: true, // 是否可以置顶任务
emptyText: '暂无发布给我的任务', // 空状态文本
detailPage: '/pages/workbench/task/reportTaskDetail' // 详情页面路径
}
}
},
onLoad() {
this.loadTaskList()
},
onPullDownRefresh() {
this.refreshList()
uni.stopPullDownRefresh()
},
onReachBottom() {
this.handleLoadMore()
},
methods: {
// 加载任务列表
async loadTaskList() {
if (this.loading) return
this.loading = true
try {
const params = {
...this.queryParams
}
let response
// 根据任务类型调用不同的API
if (this.taskType === 'received') {
// 发布给我的任务
response = await listTaskWork(params)
} else if (this.taskType === 'published') {
// 我发布的任务
response = await listTaskCreate(params)
}
if (response.code === 200) {
const { rows, total } = response
if (this.queryParams.pageNum === 1) {
this.taskList = rows || []
} else {
this.taskList = [...this.taskList, ...(rows || [])]
}
this.total = total
this.updateLoadMoreStatus(rows, total)
} else {
uni.showToast({
title: response.msg || '获取任务列表失败',
icon: 'none'
})
}
} catch (error) {
console.error('加载任务列表失败:', error)
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
})
} finally {
this.loading = false
}
},
// 刷新列表
refreshList() {
this.queryParams.pageNum = 1
this.loadTaskList()
},
// 更新加载更多状态
updateLoadMoreStatus(rows, total) {
const currentTotal = this.taskList.length
if (currentTotal >= total) {
this.loadMoreStatus = 'noMore'
} else if (rows && rows.length < this.queryParams.pageSize) {
this.loadMoreStatus = 'noMore'
} else {
this.loadMoreStatus = 'more'
}
},
// 搜索
handleSearch() {
this.queryParams.taskTitle = this.searchKeyword
this.queryParams.pageNum = 1
this.loadTaskList()
},
// 清除搜索
handleClear() {
this.searchKeyword = ''
this.queryParams.taskTitle = ''
this.queryParams.pageNum = 1
this.loadTaskList()
},
// 切换任务类型面板
toggleTaskTypePanel() {
this.showTaskTypePanel = !this.showTaskTypePanel
},
// 切换任务类型
switchTaskType(type) {
if (this.taskType === type) return
this.taskType = type
this.showTaskTypePanel = false // 选择后关闭面板
// 重置搜索和分页
this.searchKeyword = ''
this.queryParams.pageNum = 1
this.queryParams.taskTitle = ''
// 根据任务类型更新配置
if (type === 'received') {
// 发布给我的任务:可以完成、可以置顶、不能删除
this.taskListConfig = {
showCheckbox: true,
canComplete: true,
canDelete: false,
canTop: true,
emptyText: '暂无发布给我的任务',
detailPage: '/pages/workbench/task/reportTaskDetail'
}
} else if (type === 'published') {
// 我发布的任务:不能完成、不能置顶、可以删除
this.taskListConfig = {
showCheckbox: false,
canComplete: false,
canDelete: true,
canTop: false,
emptyText: '暂无我发布的任务',
detailPage: '/pages/workbench/task/reportTaskDetail'
}
}
// 重新加载数据
this.loadTaskList()
},
// 创建任务
createTask() {
uni.navigateTo({
url: '/pages/workbench/task/create'
})
},
// 任务点击
handleTaskClick(task) {
uni.navigateTo({
url: `${this.taskListConfig.detailPage}?id=${task.taskId}`
})
},
// 加载更多
handleLoadMore() {
if (this.loadMoreStatus === 'noMore' || this.loading) return
this.queryParams.pageNum++
this.loadTaskList()
},
// 置顶/取消置顶任务
async handleSetTaskTop(task, ownRank) {
try {
const response = await updateTask({
taskId: task.taskId,
ownRank: ownRank
});
if (response.code === 200) {
uni.showToast({
title: ownRank === 1 ? '置顶成功' : '取消置顶成功',
icon: 'success'
});
this.refreshList();
} else {
uni.showToast({
title: response.msg || '操作失败',
icon: 'none'
});
}
} catch (error) {
uni.showToast({
title: '操作失败,请重试',
icon: 'none'
});
}
},
// 删除任务
async handleDeleteTask(task) {
uni.showModal({
title: '确认删除',
content: `确定要删除任务"${task.taskTitle}"吗?`,
success: async (res) => {
if (res.confirm) {
try {
const response = await delTask(task.taskId);
if (response.code === 200) {
uni.showToast({
title: '删除成功',
icon: 'success'
});
this.refreshList();
} else {
uni.showToast({
title: response.msg || '删除失败',
icon: 'none'
});
}
} catch (error) {
uni.showToast({
title: '删除失败,请重试',
icon: 'none'
});
}
}
}
});
},
// 完成任务
async handleCompleteTask(task) {
try {
const response = await updateTask({
taskId: task.taskId,
state: 2, // 2表示任务已完成
completedTime: new Date()
});
if (response.code === 200) {
uni.showToast({
title: '任务完成',
icon: 'success'
});
this.refreshList();
} else {
uni.showToast({
title: response.msg || '操作失败',
icon: 'none'
});
}
} catch (error) {
uni.showToast({
title: '操作失败,请重试',
icon: 'none'
});
}
}
}
}
</script>
<style lang="scss" scoped>
.task-container {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 120rpx;
}
.search-bar {
padding: 20rpx;
position: sticky;
top: 0;
z-index: 100;
position: relative;
}
.search-container {
display: flex;
align-items: center;
gap: 20rpx;
}
.task-type-button-container {
position: relative;
}
.search-input {
flex: 1;
}
.task-type-button,
.add-button {
width: 60rpx;
height: 60rpx;
background-color: transparent;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.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;
}
}
.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; /* 两行文字的高度32rpx * 1.4 * 2 */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.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;
}
}
.empty-state {
padding: 100rpx 20rpx;
text-align: center;
}
.task-type-panel {
position: absolute;
left: 0;
top: 80rpx;
background-color: #fff;
border-radius: 12rpx;
padding: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
border: 1rpx solid #e9ecef;
z-index: 998;
min-width: 300rpx;
}
.task-type-option {
display: flex;
align-items: center;
gap: 16rpx;
padding: 20rpx;
border-radius: 8rpx;
background-color: #f8f9fa;
border: 1rpx solid #e9ecef;
transition: all 0.2s ease;
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
&:hover {
background-color: rgba($im-primary, 0.05);
}
text {
font-size: 28rpx;
color: #333;
}
}
.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);
}
</style>