LiXiang преди 2 години
ревизия
700d680540

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 3 - 0
.vscode/extensions.json

@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
+}

+ 7 - 0
README.md

@@ -0,0 +1,7 @@
+# Vue 3 + Vite
+
+This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
+
+## Recommended IDE Setup
+
+- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).

+ 16 - 0
index.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <link rel="icon" href="./public/favicon.ico" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>生产测试软件</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.js"></script>
+</body>
+
+</html>

Файловите разлики са ограничени, защото са твърде много
+ 1167 - 0
package-lock.json


+ 33 - 0
package.json

@@ -0,0 +1,33 @@
+{
+  "name": "txproject",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@element-plus/icons": "^0.0.11",
+    "@element-plus/icons-vue": "^2.1.0",
+    "@vueuse/core": "^10.0.2",
+    "axios": "^1.3.6",
+    "element-plus": "^2.3.3",
+    "pinia": "^2.0.33",
+    "vue": "^3.2.47",
+    "vue-router": "^4.1.6"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^4.1.0",
+    "autoprefixer": "^10.4.14",
+    "postcss": "^8.4.23",
+    "sass": "^1.62.0",
+    "tailwindcss": "^3.3.1",
+    "unplugin-auto-import": "^0.15.3",
+    "unplugin-icons": "^0.16.1",
+    "unplugin-vue-components": "^0.24.1",
+    "vite": "^4.2.0",
+    "vite-plugin-vue-setup-extend": "^0.4.0"
+  }
+}

+ 6 - 0
postcss.config.js

@@ -0,0 +1,6 @@
+export default {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+}

BIN
public/favicon.ico


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
public/vite.svg


+ 7 - 0
src/App.vue

@@ -0,0 +1,7 @@
+<template>
+  <router-view></router-view>
+</template>
+<script setup>
+import Layout from './views/Layout.vue'
+
+</script>

+ 10 - 0
src/api/login.js

@@ -0,0 +1,10 @@
+import request from './request'
+
+export const login = params => {
+  console.log(params)
+  return request({
+    url: 'url',
+    method: 'post',
+    params,
+  })
+}

+ 28 - 0
src/api/request.js

@@ -0,0 +1,28 @@
+import axios from 'axios'
+
+const instance = axios.create({
+  baseURL: '',
+  timeout: 1000 * 30,
+})
+
+// 添加请求拦截器
+instance.interceptors.request.use(
+  function (config) {
+    return config
+  },
+  function (error) {
+    console.log(error)
+    return Promise.reject(error)
+  }
+)
+
+// 添加响应拦截器
+instance.interceptors.response.use(
+  function (response) {
+    return response
+  },
+  function (error) {
+    return Promise.reject(error)
+  }
+)
+export default instance

BIN
src/assets/images/paper.png


+ 1 - 0
src/assets/vue.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

+ 63 - 0
src/auto-imports.d.ts

@@ -0,0 +1,63 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by unplugin-auto-import
+export {}
+declare global {
+  const EffectScope: typeof import('vue')['EffectScope']
+  const computed: typeof import('vue')['computed']
+  const createApp: typeof import('vue')['createApp']
+  const customRef: typeof import('vue')['customRef']
+  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
+  const defineComponent: typeof import('vue')['defineComponent']
+  const effectScope: typeof import('vue')['effectScope']
+  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
+  const getCurrentScope: typeof import('vue')['getCurrentScope']
+  const h: typeof import('vue')['h']
+  const inject: typeof import('vue')['inject']
+  const isProxy: typeof import('vue')['isProxy']
+  const isReactive: typeof import('vue')['isReactive']
+  const isReadonly: typeof import('vue')['isReadonly']
+  const isRef: typeof import('vue')['isRef']
+  const markRaw: typeof import('vue')['markRaw']
+  const nextTick: typeof import('vue')['nextTick']
+  const onActivated: typeof import('vue')['onActivated']
+  const onBeforeMount: typeof import('vue')['onBeforeMount']
+  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
+  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
+  const onDeactivated: typeof import('vue')['onDeactivated']
+  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
+  const onMounted: typeof import('vue')['onMounted']
+  const onRenderTracked: typeof import('vue')['onRenderTracked']
+  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
+  const onScopeDispose: typeof import('vue')['onScopeDispose']
+  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
+  const onUnmounted: typeof import('vue')['onUnmounted']
+  const onUpdated: typeof import('vue')['onUpdated']
+  const provide: typeof import('vue')['provide']
+  const reactive: typeof import('vue')['reactive']
+  const readonly: typeof import('vue')['readonly']
+  const ref: typeof import('vue')['ref']
+  const resolveComponent: typeof import('vue')['resolveComponent']
+  const shallowReactive: typeof import('vue')['shallowReactive']
+  const shallowReadonly: typeof import('vue')['shallowReadonly']
+  const shallowRef: typeof import('vue')['shallowRef']
+  const toRaw: typeof import('vue')['toRaw']
+  const toRef: typeof import('vue')['toRef']
+  const toRefs: typeof import('vue')['toRefs']
+  const triggerRef: typeof import('vue')['triggerRef']
+  const unref: typeof import('vue')['unref']
+  const useAttrs: typeof import('vue')['useAttrs']
+  const useCssModule: typeof import('vue')['useCssModule']
+  const useCssVars: typeof import('vue')['useCssVars']
+  const useSlots: typeof import('vue')['useSlots']
+  const watch: typeof import('vue')['watch']
+  const watchEffect: typeof import('vue')['watchEffect']
+  const watchPostEffect: typeof import('vue')['watchPostEffect']
+  const watchSyncEffect: typeof import('vue')['watchSyncEffect']
+}
+// for type re-export
+declare global {
+  // @ts-ignore
+  export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
+}

