Explorar el Código

feat:添加团队管理页面

wangsisi hace 1 semana
padre
commit
7d30377aaa

+ 12 - 18
src/components/pageComponents/FarmInfoCard.vue

@@ -7,8 +7,8 @@
                     <div class="item-header">
                         <div class="farm-name van-ellipsis" :style="{ maxWidth: data.maxWidth || 'calc(100% - 90px)' }">{{ data.farmName }}</div>
                         <div class="tags">
-                            <span class="tag tag-area">{{ data.area }}</span>
-                            <span class="tag tag-variety">{{ data.variety }}</span>
+                            <span class="tag" :class="data.className || 'tag-variety'" v-show="data.variety || data.roleName">{{ data.variety || data.roleName }}</span>
+                            <span class="tag" :class="data.className || 'tag-gray'" v-show="data.area">{{ data.area }}</span>
                         </div>
                     </div>
                     <div class="farm-address van-ellipsis">{{ data.address }}</div>
@@ -36,14 +36,6 @@
                     <div class="remind-cont" v-html="data.broadcasts[0].content"></div>
                     <span class="remind-text" @click.stop="handleRemind">提醒他</span>
                 </div>
-                <!-- <div class="item-footer item-bottom-tip" v-if="data.estimatedIncome">
-                    <div>
-                        当前农场有 <span>{{ data.farmInfo }}</span> 的农情需求
-                    </div>
-                    <div class="income-text">
-                        预计收益 <span>{{ data.estimatedIncome }}元</span>
-                    </div>
-                </div> -->
             </slot>
         </template>
         <upload-execute ref="uploadExecuteRef" :onlyShare="true" />
