Pārlūkot izejas kodu

feat:vue3 版本重新初始化

颜琼丽 3 nedēļas atpakaļ
vecāks
revīzija
9380d39693

+ 4 - 2
RuoYi-Cloud-Vue3-master/.env.development

@@ -1,8 +1,10 @@
 # 页面标题
-VITE_APP_TITLE = 若依管理系统
+VITE_APP_TITLE = 瑞鲸速达平台
 
 # 开发环境配置
 VITE_APP_ENV = 'development'
 
-# 若依管理系统/开发环境
+# 瑞鲸速达平台/开发环境
 VITE_APP_BASE_API = '/dev-api'
+
+VITE_APP_API_BASE_URL = 'http://192.168.101.77:8080'

+ 4 - 2
RuoYi-Cloud-Vue3-master/.env.production

@@ -1,11 +1,13 @@
 # 页面标题
-VITE_APP_TITLE = 若依管理系统
+VITE_APP_TITLE = 瑞鲸速达平台
 
 # 生产环境配置
 VITE_APP_ENV = 'production'
 
-# 若依管理系统/生产环境
+# 瑞鲸速达平台/生产环境
 VITE_APP_BASE_API = '/prod-api'
 
+VITE_APP_API_BASE_URL = 'http://192.168.101.77:8080'
+
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS = gzip

+ 6 - 4
RuoYi-Cloud-Vue3-master/.env.staging

@@ -1,11 +1,13 @@
 # 页面标题
-VITE_APP_TITLE = 若依管理系统
+VITE_APP_TITLE = 瑞鲸速达平台
 
 # 生产环境配置
-VITE_APP_ENV = 'staging'
+VITE_APP_ENV = 'production'
 
-# 若依管理系统/生产环境
-VITE_APP_BASE_API = '/stage-api'
+# 瑞鲸速达平台/生产环境
+VITE_APP_BASE_API = '/prod-api'
+
+VITE_APP_API_BASE_URL = 'http://192.168.101.77:8080'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS = gzip

+ 18 - 20
RuoYi-Cloud-Vue3-master/package.json

