index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <template>
  2. <view class="container">
  3. <view class="title">
  4. <view class="title-text">{{title}}</view>
  5. </view>
  6. <view class="header">
  7. <view class="query">
  8. <u-row customStyle="margin-bottom: 10px" gutter="20">
  9. <u-col span="9">
  10. <u--input
  11. @focus="timeShow = true"
  12. v-model="startTimeXd"
  13. placeholder="开始日期 ~ 结束日期"
  14. prefixIcon="calendar"
  15. prefixIconStyle="font-size: 22px;color: #909399"
  16. ></u--input>
  17. </u-col>
  18. <u-col span="3">
  19. <view class="query-btn" @click="timeShow = !timeShow">
  20. <view class="query-btn-icon">
  21. </view>
  22. <view class="query-btn-text">筛选</view>
  23. </view>
  24. </u-col>
  25. </u-row>
  26. </view>
  27. <view class="filter">
  28. <view class="item-one">
  29. <view class="type-icon-hexiao"></view>
  30. <view class="type-data">
  31. <view class="number">{{hexiaoNumber}}</view>
  32. <view class="text">核销</view>
  33. </view>
  34. </view>
  35. <view class="item-one" v-if="type === 2">
  36. <view class="type-icon-xundian"></view>
  37. <view class="type-data">
  38. <view class="number">{{ xundianNumber}}</view>
  39. <view class="text">巡店</view>
  40. </view>
  41. </view>
  42. <view class="item-one" v-if="type !== 3">
  43. <view class="type-icon-shanghuo"></view>
  44. <view class="type-data">
  45. <view class="number">{{ shangHuoNumber}}</view>
  46. <view class="text">上货</view>
  47. </view>
  48. </view>
  49. <view class="item-one" v-if="type === 3">
  50. <view class="type-icon-xiadan"></view>
  51. <view class="type-data">
  52. <view class="number">{{xiaDanNumber}}</view>
  53. <view class="text">下单</view>
  54. </view>
  55. </view>
  56. </view>
  57. </view>
  58. <view class="content">
  59. <view class="t-one">
  60. <view class="t-text">核销和上货趋势统计</view>
  61. <view class="charts-box" v-show="!timeShow">
  62. <qiun-data-charts
  63. type="line"
  64. :opts="opts"
  65. :chartData="chartData"
  66. />
  67. </view>
  68. </view>
  69. <view class="t-one" v-show=" type == 2 && !timeShow">
  70. <view class="t-text">巡店统计</view>
  71. <view class="charts-box">
  72. <qiun-data-charts
  73. type="column"
  74. :opts="opts"
  75. :chartData="chartDataXd"
  76. />
  77. </view>
  78. </view>
  79. </view>
  80. <u-popup :show="show" mode="bottom" @close="show = false" >
  81. <view class="popup-content">
  82. <view class="popup-text">筛选</view>
  83. <u-row customStyle="margin-bottom: 10px">
  84. <u-col span="3">
  85. <view class="explain">选择日期</view>
  86. </u-col>
  87. <u-col span="9">
  88. <u--input
  89. v-model="startTimeXd"
  90. placeholder="开始日期 ~ 结束日期"
  91. prefixIcon="calendar"
  92. prefixIconStyle="font-size: 22px;color: #909399"
  93. @focus="timeShow = true"
  94. ></u--input>
  95. </u-col>
  96. </u-row>
  97. <u-row customStyle="margin-bottom: 10px">
  98. <u-col span="3">
  99. <view class="explain">门店名称</view>
  100. </u-col>
  101. <u-col span="9">
  102. <u--input
  103. placeholder="请输入内容"
  104. border="surround"
  105. ></u--input>
  106. </u-col>
  107. </u-row>
  108. <u-row customStyle="margin-bottom: 10px">
  109. <u-col span="3">
  110. <view class="explain">业务员</view>
  111. </u-col>
  112. <u-col span="9">
  113. <u--input
  114. placeholder="请输入内容"
  115. border="surround"
  116. ></u--input>
  117. </u-col>
  118. </u-row>
  119. <u-row customStyle="margin-bottom: 10px">
  120. <u-col span="3">
  121. <view class="explain">订单编号</view>
  122. </u-col>
  123. <u-col span="9">
  124. <u--input
  125. placeholder="请输入内容"
  126. border="surround"
  127. ></u--input>
  128. </u-col>
  129. </u-row>
  130. <view class="popup-btn">
  131. <u-button class="popup-btn-one">搜索</u-button>
  132. <u-button class="popup-btn-one" type="primary">重置</u-button>
  133. </view>
  134. </view>
  135. </u-popup>
  136. <u-calendar :minDate="minDate" :monthNumber="6" :show="timeShow" :mode="mode" @confirm="confirm" @close="timeCalendar"></u-calendar>
  137. </view>
  138. </template>
  139. <script>
  140. import {getSalesTotal,getSalesTrend,getSalesmanSalesTotal,getSalesmanSalesTrend,getSalesmanVisitTrend,getStoreSalesSummary,getStoreSalesTrend} from "../../../api/hexiao";
  141. export default {
  142. data() {
  143. return {
  144. chartTitle: "核销和上货趋势统计",
  145. storeId: 0,
  146. ywyId:0,
  147. minDate: new Date(new Date().setMonth(new Date().getMonth() - 2)),
  148. maxDate: new Date(),
  149. hexiaoNumber: 0,
  150. xundianNumber: 0,
  151. shangHuoNumber: 0,
  152. xiaDanNumber: 0,
  153. type: 1,
  154. title: '',
  155. startTime: '',
  156. endTime: '',
  157. startTimeXd: '',
  158. timeShow: false,
  159. mode: 'range',
  160. show: false,
  161. chartDataXd: {},
  162. chartData: {},
  163. //您可以通过修改 config-ucharts.js 文件中下标为 ['line'] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
  164. opts: {
  165. height: 210,
  166. color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
  167. padding: [15,10,0,15],
  168. enableScroll: false,
  169. legend: {},
  170. xAxis: {
  171. disableGrid: true
  172. },
  173. yAxis: {
  174. gridType: "dash",
  175. dashLength: 2
  176. },
  177. extra: {
  178. line: {
  179. type: "straight",
  180. width: 2,
  181. activeType: "hollow"
  182. }
  183. }
  184. }
  185. };
  186. },
  187. onLoad: function(options) {
  188. console.log(options);
  189. //门店
  190. if (options.type == 1){
  191. this.title = '门店销售数据';
  192. this.type = 1;
  193. this.storeId = options.storeId;
  194. this.initMenDian();
  195. }
  196. //业务员
  197. if (options.type == 2){
  198. this.title = '业务员销售数据';
  199. this.type = 2;
  200. this.ywyId = options.ywyId;
  201. console.log(this.type);
  202. this.initYWY();
  203. }
  204. //经销商
  205. if (options.type == 3){
  206. this.title = '经销商销售数据';
  207. this.type = 3;
  208. this.initJXS();
  209. }
  210. },
  211. onReady() {
  212. },
  213. methods: {
  214. timeCalendar(){
  215. console.log('timeCalendar');
  216. this.timeShow = false;
  217. },
  218. initMenDian() {
  219. this.chartTitle = "核销和上货趋势统计";
  220. let that = this;
  221. getStoreSalesSummary(this.startTime,this.endTime,this.storeId).then(res => {
  222. if (res.code === 0){
  223. that.hexiaoNumber = res.data.verificationTotal;
  224. that.shangHuoNumber = res.data.activateTotal;
  225. }
  226. }).catch(err => {
  227. });
  228. getStoreSalesTrend(this.startTime,this.endTime,this.storeId).then(resData => {
  229. if (resData.code === 0){
  230. let apiResponse = resData.data;
  231. // 按日期排序数据
  232. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  233. // 提取日期列表并排序
  234. let categories = sortedData.map(item => {
  235. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  236. return item.date.split("-")[2]; // 这里提取日期中的日部分
  237. });
  238. console.log(categories)
  239. // 提取核销数据和上货数据
  240. let verificationData = sortedData.map(item => item.verificationCount);
  241. let activateData = sortedData.map(item => item.activateCount);
  242. // 构造图表需要的格式
  243. let resTb = {
  244. categories: categories,
  245. series: [
  246. {
  247. name: "核销",
  248. data: verificationData
  249. },
  250. {
  251. name: "上货",
  252. data: activateData
  253. }
  254. ]
  255. };
  256. this.chartData = JSON.parse(JSON.stringify(resTb));
  257. }
  258. })
  259. },
  260. initYWY() {
  261. let that = this;
  262. getSalesmanSalesTotal(this.startTime,this.endTime,this.ywyId).then(res => {
  263. if (res.code === 0){
  264. console.log(res.data);
  265. that.hexiaoNumber = res.data.verificationTotal;
  266. that.xundianNumber = res.data.visitTotal;
  267. that.shangHuoNumber = res.data.activateTotal;
  268. }
  269. }).catch(err => {
  270. });
  271. getSalesmanSalesTrend(this.startTime,this.endTime,this.ywyId).then(res => {
  272. if (res.code === 0){
  273. console.log(res.data);
  274. let apiResponse = res.data;
  275. // 按日期排序数据
  276. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  277. // 提取日期列表并排序
  278. let categories = sortedData.map(item => {
  279. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  280. return item.date.split("-")[2]; // 这里提取日期中的日部分
  281. });
  282. // 提取核销数据和上货数据
  283. let verificationData = sortedData.map(item => item.verificationCount);
  284. let activateData = sortedData.map(item => item.activateCount);
  285. // 构造图表需要的格式
  286. let resTb = {
  287. categories: categories,
  288. series: [
  289. {
  290. name: "核销",
  291. data: verificationData
  292. },
  293. {
  294. name: "上货",
  295. data: activateData
  296. }
  297. ]
  298. };
  299. this.chartData = JSON.parse(JSON.stringify(resTb));
  300. }
  301. }).catch(err => {
  302. });
  303. getSalesmanVisitTrend(this.startTime,this.endTime,this.ywyId).then(res => {
  304. if (res.code === 0){
  305. // 处理巡店趋势数据
  306. let apiResponse = res.data;
  307. // 提取日期列表(这里提取日部分)
  308. let categories = apiResponse.map(item => {
  309. return item.date.split("-")[2]; // 提取日期中的日部分
  310. });
  311. // 按日期排序数据
  312. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  313. // 提取巡店数据
  314. let visitData = sortedData.map(item => item.visitCount || 0);
  315. // 构造图表需要的格式(与selectedCode中格式一致)
  316. let resFormat = {
  317. categories: categories,
  318. series: [
  319. {
  320. name: "巡店",
  321. data: visitData
  322. }
  323. ]
  324. };
  325. this.chartDataXd = JSON.parse(JSON.stringify(resFormat));
  326. }
  327. }).catch(err => {
  328. console.error(err);
  329. });
  330. },
  331. initJXS() {
  332. this.chartTitle = "核销和下单趋势统计";
  333. getSalesTotal(this.startTime,this.endTime).then(res => {
  334. if (res.code === 0){
  335. this.hexiaoNumber = res.data.orderTotal;
  336. this.xiaDanNumber = res.data.verificationTotal;
  337. }
  338. }).catch(err => {
  339. });
  340. getSalesTrend(this.startTime,this.endTime).then(data => {
  341. if (data.code === 0){
  342. let apiResponse = data.data;
  343. // 按日期排序数据
  344. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  345. // 提取日期列表并排序
  346. let categories = sortedData.map(item => {
  347. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  348. return item.date.split("-")[2];
  349. })
  350. let verificationData = sortedData.map(item => item.verificationCount);
  351. let orderCountData = sortedData.map(item => item.orderCount);
  352. let res = {
  353. categories: categories,
  354. series: [
  355. {
  356. name: "核销",
  357. data: verificationData
  358. },
  359. {
  360. name: "下单",
  361. data: orderCountData
  362. }
  363. ]
  364. };
  365. this.chartData = JSON.parse(JSON.stringify(res));
  366. }
  367. })
  368. },
  369. confirm(e) {
  370. this.startTime = e[0];
  371. this.endTime = e[e.length -1];
  372. this.startTimeXd = e[0]+' ~ '+e[e.length -1];
  373. this.timeShow = false;
  374. if (this.type == 1){
  375. this.initMenDian();
  376. }
  377. if (this.type == 2){
  378. this.initYWY();
  379. }
  380. if (this.type == 3){
  381. this.initJXS();
  382. }
  383. },
  384. }
  385. };
  386. </script>
  387. <style scoped>
  388. .container {
  389. background-image: url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/bgi_2.png");
  390. background-size: 100% 100%;
  391. background-position: center;
  392. background-repeat: no-repeat;
  393. height: 100vh;
  394. padding: 0px 10px;
  395. }
  396. .title-text{
  397. font-weight: bold;
  398. font-size: 18px;
  399. color: #102A3C;
  400. text-align: center;
  401. height: 12vh;
  402. line-height: 16vh;
  403. }
  404. /* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
  405. .charts-box {
  406. width: 100%;
  407. height: 210px;
  408. }
  409. .query-btn {
  410. background-color: #409eff;
  411. color: #fff;
  412. padding: 20rpx;
  413. border-radius: 10rpx;
  414. height: 34rpx;
  415. display: flex;
  416. justify-content: center;
  417. align-items: center;
  418. }
  419. .query-btn-icon {
  420. height: 32rpx;
  421. width: 32rpx;
  422. background-image:
  423. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/queryIoc.png");
  424. background-size: cover;
  425. background-position: center;
  426. background-repeat: no-repeat;
  427. }
  428. .query-btn-text {
  429. font-weight: 400;
  430. font-size: 30rpx;
  431. color: #F5F5F5;
  432. }
  433. .filter{
  434. display: flex;
  435. justify-content: space-around;
  436. align-items: center;
  437. height: 160rpx;
  438. background: #FFFFFF;
  439. box-shadow: 0rpx 10rpx 20rpx 0rpx rgba(168,168,168,0.22);
  440. border-radius: 12rpx;
  441. border: 2px solid #FFFFFF;
  442. }
  443. .item-one{
  444. display: flex;
  445. }
  446. .type-icon-hexiao {
  447. height: 80rpx;
  448. width: 80rpx;
  449. background-image:
  450. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/hexiaoIoc.png");
  451. background-size: cover;
  452. background-position: center;
  453. background-repeat: no-repeat;
  454. }
  455. .type-icon-xundian {
  456. height: 80rpx;
  457. width: 80rpx;
  458. background-image:
  459. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/xundianIoc.png");
  460. background-size: cover;
  461. background-position: center;
  462. background-repeat: no-repeat;
  463. }
  464. .type-icon-shanghuo {
  465. height: 80rpx;
  466. width: 80rpx;
  467. background-image:
  468. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/shanghuoIoc.png");
  469. background-size: cover;
  470. background-position: center;
  471. background-repeat: no-repeat;
  472. }
  473. .type-icon-xiadan {
  474. height: 80rpx;
  475. width: 80rpx;
  476. background-image:
  477. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/xiadanIoc.png");
  478. background-size: cover;
  479. background-position: center;
  480. background-repeat: no-repeat;
  481. }
  482. .number{
  483. font-weight: bold;
  484. font-size: 30rpx;
  485. color: #3B3638;
  486. }
  487. .text{
  488. font-weight: 400;
  489. font-size: 28rpx;
  490. color: #84868A;
  491. }
  492. .type-data{
  493. margin-left: 10rpx;
  494. }
  495. .t-one{
  496. margin-top: 10px;
  497. background-color: #fff;
  498. }
  499. .t-text {
  500. position: relative;
  501. padding-left: 10px; /* 为竖杠留出空间 */
  502. font-size: 30rpx; /* 根据需要调整字体大小 */
  503. color: #3B3638; /* 标题颜色 */
  504. font-weight: bold;
  505. }
  506. .t-text::before {
  507. content: ''; /* 必须设置 content 属性 */
  508. position: absolute;
  509. left: 0;
  510. top: 50%;
  511. transform: translateY(-50%); /* 垂直居中 */
  512. width: 4px; /* 竖杠宽度 */
  513. height: 16px; /* 竖杠高度 */
  514. background-color: #1890FF; /* 蓝色 */
  515. }
  516. ::v-deep .u-input{
  517. background-color: #fff;
  518. }
  519. ::v-deep .u-calendar{
  520. z-index: 999;
  521. }
  522. .popup-content{
  523. height: 45vh;
  524. padding: 10px;
  525. }
  526. .popup-text{
  527. font-family: PingFang SC;
  528. font-weight: bold;
  529. font-size: 36rpx;
  530. color: #1C1E1D;
  531. text-align: center;
  532. margin-bottom: 10px;
  533. }
  534. .popup-btn{
  535. display: flex;
  536. justify-content: space-around;
  537. }
  538. .popup-btn-one{
  539. width: 275rpx;
  540. height: 70rpx;
  541. background: linear-gradient(0deg, #6FA4FE, #488CFF);
  542. box-shadow: 0rpx 9rpx 16rpx 0rpx rgba(153,153,153,0.35);
  543. border-radius: 35rpx;
  544. }
  545. .explain{
  546. font-weight: 400;
  547. font-size: 28rpx;
  548. color: #3B3638;
  549. }
  550. </style>