index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <template>
  2. <!-- 主页 -->
  3. <div class="homePage flex-col">
  4. <div class="homeBox">
  5. <s-header
  6. :name="sys ? sys.title : $t('public.sysName')"
  7. :noback="true"
  8. :isFixed="false"
  9. ></s-header>
  10. <!-- 留言滚动条 -->
  11. <template v-if="noticeContent.title">
  12. <van-notice-bar
  13. @click="noticeClk"
  14. mode="link"
  15. :scrollable="true"
  16. color="rgba(64,77,116,1)"
  17. background="#fff"
  18. left-icon="volume-o"
  19. :text="noticeContent.title"
  20. />
  21. </template>
  22. <div class="intervalRow"></div>
  23. <div class="nameDeviceRow flex-col">
  24. <span class="txt3">{{ userName }}</span>
  25. <div class="l-flex-RC">
  26. <span class="info3"
  27. >{{ equipStatus.machineTotalNum }}
  28. {{ $t("home.totalEquipment") }}</span
  29. >
  30. <div class="lineCon o-mlr-6"></div>
  31. <span class="word2"
  32. >{{ equipStatus.machineUseNum }} {{ $t("home.running") }}</span
  33. >
  34. </div>
  35. </div>
  36. <!-- 数据概览 -->
  37. <div class="titleBox flex-col">
  38. <div class="layer2 flex-row">
  39. <div class="section5 flex-col"></div>
  40. <div class="TextGroup2 flex-col">
  41. <span class="txt4">{{ $t("home.dataOverview") }}</span>
  42. </div>
  43. </div>
  44. </div>
  45. <!-- 时间选择 -->
  46. <dateSelectList @update="update($event)"></dateSelectList>
  47. <typeSelectList :isHome="true" @upselectdata="upselectdata($event)"></typeSelectList>
  48. <!-- 订单数据 -->
  49. <div class="o-plr-8">
  50. <div class="outer5 flex-col" @click="pushOrderCenter">
  51. <div class="block5 flex-col">
  52. <div class="topTitle flex-row justify-end">
  53. <span class="txt10">{{ $t("home.orderData") }}</span>
  54. <div class="layer4 flex-col"></div>
  55. </div>
  56. <div class="outerBox flex-row">
  57. <div class="main4 flex-col justify-between">
  58. <div class="main5 flex-row justify-center">
  59. <span class="word8">&yen;</span>
  60. <span class="word9">{{ salesVolume }}</span>
  61. </div>
  62. <span class="info5">{{ $t("home.totalIncome") }}</span>
  63. </div>
  64. <div class="TextGroup7 flex-col">
  65. <div class="mod3 flex-col justify-between">
  66. <span class="txt8">{{ salesNumber }}</span>
  67. <span class="info6">{{ $t("home.productNum") }}</span>
  68. </div>
  69. </div>
  70. <div class="TextGroup8 flex-col">
  71. <div class="outer6 flex-col justify-between">
  72. <span class="txt9">{{ orderNumber }}</span>
  73. <span class="word10">{{ $t("home.numberOfOrders") }}</span>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. </div>
  80. <!-- 时间 -->
  81. <div class="c-text-c c-text-18">
  82. {{$M_FormatTime(dateSelect.startDate,'YYYY-MM-DD')}}--{{$M_FormatTime(dateSelect.endDate,'YYYY-MM-DD')}}
  83. </div>
  84. <div v-if="!noData(salesVolume, salesNumber)">
  85. <div ref="chartBox" class="Chart1 flex-col"></div>
  86. </div>
  87. <kNoData v-else></kNoData>
  88. <div class="outer9 flex-col justify-center">
  89. <div class="main24 flex-col justify-between">
  90. <div class="ImageText10 flex-col">
  91. <div class="wrap2 flex-row justify-between">
  92. <div class="outer10 flex-col"></div>
  93. <div class="TextGroup13 flex-col">
  94. <span class="txt13">{{ $t("home.commonTools") }}</span>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. <div class="outer11 flex-row">
  101. <div
  102. class="main25 flex-col"
  103. v-for="(item, index) in pushToolList"
  104. :key="index"
  105. @click="pushToolPage(item.value)"
  106. >
  107. <img class="mod7 flex-col" :src="showLogo(item.value)" />
  108. <div class="TextGroup14 flex-col">
  109. <span class="info15" v-html="item.label"></span>
  110. </div>
  111. </div>
  112. </div>
  113. </div>
  114. <!-- 通知弹窗 -->
  115. <kDialog
  116. :dialogTitle="$t('home.notificationPop.notification')"
  117. :cancelBtnTxt="$t('home.notificationPop.nextTime')"
  118. :confirmBtnTxt="$t('home.notificationPop.roger')"
  119. ref="kDialogRef"
  120. @confirmclk="confirmClk"
  121. >
  122. <template #content>
  123. <div
  124. class="o-w"
  125. style="max-height: 50vh; overflow-y: auto"
  126. v-html="noticeContent.note"
  127. ></div>
  128. </template>
  129. </kDialog>
  130. <nav-bar></nav-bar>
  131. </div>
  132. </template>
  133. <script>
  134. // 导入无数据组件
  135. import kNoData from "@/components/commom/kNoData/index.vue";
  136. import kDialog from "@/components/commom/kDialog/index.vue";
  137. import { onMounted, ref, nextTick } from "vue";
  138. import sHeader from "@/components/SimpleHeader";
  139. import navBar from "@/components/NavBar";
  140. import dateSelectList from "@/components/dateSelectList";
  141. import typeSelectList from "@/components/typeSelectList";
  142. import { getLoginUser, $M_Menus,$M_FormatTime } from "@/common/js/utils";
  143. import { useRouter } from "vue-router";
  144. import {
  145. getStatistics,
  146. Api_getNotice,
  147. Api_postMachineNum,
  148. Api_getUpdateNotice,
  149. } from "@/service/home";
  150. import dateUtil from "@/utils/dateUtil";
  151. import { useI18n } from "vue-i18n";
  152. import { Toast } from "vant";
  153. export default {
  154. name: "home",
  155. components: {
  156. sHeader,
  157. navBar,
  158. dateSelectList,
  159. typeSelectList,
  160. kDialog,
  161. kNoData,
  162. },
  163. setup() {
  164. // 设备状况
  165. const equipStatus = ref({});
  166. // 获取设备情况
  167. const getMachineNum = () => {
  168. Api_postMachineNum({ adminId: user.id }).then((res) => {
  169. console.log("res", res);
  170. equipStatus.value = res.data.data || {};
  171. });
  172. };
  173. const noticeContent = ref({});
  174. // 获取公告
  175. const getNotice = () => {
  176. Api_getNotice({ id: user.id }).then((res) => {
  177. console.log("res", res);
  178. noticeContent.value = res.data.data || {};
  179. });
  180. };
  181. const { t } = useI18n();
  182. // 通知弹窗
  183. const kDialogRef = ref(null);
  184. // 点击通知栏
  185. const noticeClk = () => {
  186. kDialogRef.value.openDialog();
  187. };
  188. // 点击右侧按钮
  189. const confirmClk = (e) => {
  190. console.log(e, 2222);
  191. Api_getUpdateNotice({
  192. adminId: user.id,
  193. noticeId: noticeContent.value.id,
  194. }).then((res) => {
  195. console.log("res", res);
  196. Toast(res.data.message);
  197. setTimeout(() => {
  198. getNotice();
  199. }, 500);
  200. });
  201. };
  202. const user = getLoginUser();
  203. const router = useRouter();
  204. const userName = ref(user.name);
  205. const sys = ref(null);
  206. // 图表对象
  207. const chartBox = ref();
  208. let chartObj = null;
  209. // 跳转订单中心
  210. const pushOrderCenter = () => {
  211. router.push({ path: "/orderCenter" });
  212. };
  213. const dateSelect = ref({});
  214. const update = (uDate) => {
  215. dateSelect.value = uDate;
  216. getStatisticsFun();
  217. };
  218. let typeSelectData = {};
  219. const upselectdata = (uSData) => {
  220. typeSelectData = uSData;
  221. getStatisticsFun();
  222. };
  223. const salesVolume = ref(0);
  224. const salesNumber = ref(0);
  225. const orderNumber = ref(0);
  226. // 查询图表
  227. const getStatisticsFun = async () => {
  228. const params = {
  229. ...dateSelect.value,
  230. // ...typeSelectData,
  231. adminId: user.id,
  232. ifForeign: user.ifForeign,
  233. payType: typeSelectData.payType,
  234. clientId: typeSelectData.clientId,
  235. username: typeSelectData.userName, // 商家
  236. equipmentId:
  237. typeSelectData.equipmentId === "" ? null : typeSelectData.equipmentId,
  238. };
  239. const { data } = await getStatistics(params);
  240. if (data.code && data.data) {
  241. salesVolume.value = 0;
  242. salesNumber.value = 0;
  243. orderNumber.value = 0;
  244. data.data.series[0].data.forEach((item) => {
  245. salesNumber.value = parseInt(salesNumber.value + item);
  246. });
  247. data.data.series[1].data.forEach((item) => {
  248. salesVolume.value = parseInt(salesVolume.value + item);
  249. });
  250. data.data.series[2].data.forEach((item) => {
  251. orderNumber.value = parseInt(orderNumber.value + item);
  252. });
  253. // 解决eacharts与v-if的渲染问题
  254. await nextTick();
  255. if (chartBox.value) {
  256. chartObj = window.echarts.init(chartBox.value, null, {
  257. renderer: "canvas",
  258. useDirtyRect: false,
  259. });
  260. const option = {
  261. tooltip: {
  262. trigger: "axis",
  263. axisPointer: {
  264. type: "shadow",
  265. },
  266. },
  267. grid: {
  268. left: "3%",
  269. right: "4%",
  270. bottom: "10%",
  271. containLabel: true,
  272. },
  273. legend: {
  274. bottom: 0,
  275. right: 10,
  276. itemWidth: 10,
  277. itemHeight: 10,
  278. icon: "rect",
  279. },
  280. // 固定屏幕显示多少个,其余的滑动
  281. dataZoom: [
  282. // {
  283. // type: 'slider',
  284. // xAxisIndex: 0,
  285. // filterMode: 'none',
  286. // // 开始的值
  287. // startValue: null,
  288. // // 结束的值
  289. // endValue: null,
  290. // // 锁定滑动的区域
  291. // // zoomLock:true,
  292. // },
  293. {
  294. type: "inside",
  295. xAxisIndex: 0,
  296. filterMode: "none",
  297. startValue: null,
  298. endValue: null,
  299. zoomLock: true,
  300. },
  301. ],
  302. xAxis: {
  303. type: "category",
  304. axisLabel: {
  305. rotate: 45,
  306. },
  307. data: data.data.categories,
  308. },
  309. yAxis: {
  310. type: "value",
  311. },
  312. series: [
  313. {
  314. ...data.data.series[0],
  315. type: "bar",
  316. itemStyle: { color: "#E59A6D" },
  317. label: {
  318. show: true,
  319. position: "top",
  320. },
  321. },
  322. {
  323. ...data.data.series[1],
  324. type: "bar",
  325. itemStyle: { color: "#4D6ADD" },
  326. label: {
  327. show: true,
  328. position: "top",
  329. },
  330. },
  331. ],
  332. };
  333. option.dataZoom[0]["startValue"] =
  334. data.data.categories[data.data.categories.length - 5];
  335. option.dataZoom[0]["endValue"] =
  336. data.data.categories[data.data.categories.length - 1];
  337. chartObj && chartObj.setOption(option);
  338. //图形宽度随屏幕宽度改变而改变
  339. window.onresize = chartObj.resize;
  340. }
  341. }
  342. };
  343. const pushToolList = ref([]);
  344. // 页面初始化
  345. onMounted(() => {
  346. if (localStorage.getItem("loginSys")) {
  347. const loginSysString = localStorage.getItem("loginSys");
  348. sys.value = JSON.parse(loginSysString);
  349. }
  350. // 设置菜单权限
  351. menuSet();
  352. dateSelect.value = {
  353. chartType: "day",
  354. startDate: dateUtil.formateDate(
  355. new Date(new Date(new Date().getTime()).setHours(0, 0, 0, 0)),
  356. "yyyy-MM-dd hh:mm:ss"
  357. ),
  358. endDate: dateUtil.formateDate(
  359. new Date(new Date(new Date().getTime()).setHours(23, 59, 59, 59)),
  360. "yyyy-MM-dd hh:mm:ss"
  361. ),
  362. };
  363. typeSelectData = {
  364. userName: user.username,
  365. clientId: null,
  366. };
  367. getStatisticsFun();
  368. // 获取首页公告
  369. getNotice();
  370. // 获取设备情况
  371. getMachineNum();
  372. });
  373. // 设置菜单权限
  374. const menuSet = () => {
  375. const menuList = [];
  376. // 组合菜单权限
  377. user.menuCodeList.forEach((item) => {
  378. for (const key in $M_Menus) {
  379. // 除了设备查看M2,数据概况M14,订单退款M16,系统脱机M17不用加在菜单上
  380. if (
  381. item === key &&
  382. (item !== "M2" &&
  383. item !== "M14" &&
  384. item !== "M16" &&
  385. item !== "M17")
  386. ) {
  387. menuList.push({
  388. label:$M_Menus[key],
  389. value:item
  390. });
  391. }
  392. }
  393. });
  394. // 赋值菜单
  395. pushToolList.value = menuList;
  396. // 查询是否有apk管理
  397. const isApkMan = user.menuCodeList.some((item) => {
  398. return item === "M19";
  399. });
  400. // 查询是否有账号权限
  401. const isAccount = user.menuCodeList.some((item) => {
  402. return item === "M8";
  403. });
  404. // 如果没有apk管理
  405. if (!isApkMan) {
  406. // 如果是公司人,要把apk添加上去
  407. if (user.type === 0 || user.type === 1) {
  408. pushToolList.value.push({
  409. label:t("home.apkMan"),
  410. value:"M19"
  411. });
  412. }
  413. }
  414. // 如果没有账号权限
  415. if(!isAccount){
  416. // 如果是公司人type=0,要把账号权限添加上去
  417. if (user.type === 0) {
  418. pushToolList.value.push({
  419. label:t("home.accountPermission"),
  420. value:"M8"
  421. });
  422. }
  423. }
  424. };
  425. // 常用操作跳转页面
  426. const pushToolPage = (index) => {
  427. switch (index) {
  428. case "M1":
  429. router.push({ path: "/device" });
  430. break;
  431. case "M3":
  432. router.push({ path: "/distributionSet" });
  433. break;
  434. case "M4":
  435. router.push({ path: "/alarmHistory" });
  436. break;
  437. case "M5":
  438. router.push({ path: "/advertManage" });
  439. break;
  440. case "M6":
  441. router.push({ path: "/taskMessage" });
  442. break;
  443. case "M7":
  444. router.push({ path: "/discountCode" });
  445. break;
  446. case "M8":
  447. router.push({ path: "/accountPer" });
  448. break;
  449. case "M9":
  450. router.push({ path: "/orderExport" });
  451. break;
  452. case "M10":
  453. router.push({ path: "/subLedgerManage" });
  454. break;
  455. case "M11":
  456. router.push({ path: "/robotranking" });
  457. break;
  458. case "M12":
  459. router.push({ path: "/joinpayMch" });
  460. break;
  461. case "M13":
  462. router.push({ path: "/shandeMch" });
  463. break;
  464. case "M15":
  465. router.push({ path: "/orderCenter" });
  466. break;
  467. case "M18":
  468. router.push({ path: "/labelMan" });
  469. break;
  470. case "M19":
  471. router.push({ path: "/apkManage" });
  472. break;
  473. case "M20":
  474. router.push({ path: "/merchantManage" });
  475. break;
  476. }
  477. };
  478. // 如果是空数据
  479. const noData = (volumes, nums) => {
  480. if (!volumes && !nums) {
  481. return true;
  482. }
  483. return false;
  484. };
  485. // 显示logo
  486. const showLogo = (url)=>{
  487. return require(`../../assets/home/${url}.png`);
  488. };
  489. return {
  490. userName,
  491. update,
  492. upselectdata,
  493. chartBox,
  494. pushOrderCenter,
  495. pushToolList,
  496. pushToolPage,
  497. salesVolume,
  498. salesNumber,
  499. orderNumber,
  500. sys,
  501. noticeClk,
  502. confirmClk,
  503. kDialogRef,
  504. noData,
  505. equipStatus,
  506. noticeContent,
  507. showLogo,
  508. dateSelect,
  509. $M_FormatTime,
  510. };
  511. },
  512. };
  513. </script>
  514. <style lang="less" scoped >
  515. @import "@/common/style/common.less";
  516. @import "./index.less";
  517. </style>