@@ -1,8 +1,8 @@
 {
   "name": "ruoyi",
   "version": "3.6.7",
-  "description": "若依管理系统",
-  "author": "若依",
+  "description": "瑞鲸速达平台",
+  "author": "瑞鲸",
   "license": "MIT",
   "type": "module",
   "scripts": {
@@ -11,39 +11,37 @@
     "build:stage": "vite build --mode staging",
     "preview": "vite preview"
   },
-  "repository": {
-    "type": "git",
-    "url": "https://gitee.com/y_project/RuoYi-Cloud.git"
-  },
   "dependencies": {
-    "@element-plus/icons-vue": "2.3.2",
+    "@element-plus/icons-vue": "2.3.1",
     "@vueup/vue-quill": "1.2.0",
-    "@vueuse/core": "14.1.0",
-    "axios": "1.13.2",
+    "@vueuse/core": "13.3.0",
+    "axios": "^1.13.2",
     "clipboard": "2.0.11",
-    "echarts": "5.6.0",
-    "element-plus": "2.13.1",
+    "echarts": "^6.0.0",
+    "element-plus": "^2.13.1",
     "file-saver": "2.0.5",
-    "fuse.js": "7.1.0",
-    "js-beautify": "1.15.4",
+    "fuse.js": "6.6.2",
+    "js-beautify": "1.14.11",
     "js-cookie": "3.0.5",
     "jsencrypt": "3.3.2",
     "nprogress": "0.2.0",
-    "pinia": "3.0.4",
+    "pinia": "3.0.2",
     "splitpanes": "4.0.4",
-    "vue": "3.5.26",
+    "vue": "3.5.16",
     "vue-cropper": "1.1.1",
-    "vue-router": "4.6.4",
-    "vuedraggable": "4.1.0"
+    "vue-router": "4.5.1",
+    "vue3-count-to": "^1.1.2",
+    "vuedraggable": "4.1.0",
+    "yarn": "^1.22.22"
   },
   "devDependencies": {
     "@vitejs/plugin-vue": "5.2.4",
-    "sass-embedded": "1.97.2",
+    "sass-embedded": "1.89.1",
     "unplugin-auto-import": "0.18.6",
     "unplugin-vue-setup-extend-plus": "1.0.1",
-    "vite": "6.4.1",
+    "vite": "6.3.5",
     "vite-plugin-compression": "0.5.1",
-    "vite-plugin-svg-icons": "2.0.1"
+    "vite-plugin-svg-icons": "^2.0.1"
   },
   "overrides": {
     "quill": "2.0.2"

+ 22 - 22
RuoYi-Cloud-Vue3-master/src/layout/components/Navbar.vue

@@ -9,30 +9,30 @@
     </template>
 
     <div class="right-menu">
-      <template v-if="appStore.device !== 'mobile'">
-        <header-search id="header-search" class="right-menu-item" />
+<!--      <template v-if="appStore.device !== 'mobile'">-->
+<!--        <header-search id="header-search" class="right-menu-item" />-->
 
-        <el-tooltip content="源码地址" effect="dark" placement="bottom">
-          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
-        </el-tooltip>
+<!--        <el-tooltip content="源码地址" effect="dark" placement="bottom">-->
+<!--          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
 
-        <el-tooltip content="文档地址" effect="dark" placement="bottom">
-          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
-        </el-tooltip>
+<!--        <el-tooltip content="文档地址" effect="dark" placement="bottom">-->
+<!--          <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
 
-        <screenfull id="screenfull" class="right-menu-item hover-effect" />
+<!--        <screenfull id="screenfull" class="right-menu-item hover-effect" />-->
 
-        <el-tooltip content="主题模式" effect="dark" placement="bottom">
-          <div class="right-menu-item hover-effect theme-switch-wrapper" @click="toggleTheme">
-            <svg-icon v-if="settingsStore.isDark" icon-class="sunny" />
-            <svg-icon v-if="!settingsStore.isDark" icon-class="moon" />
-          </div>
-        </el-tooltip>
+<!--        <el-tooltip content="主题模式" effect="dark" placement="bottom">-->
+<!--          <div class="right-menu-item hover-effect theme-switch-wrapper" @click="toggleTheme">-->
+<!--            <svg-icon v-if="settingsStore.isDark" icon-class="sunny" />-->
+<!--            <svg-icon v-if="!settingsStore.isDark" icon-class="moon" />-->
+<!--          </div>-->
+<!--        </el-tooltip>-->
 
-        <el-tooltip content="布局大小" effect="dark" placement="bottom">
-          <size-select id="size-select" class="right-menu-item hover-effect" />
-        </el-tooltip>
-      </template>
+<!--        <el-tooltip content="布局大小" effect="dark" placement="bottom">-->
+<!--          <size-select id="size-select" class="right-menu-item hover-effect" />-->
+<!--        </el-tooltip>-->
+<!--      </template>-->
 
       <el-dropdown @command="handleCommand" class="avatar-container right-menu-item hover-effect" trigger="hover">
         <div class="avatar-wrapper">
@@ -44,9 +44,9 @@
             <router-link to="/user/profile">
               <el-dropdown-item>个人中心</el-dropdown-item>
             </router-link>
-            <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
-                <span>布局设置</span>
-              </el-dropdown-item>
+<!--            <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">-->
+<!--                <span>布局设置</span>-->
+<!--            </el-dropdown-item>-->
             <el-dropdown-item divided command="logout">
               <span>退出登录</span>
             </el-dropdown-item>

+ 162 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/BarChart.vue

@@ -0,0 +1,162 @@
+<template>
+  <div ref="chartRef" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import * as echarts from 'echarts'
+
+const animationDuration = 6000
+
+const props = defineProps({
+  className: {
+    type: String,
+    default: 'chart'
+  },
+  width: {
+    type: String,
+    default: '100%'
+  },
+  height: {
+    type: String,
+    default: '300px'
+  }
+})
+
+const chartRef = ref(null)
+let chartInstance = null
+let resizeObserver = null
+let resizeTimer = null
+
+const handleResize = () => {
+  if (resizeTimer) {
+    clearTimeout(resizeTimer)
+  }
+
+  resizeTimer = setTimeout(() => {
+    if (chartInstance) {
+      try {
+        chartInstance.resize()
+      } catch (error) {
+        console.error('图表重绘失败:', error)
+      }
+    }
+  }, 200)
+}
+
+const initResizeListener = () => {
+  // 监听窗口大小变化
+  window.addEventListener('resize', handleResize)
+
+  // 使用 ResizeObserver 监听容器自身大小变化
+  if (typeof ResizeObserver !== 'undefined' && chartRef.value) {
+    resizeObserver = new ResizeObserver((entries) => {
+      handleResize()
+    })
+    resizeObserver.observe(chartRef.value)
+  }
+}
+
+const removeResizeListener = () => {
+  // 清理定时器
+  if (resizeTimer) {
+    clearTimeout(resizeTimer)
+    resizeTimer = null
+  }
+
+  // 移除窗口监听
+  window.removeEventListener('resize', handleResize)
+
+  // 断开 ResizeObserver
+  if (resizeObserver) {
+    resizeObserver.disconnect()
+    resizeObserver = null
+  }
+}
+
+const initChart = () => {
+  if (!chartRef.value) return
+
+  if (chartInstance) {
+    chartInstance.dispose()
+  }
+
+  chartInstance = echarts.init(chartRef.value, 'macarons')
+
+  chartInstance.setOption({
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      top: 10,
+      left: '2%',
+      right: '2%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: [{
+      type: 'category',
+      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+      axisTick: {
+        alignWithLabel: true
+      }
+    }],
+    yAxis: [{
+      type: 'value',
+      axisTick: {
+        show: false
+      }
+    }],
+    series: [{
+      name: 'pageA',
+      type: 'bar',
+      stack: 'vistors',
+      barWidth: '60%',
+      data: [79, 52, 200, 334, 390, 330, 220],
+      animationDuration
+    }, {
+      name: 'pageB',
+      type: 'bar',
+      stack: 'vistors',
+      barWidth: '60%',
+      data: [80, 52, 200, 334, 390, 330, 220],
+      animationDuration
+    }, {
+      name: 'pageC',
+      type: 'bar',
+      stack: 'vistors',
+      barWidth: '60%',
+      data: [30, 52, 200, 334, 390, 330, 220],
+      animationDuration
+    }]
+  })
+
+  // 图表初始化后立即重绘一次,确保尺寸正确
+  nextTick(() => {
+    chartInstance.resize()
+  })
+}
+
+onMounted(() => {
+  nextTick(() => {
+    initChart()
+    initResizeListener()
+  })
+})
+
+onBeforeUnmount(() => {
+  removeResizeListener()
+  if (chartInstance) {
+    chartInstance.dispose()
+    chartInstance = null
+  }
+})
+
+// 暴露方法给父组件
+defineExpose({
+  resizeChart: handleResize
+})
+</script>