+ 25 - 0
src/components.d.ts

@@ -0,0 +1,25 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+import '@vue/runtime-core'
+
+export {}
+
+declare module '@vue/runtime-core' {
+  export interface GlobalComponents {
+    ElAside: typeof import('element-plus/es')['ElAside']
+    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElContainer: typeof import('element-plus/es')['ElContainer']
+    ElHeader: typeof import('element-plus/es')['ElHeader']
+    ElIcon: typeof import('element-plus/es')['ElIcon']
+    ElMain: typeof import('element-plus/es')['ElMain']
+    ElMenu: typeof import('element-plus/es')['ElMenu']
+    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
+    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    Layout: typeof import('./components/Layout.vue')['default']
+    RouterLink: typeof import('vue-router')['RouterLink']
+    RouterView: typeof import('vue-router')['RouterView']
+  }
+}

+ 3 - 0
src/composables/dark.js

@@ -0,0 +1,3 @@
+import { useDark, useToggle } from '@vueuse/core'
+export const isDark = useDark()
+export const toggleDark = useToggle(isDark)

+ 31 - 0
src/directive/loading/index.js

@@ -0,0 +1,31 @@
+import { createApp } from 'vue'
+import Loading from './index.vue'
+
+const loading = {
+  mounted(el, binding) {
+    const app = createApp(Loading)
+    console.log(binding)
+    const instance = app.mount(document.createElement('div'))
+    console.log(el)
+    el.instance = instance
+    el.style.position = 'relative'
+    if (binding.value) {
+      appendEl(el)
+    }
+  },
+  updated(el, binding) {
+    if (binding.value !== binding.oldValue) {
+      binding.value ? appendEl(el) : removeEl(el)
+    }
+  },
+}
+
+const appendEl = el => {
+  el.appendChild(el.instance.$el)
+}
+
+const removeEl = el => {
+  el.removeChild(el.instance.$el)
+}
+
+export default loading

