Explorar o código

feat: 集成 eslint

qinlaiqiao %!s(int64=3) %!d(string=hai) anos
pai
achega
2fe6b8c963

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+/build
+/dist
+/public
+vue.config.js

+ 80 - 0
.eslintrc.js

@@ -0,0 +1,80 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true,
+  },
+  extends: [
+    'plugin:vue/vue3-essential',
+    '@vue/airbnb',
+    '@vue/typescript/recommended',
+    '@vue/prettier',
+    '@vue/prettier/@typescript-eslint',
+  ],
+  parserOptions: {
+    ecmaVersion: 2020,
+    parser: '@typescript-eslint/parser',
+  },
+  rules: {
+    'import/extensions': [
+      'error',
+      'ignorePackages',
+      {
+        js: 'never',
+        mjs: 'never',
+        jsx: 'never',
+        ts: 'never',
+        tsx: 'never',
+      },
+    ],
+    'import/no-unresolved': 'off',
+    '@typescript-eslint/no-empty-function': 'off',
+    '@typescript-eslint/no-explicit-any': 'off',
+    '@typescript-eslint/explicit-module-boundary-types': 'off',
+    '@typescript-eslint/no-non-null-assertion': 'off',
+    'no-unused-expressions': [
+      'error',
+      {
+        allowShortCircuit: true,
+      },
+    ],
+    'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
+    'no-restricted-syntax': 'off',
+    'no-shadow': 'off',
+    'vue/no-v-model-argument': 'off',
+    '@typescript-eslint/no-shadow': 'error',
+    '@typescript-eslint/interface-name-prefix': 'off',
+    '@typescript-eslint/no-var-requires': 'off',
+    'no-return-assign': 'off',
+    'no-param-reassign': 'off',
+    'no-plusplus': 'off',
+    'class-methods-use-this': 'off',
+    'no-await-in-loop': 'off',
+    'no-continue': 'off',
+    'guard-for-in': 'off',
+    'no-return-await': 'off',
+    'prefer-destructuring': 'off',
+    '@typescript-eslint/no-this-alias': 'off',
+    'import/order': [
+      'error',
+      {
+        pathGroups: [
+          {
+            pattern: '@/**',
+            group: 'internal',
+          },
+        ],
+        groups: [['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object']],
+      },
+    ],
+  },
+  globals: {
+  },
+  overrides: [
+    {
+      files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
+      env: {
+        mocha: true,
+      },
+    },
+  ],
+};

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 5015 - 192
package-lock.json


+ 9 - 0
package.json

@@ -29,8 +29,17 @@
     "@types/animejs": "^3.1.4",
     "@types/jest": "^26.0.23",
     "@types/koa-bodyparser": "^4.3.1",
+    "@typescript-eslint/eslint-plugin": "^5.3.0",
+    "@typescript-eslint/parser": "^5.3.0",
     "@vitejs/plugin-vue": "^1.9.3",
+    "@vue/cli-plugin-eslint": "^4.5.15",
+    "@vue/eslint-config-airbnb": "^5.3.0",
+    "@vue/eslint-config-prettier": "^6.0.0",
+    "@vue/eslint-config-typescript": "^9.0.1",
     "autoprefixer": "^10.4.0",
+    "eslint": "^8.1.0",
+    "eslint-plugin-prettier": "^4.0.0",
+    "eslint-plugin-vue": "^8.0.3",
     "jest": "^26.6.3",
     "postcss": "^8.3.11",
     "sass": "^1.43.4",

+ 2 - 2
src/App.vue

@@ -2,11 +2,11 @@
 </script>
 
 <template>
-  <router-view/>
+  <router-view />
 </template>
 
 <style lang="scss">
 #app {
-  @apply w-full h-full
+  @apply w-full h-full;
 }
 </style>

+ 2 - 2
src/main.ts

@@ -1,4 +1,4 @@
-import {createApp} from 'vue'
+import { createApp } from 'vue'
 import App from './App.vue'
 import ElementPlus from 'element-plus'
 import zhCn from 'element-plus/es/locale/lang/zh-cn'
@@ -6,6 +6,6 @@ import '@/styles/index.scss';
 import router from './router';
 
 const app = createApp(App)
-app.use(ElementPlus, {size: 'mini', locale: zhCn,})
+app.use(ElementPlus, { size: 'mini', locale: zhCn, })
 app.use(router)
 app.mount('#app')

+ 1 - 1
src/router/index.ts

