Browse Source

coding...

刘洋 1 year ago
parent
commit
d83e8903e9

BIN
src/assets/imgs/time.png


+ 107 - 0
src/components/global/custom-date-picker/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <t-date-range-picker v-model="range" :presets="presets" />
+</template>
+<script setup name="CustomDatePicker">
+import { ref, onMounted } from 'vue';
+import dayjs from 'dayjs';
+import { useVModel } from '@vueuse/core';
+const props = defineProps({
+  modelValue: Array,
+});
+const emit = defineEmits(['update:modelValue']);
+
+const range = useVModel(props, 'modelValue', emit);
+
+onMounted(() => {
+  if (!props.modelValue?.length) {
+    range.value = [
+      dayjs().startOf('year').format('YYYY-MM-DD'),
+      dayjs().endOf('year').format('YYYY-MM-DD'),
+    ];
+  }
+});
+
+const presets = ref({
+  本年度: [
+    dayjs().startOf('year').format('YYYY-MM-DD'),
+    dayjs().endOf('year').format('YYYY-MM-DD'),
+  ],
+  上一年度: [
+    dayjs().add(-1, 'year').startOf('year').format('YYYY-MM-DD'),
+    dayjs().add(-1, 'year').endOf('year').format('YYYY-MM-DD'),
+  ],
+  下一年度: [
+    dayjs().add(1, 'year').startOf('year').format('YYYY-MM-DD'),
+    dayjs().add(1, 'year').endOf('year').format('YYYY-MM-DD'),
+  ],
+  上半年度: [
+    dayjs().startOf('year').format('YYYY-MM-DD'),
+    dayjs().endOf('year').subtract(6, 'month').format('YYYY-MM-DD'),
+  ],
+  下半年度: [
+    dayjs().startOf('year').add(6, 'month').format('YYYY-MM-DD'),
+    dayjs().endOf('year').format('YYYY-MM-DD'),
+  ],
+  本季度: [
+    dayjs().startOf('quarter').format('YYYY-MM-DD'),
+    dayjs().endOf('quarter').format('YYYY-MM-DD'),
+  ],
+  上一季度: [
+    dayjs().add(-1, 'quarter').startOf('quarter').format('YYYY-MM-DD'),
+    dayjs().add(-1, 'quarter').endOf('quarter').format('YYYY-MM-DD'),
+  ],
+  下一季度: [
+    dayjs().add(1, 'quarter').startOf('quarter').format('YYYY-MM-DD'),
+    dayjs().add(1, 'quarter').endOf('quarter').format('YYYY-MM-DD'),
+  ],
+  本月: [
+    dayjs().startOf('month').format('YYYY-MM-DD'),
+    dayjs().endOf('month').format('YYYY-MM-DD'),
+  ],
+  上月: [
+    dayjs().add(-1, 'month').startOf('month').format('YYYY-MM-DD'),
+    dayjs().add(-1, 'month').endOf('month').format('YYYY-MM-DD'),
+  ],
+  下月: [
+    dayjs().add(1, 'month').startOf('month').format('YYYY-MM-DD'),
+    dayjs().add(1, 'month').endOf('month').format('YYYY-MM-DD'),
+  ],
+  本周: [
+    dayjs().startOf('week').add(1, 'day').format('YYYY-MM-DD'),
+    dayjs().endOf('week').add(1, 'day').format('YYYY-MM-DD'),
+  ],
+  上周: [
+    dayjs().add(-1, 'week').startOf('week').add(1, 'day').format('YYYY-MM-DD'),
+    dayjs().add(-1, 'week').endOf('week').add(1, 'day').format('YYYY-MM-DD'),
+  ],
+  下周: [
+    dayjs().add(1, 'week').startOf('week').add(1, 'day').format('YYYY-MM-DD'),
+    dayjs().add(1, 'week').endOf('week').add(1, 'day').format('YYYY-MM-DD'),
+  ],
+  今天: [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')],
+  昨天: [
+    dayjs().add(-1, 'day').format('YYYY-MM-DD'),
+    dayjs().add(-1, 'day').format('YYYY-MM-DD'),
+  ],
+  明天: [
+    dayjs().add(1, 'day').format('YYYY-MM-DD'),
+    dayjs().add(1, 'day').format('YYYY-MM-DD'),
+  ],
+  过去7天: [
+    dayjs().add(-7, 'day').format('YYYY-MM-DD'),
+    dayjs().format('YYYY-MM-DD'),
+  ],
+  过去30天: [
+    dayjs().add(-30, 'day').format('YYYY-MM-DD'),
+    dayjs().format('YYYY-MM-DD'),
+  ],
+  未来7天: [
+    dayjs().format('YYYY-MM-DD'),
+    dayjs().add(7, 'day').format('YYYY-MM-DD'),
+  ],
+  未来30天: [
+    dayjs().format('YYYY-MM-DD'),
+    dayjs().add(30, 'day').format('YYYY-MM-DD'),
+  ],
+});
+</script>

+ 75 - 0
src/components/global/report-header/index.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="report-header flex items-center justify-between">
+    <div class="title">{{ props.title }}</div>
+    <div class="right-box flex h-full items-center">
+      <CustomDatePicker v-model="range"></CustomDatePicker>
+      <img class="time-icon" src="../../../assets//imgs/time.png" />
+      <p>{{ timeText }} &nbsp; {{ getCurrentWeek() }}</p>
+    </div>
+  </div>
+</template>
+<script setup name="ReportHeader">
+import { ref, computed, onBeforeUnmount, onMounted } from 'vue';
+import { useIntervalFn } from '@vueuse/core';
+import { dateFormat } from '@/utils/tool';
+import { useVModel } from '@vueuse/core';
+import CustomDatePicker from '../custom-date-picker';
+const emit = defineEmits(['update:dateRange']);
+const props = defineProps({ title: String, dateRange: Array });
+const range = useVModel(props, 'dateRange', emit);
+const currentTime = ref(Date.now());
+const updateTime = () => {
+  currentTime.value = new Date().getTime();
+};
+const timeText = computed(() => {
+  return dateFormat(currentTime.value, `yyyy年MM月dd日 HH:mm:ss`);
+});
+const weeks = ref([
+  '星期天',
+  '星期一',
+  '星期二',
+  '星期三',
+  '星期四',
+  '星期五',
+  '星期六',
+]);
+const getCurrentWeek = () => {
+  return weeks.value[new Date().getDay()];
+};
+const { pause, resume, isActive } = useIntervalFn(
+  () => {
+    updateTime();
+  },
+  1000,
+  { immediate: false }
+);
+onMounted(() => {
+  resume();
+});
+onBeforeUnmount(() => {
+  pause();
+});
+</script>
+<style lang="less" scoped>
+.report-header {
+  height: 57px;
+  padding: 0 16px;
+  background-color: #fff;
+  border-bottom: 1px solid #e5e5e5;
+  .title {
+    color: #262626;
+    font-size: 16px;
+    font-weight: bold;
+  }
+  .right-box {
+    .time-icon {
+      height: 20px;
+      margin-right: 10px;
+    }
+    & > p {
+      color: #595959;
+      font-size: 14px;
+    }
+  }
+}
+</style>

+ 1 - 1
src/router/asyncRoutes.js

@@ -112,7 +112,7 @@ export const devPushMenuList = [
   },
   {
     id: '2001',
-    name: '数据驾驶舱',
+    name: '派单分析',
     parentId: '2000',
     url: 'test1',
     sort: 1,

+ 2 - 2
src/router/modules/report.js

@@ -5,7 +5,7 @@ export default {
     title: '数据驾驶舱',
     sort: 9,
     isModule: true,
-    alias: '',
+    alias: 'test',
     icon: 'work',
   },
   children: [
@@ -16,7 +16,7 @@ export default {
       meta: {
         title: '派单分析',
         sort: 1,
-        alias: '',
+        alias: 'test1',
         icon: 'notice',
       },
     },

+ 5 - 1
src/store/modules/user.js

@@ -113,7 +113,11 @@ const useUserStore = defineStore('user', {
       const data = item?.children || [];
       let moduleMenus = [];
       data.forEach((item) => {
-        moduleMenus.push({ ...omit(item, ['children']), disabled: true });
+        // moduleMenus.push({ ...omit(item, ['children']), disabled: true });
+        moduleMenus.push({
+          ...omit(item, ['children']),
+          disabled: !!item.children,
+        });
         if (item.children && item.children.length) {
           item.children.forEach((elem) => {
             moduleMenus.push({ ...elem, disabled: false });

+ 75 - 0
src/style/tdesign-reset.css

@@ -0,0 +1,75 @@
+:root,
+:root[theme-mode='light'] {
+  --td-brand-color: #165dff;
+  --td-warning-color: #ff7d00;
+  --td-error-color: #f53f3f;
+  --td-success-color: #00b42a;
+}
+.t-dialog--default {
+  padding-top: 20px;
+}
+.t-dialog__body {
+  padding-top: 25px;
+  overflow: initial;
+}
+.t-dialog__body .t-form__label,
+.t-drawer__body .t-form__label {
+  color: #595959;
+  padding-right: 8px;
+}
+.t-date-picker__panel .t-pagination-mini .t-pagination-mini__current {
+  display: none;
+}
+.t-dialog__ctx .t-dialog__position.t-dialog--top {
+  padding: 0;
+  align-items: center;
+}
+.t-table__empty-row > td {
+  padding: 0 !important;
+}
+.t-table__empty-row > td .t-table__empty {
+  min-height: 40px;
+}
+.t-head-menu__inner .t-menu:first-child {
+  margin-left: 0;
+}
+.t-col > .t-form__item {
+  width: 100%;
+  margin-right: 0;
+}
+.t-form__item .t-date-picker {
+  width: 100%;
+}
+.t-select.t-select-input--multiple .t-input__prefix {
+  display: flex !important;
+  overflow: auto;
+}
+.t-button:not(.t-button--icon-only) .svg-icon {
+  margin-right: 8px;
+}
+.t-button .svg-icon {
+  width: 13px;
+  height: 13px;
+}
+.t-button.t-size-s .svg-icon {
+  width: 11px;
+  height: 11px;
+}
+.t-button.t-button--theme-default:hover .svg-icon use {
+  fill: #165dff;
+}
+.t-button--theme-default.t-is-disabled .svg-icon use {
+  fill: #00000042 !important;
+}
+.t-button--theme-primary.t-is-disabled .svg-icon use {
+  fill: #fff !important;
+}
+.t-link--theme-primary.t-is-disabled {
+  color: #b0b0b0 !important;
+}
+.t-date-range-picker__panel .t-date-picker__presets {
+  width: 560px;
+  overflow: auto;
+  display: block;
+  padding-bottom: 10px;
+}

+ 7 - 0
src/style/tdesign-reset.less

@@ -94,3 +94,10 @@
 .t-link--theme-primary.t-is-disabled {
   color: #b0b0b0 !important;
 }
+
+.t-date-range-picker__panel .t-date-picker__presets {
+  width: 560px;
+  overflow: auto;
+  display: block;
+  padding-bottom: 10px;
+}

+ 4 - 1
src/views/login/forget-pwd.vue

@@ -70,7 +70,7 @@
 </template>
 
 <script setup name="ForgetPwd">
-import { reactive, ref } from 'vue';
+import { reactive, ref, onBeforeUnmount } from 'vue';
 import { clear } from '@/utils/tool';
 import { useIntervalFn } from '@vueuse/core';
 import { MessagePlugin } from 'tdesign-vue-next';
@@ -101,6 +101,9 @@ const { pause, resume, isActive } = useIntervalFn(
   1000,
   { immediate: false }
 );
+onBeforeUnmount(() => {
+  pause();
+});
 const getCode = () => {
   if (!formData.mobileNumber) {
     MessagePlugin.error('请先输入手机号');

+ 4 - 1
src/views/login/index.vue

@@ -121,7 +121,7 @@
 </template>
 
 <script setup name="Login">
-import { ref, reactive } from 'vue';
+import { ref, reactive, onBeforeUnmount } from 'vue';
 import { RollbackIcon } from 'tdesign-icons-vue-next';
 import { useRoute, useRouter } from 'vue-router';
 import { useUserStore, useAppStore } from '@/store';
@@ -152,6 +152,9 @@ const { pause, resume, isActive } = useIntervalFn(
   1000,
   { immediate: false }
 );
+onBeforeUnmount(() => {
+  pause();
+});
 const getCode = () => {
   if (!formData2.mobileNumber) {
     MessagePlugin.error('请先输入手机号');

+ 101 - 3
src/views/report/dispatch-analysis/index.vue

@@ -1,7 +1,105 @@
 <template>
-  <div class="dispatch-analysis"> 派单分析</div>
+  <div class="dispatch-analysis">
+    <report-header
+      title="派单分析"
+      v-model:dateRange="curTimeRange"
+    ></report-header>
+    <div class="page-main">
+      <div class="row1 flex">
+        <div class="col1">
+          <div class="card chart1-box">
+            <!-- <div class="flex justify-between items-center"> -->
+            <span class="title">客户类型</span>
+            <!-- <custom-date-picker v-model="curTimeRange"></custom-date-picker> -->
+            <!-- </div> -->
+          </div>
+          <div class="card chart2-box"></div>
+        </div>
+        <div class="col2 flex-1"></div>
+        <div class="col3">
+          <div class="card chart4-box"></div>
+          <div class="card chart5-box"></div>
+        </div>
+      </div>
+      <div class="row2 flex">
+        <div class="col1">
+          <div class="card chart6-box"></div>
+        </div>
+        <div class="col2 flex-1">
+          <div class="card chart7-box"></div>
+        </div>
+        <div class="col3">
+          <div class="card chart8-box"></div>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
-<script setup name="DispatchAnalysis"></script>
+<script setup name="DispatchAnalysis">
+import { ref } from 'vue';
+const curTimeRange = ref([]);
+</script>
 
-<style lang="scss" scoped></style>
+<style lang="less" scoped>
+.dispatch-analysis {
+  .page-main {
+    height: calc(100vh - 57px);
+    padding: 15px;
+    .row1 {
+      height: calc((100% - 30px) * 2 / 3 + 15px);
+    }
+    .row2 {
+      height: calc((100% - 30px) / 3);
+      margin-top: 15px;
+    }
+    .col1,
+    .col3 {
+      width: 268px;
+      height: calc((100% - 30px) * 2 / 3 + 15px);
+    }
+    .col2 {
+      width: calc(100% - 566px);
+      margin-left: 15px;
+      margin-right: 15px;
+    }
+    .row2 {
+      .col1,
+      .col3 {
+        height: 100%;
+        .card {
+          height: 100%;
+        }
+      }
+    }
+    .row1 {
+      .col1,
+      .col3 {
+        height: 100%;
+        .card {
+          height: calc((100% - 15px) / 2);
+          &:not(:first-child) {
+            margin-top: 15px;
+          }
+        }
+      }
+    }
+    .row2 {
+      .card {
+        height: 100%;
+      }
+    }
+    .card {
+      padding: 10px;
+      background-color: #fff;
+      border: 1px solid #e5e5e5;
+      border-radius: 4px;
+      .title {
+        color: #262626;
+        font-size: 14px;
+        font-weight: bold;
+      }
+    }
+  }
+}
+</style>