+ 228 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/LineChart.vue

@@ -0,0 +1,228 @@
+<template>
+  <div ref="chartRef" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
+import * as echarts from 'echarts'
+
+const props = defineProps({
+  className: {
+    type: String,
+    default: 'chart'
+  },
+  width: {
+    type: String,
+    default: '100%'
+  },
+  height: {
+    type: String,
+    default: '350px'
+  },
+  autoResize: {
+    type: Boolean,
+    default: true
+  },
+  chartData: {
+    type: Object,
+    required: true
+  }
+})
+
+const chartRef = ref(null)
+let chartInstance = null
+let resizeObserver = null
+let resizeTimer = null
+
+onMounted(() => {
+  nextTick(() => {
+    initChart()
+    if (props.autoResize) {
+      initResizeListener()
+    }
+  })
+})
+
+onBeforeUnmount(() => {
+  // 清理定时器
+  if (resizeTimer) {
+    clearTimeout(resizeTimer)
+    resizeTimer = null
+  }
+
+  // 清理 ResizeObserver
+  if (resizeObserver && chartRef.value) {
+    resizeObserver.unobserve(chartRef.value)
+    resizeObserver.disconnect()
+    resizeObserver = null
+  }
+
+  // 销毁图表实例
+  if (chartInstance) {
+    chartInstance.dispose()
+    chartInstance = null
+  }
+})
+
+watch(
+    () => props.chartData,
+    (newVal) => {
+      setOptions(newVal)
+    },
+    { deep: true }
+)
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (resizeTimer) {
+    clearTimeout(resizeTimer)
+  }
+
+  // 使用防抖,避免频繁重绘
+  resizeTimer = setTimeout(() => {
+    if (chartInstance) {
+      try {
+        chartInstance.resize()
+      } catch (error) {
+        console.error('图表重绘失败:', error)
+      }
+    }
+  }, 200)
+}
+
+// 初始化 ResizeObserver 监听容器大小变化
+const initResizeListener = () => {
+  // 监听窗口大小变化
+  window.addEventListener('resize', handleResize)
+
+  // 如果浏览器支持 ResizeObserver,监听容器自身的大小变化
+  if (typeof ResizeObserver !== 'undefined' && chartRef.value) {
+    resizeObserver = new ResizeObserver((entries) => {
+      for (let entry of entries) {
+        if (entry.target === chartRef.value) {
+          handleResize()
+        }
+      }
+    })
+    resizeObserver.observe(chartRef.value)
+  }
+}
+
+const initChart = () => {
+  if (!chartRef.value) return
+
+  // 如果已有实例,先销毁
+  if (chartInstance) {
+    chartInstance.dispose()
+    chartInstance = null
+  }
+
+  try {
+    chartInstance = echarts.init(chartRef.value, 'macarons')
+    setOptions(props.chartData)
+
+    // 添加图表渲染完成后的重绘,确保初始尺寸正确
+    nextTick(() => {
+      if (chartInstance) {
+        chartInstance.resize()
+      }
+    })
+  } catch (error) {
+    console.error('图表初始化失败:', error)
+  }
+}
+
+const setOptions = ({ expectedData, actualData } = {}) => {
+  if (!chartInstance) return
+
+  try {
+    chartInstance.setOption({
+      title: {
+        text: '用户访问数据',
+        left: "3%",
+        top: "0%"
+      },
+      tooltip: {
+        trigger: 'axis',
+        z: 60,
+        show: true,
+        showContent: true
+      },
+      xAxis: {
+        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+        boundaryGap: false,
+        axisTick: {
+          show: false
+        }
+      },
+      grid: {
+        left: "5%",
+        right: "5%",
+        bottom: "5%",
+        containLabel: true
+      },
+      yAxis: {
+        axisTick: {
+          show: false
+        }
+      },
+      legend: {
+        data: ['expected', 'actual'],
+        top: "2%",
+        textStyle: {
+          color: '#666'
+        }
+      },
+      series: [
+        {
+          name: 'expected',
+          itemStyle: {
+            color: '#FF005A'
+          },
+          lineStyle: {
+            color: '#FF005A',
+            width: 2
+          },
+          smooth: true,
+          type: 'line',
+          data: expectedData || [],
+          animationDuration: 2800,
+          animationEasing: 'cubicInOut'
+        },
+        {
+          name: 'actual',
+          smooth: true,
+          type: 'line',
+          itemStyle: {
+            color: '#3888fa'
+          },
+          lineStyle: {
+            color: '#3888fa',
+            width: 2
+          },
+          areaStyle: {
+            color: '#f3f8ff'
+          },
+          data: actualData || [],
+          animationDuration: 2800,
+          animationEasing: 'quadraticOut'
+        }
+      ]
+    })
+  } catch (error) {
+    console.error('设置图表选项失败:', error)
+  }
+}
+
+// 添加一个手动调整大小的方法,可以在父组件中调用
+const resizeChart = () => {
+  if (chartInstance) {
+    chartInstance.resize()
+  }
+}
+
+// 暴露方法给父组件
+defineExpose({
+  resizeChart
+})
+</script>

