Explorar o código

feat: 加入动画淡入效果

Eason-87 hai 5 días
pai
achega
87e5c2a1fd

+ 0 - 6
components.d.ts

@@ -20,13 +20,7 @@ declare module 'vue' {
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
-    ElMenu: typeof import('element-plus/es')['ElMenu']
-    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
-    ElSwitch: typeof import('element-plus/es')['ElSwitch']
-    ElTable: typeof import('element-plus/es')['ElTable']
-    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTag: typeof import('element-plus/es')['ElTag']
     Header: typeof import('./src/components/home/header.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']

+ 1 - 1
package.json

@@ -16,9 +16,9 @@
   "dependencies": {
     "@iconify/iconify": "^3.1.1",
     "@iconify/vue": "^5.0.0",
-    "@kjgl77/datav-vue3": "^1.7.4",
     "axios": "^1.13.1",
     "element-plus": "^2.11.7",
+    "motion-v": "^1.7.4",
     "pinia": "^3.0.3",
     "vue": "^3.5.22",
     "vue-router": "^4.6.3"

+ 63 - 59
pnpm-lock.yaml

@@ -14,15 +14,15 @@ importers:
       '@iconify/vue':
         specifier: ^5.0.0
         version: 5.0.0(vue@3.5.22(typescript@5.9.3))
-      '@kjgl77/datav-vue3':
-        specifier: ^1.7.4
-        version: 1.7.4(vue@3.5.22(typescript@5.9.3))
       axios:
         specifier: ^1.13.1
         version: 1.13.1
       element-plus:
         specifier: ^2.11.7
         version: 2.11.7(vue@3.5.22(typescript@5.9.3))
+      motion-v:
+        specifier: ^1.7.4
+        version: 1.7.4(@vueuse/core@10.11.1(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))
       pinia:
         specifier: ^3.0.3
         version: 3.0.3(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))
@@ -209,10 +209,6 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0-0
 
-  '@babel/runtime@7.28.4':
-    resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/template@7.27.2':
     resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
     engines: {node: '>=6.9.0'}
@@ -411,21 +407,6 @@ packages:
     peerDependencies:
       vue: '>=3'
 
-  '@jiaminghi/bezier-curve@0.0.9':
-    resolution: {integrity: sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==}
-
-  '@jiaminghi/c-render@0.4.3':
-    resolution: {integrity: sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==}
-
-  '@jiaminghi/charts@0.2.18':
-    resolution: {integrity: sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==}
-
-  '@jiaminghi/color@1.1.3':
-    resolution: {integrity: sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg==}
-
-  '@jiaminghi/transition@1.1.11':
-    resolution: {integrity: sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==}
-
   '@jridgewell/gen-mapping@0.3.13':
     resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
 
@@ -442,9 +423,6 @@ packages:
   '@jridgewell/trace-mapping@0.3.31':
     resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
 
-  '@kjgl77/datav-vue3@1.7.4':
-    resolution: {integrity: sha512-zYVTVKkklUxwtiNKS1qPBilm4rTW+WItfp0zVpaRAI8wgXkLSPbDR9xPq2+UcU/Jft7/DVdMfBp709E2ResuPQ==}
-
   '@polka/url@1.0.0-next.29':
     resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
 
@@ -997,6 +975,20 @@ packages:
   fraction.js@4.3.7:
     resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
 
+  framer-motion@12.23.12:
+    resolution: {integrity: sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==}
+    peerDependencies:
+      '@emotion/is-prop-valid': '*'
+      react: ^18.0.0 || ^19.0.0
+      react-dom: ^18.0.0 || ^19.0.0
+    peerDependenciesMeta:
+      '@emotion/is-prop-valid':
+        optional: true
+      react:
+        optional: true
+      react-dom:
+        optional: true
+
   fsevents@2.3.3:
     resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
     engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1036,6 +1028,9 @@ packages:
     resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
     engines: {node: '>= 0.4'}
 
+  hey-listen@1.0.8:
+    resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
+
   hookable@5.5.3:
     resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
 
@@ -1209,6 +1204,18 @@ packages:
   mlly@1.8.0:
     resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
 
+  motion-dom@12.23.12:
+    resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==}
+
+  motion-utils@12.23.6:
+    resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
+
+  motion-v@1.7.4:
+    resolution: {integrity: sha512-YNDUAsany04wfI7YtHxQK3kxzNvh+OdFUk9GpA3+hMt7j6P+5WrVAAgr8kmPPoVza9EsJiAVhqoN3YYFN0Twrw==}
+    peerDependencies:
+      '@vueuse/core': '>=10.0.0'
+      vue: '>=3.0.0'
+
   mrmime@2.0.1:
     resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
     engines: {node: '>=10'}
