Procházet zdrojové kódy

fix: 新增列表数据更新,修改数据更新 hook 函数

奔跑的面条 před 3 roky
rodič
revize
6cd2a06974

+ 17 - 9
src/api/mock/index.ts

@@ -3,14 +3,22 @@ import { MockMethod } from 'vite-plugin-mock'
 import { RequestHttpEnum } from '@/enums/httpEnum'
 
 // 单个X数据
-export const mockDataUrl = '/mock/mockData'
+export const chartDataUrl = '/mock/chartData'
+export const rankListUrl = '/mock/RankList'
 
-const mockObject: MockMethod[] =[{
-  // 正则
-  // url: /\/mock\/mockData(|\?\S*)$/,
-  url: '/mock/mockData',
-  method: RequestHttpEnum.GET,
-  response: () => test.featchMockData
-}]
+const mockObject: MockMethod[] = [
+  {
+    // 正则
+    // url: /\/mock\/mockData(|\?\S*)$/,
+    url: '/mock/chartData',
+    method: RequestHttpEnum.GET,
+    response: () => test.fetchMockData,
+  },
+  {
+    url: '/mock/rankList',
+    method: RequestHttpEnum.GET,
+    response: () => test.fetchRankList,
+  },
+]
 
-export default mockObject
+export default mockObject

+ 34 - 14
src/api/mock/test.mock.ts

@@ -1,42 +1,62 @@
 export default {
-  // 轮播
-  featchMockData: {
+  // 图
+  fetchMockData: {
     status: 200,
-    msg: "请求成功",
+    msg: '请求成功',
     data: {
-      dimensions: ["product", "dataOne", "dataTwo"],
+      dimensions: ['product', 'dataOne', 'dataTwo'],
       source: [
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
         {
-          'product': '@name',
+          product: '@name',
           'dataOne|100-900': 3,
           'dataTwo|100-900': 3,
         },
-      ]
-    }
-  }
-}
+      ],
+    },
+  },
+  // 排名列表
+  fetchRankList: {
+    status: 200,
+    msg: '请求成功',
+    data: [
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+      { name: '@name', 'value|100-900': 5 },
+    ],
+  },
+}

+ 0 - 0
src/components/LoadingComponent/LoadingSkeleton.vue → src/components/GoLoading/LoadingSkeleton.vue


+ 2 - 2
src/components/LoadingComponent/index.ts → src/components/GoLoading/index.ts

@@ -1,10 +1,10 @@
 import type { App } from 'vue'
-import LoadingComponent from './index.vue'
+import GoLoading from './index.vue'
 import AsyncLoading from './index.vue'
 import AsyncSkeletonLoading from './LoadingSkeleton.vue'
 
 // 正常组件