+ 177 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/PanelGroup.vue

@@ -0,0 +1,177 @@
+<template>
+  <el-row :gutter="40" class="panel-group">
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('newVisitis')">
+        <div class="card-panel-icon-wrapper icon-people">
+          <svg-icon icon-class="peoples" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            访客
+          </div>
+          <CountTo :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('messages')">
+        <div class="card-panel-icon-wrapper icon-message">
+          <svg-icon icon-class="message" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            消息
+          </div>
+          <CountTo :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('purchases')">
+        <div class="card-panel-icon-wrapper icon-money">
+          <svg-icon icon-class="money" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            金额
+          </div>
+          <CountTo :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+      <div class="card-panel" @click="handleSetLineChartData('shoppings')">
+        <div class="card-panel-icon-wrapper icon-shopping">
+          <svg-icon icon-class="shopping" class-name="card-panel-icon" />
+        </div>
+        <div class="card-panel-description">
+          <div class="card-panel-text">
+            订单
+          </div>
+          <CountTo :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
+        </div>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script setup>
+
+import { CountTo } from "vue3-count-to";
+
+const emit = defineEmits(['handleSetLineChartData'])
+
+const handleSetLineChartData = (type) => {
+  emit('handleSetLineChartData', type)
+}
+</script>
+
+<style lang="scss" scoped>
+.panel-group {
+  margin-top: 18px;
+
+  .card-panel-col {
+    margin-bottom: 32px;
+  }
+
+  .card-panel {
+    height: 108px;
+    cursor: pointer;
+    font-size: 12px;
+    position: relative;
+    overflow: hidden;
+    color: #666;
+    background: #fff;
+    box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
+    border-color: rgba(0, 0, 0, .05);
+
+    &:hover {
+      .card-panel-icon-wrapper {
+        color: #fff;
+      }
+
+      .icon-people {
+        background: #40c9c6;
+      }
+
+      .icon-message {
+        background: #36a3f7;
+      }
+
+      .icon-money {
+        background: #f4516c;
+      }
+
+      .icon-shopping {
+        background: #34bfa3
+      }
+    }
+
+    .icon-people {
+      color: #40c9c6;
+    }
+
+    .icon-message {
+      color: #36a3f7;
+    }
+
+    .icon-money {
+      color: #f4516c;
+    }
+
+    .icon-shopping {
+      color: #34bfa3
+    }
+
+    .card-panel-icon-wrapper {
+      float: left;
+      margin: 14px 0 0 14px;
+      padding: 16px;
+      transition: all 0.38s ease-out;
+      border-radius: 6px;
+    }
+
+    .card-panel-icon {
+      float: left;
+      font-size: 48px;
+    }
+
+    .card-panel-description {
+      float: right;
+      font-weight: bold;
+      margin: 26px;
+      margin-left: 0px;
+
+      .card-panel-text {
+        line-height: 18px;
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 16px;
+        margin-bottom: 12px;
+      }
+
+      .card-panel-num {
+        font-size: 20px;
+      }
+    }
+  }
+}
+
+@media (max-width:550px) {
+  .card-panel-description {
+    display: none;
+  }
+
+  .card-panel-icon-wrapper {
+    float: none !important;
+    width: 100%;
+    height: 100%;
+    margin: 0 !important;
+
+    .svg-icon {
+      display: block;
+      margin: 14px auto !important;
+      float: none !important;
+    }
+  }
+}
+</style>