@@ -1384,6 +1391,9 @@ packages:
     resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
     engines: {node: '>=6'}
 
+  tslib@2.8.1:
+    resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
   typescript@5.9.3:
     resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
     engines: {node: '>=14.17'}
@@ -1732,8 +1742,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/runtime@7.28.4': {}
-
   '@babel/template@7.27.2':
     dependencies:
       '@babel/code-frame': 7.27.1
@@ -1863,28 +1871,6 @@ snapshots:
       '@iconify/types': 2.0.0
       vue: 3.5.22(typescript@5.9.3)
 
-  '@jiaminghi/bezier-curve@0.0.9':
-    dependencies:
-      '@babel/runtime': 7.28.4
-
-  '@jiaminghi/c-render@0.4.3':
-    dependencies:
-      '@babel/runtime': 7.28.4
-      '@jiaminghi/bezier-curve': 0.0.9
-      '@jiaminghi/color': 1.1.3
-      '@jiaminghi/transition': 1.1.11
-
-  '@jiaminghi/charts@0.2.18':
-    dependencies:
-      '@babel/runtime': 7.28.4
-      '@jiaminghi/c-render': 0.4.3
-
-  '@jiaminghi/color@1.1.3': {}
-
-  '@jiaminghi/transition@1.1.11':
-    dependencies:
-      '@babel/runtime': 7.28.4
-
   '@jridgewell/gen-mapping@0.3.13':
     dependencies:
       '@jridgewell/sourcemap-codec': 1.5.5
@@ -1904,16 +1890,6 @@ snapshots:
       '@jridgewell/resolve-uri': 3.1.2
       '@jridgewell/sourcemap-codec': 1.5.5
 
-  '@kjgl77/datav-vue3@1.7.4(vue@3.5.22(typescript@5.9.3))':
-    dependencies:
-      '@jiaminghi/c-render': 0.4.3
-      '@jiaminghi/charts': 0.2.18
-      '@jiaminghi/color': 1.1.3
-      '@vueuse/core': 10.11.1(vue@3.5.22(typescript@5.9.3))
-    transitivePeerDependencies:
-      - '@vue/composition-api'
-      - vue
-
   '@polka/url@1.0.0-next.29': {}
 
   '@rolldown/pluginutils@1.0.0-beta.29': {}
@@ -2481,6 +2457,12 @@ snapshots:
 
   fraction.js@4.3.7: {}
 
+  framer-motion@12.23.12:
+    dependencies:
+      motion-dom: 12.23.12
+      motion-utils: 12.23.6
+      tslib: 2.8.1
+
   fsevents@2.3.3:
     optional: true
 
@@ -2520,6 +2502,8 @@ snapshots:
     dependencies:
       function-bind: 1.1.2
 
+  hey-listen@1.0.8: {}
+
   hookable@5.5.3: {}
 
   is-docker@3.0.0: {}
@@ -2646,6 +2630,24 @@ snapshots:
       pkg-types: 1.3.1
       ufo: 1.6.1
 
