team.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <template>
  2. <div class="team">
  3. <el-row :gutter="20" style="width: 100%; overflow:hidden;">
  4. <el-col :span="4">
  5. <div class="teamTree">
  6. <el-input class="search-input" v-model="treeValue" placeholder="团队名称查找" prefix-icon="Search" @keyup.enter="initTeam"></el-input>
  7. <div class="custom-tree-node" v-for="item in teamData" :key="item.id" @click.stop="initList(item)">
  8. <span class="custom-tree-node-label">{{ item.name }}</span>
  9. <el-dropdown class="custom-tree-node-more" @command="treeNodeCommend(item, $event)">
  10. <el-icon><MoreFilled /></el-icon>
  11. <template #dropdown>
  12. <el-dropdown-menu>
  13. <el-dropdown-item command="编辑">编辑</el-dropdown-item>
  14. <el-dropdown-item command="删除">删除</el-dropdown-item>
  15. </el-dropdown-menu>
  16. </template>
  17. </el-dropdown>
  18. </div>
  19. </div>
  20. <el-button class="add-btn" icon="plus" @click="addTeamDraw">添加团队</el-button>
  21. </el-col>
  22. <el-col :span="20">
  23. <el-row :gutter="20">
  24. <el-col :span="22" class="info">
  25. <h3>{{ teamInfo.name }}</h3>
  26. <p>所属机构: {{ teamInfo?.deptName }}</p>
  27. <p>管理人: {{ teamInfo?.managerName?`${teamInfo?.managerName}-`:'' }}{{ teamInfo?.managerId }}</p>
  28. <p>描述:{{ teamInfo?.describeInformation }}</p>
  29. </el-col>
  30. <el-col :span="2" class="btn">
  31. <el-button plain @click="setPeople">设置负责人</el-button>
  32. </el-col>
  33. </el-row>
  34. <el-input style="width: 300px; margin: 10px 0" v-model="searchValue" prefix-icon="Search" placeholder="输入姓名,手机号,工号查找" clearable @keyup.enter="initList(teamInfo)"></el-input>
  35. <el-table
  36. :data="tableData"
  37. ref="operationListRef"
  38. height="530"
  39. @selection-change="handleSelectionChange"
  40. >
  41. <el-table-column type="selection" width="55"></el-table-column>
  42. <el-table-column label="姓名" prop="name" width="80">
  43. <template #default="scope">
  44. <div class="nameInfo">{{ scope.row.name }}<span v-show="scope.row.manager === '1'">负责人</span></div>
  45. </template>
  46. </el-table-column>
  47. <el-table-column label="手机号" prop="mobile" width="150"></el-table-column>
  48. <el-table-column label="工号" prop="userId" width="200"></el-table-column>
  49. <el-table-column label="类型" prop="typeAttr" width="100">
  50. <template #default="scope">
  51. {{ scope.row.typeAttr == '0'?'个代':scope.row.typeAttr == '1'?'渠道':scope.row.typeAttr == '2'?'团队':scope.row.typeAttr == '3'?'电销组': '' }}
  52. </template>
  53. </el-table-column>
  54. <el-table-column label="归属" prop="deptName" width="200"></el-table-column>
  55. <el-table-column label="所属机构" prop="deptName" width="200"></el-table-column>
  56. <el-table-column label="人员状态" prop="status" width="150">
  57. <template #default="scope">
  58. {{ scope.row.status == '0'?'待认证':scope.row.status == '1'?'已认证':scope.row.status == '2'?'待提交资料':scope.row.status == '3'?'已入职':'' }}
  59. </template>
  60. </el-table-column>
  61. <el-table-column label="账号状态" prop="isEnable" width="150">
  62. <template #default="scope">
  63. {{ scope.row.isEnable == '1'?'禁用':scope.row.isEnable == '0'?'启用': '--' }}
  64. </template>
  65. </el-table-column>
  66. <el-table-column label="管理人" prop="leaderName" width="150"></el-table-column>
  67. <el-table-column label="管理人工号" prop="leaderId" width="200"></el-table-column>
  68. <el-table-column label="推荐人" prop="referrerName" width="150"></el-table-column>
  69. <el-table-column label="推荐人工号" prop="referrerId" width="200"></el-table-column>
  70. <el-table-column fixed="right" label="操作" width="120">
  71. <template #default="scope">
  72. <div style="display: flex; align-items: center; justify-content: space-between">
  73. <a style="color: #409EFF; cursor: pointer" @click="showDetail(scope)">详情</a>&nbsp;
  74. <el-dropdown placement="bottom" trigger="click" @command="tableDataCommand(scope, $event)">
  75. <a style="color: #409EFF; cursor: pointer">更多</a>
  76. <template #dropdown>
  77. <el-dropdown-menu>
  78. <el-dropdown-item command="编辑">编辑</el-dropdown-item>
  79. <el-dropdown-item command="启用">启用</el-dropdown-item>
  80. <el-dropdown-item command="禁用">禁用</el-dropdown-item>
  81. <el-dropdown-item command="删除">删除</el-dropdown-item>
  82. <el-dropdown-item command="分配管理人">分配管理人</el-dropdown-item>
  83. </el-dropdown-menu>
  84. </template>
  85. </el-dropdown>
  86. </div>
  87. </template>
  88. </el-table-column>
  89. </el-table>
  90. <div style="display: flex; justify-content: center; margin-top: 15px">
  91. <el-pagination
  92. v-model:current-page="currentPage"
  93. v-model:page-size="pageSize"
  94. :page-sizes="[10, 20, 30, 40]"
  95. layout="total, sizes, prev, pager, next, jumper"
  96. :total="total"
  97. @size-change="handleSizeChange"
  98. @current-change="handleCurrentChange"
  99. />
  100. </div>
  101. </el-col>
  102. </el-row>
  103. <el-dialog
  104. v-model="dialogShow"
  105. :title="title"
  106. width="1000"
  107. >
  108. <addOperation ref="AddOperationRef" @closeDialog="closeAddOperation"></addOperation>
  109. </el-dialog>
  110. <el-dialog
  111. v-model="addTeamShow"
  112. title="添加"
  113. width="800"
  114. >
  115. <addTeam ref="AddTeamRef" @closeDialog="closeAddTeamDialog"></addTeam>
  116. </el-dialog>
  117. <el-dialog
  118. v-model="allocationShow"
  119. title="分配管理人"
  120. width="800"
  121. >
  122. <allocation ref="AllocationRef" @closeDialog="closeAllocation"></allocation>
  123. </el-dialog>
  124. <el-dialog
  125. v-model="peopleShow"
  126. title="设置负责人"
  127. width="800"
  128. >
  129. <el-radio-group v-if="tableData?.length>0" v-model="radioValue" class="allocation-radio">
  130. <el-radio v-for="item in tableData" :value="item.id" size="large">
  131. <template #default>
  132. <div>{{ item.name }}</div>
  133. <div>{{ item.id }}</div>
  134. </template>
  135. </el-radio>
  136. </el-radio-group>
  137. <el-empty v-else description="暂无数据" />
  138. <template #footer>
  139. <el-button @click="onCancel">取消</el-button>
  140. <el-button type="primary" @click="onConfirm">确定</el-button>
  141. </template>
  142. </el-dialog>
  143. </div>
  144. </template>
  145. <script setup lang="ts">
  146. import { ref, onMounted } from 'vue'
  147. import {ElMessageBox, ElMessage, TableInstance} from 'element-plus'
  148. import { useRouter } from 'vue-router'
  149. import api from "@/api";
  150. import addOperation from './modules/addOperation.vue'
  151. import allocation from './modules/allocation.vue'
  152. import addTeam from './modules/addTeam.vue'
  153. import Allocation from "@/views/operationManagement/modules/allocation.vue";
  154. import {initial} from "lodash-es";
  155. import team from "@/api/modules/team.ts";
  156. let myRouter = useRouter()
  157. const AddTeamRef = ref(null)
  158. const AddOperationRef = ref(null)
  159. const AllocationRef = ref(null)
  160. // 机构数据
  161. let options = ref([])
  162. // 获取机构数据
  163. const institutionList = () => {
  164. api.institutionApi.institutionList({ name: '', system: '' }).then(res => {
  165. if(res?.code == 200) {
  166. options.value = res.data
  167. } else {
  168. ElMessage({
  169. message: res.msg,
  170. type: 'warning'
  171. })
  172. }
  173. })
  174. }
  175. // 团队
  176. let treeValue = ref('')
  177. let teamData = ref([])
  178. let addTeamShow = ref(false)
  179. const initTeam = () => {
  180. api.teamApi.teamList({
  181. param: treeValue.value,
  182. attribute: 1
  183. }).then(res => {
  184. if(res.code == 200) {
  185. teamData.value = res.data
  186. if(teamData.value) {
  187. initList(teamData.value[0])
  188. }
  189. } else {
  190. ElMessage({
  191. message: res.msg,
  192. type: 'warning'
  193. })
  194. }
  195. })
  196. }
  197. // 分页
  198. let currentPage = ref(1)
  199. let pageSize = ref(10)
  200. let total = ref(0)
  201. const handleSizeChange = (size) => {
  202. pageSize.value = size
  203. initTeam()
  204. }
  205. const handleCurrentChange = (page) => {
  206. currentPage.value = page
  207. initTeam()
  208. }
  209. // 初始化列表
  210. let teamInfo = ref({
  211. name: '',
  212. deptName: '',
  213. managerName: '',
  214. managerId: '',
  215. describeInformation: ''
  216. })
  217. const initList = (item) => {
  218. teamInfo.value = item
  219. api.teamApi.getTeamUser({
  220. id: item.id,
  221. name: searchValue.value,
  222. pages: currentPage.value,
  223. size: pageSize.value
  224. }).then(res => {
  225. if(res.code == 200) {
  226. tableData.value = res.data.records
  227. total.value = res.data.total
  228. } else {
  229. ElMessage({
  230. message: res.msg,
  231. type: 'warning'
  232. })
  233. }
  234. })
  235. }
  236. const treeNodeCommend = (item, e) => {
  237. switch (e) {
  238. case '编辑':
  239. addTeamShow.value = true
  240. nextTick(() => {
  241. AddTeamRef.value.initEdit(item, true, 1)
  242. })
  243. break;
  244. case '删除':
  245. ElMessageBox({
  246. title: '删除团队',
  247. message: '确定要删除该团队吗?',
  248. type: 'warning',
  249. showCancelButton: true,
  250. confirmButtonText: '确定',
  251. cancelButtonText: '取消',
  252. }).then(( action ) => {
  253. if(action === 'confirm') {
  254. api.teamApi.deleteById(item.id).then(res => {
  255. if(res.code == 200) {
  256. ElMessage({
  257. message: res.msg,
  258. type: 'success'
  259. })
  260. initTeam()
  261. } else {
  262. ElMessage({
  263. message: res.msg,
  264. type: 'warning'
  265. })
  266. }
  267. })
  268. }
  269. }).catch(( action ) => {
  270. })
  271. break;
  272. }
  273. }
  274. const addTeamDraw = () => {
  275. addTeamShow.value = true
  276. nextTick(() => {
  277. AddTeamRef.value.teamForm.attribute = 1
  278. })
  279. }
  280. const closeAddTeamDialog = (type) => {
  281. addTeamShow.value = false
  282. initTeam()
  283. }
  284. // 搜索字段
  285. let searchValue = ref('')
  286. // 列表数据
  287. let tableData = ref([])
  288. // 编辑弹框
  289. let dialogShow = ref(false)
  290. // 编辑弹框标题
  291. let title = ref('编辑')
  292. // 表格组件中的勾选
  293. const handleSelectionChange = (row) => {
  294. }
  295. // 详情
  296. const showDetail = (scope) => {
  297. myRouter.push({
  298. path: '/operationDetail',
  299. query: {
  300. id: scope.row.userId
  301. }
  302. })
  303. }
  304. // 分配管理人
  305. let allocationShow = ref(false)
  306. // 设置负责人
  307. let peopleShow = ref(false)
  308. let radioValue = ref('')
  309. const setPeople = () => {
  310. peopleShow.value = true
  311. // pageSize.value = 99999
  312. initList(teamInfo.value)
  313. }
  314. const onCancel = () => {
  315. peopleShow.value = false
  316. radioValue.value = ''
  317. }
  318. const onConfirm = () => {
  319. if(!radioValue.value) {
  320. ElMessage({
  321. message: '请选择负责人',
  322. type: 'warning'
  323. })
  324. return
  325. }
  326. api.teamApi.setResponsiblePerson({
  327. id: teamInfo.value.id,
  328. managerId: radioValue.value
  329. }).then(res => {
  330. if(res.code == 200) {
  331. ElMessage({
  332. message: res.msg,
  333. type: 'success'
  334. })
  335. initList(teamInfo.value)
  336. } else {
  337. ElMessage({
  338. message: res.msg,
  339. type: 'warning'
  340. })
  341. }
  342. peopleShow.value = false
  343. })
  344. }
  345. // 关闭设置负责人
  346. const closeAllocation = (type: boolean) => {
  347. allocationShow.value = type
  348. }
  349. // 更多
  350. const tableDataCommand = (scope, e) => {
  351. switch (e) {
  352. case '编辑':
  353. dialogShow.value = true
  354. nextTick(() => {
  355. AddOperationRef.value.initEditData(scope.row.userId)
  356. })
  357. title.value = '编辑'
  358. break;
  359. case '删除':
  360. ElMessageBox({
  361. title: '删除业务员',
  362. message: '确定要删除该业务员吗?',
  363. type: 'warning',
  364. showCancelButton: true,
  365. confirmButtonText: '确定',
  366. cancelButtonText: '取消',
  367. }).then(( action ) => {
  368. if(action === 'confirm') {
  369. api.teamApi.deleteAssociatedUsers({
  370. id: teamInfo.value.id,
  371. userIds: [scope.row.id]
  372. }).then(res => {
  373. if(res?.code == 200) {
  374. ElMessage({
  375. message: res.msg,
  376. type: 'success'
  377. })
  378. initList(teamInfo.value)
  379. } else {
  380. ElMessage({
  381. message: res.msg,
  382. type: 'warning'
  383. })
  384. }
  385. })
  386. }
  387. }).catch(( action ) => {
  388. })
  389. break;
  390. case '禁用':
  391. ElMessageBox({
  392. title: '禁用业务员',
  393. message: '确定要禁用该业务员吗?',
  394. type: 'warning',
  395. showCancelButton: true,
  396. confirmButtonText: '确定',
  397. cancelButtonText: '取消',
  398. }).then(( action ) => {
  399. if(action === 'confirm') {
  400. let data = {
  401. id: [scope.row.id],
  402. isEnable: 1,
  403. getAll: 0
  404. }
  405. api.operationApi.operationIsEnable(data).then(res => {
  406. if(res?.code == 200) {
  407. ElMessage({
  408. message: res.msg,
  409. type: 'success'
  410. })
  411. initList(teamInfo.value)
  412. } else {
  413. ElMessage({
  414. message: res.msg,
  415. type: 'warning'
  416. })
  417. }
  418. })
  419. }
  420. }).catch(( action ) => {
  421. })
  422. break;
  423. case '启用':
  424. ElMessageBox({
  425. title: '启用业务员',
  426. message: '确定要启用该业务员吗?',
  427. type: 'warning',
  428. showCancelButton: true,
  429. confirmButtonText: '确定',
  430. cancelButtonText: '取消',
  431. }).then(( action ) => {
  432. if(action === 'confirm'){
  433. let data = {
  434. id: [scope.row.id],
  435. isEnable: 0,
  436. getAll: 0
  437. }
  438. api.operationApi.operationIsEnable(data).then(res => {
  439. if(res?.code == 200) {
  440. ElMessage({
  441. message: res.msg,
  442. type: 'success'
  443. })
  444. initList(teamInfo.value)
  445. } else {
  446. ElMessage({
  447. message: res.msg,
  448. type: 'warning'
  449. })
  450. }
  451. })
  452. }
  453. }).catch(( action ) => {
  454. })
  455. break;
  456. case '分配管理人':
  457. allocationShow.value = true
  458. nextTick(() => {
  459. AllocationRef.value.initCheckedKeys(scope.row.deptId, selectType.value, [scope.row.id])
  460. })
  461. break;
  462. }
  463. }
  464. const closeAddOperation = (type: string) => {
  465. dialogShow.value = false
  466. }
  467. onMounted(() => {
  468. institutionList()
  469. initTeam()
  470. })
  471. </script>
  472. <style scoped lang="scss">
  473. .team{
  474. height: 770px;
  475. background: #fff;
  476. .search-input{
  477. padding: 10px 20px;
  478. }
  479. .teamTree{
  480. height: 700px;
  481. overflow-y: auto;
  482. background: #fff;
  483. .custom-tree-node{
  484. width: calc(100% - 40px);
  485. display: flex;
  486. justify-content: space-between;
  487. align-items: center;
  488. padding: 5px 10px;
  489. margin: 5px auto;
  490. cursor: pointer;
  491. &:hover{
  492. background: rgba(0,0,0,.1);
  493. }
  494. .custom-tree-node-label{
  495. width: 70%;
  496. overflow: hidden;
  497. white-space: nowrap;
  498. text-overflow: ellipsis;
  499. }
  500. }
  501. }
  502. .add-btn{
  503. display: block;
  504. margin: 0 auto;
  505. }
  506. .info{
  507. h3{
  508. margin: 10px 0;
  509. }
  510. p{
  511. margin: 6px 0;
  512. font-size: 14px;
  513. color: rgba(0,0,0,.7);
  514. }
  515. }
  516. .btn{
  517. display: flex;
  518. justify-content: flex-end;
  519. align-items: flex-end;
  520. }
  521. .nameInfo{
  522. display: flex;
  523. justify-content: center;
  524. align-content: center;
  525. span{
  526. background: #f0f0f0;
  527. padding: 2px 4px;
  528. border-radius: 2px;
  529. }
  530. }
  531. }
  532. </style>