+ 83 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/PieChart.vue

@@ -0,0 +1,83 @@
+<template>
+  <div ref="chartRef" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import * as echarts from 'echarts'
+import { useChartResize } from './useChartResize'
+
+const props = defineProps({
+  className: {
+    type: String,
+    default: 'chart'
+  },
+  width: {
+    type: String,
+    default: '100%'
+  },
+  height: {
+    type: String,
+    default: '300px'
+  }
+})
+
+const chartRef = ref(null)
+const chartInstance = ref(null)
+const { initResizeListener, removeResizeListener } = useChartResize(chartInstance)
+
+const initChart = () => {
+  if (!chartRef.value) return
+
+  if (chartInstance.value) {
+    chartInstance.value.dispose()
+  }
+
+  chartInstance.value = echarts.init(chartRef.value, 'macarons')
+
+  chartInstance.value.setOption({
+    tooltip: {
+      trigger: 'item',
+      formatter: '{a} <br/>{b} : {c} ({d}%)'
+    },
+    legend: {
+      left: 'center',
+      bottom: '10',
+      data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
+    },
+    series: [
+      {
+        name: 'WEEKLY WRITE ARTICLES',
+        type: 'pie',
+        roseType: 'radius',
+        radius: [15, 95],
+        center: ['50%', '38%'],
+        data: [
+          { value: 320, name: 'Industries' },
+          { value: 240, name: 'Technology' },
+          { value: 149, name: 'Forex' },
+          { value: 100, name: 'Gold' },
+          { value: 59, name: 'Forecasts' }
+        ],
+        animationEasing: 'cubicInOut',
+        animationDuration: 2600
+      }
+    ]
+  })
+}
+
+onMounted(() => {
+  nextTick(() => {
+    initChart()
+    initResizeListener(chartRef.value)
+  })
+})
+
+onBeforeUnmount(() => {
+  removeResizeListener()
+  if (chartInstance.value) {
+    chartInstance.value.dispose()
+    chartInstance.value = null
+  }
+})
+</script>

