Bläddra i källkod

refactor(dashboard): 重构仪表盘页面

- 移除了多个无用的仪表盘组件
- 新增 Line 组件用于展示折线图
- 更新了环境变量配置
- 优化了表格组件的代码结构
zhangtao 4 veckor sedan
förälder
incheckning
8f216dd7bb

+ 4 - 4
.env.development

@@ -7,16 +7,16 @@ VITE_PUBLIC_PATH = /
 
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
-VITE_PROXY = [["/jeecgboot","http://192.168.1.34:8080/jeecg-boot"],["/upload","http://192.168.1.34:8080/jeecg-boot"]]
+# VITE_PROXY = [["/jeecgboot","http://192.168.1.34:8080/jeecg-boot"],["/upload","http://192.168.1.34:8080/jeecg-boot"]]
 # VITE_PROXY = [["/jeecgboot","http://192.168.0.11:8080/jeecg-boot"],["/upload","http://192.168.0.11:8080/upload"]]
 # VITE_PROXY = [["/jeecgboot","http://192.168.1.253:8080/jeecg-boot"],["/upload","http://192.168.1.253:8080/upload"]]
-# VITE_PROXY = [["/jeecgboot","http://192.168.1.166:8080/jeecg-boot"],["/upload","http://192.168.1.166:8080/upload"]]
+VITE_PROXY = [["/jeecgboot","http://192.168.1.166:8080/jeecg-boot"],["/upload","http://192.168.1.166:8080/upload"]]
 
 #后台接口全路径地址(必填)
-VITE_GLOB_DOMAIN_URL=http://192.168.1.34:8080/jeecg-boot #//黄、
+# VITE_GLOB_DOMAIN_URL=http://192.168.1.34:8080/jeecg-boot #//黄、
 # VITE_GLOB_DOMAIN_URL=http://192.168.0.11:8080/jeecg-boot  #李
 # VITE_GLOB_DOMAIN_URL=http://192.168.1.253:8080/jeecg-boot  #张
-# VITE_GLOB_DOMAIN_URL=http://192.168.1.166:8080/jeecg-boot  #张
+VITE_GLOB_DOMAIN_URL=http://192.168.1.166:8080/jeecg-boot  #张
 
 
 #后台接口父地址(必填)

+ 2 - 2
src/components/ZtCustomTable/index.vue

@@ -96,7 +96,7 @@
     const newRow: DataRow = {};
     inputFields.forEach((field) => {
       newRow[String(field)] = null;
-      newRow['id'] = dayjs().valueOf();
+      newRow['rowId'] = dayjs().valueOf();
     });
     return newRow;
   };
@@ -113,6 +113,6 @@
     }
   }
   function handleKey(row) {
-    return row.id;
+    return row.rowId;
   }
 </script>

+ 2 - 1
src/views/businessManagement/competition/competitionCommon.vue

@@ -113,7 +113,6 @@
       };
     });
     console.log(form, '表单数据');
-
     if (!valiDataCustom(gamePriceRules) || !valiDataCustom(scheduleRules)) {
       return message.error('请填写完整');
     }
@@ -138,6 +137,8 @@
         };
       }),
     };