@@ -60,9 +52,8 @@ const props = defineProps({
         validator: (value) => {
             return (
                 value.farmName !== undefined &&
-                value.area !== undefined &&
-                value.variety !== undefined &&
-                value.address !== undefined
+                value.address !== undefined &&
+                (value.variety !== undefined || value.roleName !== undefined)
             );
         },
     },
@@ -146,16 +137,19 @@ const handleRemind = () => {
                 .tags {
                     display: flex;
                     gap: 6px;
-                    flex: none;
+                    align-items: center;
                     .tag {
                         padding: 1px 8px;
                         border-radius: 2px;
                         font-size: 12px;
-                        &.tag-area {
-                            background: #f4f4f4;
-                            color: #1d2129;
+                        &.tag-gray {
+                            background: rgba(243, 243, 243, 0.5);
+                            color: #7D7D7D;
+                        }
+                        &.tag-role {
+                            background: rgba(255, 149, 61, 0.2);
+                            color: #FF953D;
                         }
-
                         &.tag-variety {
                             background: rgba(232, 243, 255, 1);
                             color: #2199f8;

+ 8 - 11
src/router/globalRoutes.js

@@ -114,11 +114,11 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/modify_work/completedWork.vue"),
     },
-    // 我的档案
+    // 团队管理
     {
-        path: "/archives",
-        name: "Archives",
-        component: () => import("@/views/old_mini/mine/pages/archives.vue"),
+        path: "/team_manage",
+        name: "TeamManage",
+        component: () => import("@/views/old_mini/mine/pages/teamManage.vue"),
     },
     // 农事记录
     {
@@ -245,14 +245,11 @@ export default [
         meta: { keepAlive: true },
         component: () => import("@/views/old_mini/home/subPages/expertDetail.vue"),
     },
-    //认证身份页面
+    //项目管理员
     {
-        path: "/authentication",
-        name: "Authentication",
-        meta: {
-            keepAlive: true,
-        },
-        component: () => import("@/views/old_mini/mine/pages/authentication.vue"),
+        path: "/project_manager",
+        name: "ProjectManager",
+        component: () => import("@/views/old_mini/mine/pages/projectManager.vue"),
     },
     //注册页面
     {

+ 1 - 1
src/styles/common.scss

@@ -312,7 +312,7 @@ div {
             border: 1px solid rgba(153, 153, 153, 0.5);
         }
         &.primary-btn {
-            background: linear-gradient(140deg, #9FD5FF, #2199F8);
+            background: linear-gradient(170deg, #9FD5FF, #2199F8);
             color: #ffffff;
             border: none;
         }

+ 2 - 2
src/views/old_mini/mine/index.vue

@@ -207,7 +207,7 @@ const cellItems = computed(() => {
         return [
             {
                 title: "我的消息",
-                path: "/message_list?from=mine",
+                path: "/message",
             },
             {
                 title: "农事方案",
@@ -227,7 +227,7 @@ const cellItems = computed(() => {
             },
             {
                 title: "团队管理",
-                path: "/service_manage",
+                path: "/team_manage",
             },
         ];
     }

+ 0 - 193
src/views/old_mini/mine/pages/archives.vue

@@ -1,193 +0,0 @@
-<template>
-    <div class="archives-page">
-        <custom-header name="信息化档案"></custom-header>
-        <div class="archives-content">
-            <div class="archives-header">
-                <el-select class="header-item" v-model="value" placeholder="Select" style="width: 240px">
-                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
-                </el-select>
-                <div class="sort header-item" @click="toggleSort">
-                    <span>时间排序</span>
-                    <div class="sort-icon">
-                        <el-icon :class="{ active: sortDirection === 'asc' }"><CaretTop /></el-icon>
-                        <el-icon class="caret-bottom" :class="{ active: sortDirection === 'desc' }"><CaretBottom /></el-icon>
-                    </div>
-                </div>
-            </div>
-            <div class="archives-list">
-                <div class="archives-item" v-for="item in 3" :key="item" @click="handleItem(item)">
-                    <div class="item-content">
-                        <div class="img"></div>
-                        <div class="archives-info">
-                            <div class="info-title">
-                                <span class="title-text">无人机飞巡报告</span>
-                                <span>查看详情</span>
-                            </div>
-                            <div class="info-desc van-multi-ellipsis--l2">果园面积共XX亩,共有XX棵生树本次飞巡拍摄了XX张照片,包括果园面积共XX亩,共有XX棵</div>
-                        </div>
-                    </div>
-                    <div class="item-footer">
-                        <span>来自 从化荔博园</span>
-                        <span>2025.05.28</span>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import { ref } from "vue";
-import { useRouter } from "vue-router";
-
-const router = useRouter();
-
-const value = ref("Option1");
-const options = [
-    {
-        value: "Option1",
-        label: "农事类型",
-    },
-    {
-        value: "Option2",
-        label: "Option2",
-    },
-];
-
-// 排序方向状态:asc-升序,desc-降序,null-无排序
-const sortDirection = ref(null);
-
-// 切换排序方向
-const toggleSort = () => {
-    if (sortDirection.value === null) {
-        sortDirection.value = 'asc';
-    } else if (sortDirection.value === 'asc') {
-        sortDirection.value = 'desc';
-    } else {
-        sortDirection.value = 'asc';
-    }
-    
-    // 这里可以添加实际的排序逻辑
-    console.log('排序方向:', sortDirection.value);
-};
-
-const handleItem = (item) => {
-    router.push("/report_detail");
-}
-</script>
-
-<style lang="scss" scoped>
-.archives-page {
-    width: 100%;
-    height: 100vh;
-    background-color: #f7f7f7;
-    .archives-content {
-        width: 100%;
-        height: 100%;
-        padding: 12px;
-        box-sizing: border-box;
-        .archives-header{
-            display: flex;
-            align-items: center;
-            gap: 10px;
-            .header-item{
-                flex: 1;
-                ::v-deep{
-                    .el-select__wrapper{
-                        padding: 7px 0;
-                        justify-content: center;
-                        background: none;
-                    }
-                    .el-select__selection {
-                        flex: none;
-                        width: fit-content;
-                    }
-                    .el-select__placeholder {
-                        position: static;
-                        transform: none;
-                        width: fit-content;
-                        color: #6D6D6D;
-                    }
-                    .el-select__caret {
-                        color: #6D6D6D;
-                    }
-                }
-            }
-            .sort{
-                display: flex;
-                justify-content: center;
-                align-items: center;
-                color: #6D6D6D;
-                padding: 7px 0;
-                border-radius: 4px;
-                border: 1px solid #DDDDDD;
-                
-                .sort-icon{
-                    display: flex;
-                    flex-direction: column;
-                    margin-left: 2px;
-                    .caret-bottom{
-                        margin-top: -8px;
-                    }
-                    
-                    .el-icon {
-                        color: #6D6D6D;
-                        
-                        &.active {
-                            color: #409EFF;
-                        }
-                    }
-                }
-            }
-        }
-        .archives-list{
-            .archives-item{
-                margin-top: 12px;
-                border-radius: 8px;
-                background: #fff;
-                padding: 10px;
-                .item-content{
-                    display: flex;
-                    margin-bottom: 12px;
-                    .img{
-                        width: 64px;
-                        height: 64px;
-                        border-radius: 8px;
-                        margin-right: 16px;
-                        background-color: red;
-                    }
-                    .archives-info{
-                        width: calc(100% - 64px - 16px);
-                        .info-title{
-                            display: flex;
-                            justify-content: space-between;
-                            align-items: center;
-                            color: #A8A8A8;
-                            font-size: 12px;
-                            .title-text{
-                                font-size: 16px;
-                                font-weight: 500;
-                                color: #000;
-                            }
-                        }
-                        .info-desc{
-                            margin-top: 5px;
-                            font-size: 12px;
-                            color: #575757;
-                        }
-                    }
-                }
-                .item-footer{
-                    border-top: 1px solid rgba(0, 0, 0, 0.1);
-                    padding-top: 12px;
-                    display: flex;
-                    justify-content: space-between;
-                    align-items: center;
-                    color: #999999;
-                }
-            }
-        }
-    }
-}
-</style>

+ 0 - 121
src/views/old_mini/mine/pages/authentication.vue

@@ -1,121 +0,0 @@
-<template>
-    <div class="authentication-page">
-        <custom-header name="认证身份"></custom-header>
-        <div class="content">
-            <span class="text">请选择您要认证的身份</span>
-            <div class="card-group">
-                <div
-                    :class="['card-item', { active: active === index }]"
-                    v-for="(item, index) in list"
-                    :key="index"
-                    @click="handleActive(item, index)"
-                >
-                    <div class="info">
-                        <div class="name">{{ item.name }}</div>
-                        <span>{{ item.desc }}</span>
-                    </div>
-                    <img :src="require(`@/assets/img/mine/${item.icon}-icon.png`)" alt="" />
-                </div>
-            </div>
-            <div class="button" @click="handleOk">选好了</div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import customHeader from "@/components/customHeader.vue";
-import {ref} from 'vue'
-import { useRouter } from "vue-router";
-const router = useRouter();
-
-const list = [
-    {
-        name:"专家",
-        desc:"根据表型触发农事,确认农事处方",
-        icon:"figure",
-        identity:"EXPERT",
-        role:3
-    },
-    {
-        name:"农资农服",
-        desc:"巡飞地形,收集农情测报",
-        icon:"drone",
-        identity:"NZ",
-        role:2
-    },
-]
-    // {
-    //     name:"农服",
-    //     desc:"接单执行,服务农户",
-    //     icon:"shield",
-    //     identity:"NF",
-    //     role:1
-    // }
-
-const active = ref(0)
-const handleActive = (item,index) =>{
-    active.value = index
-}
-
-const handleOk = () =>{
-    router.push(`/register?identity=${list[active.value].identity}&role=${list[active.value].role}`)
-}
-</script>
-
-<style lang="scss" scoped>
-.authentication-page {
-    width: 100%;
-    height: 100vh;
-    background-color: #f5f7fb;
-    .content {
-        height: calc(100% - 40px);
-        padding: 60px 30px;
-        box-sizing: border-box;
-        .text {
-            font-size: 18px;
-        }
-        .card-group {
-            margin-top: 26px;
-            .card-item {
-                background: #fff;
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                padding: 27px 20px;
-                border-radius: 2px;
-                border: 1px solid transparent;
-                &.active {
-                    background: rgba(33, 153, 248, 0.1);
-                    border: 1px solid #2199f8;
-                }
-                .info {
-                    .name {
-                        font-size: 18px;
-                        font-weight: bold;
-                        margin-bottom: 2px;
-                    }
-                    span {
-                        color: rgba(0, 0, 0, 0.2);
-                    }
-                }
-                img {
-                    width: 42px;
-                }
-            }
-
-            .card-item + .card-item {
-                margin-top: 20px;
-            }
-        }
-        .button {
-            color: #fff;
-            border-radius: 2px;
-            background: #2199f8;
-            text-align: center;
-            font-size: 16px;
-            padding: 8px 0;
-            margin-top: 50px;
-        }
-    }
-}
-</style>

+ 52 - 38
src/views/old_mini/mine/pages/message.vue

@@ -3,14 +3,15 @@
         <custom-header name="我的消息" bgColor="#f7f7f7"></custom-header>
         <div class="message-list">
             <div class="message-item" v-for="(item, index) in messageList" :key="index" @click="handleItem(item)">
-                <div class="message">
-                    <badge v-show="item.num" :content="item.num" max="99" :offset="[-15, 5]">
-                        <img class="img" v-if="item.type!=='message'" :src="require(`@/assets/img/mine/${item.type}.png`)" alt="" />
-                        <img class="img" v-else src="@/assets/img/mine/expert.png" alt="">
-                    </badge>
-                    <div class="info">
-                        <span class="name">{{item.name}}</span>
-                        <div class="van-ellipsis">{{item.desc}}</div>
+                <div class="message-content">
+                    <div class="title">{{ item.title }}</div>
+                    <div class="desc">{{ item.desc }}</div>
+                    <div class="footer">
+                        <div class="footer-left">
+                            <span class="view-detail">查看详情</span>
+                            <span class="date">{{ item.date }}</span>
+                        </div>
+                        <el-icon class="arrow-icon"><ArrowRight /></el-icon>
                     </div>
                 </div>
             </div>
@@ -19,30 +20,33 @@
 </template>
 
 <script setup>
-import { Badge } from "vant";
 import { ref } from "vue";
 import { useRouter } from "vue-router";
+import { ArrowRight } from "@element-plus/icons-vue";
 import customHeader from "@/components/customHeader.vue";
 const router = useRouter();
 
 const messageList = ref([
     {
-        name: "指导专家咨询",
-        type: "expert",
-        desc: "从化荔博园:",
-        num: 1,
+        title: "派单提醒: 05.06水稻园某某农事请查收!",
+        desc: "风险描述风险描述风险描述",
+        date: "03-02",
     },
     {
-        name: "农资农服咨询",
-        type: "agricultural",
-        desc: "农资农服:",
-        num: 1,
+        title: "农情互动提醒:",
+        desc: "风险描述风险描述风险描述",
+        date: "03-02",
+    },
+    {
+        title: "农事执行提醒",
+        desc: "风险描述风险描述风险描述",
+        date: "03-02",
     },
 ]);
 
-const handleItem = ({type,name}) =>{
-    router.push("/message_list");
-}
+const handleItem = (item) => {
+    // router.push("/message_list");
+};
 </script>
 
 <style lang="scss" scoped>
@@ -59,31 +63,41 @@ const handleItem = ({type,name}) =>{
         padding: 12px;
         box-sizing: border-box;
         .message-item {
-            display: flex;
-            justify-content: space-between;
             background-color: #fff;
             border-radius: 14px;
-            padding: 10px;
-            .message {
-                width: calc(100% - 64px);
-                display: flex;
-                align-items: center;
-                .img {
-                    width: 48px;
-                    height: 48px;
-                    margin-right: 10px;
+            padding: 16px;
+            .message-content {
+                .title {
+                    font-size: 16px;
+                    font-weight: 500;
+                    margin-bottom: 8px;
                 }
-                .info {
-                    width: 100%;
-                    color: #999999;
-                    line-height: 24px;
-                    .name {
+                .desc {
+                    color: #BBBBBB;
+                    margin-bottom: 10px;
+                }
+                .footer {
+                    display: flex;
+                    align-items: center;
+                    justify-content: space-between;
+                    border-top: 1px solid #F5F5F5;
+                    padding-top: 10px;
+                    .view-detail {
                         color: #333333;
-                        font-size: 16px;
-                        font-weight: 500;
+                        font-size: 14px;
+                        margin-right: 8px;
+                    }
+                    .date {
+                        color: #B6B6B6;
+                        font-size: 14px;
                     }
                 }
             }
+            .arrow-icon {
+                color: #999999;
+                font-size: 16px;
+                margin-left: 12px;
+            }
         }
         .message-item + .message-item {
             margin-top: 12px;

+ 76 - 0
src/views/old_mini/mine/pages/projectManager.vue

@@ -0,0 +1,76 @@
+<template>
+    <div class="authentication-page">
+        <custom-header name="项目管理员"></custom-header>
+        <div class="team-content">
+            <div class="team-list">
+                <farm-info-card
+                    v-for="ele in teamList"
+                    :key="ele.receiveUserId"
+                    class="list-item"
+                    :data="ele"
+                >
+                    <template #right>
+                        <div @click.stop="handleRemoveProjectManager(ele)">移除</div>
+                    </template>
+                </farm-info-card>
+            </div>
+        </div>
+        <div class="custom-bottom-fixed-btns">
+            <div class="bottom-btn primary-btn" @click="handleAddProjectManager">添加项目管理员</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import customHeader from "@/components/customHeader.vue";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
+import { ref } from "vue";
+import { useRouter } from "vue-router";
+const router = useRouter();
+
+const teamList = ref([
+    {
+        farmName: "张张张",
+        roleName: "项目管理员",
+        address: "广东省广州市从化区从化荔博园",
+        receiveUserId: 1,
+    },
+    {
+        farmName: "张扬",
+        roleName: "项目管理员",
+        address: "无人机驾驶员、角色222",
+        receiveUserId: 2,
+    },
+    {
+        farmName: "张扬",
+        roleName: "项目管理员",
+        address: "无人机驾驶员、角色222",
+        receiveUserId: 3,
+    },
+]);
+
+const handleRemoveProjectManager = (item) => {
+    console.log(item);
+};
+
+const handleAddProjectManager = () => {
+    router.push("/team_manage?add=true");
+};
+</script>
+
+<style lang="scss" scoped>
+.authentication-page {
+    width: 100%;
+    height: 100vh;
+    background-color: #f5f7fb;
+    .team-content {
+        width: 100%;
+        height: 100%;
+        padding: 10px 12px;
+        box-sizing: border-box;
+    }
+    .custom-bottom-fixed-btns{
+        justify-content: center;
+    }
+}
+</style>

+ 436 - 0
src/views/old_mini/mine/pages/teamManage.vue

@@ -0,0 +1,436 @@
+<template>
+    <div class="team-management-page">
+        <custom-header :name="route.query.add ? '选择团队成员' : '团队管理'"></custom-header>
+        <div class="team-content">
+            <div class="team-title" v-show="!route.query.add">当前团队总人数(25人)</div>
+            <div class="team-list">
+                <div class="list-item" v-for="ele in teamList" :key="ele.receiveUserId">
+                    <checkbox v-if="route.query.add" @change="changeCheck" v-model="ele.checked"></checkbox>
+                    <farm-info-card class="item-info" @click="handleItem(ele)" :style="{ width: !route.query.add ? '100%' : 'calc(100% - 55px)' }" :data="ele">
+                        <template #right v-if="ele.receiveUserId != 1 && !route.query.add">
+                            <div @click.stop="handlePermission(ele)">权限设置</div>
+                        </template>
+                    </farm-info-card>
+                </div>
+            </div>
+        </div>
+        <div class="custom-bottom-fixed-btns">
+            <div class="bottom-btn secondary-btn" @click="handleSetAdmin">
+                {{ route.query.add ? "取消选择" : "设置管理员" }}
+            </div>
+            <div class="bottom-btn primary-btn" @click="handleAddTeamMember">
+                {{ route.query.add ? "确认设为" : "新增团队成员" }}
+            </div>
+        </div>
+
+        <!-- 新增团队成员弹窗 -->
+        <popup
+            v-model:show="showAddMemberPopup"
+            closeable
+            round
+            class="add-member-popup"
+            :close-on-click-overlay="false"
+            @closed="handlePopupClosed"
+        >
+            <div class="popup-content">
+                <div class="popup-title">新增团队成员</div>
+                <el-form ref="formRef" :model="formData" label-position="top" class="member-form" size="large">
+                    <el-form-item label="姓名">
+                        <el-input v-model="formData.name" placeholder="请输入姓名" clearable />
+                    </el-form-item>
+                    <el-form-item label="手机号">
+                        <el-input v-model="formData.phone" placeholder="请输入手机号" clearable maxlength="11" />
+                    </el-form-item>
+                    <el-form-item label="角色类型">
+                        <div class="role-type-grid">
+                            <div
+                                v-for="role in roleTypes"
+                                :key="role.value"
+                                class="role-btn"
+                                :class="{ active: formData.roleType === role.value }"
+                                @click="formData.roleType = role.value"
+                            >
+                                {{ role.label }}
+                            </div>
+                        </div>
+                    </el-form-item>
+                </el-form>
+                <div class="popup-footer">
+                    <div class="footer-btn share-btn" @click="handleShare">分享微信好友</div>
+                    <div class="footer-btn confirm-btn" @click="handleConfirm">确认添加</div>
+                </div>
+            </div>
+        </popup>
+
+        <!-- 权限设置弹窗 -->
+        <popup
+            v-model:show="showPermissionPopup"
+            closeable
+            round
+            class="add-member-popup"
+            :close-on-click-overlay="false"
+            @closed="handlePermissionPopupClosed"
+        >
+            <div class="popup-content">
+                <div class="popup-title">权限设置</div>
+                <div class="role-type-grid permission-list">
+                    <div
+                        v-for="permission in permissionTypes"
+                        :key="permission.value"
+                        class="role-btn"
+                        :class="{ active: permissionData.selectedPermission === permission.value }"
+                        @click="togglePermission(permission.value)"
+                    >
+                        {{ permission.label }}
+                    </div>
+                </div>
+                <div class="popup-footer">
+                    <div class="footer-btn cancel-admin-btn" @click="handleCancelAdmin">取消管理员</div>
+                    <div class="footer-btn confirm-btn" @click="handleConfirmPermission">确认设置</div>
+                </div>
+            </div>
+        </popup>
+    </div>
+</template>
+
+<script setup>
+import customHeader from "@/components/customHeader.vue";
+import { ref, reactive, onMounted } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import { Popup, Checkbox } from "vant";
+import { ElMessage } from "element-plus";
+import FarmInfoCard from "@/components/pageComponents/FarmInfoCard.vue";
+
+const router = useRouter();
+const formRef = ref(null);
+const showAddMemberPopup = ref(false);
+const showPermissionPopup = ref(false);
+const currentPermissionItem = ref(null);
+const route = useRoute();
+
+onMounted(() => {
+    if (route.query.add) {
+        teamList.value = [
+            {
+                farmName: "张张张",
+                checked: false,
+                roleName: "超级管理员",
+                className: "tag-role",
+                address: "广东省广州市从化区从化荔博园",
+                receiveUserId: 1,
+            },
+            {
+                farmName: "张扬",
+                checked: false,
+                roleName: "普通成员",
+                className: "tag-gray",
+                address: "无人机驾驶员、角色222",
+                receiveUserId: 2,
+            },
+            {
+                farmName: "张扬",
+                checked: false,
+                roleName: "普通成员",
+                className: "tag-gray",
+                address: "无人机驾驶员、角色222",
+                receiveUserId: 3,
+            },
+        ];
+    } else {
+        teamList.value = [
+            {
+                farmName: "张张张",
+                roleName: "超级管理员",
+                className: "tag-role",
+                address: "广东省广州市从化区从化荔博园",
+                receiveUserId: 1,
+            },
+            {
+                farmName: "张扬",
+                roleName: "项目管理员",
+                address: "无人机驾驶员、角色222",
+                receiveUserId: 2,
+            },
+            {
+                farmName: "张扬",
+                roleName: "普通成员",
+                className: "tag-gray",
+                address: "无人机驾驶员、角色222",
+                receiveUserId: 3,
+            },
+        ];
+    }
+});
+
+const filterList = ref([]);
+const changeCheck = () => {
+    filterList.value = teamList.value.filter((item) => item.checked);
+    console.log("filterList",filterList.value);
+};
+
+const teamList = ref([]);
+
+// 角色类型选项
+const roleTypes = ref([
+    { label: "无人机驾驶员", value: "pilot" },
+    { label: "项目管理员", value: "admin" },
+    { label: "普通成员", value: "member" },
+    { label: "其他", value: "other" },
+]);
+
+// 表单数据
+const formData = reactive({
+    name: "",
+    phone: "",
+    roleType: "pilot", // 默认选中无人机驾驶员
+});
+
+// 权限类型选项
+const permissionTypes = ref([
+    { label: "转入农事权限", value: "transfer" },
+    { label: "增删成员", value: "member" },
+    { label: "任务接单", value: "task" },
+    { label: "农事规划", value: "plan" },
+]);
+
+// 权限数据
+const permissionData = reactive({
+    selectedPermission: "transfer", // 默认选中转入农事权限
+});
+
+const handlePermission = (item) => {
+    currentPermissionItem.value = item;
+    // TODO: 从item中获取当前用户的权限设置
+    // 这里先使用默认值
+    permissionData.selectedPermission = "transfer";
+    showPermissionPopup.value = true;
+};
+
+// 切换权限选择(单选)
+const togglePermission = (value) => {
+    permissionData.selectedPermission = value;
+};
+
+// 权限弹窗关闭处理
+const handlePermissionPopupClosed = () => {
+    currentPermissionItem.value = null;
+    permissionData.selectedPermission = "transfer";
+};
+
+// 取消管理员
+const handleCancelAdmin = () => {
+    // TODO: 实现取消管理员功能
+    showPermissionPopup.value = false;
+};
+
+// 确认权限设置
+const handleConfirmPermission = () => {
+    // TODO: 调用API保存权限设置
+    ElMessage.success("权限设置成功");
+    showPermissionPopup.value = false;
+};
+
+// 弹窗关闭处理
+const handlePopupClosed = () => {
+    // 重置表单
+    formData.name = "";
+    formData.phone = "";
+    formData.roleType = "pilot";
+};
+
+// 分享微信好友
+const handleShare = () => {
+    ElMessage.info("分享功能待实现");
+    // TODO: 实现分享到微信好友的功能
+};
+
+// 确认添加
+const handleConfirm = () => {
+    // 验证姓名
+    if (!formData.name || !formData.name.trim()) {
+        ElMessage.warning("请输入姓名");
+        return;
+    }
+
+    // 验证手机号
+    if (!formData.phone || !formData.phone.trim()) {
+        ElMessage.warning("请输入手机号");
+        return;
+    }
+
+    // 验证手机号格式
+    const phonePattern = /^1[3-9]\d{9}$/;
+    if (!phonePattern.test(formData.phone)) {
+        ElMessage.warning("请输入正确的手机号");
+        return;
+    }
+
+    // 验证角色类型
+    if (!formData.roleType) {
+        ElMessage.warning("请选择角色类型");
+        return;
+    }
+
+    // 验证通过,执行添加操作
+    // TODO: 调用API添加团队成员
+    ElMessage.success("添加成功");
+    showAddMemberPopup.value = false;
+    // 可以在这里刷新团队列表
+};
+
+const handleAddTeamMember = () => {
+    if (route.query.add) {
+        if (filterList.value.length) {
+            showPermissionPopup.value = true;
+        } else {
+            ElMessage.warning("请选择团队成员");
+            return;
+        }
+    } else {
+        showAddMemberPopup.value = true;
+    }
+};
+
+const handleSetAdmin = () => {
+    if (route.query.add) {
+        teamList.value = teamList.value.map((item) => {
+            item.checked = false;
+            return item;
+        });
+    } else {
+        router.push("/project_manager");
+    }
+};
+
+const handleItem = (item) => {
+    if (route.query.add) {
+        item.checked = !item.checked;
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.team-management-page {
+    width: 100%;
+    height: 100vh;
+    background-color: #f5f7fb;
+    .team-content {
+        width: 100%;
+        height: 100%;
+        padding: 10px 12px;
+        box-sizing: border-box;
+        .team-title {
+            margin-bottom: 10px;
+        }
+        .team-list{
+            .list-item{
+                display: flex;
+                justify-content: space-between;
+                width: 100%;
+                .item-info{
+                    width: calc(100% - 55px);
+                }
+            }
+            .list-item + .list-item{
+                margin-top: 10px;
+            }
+        }
+    }
+}
+
+.add-member-popup {
+    width: 90%;
+    max-width: 400px;
+    box-sizing: border-box;
+    padding: 24px 18px 20px;
+    background: #ffffff;
+    border-radius: 10px;
+
+    ::v-deep {
+        .van-popup__close-icon {
+            color: #000;
+            font-size: 18px;
+        }
+    }
+
+    .popup-content {
+        .popup-title {
+            font-size: 18px;
+            font-weight: 600;
+            color: #000;
+            text-align: center;
+            margin-bottom: 15px;
+        }
+
+        .member-form {
+            ::v-deep {
+                .el-form-item {
+                    .el-form-item__label {
+                        font-size: 15px;
+                        color: #000;
+                    }
+                }
+            }
+        }
+
+        .role-type-grid {
+            display: flex;
+            flex-wrap: wrap;
+            justify-content: space-between;
+            gap: 10px 0;
+            width: 100%;
+
+            .role-btn {
+                width: calc(50% - 8px);
+                border-radius: 4px;
+                text-align: center;
+                font-size: 14px;
+                color: rgba(0, 0, 0, 0.26);
+                border: 1px solid rgba(0, 0, 0, 0.26);
+
+                &.active {
+                    background: #2199f8;
+                    color: #ffffff;
+                    border-color: #2199f8;
+                }
+            }
+
+            &.permission-list{
+                .role-btn{
+                    padding: 10px 0;
+                }
+            }
+        }
+
+        .popup-footer {
+            display: flex;
+            gap: 20px;
+            margin-top: 30px;
+            padding-top: 20px;
+            border-top: 1px solid rgba(0, 0, 0, 0.1);
+
+            .footer-btn {
+                flex: 1;
+                padding: 10px 20px;
+                border-radius: 25px;
+                text-align: center;
+                font-size: 16px;
+                color: #ffffff;
+
+                &.share-btn {
+                    background: #ff953d;
+                }
+
+                &.confirm-btn {
+                    background: #2199f8;
+                }
+
+                &.cancel-admin-btn {
+                    color: #666666;
+                    border: 1px solid rgba(153, 153, 153, 0.5);
+                }
+            }
+        }
+    }
+}
+</style>