index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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. //门店
  189. if (options.type == 1){
  190. this.title = '门店销售数据';
  191. this.type = 1;
  192. this.storeId = options.storeId;
  193. this.initMenDian();
  194. }
  195. //业务员
  196. if (options.type == 2){
  197. this.title = '业务员销售数据';
  198. this.type = 2;
  199. this.ywyId = options.ywyId;
  200. console.log(this.type);
  201. this.initYWY();
  202. }
  203. //经销商
  204. if (options.type == 3){
  205. this.title = '经销商销售数据';
  206. this.type = 3;
  207. this.initJXS();
  208. }
  209. },
  210. onReady() {
  211. },
  212. methods: {
  213. timeCalendar(){
  214. console.log('timeCalendar');
  215. this.timeShow = false;
  216. },
  217. initMenDian() {
  218. this.chartTitle = "核销和上货趋势统计";
  219. let that = this;
  220. getStoreSalesSummary(this.startTime,this.endTime,this.storeId).then(res => {
  221. if (res.code === 0){
  222. that.hexiaoNumber = res.data.verificationTotal;
  223. that.shangHuoNumber = res.data.activateTotal;
  224. }
  225. }).catch(err => {
  226. });
  227. getStoreSalesTrend(this.startTime,this.endTime,this.storeId).then(resData => {
  228. if (resData.code === 0){
  229. let apiResponse = resData.data;
  230. // 提取日期列表并排序
  231. let categories = apiResponse.map(item => {
  232. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  233. return item.date.split("-")[2]; // 这里提取日期中的日部分
  234. });
  235. // 排序日期列表
  236. categories.sort((a, b) => {
  237. return a.localeCompare(b);
  238. })
  239. // 按日期排序数据
  240. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  241. // 提取核销数据和上货数据
  242. let verificationData = sortedData.map(item => item.verificationCount);
  243. let activateData = sortedData.map(item => item.activateCount);
  244. // 构造图表需要的格式
  245. let resTb = {
  246. categories: categories,
  247. series: [
  248. {
  249. name: "核销",
  250. data: verificationData
  251. },
  252. {
  253. name: "上货",
  254. data: activateData
  255. }
  256. ]
  257. };
  258. this.chartData = JSON.parse(JSON.stringify(resTb));
  259. }
  260. })
  261. },
  262. initYWY() {
  263. let that = this;
  264. getSalesmanSalesTotal(this.startTime,this.endTime,this.ywyId).then(res => {
  265. if (res.code === 0){
  266. console.log(res.data);
  267. that.hexiaoNumber = res.data.verificationTotal;
  268. that.xundianNumber = res.data.visitTotal;
  269. that.shangHuoNumber = res.data.activateTotal;
  270. }
  271. }).catch(err => {
  272. });
  273. getSalesmanSalesTrend(this.startTime,this.endTime,this.ywyId).then(res => {
  274. if (res.code === 0){
  275. console.log(res.data);
  276. let apiResponse = res.data;
  277. // 提取日期列表并排序
  278. let categories = apiResponse.map(item => {
  279. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  280. return item.date.split("-")[2]; // 这里提取日期中的日部分
  281. });
  282. // 排序日期
  283. categories.sort((a, b) => parseInt(a) - parseInt(b));
  284. // 按日期排序数据
  285. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  286. // 提取核销数据和上货数据
  287. let verificationData = sortedData.map(item => item.verificationCount);
  288. let activateData = sortedData.map(item => item.activateCount);
  289. // 构造图表需要的格式
  290. let resTb = {
  291. categories: categories,
  292. series: [
  293. {
  294. name: "核销",
  295. data: verificationData
  296. },
  297. {
  298. name: "上货",
  299. data: activateData
  300. }
  301. ]
  302. };
  303. this.chartData = JSON.parse(JSON.stringify(resTb));
  304. }
  305. }).catch(err => {
  306. });
  307. getSalesmanVisitTrend(this.startTime,this.endTime,this.ywyId).then(res => {
  308. if (res.code === 0){
  309. // 处理巡店趋势数据
  310. let apiResponse = res.data;
  311. // 提取日期列表(这里提取日部分)
  312. let categories = apiResponse.map(item => {
  313. return item.date.split("-")[2]; // 提取日期中的日部分
  314. });
  315. // 按日期排序数据
  316. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  317. // 提取巡店数据
  318. let visitData = sortedData.map(item => item.visitCount || 0);
  319. // 构造图表需要的格式(与selectedCode中格式一致)
  320. let resFormat = {
  321. categories: categories,
  322. series: [
  323. {
  324. name: "巡店",
  325. data: visitData
  326. }
  327. ]
  328. };
  329. this.chartDataXd = JSON.parse(JSON.stringify(resFormat));
  330. }
  331. }).catch(err => {
  332. console.error(err);
  333. });
  334. },
  335. initJXS() {
  336. this.chartTitle = "核销和下单趋势统计";
  337. getSalesTotal(this.startTime,this.endTime).then(res => {
  338. if (res.code === 0){
  339. this.hexiaoNumber = res.data.orderTotal;
  340. this.xiaDanNumber = res.data.verificationTotal;
  341. }
  342. }).catch(err => {
  343. });
  344. getSalesTrend(this.startTime,this.endTime).then(data => {
  345. if (data.code === 0){
  346. let apiResponse = data.data;
  347. // 提取日期列表并排序
  348. let categories = apiResponse.map(item => {
  349. // 从日期中提取月日,例如 "2025-08-01" -> "08-01" -> "8/1" 或者只显示日 "1"
  350. return item.date.split("-")[2];
  351. })
  352. categories.sort((a, b) => parseInt(a) - parseInt(b));
  353. // 按日期排序数据
  354. let sortedData = apiResponse.sort((a, b) => new Date(a.date) - new Date(b.date));
  355. let verificationData = sortedData.map(item => item.verificationCount);
  356. let orderCountData = sortedData.map(item => item.orderCount);
  357. let res = {
  358. categories: categories,
  359. series: [
  360. {
  361. name: "核销",
  362. data: verificationData
  363. },
  364. {
  365. name: "下单",
  366. data: orderCountData
  367. }
  368. ]
  369. };
  370. this.chartData = JSON.parse(JSON.stringify(res));
  371. }
  372. })
  373. },
  374. confirm(e) {
  375. this.startTime = e[0];
  376. this.endTime = e[e.length -1];
  377. this.startTimeXd = e[0]+' ~ '+e[e.length -1];
  378. this.timeShow = false;
  379. if (this.type == 1){
  380. this.initMenDian();
  381. }
  382. if (this.type == 2){
  383. this.initYWY();
  384. }
  385. if (this.type == 3){
  386. this.initJXS();
  387. }
  388. },
  389. }
  390. };
  391. </script>
  392. <style scoped>
  393. .container {
  394. background-image: url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/bgi_2.png");
  395. background-size: 100% 100%;
  396. background-position: center;
  397. background-repeat: no-repeat;
  398. height: 100vh;
  399. padding: 0px 10px;
  400. }
  401. .title-text{
  402. font-weight: bold;
  403. font-size: 18px;
  404. color: #102A3C;
  405. text-align: center;
  406. height: 12vh;
  407. line-height: 16vh;
  408. }
  409. /* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
  410. .charts-box {
  411. width: 100%;
  412. height: 210px;
  413. }
  414. .query-btn {
  415. background-color: #409eff;
  416. color: #fff;
  417. padding: 20rpx;
  418. border-radius: 10rpx;
  419. height: 34rpx;
  420. display: flex;
  421. justify-content: center;
  422. align-items: center;
  423. }
  424. .query-btn-icon {
  425. height: 32rpx;
  426. width: 32rpx;
  427. background-image:
  428. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/queryIoc.png");
  429. background-size: cover;
  430. background-position: center;
  431. background-repeat: no-repeat;
  432. }
  433. .query-btn-text {
  434. font-weight: 400;
  435. font-size: 30rpx;
  436. color: #F5F5F5;
  437. }
  438. .filter{
  439. display: flex;
  440. justify-content: space-around;
  441. align-items: center;
  442. height: 160rpx;
  443. background: #FFFFFF;
  444. box-shadow: 0rpx 10rpx 20rpx 0rpx rgba(168,168,168,0.22);
  445. border-radius: 12rpx;
  446. border: 2px solid #FFFFFF;
  447. }
  448. .item-one{
  449. display: flex;
  450. }
  451. .type-icon-hexiao {
  452. height: 80rpx;
  453. width: 80rpx;
  454. background-image:
  455. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/hexiaoIoc.png");
  456. background-size: cover;
  457. background-position: center;
  458. background-repeat: no-repeat;
  459. }
  460. .type-icon-xundian {
  461. height: 80rpx;
  462. width: 80rpx;
  463. background-image:
  464. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/xundianIoc.png");
  465. background-size: cover;
  466. background-position: center;
  467. background-repeat: no-repeat;
  468. }
  469. .type-icon-shanghuo {
  470. height: 80rpx;
  471. width: 80rpx;
  472. background-image:
  473. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/shanghuoIoc.png");
  474. background-size: cover;
  475. background-position: center;
  476. background-repeat: no-repeat;
  477. }
  478. .type-icon-xiadan {
  479. height: 80rpx;
  480. width: 80rpx;
  481. background-image:
  482. url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/xiadanIoc.png");
  483. background-size: cover;
  484. background-position: center;
  485. background-repeat: no-repeat;
  486. }
  487. .number{
  488. font-weight: bold;
  489. font-size: 30rpx;
  490. color: #3B3638;
  491. }
  492. .text{
  493. font-weight: 400;
  494. font-size: 28rpx;
  495. color: #84868A;
  496. }
  497. .type-data{
  498. margin-left: 10rpx;
  499. }
  500. .t-one{
  501. margin-top: 10px;
  502. background-color: #fff;
  503. }
  504. .t-text {
  505. position: relative;
  506. padding-left: 10px; /* 为竖杠留出空间 */
  507. font-size: 30rpx; /* 根据需要调整字体大小 */
  508. color: #3B3638; /* 标题颜色 */
  509. font-weight: bold;
  510. }
  511. .t-text::before {
  512. content: ''; /* 必须设置 content 属性 */
  513. position: absolute;
  514. left: 0;
  515. top: 50%;
  516. transform: translateY(-50%); /* 垂直居中 */
  517. width: 4px; /* 竖杠宽度 */
  518. height: 16px; /* 竖杠高度 */
  519. background-color: #1890FF; /* 蓝色 */
  520. }
  521. ::v-deep .u-input{
  522. background-color: #fff;
  523. }
  524. ::v-deep .u-calendar{
  525. z-index: 999;
  526. }
  527. .popup-content{
  528. height: 45vh;
  529. padding: 10px;
  530. }
  531. .popup-text{
  532. font-family: PingFang SC;
  533. font-weight: bold;
  534. font-size: 36rpx;
  535. color: #1C1E1D;
  536. text-align: center;
  537. margin-bottom: 10px;
  538. }
  539. .popup-btn{
  540. display: flex;
  541. justify-content: space-around;
  542. }
  543. .popup-btn-one{
  544. width: 275rpx;
  545. height: 70rpx;
  546. background: linear-gradient(0deg, #6FA4FE, #488CFF);
  547. box-shadow: 0rpx 9rpx 16rpx 0rpx rgba(153,153,153,0.35);
  548. border-radius: 35rpx;
  549. }
  550. .explain{
  551. font-weight: 400;
  552. font-size: 28rpx;
  553. color: #3B3638;
  554. }
  555. </style>