managerStatisticsV2.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <template>
  2. <div class="manager_statistics_box boxMinHeight">
  3. <el-tabs v-model="currentTag">
  4. <el-tab-pane v-for="(item,index) in tabs" :key="index" :label="item.label" :name="item.name" :disabled="loading"></el-tab-pane>
  5. </el-tabs>
  6. <el-container>
  7. <el-header height="100px">
  8. <!-- 搜索 -->
  9. <el-form :model="formData" :inline="true" >
  10. <el-form-item label="部门">
  11. <el-cascader
  12. v-model="dept_name_xq_xq"
  13. :options="deptTrees"
  14. @change="getLastDeptNull"
  15. ref="dept"
  16. filterable
  17. change-on-select
  18. placeholder="全公司"
  19. clearable
  20. ></el-cascader>
  21. </el-form-item>
  22. <!-- 关键字 -->
  23. <el-form-item class="persons_names">
  24. <el-input v-model="formData.keyword" :clearable="true" placeholder="搜索姓名" max="200" class="persons_name" @clear="keywordSearch" >
  25. <el-button slot="append" icon="el-icon-search" @click="keywordSearch"></el-button>
  26. </el-input>
  27. </el-form-item>
  28. <!-- 月份搜索 -->
  29. <el-form-item label="月份" v-if="currentTag === 'target'">
  30. <el-date-picker
  31. class="date-picker-width"
  32. v-model="formData.month"
  33. clearable
  34. width="100%"
  35. type="month"
  36. :clearable="false"
  37. placeholder="请选择月份"
  38. value-format="yyyy-MM"
  39. />
  40. </el-form-item>
  41. <!-- 时间区间搜索 -->
  42. <el-form-item label="时间区间" v-if="currentTag === 'search'">
  43. <el-date-picker
  44. v-model="timeScope"
  45. type="daterange"
  46. align="right"
  47. unlink-panels
  48. range-separator="至"
  49. start-placeholder="开始日期"
  50. end-placeholder="结束日期"
  51. value-format="yyyy-MM-dd"
  52. editable
  53. :clearable="false"
  54. />
  55. </el-form-item>
  56. <!-- 达标选项 -->
  57. <el-form-item v-if="currentTag === 'target'" label="只看全部达标的" >
  58. <el-checkbox v-model="formData.complete" size="medium" />
  59. </el-form-item>
  60. <el-form-item>
  61. <div class="flex-box">
  62. <downloadexcel
  63. v-if="currentTag === 'target' ? (target.total > 0) : (search.total > 0)"
  64. :fetch="getDownloadData"
  65. name="管理者奖扣列表.xls"
  66. :fields="downloadFields"
  67. >
  68. <el-button type="primary" plain size="medium" style="margin-right: 10px;">导出报表</el-button>
  69. </downloadexcel>
  70. <span class="blue cursor" style="padding-left: 20px;font-size: 14px;" @click="$openUrl(18)">什么是每月奖扣目标,如何使用?</span>
  71. </div>
  72. </el-form-item>
  73. </el-form>
  74. </el-header>
  75. <el-main v-if="currentTag === 'target'">
  76. <el-table :data="target.list" style="width: 100%" v-loading="loading" @row-click="openDetailTarget">
  77. <el-table-column label="管理者">
  78. <template slot-scope="scope">
  79. <userImage class="fl" :id="scope.row.id" :user_name="scope.row.name" :img_url="scope.row.img_url" width="50px" height="50px" />
  80. <span style="margin-left: 10px; line-height: 50px; display: inline-block;">{{scope.row.name}}</span>
  81. </template>
  82. </el-table-column>
  83. <el-table-column label="奖分">
  84. <template slot-scope="scope">
  85. <b>{{scope.row.reward.point}}</b>
  86. <span :class="scope.row.reward.status === 1 ? 'color_green' : ''">{{scope.row.reward.status === 1 ? '达标' : ''}}</span>
  87. <br/>
  88. <span class="span_h">奖分目标 {{scope.row.reward.target}}</span>
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="扣分">
  92. <template slot-scope="scope">
  93. <b>{{scope.row.deduction.point}}</b>
  94. <span :class="scope.row.deduction.status === 1 ? 'color_green' : ''">{{scope.row.deduction.status === 1 ? '达标' : ''}}</span>
  95. <br/>
  96. <span class="span_h">扣分目标 {{scope.row.deduction.target}}</span>
  97. </template>
  98. </el-table-column>
  99. <el-table-column label="奖扣比例">
  100. <template slot-scope="scope">
  101. <div v-if="scope.row.ratio.enable === 1">
  102. <b>{{scope.row.ratio.reward_ratio}} : 1</b>
  103. <span :class="scope.row.ratio.status === 1 ? 'color_green' : ''">{{scope.row.ratio.status === 1 ? '达标' : ''}}</span>
  104. <br/>
  105. <span class="span_h">
  106. 比例目标 小于 {{scope.row.ratio.target}}
  107. <b>:</b>
  108. 1
  109. </span>
  110. </div>
  111. <div v-else style="padding-left:21px">—</div>
  112. </template>
  113. </el-table-column>
  114. <el-table-column label="奖扣人次" >
  115. <template slot-scope="scope">
  116. <b>{{ scope.row.exec.count }}&nbsp;</b>
  117. <span :class="scope.row.exec.status === 1 ? 'color_green' : ''">{{ scope.row.exec.status === 1 ? '达标' : '' }}</span>
  118. <br />
  119. <span class="span_h">人次目标 {{ scope.row.exec.target }}人次</span>
  120. </template>
  121. </el-table-column>
  122. </el-table>
  123. <center style="padding: 20px 0;">
  124. <el-pagination
  125. background
  126. @size-change="handleTargetSizeChange"
  127. @current-change="handleTargetPageChange"
  128. :current-page="target.page"
  129. layout="total, sizes, prev, pager, next"
  130. :page-size="target.pageSize"
  131. :page-sizes="[10, 20, 50, 100]"
  132. :total="target.total"
  133. />
  134. </center>
  135. </el-main>
  136. <el-main v-if="currentTag === 'search'">
  137. <el-table :data="search.list" style="width: 100%" v-loading="loading" @row-click="openDetailSearch">
  138. <el-table-column label="管理者">
  139. <template slot-scope="scope">
  140. <userImage class="fl" :id="scope.row.id" :user_name="scope.row.name" :img_url="scope.row.img_url" width="50px" height="50px" />
  141. <span style="margin-left: 10px; line-height: 50px; display: inline-block;">{{scope.row.name}}</span>
  142. </template>
  143. </el-table-column>
  144. <el-table-column label="奖分" prop="reward_point" />
  145. <el-table-column label="扣分" prop="deduction_point"/>
  146. <el-table-column label="奖扣比例" prop="ratio" :formatter="ratioFormatter"/>
  147. <el-table-column label="奖扣人次" prop="exec" />
  148. </el-table>
  149. <center style="padding: 20px 0;">
  150. <el-pagination
  151. background
  152. @size-change="handleSearchSizeChange"
  153. @current-change="handleSearchPageChange"
  154. :current-page="search.page"
  155. layout="total, sizes, prev, pager, next"
  156. :page-size="search.pageSize"
  157. :page-sizes="[10, 20, 50, 100]"
  158. :total="search.total"
  159. />
  160. </center>
  161. </el-main>
  162. </el-container>
  163. </div>
  164. </template>
  165. <script>
  166. import Template from "../../../examine/components/Template.vue";
  167. import downloadexcel from "vue-json-excel";
  168. export default {
  169. name:'manager_statistics_v2',
  170. components: {Template,downloadexcel},
  171. data(){
  172. let startDate = new Date();
  173. startDate.setTime(startDate.getTime() - 3600 * 1000 * 24 * 7);
  174. startDate = this.$moment(startDate).format('YYYY-MM-DD');
  175. let endDate = this.$moment().format('YYYY-MM-DD');
  176. return {
  177. tabs:[
  178. {label:'奖扣目标',name:'target'},
  179. {label: '奖扣查询',name: 'search'}
  180. ],
  181. currentTag:'target',
  182. loading:false,
  183. deptTrees: [],
  184. formData:{
  185. month: this.$moment().format('YYYY-MM'),
  186. startDate: startDate,
  187. endDate: endDate,
  188. deptId: 0,
  189. keyword: '',
  190. complete: false
  191. },
  192. timeScope:[
  193. startDate,
  194. endDate
  195. ],
  196. dept_name_xq_xq: '',
  197. target:{
  198. list:[],
  199. total:0,
  200. page:1,
  201. pageSize:10
  202. },
  203. search:{
  204. list:[],
  205. total:0,
  206. page:1,
  207. pageSize:10
  208. },
  209. downloadTargetFields:{
  210. '姓名':'name',
  211. '部门':'dept',
  212. '实际奖分':'rewardPoint',
  213. '奖分目标':'rewardTarget',
  214. '实际扣分':'deductionPoint',
  215. '扣分目标':'deductionTarget',
  216. '实际奖扣比例':'ratio',
  217. '比例目标':'ratioTarget',
  218. '实际奖扣人次':'exec',
  219. '人次目标':'execTarget',
  220. '月份':'timeScope',
  221. },
  222. downloadSearchFields:{
  223. '姓名':'name',
  224. '部门':'dept',
  225. '奖分':'rewardPoint',
  226. '扣分':'deductionPoint',
  227. '奖扣比例':'ratio',
  228. '奖扣人次':'exec',
  229. '周期':'timeScope',
  230. },
  231. downloadData:[]
  232. }
  233. },
  234. created() {
  235. this.currentTag = this.$route.query.tag || 'target';
  236. if (['target','search'].indexOf(this.currentTag) < 0) this.currentTag = 'target';
  237. },
  238. computed:{
  239. downloadFields: function (){
  240. return this.currentTag === 'target' ? this.downloadTargetFields : this.downloadSearchFields;
  241. }
  242. },
  243. mounted() {
  244. if (this.$getCache('dept_tree')) {
  245. this.deptTrees = this.getTreeData(this.$getCache('dept_tree'));
  246. }
  247. this.getList();
  248. },
  249. watch:{
  250. 'formData.month'(val,oVal){
  251. if (val === oVal) return;
  252. this.target.page = 1;
  253. this.search.page = 1;
  254. this.getList();
  255. },
  256. 'formData.startDate'(val,oVal){
  257. if (val === oVal) return;
  258. this.target.page = 1;
  259. this.search.page = 1;
  260. this.getList();
  261. },
  262. 'formData.endDate'(val,oVal){
  263. if (val === oVal) return;
  264. this.target.page = 1;
  265. this.search.page = 1;
  266. this.getList();
  267. },
  268. 'formData.deptId'(val,oVal){
  269. if (val === oVal) return;
  270. this.target.page = 1;
  271. this.search.page = 1;
  272. this.getList();
  273. },
  274. 'formData.complete'(val,oVal){
  275. if (val === oVal) return;
  276. this.target.page = 1;
  277. this.search.page = 1;
  278. this.getList();
  279. },
  280. 'target.page'(val,oVal){
  281. if (val === oVal) return;
  282. this.getList();
  283. },
  284. 'target.pageSize'(val,oVal){
  285. if (val === oVal) return;
  286. this.getList();
  287. },
  288. 'search.page'(val,oVal){
  289. if (val === oVal) return;
  290. this.getList();
  291. },
  292. 'search.pageSize'(val,oVal){
  293. if (val === oVal) return;
  294. this.getList();
  295. },
  296. currentTag(val,oVal){
  297. if (val === oVal) return;
  298. this.getList();
  299. // this.$router.push({path: '/manager_statistics',query:{tag:val}})
  300. },
  301. timeScope(val,oVal){
  302. this.formData.startDate = val[0];
  303. this.formData.endDate = val[1];
  304. }
  305. },
  306. methods: {
  307. //部门
  308. getLastDeptNull(val) {
  309. if (val.length == 0) {
  310. this.formData.deptId = 0;
  311. } else {
  312. this.formData.deptId = val[val.length-1];
  313. }
  314. this.$nextTick(() => {
  315. this.$refs.dept.dropDownVisible = false; //监听值发生变化就关闭它
  316. });
  317. },
  318. // 递归判断列表,把最后的children设为undefined
  319. getTreeData(data) {
  320. for (var i = 0; i < data.length; i++) {
  321. if (data[i].children.length < 1) {
  322. // children若为空数组,则将children设为undefined
  323. data[i].children = undefined;
  324. } else {
  325. // children若不为空数组,则继续 递归调用 本方法
  326. this.getTreeData(data[i].children);
  327. }
  328. }
  329. return data;
  330. },
  331. getList(){
  332. if (this.currentTag === 'target'){
  333. this.getTargetList();
  334. }else {
  335. this.getSearchList();
  336. }
  337. },
  338. parseDownloadDataTarget(data){
  339. return {
  340. name:data.name,
  341. dept:data.dept,
  342. rewardPoint:data.reward.point,
  343. rewardTarget:data.reward.target,
  344. deductionPoint:data.deduction.point,
  345. deductionTarget:data.deduction.target,
  346. ratio:data.ratio.enable === 1 ? data.ratio.reward_ratio + '比1' : '-',
  347. ratioTarget:data.ratio.target+'比1',
  348. exec:data.exec.count,
  349. execTarget:data.exec.target,
  350. }
  351. },
  352. parseDownloadDataSearch(data){
  353. return {
  354. name:data.name,
  355. dept:data.dept,
  356. rewardPoint:data.reward_point,
  357. deductionPoint:data.deduction_point,
  358. ratio:data.ratio,
  359. exec:data.exec,
  360. }
  361. },
  362. getTargetList(){
  363. let msg = {
  364. type:'es',
  365. employee_id:this.$userInfo().id,
  366. page:this.target.page,
  367. page_size:this.target.pageSize,
  368. month:this.formData.month,
  369. dept_id:this.formData.deptId,
  370. complete:this.formData.complete ? 1 : 0,
  371. keyword:this.formData.keyword
  372. }
  373. let self = this;
  374. self.loading = true;
  375. //清空导出数据
  376. self.downloadData = [];
  377. this.$socketApiTow.sendData(msg,(res) => {
  378. if (res.type !== msg.type || res.code !== 1) return;
  379. self.target.list = res.result.list;
  380. self.target.total = res.result.total;
  381. //刷新导出数据
  382. if (msg.page === 0){
  383. self.downloadData = self.target.list.map((item) => {
  384. let i = self.parseDownloadDataTarget(item);
  385. i.timeScope = msg.month
  386. return i;
  387. });
  388. self.loading = false;
  389. }else {
  390. msg.page = 0;
  391. self.$socketApiTow.sendData(msg,(res) => {
  392. if (res.type !== msg.type || res.code !== 1) return;
  393. self.downloadData = res.result.list.map((item) => {
  394. let i = self.parseDownloadDataTarget(item);
  395. i.timeScope = msg.month
  396. return i;
  397. });
  398. self.loading = false;
  399. })
  400. }
  401. })
  402. },
  403. getSearchList(){
  404. let msg = {
  405. type:'ess',
  406. employee_id:this.$userInfo().id,
  407. start_date:this.formData.startDate,
  408. end_date:this.formData.endDate,
  409. dept_id:this.formData.deptId,
  410. keyword:this.formData.keyword,
  411. page:this.search.page,
  412. page_size:this.search.pageSize
  413. }
  414. let self = this;
  415. self.loading = true;
  416. //清空导出数据
  417. self.downloadData = [];
  418. this.$socketApiTow.sendData(msg,(res)=>{
  419. if (res.type !== msg.type || res.code !== 1) return;
  420. self.search.list = res.result.list;
  421. self.search.total = res.result.total;
  422. //刷新导出数据
  423. if (msg.page === 0){
  424. self.downloadData = self.search.list.map((item) => {
  425. let i = self.parseDownloadDataSearch(item);
  426. i.timeScope = msg.start_date + "至" + msg.end_date;
  427. return i;
  428. });
  429. self.loading = false;
  430. }else {
  431. msg.page = 0;
  432. self.$socketApiTow.sendData(msg,(res) => {
  433. if (res.type !== msg.type || res.code !== 1) return;
  434. self.downloadData = res.result.list.map((item) => {
  435. let i = self.parseDownloadDataSearch(item);
  436. i.timeScope = msg.start_date + "至" + msg.end_date;
  437. return i;
  438. });
  439. self.loading = false;
  440. })
  441. }
  442. })
  443. },
  444. handleTargetSizeChange(val){
  445. this.target.pageSize = val;
  446. },
  447. handleTargetPageChange(val){
  448. this.target.page = val;
  449. },
  450. handleSearchSizeChange(val){
  451. this.search.pageSize = val;
  452. },
  453. handleSearchPageChange(val){
  454. this.search.page = val;
  455. },
  456. keywordSearch(){
  457. this.target.page = 1;
  458. this.search.page = 1;
  459. this.getList();
  460. },
  461. getDownloadData(){
  462. return this.downloadData;
  463. },
  464. openDetailTarget(e){
  465. this.openDetail({
  466. date:this.formData.month,
  467. id:e.id,
  468. name:e.name,
  469. source:'target',
  470. });
  471. },
  472. openDetailSearch(e){
  473. this.openDetail({
  474. startDate:this.formData.startDate,
  475. endDate:this.formData.endDate,
  476. id:e.id,
  477. name:e.name,
  478. source:'search',
  479. });
  480. },
  481. openDetail(data){
  482. // this.$router.push({path:'/integral_event_two',query:{data:JSON.stringify(data)}})
  483. this.$router.replace({path:'/integral_event_two',query:{data:JSON.stringify(data)}});
  484. },
  485. ratioFormatter(row, column, cellValue, index){
  486. return cellValue ? cellValue : '--';
  487. },
  488. }
  489. }
  490. </script>
  491. <style scoped lang="scss">
  492. .search_box {
  493. /deep/ button:active {
  494. background: #409EFF;
  495. }
  496. /deep/ button:active .el-icon-search {
  497. color: #fff;
  498. }
  499. }
  500. .date-picker-width {
  501. width: 100% !important;
  502. }
  503. .color_green {
  504. color: #67c23a;
  505. }
  506. .nopoint_box {
  507. display: inline-block;
  508. text-align: center;
  509. width: 100%;
  510. margin-bottom: 10px;
  511. }
  512. .title {
  513. display: block;
  514. text-align: center;
  515. font-size: 12px !important;
  516. line-height: 30px;
  517. color: #909399 !important;
  518. padding: 0;
  519. }
  520. .nopoint_box a {
  521. color: #409EFF;
  522. }
  523. .chart_content {
  524. height: 90vh;
  525. overflow-y: auto;
  526. overflow-x: hidden;
  527. .chart-legend__wrap {
  528. text-align: right;
  529. padding: 20px;
  530. padding-right: 50px;
  531. & .chart-legend__pink {
  532. position: relative;
  533. padding-left: 12px;
  534. padding-right: 5px;
  535. &:after {
  536. content: '';
  537. position: absolute;
  538. margin-top: -2px;
  539. top: 35%;
  540. left: 0;
  541. width: 8px;
  542. height: 8px;
  543. background: #f56c6c;
  544. border-radius: 100%;
  545. }
  546. }
  547. & .chart-legend__green {
  548. position: relative;
  549. padding-left: 12px;
  550. &:after {
  551. content: '';
  552. position: absolute;
  553. margin-top: -2px;
  554. top: 35%;
  555. left: 0;
  556. width: 8px;
  557. height: 8px;
  558. background: #53b87f;
  559. border-radius: 100%;
  560. }
  561. }
  562. }
  563. }
  564. // 滚动条样式
  565. .chart_content::-webkit-scrollbar-track {
  566. -webkit-box-shadow: inset 0 0 5px rgb(255, 255, 255);
  567. border-radius: 5px;
  568. background-color: rgb(255, 255, 255);
  569. }
  570. .chart_content::-webkit-scrollbar {
  571. width: 5px;
  572. background-color: rgba(201, 201, 201, 0);
  573. }
  574. .chart_content::-webkit-scrollbar-thumb {
  575. border-radius: 5px;
  576. -webkit-box-shadow: inset 0 0 5px rgb(153, 145, 145) (160, 154, 154);
  577. background-color: rgb(168, 167, 167);
  578. }
  579. .dataItem {
  580. text-align: center;
  581. .point {
  582. font-size: 22px;
  583. color: #409EFF;
  584. margin: 10px 0;
  585. }
  586. .target {
  587. font-size: 12px;
  588. color: #909399;
  589. }
  590. }
  591. .drawer_title {
  592. font-size: 18px;
  593. padding: 20px;
  594. }
  595. .manager_statistics_box {
  596. background-color: #ffffff;
  597. padding: 20px;
  598. /deep/ .el-row .el-checkbox .el-checkbox__label {
  599. line-height: 20px;
  600. }
  601. }
  602. .tips {
  603. background: #409EFF;
  604. border-radius: 50%;
  605. width: 14px;
  606. height: 14px;
  607. color: #fff;
  608. display: inline-block;
  609. font-size: 12px;
  610. line-height: 14px;
  611. text-align: center;
  612. }
  613. .el-form-item__label {
  614. width: 0px !important;
  615. }
  616. // .persons_names{
  617. // margin-left: 160px;
  618. // }
  619. .wlj {
  620. & .color_green {
  621. color: #49d3a7;
  622. }
  623. & .color_red {
  624. color: #f04b56;
  625. }
  626. }
  627. b {
  628. font-size: 14px;
  629. }
  630. .span_h {
  631. font-size: 13px;
  632. color: #898c94;
  633. }
  634. /deep/.el-table tbody tr{
  635. cursor: pointer;
  636. }
  637. </style>