quotationAnalysis.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <div class="div-box-new-margin" >
  3. <div class="div-border-box">
  4. <div class="div-line"></div>
  5. <div style="line-height: 22px;height: 22px;vertical-align: auto;margin-left: 16px">{{$t(`报价分析`)}}</div>
  6. <div class="container-div">
  7. <boxLine title="报价总次数" :data="totalqty" content="统计到当前查询时间为止的报价总次数(审核状态)" :windowWidth="windowWidth"></boxLine>
  8. <boxLine title="客户报价次数" :data="cusqty" content="统计到当前查询时间为止的客户报价总次数(审核状态)" :windowWidth="windowWidth"></boxLine>
  9. <boxLine title="项目报价次数" :data="proqty" content="统计到当前查询时间为止的项目报价总次数(审核状态)" :windowWidth="windowWidth"></boxLine>
  10. <boxLine title="报价总金额" :data="totalamount" content="统计到当前查询时间为止的报价总金额(审核状态)" :windowWidth="windowWidth"></boxLine>
  11. <boxLine title="客户报价金额" :data="cusamount" content="统计到当前查询时间为止的客户报价金额(审核状态)" :windowWidth="windowWidth"></boxLine>
  12. <boxLine title="项目报价金额" :data="proamount" content="统计到当前查询时间为止的项目报价金额(审核状态)" :windowWidth="windowWidth"></boxLine>
  13. </div>
  14. <div :style="{padding:padding,height: '451px',marginTop:'10px',background:'#fff'}" id="quotationAnalysisFull">
  15. <div class="out">
  16. <div class="mt-10" style="min-width: 220px;">{{$t(`近12月报价次数趋势分析`)}}</div>
  17. <div class="in">
  18. <div class="inline-16 mt-10">
  19. <departmentSalesperson ref="departmentSalesperson" class="inline-16" @depSelect="depSelect" @personSelect="personSelect" :isFull="isFull" :isNewDep="true"></departmentSalesperson>
  20. </div>
  21. <div class="mt-10 inline-16">
  22. <p class="search__label">{{$t('状态')}}:</p>
  23. <el-select v-model="plotParam.content.where.isleave" clearable style="margin-right:10px" size="small" :placeholder="$t('请选择状态')" @change="listData(plotParam.content.dataid,plotParam.content.where.isleave,'状态');queryQuotationModel(plotParam.content.dataid,plotParam.content.where.isleave,'状态')" >
  24. <el-option :label="$t('在职')" value="1"></el-option>
  25. <el-option :label="$t('离职')" value="2"></el-option>
  26. </el-select>
  27. </div>
  28. <div class="mt-10 inline-15">
  29. <span class="search__label inline-16">{{$t('分析日期')}}:</span>
  30. <el-date-picker
  31. v-model="endDate"
  32. type="date"
  33. :clearable="false"
  34. :append-to-body="!isFull"
  35. @change="changeDate"
  36. format="yyyy-MM-dd"
  37. value-format="yyyy-MM-dd"
  38. size="small"
  39. :range-separator="$t('至')"
  40. :start-placeholder="$t('开始月份')"
  41. :end-placeholder="$t('结束月份')">
  42. </el-date-picker>
  43. </div>
  44. <fullScreen domId="quotationAnalysisFull" @onFull="onFull" @backFull="backFull"></fullScreen>
  45. </div>
  46. </div>
  47. <div class="chart">
  48. <!-- <div id="quotationAnalysisChart" :style="{height: isFull?heightChart:windowWidth>1435?'90%':'90%'}"></div>-->
  49. <div id="quotationAnalysisChart" :style="{height: isFull?heightChart:windowWidth<1660?'90%':windowWidth<1676?'90%':'100%'}"></div>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. </template>
  55. <script>
  56. import boxLine from "@/views/salesData/components/boxLine1";
  57. import { Line,G2 } from '@antv/g2plot';
  58. import departmentSalesperson from "@/views/salesData/components/departmentSalesperson";
  59. import fullScreen from "@/views/salesData/components/fullScreen";
  60. const G = G2.getEngine('canvas');
  61. const seriesKey = 'series';
  62. const valueKey = 'value';
  63. const meta = {
  64. date: {
  65. alias: '日期',
  66. },
  67. oldtotalqty: {
  68. alias: '去年同期报价总数量',
  69. },
  70. oldproqty: {
  71. alias: '去年同期项目报价数量',
  72. },
  73. newproqty:{
  74. alias: '项目报价数量'
  75. },
  76. newtotalqty:{
  77. alias: '报价总数量'
  78. },
  79. oldcusqty:{
  80. alias: '去年同期客户报价数量'
  81. },
  82. newcusqty:{
  83. alias: '客户报价数量'
  84. }
  85. };
  86. export default {
  87. name: "quotationAnalysis",
  88. props:['dataid','windowWidth','scrollHeight'],
  89. components:{boxLine,departmentSalesperson,fullScreen},
  90. data(){
  91. return {
  92. chartLine:null,
  93. "proqty": '',//项目报价总数
  94. "proamount": '',//项目报价金额
  95. "cusqty": '',//客户报价总数
  96. "totalamount": '',//报价总金额
  97. "totalqty": '',//报价总数量
  98. "cusamount": '',//客户报价金额,
  99. param:{
  100. "id": 20231011201004,
  101. "content": {
  102. "type": '0',//0人员 1部门
  103. "dataid": '',
  104. "where":{
  105. "isleave":'1'
  106. }
  107. }
  108. },
  109. plotParam:{
  110. "id": 20231011154704,
  111. "content": {
  112. "type": 0,//0人员 1部门
  113. "dataid": '',
  114. "enddate": "", //分析日期
  115. "where":{
  116. "isleave":'1'
  117. }
  118. }
  119. },
  120. plotList:[],
  121. endDate:new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-' + new Date().getDate(),
  122. padding:'0',
  123. heightChart:'100%',
  124. isFull:false
  125. }
  126. },
  127. methods:{
  128. async listData(val,type,state){
  129. if (state == '状态'){
  130. this.$refs.departmentSalesperson.person = ''
  131. this.param.content.type = 1
  132. this.param.content.dataid = this.$refs.departmentSalesperson.depmentid ? this.$refs.departmentSalesperson.depmentid : -1
  133. }else {
  134. this.param.content.dataid = val?val : this.dataid
  135. }
  136. this.param.content.where.isleave = type
  137. const res = await this.$api.requested(this.param)
  138. this.proqty = res.data.proqty
  139. this.proamount = res.data.proamount
  140. this.cusqty = res.data.cusqty
  141. this.totalamount = res.data.totalamount
  142. this.totalqty = res.data.totalqty
  143. this.cusamount = res.data.cusamount
  144. state == '状态' ?this.personData(this.$refs.departmentSalesperson.depmentid):''
  145. },
  146. /*获取报价分析数据*/
  147. async queryQuotation(val,type) {
  148. /* this.plotParam.content.dataid = val || this.dataid
  149. console.log(this.endDate)
  150. this.plotParam.content.enddate = this.endDate
  151. const res = await this.$api.requested(this.plotParam)
  152. this.plotList=res.data*/
  153. this.renderPie(val,type)
  154. },
  155. /*渲染图表数据*/
  156. async queryQuotationModel(val,type,state) {
  157. if (state == '状态'){
  158. this.plotParam.content.dataid = this.plotParam.content.type == 0?-1:val
  159. }else {
  160. this.plotParam.content.dataid = val?val : this.dataid
  161. }
  162. this.plotParam.content.enddate = this.endDate
  163. this.plotParam.content.where.isleave = type
  164. const res = await this.$api.requested(this.plotParam)
  165. this.plotList=res.data
  166. this.chartLine.changeData(this.processData(this.plotList, ['newtotalqty', 'newcusqty','newproqty','oldtotalqty','oldcusqty','oldproqty']))
  167. },
  168. processData(data, yFields) {
  169. const result = [];
  170. data.forEach((d) => {
  171. yFields.forEach((yField) => {
  172. const name = this.$t(meta?.[yField]?.alias || yField) ;
  173. result.push({ ...d, date: d.date, [seriesKey]: name, [valueKey]: d[yField] });
  174. });
  175. });
  176. return result;
  177. },
  178. renderPie(val,type){
  179. this.chartLine = new Line('quotationAnalysisChart',{
  180. data:this.processData(this.plotList, ['newtotalqty', 'newcusqty','newproqty','oldtotalqty','oldcusqty','oldproqty']),
  181. xField: 'date',
  182. yField: valueKey,
  183. seriesField: seriesKey,
  184. smooth: true,
  185. label:{
  186. // 可手动配置 label 数据标签位置
  187. position: 'top', // 'top', 'bottom', 'middle',
  188. // 配置样式
  189. layout: [],
  190. }
  191. /*label: {
  192. // 可手动配置 label 数据标签位置
  193. position: 'top', // 'top', 'bottom', 'middle',
  194. // 配置样式
  195. layout: [{ type: 'hide-overlap' }],
  196. /!* formatter: (item) => item.value + '%',*!/
  197. },*/
  198. });
  199. this.chartLine.render()
  200. this.queryQuotationModel(val,type)
  201. },
  202. changeDate(){
  203. this.queryQuotationModel()
  204. },
  205. /*选择部门*/
  206. depSelect(val){
  207. this.plotParam.content.type = 1
  208. this.param.content.type = 1
  209. this.plotParam.content.dataid = val?val:-1
  210. this.dataid = val?val:-1
  211. this.listData(this.dataid,this.plotParam.content.where.isleave)
  212. this.queryQuotationModel(this.dataid,this.plotParam.content.where.isleave)
  213. this.personData(this.dataid)
  214. },
  215. /*选择业务员*/
  216. personSelect(val){
  217. if (val || this.$refs.departmentSalesperson.depmentid){
  218. this.plotParam.content.type = val?0:1
  219. this.param.content.type = val?0:1
  220. this.plotParam.content.dataid = val?val:this.$refs.departmentSalesperson.depmentid
  221. this.dataid = val?val:this.$refs.departmentSalesperson.depmentid
  222. }else {
  223. this.plotParam.content.type = 1
  224. this.param.content.type = 1
  225. this.plotParam.content.dataid = -1
  226. this.dataid = -1
  227. }
  228. this.listData(this.dataid,this.plotParam.content.where.isleave)
  229. this.queryQuotationModel(this.dataid,this.plotParam.content.where.isleave)
  230. },
  231. /*获取新的业务员列表*/
  232. async personData(depid){
  233. let param = {
  234. id: 20230620102004,
  235. content: {
  236. isleave:this.plotParam.content.where.isleave,
  237. depid:depid
  238. },
  239. }
  240. const res = await this.$api.requested(param)
  241. this.$refs.departmentSalesperson.personnelList = res.data.hr
  242. },
  243. /*全屏*/
  244. onFull(){
  245. this.heightChart = this.windowWidth > 1144 ?'calc(100vh - 80px)':'calc(100vh - 115px)'
  246. this.padding = '16px'
  247. this.isFull = true
  248. },
  249. /*退出全屏*/
  250. backFull(val){
  251. /*this.heightChart = '100%'*/
  252. this.padding = '0'
  253. this.isFull = false
  254. this.$emit('backFull',val)
  255. }
  256. },
  257. mounted() {
  258. }
  259. }
  260. </script>
  261. <style scoped>
  262. .div-line{
  263. background: #4F7BFD;
  264. height: 20px;
  265. width: 5px;
  266. float: left;
  267. }
  268. .container-div{
  269. display: flex;
  270. flex-wrap: wrap;
  271. margin: 10px 18px 0 0;
  272. }
  273. </style>