+ 120 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/RaddarChart.vue

@@ -0,0 +1,120 @@
+<template>
+  <div ref="chartRef" :class="className" :style="{height:height,width:width}" />
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick,markRaw } from 'vue'
+import * as echarts from 'echarts'
+import { useChartResize } from './useChartResize'
+
+const animationDuration = 3000
+
+const props = defineProps({
+  className: {
+    type: String,
+    default: 'chart'
+  },
+  width: {
+    type: String,
+    default: '100%'
+  },
+  height: {
+    type: String,
+    default: '300px'
+  }
+})
+
+const chartRef = ref(null)
+const chartInstance = ref(null)
+const { initResizeListener, removeResizeListener } = useChartResize(chartInstance)
+
+const initChart = () => {
+  if (!chartRef.value) return
+
+  if (chartInstance.value) {
+    chartInstance.value.dispose()
+  }
+
+  chartInstance.value = markRaw(echarts.init(chartRef.value, 'macarons'))
+
+  chartInstance.value.setOption({
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    radar: {
+      radius: '66%',
+      center: ['50%', '42%'],
+      splitNumber: 8,
+      splitArea: {
+        areaStyle: {
+          color: 'rgba(127,95,132,.3)',
+          opacity: 1,
+          shadowBlur: 45,
+          shadowColor: 'rgba(0,0,0,.5)',
+          shadowOffsetX: 0,
+          shadowOffsetY: 15
+        }
+      },
+      indicator: [
+        { name: 'Sales', max: 10000 },
+        { name: 'Administration', max: 20000 },
+        { name: 'Information Techology', max: 20000 },
+        { name: 'Customer Support', max: 20000 },
+        { name: 'Development', max: 20000 },
+        { name: 'Marketing', max: 20000 }
+      ]
+    },
+    legend: {
+      left: 'center',
+      bottom: '10',
+      data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
+    },
+    series: [{
+      type: 'radar',
+      symbolSize: 0,
+      areaStyle: {
+        normal: {
+          shadowBlur: 13,
+          shadowColor: 'rgba(0,0,0,.2)',
+          shadowOffsetX: 0,
+          shadowOffsetY: 10,
+          opacity: 1
+        }
+      },
+      data: [
+        {
+          value: [5000, 7000, 12000, 11000, 15000, 14000],
+          name: 'Allocated Budget'
+        },
+        {
+          value: [4000, 9000, 15000, 15000, 13000, 11000],
+          name: 'Expected Spending'
+        },
+        {
+          value: [5500, 11000, 12000, 15000, 12000, 12000],
+          name: 'Actual Spending'
+        }
+      ],
+      animationDuration: animationDuration
+    }]
+  })
+}
+
+onMounted(() => {
+  nextTick(() => {
+    initChart()
+    initResizeListener(chartRef.value)
+  })
+})
+
+onBeforeUnmount(() => {
+  removeResizeListener()
+  if (chartInstance.value) {
+    chartInstance.value.dispose()
+    chartInstance.value = null
+  }
+})
+</script>

