瀏覽代碼

提交代码

zlwu 1 年之前
父節點
當前提交
d634846222

+ 2 - 2
mobile/src/components/FileUpload/index.vue

@@ -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;
 }
 

+ 6 - 4
mobile/src/components/Process/submitVerify.vue

@@ -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 {

+ 14 - 13
mobile/src/components/UserSelect/index.vue

@@ -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 {

+ 8 - 0
mobile/src/pages.json

@@ -33,6 +33,14 @@
 				"navigationBarTextStyle": "white"
 			}
 		},
+		{
+			"path": "pages/task/taskWaiting",
+			"style": {
+				"navigationBarTitleText": "我的待办",
+				"navigationBarBackgroundColor": "#0051d9",
+				"navigationBarTextStyle": "white"
+			}
+		},
 		{
 			"path": "pages/task/taskFinish",
 			"style": {

+ 1 - 1
mobile/src/pages/index/index.vue

@@ -725,7 +725,7 @@ export default {
         // 跳转到我的待办
         gotoAllTaskWaiting() {
             uni.navigateTo({
-                url: '/pages/task/allTaskWaiting',
+                url: '/pages/task/taskWaiting',
             });
         },
 

+ 836 - 0
mobile/src/pages/task/taskWaiting.vue

@@ -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>