hintDetail.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. <template>
  2. <div class="hintDetail">
  3. <div class="header">
  4. <van-nav-bar class="navBar" title="门店拜访" left-arrow @click-left="onClickLeft" />
  5. </div>
  6. <div class="tabBox">
  7. <van-tabs class="myTab" v-model="activeTabName" color="#0057ba" @change="tabChange">
  8. <van-tab
  9. v-for="(item, index) in tabsItem"
  10. :title="item.title"
  11. :name="item.name"
  12. :key="index"></van-tab>
  13. </van-tabs>
  14. <van-tabs
  15. class="myTab"
  16. v-model="activaPantoneName"
  17. color="#0057ba"
  18. @change="tabChangePantone"
  19. v-if="activeTabName == 'pantone'">
  20. <van-tab
  21. v-for="(val, key, index) in tabsItemPantone"
  22. :key="index"
  23. :title="key"
  24. :name="key"></van-tab>
  25. </van-tabs>
  26. </div>
  27. <div class="content">
  28. <el-table
  29. v-if="fromType"
  30. :data="tableList"
  31. :load="load"
  32. :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
  33. border
  34. class="elTreeTable"
  35. lazy
  36. :row-key="rowKey"
  37. :key="toggleIndex">
  38. <el-table-column
  39. class="firstName"
  40. :label="firstLabel"
  41. :prop="firstProp"
  42. align="center"
  43. width="120">
  44. <template slot-scope="scope">
  45. <span>{{ scope.row[firstProp] }}</span>
  46. <!-- <span v-if="scope.row.reportType != 1">{{ scope.row.deptName }}</span> -->
  47. </template>
  48. </el-table-column>
  49. <el-table-column
  50. :label="item.label"
  51. width="46"
  52. align="center"
  53. v-for="(item, index) in tableColumn"
  54. :key="index"
  55. v-if="tableColumn.length">
  56. <el-table-column
  57. :label="val.label"
  58. :prop="val.prop"
  59. width="46"
  60. align="center"
  61. v-if="item.childredColumn"
  62. v-for="(val, ind) in item.childredColumn"
  63. :key="ind">
  64. </el-table-column>
  65. </el-table-column>
  66. </el-table>
  67. <div class="mask" v-if="maskShow"><van-loading type="spinner" color="#1989fa" /></div>
  68. </div>
  69. </div>
  70. </template>
  71. <script>
  72. import {
  73. selectNoVisitsInfo,
  74. selectPendingCasesInfo,
  75. getReportMaterialType,
  76. getReportMaterial,
  77. } from '@/api/index';
  78. import { mapState } from 'vuex';
  79. export default {
  80. name: 'hintDetail',
  81. computed: {
  82. ...mapState({
  83. userInfo: (state) => state.user.userInfo,
  84. }),
  85. },
  86. data() {
  87. return {
  88. empLevel: '',
  89. deptId: null,
  90. fromType: null,
  91. activeTabName: 'noVisit',
  92. activaPantoneName: '',
  93. tabsItem: [
  94. {
  95. title: '未拜访',
  96. name: 'noVisit',
  97. },
  98. {
  99. title: '建店',
  100. name: 'createStore',
  101. },
  102. // {
  103. // title: '色卡',
  104. // name: 'pantone',
  105. // },
  106. ],
  107. activePantoneTabName: '', //色卡tabName
  108. tabsItemPantone: {}, //色卡tabItem
  109. toggleIndex: 0,
  110. firstLabel: '',
  111. firstProp: '',
  112. tableColumn: [],
  113. tableList: [],
  114. // 未拜访
  115. noVisit: [
  116. {
  117. label: '可控店',
  118. childredColumn: [
  119. {
  120. label: '(当月)',
  121. prop: 'keKongNotVisited',
  122. },
  123. ],
  124. },
  125. {
  126. label: '金牌店',
  127. childredColumn: [
  128. {
  129. label: '(当月)',
  130. prop: 'jinPaiNotVisited',
  131. },
  132. ],
  133. },
  134. {
  135. label: '同A店',
  136. childredColumn: [
  137. {
  138. label: '(近2月)',
  139. prop: 'tongANotVisited',
  140. },
  141. ],
  142. },
  143. {
  144. label: '同B店',
  145. childredColumn: [
  146. {
  147. label: '(近3月)',
  148. prop: 'tongBNotVisited',
  149. },
  150. ],
  151. },
  152. ],
  153. // 建店
  154. createStore: [
  155. {
  156. label: '可控店',
  157. childredColumn: [
  158. {
  159. label: '(45天未结案)',
  160. prop: 'keKongAbnormalNum',
  161. },
  162. ],
  163. },
  164. {
  165. label: '金牌店',
  166. childredColumn: [
  167. {
  168. label: '(7天未完工)',
  169. prop: 'jinPaiUnfinishedNum',
  170. },
  171. {
  172. label: '(30天未结案)',
  173. prop: 'jinPaiAbnormalNum',
  174. },
  175. ],
  176. },
  177. {
  178. label: '同A店',
  179. childredColumn: [
  180. {
  181. label: '(30天未结案)',
  182. prop: 'tongAAbnormalNum',
  183. },
  184. ],
  185. },
  186. {
  187. label: '同B店',
  188. childredColumn: [
  189. {
  190. label: '(30天未结案)',
  191. prop: 'tongBAbnormalNum',
  192. },
  193. ],
  194. },
  195. ],
  196. // 色卡
  197. pantone: [
  198. {
  199. label: '直发销售部',
  200. childredColumn: [
  201. {
  202. label: '(本)',
  203. prop: 'zfxsbNum',
  204. },
  205. ],
  206. },
  207. {
  208. label: '已领用',
  209. childredColumn: [
  210. {
  211. label: '(本)',
  212. prop: 'ywyylyNum',
  213. },
  214. ],
  215. },
  216. {
  217. label: '门店发放',
  218. childredColumn: [
  219. {
  220. label: '(本)',
  221. prop: 'ywyyffNum',
  222. },
  223. ],
  224. },
  225. {
  226. label: '门店未签收',
  227. childredColumn: [
  228. {
  229. label: '(本)',
  230. prop: 'mdwqsNum',
  231. },
  232. ],
  233. },
  234. {
  235. label: '未签收门店',
  236. childredColumn: [
  237. {
  238. label: '(家)',
  239. prop: 'wqsmdNum',
  240. },
  241. ],
  242. },
  243. ],
  244. materialCode: null, //色卡物料来源
  245. maskShow: true,
  246. };
  247. },
  248. watch: {
  249. // 监听tab切换的状态
  250. fromType: {
  251. handler(newVal) {
  252. this.tableColumn = this[newVal]; //表格头
  253. this.activeTabName = newVal; // 当前激活tab
  254. },
  255. immediate: true,
  256. },
  257. // 初始化监听fromType,不同类型显示不同的tabItem
  258. '$route.query.fromType': {
  259. handler(newVal) {
  260. if (newVal) this.setTabsItem();
  261. },
  262. immediate: true,
  263. },
  264. },
  265. activated() {
  266. this.empLevel = this.userInfo.empLevel;
  267. this.firstLabel = this.empLevel == '1' ? '组织名称/大区主管' : '组织名称/销售部主管';
  268. this.fromType = this.$route.query.fromType; // fromType: 'noVisit':未拜访; 'createStore':建店; 'pantone':色卡
  269. this.deptId = this.userInfo.deptId; // 当前用户部门id
  270. this.activaPantoneName = this.$route.query.pantoneName; //当前色卡
  271. this.materialCode = this.$route.query.materialCode; // 色卡code
  272. this.initData();
  273. },
  274. methods: {
  275. rowKey(row) {
  276. return this.fromType == 'pantone' ? row['id'] : row['onlyId'];
  277. },
  278. setTabsItem() {
  279. this.tabsItem = [
  280. {
  281. title: '未拜访',
  282. name: 'noVisit',
  283. },
  284. {
  285. title: '建店',
  286. name: 'createStore',
  287. },
  288. ];
  289. // 2销售部主管显示色卡
  290. if (this.userInfo.empLevel == '2') {
  291. this.tabsItem.push({
  292. title: '色卡',
  293. name: 'pantone',
  294. });
  295. }
  296. },
  297. /**
  298. * 初始化数据和搜索操作接口的入口
  299. * @param {*function} resolve //子级数据数据回调
  300. * @param {*object} tree //展开时当前节点数据
  301. * */
  302. initData(resolve, tree) {
  303. // 请求子级数据时不需要loading
  304. if (!resolve && !tree) {
  305. this.toggleIndex = this.toggleIndex++;
  306. this.maskShow = true;
  307. }
  308. if (this.fromType == 'noVisit') {
  309. // 未拜访
  310. this.deptId = tree ? tree.onlyId : this.userInfo.deptId;
  311. this.firstProp = 'onlyName';
  312. this.selectNoVisitsInfoFun(resolve);
  313. } else if (this.fromType == 'createStore') {
  314. // 建店
  315. this.deptId = tree ? tree.onlyId : this.userInfo.deptId;
  316. this.firstProp = 'onlyName';
  317. this.selectPendingCasesInfoFun(resolve);
  318. } else if (this.fromType == 'pantone') {
  319. // 色卡
  320. this.firstProp = 'warehouseName';
  321. let empLevel = tree ? tree.empLevel : null;
  322. this.getPantoneData(resolve, empLevel);
  323. }
  324. },
  325. tabChange(val) {
  326. this.tableList = []; // 清楚tab数
  327. this.tabsItemPantone = {}; // 清楚色卡tab数据
  328. this.fromType = val;
  329. this.initData();
  330. },
  331. tabChangePantone(val) {
  332. this.tableList = [];
  333. this.materialCode = this.tabsItemPantone[val].materialCode;
  334. this.initData();
  335. },
  336. onClickLeft() {
  337. this.$router.go(-1);
  338. },
  339. linKReportHistory(row, type) {},
  340. // 加载子节点数据的函数
  341. load(tree, treeNode, resolve) {
  342. this.initData(resolve, tree);
  343. },
  344. // 未拜访
  345. selectNoVisitsInfoFun(resolve) {
  346. selectNoVisitsInfo({ deptId: this.deptId }).then((res) => {
  347. if (res.code == 200) {
  348. res.data.forEach((val) => {
  349. if (val.empLevel < 3) val.hasChildren = true;
  350. });
  351. // 是否是子级
  352. if (resolve) {
  353. resolve && resolve(res.data);
  354. } else {
  355. this.maskShow = false;
  356. this.tableList = res.data;
  357. }
  358. } else {
  359. this.maskShow = false;
  360. this.Toast({
  361. message: res.msg,
  362. duration: 5000,
  363. });
  364. }
  365. });
  366. },
  367. // 建店
  368. selectPendingCasesInfoFun(resolve) {
  369. selectPendingCasesInfo({ deptId: this.deptId }).then((res) => {
  370. if (res.code == 200) {
  371. res.data.forEach((val) => {
  372. if (val.empLevel < 3) val.hasChildren = true;
  373. });
  374. // 是否是子级
  375. if (resolve) {
  376. resolve && resolve(res.data);
  377. } else {
  378. this.maskShow = false;
  379. this.tableList = res.data;
  380. }
  381. } else {
  382. this.maskShow = false;
  383. this.Toast({
  384. message: res.msg,
  385. duration: 5000,
  386. });
  387. }
  388. });
  389. },
  390. // 色卡tab
  391. getPantoneData(resolve, empLevel) {
  392. if (JSON.stringify(this.tabsItemPantone) != '{}') {
  393. // this.tabsItemPantone != {} 不是初次获取tab数据不需要在赋值
  394. this.getReportMaterialTypeFun(resolve, empLevel);
  395. } else {
  396. getReportMaterial().then((res) => {
  397. this.tabsItemPantone = res.data;
  398. delete this.tabsItemPantone.tip;
  399. // 初次获取tab数据延迟等待this.activaPantoneName当前激活tab赋值成功,获取其物料code
  400. this.$nextTick(() => {
  401. this.materialCode = this.materialCode
  402. ? this.materialCode
  403. : this.tabsItemPantone[this.activaPantoneName].materialCode;
  404. this.getReportMaterialTypeFun(null, null);
  405. });
  406. });
  407. }
  408. },
  409. // 色卡详情
  410. getReportMaterialTypeFun(resolve, empLevel) {
  411. // empLevel 第一次传 null
  412. getReportMaterialType({ materialCode: this.materialCode, empLevel: empLevel }).then((res) => {
  413. if (res.code == 200) {
  414. res.data.colorCardList.forEach((val) => {
  415. if (val.empLevel < 3) val.hasChildren = true;
  416. });
  417. // 是否是子级
  418. if (resolve) {
  419. resolve && resolve(res.data.colorCardList);
  420. } else {
  421. this.maskShow = false;
  422. this.tableList = res.data.colorCardList;
  423. }
  424. } else {
  425. this.maskShow = false;
  426. this.Toast({
  427. message: res.msg,
  428. duration: 5000,
  429. });
  430. }
  431. });
  432. },
  433. },
  434. };
  435. </script>
  436. <style lang="scss" scoped>
  437. .hintDetail {
  438. .tabBox {
  439. position: sticky;
  440. top: 0px;
  441. z-index: 10;
  442. }
  443. }
  444. </style>
  445. <style lang="scss">
  446. #app {
  447. width: 100%;
  448. height: 100%;
  449. .bgcolor {
  450. width: 100%;
  451. height: 100%;
  452. .hintDetail {
  453. width: 100%;
  454. height: 100%;
  455. display: flex;
  456. flex-direction: column;
  457. .content {
  458. flex: 1;
  459. overflow: hidden;
  460. padding-bottom: 20px;
  461. background: #fff;
  462. position: relative;
  463. .el-table {
  464. overflow: hidden;
  465. height: 100%;
  466. display: flex;
  467. flex-direction: column;
  468. .el-table__body-wrapper {
  469. overflow: auto;
  470. flex: 1;
  471. }
  472. }
  473. .mask {
  474. position: absolute;
  475. width: 100%;
  476. height: 100%;
  477. top: 0;
  478. background: rgba(255, 255, 255, 0.8);
  479. display: flex;
  480. justify-content: center;
  481. align-items: center;
  482. }
  483. }
  484. }
  485. }
  486. }
  487. .hintDetail {
  488. .el-table__head .el-table__body {
  489. overflow: hidden;
  490. width: 99.9% !important;
  491. }
  492. .elTreeTable table {
  493. width: 99.9% !important;
  494. }
  495. .el-table__body {
  496. width: 99.9% !important;
  497. }
  498. .el-table__empty-block {
  499. width: 99.9% !important;
  500. }
  501. .elTreeTable .el-table__cell:first-child .cell {
  502. padding-left: 2px !important;
  503. }
  504. .elTreeTable .el-table__cell {
  505. padding: 0px;
  506. }
  507. .elTreeTable .el-table__body td.el-table__cell {
  508. padding: 2px;
  509. }
  510. .elTreeTable table col {
  511. text-align: center;
  512. }
  513. .elTreeTable th.el-table__cell > .cell {
  514. padding: 1px !important;
  515. }
  516. .elTreeTable {
  517. font-size: 12px !important;
  518. }
  519. .elTreeTable th.el-table__cell {
  520. padding: 1px !important;
  521. }
  522. .elTreeTable th.el-table__cell > .cell {
  523. text-align: center;
  524. }
  525. .elTreeTable .el-table__header tr:first-child th.el-table__cell:first-child .cell {
  526. /* width: 98px; */
  527. }
  528. .elTreeTable .linkSpan {
  529. text-decoration: underline;
  530. color: #0057ba;
  531. display: block;
  532. text-align: right;
  533. padding: 6px 10px;
  534. }
  535. .elTreeTable td.el-table__cell div {
  536. padding: 0px;
  537. }
  538. .elTreeTable .cell .spanNum {
  539. display: block;
  540. text-align: right;
  541. padding: 6px 10px;
  542. }
  543. .elTreeTable .el-table__expand-icon {
  544. float: right;
  545. .el-icon-arrow-right {
  546. vertical-align: -2px;
  547. }
  548. }
  549. }
  550. </style>