+ 107 - 0
src/directive/loading/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="box">
+    <div class="load-container">
+      <div class="boxLoading"></div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+</script>
+
+<script>
+export default {
+  name: ''
+}
+</script>
+<style scoped lang="scss">
+.box {
+  z-index: 999;
+  position: static;
+  width: 100%;
+  height: 100%;
+  background-color: rgba($color: #333, $alpha: .9);
+}
+
+.load-container {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  width: 90px;
+  height: 90px;
+  margin: 0 auto;
+
+  .boxLoading {
+    width: 50px;
+    height: 50px;
+    margin: auto;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 0;
+    bottom: 0;
+
+    &:before {
+      content: "";
+      width: 50px;
+      height: 5px;
+      background: #000;
+      opacity: 0.1;
+      position: absolute;
+      top: 59px;
+      left: 0;
+      border-radius: 50%;
+      animation: shadow 0.5s linear infinite;
+    }
+
+    &:after {
+      content: "";
+      width: 50px;
+      height: 50px;
+      background: #00adb5;
+      animation: animate 0.5s linear infinite;
+      position: absolute;
+      top: 0;
+      left: 0;
+      border-radius: 3px;
+    }
+  }
+}
+
+@keyframes animate {
+  17% {
+    border-bottom-right-radius: 3px;
+  }
+
+  25% {
+    transform: translateY(9px) rotate(22.5deg);
+  }
+
+  50% {
+    transform: translateY(18px) scale(1, 0.9) rotate(45deg);
+    border-bottom-right-radius: 40px;
+  }
+
+  75% {
+    transform: translateY(9px) rotate(67.5deg);
+  }
+
+  100% {
+    transform: translateY(0) rotate(90deg);
+  }
+}
+
+@keyframes shadow {
+
+  0%,
+  100% {
+    transform: scale(1, 1);
+  }
+
+  50% {
+    transform: scale(1.2, 1);
+  }
+}
+</style>

+ 31 - 0
src/hooks/useLogin.js

@@ -0,0 +1,31 @@
+import { ElMessage } from 'element-plus'
+import { ref, computed } from 'vue'
+import { useRouter } from 'vue-router'
+import { useStorage } from '@vueuse/core'
+export function useLogin() {
+  const router = useRouter()
+  const isLogin = computed(() => {
+    console.log(token.value)
+    console.log(Boolean(token.value))
+    return Boolean(token.value)
+  })
+  const token = useStorage('token', '')
+  const login = async ({ name, pwd }) => {
+    if (name != 'admin') return ElMessage.error('用户名不存在!')
+    if (pwd != 'admin') return ElMessage.error('密码错误!')
+    token.value = 'txCJ9.wSyVG5XeJaWDDbISCu6F_YJQ84PM-97gtktIEiUIfeI'
+    router.replace('/home')
+    ElMessage.success('登录成功!')
+  }
+  const logout = () => {
+    token.value = ''
+    router.replace('/login')
+    ElMessage.success('登出成功!')
+  }
+  return {
+    token,
+    isLogin,
+    logout,
+    login,
+  }
+}

+ 3 - 0
src/index.css

@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;

+ 21 - 0
src/main.js

@@ -0,0 +1,21 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import './style/index.scss'
+import './index.css'
+import router from './router'
+import store from './store'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import mloaidng from './directive/loading'
+const app = createApp(App)
+
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component(key, component)
+}
+// 自定义指令
+app.directive('mloading', mloaidng)
+app.use(router).use(store)
+app.use(ElementPlus)
+
+app.mount('#app')

+ 38 - 0
src/router/index.js

@@ -0,0 +1,38 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import { useLogin } from '@/hooks/useLogin'
+const { isLogin, token } = useLogin()
+const routes = [
+  {
+    path: '/login',
+    name: 'login',
+    component: () => import('../views/Login.vue'),
+  },
+  {
+    path: '/',
+    component: () => import('../views/Layout.vue'),
+    redirect: '/home',
+    children: [
+      {
+        path: '/home',
+        name: 'home',
+        component: () => import('../views/Home.vue'),
+      },
+      {
+        path: '/test',
+        name: 'test',
+        component: () => import('../views/Test.vue'),
+      },
+    ],
+  },
+]
+const router = createRouter({
+  history: createWebHistory(),
+  routes,
+})
+
+router.beforeEach((to, from, next) => {
+  if (!token.value && to.path !== '/login') next({ path: '/login' })
+  if (token.value && to.path == '/login') next({ path: '/home' })
+  else next()
+})
+export default router

+ 5 - 0
src/store/index.js

@@ -0,0 +1,5 @@
+import { createPinia } from 'pinia'
+
+const store = createPinia()
+
+export default store

+ 22 - 0
src/store/testTodo.js

@@ -0,0 +1,22 @@
+import { defineStore } from 'pinia'
+
+export const useTodos = defineStore('todos', {
+  state: () => ({
+    todoList: [{ text: '测试', id: '12asd', isFinished: false }],
+    nextId: 0,
+    testObj: {
+      name: 'TEST',
+      age: 18,
+    },
+  }),
+  actions: {
+    addTodo() {
+      // this.testObj.name = 'TEST' + new Date().getTime()
+      this.todoList.push({
+        text: '测试' + new Date().getTime(),
+        id: new Date().getTime(),
+        isFinished: false,
+      })
+    },
+  },
+})

+ 3 - 0
src/style/elementReset.scss