+    console.log(newObj, '表单数据');
+
     isSubmit.value = true;
     try {
       await saveOrUpdate(newObj, Number(route.query.type) == 1);

+ 1 - 1
src/views/businessManagement/courses/courses.data.ts

@@ -232,7 +232,7 @@ export const formSchema: FormSchema[] = [
   {
     label: '使用须知',
     field: 'reminder',
-    component: 'InputTextArea',
+    component: 'JEditor',
     required: true,
   },
   {

+ 3 - 0
src/views/dashboard/Analysis/api.ts

@@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
 enum Api {
   loginfo = '/sys/loginfo',
   visitInfo = '/sys/visitInfo',
+  indexData = '/statisticsInfo/findByStatistics',
 }
 /**
  * 日志统计信息
@@ -14,3 +15,5 @@ export const getLoginfo = (params) => defHttp.get({ url: Api.loginfo, params },
  * @param params
  */
 export const getVisitInfo = (params) => defHttp.get({ url: Api.visitInfo, params }, { isTransformResponse: false });
+
+export const getIndexData = () => defHttp.get({ url: Api.indexData });

+ 0 - 110
src/views/dashboard/Analysis/components/BdcTabCard.vue

@@ -1,110 +0,0 @@
-<template>
-  <a-card :loading="loading" :bordered="false" :body-style="{ padding: '0' }">
-    <div class="salesCard">
-      <a-tabs default-active-key="1" size="large" :tab-bar-style="{ marginBottom: '24px', paddingLeft: '16px' }">
-        <template #rightExtra>
-          <div class="extra-wrapper">
-            <div class="extra-item">
-              <a>今日</a>
-              <a>本周</a>
-              <a>本月</a>
-              <a>本年</a>
-            </div>
-            <a-range-picker :style="{ width: '256px' }" />
-          </div>
-        </template>
-        <a-tab-pane loading="true" tab="受理监管" key="1">
-          <a-row>
-            <a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
-              <QuickNav :loading="loading" class="enter-y" :bordered="false" :body-style="{ padding: 0 }" />
-            </a-col>
-          </a-row>
-        </a-tab-pane>
-        <a-tab-pane tab="交互监管" key="2">
-          <a-row>
-            <a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
-              <QuickNav :loading="loading" class="enter-y" :bordered="false" :body-style="{ padding: 0 }" />
-            </a-col>
-          </a-row>
-        </a-tab-pane>
-        <a-tab-pane tab="存储监管" key="3">
-          <a-row>
-            <a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
-              <QuickNav :loading="loading" class="enter-y" :bordered="false" :body-style="{ padding: 0 }" />
-            </a-col>
-          </a-row>
-        </a-tab-pane>
-      </a-tabs>
-    </div>
-  </a-card>
-</template>
-<script lang="ts" setup>
-  import { ref, computed } from 'vue';
-  import QuickNav from './QuickNav.vue';
-  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
-
-  defineProps({
-    loading: {
-      type: Boolean,
-    },
-  });
-  const { getThemeColor } = useRootSetting();
-  const interactiveColor = ref();
-  const rankList = [];
-  for (let i = 0; i < 7; i++) {
-    rankList.push({
-      name: '白鹭岛 ' + (i + 1) + ' 号店',
-      total: 1234.56 - i * 100,
-    });
-  }
-
-  const barData = [];
-  for (let i = 0; i < 12; i += 1) {
-    barData.push({
-      name: `${i + 1}月`,
-      value: Math.floor(Math.random() * 1000) + 200,
-    });
-  }
-  const barMultiData = [];
-  for (let j = 0; j < 2; j++) {
-    for (let i = 0; i < 12; i += 1) {
-      barMultiData.push({
-        type: j == 0 ? 'jeecg' : 'jeebt',
-        name: `${i + 1}月`,
-        value: Math.floor(Math.random() * 1000) + 200,
-      });
-    }
-  }
-
-  const seriesColor = computed(() => {
-    interactiveColor.value = [
-      { type: 'jeecg', color: getThemeColor.value },
-      { type: 'jeebt', color: getRandomColor() },
-    ];
-    return getThemeColor.value;
-  });
-  function getRandomColor() {
-    var letters = '0123456789ABCDEF';
-    var color = '#';
-    for (var i = 0; i < 6; i++) {
-      color += letters[Math.floor(Math.random() * 16)];
-    }
-    return color;
-  }
-</script>
-
-<style lang="less" scoped>
-  .extra-wrapper {
-    line-height: 55px;
-    padding-right: 24px;
-
-    .extra-item {
-      display: inline-block;
-      margin-right: 24px;
-
-      a {
-        margin-left: 24px;
-      }
-    }
-  }
-</style>

+ 0 - 40
src/views/dashboard/Analysis/components/GrowCard.vue

@@ -1,40 +0,0 @@
-<template>
-  <div class="md:flex">
-    <template v-for="(item, index) in growCardList" :key="item.title">
-      <Card
-        size="small"
-        :loading="loading"
-        :title="item.title"
-        class="md:w-1/4 w-full !md:mt-0 !mt-4"
-        :class="[index + 1 < 4 && '!md:mr-4']"
-        :canExpan="false"
-      >
-        <template #extra>
-          <Tag :color="item.color">{{ item.action }}</Tag>
-        </template>
-
-        <div class="py-4 px-4 flex justify-between">
-          <CountTo prefix="$" :startVal="1" :endVal="item.value" class="text-2xl" />
-          <Icon :icon="item.icon" :size="40" />
-        </div>
-
-        <div class="p-2 px-4 flex justify-between">
-          <span>总{{ item.title }}</span>
-          <CountTo prefix="$" :startVal="1" :endVal="item.total" />
-        </div>
-      </Card>
-    </template>
-  </div>
-</template>
-<script lang="ts" setup>
-  import { CountTo } from '/@/components/CountTo/index';
-  import { Icon } from '/@/components/Icon';
-  import { Tag, Card } from 'ant-design-vue';
-  import { growCardList } from '../data';
-
-  defineProps({
-    loading: {
-      type: Boolean,
-    },
-  });
-</script>

+ 81 - 0
src/views/dashboard/Analysis/components/Line.vue

@@ -0,0 +1,81 @@
+<template>
+  <div ref="chartRef" :style="{ height, width }"></div>
+</template>
+<script lang="ts">
+  import { defineComponent, PropType, ref, Ref, onMounted, nextTick } from 'vue';
+  import { useECharts } from '/@/hooks/web/useECharts';
+  import dayjs from 'dayjs';
+  function generateCurrentMonthDays(chartData: any[] = []) {
+    const days: any = [];
+    const values: any[] = [];
+    const daysInMonth = dayjs().daysInMonth();
+
+    // 创建一个映射,将dateDailyDate作为键,对应的数值作为值
+    const dataMap: Record<string, number> = {};
+    chartData.forEach((item) => {
+      if (item.dateDailyDate) {
+        dataMap[item.dateDailyDate] = item.expectIncomeMoney || 0;
+      }
+    });
+    console.log(dataMap, 'dataMap');
+
+    for (let i = 1; i <= daysInMonth; i++) {
+      const dayStr = `${String(dayjs().month() + 1).padStart(2, '0')}/${String(i).padStart(2, '0')}`;
+      const formattedDayStr = `${dayjs().month() + 1}/${i}`;
+      days.push(formattedDayStr);
+      values.push(dataMap[dayStr] || null);
+    }
+    return { days, values };
+  }
+  export default defineComponent({
+    props: {
+      width: {
+        type: String as PropType<string>,
+        default: '100%',
+      },
+      height: {
+        type: String as PropType<string>,
+        default: 'calc(100vh - 78px)',
+      },
+      chartData: {
+        type: Array as PropType<Array<any>>,
+        default: () => [],
+      },
+    },
+    setup(ctx) {
+      const chartRef = ref<HTMLDivElement | null>(null);
+      const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
+      const { days, values } = generateCurrentMonthDays(ctx.chartData);
+      console.log(days, values);
+
+      onMounted(() => {
+        setOptions({
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'cross',
+              label: {
+                backgroundColor: '#6a7985',
+              },
+            },
+          },
+          xAxis: {
+            data: days,
+          },
+          yAxis: {
+            axisLine: {},
+          },
+          series: [
+            {
+              name: '销售额',
+              type: 'line',
+              data: values,
+              connectNulls: true,
+            },
+          ],
+        });
+      });
+      return { chartRef };
+    },
+  });
+</script>

+ 0 - 56
src/views/dashboard/Analysis/components/QuickNav.vue

@@ -1,56 +0,0 @@
-<template>
-  <Card title="快捷导航" v-bind="$attrs">
-    <template v-for="item in navItems" :key="item">
-      <CardGrid @click="goPage">
-        <span class="flex flex-col items-center">
-          <Icon :icon="item.icon" :color="item.color" size="20" />
-          <span class="text-md mt-2">{{ item.title }}</span>
-        </span>
-      </CardGrid>
-    </template>
-  </Card>
-</template>
-<script lang="ts" setup>
-  import { Card } from 'ant-design-vue';
-  import { useMessage } from '/@/hooks/web/useMessage';
-  import { Icon } from '/@/components/Icon';
-
-  const CardGrid = Card.Grid;
-  const $message = useMessage();
-  const navItems = [
-    {
-      title: '业务受理',
-      icon: 'ion:home-outline',
-      color: '#1fdaca',
-    },
-    {
-      title: '业务管理',
-      icon: 'ion:grid-outline',
-      color: '#bf0c2c',
-    },
-    {
-      title: '文件管理',
-      icon: 'ion:layers-outline',
-      color: '#e18525',
-    },
-    {
-      title: '信息查询',
-      icon: 'ion:settings-outline',
-      color: '#3fb27f',
-    }, 
-		{
-				title: '通知公告',
-				icon: 'ion:notifications',
-				color: '#13b0ff',
-		}, 
-		{
-				title: '我的任务',
-				icon: 'ion:person-stalker',
-				color: '#b27315',
-		}
-  ];
-
-  function goPage() {
-    $message.createMessage.success('根据业务自行处理跳转页面!');
-  }
-</script>

+ 0 - 63
src/views/dashboard/Analysis/components/SalesProductPie.vue

@@ -1,63 +0,0 @@
-<template>
-  <Card title="成交占比" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts" setup>
-  import { Ref, ref, watch } from 'vue';
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  const props = defineProps({
-    loading: Boolean,
-    width: {
-      type: String as PropType<string>,
-      default: '100%',
-    },
-    height: {
-      type: String as PropType<string>,
-      default: '300px',
-    },
-  });
-
-  const chartRef = ref<HTMLDivElement | null>(null);
-  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-  watch(
-    () => props.loading,
-    () => {
-      if (props.loading) {
-        return;
-      }
-      setOptions({
-        tooltip: {
-          trigger: 'item',
-        },
-
-        series: [
-          {
-            name: '访问来源',
-            type: 'pie',
-            radius: '80%',
-            center: ['50%', '50%'],
-            color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
-            data: [
-              { value: 500, name: '电子产品' },
-              { value: 310, name: '服装' },
-              { value: 274, name: '化妆品' },
-              { value: 400, name: '家居' },
-            ].sort(function (a, b) {
-              return a.value - b.value;
-            }),
-            roseType: 'radius',
-            animationType: 'scale',
-            animationEasing: 'exponentialInOut',
-            animationDelay: function () {
-              return Math.random() * 400;
-            },
-          },
-        ],
-      });
-    },
-    { immediate: true }
-  );
-</script>

+ 0 - 33
src/views/dashboard/Analysis/components/SiteAnalysis.vue

@@ -1,33 +0,0 @@
-<template>
-  <Card :tab-list="tabListTitle" v-bind="$attrs" :active-tab-key="activeKey" @tabChange="onTabChange">
-    <p v-if="activeKey === 'tab1'">
-      <VisitAnalysis />
-    </p>
-    <p v-if="activeKey === 'tab2'">
-      <VisitAnalysisBar />
-    </p>
-  </Card>
-</template>
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import { Card } from 'ant-design-vue';
-  import VisitAnalysis from './VisitAnalysis.vue';
-  import VisitAnalysisBar from './VisitAnalysisBar.vue';
-
-  const activeKey = ref('tab1');
-
-  const tabListTitle = [
-    {
-      key: 'tab1',
-      tab: '流量趋势',
-    },
-    {
-      key: 'tab2',
-      tab: '访问量',
-    },
-  ];
-
-  function onTabChange(key) {
-    activeKey.value = key;
-  }
-</script>

+ 0 - 104
src/views/dashboard/Analysis/components/VisitAnalysis.vue

@@ -1,104 +0,0 @@
-<template>
-  <div ref="chartRef" :style="{ height, width }"></div>
-</template>
-<script lang="ts" setup>
-  import { onMounted, ref, Ref, watchEffect } from 'vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-  import { basicProps } from './props';
-  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
-  defineProps({
-    ...basicProps,
-  });
-  const chartRef = ref<HTMLDivElement | null>(null);
-  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-
-  const { getThemeColor } = useRootSetting();
-  const init = () => {
-    setOptions({
-      tooltip: {
-        trigger: 'axis',
-        axisPointer: {
-          lineStyle: {
-            width: 1,
-            color: getThemeColor.value,
-          },
-        },
-      },
-      xAxis: {
-        type: 'category',
-        boundaryGap: false,
-        data: [
-          '6:00',
-          '7:00',
-          '8:00',
-          '9:00',
-          '10:00',
-          '11:00',
-          '12:00',
-          '13:00',
-          '14:00',
-          '15:00',
-          '16:00',
-          '17:00',
-          '18:00',
-          '19:00',
-          '20:00',
-          '21:00',
-          '22:00',
-          '23:00',
-        ],
-        splitLine: {
-          show: true,
-          lineStyle: {
-            width: 1,
-            type: 'solid',
-            color: 'rgba(226,226,226,0.5)',
-          },
-        },
-        axisTick: {
-          show: false,
-        },
-      },
-      yAxis: [
-        {
-          type: 'value',
-          max: 80000,
-          splitNumber: 4,
-          axisTick: {
-            show: false,
-          },
-          splitArea: {
-            show: true,
-            areaStyle: {
-              color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'],
-            },
-          },
-        },
-      ],
-      grid: { left: '1%', right: '1%', top: '2  %', bottom: 0, containLabel: true },
-      series: [
-        {
-          smooth: true,
-          data: [111, 222, 4000, 18000, 33333, 55555, 66666, 33333, 14000, 36000, 66666, 44444, 22222, 11111, 4000, 2000, 500, 333, 222, 111],
-          type: 'line',
-          areaStyle: {},
-          itemStyle: {
-            color: '#5ab1ef',
-          },
-        },
-        {
-          smooth: true,
-          data: [33, 66, 88, 333, 3333, 5000, 18000, 3000, 1200, 13000, 22000, 11000, 2221, 1201, 390, 198, 60, 30, 22, 11],
-          type: 'line',
-          areaStyle: {},
-          itemStyle: {
-            color: getThemeColor.value,
-          },
-        },
-      ],
-    });
-  };
-  watchEffect(() => {
-    init();
-  });
-</script>

+ 0 - 51
src/views/dashboard/Analysis/components/VisitAnalysisBar.vue

@@ -1,51 +0,0 @@
-<template>
-  <div ref="chartRef" :style="{ height, width }"></div>
-</template>
-<script lang="ts" setup>
-  import { onMounted, ref, Ref, watchEffect } from 'vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-  import { basicProps } from './props';
-  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
-
-  defineProps({
-    ...basicProps,
-  });
-
-  const chartRef = ref<HTMLDivElement | null>(null);
-  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-  const { getThemeColor } = useRootSetting();
-  const init = () => {
-    setOptions({
-      tooltip: {
-        trigger: 'axis',
-        axisPointer: {
-          lineStyle: {
-            width: 1,
-            color: getThemeColor.value,
-          },
-        },
-      },
-      grid: { left: '1%', right: '1%', top: '2  %', bottom: 0, containLabel: true },
-      xAxis: {
-        type: 'category',
-        data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
-      },
-      yAxis: {
-        type: 'value',
-        max: 8000,
-        splitNumber: 4,
-      },
-      series: [
-        {
-          data: [3000, 2000, 3333, 5000, 3200, 4200, 3200, 2100, 3000, 5100, 6000, 3200, 4800],
-          type: 'bar',
-          barMaxWidth: 80,
-          color: getThemeColor.value,
-        },
-      ],
-    });
-  };
-  watchEffect(() => {
-    init();
-  });
-</script>

+ 0 - 94
src/views/dashboard/Analysis/components/VisitRadar.vue

@@ -1,94 +0,0 @@
-<template>
-  <Card title="转化率" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts" setup>
-  import { Ref, ref, watch } from 'vue';
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-
-  const props = defineProps({
-    loading: Boolean,
-    width: {
-      type: String as PropType<string>,
-      default: '100%',
-    },
-    height: {
-      type: String as PropType<string>,
-      default: '300px',
-    },
-  });
-
-  const chartRef = ref<HTMLDivElement | null>(null);
-  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-  watch(
-    () => props.loading,
-    () => {
-      if (props.loading) {
-        return;
-      }
-      setOptions({
-        legend: {
-          bottom: 0,
-          data: ['访问', '购买'],
-        },
-        tooltip: {},
-        radar: {
-          radius: '60%',
-          splitNumber: 8,
-          indicator: [
-            {
-              name: '电脑',
-            },
-            {
-              name: '充电器',
-            },
-            {
-              name: '耳机',
-            },
-            {
-              name: '手机',
-            },
-            {
-              name: 'Ipad',
-            },
-            {
-              name: '耳机',
-            },
-          ],
-        },
-        series: [
-          {
-            type: 'radar' as 'custom',
-            symbolSize: 0,
-            areaStyle: {
-              shadowBlur: 0,
-              shadowColor: 'rgba(0,0,0,.2)',
-              shadowOffsetX: 0,
-              shadowOffsetY: 10,
-              opacity: 1,
-            },
-            data: [
-              {
-                value: [90, 50, 86, 40, 50, 20],
-                name: '访问',
-                itemStyle: {
-                  color: '#b6a2de',
-                },
-              },
-              {
-                value: [70, 75, 70, 76, 20, 85],
-                name: '购买',
-                itemStyle: {
-                  color: '#5ab1ef',
-                },
-              },
-            ],
-          },
-        ],
-      });
-    },
-    { immediate: true }
-  );
-</script>

+ 0 - 80
src/views/dashboard/Analysis/components/VisitSource.vue

@@ -1,80 +0,0 @@
-<template>
-  <Card title="访问来源" :loading="loading">
-    <div ref="chartRef" :style="{ width, height }"></div>
-  </Card>
-</template>
-<script lang="ts" setup>
-  import { Ref, ref, watch } from 'vue';
-  import { Card } from 'ant-design-vue';
-  import { useECharts } from '/@/hooks/web/useECharts';
-  const props = defineProps({
-    loading: Boolean,
-    width: {
-      type: String as PropType<string>,
-      default: '100%',
-    },
-    height: {
-      type: String as PropType<string>,
-      default: '300px',
-    },
-  });
-  const chartRef = ref<HTMLDivElement | null>(null);
-  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
-  watch(
-    () => props.loading,
-    () => {
-      if (props.loading) {
-        return;
-      }
-      setOptions({
-        tooltip: {
-          trigger: 'item',
-        },
-        legend: {
-          bottom: '1%',
-          left: 'center',
-        },
-        series: [
-          {
-            color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
-            name: '访问来源',
-            type: 'pie',
-            radius: ['40%', '70%'],
-            avoidLabelOverlap: false,
-            itemStyle: {
-              borderRadius: 10,
-              borderColor: '#fff',
-              borderWidth: 2,
-            },
-            label: {
-              show: false,
-              position: 'center',
-            },
-            emphasis: {
-              label: {
-                show: true,
-                fontSize: '12',
-                fontWeight: 'bold',
-              },
-            },
-            labelLine: {
-              show: false,
-            },
-            data: [
-              { value: 1048, name: '搜索引擎' },
-              { value: 735, name: '直接访问' },
-              { value: 580, name: '邮件营销' },
-              { value: 484, name: '联盟广告' },
-            ],
-            animationType: 'scale',
-            animationEasing: 'exponentialInOut',
-            animationDelay: function () {
-              return Math.random() * 100;
-            },
-          },
-        ],
-      });
-    },
-    { immediate: true }
-  );
-</script>

+ 0 - 16
src/views/dashboard/Analysis/components/props.ts

@@ -1,16 +0,0 @@
-import { PropType } from 'vue';
-
-export interface BasicProps {
-  width: string;
-  height: string;
-}
-export const basicProps = {
-  width: {
-    type: String as PropType<string>,
-    default: '100%',
-  },
-  height: {
-    type: String as PropType<string>,
-    default: '280px',
-  },
-};

+ 0 - 242
src/views/dashboard/Analysis/homePage/IndexBdc.vue

@@ -1,242 +0,0 @@
-<template>
-  <div class="p-4">
-    <ChartGroupCard class="enter-y" :loading="loading" type="bdc" />
-    <BdcTabCard class="!my-4 enter-y" :loading="loading" />
-    <a-row>
-      <a-col :span="24">
-        <a-card :loading="loading" :class="{ 'anty-list-cust': true }" :bordered="false">
-          <a-tabs v-model:activeKey="indexBottomTab" size="large" :tab-bar-style="{ marginBottom: '24px', paddingLeft: '16px' }">
-            <template #rightExtra>
-              <div class="extra-wrapper">
-                <a-radio-group v-model:value="indexRegisterType" @change="changeRegisterType">
-                  <a-radio-button value="转移登记">转移登记</a-radio-button>
-                  <a-radio-button value="抵押登记">抵押登记</a-radio-button>
-                  <a-radio-button value="">所有</a-radio-button>
-                </a-radio-group>
-              </div>
-            </template>
-
-            <a-tab-pane tab="业务流程限时监管" key="1">
-              <a-table
-                :dataSource="dataSource"
-                size="default"
-                rowKey="reBizCode"
-                :columns="table.columns"
-                :pagination="ipagination"
-                @change="tableChange"
-              >
-                <template #bodyCell="{ column, record }">
-                  <template v-if="column.dataIndex === 'flowRate'">
-                    <Progress
-                      :strokeColor="getPercentColor(record.flowRate)"
-                      :format="getPercentFormat"
-                      :percent="getFlowRateNumber(record.flowRate)"
-                      style="width: 80px"
-                    />
-                  </template>
-                </template>
-              </a-table>
-            </a-tab-pane>
-
-            <a-tab-pane loading="true" tab="业务节点限时监管" key="2">
-              <a-table
-                :dataSource="dataSource1"
-                size="default"
-                rowKey="reBizCode"
-                :columns="table1.columns"
-                :pagination="ipagination1"
-                @change="tableChange1"
-              >
-                <template #bodyCell="{ column, record }">
-                  <template v-if="column.dataIndex === 'flowRate'">
-                    <span style="color: red">{{ record.flowRate }}小时</span>
-                  </template>
-                </template>
-              </a-table>
-            </a-tab-pane>
-          </a-tabs>
-        </a-card>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-<script lang="ts" setup>
-  import { ref, unref } from 'vue';
-  import { Progress } from 'ant-design-vue';
-  import BdcTabCard from '../components/BdcTabCard.vue';
-  import { table, table1 } from '../data';
-
-  const loading = ref(true);
-
-  setTimeout(() => {
-    loading.value = false;
-  }, 500);
-
-  const indexBottomTab = ref('1');
-  const indexRegisterType = ref('转移登记');
-  const dataSource = ref([]);
-  const dataSource1 = ref([]);
-  const ipagination = ref(table.ipagination);
-  const ipagination1 = ref(table1.ipagination);
-
-  function changeRegisterType(e) {
-    indexRegisterType.value = e.target.value;
-    if (unref(indexBottomTab) == '1') {
-      loadDataSource();
-    } else {
-      loadDataSource1();
-    }
-  }
-
-  function tableChange(pagination) {
-    ipagination.value.current = pagination.current;
-    ipagination.value.pageSize = pagination.pageSize;
-    loadDataSource();
-  }
-
-  function tableChange1(pagination) {
-    ipagination1.value.current = pagination.current;
-    ipagination1.value.pageSize = pagination.pageSize;
-    loadDataSource1();
-  }
-
-  function getFlowRateNumber(value) {
-    return +value;
-  }
-
-  function getPercentFormat(value) {
-    if (value == 100) {
-      return '超时';
-    } else {
-      return value + '%';
-    }
-  }
-
-  function getPercentColor(value) {
-    let p = +value;
-    if (p >= 90 && p < 100) {
-      return 'rgb(244, 240, 89)';
-    } else if (p >= 100) {
-      return 'red';
-    } else {
-      return 'rgb(16, 142, 233)';
-    }
-  }
-
-  function loadDataSource() {
-    dataSource.value = table.dataSource.filter((item) => {
-      if (!unref(indexRegisterType)) {
-        return true;
-      }
-      return item.type == unref(indexRegisterType);
-    });
-  }
-
-  function loadDataSource1() {
-    dataSource1.value = table1.dataSource.filter((item) => {
-      if (!unref(indexRegisterType)) {
-        return true;
-      }
-      return item.type == unref(indexRegisterType);
-    });
-  }
-
-  loadDataSource();
-  loadDataSource1();
-</script>
-
-<style lang="less" scoped>
-  .ant-table-wrapper {
-    :deep(.ant-table) {
-      td,
-      th {
-        padding: 10px;
-      }
-    }
-  }
-  .extra-wrapper {
-    line-height: 55px;
-    padding-right: 24px;
-
-    .extra-item {
-      display: inline-block;
-      margin-right: 24px;
-
-      a {
-        margin-left: 24px;
-      }
-    }
-  }
-
-  .item-group {
-    padding: 20px 0 8px 24px;
-    font-size: 0;
-
-    a {
-      color: rgba(0, 0, 0, 0.65);
-      display: inline-block;
-      font-size: 14px;
-      margin-bottom: 13px;
-      width: 25%;
-    }
-  }
-
-  .item-group {
-    .more-btn {
-      margin-bottom: 13px;
-      text-align: center;
-    }
-  }
-
-  .list-content-item {
-    color: rgba(0, 0, 0, 0.45);
-    display: inline-block;
-    vertical-align: middle;
-    font-size: 14px;
-    margin-left: 40px;
-  }
-
-  @media only screen and (min-width: 1600px) {
-    .list-content-item {
-      margin-left: 60px;
-    }
-  }
-
-  @media only screen and (max-width: 1300px) {
-    .list-content-item {
-      margin-left: 20px;
-    }
-
-    .width-hidden4 {
-      display: none;
-    }
-  }
-
-  .list-content-item {
-    span {
-      line-height: 20px;
-    }
-  }
-
-  .list-content-item {
-    p {
-      margin-top: 4px;
-      margin-bottom: 0;
-      line-height: 22px;
-    }
-  }
-
-  .anty-list-cust {
-    .ant-list-item-meta {
-      flex: 0.3 !important;
-    }
-  }
-
-  .anty-list-cust {
-    .ant-list-item-content {
-      flex: 1 !important;
-      justify-content: flex-start !important;
-      margin-left: 20px;
-    }
-  }
-</style>

+ 0 - 25
src/views/dashboard/Analysis/homePage/IndexDef.vue

@@ -1,25 +0,0 @@
-<template>
-  <div class="p-4">
-    <GrowCard :loading="loading" class="enter-y" />
-    <SiteAnalysis class="!my-4 enter-y" :loading="loading" />
-    <div class="md:flex enter-y">
-      <VisitRadar class="md:w-1/3 w-full" :loading="loading" />
-      <VisitSource class="md:w-1/3 !md:mx-4 !md:my-0 !my-4 w-full" :loading="loading" />
-      <SalesProductPie class="md:w-1/3 w-full" :loading="loading" />
-    </div>
-  </div>
-</template>
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import GrowCard from '../components/GrowCard.vue';
-  import SiteAnalysis from '../components/SiteAnalysis.vue';
-  import VisitSource from '../components/VisitSource.vue';
-  import VisitRadar from '../components/VisitRadar.vue';
-  import SalesProductPie from '../components/SalesProductPie.vue';
-
-  const loading = ref(true);
-
-  setTimeout(() => {
-    loading.value = false;
-  }, 500);
-</script>

+ 0 - 422
src/views/dashboard/Analysis/homePage/IndexTask.vue

@@ -1,422 +0,0 @@
-<template>
-  <div class="index-container-ty">
-    <a-row type="flex" justify="start" :gutter="3">
-      <a-col :sm="24" :lg="12">
-        <a-card>
-          <template #title>
-            <div class="index-md-title">
-              <img src="../../../../assets/images/daiban.png" />
-              我的待办【{{ dataSource1.length }}】
-            </div>
-          </template>
-
-          <template v-if="dataSource1 && dataSource1.length > 0" #extra>
-            <a @click="goPage"
-              >更多
-              <Icon icon="ant-design:double-right-outlined" />
-            </a>
-          </template>
-
-          <a-table
-            :class="'my-index-table tytable1'"
-            ref="table1"
-            size="small"
-            rowKey="id"
-            :columns="columns"
-            :dataSource="dataSource1"
-            :pagination="false"
-          >
-            <template #ellipsisText="{ text }">
-              <JEllipsis :value="text" :length="textMaxLength"></JEllipsis>
-            </template>
-
-            <template #dayWarnning="{ text, record }">
-              <BellTwoTone style="font-size: 22px" :twoToneColor="getTipColor(record)" />
-            </template>
-
-            <template #action="{ text, record }">
-              <a @click="handleData">办理</a>
-            </template>
-          </a-table>
-        </a-card>
-      </a-col>
-
-      <a-col :sm="24" :lg="12">
-        <a-card>
-          <template #title>
-            <div class="index-md-title">
-              <img src="../../../../assets/images/zaiban.png" />
-              我的在办【{{ dataSource2.length }}】
-            </div>
-          </template>
-
-          <template v-if="dataSource2 && dataSource2.length > 0" #extra>
-            <a @click="goPage"
-              >更多
-              <Icon icon="ant-design:double-right-outlined" />
-            </a>
-          </template>
-
-          <a-table
-            :class="'my-index-table tytable2'"
-            ref="table1"
-            size="small"
-            rowKey="id"
-            :columns="columns"
-            :dataSource="dataSource2"
-            :pagination="false"
-          >
-            <template #ellipsisText="{ text }">
-              <JEllipsis :value="text" :length="textMaxLength"></JEllipsis>
-            </template>
-
-            <template #dayWarnning="{ text, record }">
-              <BellTwoTone style="font-size: 22px" :twoToneColor="getTipColor(record)" />
-            </template>
-
-            <template #action="{ text, record }">
-              <a @click="handleData">办理</a>
-            </template>
-          </a-table>
-        </a-card>
-      </a-col>
-
-      <a-col :span="24">
-        <div style="height: 5px"></div>
-      </a-col>
-
-      <a-col :sm="24" :lg="12">
-        <a-card>
-          <template #title>
-            <div class="index-md-title">
-              <img src="../../../../assets/images/guaz.png" />
-              我的挂账【{{ dataSource4.length }}】
-            </div>
-          </template>
-
-          <a-table
-            :class="'my-index-table tytable4'"
-            ref="table1"
-            size="small"
-            rowKey="id"
-            :columns="columns"
-            :dataSource="dataSource4"
-            :pagination="false"
-          >
-            <template #ellipsisText="{ text }">
-              <JEllipsis :value="text" :length="textMaxLength"></JEllipsis>
-            </template>
-
-            <template #dayWarnning="{ text, record }">
-              <BellTwoTone style="font-size: 22px" :twoToneColor="getTipColor(record)" />
-            </template>
-
-            <template #action="{ text, record }">
-              <a @click="handleData">办理</a>
-            </template>
-          </a-table>
-        </a-card>
-      </a-col>
-
-      <a-col :sm="24" :lg="12">
-        <a-card>
-          <template #title>
-            <div class="index-md-title">
-              <img src="../../../../assets/images/duban.png" />
-              我的督办【{{ dataSource3.length }}】
-            </div>
-          </template>
-
-          <a-table
-            :class="'my-index-table tytable3'"
-            ref="table1"
-            size="small"
-            rowKey="id"
-            :columns="columns"
-            :dataSource="dataSource3"
-            :pagination="false"
-          >
-            <template #ellipsisText="{ text }">
-              <JEllipsis :value="text" :length="textMaxLength"></JEllipsis>
-            </template>
-
-            <template #dayWarnning="{ text, record }">
-              <BellTwoTone style="font-size: 22px" :twoToneColor="getTipColor(record)" />
-            </template>
-
-            <template #action="{ text, record }">
-              <a @click="handleData">办理</a>
-            </template>
-          </a-table>
-        </a-card>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import noDataPng from '/@/assets/images/nodata.png';
-  import { useMessage } from '/@/hooks/web/useMessage';
-  import JEllipsis from '/@/components/Form/src/jeecg/components/JEllipsis.vue';
-  import { BulbTwoTone, BellTwoTone } from '@ant-design/icons-vue';
-
-  const tempSs1 = [
-    {
-      id: '001',
-      orderNo: '电[1]1267102',
-      orderTitle: '药品出问题了',
-      restDay: 1,
-    },
-    {
-      id: '002',
-      orderNo: '电[4]5967102',
-      orderTitle: '吃了xxx医院的药,病情越来越严重',
-      restDay: 0,
-    },
-    {
-      id: '003',
-      orderNo: '电[3]5988987',
-      orderTitle: '今天去超市买鸡蛋,鸡蛋都是坏的',
-      restDay: 7,
-    },
-    {
-      id: '004',
-      orderNo: '电[2]5213491',
-      orderTitle: 'xx宝实体店高价售卖xx',
-      restDay: 5,
-    },
-    {
-      id: '005',
-      orderNo: '电[1]1603491',
-      orderTitle: '以红利相诱,答应退保后扣一年费用',
-      restDay: 0,
-    },
-  ];
-
-  const tempSs2 = [
-    {
-      id: '001',
-      orderTitle: '我要投诉这个大超市',
-      orderNo: '电[1]10299456',
-      restDay: 6,
-    },
-    {
-      id: '002',
-      orderTitle: 'xxx医院乱开药方,售卖假药',
-      orderNo: '电[2]20235691',
-      restDay: 0,
-    },
-    {
-      id: '003',
-      orderTitle: '我想问问这家店是干啥的',
-      orderNo: '电[3]495867322',
-      restDay: 7,
-    },
-    {
-      id: '004',
-      orderTitle: '我要举报朝阳区奥森公园酒店',
-      orderNo: '电[2]1193849',
-      restDay: 3,
-    },
-    {
-      id: '005',
-      orderTitle: '我今天吃饭吃到一个石头子',
-      orderNo: '电[4]56782344',
-      restDay: 9,
-    },
-  ];
-
-  //4-7天
-  const tip_green = 'rgba(0, 255, 0, 1)';
-  //1-3天
-  const tip_yellow = 'rgba(255, 255, 0, 1)';
-  //超期
-  const tip_red = 'rgba(255, 0, 0, 1)';
-
-  const textMaxLength = 8;
-  const $message = useMessage();
-
-  const dataSource1 = ref([]);
-  const dataSource2 = ref([]);
-  const dataSource3 = ref([]);
-  const dataSource4 = ref([]);
-  const columns = [
-    {
-      title: '',
-      dataIndex: '',
-      key: 'rowIndex',
-      width: 50,
-      fixed: 'left',
-      align: 'center',
-      slots: { customRender: 'dayWarnning' },
-    },
-    {
-      title: '剩余天数',
-      align: 'center',
-      dataIndex: 'restDay',
-      width: 80,
-    },
-    {
-      title: '工单标题',
-      align: 'center',
-      dataIndex: 'orderTitle',
-      slots: { customRender: 'ellipsisText' },
-    },
-    {
-      title: '工单编号',
-      align: 'center',
-      dataIndex: 'orderNo',
-    },
-    {
-      title: '操作',
-      dataIndex: 'action',
-      align: 'center',
-      slots: { customRender: 'action' },
-    },
-  ];
-
-  function getTipColor(rd) {
-    let num = rd.restDay;
-    if (num <= 0) {
-      return tip_red;
-    } else if (num >= 1 && num < 4) {
-      return tip_yellow;
-    } else if (num >= 4) {
-      return tip_green;
-    }
-  }
-
-  function mock() {
-    dataSource1.value = tempSs1;
-    dataSource2.value = tempSs2;
-    dataSource3.value = tempSs1;
-    dataSource4.value = tempSs2;
-    ifNullDataSource(dataSource4, '.tytable4');
-  }
-
-  function ifNullDataSource(ds, tb) {
-    if (!ds || ds.length == 0) {
-      var tmp = document.createElement('img');
-      tmp.src = noDataPng;
-      tmp.width = 300;
-      let tbclass = `${tb} .ant-table-placeholder`;
-      document.querySelector(tbclass).innerHTML = '';
-      document.querySelector(tbclass).appendChild(tmp);
-    }
-  }
-
-  function handleData() {
-    $message.createMessage.success('办理完成');
-  }
-
-  function goPage() {
-    $message.createMessage.success('请根据具体业务跳转页面');
-  }
-
-  mock();
-</script>
-
-<style scoped lang="less">
-  .my-index-table {
-    height: 270px;
-
-    table {
-      font-size: 14px !important;
-    }
-  }
-
-  .index-container-ty {
-    margin: 12px 12px 0;
-
-    :deep(.ant-card-body) {
-      padding: 10px 12px 0 12px;
-    }
-
-    :deep(.ant-card-head) {
-      line-height: 24px;
-      min-height: 24px;
-      background: #7196fb !important;
-
-      .ant-card-head-title {
-        padding-top: 6px;
-        padding-bottom: 6px;
-      }
-
-      .ant-card-extra {
-        padding: 0;
-
-        a {
-          color: #fff;
-        }
-
-        a:hover {
-          color: #152ede;
-        }
-      }
-    }
-
-    :deep(.ant-table-footer) {
-      text-align: right;
-      padding: 6px 12px 6px 6px;
-      background: #fff;
-      border-top: 2px solid #f7f1f1;
-    }
-
-    .index-md-title {
-      position: relative;
-      width: 100%;
-      color: #fff;
-      font-size: 21px;
-      font-family: cursive;
-      padding-left: 25px;
-
-      img {
-        position: absolute;
-        height: 25px;
-        left: 0;
-      }
-    }
-
-    :deep(.ant-table-thead > tr > th),
-    :deep(.ant-table-tbody > tr > td) {
-      border-bottom: 1px solid #90aeff;
-    }
-
-    :deep(
-      .ant-table-small
-      > .ant-table-content
-      > .ant-table-fixed-left
-      > .ant-table-body-outer
-      > .ant-table-body-inner
-      > table
-      > .ant-table-thead
-      > tr
-      > th),
-    :deep(
-      .ant-table-small
-      > .ant-table-content
-      > .ant-table-fixed-right
-      > .ant-table-body-outer
-      > .ant-table-body-inner
-      > table
-      > .ant-table-thead
-      > tr
-      > th) {
-      border-bottom: 1px solid #90aeff;
-    }
-
-    :deep(.ant-table-small > .ant-table-content > .ant-table-scroll > .ant-table-body > table > .ant-table-thead > tr > th) {
-      border-bottom: 1px solid #90aeff;
-    }
-
-    :deep(.ant-table-small) {
-      border: 1px solid #90aeff;
-    }
-
-    :deep(.ant-table-placeholder) {
-      padding: 0;
-      height: 215px;
-    }
-  }
-</style>

+ 188 - 16
src/views/dashboard/Analysis/index.vue

@@ -1,22 +1,194 @@
 <template>
-  <IndexDef v-if="indexStyle === 1"></IndexDef>
-  <IndexBdc v-if="indexStyle == 2"></IndexBdc>
-  <IndexTask v-if="indexStyle == 3"></IndexTask>
-  <div style="width: 100%; text-align: right; margin-top: 20px">
-    首页主题:
-    <a-radio-group v-model:value="indexStyle">
-      <a-radio :value="0">默认</a-radio>
-      <a-radio :value="1">销量统计</a-radio>
-      <a-radio :value="2">业务统计</a-radio>
-      <a-radio :value="3">我的任务</a-radio>
-    </a-radio-group>
+  <div class="p16px">
+    <DefineGradientBg v-slot="{ $slots, gradientColor }">
+      <div class="rd-8px px-16px pb-4px pt-8px text-white" :style="{ backgroundImage: gradientColor }">
+        <component :is="$slots.default" />
+      </div>
+    </DefineGradientBg>
+    <a-card :bordered="false" title="数据概览">
+      <div class="grid xl:grid-cols-5 sm:grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-3">
+        <div v-for="item in cardData" :key="item.key" :xs="24" :sm="12" :md="12" :lg="5">
+          <GradientBg :gradient-color="getGradientColor(item.color)" class="flex-1">
+            <h3 class="text-16px">{{ item.title }}</h3>
+            <div class="flex">
+              <CountTo :endVal="item.value" :style="{ fontSize: '34px' }"> </CountTo>
+              <div class="ml12px mt25px"> {{ item.unit }} </div>
+            </div>
+            <div class="flex justify-between pt-12px">
+              <Icon :icon="item.icon" :size="28"> </Icon>
+              <div class="text-18px" v-if="item.Proportion != null">
+                环比:<span> {{ item.Proportion > 0 ? '+' : '' }} {{ item.Proportion }} %</span>
+              </div>
+              <div v-else> 无环比数据 </div>
+            </div>
+          </GradientBg>
+        </div>
+      </div>
+    </a-card>
+    <div class="mt24px">
+      <a-card :bordered="false" title="销售额趋势">
+        <Line height="300px" :chartData="chartData" v-if="chartData.length"></Line>
+      </a-card>
+    </div>
+
+    <div class="mt24px grid lg:grid-cols-2 sm:grid-cols-1 gap-3">
+      <a-card :bordered="false" title="门店销售额排行">
+        <template #extra>
+          <a-radio-group v-model:value="storeBtn" button-style="solid">
+            <a-radio-button ::value="0">今日</a-radio-button>
+            <a-radio-button :value="1">本周</a-radio-button>
+            <a-radio-button :value="2">本月</a-radio-button>
+          </a-radio-group>
+        </template>
+        <a-list item-layout="horizontal" :data-source="data">
+          <template #renderItem="{ item }">
+            <a-list-item>
+              <a-list-item-meta description="Ant Design, a design language for background applications, is refined by Ant UED Team">
+                <template #title>
+                  <a href="https://www.antdv.com/">{{ item.title }}</a>
+                </template>
+                <template #avatar>
+                  <a-avatar src="https://joeschmoe.io/api/v1/random" />
+                </template>
+              </a-list-item-meta>
+            </a-list-item>
+          </template>
+        </a-list>
+      </a-card>
+      <a-card :bordered="false" title="商品销量排行">
+        <template #extra>
+          <a-radio-group v-model:value="goodsBtn" button-style="solid">
+            <a-radio-button ::value="0">今日</a-radio-button>
+            <a-radio-button :value="1">本周</a-radio-button>
+            <a-radio-button :value="2">本月</a-radio-button>
+          </a-radio-group>
+        </template>
+        <a-list item-layout="horizontal" :data-source="data">
+          <template #renderItem="{ item }">
+            <a-list-item>
+              <a-list-item-meta description="Ant Design, a design language for background applications, is refined by Ant UED Team">
+                <template #title>
+                  <a href="https://www.antdv.com/">{{ item.title }}</a>
+                </template>
+                <template #avatar>
+                  <a-avatar src="https://joeschmoe.io/api/v1/random" />
+                </template>
+              </a-list-item-meta>
+            </a-list-item>
+          </template>
+        </a-list>
+      </a-card>
+    </div>
   </div>
 </template>
 <script lang="ts" setup>
-  import { ref } from 'vue';
-  import IndexDef from './homePage/IndexDef.vue';
-  import IndexBdc from './homePage/IndexBdc.vue';
-  import IndexTask from './homePage/IndexTask.vue';
+  import { Icon } from '/@/components/Icon';
+  import Line from './components/Line.vue';
+  import CountTo from '/@/components/CountTo/src/CountTo.vue';
+  import { createReusableTemplate } from '@vueuse/core';
+  import { ref, unref } from 'vue';
+  import { getIndexData } from './api';
+  const storeBtn = ref(0);
+  const goodsBtn = ref(0);
+  interface GradientBgProps {
+    gradientColor: string;
+  }
+  interface CardData {
+    key: string;
+    title: string;
+    value: number;
+    unit: string;
+    color: {
+      start: string;
+      end: string;
+    };
+    icon: string;
+    Proportion: number;
+  }
+  const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
+  const cardData = ref<CardData[]>([
+    {
+      key: 'visitCount',
+      title: '今日平台销售额',
+      value: 9725,
+      unit: '元',
+      color: {
+        start: '#ec4786',
+        end: '#b955a4',
+      },
+      icon: 'ant-design:bar-chart-outlined',
+      Proportion: 8,
+    },
+    {
+      key: 'turnover',
+      title: '今日平台有效订单量',
+      value: 1026,
+      unit: '笔',
+      color: {
+        start: '#865ec0',
+        end: '#5144b4',
+      },
+      icon: 'ant-design:file-text-outlined',
+      Proportion: 8,
+    },
+    {
+      key: 'downloadCount',
+      title: '今日平台预计收入',
+      value: 970925,
+      unit: '元',
+      color: {
+        start: '#56cdf3',
+        end: '#719de3',
+      },
+      icon: 'ant-design:dollar-circle-outlined',
+      Proportion: 8,
+    },
+    {
+      key: 'dealCount',
+      title: '今日平台消费人次',
+      value: 9527,
+      unit: '人次',
+      color: {
+        start: '#fcbc25',
+        end: '#f68057',
+      },
+      icon: 'ant-design:user-outlined',
+      Proportion: 8,
+    },
+    {
+      key: 'add',
+      title: '今日平台新增用户数',
+      value: 9527,
+      unit: '个',
+      color: {
+        start: '#4ade80',
+        end: '#134e4a',
+      },
+      icon: 'ant-design:user-add-outlined',
+      Proportion: 8,
+    },
+  ]);
+  const chartData = ref([]);
+  function getGradientColor(color: CardData['color']) {
+    return `linear-gradient(to bottom right, ${color.start}, ${color.end})`;
+  }
+  async function getDataIndex() {
+    const res = await getIndexData();
+    unref(cardData)[0].value = res.saleMoney;
+    unref(cardData)[0].Proportion = res.saleMoneyChain;
+    unref(cardData)[1].value = res.effectiveOrderNum;
+    unref(cardData)[1].Proportion = res.effectiveOrderNumChain;
+    unref(cardData)[2].value = res.expectIncomeMoney;
+    unref(cardData)[2].Proportion = res.expectIncomeMoneyChain;
+    unref(cardData)[3].value = res.consumeNumber;
+    unref(cardData)[3].Proportion = res.consumeNumberChain;
+    unref(cardData)[4].value = res.addNumber;
+    unref(cardData)[4].Proportion = res.addNumberChain;
+    chartData.value = res.findByStatisticsChartVOList;
+    console.log(unref(cardData), '获取数据');
+  }
 
-  const indexStyle = ref(0);
+  getDataIndex();
 </script>
+
+<style scoped></style>

+ 83 - 0
src/views/safetyManagement/signingList/index.vue

@@ -0,0 +1,83 @@
+<template>
+  <div>
+    <!--引用表格-->
+    <BasicTable @register="registerTable" :rowSelection="rowSelection">
+      <!--插槽:table标题-->
+      <template #tableTitle> </template>
+      <!--操作栏-->
+      <template #action="{ record }">
+        <TableAction :actions="getTableAction(record)" />
+      </template>
+    </BasicTable>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, reactive, computed, unref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/Table';
+  import { useModal } from '/@/components/Modal';
+  import { useListPage } from '/@/hooks/system/useListPage';
+  import { columns, searchFormSchema } from './signing.data';
+  import { getViewUrl, list } from './signing.api';
+  const queryParam = reactive<any>({});
+  //注册model
+  const [registerModal, { openModal }] = useModal();
+  //注册table数据
+  const { tableContext } = useListPage({
+    tableProps: {
+      api: list,
+      columns,
+      canResize: false,
+      formConfig: {
+        //labelWidth: 120,
+        schemas: searchFormSchema,
+        autoSubmitOnEnter: true,
+        showAdvancedButton: true,
+        fieldMapToNumber: [],
+        fieldMapToTime: [['Time', ['startTime', 'endTime'], 'YYYY-MM-DD']],
+      },
+      actionColumn: {
+        width: 120,
+        fixed: 'right',
+      },
+      beforeFetch: (params) => {
+        return Object.assign(params, queryParam);
+      },
+    },
+  });
+
+  const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
+
+  /**
+   * 编辑事件
+   */
+  async function handleEdit(record: Recordable) {
+    // const data = await getDetaile({ id: record.id });
+    console.log(record, 'record');
+
+    const res = await getViewUrl({ signFlowId: record.signFlowId });
+    console.log(res, '阿斯顿撒打算');
+  }
+
+  /**
+   * 操作栏
+   */
+  function getTableAction(record) {
+    return [
+      {
+        label: '绑定场地',
+        onClick: handleEdit.bind(null, record),
+        ifShow: () => {
+          return record.signFlowId;
+        },
+      },
+    ];
+  }
+</script>
+
+<style lang="less" scoped>
+  :deep(.ant-picker),
+  :deep(.ant-input-number) {
+    width: 100%;
+  }
+</style>

+ 16 - 0
src/views/safetyManagement/signingList/signing.api.ts

@@ -0,0 +1,16 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+  list = '/api/esign/queryUserSignContractList',
+  getViewUrl = '/api/esign/fileDownloadUrl',
+}
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.post({ url: Api.list, params });
+
+export const getViewUrl = (params) => defHttp.get({ url: Api.getViewUrl, params });

