index.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. <div id="app" v-cloak>
  2. <el-card shadow="never" style="border:0;min-width: 1000px;" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  3. <div slot="header">
  4. <span>团队管理</span>
  5. <!-- <div style="float: right">-->
  6. <!-- <el-button type="primary" size="small" style="padding: 9px 15px !important;" @click="editClick">添加团长</el-button>-->
  7. <!-- </div>-->
  8. </div>
  9. <div class="table-body">
  10. <el-form ref="form" style="margin-bottom: 10px;" :model="search" label-width="96px" size="mini">
  11. <el-row :gutter="12">
  12. <el-col :span="6" style="padding-left: 0;" class="top_form">
  13. <el-form-item label="会员ID">
  14. <el-input v-model="search.user_id" placeholder="请输入会员ID" clearable></el-input>
  15. </el-form-item>
  16. </el-col>
  17. <el-col :span="6" class="top_form">
  18. <el-form-item label="会员">
  19. <el-input v-model="search.mobile" placeholder="会员手机号" clearable></el-input>
  20. </el-form-item>
  21. </el-col>
  22. <el-col :span="6" class="top_form">
  23. <el-form-item label="团队等级">
  24. <el-select v-model="search.level" placeholder="请选择会员等级">
  25. <el-option label="全部" value=""></el-option>
  26. <el-option v-for="(name,level) in level_arr" :label="name" :value="level" :key="level"></el-option>
  27. </el-select>
  28. </el-form-item>
  29. </el-col>
  30. </el-row>
  31. <el-row :gutter="24">
  32. <el-col class="top_form">
  33. <el-form-item label="加入时间">
  34. <el-date-picker
  35. v-model="search.time"
  36. type="datetimerange"
  37. range-separator="至"
  38. start-placeholder="开始日期"
  39. end-placeholder="结束日期"
  40. value-format="yyyy-MM-dd HH:mm:ss"
  41. @change="addTimeChange"
  42. :default-time="['00:00:00', '23:59:59']"
  43. >
  44. </el-date-picker>
  45. </el-form-item>
  46. </el-col>
  47. <el-col>
  48. <el-button type="primary" size="mini" @click="toSearch" >搜索</el-button>
  49. <el-button type="danger" size="mini" @click="resetSearch" >清除</el-button>
  50. </el-col>
  51. </el-row>
  52. </el-form>
  53. <el-tabs v-model="activeName">
  54. <el-table :data="list" stripe v-loading="loading" size="small" style="margin-bottom: 15px;">
  55. <el-table-column prop="user_id" label="会员ID" align="center" width="80"></el-table-column>
  56. <el-table-column label="用户信息" align="center" width="180">
  57. <template slot-scope="scope">
  58. <el-tag class="user-tag" type="warning" size="small" v-if="scope.row.is_virtual" style="position: absolute;left: 5px;top: 5px;zoom: 0.8;">虚拟</el-tag>
  59. <com-image style="float: left;margin-right: 5px;" class="avatar_url" mode="aspectFill" :src="scope.row.user.avatar_url ? scope.row.user.avatar_url : '/resources/img/common/default-avatar.png'"></com-image>
  60. <div>{{scope.row.user.nickname}}<br/>{{scope.row.user.mobile}}</div>
  61. </template>
  62. </el-table-column>
  63. <el-table-column label="团队等级" prop="level" align="center" width="120">
  64. <template slot-scope="scope">
  65. <el-tag size="small" type="info" v-if="scope.row.level == 0">默认等级</el-tag>
  66. <el-tag size="small" v-else>{{ level_arr[scope.row.level] }}</el-tag>
  67. </template>
  68. </el-table-column>
  69. <el-table-column label="升级时间" align="center" width="160" >
  70. <template slot-scope="scope">
  71. <div v-if="scope.row.upgrade_level_at > 0">
  72. {{ scope.row.upgrade_level_at|dateTimeFormat('Y-m-d H:i:s') }}
  73. </div>
  74. <div v-else>
  75. {{ scope.row.created_at|dateTimeFormat('Y-m-d H:i:s') }}
  76. </div>
  77. </template>
  78. </el-table-column>
  79. <el-table-column label="助力升级会员" align="center" width="100">
  80. <template slot-scope="scope">
  81. 共 {{ scope.row.help_num }} 人<template v-if="scope.row.has_virtual"><el-tag class="user-tag" type="warning" size="small" style="zoom: 0.8;">含{{scope.row.virtual_user_num}}个虚拟会员</el-tag></template>
  82. <el-button v-if="scope.row.help_num > 0" type="text" @click="handle('help', scope.row)" style="margin-left: 10px;">查看</el-button>
  83. </template>
  84. </el-table-column>
  85. <el-table-column label="推荐人" align="center" width="150">
  86. <template slot-scope="scope">
  87. <div v-if="scope.row.puser">
  88. <com-image style="float: left;margin-right: 5px;" class="avatar_url" mode="aspectFill" :src="scope.row.puser.avatar_url ? scope.row.puser.avatar_url : '/resources/img/common/default-avatar.png'"></com-image>
  89. <div>ID:{{scope.row.puser.id}}<br/>{{scope.row.puser.nickname}}</div>
  90. </div>
  91. <div v-else="scope.row.puser">-</div>
  92. </template>
  93. </el-table-column>
  94. <el-table-column :label="capital_map.second_prize + '用户'" align="center" width="150">
  95. <template slot-scope="scope">
  96. <div v-if="scope.row.topuser">
  97. <com-image style="float: left;margin-right: 5px;" class="avatar_url" mode="aspectFill" :src="scope.row.topuser.avatar_url ? scope.row.topuser.avatar_url : '/resources/img/common/default-avatar.png'"></com-image>
  98. <div>ID:{{scope.row.topuser.id}}<br/>{{scope.row.topuser.nickname}}</div>
  99. </div>
  100. <div v-else="scope.row.puser">-</div>
  101. </template>
  102. </el-table-column>
  103. <el-table-column label="奖励类型" prop="reward_currency" align="center"></el-table-column>
  104. <el-table-column label="已结算佣金" prop="commission" align="center"></el-table-column>
  105. <el-table-column :label="capital_map.freeze_fund" prop="frozen_fund" align="center"></el-table-column>
  106. <el-table-column label="业绩" prop="achievement" align="center"></el-table-column>
  107. <el-table-column label="市场业绩" prop="achievement" align="center">
  108. <template slot-scope="scope">
  109. <el-tooltip placement="top" effect="light">
  110. <div slot="content" style="line-height: 24px;">
  111. <div v-if="scope.row.market.length > 0">
  112. <span v-if="scope.row.market[0]">第一市场:¥{{ scope.row.market[0].achievement }}</span>
  113. <br/>
  114. <span v-if="scope.row.market[1]">第二市场:¥{{ scope.row.market[1].achievement }}</span>
  115. </div>
  116. <div v-else>暂无市场</div>
  117. </div>
  118. <el-button>查看</el-button>
  119. </el-tooltip>
  120. </template>
  121. </el-table-column>
  122. <el-table-column label="解冻基金达标" prop="is_thaw" align="center" width="100" >
  123. <template slot-scope="scope">
  124. <div v-if="scope.row.level == 1">-</div>
  125. <div v-if="scope.row.level >= 2">
  126. <el-tag type="danger" size="small" v-if="scope.row.is_thaw == 0">未达标</el-tag>
  127. <el-tag type="success" size="small" v-if="scope.row.is_thaw == 1">达标</el-tag>
  128. <el-tag size="small" v-if="scope.row.is_thaw == 2">部分解冻</el-tag>
  129. </div>
  130. </template>
  131. </el-table-column>
  132. <el-table-column label="加入时间" align="center" width="160" >
  133. <template slot-scope="scope">
  134. {{scope.row.created_at|dateTimeFormat('Y-m-d H:i:s')}}
  135. </template>
  136. </el-table-column>
  137. <el-table-column
  138. label="启用最高奖励"
  139. width="120"
  140. align="center">
  141. <template slot-scope="scope">
  142. <el-switch
  143. :active-value="1"
  144. :inactive-value="0"
  145. @change="handle('change_status', scope.row)"
  146. v-model="scope.row.is_height_commission">
  147. </el-switch>
  148. </template>
  149. </el-table-column>
  150. <el-table-column label="最高奖励" prop="height_commission" align="center"></el-table-column>
  151. <el-table-column label="升级为老板时间" align="center" width="160">
  152. <template slot-scope="scope">
  153. <div v-if="scope.row.upgrade_boss_at > 0">
  154. {{ scope.row.upgrade_boss_at|dateTimeFormat('Y-m-d H:i:s') }}
  155. </div>
  156. </template>
  157. </el-table-column>
  158. <el-table-column label="操作" align="center" width="120">
  159. <!-- <template slot-scope="scope">
  160. <el-button type="text" @click="handle('destroy',scope.row)">删除</el-button>
  161. </template> -->
  162. <template slot-scope="scope">
  163. <el-button type="text" @click="handleCommission(scope.row)">设置最高奖励</el-button>
  164. </template>
  165. </el-table-column>
  166. </el-table>
  167. </el-tabs>
  168. <div style="text-align: right;margin: 20px 0;">
  169. <el-pagination @current-change="pagination" background layout="prev, pager, next" :page-count="pageCount"></el-pagination>
  170. </div>
  171. </div>
  172. </el-card>
  173. <!-- 查看助力用户 -->
  174. <el-dialog title="助力用户" :visible.sync="helpDialog" id="help-dialog" center v-if="helpDialog" :before-close="handleClose">
  175. <div style="position: absolute; left: 25px; top: 15px;">
  176. <el-button v-if="is_change === false" type="primary" size="small" @click="handle('open_change')">换位编辑</el-button>
  177. </div>
  178. <el-alert v-if="is_change" title="注意事项" type="warning" :closable="false">
  179. ① 鼠标拖拽可以对表格用户进行换位!<br>
  180. ② 对助力用户的位置进行更换会导致团队下的用户给平台补贴的人也会随之改变,所以请谨慎使用此功能!<br>
  181. ③ 换位任务正在处理中,有会员下单有可能会导致平台补贴给到不同用户,建议在系统非繁忙时段进行换位!<br>
  182. ④ 换位前此用户下1、2号位的位置业绩不会因为换位而改变
  183. </el-alert>
  184. <el-table :data="helpList" stripe v-loading="helpLoading" size="small" row-key="pos" style="margin-bottom: 15px;">
  185. <el-table-column prop="user_id" label="会员ID" align="center" width="150"></el-table-column>
  186. <el-table-column label="基本信息" align="center" width="200">
  187. <template slot-scope="scope">
  188. <el-tag class="user-tag" type="warning" size="small" v-if="scope.row.is_virtual" style="position: absolute;left: 5px;top: 5px;zoom: 0.8;">虚拟</el-tag>
  189. <com-image style="float: left;margin-right: 5px;" class="avatar_url" mode="aspectFill" :src="scope.row.user.avatar_url ? scope.row.user.avatar_url : '/resources/img/common/default-avatar.png'"></com-image>
  190. <div>{{scope.row.user.nickname}}<br/>{{scope.row.user.mobile}}</div>
  191. </template>
  192. </el-table-column>
  193. <el-table-column :label="pos_name" align="center">
  194. <template slot-scope="scope">
  195. {{ scope.row.pos }}
  196. </template>
  197. </el-table-column>
  198. <el-table-column v-if="is_change" label="更改后位置" align="center">
  199. <template slot-scope="scope">
  200. {{ scope.row.now_pos ?? scope.row.pos }}
  201. </template>
  202. </el-table-column>
  203. <el-table-column label="助力时间" align="center">
  204. <template slot-scope="scope">
  205. {{scope.row.created_at|dateTimeFormat('Y-m-d H:i:s')}}
  206. </template>
  207. </el-table-column>
  208. </el-table>
  209. <div style="text-align: right;margin: 20px 0;">
  210. <el-pagination v-if="is_change === false" @current-change="helpPagination" background layout="prev, pager, next" :page-count="helpPageCount"></el-pagination>
  211. </div>
  212. <div style="display: flex; flex-direction: row-reverse;" v-if="is_change">
  213. <el-button style="margin-left: 15px;" type="primary" @click="handle('submit_change')" size="small">换位提交</el-button>
  214. <el-button @click="handle('close_change')" size="small">取消编辑</el-button>
  215. </div>
  216. </el-dialog>
  217. <el-dialog title="设置佣金最高奖励" :visible.sync="dialogCommission" width="30%">
  218. <el-form :model="commissionForm" label-width="80px" :rules="commissionFormRules" ref="commissionForm">
  219. <el-form-item label="最高奖励" prop="price" size="small">
  220. <el-input type="number" v-model="commissionForm.height_commission" placeholder="请输入金额"></el-input>
  221. </el-form-item>
  222. </el-form>
  223. <div slot="footer" class="dialog-footer">
  224. <el-button @click="dialogCommission = false">取消</el-button>
  225. <el-button :loading="btnLoading" type="primary" @click="commissionSubmit">确定</el-button>
  226. </div>
  227. </el-dialog>
  228. </div>
  229. <script src="/resources/js/Sortable.min.js"></script>
  230. <script src="/resources/unpkg/vuedraggable@2.18.1/dist/vuedraggable.umd.min.js"></script>
  231. <script>
  232. const app = new Vue({
  233. el: '#app',
  234. data: {
  235. activeName: '-1',
  236. loading: false,
  237. helpLoading: false,
  238. helpDialog: false,
  239. page: 1,
  240. pageCount: 0,
  241. helpPage: 1,
  242. helpPageCount: 0,
  243. list: [],
  244. helpList: [],
  245. hepl_uid:0,
  246. search: {
  247. user_id: null,
  248. mobile: null,
  249. level: null,
  250. start_at: null,
  251. end_at: null,
  252. },
  253. //等级列表信息
  254. level_arr: [],
  255. capital_map: {
  256. first_prize: '直推奖',
  257. second_prize: '平台补贴',
  258. equal_prize: '培育奖',
  259. freeze_fund: '冻结基金',
  260. },
  261. is_change: false,
  262. pos_name: '助力位置',
  263. tableObject: {},
  264. helpLimit: 100,
  265. commissionForm: {
  266. id:0,
  267. height_commission:0,
  268. },
  269. commissionFormRules: {
  270. height_commission: [
  271. {required: true, message: '金额不能为空', trigger: 'blur'},
  272. ],
  273. },
  274. btnLoading:false,
  275. dialogCommission:false,
  276. },
  277. mounted() {
  278. this.loadData();
  279. },
  280. methods: {
  281. //获取列表信息
  282. loadData() {
  283. this.loading = true;
  284. let params = {
  285. r: 'double-copy/default/index',
  286. page:this.page,
  287. };
  288. params = Object.assign(params, this.search);
  289. request({
  290. params: params,
  291. method: 'get'
  292. }).then(e => {
  293. this.loading = false;
  294. if (e.data.code == 0) {
  295. this.list = e.data.data.list.list;
  296. this.level_arr = e.data.data.level_arr;
  297. this.pageCount = e.data.data.list.page_count;
  298. this.page = e.data.data.list.page;
  299. if (!isEmpty(e.data.data.capital_map)) this.capital_map = e.data.data.capital_map;
  300. } else {
  301. this.$message.error(e.data.msg);
  302. }
  303. }).catch(e => {
  304. this.loading = false;
  305. });
  306. },
  307. pagination(currentPage) {
  308. let self = this;
  309. self.page = currentPage;
  310. self.loadData();
  311. },
  312. helpPagination(currentPage) {
  313. let self = this;
  314. self.helpPage = currentPage;
  315. self.loadHelpList();
  316. },
  317. //搜索时间处理
  318. addTimeChange(v){
  319. this.search.start_at = v?v[0]:'';
  320. this.search.end_at = v?v[1]:'';
  321. },
  322. //搜索
  323. toSearch() {
  324. this.page = 1;
  325. this.loadData();
  326. },
  327. //清空搜索
  328. resetSearch() {
  329. this.search = {};
  330. this.loadData();
  331. },
  332. // 操作处理
  333. handle(type, data = null) {
  334. let id = data ? parseInt(data.id) : '';
  335. switch (type) {
  336. case 'destroy':
  337. params = {id: data.id, status: -1};
  338. this.$confirm('删除该条数据后不可以恢复, 是否继续?', '警告', {type: 'warning'}).then(() => {
  339. this.send(params,'double-copy/default/handle',(resp) => {
  340. if (resp.code == 0) this.loadData();
  341. })
  342. })
  343. break;
  344. case 'help':
  345. this.helpDialog = true;
  346. this.hepl_uid = data.user_id;
  347. this.loadHelpList();
  348. break;
  349. case 'open_change':
  350. this.helpList.forEach((item, index) => {
  351. this.helpList[index].now_pos = item.pos
  352. })
  353. this.is_change = true;// 开启编辑
  354. this.pos_name = '更换前位置'
  355. this.$nextTick(() => {
  356. this.rowDrop();
  357. })
  358. $("#help-dialog table tr").css({"cursor":"pointer"});
  359. break;
  360. case 'close_change':
  361. this.close_change()
  362. this.loadHelpList();
  363. break;
  364. case 'submit_change':
  365. this.$confirm('确定更换这些助力会员位置吗?', '警告', {type: 'warning'}).then(() => {
  366. this.send(this.helpList,'double-copy/default/change',(resp) => {
  367. if (resp.code == 0) {
  368. this.handleClose();
  369. this.loadData();
  370. }
  371. }, 'post')
  372. })
  373. break;
  374. case 'change_status':// 修改状态
  375. params = {
  376. id: data.id,
  377. is_height_commission: data.is_height_commission
  378. };
  379. this.send(params,'double-copy/default/handle');
  380. break;
  381. }
  382. },
  383. send(params,url,callback = null, method = 'get') {
  384. let self = this;
  385. let basic_params = {
  386. r: url
  387. };
  388. let data = method === 'get' ? null : params
  389. params = method === 'get' ? Object.assign(basic_params, params) : basic_params;
  390. request({
  391. params: params,
  392. data: data,
  393. method: method
  394. }).then(e => {
  395. if (e.data.code == 0) {
  396. self.$message.success(e.data.msg);
  397. } else {
  398. self.$message.error(e.data.msg);
  399. }
  400. if (callback) callback(e.data);
  401. }).catch(e => {
  402. console.log(e);
  403. });
  404. },
  405. handleClose() {
  406. this.helpDialog = false
  407. this.close_change()
  408. },
  409. close_change() {
  410. this.pos_name = '助力位置'
  411. this.is_change = false;// 开启编辑
  412. this.helpList.forEach((item, index) => {
  413. this.helpList[index].now_pos = item.pos
  414. })
  415. $("#help-dialog table tr").css({"cursor":"default"});
  416. this.tableObject.destroy();
  417. },
  418. loadHelpList() {
  419. this.helpLoading = true;
  420. let params = {
  421. r: 'double-copy/default/help-list',
  422. user_id:this.hepl_uid,
  423. page:this.helpPage,
  424. limit:this.helpLimit,
  425. };
  426. request({
  427. params: params,
  428. method: 'get'
  429. }).then(e => {
  430. this.helpLoading = false;
  431. if (e.data.code == 0) {
  432. this.helpList = e.data.data.list;
  433. this.helpPage = e.data.data.page;
  434. this.helpPageCount = e.data.data.page_count;
  435. } else {
  436. this.$message.error(e.data.msg);
  437. }
  438. }).catch(e => {
  439. this.helpLoading = false;
  440. });
  441. },
  442. //行拖拽
  443. rowDrop() {
  444. const tbody = document.querySelector('#help-dialog .el-table__body-wrapper tbody')
  445. console.log(tbody,'tbody')
  446. const _this = this
  447. this.tableObject = Sortable.create(tbody, {
  448. onEnd({ newIndex, oldIndex }) {
  449. let curr_page = (_this.helpPage - 1) * _this.helpLimit
  450. _this.helpList[oldIndex].now_pos = newIndex + 1
  451. const currRow = _this.helpList.splice(oldIndex, 1)[0]
  452. _this.helpList.splice(newIndex, 0, currRow)
  453. _this.helpList.forEach((item, index) => {
  454. _this.helpList[index].now_pos = curr_page + (index + 1)
  455. })
  456. console.log(_this.helpList)
  457. }
  458. })
  459. },
  460. handleCommission(row) {
  461. this.commissionForm.id = row.id;
  462. this.commissionForm.height_commission = row.height_commission;
  463. this.dialogCommission = true;
  464. },
  465. commissionSubmit() {
  466. this.$refs.commissionForm.validate((valid) => {
  467. if (valid) {
  468. this.commissionRequest();
  469. }
  470. });
  471. },
  472. commissionRequest(){
  473. let para = Object.assign({}, this.commissionForm);
  474. this.btnLoading = true;
  475. request({
  476. params: {
  477. r: 'double-copy/default/commission',
  478. },
  479. method: 'post',
  480. data: para,
  481. }).then(e => {
  482. if (e.data.code === 0) {
  483. this.$message.success(e.data.msg);
  484. this.loadData();
  485. } else {
  486. this.$message.error(e.data.msg);
  487. }
  488. this.dialogCommission = false;
  489. this.btnLoading = false;
  490. }).catch(e => {
  491. this.dialogCommission = false;
  492. this.btnLoading = false;
  493. });
  494. },
  495. }
  496. });
  497. </script>