Browse Source

最新需求修改:项目-公司-团队

htc 2 days ago
parent
commit
448203d3a9

+ 38 - 1
src/api/agent/index.js

@@ -114,9 +114,46 @@ export function getPersonQueList(query) {
 // ---end 问卷管理
 
 // ---start 项目管理
+export function getProgramList(query) {
+  return request({
+    url: '/core/program/page',
+    method: 'get',
+    params: query
+  })
+}
+export function addProgram(data) {
+  return request({
+    url: '/core/program',
+    method: 'post',
+    data
+  })
+}
+export function updateProgram(data) {
+  return request({
+    url: '/core/program',
+    method: 'put',
+    data
+  })
+}
+export function getProgramInfo(query) {
+  return request({
+    url: `core/program/${query}`,
+    method: 'get'
+  })
+}
+export function deleteProgram(data) {
+  return request({
+    url: `/core/program`,
+    method: 'delete',
+    data
+  })
+}
+// ---end 项目管理
+
+// ---start 公司管理
 export function getCoachProgramList(query) {
   return request({
-    url: '/core/project/listByCoach',
+    url: '/core/project/list',
     method: 'get',
     params: query
   })

+ 7 - 0
src/assets/scss/global.scss

@@ -6,6 +6,13 @@
 .el-button--text,.el-checkbox__input.is-checked+.el-checkbox__label{
     color: #761E6A !important;
 }
+.el-button--danger{
+    background: #FFFFFF !important;
+    border-color: #761E6A !important;
+}
+.el-button.el-button--danger.el-button--default i,.el-button.el-button--danger.el-button--default span{
+    color: #761E6A !important;
+}
 .el-radio__input.is-checked .el-radio__inner{
     background: #761E6A !important;
     border-color: #761E6A !important;

+ 1 - 1
src/components/reportList/index.vue

@@ -7,7 +7,7 @@
         </div>
         <div class="rlpl_r adfac">
           <div class="rr_pre rp1">
-            <p class="text">{{ item.enterpriseName||'' }}</p>
+            <p class="text"><span v-if="item.programName">{{ item.programName}} - </span>{{ item.enterpriseName||'' }}</p>
             <p class="tip">{{ item.title||'' }}</p>
           </div>
           <div class="rr_pre rp2" v-if="!isTeam">

+ 5 - 1
src/components/reportPdf/pdf.vue

@@ -11,11 +11,15 @@
                 <div class="pt_name">团队诊断报告</div>
                 <div class="pt_tip">{{ reportData?.cover?.title }}</div>
             </div>
-            <div class="fm_pre adfac" style="margin-top: 195px;">
+            <div class="fm_pre adfac" style="margin-top: 165px;">
                 <div class="fmp_l">报告撰写人:</div>
                 <!-- <div class="fmp_r">{{ reportData?.cover?.realName }}</div> -->
                 <div class="fmp_r">创衡AI教练助手</div>
             </div>
+            <div class="fm_pre adfac">
+                <div class="fmp_l">项目名称:</div>
+                <div class="fmp_r">{{ reportData?.cover?.programName }}</div>
+            </div>
             <div class="fm_pre adfac">
                 <div class="fmp_l">客户名称:</div>
                 <div class="fmp_r">{{ reportData?.cover?.enterpriseName }}</div>

+ 5 - 1
src/components/reportPdf/pdfUser.vue

@@ -11,10 +11,14 @@
                 <div class="pt_name" style="font-size: 50px;">团队诊断报告-个人版</div>
                 <div class="pt_tip">{{ useCommonStore()?.$state?.userRealName }}</div>
             </div>
-            <div class="fm_pre adfac" style="margin-top: 195px;">
+            <div class="fm_pre adfac" style="margin-top: 165px;">
                 <div class="fmp_l">报告撰写人:</div>
                 <div class="fmp_r">创衡AI教练助手</div>
             </div>
+            <div class="fm_pre adfac">
+                <div class="fmp_l">项目名称:</div>
+                <div class="fmp_r">{{ reportData?.cover?.programName }}</div>
+            </div>
             <div class="fm_pre adfac">
                 <div class="fmp_l">客户名称:</div>
                 <div class="fmp_r">{{ reportData?.cover?.enterpriseName }}</div>

+ 17 - 1
src/store_v3/modules/agent.js

@@ -1,9 +1,22 @@
 import {defineStore} from "pinia";
 import {ref} from "vue";
 
-import { getCoachList,getQuestionnaireList,getCoachProgramList,getTeamListById } from '@/api/agent/index.js'
+import { getProgramList,getCoachList,getQuestionnaireList,getCoachProgramList,getTeamListById } from '@/api/agent/index.js'
 
 export const useAgentStore = defineStore('agent', () => {
+    const programList = ref([]);
+    const programMap = ref(new Map());
+    const getProgramData = () => {
+        getProgramList({page:1,limit:-1,programName:''}).then((res) => {
+            programList.value = res.data.list;
+            const map = new Map();
+            programList.value.forEach((supplier) => {
+                map.set(supplier.id, supplier);
+            });
+            programMap.value = map;
+        });
+    };
+
     const companyList = ref([]);
     const companyMap = ref(new Map());
     const getCompanyData = () => {
@@ -57,6 +70,9 @@ export const useAgentStore = defineStore('agent', () => {
     };
 
     return {
+        programList,
+        programMap,
+        getProgramData,
         companyList,
         companyMap,
         getCompanyData,

+ 1 - 1
src/utils/ruoyi.js

@@ -272,5 +272,5 @@ export function generateNo() {
   // 生成 0 到 9999 之间的随机整数
   const randomNum = Math.floor(Math.random() * 10000);
   // 返回
-  return month + '' + day + '' + String(randomNum).padStart(4, '0');
+  return 'CP' + month + '' + day + '' + String(randomNum).padStart(4, '0');
 }

+ 62 - 313
src/views/modules/agent/company.vue

@@ -1,107 +1,67 @@
 <template>
     <div class="page">
         <div class="title">{{ title }}</div>
-        <div class="tabs">
-            <div class="t_pre" :class="{'active':tidx===1}" @click="handleChangeTab(1)">活动项目</div>
-            <div class="t_pre" :class="{'active':tidx===2}" @click="handleChangeTab(2)">项目进展</div>
-            <template v-if="tidx===1">
-                <div class="t_add t_add2" @click="handleAddTeam" v-hasPermi="['core:project:addTeam']">+ 添加团队</div>
-                <div class="t_add" @click="handleAdd" v-hasPermi="['core:project:add']">+ 创建项目</div>
-            </template>
-            <template v-else-if="tidx===2">
-                <div class="t_add" @click="handleAddJZ">+ 添加项目进展</div>
-            </template>
+        <div class="query adfacjb">
+            <el-input placeholder="请输入公司名称" prefix-icon="el-icon-search" v-model="programName" style="flex: 1;padding-right: 20px;" @keyup.enter.native="getProgramList"></el-input>
+            <el-button type="danger" icon="el-icon-plus" @click="handleAddTeam" v-hasPermi="['core:project:addTeam']">添加团队</el-button>
+            <el-button type="primary" icon="el-icon-plus" @click="handleAdd" v-hasPermi="['core:project:add']">创建公司</el-button>
         </div>
-        <template v-if="tidx===1">
-            <div class="query adfacjb">
-                <el-input placeholder="请输入内容" prefix-icon="el-icon-search" v-model="programName" style="width: 100%" @keyup.enter.native="getProgramList"></el-input>
-            </div>
-            <div class="content">
-                <template v-if="companyList.length">
-                    <div class="team_user_list">
-                        <div class="tul_left">
-                            <div class="tull_top">
-                                <div class="tullt_l">全部项目</div>
-                            </div>
-                            <div class="tull_list">
-                                <div class="tull_item" :class="{'active':item.select}" v-for="(item,index) in companyList" :key="index" @click="handleExpand(item,index)">
-                                    <div class="tname">
-                                        <div>
-                                            <span>{{ item.enterpriseName }}</span>
-                                        </div>
-                                        <el-popover placement="right" width="177" trigger="hover">
-                                            <div class="tl_czs">
-                                                <div class="tlc_pre" @click="handleProgramDetail(item)" v-hasPermi="['core:program:info']">项目详情</div>
-                                                <div class="tlc_pre" @click="handleProgramDelete(item)" v-hasPermi="['core:program:delete']">删除项目</div>
-                                            </div>
-                                            <i slot="reference" class="el-icon-edit" style="font-size: 16px;color: #999;" @click.stop="handleSetTeam(team,idx)"></i>
-                                        </el-popover>
+        <div class="content">
+            <template v-if="companyList.length">
+                <div class="team_user_list">
+                    <div class="tul_left">
+                        <div class="tull_top">
+                            <div class="tullt_l">全部公司</div>
+                        </div>
+                        <div class="tull_list">
+                            <div class="tull_item" :class="{'active':item.select}" v-for="(item,index) in companyList" :key="index" @click="handleExpand(item,index)">
+                                <div class="tname">
+                                    <div>
+                                        <span>{{ item.enterpriseName }}</span>
                                     </div>
+                                    <el-popover placement="right" width="177" trigger="hover">
+                                        <div class="tl_czs">
+                                            <div class="tlc_pre" @click="handleProgramDetail(item)" v-hasPermi="['core:project:info']">公司详情</div>
+                                            <div class="tlc_pre" @click="handleProgramDelete(item)" v-hasPermi="['core:project:delete']">删除公司</div>
+                                        </div>
+                                        <i slot="reference" class="el-icon-edit" style="font-size: 16px;color: #999;" @click.stop="handleSetTeam(team,idx)"></i>
+                                    </el-popover>
                                 </div>
                             </div>
                         </div>
-                        <div class="tul_right">
-                            <div class="tulr_top">
-                                <div class="tullt_l">项目团队</div>
-                            </div>
-                            <el-table :data="teamList" border cell-class-name="vertical-top-cell" v-loading="loading" empty-text="暂无团队" max-height="578px" style="margin-top: 16px;">
-                                <el-table-column label="序号" width="50">
-                                    <template #default="scope">
-                                        {{ scope.$index + 1 }}
-                                    </template>
-                                </el-table-column>
-                                <el-table-column label="团队类型" prop="teamName"></el-table-column>
-                                <el-table-column label="团队人数" prop="teamNum"></el-table-column>
-                                <el-table-column label="团队故事" prop="teamStory" width="700" show-overflow-tooltip></el-table-column>
-                                <el-table-column label="操作" width="200">
-                                    <template #default="scope">
-                                        <el-button link type="text" size="mini" @click="handleTeamDetail(scope.row)" v-hasPermi="['core:team:info']">编辑</el-button>
-                                        <el-button link type="text" size="mini" @click="handleUsers(scope.row)">成员管理</el-button>
-                                        <el-button link type="text" size="mini" @click="handleTeamDelete(scope.row)" v-hasPermi="['core:team:delete']">删除</el-button>
-                                    </template>
-                                </el-table-column>
-                            </el-table>
-                        </div>
                     </div>
-                </template>
-                <template v-else>
-                    <div class="empty">
-                        <img src="@/assets/images/agent/team.png">
-                        <p>您还没有任何项目及团队成员信息</p>
-                        <div class="e_add" @click="handleAdd" v-hasPermi="['core:project:add']">+ 创建新项目</div>
-                    </div>
-                </template>
-            </div>
-        </template>
-        <template v-else-if="tidx===2">
-            <div class="query adfacjb">
-                <el-input placeholder="请输入公司名称" prefix-icon="el-icon-search" v-model="programName2" style="width: 100%" @keyup.enter.native="getProgramProgressData"></el-input>
-            </div>
-            <div class="content">
-                <template v-if="companyList2.length">
-                    <el-table :data="companyList2" border cell-class-name="vertical-top-cell" v-loading="loading7" empty-text="暂无项目" max-height="578px" style="margin-top: 6px;">
-                        <el-table-column label="公司名称" prop="enterpriseName"></el-table-column>
-                        <el-table-column label="更新时间" prop="updateDate"></el-table-column>
-                        <el-table-column label="公司背景" prop="background" width="400" show-overflow-tooltip></el-table-column>
-                        <el-table-column label="项目的阶段及状态" prop="progress" width="400" show-overflow-tooltip></el-table-column>
-                        <el-table-column label="操作" width="150">
-                            <template #default="scope">
-                                <el-button link type="text" size="mini" @click="handleEdit7(scope.row)" v-hasPermi="['core:projectprogress:update']">编辑</el-button>
-                                <el-button link type="text" size="mini" @click="handleDelete7(scope.row)" v-hasPermi="['core:projectprogress:delete']">删除</el-button>
-                            </template>
-                        </el-table-column>
-                    </el-table>
-                </template>
-                <template v-else>
-                    <div class="empty">
-                        <img src="@/assets/images/agent/team.png">
-                        <p>您还没有添加过任何项目进展</p>
-                        <div class="e_add" @click="handleAddJZ">+ 添加项目进展</div>
+                    <div class="tul_right">
+                        <div class="tulr_top">
+                            <div class="tullt_l">公司团队</div>
+                        </div>
+                        <el-table :data="teamList" border cell-class-name="vertical-top-cell" v-loading="loading" empty-text="暂无团队" max-height="578px" style="margin-top: 16px;">
+                            <el-table-column label="序号" width="50">
+                                <template #default="scope">
+                                    {{ scope.$index + 1 }}
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="团队类型" prop="teamName"></el-table-column>
+                            <el-table-column label="团队人数" prop="teamNum"></el-table-column>
+                            <el-table-column label="团队故事" prop="teamStory" width="700" show-overflow-tooltip></el-table-column>
+                            <el-table-column label="操作" width="200">
+                                <template #default="scope">
+                                    <el-button link type="text" size="mini" @click="handleTeamDetail(scope.row)" v-hasPermi="['core:team:info']">编辑</el-button>
+                                    <el-button link type="text" size="mini" @click="handleUsers(scope.row)">成员管理</el-button>
+                                    <el-button link type="text" size="mini" @click="handleTeamDelete(scope.row)" v-hasPermi="['core:team:delete']">删除</el-button>
+                                </template>
+                            </el-table-column>
+                        </el-table>
                     </div>
-                </template>
-            </div>
-        </template>
-        <template v-else-if="tidx===3"></template>
+                </div>
+            </template>
+            <template v-else>
+                <div class="empty">
+                    <img src="@/assets/images/agent/team.png">
+                    <p>您还没有任何公司及团队成员信息</p>
+                    <div class="e_add" @click="handleAdd" v-hasPermi="['core:project:add']">+ 创建新公司</div>
+                </div>
+            </template>
+        </div>
         <el-drawer :title="userTitle" :visible.sync="userShow" append-to-body size="60%" @close="userShow=false">
             <el-form ref="userRef" :model="userForm" :rules="userRules" label-width="100px" style="width: 90%;margin: 0 auto;">
                 <el-row>
@@ -256,48 +216,6 @@
                         <el-option v-for="item in staffSize" :label="item.label" :value="item.value"></el-option>
                     </el-select>
                 </el-form-item>
-                <el-form-item label="项目教练" prop="">
-                    <el-popover
-                        placement="top-start"
-                        title="选择教练"
-                        width="790"
-                        trigger="click"
-                        v-model="coachShow"
-                        @show="hangleSelectCoach">
-                        <div class="ed_coach adf">
-                            <div class="ec_l">
-                                <el-input placeholder="请输入教练名搜索" suffix-icon="el-icon-search" v-model="coachName" style="width: 100%;" @keyup.enter.native="handleQueryCoach"></el-input>
-                                <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="margin-top: 65px;">全选</el-checkbox>
-                                <div class="ecl_cbs">
-                                    <el-checkbox v-model="coach.checked" v-for="(coach,index) in coachList" :key="coach.id" @change="handleChangeCoach" style="margin-top: 24px;display: block;">{{ coach.realName }}</el-checkbox>
-                                </div>
-                            </div>
-                            <div class="ec_r">
-                                <div class="ecr_text">已选择({{ coachSelecteds.length }}/<span>{{ coachList.length }}</span>)</div>
-                                <div class="ecr_names">
-                                    <div class="en_pre adfacjc" v-for="(item,index) in coachSelecteds" :key="index">
-                                        <span>{{ item.realName }}</span>
-                                        <img src="@/assets/images/agent/delete_mini.png" @click="handleDeleteCoach(item,index)">
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                        <div class="demo-drawer__footer" style="display: flex;justify-content: end;margin-top: 20px;">
-                            <el-button type="primary" @click="submitForm5">确 认</el-button>
-                            <el-button @click="cancel5" style="margin-right: 5%;">取 消</el-button>
-                        </div>
-                        <div slot="reference">
-                            <div class="f_s adfacjb" v-if="programForm.coachList.length===0">
-                                <div class="fs_text" :class="{'active':coachs!=='请选择'}">{{ coachs }}</div>
-                                <i class="el-icon-arrow-down" style="color: #C0C4CC;"></i>
-                            </div>
-                            <div class="f_s adfacjb" v-else>
-                                <p>{{ cocahNames }}</p>
-                                <i class="el-icon-arrow-down" style="color: #C0C4CC;"></i>
-                            </div>
-                        </div>
-                    </el-popover>
-                </el-form-item>
                 <el-form-item label="公司背景" prop="background">
                     <el-input type="textarea" :rows="2" v-model="programForm.background" placeholder="请输入公司背景" />
                 </el-form-item>
@@ -359,13 +277,6 @@
                         </el-form-item>
                     </el-col>
                 </el-row>
-                <el-row style="width: 100%;">
-                    <el-col :span="24">
-                        <el-form-item label="项目教练" prop="">
-                            <el-input v-model="xmjzForm.ccc" clearable disabled></el-input>
-                        </el-form-item>
-                    </el-col>
-                </el-row>
                 <el-row style="width: 100%;">
                     <el-col :span="24">
                         <el-form-item label="公司背景" prop="">
@@ -438,7 +349,7 @@
     const programid = ref('')
     const teamid = ref('')
     const loading = ref(false);
-    const programTitle = ref('项目详情');
+    const programTitle = ref('公司详情');
     const queryParams = ref({
         page:1,
         limit:10,
@@ -555,7 +466,6 @@
         city:'',
         area:'',
         areaCode:'',
-        coachList:[],
         background:''
     });
     const programRules = ref({
@@ -584,7 +494,6 @@
     const coachName = ref('')
     const coachShow = ref(false)
     const coachSelecteds = ref([])
-    const coachList = ref([])
     const isIndeterminate = ref(false)
     const checkAll = ref(false)
     const cocahNames = ref('')
@@ -652,7 +561,7 @@
     }
     const handleAdd = () => {
         programid.value = '';
-        programTitle.value = '创建项目';
+        programTitle.value = '创建公司';
         programShow.value = true;
         programForm.value = {
             id:'',
@@ -664,7 +573,6 @@
             city:'',
             area:'',
             areaCode:'',
-            coachList:[],
             background:''
         };
         proxy.$refs.programRef.resetFields();
@@ -715,8 +623,7 @@
     };
 
     const handleAddTeam = () => {
-        if(!programid.value) return proxy.$message.error('请先选择项目')
-        if(programTeamNum.value>0) return proxy.$message.error('该项目已有团队,请先删除或修改')
+        if(!programid.value) return proxy.$message.error('请先选择公司')
         programTeamShow.value = true;
     };
 
@@ -766,13 +673,7 @@
             return {
                 ...d,
                 expand: false,
-                select: false,
-                teams: res.data[i].teams.map(t => {
-                    return {
-                        ...t,
-                        select: false
-                    }
-                })
+                select: false
             }
         });
         loading.value = false;
@@ -902,11 +803,10 @@
     }
 
     const handleProgramDetail = program => {
-        programTitle.value = "项目详情";
+        programTitle.value = "公司详情";
         programid.value = program.id;
         getCoachProgramInfo(program.id).then(res => {
             programForm.value = {...programForm.value,...res.data};
-            if(programForm.value.coachList===null) programForm.value.coachList = [];
             let areas = programForm.value.areaCode.split('-');
             if(areas.length === 3){
                 programForm.value.province = areas[0];
@@ -915,41 +815,17 @@
                 countyAreaDetailInfoList(areas[1]);
                 programForm.value.area = areas[2];
             }
-            cocahNames.value = programForm.value.coachList.map(item => item.coachName).join(';');
             programShow.value = true;
         })
     }
     const handleProgramDelete = async program => {
-        await proxy.$modal.confirm('确认删除项目【' + program.enterpriseName + '】吗?');
+        await proxy.$modal.confirm('确认删除公司【' + program.enterpriseName + '】吗?');
         deleteCoachProgram(program.id).then(res=>{
             if(res.code === 0) proxy?.$modal.msgSuccess("删除成功");
             else return proxy?.$modal.msgError(res.msg);
             getProgramList();
         });
     }
-    const hangleSelectCoach = () => {
-        getCoachList({page:1,limit:-1,realName:coachName.value}).then(res => {
-            if(res.code!==0) return proxy.$message.error(res.msg);
-            coachList.value = res.data.list.filter(d=>d.userType=='1');
-            coachList.value.forEach(item => {
-                item.checked = false;
-            })
-            coachShow.value = true;
-        })
-    }
-    const submitForm5 = () => {
-        if(coachSelecteds.value.length===0) return proxy.$message.warning('请至少选择一位教练')
-        programForm.value.coachList = JSON.parse(JSON.stringify(coachSelecteds.value)).map(c=>{return {coachId:c.id,coachName:c.realName}});
-        cocahNames.value = programForm.value.coachList.map(c=>c.coachName).join(';');
-        checkAll.value = false;
-        isIndeterminate.value = false;
-        coachSelecteds.value = [];
-        coachList.value = [];
-        coachShow.value = false;
-    }
-    const cancel5 = () => {
-        coachShow.value = false;
-    }
 
     const submitForm4 = () => {
         proxy.$refs.programRef.validate((valid) => {
@@ -958,7 +834,6 @@
                 programForm.value.id = programid.value;
                 programForm.value.areaCode = `${programForm.value.province}-${programForm.value.city}-${programForm.value.area}`;
                 let dto = JSON.parse(JSON.stringify(programForm.value));
-                if(dto.coachList.length===0) return proxy.$message.warning('请至少选择一位教练');
                 if(dto.id){
                     updateCoachProgram(programForm.value).then((res)=>{
                         if(res.code!==0) return proxy.$message.error(res.msg);
@@ -993,55 +868,10 @@
             city:'',
             area:'',
             areaCode:'',
-            coachList:[],
             background:''
         }
         proxy.$refs.programRef.resetFields();
     }
-    const handleCheckAllChange = (val) => {
-        coachSelecteds.value = val ? JSON.parse(JSON.stringify(coachList.value)) : [];
-        isIndeterminate.value = false;
-        coachList.value.forEach(item => item.checked = val)
-    }
-    const handleChangeCoach = () => {
-        let trues = coachList.value.filter(item => item.checked).length;
-        if(trues>0&&trues<coachList.value.length) isIndeterminate.value = true;
-        else isIndeterminate.value = false;
-        if(trues===coachList.value.length) checkAll.value = true;
-        else checkAll.value = false;
-
-        coachSelecteds.value = coachList.value.filter(item => item.checked);
-    }
-    const handleDeleteCoach = (item,index) => {
-        let i = coachList.value.findIndex(c => c.id === item.id);
-        if(i>-1) coachList.value[i].checked = false;
-        coachSelecteds.value.splice(index,1);
-
-        let trues = coachList.value.filter(item => item.checked).length;
-        if(trues>0&&trues<coachList.value.length) isIndeterminate.value = true;
-        else isIndeterminate.value = false;
-        if(trues===coachList.value.length) checkAll.value = true;
-        else checkAll.value = false;
-    }
-
-    const handleBeforeUpload = (e,node,data)=>{
-        let type = e.name.split('.')[e.name.split('.').length-1];
-        let isExcel = e.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
-        if(type.toLowerCase() !== 'xlsx' && type.toLowerCase() !== 'xls' && !isExcel){
-            proxy?.$modal.msgError('请上传xlsx或xls格式的Excel文件!');
-            return false;
-        }
-        setTimeout(()=>{
-            getUserList();
-        },1000)
-    }
-    const handleSuccess = (e,node,data)=>{
-        if(e.code===0){
-            proxy?.$modal.msgSuccess('导入成功!'+e.msg);
-        }else {
-            proxy?.$modal.msgError('导入失败!'+e.msg);
-        }
-    }
 
     const submitForm6 = () => {
         proxy.$refs.programTeamRef.validate((valid) => {
@@ -1074,36 +904,10 @@
         }
     }
 
-    const handleEdit7 = (row) => {
-        xmjzTitle.value = '编辑项目进展';
-        getProgramProgressInfo(row.id).then((res)=>{
-            if(res.code!==0) return proxy.$message.error(res.msg);
-            else{
-                xmjzForm.value = res.data;
-                getCoachProgramInfo(res.data.enterpriseId).then(res => {
-                    xmjzForm.value.background = res.data.background;
-                    xmjzForm.value.bbb = staffSize.value.find(item => item.value === res.data.staffSizeCode).label;
-                    xmjzForm.value.ccc = res.data.coachList.map(item => item.coachName);
-                    xmjzShow.value = true;
-                })
-            }
-        })
-    }
-
-    const handleDelete7 = async (row) => {
-        await proxy.$modal.confirm('确认删除吗?');
-        deleteProgramProgress([row.id]).then(res=>{
-            if(res.code === 0) proxy?.$modal.msgSuccess("删除成功");
-            else return proxy?.$modal.msgError(res.msg);
-            getProgramProgressData();
-        });
-    }
-
     const handleChange7 = row => {
         getCoachProgramInfo(row).then(res => {
             xmjzForm.value.background = res.data.background;
             xmjzForm.value.bbb = staffSize.value.find(item => item.value === res.data.staffSizeCode).label;
-            xmjzForm.value.ccc =res.data.coachList.map(item => item.coachName);
         })
     }
 
@@ -1166,7 +970,7 @@
             background: #FFFFFF;
             border-radius: 6px;
             border: 1px solid #F3F4F6;
-            margin-top: 11px;
+            margin-top: 31px;
         }
 
     .page{
@@ -1180,64 +984,9 @@
             line-height: 16px;
         }
 
-        .tabs{
-            position: relative;
-            display: flex;
-            align-items: center;
-            border-bottom: 1px solid #E5E7EB;
-            padding-bottom: 18px;
-            margin-top: 32px;
-            .t_pre{
-                width: 116px;
-                font-family: PingFangSC, PingFang SC;
-                font-weight: 400;
-                font-size: 14px;
-                color: #111111;
-                line-height: 16px;
-                text-align: center;
-                position: relative;
-                cursor: pointer;
-                &.active{
-                    font-weight: bold;
-                    color: #761E6A;
-                    &::after{
-                        content: '';
-                        position: absolute;
-                        bottom: -18px;
-                        left: 0;
-                        width: 100%;
-                        height: 2px;
-                        background: #761E6A;
-                    }
-                }
-            }
-            .t_add{
-                width: 112px;
-                height: 30px;
-                background: #761E6A;
-                border-radius: 6px;
-                font-family: PingFangSC, PingFang SC;
-                font-weight: 400;
-                font-size: 14px;
-                color: #FFFFFF;
-                line-height: 26px;
-                text-align: center;
-                position: absolute;
-                top: -10px;
-                right: 0;
-                cursor: pointer;
-                border: 1px solid #833478;
-                &.t_add2{
-                    background: #FFFFFF;
-                    color: #833478;
-                    right: 130px;
-                }
-            }
-        }
-
         .content{
             width: 100%;
-            height: calc(100vh - 220px);
+            height: calc(100vh - 170px);
             background: #FFFFFF;
             border: 1px solid #F3F4F6;
             margin-top: 5px;

+ 1 - 1
src/views/modules/agent/company/teamUser.vue

@@ -5,7 +5,7 @@
                 <div class="t_l adfac">
                     <img src="@/assets/images/agent/arrow_left.png" @click="handleBack">
                     <div class="spans">
-                        <span>项目管理</span>
+                        <span>公司管理</span>
                         <span class="last">&nbsp;/&nbsp;成员管理</span>
                     </div>
                 </div>

File diff suppressed because it is too large
+ 1650 - 0
src/views/modules/agent/program copy.vue


+ 870 - 0
src/views/modules/agent/program.vue

@@ -0,0 +1,870 @@
+<template>
+    <div class="page">
+        <div class="title">{{ title }}</div>
+        <div class="tabs">
+            <div class="t_pre" :class="{'active':tidx===1}" @click="handleChangeTab(1)">活动项目</div>
+            <div class="t_pre" :class="{'active':tidx===2}" @click="handleChangeTab(2)">项目进展</div>
+            <template v-if="tidx===1">
+                <div class="t_add" @click="handleAddProgram" v-hasPermi="['core:project:add']">+ 创建项目</div>
+            </template>
+            <template v-else-if="tidx===2">
+                <div class="t_add" @click="handleAddJZ">+ 添加项目进展</div>
+            </template>
+        </div>
+        <template v-if="tidx===1">
+            <div class="query adfacjb">
+                <el-input placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="queryParams.programName" style="width: 100%" @keyup.enter.native="getProgramListFn"></el-input>
+            </div>
+            <div class="content">
+                <template v-if="programList.length">
+                    <el-table :data="programList" border cell-class-name="vertical-top-cell" v-loading="loading" empty-text="暂无项目" max-height="578px">
+                        <el-table-column label="序号" width="50">
+                            <template #default="scope">
+                                {{ scope.$index + 1 }}
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="项目编号" prop="programNo" width="150"></el-table-column>
+                        <el-table-column label="项目名称" prop="programName"></el-table-column>
+                        <el-table-column label="公司名称" prop="enterpriseName"></el-table-column>
+                        <el-table-column label="团队名称" prop="teamName"></el-table-column>
+                        <el-table-column label="教练" prop="coachNames"></el-table-column>
+                        <el-table-column label="备注" prop="remark" width="300" show-overflow-tooltip></el-table-column>
+                        <el-table-column label="操作" width="150">
+                            <template #default="scope">
+                                <el-button link type="text" size="mini" @click="handleEdit(scope.row)">编辑</el-button>
+                                <el-button link type="text" size="mini" @click="handleDelete(scope.row)" v-hasPermi="['core:program:delete']">删除</el-button>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                    <el-row style="display: flex;justify-content: center;">
+                        <el-pagination
+                            @size-change="handleSizeChange"
+                            @current-change="handleCurrentChange"
+                            :current-page="queryParams.page"
+                            :page-sizes="[5, 10, 20, 50]"
+                            :page-size="10"
+                            layout="total, sizes, prev, pager, next, jumper"
+                            :total="total"
+                            v-show="total > 0">
+                        </el-pagination>
+                    </el-row>
+                </template>
+                <template v-else>
+                    <div class="empty">
+                        <img src="@/assets/images/agent/team.png">
+                        <p>您还没有添加过任何项目</p>
+                        <div class="e_add" @click="handleAddProgram">+ 添加项目</div>
+                    </div>
+                </template>
+            </div>
+        </template>
+        <template v-else-if="tidx===2">
+            <div class="query adfacjb">
+                <el-input placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="programName2" style="width: 100%" @keyup.enter.native="getProgramProgressData"></el-input>
+            </div>
+            <div class="content">
+                <template v-if="programList2.length">
+                    <el-table :data="programList2" border cell-class-name="vertical-top-cell" v-loading="loading2" empty-text="暂无项目进展" max-height="578px">
+                        \<el-table-column label="序号" width="50">
+                            <template #default="scope">
+                                {{ scope.$index + 1 }}
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="项目编号" prop="programNo"></el-table-column>
+                        <el-table-column label="项目名称" prop="programName"></el-table-column>
+                        <el-table-column label="公司名称" prop="enterpriseName"></el-table-column>
+                        <el-table-column label="更新时间" prop="updateDate"></el-table-column>
+                        <el-table-column label="项目的阶段及状态" prop="progress" width="400" show-overflow-tooltip></el-table-column>
+                        <el-table-column label="操作" width="150">
+                            <template #default="scope">
+                                <el-button link type="text" size="mini" @click="handleEdit2(scope.row)" v-hasPermi="['core:projectprogress:update']">编辑</el-button>
+                                <el-button link type="text" size="mini" @click="handleDelete2(scope.row)" v-hasPermi="['core:projectprogress:delete']">删除</el-button>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                </template>
+                <template v-else>
+                    <div class="empty">
+                        <img src="@/assets/images/agent/team.png">
+                        <p>您还没有添加过任何项目进展</p>
+                        <div class="e_add" @click="handleAddJZ">+ 添加项目进展</div>
+                    </div>
+                </template>
+            </div>
+        </template>
+        <el-drawer :title="programTitle" :visible.sync="programShow" append-to-body size="50%" @close="cancel">
+            <el-form ref="programRef" :model="programForm" :rules="programRules" label-width="100px" style="width: 90%;margin: 0 auto;">
+                <el-form-item label="项目编号" prop="programNo">
+                    <el-input v-model="programForm.programNo"disabled />
+                </el-form-item>
+                <el-form-item label="项目名称" prop="programName">
+                    <el-input v-model="programForm.programName" placeholder="请输入项目名称" />
+                </el-form-item>
+                <el-form-item label="公司名称" prop="enterpriseId">
+                    <el-select v-model="programForm.enterpriseId" placeholder="请选择公司" filterable clearable style="width: 100%;" @change="handleChangeCompany">
+                        <el-option v-for="item in useAgentStore().companyList" :key="item.id" :label="item.enterpriseName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="团队名称" prop="teamId">
+                    <el-select v-model="programForm.teamId" placeholder="请选择团队" filterable clearable style="width: 100%;" :disabled="!programForm.enterpriseId">
+                        <el-option v-for="item in teamList" :key="item.id" :label="item.teamName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="项目教练" prop="">
+                    <el-popover
+                        placement="top-start"
+                        title="选择教练"
+                        width="790"
+                        trigger="click"
+                        v-model="coachShow"
+                        @show="hangleSelectCoach">
+                        <div class="ed_coach adf">
+                            <div class="ec_l">
+                                <el-input placeholder="请输入教练名搜索" suffix-icon="el-icon-search" v-model="coachName" style="width: 100%;" @keyup.enter.native="handleQueryCoach"></el-input>
+                                <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="margin-top: 65px;">全选</el-checkbox>
+                                <div class="ecl_cbs">
+                                    <el-checkbox v-model="coach.checked" v-for="(coach,index) in coachList" :key="coach.id" @change="handleChangeCoach" style="margin-top: 24px;display: block;">{{ coach.realName }}</el-checkbox>
+                                </div>
+                            </div>
+                            <div class="ec_r">
+                                <div class="ecr_text">已选择({{ coachSelecteds.length }}/<span>{{ coachList.length }}</span>)</div>
+                                <div class="ecr_names">
+                                    <div class="en_pre adfacjc" v-for="(item,index) in coachSelecteds" :key="index">
+                                        <span>{{ item.realName }}</span>
+                                        <img src="@/assets/images/agent/delete_mini.png" @click="handleDeleteCoach(item,index)">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="demo-drawer__footer" style="display: flex;justify-content: end;margin-top: 20px;">
+                            <el-button type="primary" @click="submitForm2">确 认</el-button>
+                            <el-button @click="cancel2" style="margin-right: 5%;">取 消</el-button>
+                        </div>
+                        <div slot="reference">
+                            <div class="f_s adfacjb" v-if="programForm.coachList.length===0">
+                                <div class="fs_text" :class="{'active':coachs!=='请选择'}">{{ coachs }}</div>
+                                <i class="el-icon-arrow-down" style="color: #C0C4CC;"></i>
+                            </div>
+                            <div class="f_s adfacjb" v-else>
+                                <p>{{ cocahNames }}</p>
+                                <i class="el-icon-arrow-down" style="color: #C0C4CC;"></i>
+                            </div>
+                        </div>
+                    </el-popover>
+                </el-form-item>
+                <el-form-item label="项目备注" prop="remark">
+                    <el-input type="textarea" :rows="2" v-model="programForm.remark" placeholder="请输入项目概述" />
+                </el-form-item>
+            </el-form>
+            <div class="demo-drawer__footer" style="display: flex;justify-content: end;">
+                <el-button :loading="buttonLoading" type="primary" @click="submitForm" v-hasPermi="['core:program:save']">保 存</el-button>
+                <el-button @click="cancel" style="margin-right: 5%;">取 消</el-button>
+            </div>
+        </el-drawer>
+        <el-drawer :title="progressTitle" :visible.sync="progressShow" append-to-body size="50%" @close="cancel">
+            <el-form ref="progressRef" :model="progressForm" :rules="progressRules" label-width="140px" style="width: 90%;margin: 0 auto;">
+                <el-form-item label="项目名称" prop="programId">
+                    <el-select v-model="progressForm.programId" placeholder="请选择项目名称" filterable clearable style="width: 100%;" @change="handleChangeProgram">
+                        <el-option v-for="item in useAgentStore().programList" :key="item.id" :label="item.programName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="公司名称">
+                    <el-select v-model="progressForm.enterpriseId" placeholder="请选择公司" filterable clearable style="width: 100%;" disabled>
+                        <el-option v-for="item in useAgentStore().companyList" :key="item.id" :label="item.enterpriseName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="团队名称">
+                    <el-select v-model="progressForm.teamId" placeholder="请选择团队" filterable clearable style="width: 100%;" disabled>
+                        <el-option v-for="item in teamList" :key="item.id" :label="item.teamName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="项目教练" prop="">
+                    <el-input v-model="progressForm.cocahNames" disabled></el-input>
+                </el-form-item>
+                <el-form-item label="项目的阶段及状态" prop="progress">
+                    <el-input type="textarea" :rows="2" v-model="progressForm.progress" placeholder="请输入项目的阶段及状态" />
+                </el-form-item>
+            </el-form>
+            <div class="demo-drawer__footer" style="display: flex;justify-content: end;">
+                <el-button :loading="buttonLoading3" type="primary" @click="submitForm3" v-hasPermi="['core:projectprogress:save']">保 存</el-button>
+                <el-button @click="cancel3" style="margin-right: 5%;">取 消</el-button>
+            </div>
+        </el-drawer>
+    </div>
+</template>
+
+<script setup name="">
+    import { generateNo } from '@/utils/ruoyi'
+    import { ref, getCurrentInstance, onMounted } from 'vue'
+    const { proxy } = getCurrentInstance();
+    import { useAgentStore } from '@/store_v3/modules/agent';
+    useAgentStore().getCompanyData();
+    useAgentStore().getProgramData();
+    import { 
+        getProgramList,
+        addProgram,
+        updateProgram,
+        getProgramInfo,
+        deleteProgram,
+        getCoachList,
+        getTeamListById,
+        getProgramProgressList,
+        addProgramProgress,
+        updateProgramProgress,
+        getProgramProgressInfo,
+        deleteProgramProgress,
+    } from '@/api/agent/index.js'
+    
+    const title = ref('项目管理')
+    const tidx = ref(1)
+    const programName2 = ref('')
+    const programList = ref([])
+    const total = ref(0)
+    const programList2 = ref([])
+    const teamList = ref([])
+    const loading = ref(false)
+    const loading2 = ref(false)
+    const coachs = ref('请选择')
+    const coachName = ref('')
+    const coachShow = ref(false)
+    const coachSelecteds = ref([])
+    const coachList = ref([])
+    const isIndeterminate = ref(false)
+    const checkAll = ref(false)
+    const cocahNames = ref('')
+    const queryParams = ref({
+        page: 1,
+        limit: 10,
+        programName: ''
+    })
+    const programTitle = ref('添加项目')
+    const programShow = ref(false)
+    const programRef = ref(null)
+    const programForm = ref({
+        id: '',
+        programNo: '',
+        programName: '',
+        enterpriseId: '',
+        enterpriseName: '',
+        teamId: '',
+        teamName: '',
+        coachList: [],
+        remark: ''
+    })
+    const programRules = ref({
+        programNo: [
+            { required: true, message: '请输入项目编号', trigger: 'blur' }
+        ],
+        programName: [
+            { required: true, message: '请输入项目名称', trigger: 'blur' }
+        ],
+        enterpriseId: [
+            { required: true, message: '请选择公司', trigger: 'change' }
+        ],
+        teamId: [
+            { required: true, message: '请选择团队', trigger: 'change' }
+        ]
+    })
+    const buttonLoading = ref(false)
+
+    const progressTitle = ref('添加项目阶段及进展')
+    const progressShow = ref(false)
+    const progressRef = ref(null)
+    const progressForm = ref({
+        id: '',
+        programId: '',
+        enterpriseId: '',
+        teamId: '',
+        cocahNames: '',
+        progress: ''
+    })
+    const progressRules = ref({
+        programId: [
+            { required: true, message: '请选择项目', trigger: 'change' }
+        ],
+        progress: [
+            { required: true, message: '请输入项目的阶段及状态', trigger: 'blur' }
+        ]
+    })
+    const buttonLoading3 = ref(false)
+
+    const getProgramListFn = async () => {
+        loading.value = true;
+        const res = await getProgramList(queryParams.value);
+        if(res.code!==0) return proxy.$message.error(res.msg);
+        programList.value = res.data.list;
+        programList.value.forEach(p=>{
+            p.coachNames = p.coachList.map(c=>c.coachName).join('、');
+        })
+        total.value = res.data.total;
+        loading.value = false;
+    }
+    const handleSizeChange = (val) => {
+        queryParams.value.limit = val
+        getProgramListFn()
+    }
+    const handleCurrentChange = (val) => {
+        queryParams.value.page = val
+        getProgramListFn()
+    }
+    const handleChangeTab = (idx) => {
+        tidx.value = idx;
+        if(idx===2){
+            getProgramProgressData();
+        }
+    }
+    const handleAddProgram = () => {
+        reset();
+        programTitle.value = '添加项目';
+        programForm.value.programNo = generateNo();
+        programShow.value = true;
+    }
+    const handleEdit = (row) => {
+        programTitle.value = '编辑项目';
+        getProgramInfo(row.id).then(res=>{
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            programForm.value = {...programForm.value,...res.data};
+            if(programForm.value.coachList===null) programForm.value.coachList = [];
+            cocahNames.value = programForm.value.coachList.map(item => item.coachName).join(';');
+            getTeamListById({enterpriseId: res.data.enterpriseId}).then(r=>{
+                if(r.code!==0) return proxy.$message.error(r.msg);
+                teamList.value = r.data;
+            })
+            programShow.value = true;
+        });
+    }
+    const handleDelete = async (row) => {
+        await proxy.$modal.confirm('确认删除项目【' + row.programName + '】吗?');
+        deleteProgram([row.id]).then(res=>{
+            if(res.code === 0) proxy?.$modal.msgSuccess("删除成功");
+            else return proxy?.$modal.msgError(res.msg);
+            getProgramListFn();
+        });
+    }
+    const handleChangeCompany = (e) => {
+        getTeamListById({enterpriseId: e}).then(res=>{
+            if(res.code!==0) proxy.$message.error(res.msg);
+            teamList.value = res.data;
+        })
+    }
+
+    const submitForm = () => {
+        proxy.$refs.programRef.validate((valid) => {
+            if (valid) {
+                let dto = JSON.parse(JSON.stringify(programForm.value));
+                if(dto.coachList.length===0) return proxy.$message.warning('请至少选择一位教练');
+                if(dto.id){
+                    updateProgram(dto).then((res)=>{
+                        if(res.code!==0) return proxy.$message.error(res.msg);
+                        buttonLoading.value = false;
+                        programShow.value = false;
+                        getProgramListFn();
+                    })
+                }else{
+                    addProgram(dto).then((res)=>{
+                        if(res.code!==0) return proxy.$message.error(res.msg);
+                        buttonLoading.value = false;
+                        programShow.value = false;
+                        getProgramListFn();
+                    })
+                }
+            }else return false
+        })
+    }
+    const reset = () => {
+        programForm.value = {
+            id: '',
+            programNo: '',
+            programName: '',
+            enterpriseId: '',
+            enterpriseName: '',
+            teamId: '',
+            teamName: '',
+            coachList: [],
+            remark: ''
+        };
+        proxy.resetForm("programRef");
+    }
+
+    const cancel = () => {
+        programShow.value = false;
+        reset();
+    }
+    
+    const hangleSelectCoach = () => {
+        getCoachList({page:1,limit:-1,realName:coachName.value}).then(res => {
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            coachList.value = res.data.list.filter(d=>d.userType=='1');
+            coachList.value.forEach(item => {
+                item.checked = false;
+            })
+            coachShow.value = true;
+        })
+    }
+    const handleQueryCoach = e =>{
+        coachList.value = [];
+        getCoachList({page:1,limit:-1,realName:e.target.value}).then(res => {
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            coachList.value = res.data.list.filter(d=>d.userType=='1');
+            coachList.value.forEach(item => {
+                item.checked = false;
+            })
+            checkAll.value = false;
+            isIndeterminate.value = false;
+            coachSelecteds.value = [];
+        })
+    }
+    const handleCheckAllChange = (val) => {
+        coachSelecteds.value = val ? JSON.parse(JSON.stringify(coachList.value)) : [];
+        isIndeterminate.value = false;
+        coachList.value.forEach(item => item.checked = val)
+    }
+    const handleChangeCoach = () => {
+        let trues = coachList.value.filter(item => item.checked).length;
+        if(trues>0&&trues<coachList.value.length) isIndeterminate.value = true;
+        else isIndeterminate.value = false;
+        if(trues===coachList.value.length) checkAll.value = true;
+        else checkAll.value = false;
+
+        coachSelecteds.value = coachList.value.filter(item => item.checked);
+    }
+    const handleDeleteCoach = (item,index) => {
+        let i = coachList.value.findIndex(c => c.id === item.id);
+        if(i>-1) coachList.value[i].checked = false;
+        coachSelecteds.value.splice(index,1);
+
+        let trues = coachList.value.filter(item => item.checked).length;
+        if(trues>0&&trues<coachList.value.length) isIndeterminate.value = true;
+        else isIndeterminate.value = false;
+        if(trues===coachList.value.length) checkAll.value = true;
+        else checkAll.value = false;
+    }
+    const submitForm2 = () => {
+        if(coachSelecteds.value.length===0) return proxy.$message.warning('请至少选择一位教练')
+        programForm.value.coachList = JSON.parse(JSON.stringify(coachSelecteds.value)).map(c=>{return {coachId:c.id,coachName:c.realName}});
+        cocahNames.value = programForm.value.coachList.map(c=>c.coachName).join(';');
+        checkAll.value = false;
+        isIndeterminate.value = false;
+        coachSelecteds.value = [];
+        coachList.value = [];
+        coachName.value = '';
+        coachShow.value = false;
+    }
+    const cancel2 = () => {
+        checkAll.value = false;
+        isIndeterminate.value = false;
+        coachSelecteds.value = [];
+        coachList.value = [];
+        coachName.value = '';
+        coachShow.value = false;
+    }
+
+
+    const getProgramProgressData = async () => {
+        loading2.value = true;
+        const res = await getProgramProgressList({programName:programName2.value});
+        if(res.code!==0) return proxy.$message.error(res.msg);
+        programList2.value = res.data;
+        loading2.value = false;
+    }
+    const handleAddJZ = () => {
+        reset2();
+        progressTitle.value = '添加项目阶段及进展';
+        progressShow.value = true;
+    }
+    const reset2 = () => {
+        progressForm.value = {
+            id: '',
+            programId: '',
+            enterpriseId: '',
+            teamId: '',
+            cocahNames: '',
+            progress: ''
+        };
+        proxy.resetForm("progressRef");
+    }
+    const handleChangeProgram = e =>{
+        getProgramInfo(e).then(res=>{
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            progressForm.value = {...progressForm.value,...res.data};
+            progressForm.value.id = '';
+            getTeamListById({enterpriseId: res.data.enterpriseId}).then(res=>{
+                if(res.code!==0) proxy.$message.error(res.msg);
+                teamList.value = res.data;
+            })
+            progressForm.value.cocahNames = res.data.coachList.map(item => item.coachName).join('、');
+        })
+    }
+    const submitForm3 = () => {
+        proxy.$refs.progressRef.validate((valid) => {
+            if (valid) {
+                let dto = JSON.parse(JSON.stringify(progressForm.value));
+                if(dto.id){
+                    updateProgramProgress(dto).then((res)=>{
+                        if(res.code!==0) return proxy.$message.error(res.msg);
+                        buttonLoading3.value = false;
+                        progressShow.value = false;
+                        getProgramProgressData();
+                    })
+                }else{
+                    addProgramProgress(dto).then((res)=>{
+                        if(res.code!==0) return proxy.$message.error(res.msg);
+                        buttonLoading3.value = false;
+                        progressShow.value = false;
+                        getProgramProgressData();
+                    })
+                }
+            }else return false
+        })
+    }
+    const cancel3 = () => {
+        progressShow.value = false;
+        reset2();
+    }
+    const handleEdit2 = (item) => {
+        reset2();
+        progressTitle.value = '编辑项目阶段及进展';
+        getProgramProgressInfo(item.id).then(res=>{
+            if(res.code!==0) return proxy.$message.error(res.msg);
+            progressForm.value = {...progressForm.value,...res.data};
+            getProgramInfo(res.data.programId).then(res2=>{
+                if(res.code!==0) return proxy.$message.error(res2.msg);
+                progressForm.value.enterpriseId = res2.data.enterpriseId;
+                progressForm.value.teamId = res2.data.teamId;
+                getTeamListById({enterpriseId: res2.data.enterpriseId}).then(res3=>{
+                    if(res.code!==0) proxy.$message.error(res3.msg);
+                    teamList.value = res3.data;
+                })
+                progressForm.value.cocahNames = res2.data.coachList.map(item => item.coachName).join('、');
+            })
+            progressShow.value = true;
+        })
+    }
+    const handleDelete2 = async (row) => {
+        await proxy.$modal.confirm('确认删除项目进展【' + row.programName + '】吗?');
+        deleteProgramProgress([row.id]).then(res=>{
+            if(res.code === 0) proxy?.$modal.msgSuccess("删除成功");
+            else return proxy?.$modal.msgError(res.msg);
+            getProgramProgressData();
+        });
+    }
+
+    onMounted(()=>{
+        getProgramListFn();
+    })
+</script>
+
+<style scoped lang="scss">
+    ::v-deep .queryInput .el-input__inner{
+        border: none !important;
+        height: 30px !important;
+        line-height: 30px !important;
+        padding: 0 !important;
+        width: 200px !important;
+    }
+    
+    :v-deep .el-dialog__wrapper{
+        background: rgba(0,0,0,.3) !important;
+    }
+    ::v-deep .el-dialog__title{
+        font-weight: bold !important;
+    }
+    ::v-deep .el-dialog{
+        margin-top: 15vh !important;
+    }
+    ::v-deep .el-drawer__header span{
+        font-weight: bold;
+        font-size: 16px;
+        color: #1D2129;
+        line-height: 22px;
+    }
+
+    .query{
+        width: 100%;
+        padding: 16px 20px;
+        box-sizing: border-box;
+        background: #FFFFFF;
+        border-radius: 6px;
+        border: 1px solid #F3F4F6;
+        margin-top: 11px;
+    }
+
+    .page{
+        padding: 28px 16px 12px;
+        background: #FAFAFA;
+        
+        .title{
+            font-family: PingFang-SC, PingFang-SC;
+            font-weight: bold;
+            font-size: 16px;
+            color: #111111;
+            line-height: 16px;
+        }
+
+        .tabs{
+            position: relative;
+            display: flex;
+            align-items: center;
+            border-bottom: 1px solid #E5E7EB;
+            padding-bottom: 18px;
+            margin-top: 32px;
+            .t_pre{
+                width: 116px;
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: 14px;
+                color: #111111;
+                line-height: 16px;
+                text-align: center;
+                position: relative;
+                cursor: pointer;
+                &.active{
+                    font-weight: bold;
+                    color: #761E6A;
+                    &::after{
+                        content: '';
+                        position: absolute;
+                        bottom: -18px;
+                        left: 0;
+                        width: 100%;
+                        height: 2px;
+                        background: #761E6A;
+                    }
+                }
+            }
+            .t_add{
+                width: 112px;
+                height: 30px;
+                background: #761E6A;
+                border-radius: 6px;
+                font-family: PingFangSC, PingFang SC;
+                font-weight: 400;
+                font-size: 14px;
+                color: #FFFFFF;
+                line-height: 26px;
+                text-align: center;
+                position: absolute;
+                top: -10px;
+                right: 0;
+                cursor: pointer;
+                border: 1px solid #833478;
+                &.t_add2{
+                    background: #FFFFFF;
+                    color: #833478;
+                    right: 130px;
+                }
+            }
+        }
+        
+        .content{
+            width: 100%;
+            height: calc(100vh - 220px);
+            background: #FFFFFF;
+            border: 1px solid #F3F4F6;
+            margin-top: 5px;
+
+            
+            .empty{
+                width: 100%;
+                height: 100%;
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                justify-content: center;
+                img{
+                    width: 90px;
+                    height: 76px;
+                }
+                p{
+                    font-family: PingFangSC, PingFang SC;
+                    font-weight: 400;
+                    font-size: 14px;
+                    color: #1D2129;
+                    line-height: 20px;
+                    margin-top: 20px;
+                }
+                .e_add{
+                    width: 114px;
+                    height: 32px;
+                    background: #761E6A;
+                    border-radius: 6px;
+                    font-family: PingFangSC, PingFang SC;
+                    font-weight: 400;
+                    font-size: 14px;
+                    color: #FFFFFF;
+                    line-height: 32px;
+                    text-align: center;
+                    margin-top: 36px;
+                    cursor: pointer;
+                }
+            }
+        }
+    }
+
+
+    .f_s{
+        width: 100%;
+        height: 42px;
+        border-radius: 6px;
+        border: 1px solid #dcdfe6;
+        padding: 11px 11px 11px 16px;
+        box-sizing: border-box;
+        cursor: pointer;
+        .fs_text{
+            font-family: PingFangSC, PingFang SC;
+            font-weight: 400;
+            font-size: 14px;
+            color: #C0C4CC;
+            line-height: 20px;
+            &.active{
+                color: #606266;
+            }
+        }
+    }
+
+    .f_title{
+        font-family: PingFangSC, PingFang SC;
+        font-weight: 600;
+        font-size: 16px;
+        color: #0D162A;
+        line-height: 16px;
+        margin-bottom: 20px;
+    }
+
+    .f_pldr{
+        margin-top: 20px;
+        .fp_box{
+            display: flex;
+            width: 526px;
+            height: 125px;
+            border-radius: 4px;
+            border: 1px solid #EDEEF0;
+            position: relative;
+            .fpb_pre{
+                width: calc(50% - 1px);
+                height: 100%;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                .fpbp_btn{
+                    width: 140px;
+                    height: 36px;
+                    border-radius: 6px;
+                    border: 1px solid #E5E7EB;
+                    font-family: PingFangSC, PingFang SC;
+                    font-weight: 400;
+                    font-size: 12px;
+                    color: #761E6A;
+                    line-height: 32px;
+                    text-align: center;
+                    cursor: pointer;
+                }
+                &.sc{
+                    border-left: 1px solid #EDEEF0;
+                    .fpbp_btn{
+                        background: #761E6A;
+                        border: 1px solid #761E6A;
+                        color: #FFFFFF;
+                    }
+                }
+            }
+            img{
+                width: 50px;
+                height: 20px;
+                position: absolute;
+                left: 50%;
+                margin-left: -25px;
+                top: 50%;
+                margin-top: -10px;
+            }
+        }
+        p{
+            margin-top: 11px;
+            font-family: PingFangSC, PingFang SC;
+            font-weight: 400;
+            font-size: 12px;
+            color: #C1C7D2;
+            line-height: 20px;
+            text-align: justify;
+        }
+    }
+
+    .f_sdlr{
+        padding-top: 10px;
+
+        .fs_add{
+            width: 80px;
+            height: 32px;
+            background: #761E6A;
+            border-radius: 6px;
+            font-family: PingFangSC, PingFang SC;
+            font-weight: 400;
+            font-size: 14px;
+            color: #FFFFFF;
+            line-height: 32px;
+            text-align: center;
+            margin-top: 20px;
+            cursor: pointer;
+            &.del{
+                background: rgb(212, 96, 96);
+                margin: 0;
+                margin-top: 5px;
+            }
+        }
+    }
+
+    .ed_coach{
+        .ec_l{
+            width: calc(50% - 1px);
+            height: 100%;
+            padding-right: 30px;
+            box-sizing: border-box;
+            border-right: 1px solid #ECEEF5;
+            .ecl_cbs{
+                width: 100%;
+                // height: calc(100% - 143px);
+                max-height: 376px;
+                overflow-y: auto;
+            }
+        }
+        .ec_r{
+            width: 50%;
+            padding-left: 30px;
+            box-sizing: border-box;
+            .ecr_text{
+                font-family: PingFang-SC, PingFang-SC;
+                font-weight: bold;
+                font-size: 16px;
+                color: #252525;
+                line-height: 22px;
+                span{
+                    color: #B9B9B9;
+                }
+            }
+            .ecr_names{
+                margin-left: -16px;
+                overflow: hidden;
+                .en_pre{
+                    float: left;
+                    padding: 10px;
+                    background: #F9FAFB;
+                    border-radius: 6px;
+                    margin: 19px 0 0 16px;
+                    span{
+                        font-family: PingFangSC, PingFang SC;
+                        font-weight: 400;
+                        font-size: 14px;
+                        color: #252525;
+                        line-height: 14px;
+                    }
+                    img{
+                        width: 16px;
+                        height: 16px;
+                        margin-left: 10px;
+                        cursor: pointer;
+                    }
+                }
+            }
+        }
+    }
+</style>

+ 3 - 2
src/views/modules/agent/questionnaire.vue

@@ -21,7 +21,7 @@
         <div class="list">
             <div class="l_item" v-for="(item, index) in dataList" :key="index">
                 <div class="li_top adfacjb">
-                    <div class="lt_l">项目名称:{{ item.enterpriseName }}</div>
+                    <div class="lt_l">项目名称:{{ item.programName }}</div>
                     <div class="lt_r adfac">
                         <div class="lr_pre adfac" v-hasPermi="['core:questionnaire:info']" @click="handleSchedule(item)">
                             <img src="@/assets/images/agent/send_mini.png">
@@ -34,6 +34,7 @@
                         <div class="lr_status" :class="{'jxz':item.status===0,'ywc':item.status===1}">{{ item.status===0?'进行中':(item.status===1?'已完成':'未知') }}</div>
                     </div>
                 </div>
+                <div class="li_team">公司名称:{{ item.enterpriseName }}</div>
                 <div class="li_team">团队名称:{{ item.teamName }}</div>
                 <div class="li_wj">问卷名称:{{ item.title }}</div>
                 <div class="li_time_person adf">
@@ -87,9 +88,9 @@
             path: '/agentQuestionnaireSchedule',
             query:{
                 id: item.id,
-                questionnaireName: item.questionnaireName,
                 questionnaireName: item.title,
                 enterpriseName: item.enterpriseName,
+                programName: item.programName,
                 teamName: item.teamName,
                 startTime: item.startTime,
                 endTime: item.endTime,

+ 20 - 11
src/views/modules/agent/questionnaire/publish.vue

@@ -3,7 +3,8 @@
         <div class="top adfac">
             <img src="@/assets/images/agent/arrow_left.png" @click="handleBack">
             <div class="spans">
-                <span>项目管理</span>
+                <span>问卷调研</span>
+                <span>&nbsp;/&nbsp;问卷列表</span>
                 <span class="last">&nbsp;/&nbsp;发布问卷</span>
             </div>
         </div>
@@ -57,9 +58,13 @@
                         <div class="ecl_gs">
                             <div class="eg_title">按项目选</div>
                             <div class="egt_item adfacjb" v-for="(item,index) in companyList" :key="index">
-                                <div class="ei_l adfac">
-                                    <span style="cursor: pointer;" @click="handleChooseUser(item)">{{ item.name }}</span>
-                                    <span>{{ item.num }}人</span>
+                                <div class="ei_l adffc" style="cursor: pointer;">
+                                    <div class="adfac">
+                                        <span @click="handleChooseUser(item)">{{ item.programName }}</span>
+                                        <!-- <span style="margin-left: 20px;">{{ item.num }}人</span> -->
+                                        <span></span>
+                                    </div>
+                                    <div><span style="margin-left: 0;">{{ item.enterpriseName }}-{{ item.teamName }}</span></div>
                                 </div>
                                 <div class="ei_r" @click="handleChooseUser(item)">
                                     <span>成员</span>
@@ -99,13 +104,14 @@
 <script setup name="">
     import { ref, getCurrentInstance,onMounted } from 'vue'
     const { proxy } = getCurrentInstance();
-    import { getCoachProgramList,getCoachList,sendQuestionnaire } from '@/api/agent/index.js'
+    import { getProgramList,getCoachList,sendQuestionnaire } from '@/api/agent/index.js'
     
     const questionnaireId = ref('')
     const title = ref('')
     const type = ref('')
     const params = ref({
         questionnaireId:'',
+        programId:'',
         teamId:'',
         userIds:[],
         persons:[],
@@ -130,16 +136,18 @@
     const buttonLoading = ref(false)
     const canSubmit = ref(true)
 
+
     const handleAddUser = () => {
         userShow.value = true
-        getCoachProgramList({page:1,limit:-1}).then(res=>{
+        getProgramList({page:1,limit:-1}).then(res=>{
             if(res.code !==0) return proxy.$message({type:'warning',message:res.msg});
-            companyList.value = res.data.map(l=>{
+            companyList.value = res.data.list.map(l=>{
                 return {
                     id:l.id,
-                    name:l.enterpriseName,
-                    num:l.teams.reduce((a,b)=>a+b.teamNum,0),
-                    teamId:l.teams[0].teamId
+                    programName:l.programName,
+                    enterpriseName:l.enterpriseName,
+                    teamName:l.teamName,
+                    teamId:l.teamId
                 }
             });
         })
@@ -172,6 +180,7 @@
     }
 
     const handleChooseUser = (item) => {
+        params.value.programId = item.id;
         params.value.teamId = item.teamId;
         getCoachList({teamId:item.teamId,page:1,limit:-1}).then(res=>{
             if(res.code!==0) return proxy.$message({type:'warning',message:res.msg});
@@ -181,7 +190,7 @@
         })
 
         checkShow.value = true
-        companyName.value = item.name
+        companyName.value = item.programName
     }
     const handleUserBack = () => {
         checkShow.value = false

+ 4 - 2
src/views/modules/agent/questionnaire/schedule.vue

@@ -16,6 +16,7 @@
                 </div>
             </div>
             <div class="c_texts adfac">
+                <div class="cl_pre">项目名称:<span>{{ questionnaireInfo.programName }}</span></div>
                 <div class="cl_pre">公司名称:<span>{{ questionnaireInfo.enterpriseName }}</span></div>
                 <div class="cl_pre">团队类型:<span>{{ questionnaireInfo.teamName }}</span></div>
                 <div class="cl_pre">发布时间:<span>{{ questionnaireInfo.startTime }}</span></div>
@@ -64,6 +65,7 @@
                 <div class="cdc_title">生成报告</div>
                 <i class="el-icon-close cdc_close" style="font-size: 20px;color: #393939;" @click.stop="closeReportAlert"></i>
                 <img src="@/assets/images/agent/report.gif">
+                <p>{{ questionnaireInfo.programName }}</p>
                 <p>{{ questionnaireInfo.enterpriseName }} - {{ questionnaireInfo.teamName }}</p>
                 <p>报告正在生成中,预计需要时间<span>7-10分钟</span></p>
                 <p>可去<b>"报告管理"</b>中查看结果~</p>
@@ -235,10 +237,10 @@
             .c_texts{
                 margin-top: 20px;
                 .cl_pre{
-                    width: 25%;
+                    width: 20%;
                     font-family: PingFang-SC, PingFang-SC;
                     font-weight: 400;
-                    font-size: 14px;
+                    font-size: 14px; 
                     color: #808080;
                     line-height: 16px;
                     span{

+ 1 - 1
src/views/modules/home.vue

@@ -115,7 +115,7 @@
           <div class="hb_list">
             <div class="hl_item adfacjb" v-for="(item,index) in dcwjList" :key="index">
               <div class="hil_l">
-                <p>{{ item.enterpriseName }}</p>
+                <p><span v-if="item.programName">{{ item.programName }} - </span>{{ item.enterpriseName }}</p>
                 <p class="tip">{{ item.teamName }} · {{ item.userNum }}名成员</p>
               </div>
               <div class="hil_r">