提交代码
This commit is contained in:
1 parent
ed9826f92b
commit
d634846222
6 files changed
+867
-20
No files matched your search
@@ -599,7 +599,7 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
.file-upload-container {
|
||||
width: 90%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ export default {
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
max-height: 400rpx;
|
||||
max-height: 250rpx;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<u-popup
|
||||
:show="visible"
|
||||
mode="center"
|
||||
width="85%"
|
||||
width="100%"
|
||||
height="90%"
|
||||
border-radius="12"
|
||||
@close="cancel"
|
||||
:custom-style="{ width: '80vw' }"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
>
|
||||
<view class="submit-verify-container">
|
||||
<view class="header">
|
||||
@@ -198,7 +198,7 @@
|
||||
>
|
||||
退回
|
||||
</u-button>
|
||||
<u-button type="info" @click="cancel" class="action-btn">取消</u-button>
|
||||
<!-- <u-button type="info" @click="cancel" class="action-btn">取消</u-button> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -245,10 +245,11 @@
|
||||
<u-popup
|
||||
:show="backVisible"
|
||||
mode="center"
|
||||
width="90%"
|
||||
width="80%"
|
||||
height="70%"
|
||||
border-radius="12"
|
||||
@close="backVisible = false"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
>
|
||||
<view class="back-container">
|
||||
<view class="header">
|
||||
@@ -1109,6 +1110,7 @@ export default {
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 30rpx;
|
||||
width: 90% !important;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<u-popup
|
||||
v-model="visible"
|
||||
:show="visible"
|
||||
mode="center"
|
||||
width="95%"
|
||||
height="85%"
|
||||
border-radius="12"
|
||||
@close="close"
|
||||
:custom-style="{ width: '90vw' }"
|
||||
>
|
||||
<view class="user-select-container">
|
||||
<!-- 标题栏 -->
|
||||
@@ -40,7 +41,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 部门选择 -->
|
||||
<view class="dept-section">
|
||||
<!-- <view class="dept-section">
|
||||
<u-subsection
|
||||
:list="deptList"
|
||||
v-model="currentDeptIndex"
|
||||
@@ -48,10 +49,10 @@
|
||||
activeColor="#2979ff"
|
||||
fontSize="28rpx"
|
||||
/>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 用户列表 -->
|
||||
<view class="user-list">
|
||||
<scroll-view class="user-list" scroll-y="true" @scrolltolower="loadMore">
|
||||
<u-loading-page
|
||||
v-if="loading"
|
||||
loading-text="正在加载用户列表..."
|
||||
@@ -89,12 +90,12 @@
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 分页加载 -->
|
||||
<view v-if="!loading && userList.length > 0" class="load-more">
|
||||
<u-loadmore :status="loadStatus" @loadmore="loadMore" color="#2979ff" />
|
||||
</view>
|
||||
<!-- 分页加载提示 -->
|
||||
<!-- <view v-if="!loading && userList.length > 0" class="load-more">
|
||||
<u-loadmore :status="loadStatus" color="#2979ff" />
|
||||
</view> -->
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="footer">
|
||||
@@ -193,7 +194,7 @@ export default {
|
||||
async getDeptList() {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/system/dept/treeselect',
|
||||
url: '/system/user/deptTree',
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
@@ -294,7 +295,7 @@ export default {
|
||||
|
||||
// 加载更多
|
||||
loadMore() {
|
||||
if (this.loadStatus === 'loadmore') {
|
||||
if (this.loadStatus === 'loadmore' && !this.loading) {
|
||||
this.queryParams.pageNum++;
|
||||
this.getUserList(true);
|
||||
}
|
||||
@@ -457,9 +458,9 @@ export default {
|
||||
}
|
||||
|
||||
.user-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
height: 600rpx; /* 固定高度 */
|
||||
padding: 0 30rpx;
|
||||
width: 90% !important;
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/task/taskWaiting",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的待办",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/task/taskFinish",
|
||||
"style": {
|
||||
|
||||
@@ -725,7 +725,7 @@ export default {
|
||||
// 跳转到我的待办
|
||||
gotoAllTaskWaiting() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/task/allTaskWaiting',
|
||||
url: '/pages/task/taskWaiting',
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,836 @@
|
||||
<template>
|
||||
<view class="task-waiting-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="我的待办" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 搜索区域 -->
|
||||
<view class="search-container">
|
||||
<u-search
|
||||
v-model="queryParams.flowName"
|
||||
placeholder="请输入流程定义名称"
|
||||
:show-action="true"
|
||||
action-text="搜索"
|
||||
:animation="true"
|
||||
@search="handleQuery"
|
||||
@custom="handleQuery"
|
||||
></u-search>
|
||||
|
||||
<!-- 申请人选择 -->
|
||||
<view class="filter-section">
|
||||
<view class="filter-item" @click="openUserSelect">
|
||||
<u-icon name="account" size="20" color="#3c9cff"></u-icon>
|
||||
<text class="filter-text">
|
||||
{{
|
||||
selectedUsers.length > 0
|
||||
? `已选择${selectedUsers.length}个申请人`
|
||||
: '选择申请人'
|
||||
}}
|
||||
</text>
|
||||
<u-badge
|
||||
v-if="selectedUsers.length > 0"
|
||||
:count="selectedUsers.length"
|
||||
:max="99"
|
||||
></u-badge>
|
||||
<u-icon name="arrow-right" size="16" color="#c0c4cc"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page
|
||||
:loading="loading && taskList.length === 0"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 待办任务列表 -->
|
||||
<view v-if="!loading || taskList.length > 0" class="content-wrapper">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="taskList.length === 0 && !loading" class="empty-container">
|
||||
<u-empty text="暂无待办任务" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 任务卡片列表 -->
|
||||
<view v-else class="task-list">
|
||||
<view v-for="(item, index) in taskList" :key="item.id || index" class="task-card">
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="task-title">{{ item.flowName || '-' }}</view>
|
||||
<view class="task-status">
|
||||
<u-tag
|
||||
:text="getFlowStatusText(item.flowStatus)"
|
||||
:type="getFlowStatusType(item.flowStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-item">
|
||||
<text class="label">流程编码:</text>
|
||||
<text class="value">{{ item.flowCode || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">流程分类:</text>
|
||||
<text class="value">{{ item.categoryName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">任务名称:</text>
|
||||
<text class="value">{{ item.nodeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">申请人:</text>
|
||||
<text class="value">{{ item.createByName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">办理人:</text>
|
||||
<view class="assignee-tags">
|
||||
<template v-if="item.assigneeNames">
|
||||
<u-tag
|
||||
v-for="(name, idx) in item.assigneeNames.split(',')"
|
||||
:key="idx"
|
||||
:text="name"
|
||||
type="success"
|
||||
size="mini"
|
||||
style="margin-right: 8rpx; margin-bottom: 8rpx"
|
||||
></u-tag>
|
||||
</template>
|
||||
<u-tag v-else text="无" type="info" size="mini"></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">创建时间:</text>
|
||||
<text class="value">{{ formatTime(item.createTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<view class="action-btn primary-btn" @click="handleApproval(item)">
|
||||
<u-icon name="edit-pen" size="16" color="#3c9cff"></u-icon>
|
||||
<text class="btn-text">办理</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 滚动加载更多 -->
|
||||
<u-loadmore
|
||||
v-if="taskList.length > 0"
|
||||
:status="loadmoreStatus"
|
||||
:load-text="{
|
||||
loadmore: '轻轻上拉',
|
||||
loading: '努力加载中',
|
||||
nomore: '没有更多了',
|
||||
}"
|
||||
@loadmore="loadMore"
|
||||
></u-loadmore>
|
||||
</view>
|
||||
|
||||
<!-- 申请人选择弹窗 -->
|
||||
<u-popup
|
||||
:show="userSelectDialog.visible"
|
||||
mode="bottom"
|
||||
:round="14"
|
||||
@close="cancelUserSelect"
|
||||
>
|
||||
<view class="user-select-popup">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">选择申请人</text>
|
||||
<u-icon
|
||||
name="close"
|
||||
@click="cancelUserSelect"
|
||||
size="24"
|
||||
color="#909399"
|
||||
></u-icon>
|
||||
</view>
|
||||
|
||||
<view class="popup-content">
|
||||
<u-search
|
||||
v-model="userSearchKeyword"
|
||||
placeholder="搜索用户名或姓名"
|
||||
:show-action="false"
|
||||
@input="searchUsers"
|
||||
style="height: 60rpx !important"
|
||||
></u-search>
|
||||
|
||||
<scroll-view scroll-y class="user-list">
|
||||
<view
|
||||
v-for="user in userList"
|
||||
:key="user.userId"
|
||||
class="user-item"
|
||||
@click="toggleUserSelect(user)"
|
||||
>
|
||||
<view class="user-info">
|
||||
<u-avatar :text="getAvatarText(user.nickName)" size="40"></u-avatar>
|
||||
<view class="user-details">
|
||||
<text class="user-name">{{ user.nickName }}</text>
|
||||
<text class="user-username">{{ user.userName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-checkbox
|
||||
v-model="user.selected"
|
||||
@change="onCheckboxChange(user, $event)"
|
||||
@click.stop
|
||||
></u-checkbox>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="popup-footer">
|
||||
<u-button @click="cancelUserSelect" type="info" size="default">取消</u-button>
|
||||
<u-button @click="confirmUserSelect" type="primary" size="default">
|
||||
确定
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/common/request.js';
|
||||
import { getDict, getDictTagType } from '@/common/dict.js';
|
||||
|
||||
export default {
|
||||
name: 'TaskWaiting',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
taskList: [],
|
||||
total: 0,
|
||||
loadmoreStatus: 'loadmore', // loadmore, loading, nomore
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
flowName: '', // 流程定义名称
|
||||
createByIds: [], // 申请人IDs
|
||||
},
|
||||
|
||||
// 流程状态字典
|
||||
flowStatusDict: [],
|
||||
|
||||
// 申请人选择相关
|
||||
userSelectDialog: {
|
||||
visible: false,
|
||||
},
|
||||
selectedUsers: [], // 已选择的申请人
|
||||
userList: [], // 用户列表
|
||||
userSearchKeyword: '', // 用户搜索关键词
|
||||
userSearchTimer: null, // 搜索防抖定时器
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.loadFlowStatusDict();
|
||||
await this.getList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载流程状态字典
|
||||
async loadFlowStatusDict() {
|
||||
try {
|
||||
this.flowStatusDict = await getDict('wf_business_status');
|
||||
console.log('流程状态字典加载完成:', this.flowStatusDict);
|
||||
} catch (error) {
|
||||
console.error('加载流程状态字典失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 获取流程状态显示文本
|
||||
getFlowStatusText(status) {
|
||||
if (!this.flowStatusDict || this.flowStatusDict.length === 0) {
|
||||
// 字典未加载时的降级处理
|
||||
const statusMap = {
|
||||
0: '待提交',
|
||||
1: '审批中',
|
||||
2: '已通过',
|
||||
3: '已拒绝',
|
||||
4: '已撤回',
|
||||
5: '已终止',
|
||||
6: '已作废',
|
||||
};
|
||||
return statusMap[status] || '未知';
|
||||
}
|
||||
|
||||
const statusItem = this.flowStatusDict.find((item) => item.value === status);
|
||||
return statusItem ? statusItem.label : '未知';
|
||||
},
|
||||
|
||||
// 获取流程状态标签类型
|
||||
getFlowStatusType(status) {
|
||||
const fallbackMap = {
|
||||
0: 'info', // 待提交
|
||||
1: 'warning', // 审批中
|
||||
2: 'success', // 已通过
|
||||
3: 'error', // 已拒绝
|
||||
4: 'info', // 已撤回
|
||||
5: 'error', // 已终止
|
||||
6: 'error', // 已作废
|
||||
};
|
||||
return getDictTagType(this.flowStatusDict, status, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取待办任务列表
|
||||
async getList(isLoadMore = false) {
|
||||
if (!isLoadMore) {
|
||||
this.loading = true;
|
||||
this.queryParams.pageNum = 1;
|
||||
} else {
|
||||
this.loadmoreStatus = 'loading';
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/workflow/task/pageByTaskWait',
|
||||
method: 'GET',
|
||||
params: {
|
||||
pageNum: this.queryParams.pageNum,
|
||||
pageSize: this.queryParams.pageSize,
|
||||
flowName: this.queryParams.flowName || undefined,
|
||||
createByIds:
|
||||
this.queryParams.createByIds.length > 0
|
||||
? this.queryParams.createByIds
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
const newList = res.rows || [];
|
||||
|
||||
if (isLoadMore) {
|
||||
this.taskList = [...this.taskList, ...newList];
|
||||
// 判断是否还有更多数据
|
||||
if (newList.length < this.queryParams.pageSize) {
|
||||
this.loadmoreStatus = 'nomore';
|
||||
} else {
|
||||
this.loadmoreStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
this.taskList = newList;
|
||||
this.total = res.total || 0;
|
||||
// 重置加载更多状态
|
||||
if (this.taskList.length >= this.total) {
|
||||
this.loadmoreStatus = 'nomore';
|
||||
} else {
|
||||
this.loadmoreStatus = 'loadmore';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isLoadMore) {
|
||||
this.taskList = [];
|
||||
this.total = 0;
|
||||
}
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
if (isLoadMore) {
|
||||
this.loadmoreStatus = 'loadmore';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取待办任务列表失败:', error);
|
||||
if (!isLoadMore) {
|
||||
this.taskList = [];
|
||||
this.total = 0;
|
||||
}
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
if (isLoadMore) {
|
||||
this.loadmoreStatus = 'loadmore';
|
||||
}
|
||||
} finally {
|
||||
if (!isLoadMore) {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
loadMore() {
|
||||
if (this.loadmoreStatus === 'nomore' || this.loadmoreStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.queryParams.pageNum++;
|
||||
this.getList(true);
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(timeStr) {
|
||||
if (!timeStr) return '-';
|
||||
try {
|
||||
const date = new Date(timeStr);
|
||||
if (isNaN(date.getTime())) return timeStr;
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
} catch (error) {
|
||||
console.error('时间格式化失败:', error);
|
||||
return timeStr;
|
||||
}
|
||||
},
|
||||
|
||||
// 办理任务
|
||||
handleApproval(row) {
|
||||
console.log('办理任务:', row);
|
||||
|
||||
// 动态跳转到formPath对应的路径,携带businessId和taskId参数
|
||||
if (row.formPath) {
|
||||
// 确保路径以pages开头
|
||||
let fullPath = row.formPath;
|
||||
|
||||
// 统一处理路径:去掉开头的/,然后添加pages前缀
|
||||
if (!fullPath.startsWith('pages/')) {
|
||||
// 如果以/开头,先去掉/
|
||||
if (fullPath.startsWith('/')) {
|
||||
fullPath = fullPath.substring(1);
|
||||
}
|
||||
// 添加pages前缀
|
||||
fullPath = `pages/${fullPath}`;
|
||||
}
|
||||
|
||||
const url = `/${fullPath}?id=${row.businessId}&taskId=${row.id}&type=approval`;
|
||||
|
||||
// 添加调试信息
|
||||
console.log('办理任务 - 原始formPath:', row.formPath);
|
||||
console.log('办理任务 - 处理后的fullPath:', fullPath);
|
||||
console.log('办理任务 - 最终跳转URL:', url);
|
||||
|
||||
// 使用navigateTo进行跳转
|
||||
uni.navigateTo({
|
||||
url: url,
|
||||
fail: (err) => {
|
||||
console.error('办理页面跳转失败:', err);
|
||||
// 如果跳转失败,使用原有逻辑作为备选
|
||||
this.fallbackApproval(row);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// 如果没有formPath,使用原有逻辑作为备选
|
||||
this.fallbackApproval(row);
|
||||
}
|
||||
},
|
||||
|
||||
// 备选办理方法(原有逻辑)
|
||||
fallbackApproval(row) {
|
||||
console.log('使用备选办理逻辑:', row);
|
||||
// 根据表单类型跳转到对应的审批页面
|
||||
if (row.formCustom === 'Y') {
|
||||
// 自定义表单
|
||||
uni.navigateTo({
|
||||
url: `/pages/workflow/form/custom?businessId=${row.businessId}&taskId=${
|
||||
row.id
|
||||
}&formPath=${encodeURIComponent(row.formPath || '')}`,
|
||||
});
|
||||
} else {
|
||||
// 默认表单或其他类型
|
||||
uni.navigateTo({
|
||||
url: `/pages/workflow/approval/index?businessId=${row.businessId}&taskId=${row.id}&type=approval`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 打开申请人选择
|
||||
openUserSelect() {
|
||||
this.userSelectDialog.visible = true;
|
||||
this.loadUserList();
|
||||
},
|
||||
|
||||
// 取消申请人选择
|
||||
cancelUserSelect() {
|
||||
this.userSelectDialog.visible = false;
|
||||
this.userSearchKeyword = '';
|
||||
},
|
||||
|
||||
// 确认申请人选择
|
||||
confirmUserSelect() {
|
||||
// 获取当前弹窗中选中的用户
|
||||
const currentSelected = this.userList.filter((user) => user.selected);
|
||||
|
||||
console.log('确认选择 - 用户列表:', this.userList);
|
||||
console.log('确认选择 - 选中的用户:', currentSelected);
|
||||
|
||||
if (currentSelected.length > 0) {
|
||||
// 如果有选中的用户,更新已选择的用户列表
|
||||
this.selectedUsers = currentSelected;
|
||||
this.queryParams.createByIds = currentSelected.map((user) => user.userId);
|
||||
console.log('更新选中用户:', this.selectedUsers);
|
||||
} else {
|
||||
// 如果没有选中任何用户,清空已选择的用户列表
|
||||
this.selectedUsers = [];
|
||||
this.queryParams.createByIds = [];
|
||||
console.log('清空选中用户');
|
||||
}
|
||||
|
||||
this.userSelectDialog.visible = false;
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// 切换用户选择状态
|
||||
toggleUserSelect(user) {
|
||||
this.$set(user, 'selected', !user.selected);
|
||||
console.log('切换用户选择:', user.nickName, '选中状态:', user.selected);
|
||||
},
|
||||
|
||||
// checkbox变化处理
|
||||
onCheckboxChange(user, value) {
|
||||
console.log('Checkbox变化:', user.nickName, '新值:', value);
|
||||
this.$set(user, 'selected', value);
|
||||
},
|
||||
|
||||
// 加载用户列表
|
||||
async loadUserList() {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/system/user/list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
pageNum: 1,
|
||||
pageSize: 100,
|
||||
userName: this.userSearchKeyword || undefined,
|
||||
nickName: this.userSearchKeyword || undefined,
|
||||
},
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
// 每次加载用户列表时,所有用户默认都不选中
|
||||
this.userList = (res.rows || []).map((user) => ({
|
||||
...user,
|
||||
selected: false,
|
||||
}));
|
||||
console.log('加载用户列表完成,用户数量:', this.userList.length);
|
||||
} else {
|
||||
this.userList = [];
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取用户列表失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error);
|
||||
this.userList = [];
|
||||
uni.showToast({
|
||||
title: '获取用户列表失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 搜索用户(防抖处理)
|
||||
searchUsers() {
|
||||
if (this.userSearchTimer) {
|
||||
clearTimeout(this.userSearchTimer);
|
||||
}
|
||||
|
||||
this.userSearchTimer = setTimeout(() => {
|
||||
this.loadUserList();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
// 获取头像显示文字(取前两个字符)
|
||||
getAvatarText(nickName) {
|
||||
if (!nickName) return '';
|
||||
// 取前两个字符,如果只有一个字符则返回该字符
|
||||
return nickName.length > 1 ? nickName.substring(0, 1) : nickName;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.task-waiting-container {
|
||||
background-color: #f5f6fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 12rpx;
|
||||
border: 1px solid #e4e7ed;
|
||||
|
||||
&:active {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-text {
|
||||
flex: 1;
|
||||
margin-left: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
padding: 100rpx 20rpx;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.task-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.task-status {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
min-width: 140rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.assignee-tags {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16rpx 40rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f8f9fa;
|
||||
min-width: 120rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
background-color: rgba(60, 156, 255, 0);
|
||||
|
||||
.btn-text {
|
||||
color: #3c9cff;
|
||||
}
|
||||
}
|
||||
|
||||
// 申请人选择弹窗样式
|
||||
.user-select-popup {
|
||||
background-color: #fff;
|
||||
border-radius: 14rpx 14rpx 0 0;
|
||||
overflow: hidden;
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
flex-shrink: 0; /* 防止头部被压缩 */
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
flex: 1;
|
||||
padding: 24rpx 24rpx 0 24rpx; /* 底部不需要padding,由footer提供 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
}
|
||||
|
||||
.user-list {
|
||||
margin-top: 20rpx;
|
||||
flex: 1; /* 使用弹性布局,自动占满剩余空间 */
|
||||
overflow-y: auto; /* 添加垂直滚动条 */
|
||||
min-height: 0; /* 确保flex子元素可以收缩 */
|
||||
}
|
||||
|
||||
.user-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #f8f9fa;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-details {
|
||||
margin-left: 20rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-username {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
padding: 24rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-shrink: 0; /* 防止底部按钮区域被压缩 */
|
||||
background-color: #fff; /* 确保背景色一致 */
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-search {
|
||||
background-color: #f5f6fa;
|
||||
/* 清除默认的 flex: 1 */
|
||||
flex: none;
|
||||
}
|
||||
|
||||
// 弹窗内搜索框样式优化
|
||||
.popup-content ::v-deep .u-search {
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 0; /* 移除默认margin */
|
||||
}
|
||||
|
||||
.popup-content ::v-deep .u-search__content {
|
||||
height: 60rpx; /* 设置搜索框高度 */
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.popup-content ::v-deep .u-input {
|
||||
font-size: 28rpx; /* 调整输入框字体大小 */
|
||||
}
|
||||
|
||||
::v-deep .u-tag {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
::v-deep .u-loadmore {
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user