+ 79 - 0
src/views/safetyManagement/signingList/signing.data.ts

@@ -0,0 +1,79 @@
+import { storeToRefs } from 'pinia';
+import { Business } from '../../businessManagement/gymnasiumBag/gymnasiumBag.api';
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { useUserStore } from '/@/store/modules/user';
+const { userInfo } = storeToRefs(useUserStore());
+//列表数据
+export const columns: BasicColumn[] = [
+  {
+    title: '课程名称',
+    align: 'center',
+    dataIndex: 'productName',
+  },
+  {
+    title: '姓名',
+    align: 'center',
+    dataIndex: 'fullName',
+  },
+  {
+    title: '手机号',
+    align: 'center',
+    dataIndex: 'phone',
+  },
+  {
+    title: '付款时间',
+    align: 'center',
+    dataIndex: 'createTime',
+  },
+  {
+    title: '是否签署',
+    align: 'center',
+    dataIndex: 'isSign',
+    customRender: ({ record }) => {
+      return record.deviceType === 1 ? '已签' : '未签';
+    },
+  },
+];
+//查询数据
+export const searchFormSchema: FormSchema[] = [
+  {
+    label: '课程名称',
+    field: 'productName',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '姓名',
+    field: 'fullName',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '手机号',
+    field: 'phone',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '是否签署',
+    field: 'isSign',
+    component: 'Select',
+    componentProps: {
+      options: [
+        { label: '已签', value: 1 },
+        { label: '未签', value: 0 },
+      ],
+    },
+    colProps: { span: 6 },
+  },
+  {
+    label: '签署时间',
+    field: 'Time',
+    component: 'RangePicker',
+    componentProps: {
+      valueType: 'Date',
+    },
+    colProps: { span: 6 },
+  },
+];