@@ -0,0 +1,3 @@
+.el-menu.el-menu--vertical {
+  height: calc(100vh - 50px);
+}

+ 24 - 0
src/style/index.scss

@@ -0,0 +1,24 @@
+@use './reset.scss';
+@use './elementReset.scss';
+// 深色模式
+@use 'element-plus/theme-chalk/src/dark/css-vars.scss' as *;
+
+body {
+  height: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  text-rendering: optimizeLegibility;
+  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
+    Microsoft YaHei, Arial, sans-serif;
+  font-size: 16px;
+}
+
+html {
+  height: 100%;
+  box-sizing: border-box;
+}
+
+#app {
+  height: 100%;
+  width: 100vw;
+}

+ 104 - 0
src/style/reset.scss

@@ -0,0 +1,104 @@
+/* 去除浏览器默认的margin和padding, 自行删减一些不必要的标签 */
+body,
+p,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+dl,
+dd,
+ul,
+ol,
+th,
+td,
+button,
+figure,
+input,
+textarea,
+form,
+pre,
+blockquote,
+figure {
+  margin: 0;
+  padding: 0;
+}
+
+a {
+  /* 小手 */
+  cursor: pointer;
+  /* 取消超链接的默认下划线 */
+  text-decoration: none;
+  /* antd里面还做了 , 看你团队需不需要这样的风格 */
+  transition: color 0.3s ease;
+}
+
+ol,
+ul {
+  /* 去除自带的ugly样式。 */
+  list-style: none;
+}
+
+/* 这些节点部分属性没有继承父节点样式,所有继承一下,并取消outline,外轮廓的效果 */
+a,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+input,
+select,
+button,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  font-weight: inherit;
+  font-style: inherit;
+  line-height: inherit;
+  color: inherit;
+  outline: none;
+}
+
+button,
+input[type='submit'],
+input[type='button'] {
+  /* 可点击小手 */
+  cursor: pointer;
+}
+
+/* 取消部分浏览器数字输入控件的操作按钮 apperance可以改变控件的外观。 */
+input[type='number'] {
+  -moz-appearance: textfield;
+}
+
+input[type='number']::-webkit-inner-spin-button,
+input[type='number']::-webkit-outer-spin-button {
+  margin: 0;
+  -webkit-appearance: none;
+}
+
+/**
+* 删除Firefox中的内边框和填充。
+*/
+button::-moz-focus-inner,
+[type='button']::-moz-focus-inner,
+[type='reset']::-moz-focus-inner,
+[type='submit']::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+/**
+* 让html5中的hidden在IE10中正确显示
+*/
+
+[hidden] {
+  display: none;
+}
+
+template {
+  /* 有些浏览器会显示template 不过template标签用的也少,自行取舍。 */
+  display: none;
+}

+ 15 - 0
src/views/Home.vue

@@ -0,0 +1,15 @@
+<template>
+  <el-calendar v-model="value" />
+
+</template>
+<script setup >
+import { ref } from 'vue'
+const value = ref(new Date())
+</script>
+<script>
+export default {
+  name: 'Home',
+}
+</script>
+<style scoped lang="scss">
+</style>

+ 52 - 0
src/views/Layout.vue

@@ -0,0 +1,52 @@
+<template>
+  <el-config-provider>
+    <el-container class="layout-container-demo">
+      <!-- 头 -->
+      <el-header class="my-header">
+        <el-icon size="25" :color="isDark ? '#FFFF66' : '#aeFFF66'" class=" font-bold cursor-pointer mr-5"
+          @click="toggleDark()">
+          <Sunny class=" font-bold" v-show="isDark" />
+          <Moon v-show="!isDark" />
+        </el-icon>
+        <el-button @click="logout">登出</el-button>
+      </el-header>
+
+      <el-container style="height:calc(100vh - 50px)">
+        <!-- 左侧菜单 -->
+        <el-aside width="200px">
+          <el-scrollbar>
+            <el-menu router :default-active="route.path">
+              <el-menu-item index="/test">Test</el-menu-item>
+              <el-menu-item index="/home">主页</el-menu-item>
+            </el-menu>
+          </el-scrollbar>
+        </el-aside>
+        <!-- 右侧显示内容 -->
+        <el-container>
+          <el-main>
+            <router-view></router-view>
+          </el-main>
+        </el-container>
+      </el-container>
+    </el-container>
+  </el-config-provider>
+</template>
+
+<script setup>
+import { toggleDark, isDark } from '@/composables/dark'
+import { useRoute } from 'vue-router'
+import { useLogin } from '@/hooks/useLogin'
+const route = useRoute()
+const { isLogin, logout } = useLogin()
+</script>
+
+<style scoped lang="scss">
+.my-header {
+  height: 50px;
+  display: flex;
+  align-items: center;
+  justify-content: end;
+  border-bottom: solid 1px var(--el-menu-border-color);
+  background-color: var(--el-menu-bg-color);
+}
+</style>