-export { LoadingComponent }
+export { GoLoading }
 
 // 异步
 AsyncLoading.install = (app: App): void => {

+ 0 - 0
src/components/LoadingComponent/index.vue → src/components/GoLoading/index.vue


+ 56 - 31
src/hooks/useChartDataFetch.hook.ts

@@ -1,51 +1,76 @@
 import { ref, toRefs, watchEffect, nextTick } from 'vue'
 import type VChart from 'vue-echarts'
 import { http } from '@/api/http'
-import { CreateComponentType } from '@/packages/index.d'
+import { CreateComponentType, PackagesCategoryEnum } from '@/packages/index.d'
 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
 import { RequestDataTypeEnum } from '@/enums/httpEnum'
 import { isPreview } from '@/utils'
 
+// 获取类型
 type ChartEditStoreType = typeof useChartEditStore
 
 /**
- * 图表针对 setdata 数据监听与更改
- * @param chartConfig
+ * setdata 数据监听与更改
+ * @param targetComponent
+ * @param useChartEditStore 若直接引会报错,只能动态传递
+ * @param updateCallback 自定义更新函数
  */
-export const useChartDataFetch = (chartConfig: CreateComponentType, useChartEditStore: ChartEditStoreType) => {
+export const useChartDataFetch = (
+  targetComponent: CreateComponentType,
+  useChartEditStore: ChartEditStoreType, 
+  updateCallback?: (...args: any) => any
+) => {
   const vChartRef = ref<typeof VChart | null>(null)
   let fetchInterval: any = 0
 
-  isPreview() && watchEffect(() => {
-    clearInterval(fetchInterval)
+  isPreview() &&
+    watchEffect(() => {
+      clearInterval(fetchInterval)
 
-    const chartEditStore = useChartEditStore()
-    const { requestOriginUrl, requestInterval } = toRefs(
-      chartEditStore.getRequestGlobalConfig
-    )
-    const { requestDataType, requestHttpType, requestUrl } = toRefs(
-      chartConfig.data
-    )
-    if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
-    // 处理地址
-    if (requestUrl?.value && requestInterval.value > 0) {
-      // requestOriginUrl 允许为空
-      const completePath =
-        requestOriginUrl && requestOriginUrl.value + requestUrl.value
-      if (!completePath) return
+      const chartEditStore = useChartEditStore()
+      const { requestOriginUrl, requestInterval } = toRefs(
+        chartEditStore.getRequestGlobalConfig
+      )
+      const { requestDataType, requestHttpType, requestUrl } = toRefs(
+        targetComponent.data
+      )
+      if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
+      // 处理地址
+      if (requestUrl?.value && requestInterval.value > 0) {
+        // requestOriginUrl 允许为空
+        const completePath =
+          requestOriginUrl && requestOriginUrl.value + requestUrl.value
+        if (!completePath) return
 
-      fetchInterval = setInterval(async () => {
-        const res = await http(requestHttpType.value)(completePath || '', {})
-        if (res.data) {
-          nextTick(() => {
-            if(vChartRef.value) {
-              vChartRef.value.setOption({dataset: res.data})
+        fetchInterval = setInterval(async () => {
+          const res:any = await http(requestHttpType.value)(completePath || '', {})
+          if (res.data) {
+            // 是否是 Echarts
+            const isECharts =
+              targetComponent.chartConfig.package ===
+              PackagesCategoryEnum.CHARTS
+
+            try {
+              if (isECharts) {
+                nextTick(() => {
+                  if (vChartRef.value) {
+                    vChartRef.value.setOption({ dataset: res.data })
+                  }
+                })
+              } else {
+                // 若遵守规范使用 datase 作为数据 key,则省自动赋值数据
+                targetComponent.option.dataset = res.data
+              }
+              if (updateCallback) {
+                updateCallback(res.data)
+              }
+            } catch (error) {
+              console.error(error)
             }
-          })
-        }
-      }, requestInterval.value * 1000)
-    }
-  })
+          }
+        }, requestInterval.value * 1000)
+      }
+    })
 
   return { vChartRef }
 }

+ 3 - 2
src/packages/components/Tables/Tables/TableList/config.ts

@@ -5,7 +5,8 @@ import cloneDeep from 'lodash/cloneDeep'
 import dataJson from './data.json'
 
 export const option = {
-  data: dataJson,
+  // 数据
+  dataset: dataJson,
   // 表行数
   rowNum: 5,
   // 轮播时间
@@ -15,7 +16,7 @@ export const option = {
   // 自动排序
   sort: true,
   color: '#1370fb',
-  textColor: '#ffffff',
+  textColor: '#CDD2F8FF',
   borderColor: '#1370fb80',
   carousel: 'single',
   // 格式化

+ 0 - 6
src/packages/components/Tables/Tables/TableList/config.vue

@@ -24,12 +24,6 @@
           placeholder="数值单位"
         ></n-input>
       </SettingItem>
-      <SettingItem>
-        <n-space>
-          <n-switch v-model:value="optionData.sort" size="small" />
-          <n-text>自动排序</n-text>
-        </n-space>
-      </SettingItem>
     </SettingItemBox>
 
     <SettingItemBox name="样式">

+ 57 - 44
src/packages/components/Tables/Tables/TableList/index.vue

@@ -15,11 +15,14 @@
               ? status.mergedConfig.valueFormatter(item)
               : item.value
           }}
-          {{unit}}
+          {{ unit }}
         </div>
       </div>
       <div class="ranking-column" :style="`border-color: ${borderColor}`">
-        <div class="inside-column" :style="`width: ${item.percent}%;background-color: ${color}`">
+        <div
+          class="inside-column"
+          :style="`width: ${item.percent}%;background-color: ${color}`"
+        >
           <div class="shine" />
         </div>
       </div>
@@ -32,6 +35,8 @@ import { PropType, onUnmounted, reactive, ref, toRefs, watch } from 'vue'
 import { CreateComponentType } from '@/packages/index.d'
 import cloneDeep from 'lodash/cloneDeep'
 import merge from 'lodash/merge'
+import { useChartDataFetch } from '@/hooks'
+import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
 
 const props = defineProps({
   chartConfig: {
@@ -39,9 +44,10 @@ const props = defineProps({
     required: true,
   },
 })
-
 const { w, h } = toRefs(props.chartConfig.attr)
-const { rowNum, unit, color, textColor, borderColor } = toRefs(props.chartConfig.option)
+const { rowNum, unit, color, textColor, borderColor } = toRefs(
+  props.chartConfig.option
+)
 
 const status = reactive({
   mergedConfig: props.chartConfig.option,
@@ -53,41 +59,15 @@ const status = reactive({
   updater: 0,
 })
 
-const onResize = () => {
-  if (!status.mergedConfig) return
-  stopAnimation()
-  calcHeights(true)
-  animation(true)
-}
-
-watch(
-  () => w.value,
-  () => {
-    onResize()
-  }
-)
-watch(
-  () => h.value,
-  () => {
-    onResize()
-  }
-)
-watch(
-  () => rowNum.value,
-  () => {
-    onResize()
-  }
-)
-
 const calcRowsData = () => {
-  let { data, rowNum, sort } = status.mergedConfig
+  let { dataset, rowNum, sort } = status.mergedConfig
   sort &&
-    data.sort(({ value: a }, { value: b }) => {
+    dataset.sort(({ value: a }, { value: b }) => {
       if (a > b) return -1
       if (a < b) return 1
       if (a === b) return 0
     })
-  const value = data.map(({ value }) => value)
+  const value = dataset.map(({ value }) => value)
   const min = Math.min(...value) || 0
   // abs of min
   const minAbs = Math.abs(min)
@@ -95,25 +75,25 @@ const calcRowsData = () => {
   // abs of max
   const maxAbs = Math.abs(max)
   const total = max + minAbs
-  data = data.map((row, i) => ({
+  dataset = dataset.map((row, i) => ({
     ...row,
     ranking: i + 1,
     percent: ((row.value + minAbs) / total) * 100,
   }))
-  const rowLength = data.length
+  const rowLength = dataset.length
   if (rowLength > rowNum && rowLength < 2 * rowNum) {
-    data = [...data, ...data]
+    dataset = [...dataset, ...dataset]
   }
-  data = data.map((d, i) => ({ ...d, scroll: i }))
-  status.rowsData = data
-  status.rows = data
+  dataset = dataset.map((d, i) => ({ ...d, scroll: i }))
+  status.rowsData = dataset
+  status.rows = dataset
 }
 
 const calcHeights = (onresize = false) => {
-  const { rowNum, data } = status.mergedConfig
+  const { rowNum, dataset } = status.mergedConfig
   const avgHeight = h.value / rowNum
   status.avgHeight = avgHeight
-  if (!onresize) status.heights = new Array(data.length).fill(avgHeight)
+  if (!onresize) status.heights = new Array(dataset.length).fill(avgHeight)
 }
 
 const animation = async (start = false) => {
@@ -147,13 +127,46 @@ const stopAnimation = () => {
   clearTimeout(status.animationHandler)
 }
 
-const init = () => {
+const onRestart = async () => {
+  if (!status.mergedConfig) return
+  stopAnimation()
   calcRowsData()
-  calcHeights()
+  calcHeights(true)
   animation(true)
 }
 
-init()
+onRestart()
+
+watch(
+  () => w.value,
+  () => {
+    onRestart()
+  }
+)
+
+watch(
+  () => h.value,
+  () => {
+    onRestart()
+  }
+)
+
+watch(
+  () => rowNum.value,
+  () => {
+    onRestart()
+  }
+)
+
+// 数据更新
+watch(
+  () => props.chartConfig.option.dataset,
+  () => {
+    onRestart()
+  }
+)
+
+useChartDataFetch(props.chartConfig, useChartEditStore)
 
 onUnmounted(() => {
   stopAnimation()

+ 2 - 2
src/plugins/customComponents.ts

@@ -1,6 +1,6 @@
 import type { App } from 'vue'
 import { GoSkeleton } from '@/components/GoSkeleton'
-import { LoadingComponent } from '@/components/LoadingComponent'
+import { GoLoading } from '@/components/GoLoading'
 import { SketchRule } from 'vue3-sketch-ruler'
 
 /**
@@ -9,6 +9,6 @@ import { SketchRule } from 'vue3-sketch-ruler'
  */
 export function setupCustomComponents(app: App) {
   app.component('GoSkeleton', GoSkeleton)
-  app.component('LoadingComponent', LoadingComponent)
+  app.component('GoLoading', GoLoading)
   app.component('SketchRule', SketchRule)
 }

+ 1 - 4
src/settings/chartThemes/global.theme.json

@@ -78,8 +78,5 @@
       "color": "#B9B8CE"
     }
   },
-  "dataset": {
-    "dimensions": [""],
-    "source": [{}]
-  }
+  "dataset": null
 }

+ 1 - 1
src/utils/componets.ts

@@ -1,5 +1,5 @@
 import { defineAsyncComponent, AsyncComponentLoader } from 'vue'
-import { AsyncLoading, AsyncSkeletonLoading } from '@/components/LoadingComponent'
+import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading'
 
 /**
  * * 动态注册组件

+ 13 - 11
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataAjax/index.vue

@@ -20,13 +20,15 @@
               <help-outline-icon></help-outline-icon>
             </n-icon>
           </template>
-          <span>
-            开发环境使用 mock 数据,请输入【
-            <n-text type="info">
-              {{ mockDataUrl }}
-            </n-text>
-            】
-          </span>
+          <ul>
+            开发环境使用 mock 数据,请输入
+            <li>
+              <n-text type="info"> 【图表】{{ chartDataUrl }} </n-text>
+            </li>
+            <li>
+              <n-text type="info"> 【表格】{{ rankListUrl }} </n-text>
+            </li>
+          </ul>
         </n-tooltip>
       </template>
       <n-input
@@ -63,7 +65,7 @@ import { ref, toRefs } from 'vue'
 import { icon } from '@/plugins'
 import { SettingItemBox } from '@/components/ChartItemSetting/index'
 import { RequestHttpEnum } from '@/enums/httpEnum'
-import { mockDataUrl } from '@/api/mock'
+import { chartDataUrl, rankListUrl } from '@/api/mock'
 import { http } from '@/api/http'
 import { SelectHttpType } from '../../index.d'
 import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
@@ -82,12 +84,12 @@ const showMatching = ref(false)
 const selectOptions: SelectHttpType[] = [
   {
     label: RequestHttpEnum.GET,
-    value: RequestHttpEnum.GET
+    value: RequestHttpEnum.GET,
   },
   {
     label: RequestHttpEnum.POST,
-    value: RequestHttpEnum.POST
-  }
+    value: RequestHttpEnum.POST,
+  },
 ]
 
 // 发送请求

+ 24 - 9
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataMatchingAndShow/index.vue

@@ -1,6 +1,10 @@
 <template>
   <n-timeline class="go-chart-configurations-timeline">
-    <n-timeline-item type="info" :title="TimelineTitleEnum.MAPPING">
+    <n-timeline-item
+      v-if="isCharts"
+      type="info"
+      :title="TimelineTitleEnum.MAPPING"
+    >
       <n-table striped>
         <thead>
           <tr>
@@ -17,7 +21,10 @@
                 <n-text>无</n-text>
               </n-space>
               <n-space v-else>
-                <n-badge dot :type="item.result === 1 ? 'success' : 'error'"></n-badge>
+                <n-badge
+                  dot
+                  :type="item.result === 1 ? 'success' : 'error'"
+                ></n-badge>
                 <n-text>匹配{{ item.result === 1 ? '成功' : '失败' }}</n-text>
               </n-space>
             </td>
@@ -27,7 +34,7 @@
     </n-timeline-item>
     <n-timeline-item type="success" :title="TimelineTitleEnum.CONTENT">
       <n-space vertical>
-        <n-text depth="3">数据需要符合 ECharts-setdata 规范</n-text>
+        <n-text depth="3">ECharts 图表需符合 ECharts-setdata 数据规范</n-text>
         <n-space class="source-btn-box">
           <n-upload
             v-model:file-list="uploadFileListRef"
@@ -65,7 +72,7 @@
 
 <script setup lang="ts">
 import { ref, computed, watch } from 'vue'
-import { CreateComponentType } from '@/packages/index.d'
+import { CreateComponentType, PackagesCategoryEnum } from '@/packages/index.d'
 import { icon } from '@/plugins'
 import { DataResultEnum, TimelineTitleEnum } from '../../index.d'
 import { useFile } from '../../hooks/useFile.hooks'
@@ -89,6 +96,11 @@ const dimensionsAndSource = ref()
 
 const { uploadFileListRef, customRequest, beforeUpload, download} = useFile(targetData)
 
+// 是图表类型
+const isCharts = computed(()=> {
+  return targetData.value.chartConfig.package === PackagesCategoryEnum.CHARTS
+})
+
 // 获取数据
 const getSource = computed(() => {
   return JSON.stringify(source.value)
@@ -128,17 +140,20 @@ const dimensionsAndSourceHandle = () => {
 
 watch(() => targetData.value?.option?.dataset, (newData) => {
   if (newData) {
-    source.value = newData.source
-    dimensions.value = newData.dimensions
-    dimensionsAndSource.value = dimensionsAndSourceHandle()
+    // 只有 Echarts 数据才有对应的格式
+    source.value = isCharts.value ? newData.source : newData
+    if(isCharts.value) {
+      dimensions.value = newData.dimensions
+      dimensionsAndSource.value = dimensionsAndSourceHandle()
+    }
   }
-}, {
+},{
   immediate: true
 })
 </script>
 
 <style lang="scss" scoped>
-@include go("chart-configurations-timeline") {
+@include go('chart-configurations-timeline') {
   @include deep() {
     pre {
       white-space: pre-wrap;