@@ -1,4 +1,4 @@
-import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router';
+import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
 
 const routes: Array<RouteRecordRaw> = [
     {

+ 2 - 2
src/styles/_main.scss

@@ -6,7 +6,8 @@ html {
   body {
     width: 100%;
     height: 100%;
-    font-family: "微软雅黑", "Microsoft YaHei", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
+    font-family: "微软雅黑", "Microsoft YaHei", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial,
+      sans-serif;
     -webkit-font-smoothing: antialiased; /*chrome、safari*/
     -moz-osx-font-smoothing: grayscale; /*firefox*/
     -webkit-text-size-adjust: none;
@@ -18,4 +19,3 @@ html {
 @tailwind base;
 @tailwind components;
 @tailwind utilities;
-

+ 101 - 20
src/styles/_reset.scss

@@ -3,19 +3,87 @@
    License: none (public domain)
 */
 
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
   margin: 0;
   padding: 0;
   border: 0;
@@ -24,8 +92,17 @@ time, mark, audio, video {
 }
 
 /* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
   display: block;
 }
 
@@ -33,17 +110,21 @@ body {
   line-height: 1;
 }
 
-ol, ul {
+ol,
+ul {
   list-style: none;
 }
 
-blockquote, q {
+blockquote,
+q {
   quotes: none;
 }
 
-blockquote:before, blockquote::after,
-q:before, q::after {
-  content: '';
+blockquote:before,
+blockquote::after,
+q:before,
+q::after {
+  content: "";
   content: none;
 }
 

+ 1 - 3
src/styles/index.scss

@@ -1,9 +1,7 @@
 @import "reset.scss";
 @import "main.scss";
 @import "element_plus";
-@import 'animate.css';
+@import "animate.css";
 
 // iconfont,新增图标需要更新此url
 @import url("//at.alicdn.com/t/font_2835708_bg21nztdnq5.css");
-
-

+ 1 - 2
src/views/home/Home.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
-import {ref} from 'vue'
-
+import { ref } from "vue";
 </script>
 
 <template>

+ 69 - 32
src/views/login/Login.vue

@@ -1,36 +1,41 @@
 <script setup lang="ts">
-import {onMounted, ref} from 'vue'
+import { onMounted, ref } from "vue";
 import useRotateCanvas from "./scripts/rotateCanvas";
-import usePreloadImg from './scripts/preloadImg'
-import useModuleItem from './scripts/moduleItem'
+import usePreloadImg from "./scripts/preloadImg";
+import useModuleItem from "./scripts/moduleItem";
 
 // video 元素的模板引用
-const loginVideoRef = ref<HTMLVideoElement>()
+const loginVideoRef = ref<HTMLVideoElement>();
+
 // 设置视频播放速度
 const setVideoRate = (rate = 0.75) => {
-  if (loginVideoRef.value)
-    loginVideoRef.value.playbackRate = rate
-}
+  if (loginVideoRef.value) loginVideoRef.value.playbackRate = rate;
+};
 
 onMounted(() => {
   // 设置视频播放速度
-  setVideoRate()
+  setVideoRate();
   // 预加载 模块item hover图片
-  usePreloadImg()
-})
+  usePreloadImg();
+});
 
 // 底部旋转 canvas
-const {canvasRef} = useRotateCanvas()
-const {
-  moduleRef,
-} = useModuleItem()
+const { canvasRef } = useRotateCanvas();
+const { moduleRef } = useModuleItem();
 </script>
 
 <template>
   <article class="login-page">
     <!-- 视频背景 -->
-    <video ref="loginVideoRef" class="video-bg" poster="@/assets/login-bg-poster.jpg" autoplay loop muted>
-      <source src="@/assets/login-bg-video.mp4" type="video/mp4"/>
+    <video
+      ref="loginVideoRef"
+      class="video-bg"
+      poster="@/assets/login-bg-poster.jpg"
+      autoplay
+      loop
+      muted
+    >
+      <source src="@/assets/login-bg-video.mp4" type="video/mp4" />
     </video>
 
     <!-- 标题 -->
@@ -47,13 +52,13 @@ const {
       <div class="panel">
         <!-- 用户名 -->
         <div class="input-wrap username">
-          <input class="input" type="text" placeholder="用户名">
-          <i class="line"/>
+          <input class="input" type="text" placeholder="用户名" />
+          <i class="line" />
         </div>
         <!-- 密码 -->
         <div class="input-wrap password">
-          <input class="input" type="password" placeholder="密码">
-          <i class="line"/>
+          <input class="input" type="password" placeholder="密码" />
+          <i class="line" />
         </div>
         <!-- 登录按钮 -->
         <div class="login-btn">
@@ -71,15 +76,41 @@ const {
       </div>
       <!-- 功能模块 -->
       <ul class="module" ref="moduleRef">
-        <li class="item budget animate__animated animate__bounceIn" ref="budgetRef">预算审核模块</li>
-        <li class="item estimate animate__animated animate__bounceIn" ref="estimateRef">估/概算模块</li>
-        <li class="item util animate__animated animate__bounceIn" ref="utilRef">基础工具模块</li>
-        <li class="item settlement animate__animated animate__bounceIn" ref="settlementRef">结算审核模块</li>
-        <li class="item final animate__animated animate__bounceIn" ref="finalRef">决算审核模块</li>
-        <li class="item check animate__animated animate__bounceIn" ref="checkRef">检测功能模块</li>
+        <li
+          class="item budget animate__animated animate__bounceIn"
+          ref="budgetRef"
+        >
+          预算审核模块
+        </li>
+        <li
+          class="item estimate animate__animated animate__bounceIn"
+          ref="estimateRef"
+        >
+          估/概算模块
+        </li>
+        <li class="item util animate__animated animate__bounceIn" ref="utilRef">
+          基础工具模块
+        </li>
+        <li
+          class="item settlement animate__animated animate__bounceIn"
+          ref="settlementRef"
+        >
+          结算审核模块
+        </li>
+        <li
+          class="item final animate__animated animate__bounceIn"
+          ref="finalRef"
+        >
+          决算审核模块
+        </li>
+        <li
+          class="item check animate__animated animate__bounceIn"
+          ref="checkRef"
+        >
+          检测功能模块
+        </li>
       </ul>
     </main>
-
   </article>
 </template>
 
@@ -198,7 +229,7 @@ const {
         .line {
           @apply absolute w-0;
           height: 2px;
-          content: ' ';
+          content: " ";
           bottom: -2px;
           background-color: #459ef7;
           transition: width 0.2s;
@@ -213,7 +244,7 @@ const {
           width: 120px;
           height: 40px;
           line-height: 40px;
-          background: url('@/assets/login-btn.png') no-repeat;
+          background: url("@/assets/login-btn.png") no-repeat;
           background-size: 100%;
           color: #9ae1f9;
           font-size: 18px;
@@ -233,7 +264,12 @@ const {
           .flash {
             @apply absolute top-0 w-1/3 h-full;
             left: -100%;
-            background: linear-gradient(to right, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0) 100%);
+            background: linear-gradient(
+              to right,
+              rgba(255, 255, 255, 0) 0,
+              rgba(255, 255, 255, 0.4) 50%,
+              rgba(255, 255, 255, 0) 100%
+            );
             transform: skewX(-45deg);
             animation-iteration-count: infinite;
           }
@@ -268,10 +304,11 @@ const {
         @apply absolute flex justify-center cursor-pointer transform-gpu select-none opacity-95;
         width: 180px;
         height: 156px;
-        color: #44C4EF;
+        color: #44c4ef;
         font-size: 22px;
         padding-top: 40px;
-        background: url("@/assets/login-module-item-normal.png") no-repeat center;
+        background: url("@/assets/login-module-item-normal.png") no-repeat
+          center;
         background-size: cover;
         transition: all 0.26s;
 

+ 1 - 1
src/views/login/scripts/moduleItem.ts

@@ -1,4 +1,4 @@
-import {onMounted, ref} from 'vue'
+import { onMounted, ref } from 'vue'
 
 export default function useModuleItem() {
     const budgetRef = ref<HTMLLIElement>()

+ 1 - 1
src/views/login/scripts/preloadImg.ts

@@ -1,5 +1,5 @@
 import hoverImgUrl from '@/assets/login-module-item-hover.png'
-import {loadImage} from "../../../utils/frontend/loadImage";
+import { loadImage } from "../../../utils/frontend/loadImage";
 
 export default function usePreloadImg() {
     loadImage(hoverImgUrl)

+ 1 - 1
src/views/login/scripts/rotateCanvas.ts

@@ -1,4 +1,4 @@
-import {onMounted, ref} from "vue";
+import { onMounted, ref } from "vue";
 import blueImageUrl from '@/assets/login-rotate-blue.png'
 import yellowImageUrl from '@/assets/login-rotate-yellow.png'