+  motion-dom@12.23.12:
+    dependencies:
+      motion-utils: 12.23.6
+
+  motion-utils@12.23.6: {}
+
+  motion-v@1.7.4(@vueuse/core@10.11.1(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)):
+    dependencies:
+      '@vueuse/core': 10.11.1(vue@3.5.22(typescript@5.9.3))
+      framer-motion: 12.23.12
+      hey-listen: 1.0.8
+      motion-dom: 12.23.12
+      vue: 3.5.22(typescript@5.9.3)
+    transitivePeerDependencies:
+      - '@emotion/is-prop-valid'
+      - react
+      - react-dom
+
   mrmime@2.0.1: {}
 
   ms@2.1.3: {}
@@ -2811,6 +2813,8 @@ snapshots:
 
   totalist@3.0.1: {}
 
+  tslib@2.8.1: {}
+
   typescript@5.9.3: {}
 
   ufo@1.6.1: {}

+ 10 - 3
src/App.vue

@@ -1,9 +1,16 @@
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { motion } from "motion-v";
+</script>
 
 <template>
-  <div class="overflow-x-hidden">
+  <motion.div
+    class="overflow-x-hidden"
+    :key="$route.fullPath"
+    :initial="{ opacity: 0 }"
+    :animate="{ opacity: 1, transition: { duration: 0.8, ease: 'easeOut' } }"
+  >
     <router-view></router-view>
-  </div>
+  </motion.div>
 </template>
 
 <style scoped></style>

BIN=BIN
src/assets/images/bg.png


+ 0 - 1
src/assets/style/main.css

@@ -3,7 +3,6 @@
 @layer base {
   body,
   #app {
-    @apply w-screen h-screen;
     overflow-x: hidden;
   }
 }

+ 1 - 1
src/components/home/CardItem.vue

@@ -55,7 +55,7 @@ const props = defineProps<{
   desc: string;
   items: Item[];
   bg: string;
-  key: string;
+
   id: string;
 }>();
 

+ 4 - 0
src/router/index.ts

@@ -41,6 +41,10 @@ const routes: RouteRecordRaw[] = [
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes,
+  scrollBehavior(to, from, savePosition) {
+    // 始终滚动到顶部
+    return { left: 0, top: 0 };
+  },
 });
 
 export default router;

+ 1 - 8
src/types/cards.ts

@@ -1,8 +1 @@
-export type Card = {
-  key: string;
-  title: string;
-  desc: string;
-  bg: string;
-  items: Array<{ label: string; tag?: "新" | "热" }>;
-  id: string;
-};
+

+ 16 - 7
src/views/index.vue

@@ -40,7 +40,9 @@
       </div>
     </section>
 
-    <section class="max-w-[1200px] mx-auto px-2 mb-8 mt-6 flex justify-center">
+    <section
+      class="max-w-[1200px] mx-auto px-2 mb-8 mt-6 flex justify-center items-center gap-3"
+    >
       <p class="text-2xl">提供多维度、更可靠的数智化服务</p>
     </section>
 
@@ -48,7 +50,6 @@
       <div class="grid gap-5 grid-cols-1 md:grid-cols-3 xl:grid-cols-3">
         <CardItem
           v-for="card in cards"
-          :key="card.key"
           :title="card.title"
           :id="card.id"
           :desc="card.desc"
@@ -66,14 +67,22 @@ import CardItem from "@components/home/CardItem.vue";
 import img1 from "@/assets/images/1.jpg";
 import img2 from "@/assets/images/2.jpg";
 import img3 from "@/assets/images/3.jpg";
-import { type Card } from "@types/cards";
 import bgVideo from "@/assets/bg.mp4";
 