+ 0 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/mixins/resize.js


+ 34 - 0
RuoYi-Cloud-Vue3-master/src/views/dashboard/useChartResize.js

@@ -0,0 +1,34 @@
+import { onMounted, onBeforeUnmount, ref } from 'vue'
+
+export function useChartResize(chartInstance) {
+    let isDestroyed = false
+    const handleResize = () => {
+        if (isDestroyed || !chartInstance.value) {
+            return
+        }
+        try {
+            chartInstance.value.resize()
+        } catch (error) {
+            console.error('Error resizing chart:', error)
+        }
+    }
+
+    const initResizeListener = () => {
+        window.addEventListener('resize', handleResize)
+    }
+
+    const removeResizeListener = () => {
+        window.removeEventListener('resize', handleResize)
+        isDestroyed = true
+    }
+
+    onMounted(() => {
+        initResizeListener()
+    })
+
+    onBeforeUnmount(() => {
+        removeResizeListener()
+    })
+
+    return { handleResize, initResizeListener, removeResizeListener }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 62 - 1038
RuoYi-Cloud-Vue3-master/src/views/index.vue


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1059 - 0
RuoYi-Cloud-Vue3-master/src/views/index_v1.vue


+ 16 - 2
RuoYi-Cloud-Vue3-master/vite.config.js

@@ -6,6 +6,16 @@ import createVitePlugins from './vite/plugins'
 export default defineConfig(({ mode, command }) => {
   const env = loadEnv(mode, process.cwd())
   const { VITE_APP_ENV } = env
+
+
+  // 添加调试信息
+  console.log('=== 环境变量调试 ===')
+  console.log('mode:', mode)
+  console.log('cwd:', process.cwd())
+  console.log('env对象:', env)
+  console.log('VITE_APP_API_BASE_URL:', env.VITE_APP_API_BASE_URL)
+  console.log('process.env.VUE_APP_BASE_API:', process.env.VUE_APP_BASE_API)
+  console.log('===================')
   return {
     // 部署生产环境和开发环境下的URL。
     // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
@@ -46,9 +56,13 @@ export default defineConfig(({ mode, command }) => {
       proxy: {
         // https://cn.vitejs.dev/config/#server-proxy
         '/dev-api': {
-          target: 'http://localhost:8080',
+          target: env.VITE_APP_API_BASE_URL,
           changeOrigin: true,
-          rewrite: (p) => p.replace(/^\/dev-api/, '')
+          rewrite: (p) => p.replace(/^\/dev-api/, ''),
+          configure: (proxy, options) => {
+            // 可以在这里打印日志,看看代理配置是否正确
+            console.log('Proxy configured for:', options.target);
+          }
         }
       }
     },