+ 78 - 0
src/views/Login.vue

@@ -0,0 +1,78 @@
+<template>
+  <div class="login-box flex items-center justify-center">
+    <el-card shadow="always" class="m-card">
+      <el-form ref="loginForm" size="large" :model="form" :rules="rules" label-width="40px" hide-required-asterisk>
+        <el-form-item label="账号" prop="name" class=" mt-10">
+          <el-input v-model="form.name" />
+        </el-form-item>
+        <el-form-item label="密码" prop="pwd" class="mt-10">
+          <el-input type="password" v-model="form.pwd" @keyup.enter="onSubmit" />
+        </el-form-item>
+        <el-form-item label-width="0" class="mt-10">
+          <div style="width: 100%;" class=" flex items-center justify-center">
+            <el-button round type="primary" @click="onSubmit">登 录</el-button>
+          </div>
+        </el-form-item>
+      </el-form>
+    </el-card>
+  </div>
+</template>
+
+<script  setup>
+import { ref } from 'vue'
+import { useLogin } from '@/hooks/useLogin'
+const { login, isLogin } = useLogin()
+const loginForm = ref()
+const form = ref({
+  name: '',
+  pwd: ''
+})
+
+const rules = ref({
+  name: { required: true, message: 'Please input Name', trigger: 'blur' },
+  pwd: { required: true, message: 'Please input Password ', trigger: 'blur' },
+})
+
+const onSubmit = () => {
+  loginForm.value.validate(valid => {
+    if (!valid) return
+    login(form.value)
+  })
+}
+</script>
+
+<style scoped lang="scss">
+.login-box {
+  overflow: hidden;
+  width: 100vw;
+  height: 100vh;
+  position: relative;
+  background-color: #FFFFFD;
+  background-image: url('@/assets/images/paper.png');
+
+  &::before,
+  &::after {
+    content: '';
+    z-index: -1;
+    position: absolute;
+    left: 10px;
+    bottom: 10px;
+    width: 45%;
+    height: 55%;
+    max-height: 100px;
+    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
+    transform: skew(-15deg) rotate(-4deg);
+  }
+
+  &::after {
+    left: auto;
+    right: 10px;
+    transform: skew(15deg) rotate(4deg);
+  }
+}
+
+.m-card {
+  width: 400px;
+  height: 300px;
+}
+</style>

+ 22 - 0
src/views/Test.vue

@@ -0,0 +1,22 @@
+<template>
+  <div>
+    测试页面
+    <el-color-picker v-model="color" show-alpha />
+
+  </div>
+</template>
+
+<script setup >
+import { ref } from 'vue'
+const color = ref('rgba(219, 206, 202, 0.8)')
+
+// onBeforeRouteLeave(() => {
+//   window.confirm("确认要离开页面吗")
+// })
+</script>
+<script>
+export default {
+  name: 'Test',
+}
+</script>
+<style scoped lang="scss"></style>

+ 9 - 0
tailwind.config.js

@@ -0,0 +1,9 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+  content: [],
+  purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
+  theme: {
+    extend: {},
+  },
+  plugins: [],
+}

+ 25 - 0
vite.config.js

@@ -0,0 +1,25 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import AutoImport from 'unplugin-auto-import/vite'
+import Icons from 'unplugin-icons/vite'
+import IconsResolver from 'unplugin-icons/resolver'
+import Components from 'unplugin-vue-components/vite'
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
+import path from 'path'
+const pathSrc = path.resolve(__dirname, 'src')
+export default defineConfig({
+  resolve: {
+    alias: {
+      '@': pathSrc,
+    },
+  },
+  plugins: [
+    vue(),
+    AutoImport({
+      resolvers: [ElementPlusResolver()],
+    }),
+    Components({
+      resolvers: [ElementPlusResolver()],
+    }),
+  ],
+})

Файловите разлики са ограничени, защото са твърде много
+ 1577 - 0
yarn.lock