+type Card = {
+  name: string;
+  title: string;
+  desc: string;
+  bg: string;
+  items: Array<{ label: string; tag?: "新" | "热" }>;
+  id: string;
+};
+
 const cards: Card[] = [
   {
-    key: "device",
+    name: "device",
     title: "经营管理平台",
-    desc: "通过设备物联,实时掌握车间动态信息",
+    desc: "集成财务、研发、客户、人力等关键业务数据,为管理者提供全局态势感知和战略决策支持",
     id: "management",
     bg: img1,
     items: [
@@ -89,7 +98,7 @@ const cards: Card[] = [
     ],
   },
   {
-    key: "scene",
+    name: "scene",
     title: "生产指挥平台",
     desc: "深入工业场景,为中小企业数字化升级赋能",
     id: "command",
@@ -105,7 +114,7 @@ const cards: Card[] = [
     ],
   },
   {
-    key: "factory",
+    name: "factory",
     title: "Chat BI平台",
     desc: "工厂上云,高效协同,生产效率和产品质量提升",
     id: "chatbi",

+ 17 - 18
src/views/login.vue

@@ -1,24 +1,22 @@
 <template>
-  <div class="min-h-screen grid grid-cols-1 lg:grid-cols-2">
-    <!-- Left visual area -->
-    <div class="relative hidden lg:block">
-      <img
-        src="/src/assets/images/1.jpg"
-        alt="visual"
-        class="absolute inset-0 w-full h-full object-cover"
-      />
-      <div class="absolute inset-0 bg-black/20"></div>
-      <div class="relative z-10 p-6 flex items-start">
-        <div class="flex items-center gap-3">
-          <img :src="logo" alt="logo" class="h-9" />
-          <span class="text-white text-lg font-semibold">智慧经营平台</span>
-        </div>
-      </div>
+  <div class="min-h-screen relative flex items-center justify-center">
+    <!-- Background image -->
+    <img
+      :src="bgImage"
+      alt="background"
+      class="absolute inset-0 w-full h-full object-cover"
+    />
+    <div class="absolute inset-0 bg-black/10"></div>
+
+    <!-- Logo and title at top -->
+    <div class="absolute top-6 left-6 z-10 flex items-center gap-3">
+      <img :src="logo" alt="logo" class="h-9" />
+      <span class="text-white text-lg font-semibold">智慧经营平台</span>
     </div>
 
-    <!-- Right login form -->
-    <div class="flex items-center justify-center p-6">
-      <div class="w-full max-w-[420px]">
+    <!-- Login form centered -->
+    <div class="relative z-10 w-full max-w-[420px] px-6">
+      <div class="bg-white/95 backdrop-blur-sm rounded-lg p-8 shadow-2xl">
         <h1 class="text-2xl font-bold text-center mb-8">登录</h1>
 
         <el-form
@@ -65,6 +63,7 @@
 import { reactive, ref } from "vue";
 import { ElMessage } from "element-plus";
 import logo from "@/assets/images/logo.png";
+import bgImage from "@/assets/images/bg.png";
 
 type LoginForm = {
   username: string;

+ 3 - 1
src/views/management.vue

@@ -5,7 +5,9 @@
     <section class="max-w-[1200px] mx-auto mt-20 mb-8 px-4">
       <div class="text-center mb-8">
         <h2 class="text-[28px] font-bold text-[#0644a1]">经营管理平台</h2>
-        <p class="mt-2 text-[#606266]">通过设备物联,实时掌握车间动态信息</p>
+        <p class="mt-2 text-[#606266]">
+          集成财务、研发、客户、人力等关键业务数据,为管理者提供全局态势感知和战略决策支持。
+        </p>
       </div>
 
       <div class="grid grid-cols-1 md:grid-cols-3 gap-6">

+ 4 - 1
vite.config.ts

@@ -8,8 +8,10 @@ import tailwindcss from "@tailwindcss/vite";
 import AutoImport from "unplugin-auto-import/vite";
 import Components from "unplugin-vue-components/vite";
 import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
+import MotionResolver from "motion-v/resolver";
 
 export default defineConfig({
+  base: "./",
   plugins: [
     vue(),
     vueDevTools(),
@@ -18,7 +20,8 @@ export default defineConfig({
       resolvers: [ElementPlusResolver()],
     }),
     Components({
-      resolvers: [ElementPlusResolver()],
+      dts: true,
+      resolvers: [ElementPlusResolver(), MotionResolver()],
     }),
   ],
   resolve: {