Browse Source

feat(VInputPassword): Add VInputPassword Component

陈凯龙 3 năm trước cách đây
mục cha
commit
a1bf7e9b55

+ 0 - 19
.pnpm-debug.log

@@ -1,19 +0,0 @@
-{
-  "0 debug pnpm:scope": {
-    "selected": 1
-  },
-  "1 error pnpm": {
-    "errno": 1,
-    "code": "ELIFECYCLE",
-    "pkgid": "butterfly-admin@3.0.0",
-    "stage": "clean",
-    "script": "npx rimraf docs/node_modules && npx rimraf node_modules",
-    "pkgname": "butterfly-admin",
-    "err": {
-      "name": "pnpm",
-      "message": "butterfly-admin@3.0.0 clean: `npx rimraf docs/node_modules && npx rimraf node_modules`\nExit status 1",
-      "code": "ELIFECYCLE",
-      "stack": "pnpm: butterfly-admin@3.0.0 clean: `npx rimraf docs/node_modules && npx rimraf node_modules`\nExit status 1\n    at EventEmitter.<anonymous> (C:\\Users\\Saber\\AppData\\Roaming\\nvm\\v16.0.0\\node_modules\\pnpm\\dist\\pnpm.cjs:103540:20)\n    at EventEmitter.emit (node:events:365:28)\n    at ChildProcess.<anonymous> (C:\\Users\\Saber\\AppData\\Roaming\\nvm\\v16.0.0\\node_modules\\pnpm\\dist\\pnpm.cjs:91469:18)\n    at ChildProcess.emit (node:events:365:28)\n    at maybeClose (node:internal/child_process:1067:16)\n    at Process.ChildProcess._handle.onexit (node:internal/child_process:301:5)"
-    }
-  }
-}

+ 1 - 0
index.html

@@ -39,6 +39,7 @@
         }
 
         .app-loading .app-loading-logo {
+          width: 100px;
           margin: 0 auto 15px auto;
         }
 

+ 27 - 26
package.json

@@ -25,60 +25,61 @@
     "postinstall": "husky install"
   },
   "dependencies": {
-    "@vueuse/core": "^7.1.2",
+    "@vueuse/core": "^7.4.1",
+    "@zxcvbn-ts/core": "^1.2.0",
     "element-plus": "1.2.0-beta.6",
     "lodash-es": "^4.17.21",
-    "pinia": "^2.0.6",
-    "vue": "^3.2.24",
+    "pinia": "^2.0.9",
+    "vue": "3.2.26",
     "vue-i18n": "9.1.9",
     "vue-router": "^4.0.12",
     "vue-types": "^4.1.1"
   },
   "devDependencies": {
-    "@commitlint/cli": "^15.0.0",
-    "@commitlint/config-conventional": "^15.0.0",
-    "@iconify/json": "^1.1.441",
+    "@commitlint/cli": "^16.0.1",
+    "@commitlint/config-conventional": "^16.0.0",
+    "@iconify/json": "^1.1.448",
     "@intlify/vite-plugin-vue-i18n": "^3.2.1",
     "@types/lodash-es": "^4.17.5",
-    "@types/node": "^16.11.12",
-    "@typescript-eslint/eslint-plugin": "^5.6.0",
-    "@typescript-eslint/parser": "^5.6.0",
-    "@vitejs/plugin-vue": "^1.9.3",
-    "@vitejs/plugin-vue-jsx": "^1.3.0",
+    "@types/node": "^17.0.5",
+    "@typescript-eslint/eslint-plugin": "^5.8.1",
+    "@typescript-eslint/parser": "^5.8.1",
+    "@vitejs/plugin-vue": "^2.0.1",
+    "@vitejs/plugin-vue-jsx": "^1.3.3",
     "async-validator": "^4.0.7",
-    "autoprefixer": "^10.4.0",
+    "autoprefixer": "^10.4.1",
     "commitizen": "^4.2.4",
-    "eslint": "^8.4.1",
+    "eslint": "^8.5.0",
     "eslint-config-prettier": "^8.3.0",
-    "eslint-define-config": "^1.2.0",
+    "eslint-define-config": "^1.2.1",
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-vue": "^8.2.0",
     "husky": "^7.0.4",
     "less": "^4.1.2",
-    "lint-staged": "^12.1.2",
-    "postcss": "^8.4.4",
+    "lint-staged": "^12.1.4",
+    "postcss": "^8.4.5",
     "postcss-html": "^1.3.0",
     "postcss-less": "^5.0.0",
     "prettier": "^2.5.1",
-    "pretty-quick": "^3.1.2",
+    "pretty-quick": "^3.1.3",
     "rimraf": "^3.0.2",
-    "stylelint": "^14.1.0",
+    "stylelint": "^14.2.0",
     "stylelint-config-html": "^1.0.0",
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-standard": "^24.0.0",
     "stylelint-order": "^5.0.0",
-    "typescript": "4.5.2",
-    "unplugin-icons": "^0.12.23",
-    "vite": "2.6.14",
+    "typescript": "4.5.4",
+    "unplugin-icons": "^0.13.0",
+    "vite": "2.7.9",
     "vite-plugin-eslint": "^1.3.0",
-    "vite-plugin-style-import": "^1.4.0",
-    "vite-plugin-windicss": "^1.5.4",
-    "vue-tsc": "^0.3.0",
-    "windicss": "^3.2.1",
+    "vite-plugin-style-import": "^1.4.1",
+    "vite-plugin-windicss": "^1.6.1",
+    "vue-tsc": "^0.30.1",
+    "windicss": "^3.4.1",
     "windicss-analysis": "^0.3.5"
   },
   "engines": {
-    "node": ">= 16.0.0"
+    "node": ">= 14.0.0"
   },
   "license": "MIT"
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 200 - 404
pnpm-lock.yaml


BIN
public/favicon.ico


BIN
public/logo.png


+ 74 - 53
src/App.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { reactive, ref, onMounted, markRaw } from 'vue'
 import { ElConfigProvider, ElIcon } from 'element-plus'
+import { VConfigGlobal } from '@/components/ConfigGlobal'
 import zhCn from 'element-plus/lib/locale/lang/zh-cn'
 // import en from 'element-plus/lib/locale/lang/en'
 import { VFrom } from '@/components/Form'
@@ -1016,73 +1017,93 @@ const schema = reactive<VFormSchema[]>([
     field: 'field63',
     component: 'TimeSelect',
     label: t('formDemo.default')
+  },
+  {
+    field: 'field64',
+    component: 'Divider',
+    label: t('formDemo.inputPassword')
+  },
+  {
+    field: 'field65',
+    component: 'InputPassword',
+    label: t('formDemo.default')
+  },
+  {
+    field: 'field66',
+    component: 'InputPassword',
+    label: t('formDemo.passwordStrength'),
+    componentProps: {
+      strength: true
+    }
   }
 ])
 </script>
 
 <template>
-  <ElConfigProvider :locale="zhCn">
-    <VFrom :schema="schema">
-      <template #field4-prefix>
-        <ElIcon class="el-input__icon"><Calendar /></ElIcon>
-      </template>
-      <template #field4-suffix>
-        <ElIcon class="el-input__icon"><Calendar /></ElIcon>
-      </template>
+  <VConfigGlobal>
+    <ElConfigProvider :locale="zhCn">
+      <VFrom :schema="schema">
+        <template #field4-prefix>
+          <ElIcon class="el-input__icon"><Calendar /></ElIcon>
+        </template>
+        <template #field4-suffix>
+          <ElIcon class="el-input__icon"><Calendar /></ElIcon>
+        </template>
 
-      <template #field5-prepend> Http:// </template>
-      <template #field5-append> .com </template>
+        <template #field5-prepend> Http:// </template>
+        <template #field5-append> .com </template>
 
-      <template #field9-default="{ item }">
-        <div class="value">{{ item.value }}</div>
-        <span class="link">{{ item.link }}</span>
-      </template>
+        <template #field9-default="{ item }">
+          <div class="value">{{ item.value }}</div>
+          <span class="link">{{ item.link }}</span>
+        </template>
 
-      <template #field15-option="{ item }">
-        <span style="float: left">{{ item.label }}</span>
-        <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
-          {{ item.value }}
-        </span>
-      </template>
+        <template #field15-option="{ item }">
+          <span style="float: left">{{ item.label }}</span>
+          <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
+            {{ item.value }}
+          </span>
+        </template>
 
-      <template #field17-option="{ item }">
-        <span style="float: left">{{ item.label }}</span>
-        <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
-          {{ item.value }}
-        </span>
-      </template>
+        <template #field17-option="{ item }">
+          <span style="float: left">{{ item.label }}</span>
+          <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
+            {{ item.value }}
+          </span>
+        </template>
 
-      <template #field20-default="{ item }">
-        <span style="float: left">{{ item.label }}</span>
-        <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
-          {{ item.value }}
-        </span>
-      </template>
+        <template #field20-default="{ item }">
+          <span style="float: left">{{ item.label }}</span>
+          <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
+            {{ item.value }}
+          </span>
+        </template>
 
-      <template #field22-default="{ item }">
-        <span style="float: left">{{ item.label }}</span>
-        <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
-          {{ item.value }}
-        </span>
-      </template>
+        <template #field22-default="{ item }">
+          <span style="float: left">{{ item.label }}</span>
+          <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
+            {{ item.value }}
+          </span>
+        </template>
 
-      <template #field25-default="{ node, data }">
-        <span>{{ data.label }}</span>
-        <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
-      </template>
+        <template #field25-default="{ node, data }">
+          <span>{{ data.label }}</span>
+          <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
+        </template>
 
-      <template #field36-default="{ option }">
-        <span>{{ option.value }} - {{ option.desc }}</span>
-      </template>
+        <template #field36-default="{ option }">
+          <span>{{ option.value }} - {{ option.desc }}</span>
+        </template>
 
-      <template #field55-default="cell">
-        <div class="cell" :class="{ current: cell.isCurrent }">
-          <span class="text">{{ cell.text }}</span>
-          <span v-if="isHoliday(cell)" class="holiday"></span>
-        </div>
-      </template>
-    </VFrom>
-  </ElConfigProvider>
+        <template #field55-default="cell">
+          <div class="cell" :class="{ current: cell.isCurrent }">
+            <span class="text">{{ cell.text }}</span>
+            <span v-if="isHoliday(cell)" class="holiday"></span>
+          </div>
+        </template>
+      </VFrom>
+    </ElConfigProvider>
+  </VConfigGlobal>
 </template>
 
 <style lang="less" scoped>

+ 3 - 0
src/components/ConfigGlobal/index.ts

@@ -0,0 +1,3 @@
+import VConfigGlobal from './src/VConfigGlobal.vue'
+
+export { VConfigGlobal }

+ 15 - 0
src/components/ConfigGlobal/src/VConfigGlobal.vue

@@ -0,0 +1,15 @@
+<script lang="tsx">
+import { provide, defineComponent } from 'vue'
+import { vConfigGlobalProps } from './props'
+
+export default defineComponent({
+  name: 'VConfigGlobal',
+  inheritAttrs: false,
+  props: vConfigGlobalProps,
+  setup(props, { slots }) {
+    provide('configGlobal', props)
+
+    return () => slots.default?.()
+  }
+})
+</script>

+ 5 - 0
src/components/ConfigGlobal/src/props.ts

@@ -0,0 +1,5 @@
+import { propTypes } from '@/utils/propTypes'
+
+export const vConfigGlobalProps = {
+  size: propTypes.oneOf(['default', 'medium', 'small', 'mini']).def('default')
+}

+ 14 - 5
src/components/Form/src/VForm.vue

@@ -1,5 +1,5 @@
 <script lang="tsx">
-import { PropType, defineComponent, ref, computed, unref, reactive, watch } from 'vue'
+import { PropType, defineComponent, ref, computed, unref, watch } from 'vue'
 import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
 import { componentMap } from './componentMap'
 import { propTypes } from '@/utils/propTypes'
@@ -9,7 +9,7 @@ import {
   setGridProp,
   setComponentProps,
   setItemComponentSlots,
-  setModel
+  initModel
 } from './helper'
 import { useRenderSelect } from './components/useRenderSelect'
 import { useRenderRadio } from './components/useRenderRadio'
@@ -44,13 +44,22 @@ export default defineComponent({
     const getProps = computed(() => props)
     const { schema, isCol, isCustom, autoSetPlaceholder } = unref(getProps)
     // 表单数据
-    const formModel = reactive<Recordable>({})
+    const formModel = ref<Recordable>({})
+    watch(
+      () => formModel.value,
+      (formModel: Recordable) => {
+        console.log(formModel)
+      },
+      {
+        deep: true
+      }
+    )
 
     // 监听表单结构化数组,重新生成formModel
     watch(
       () => schema,
       (schema) => {
-        setModel(schema, formModel)
+        formModel.value = initModel(schema, unref(formModel))
       },
       {
         immediate: true,
@@ -108,7 +117,7 @@ export default defineComponent({
             const Com = componentMap[item.component as string] as ReturnType<typeof defineComponent>
             return (
               <Com
-                vModel={formModel[item.field]}
+                vModel={formModel.value[item.field]}
                 {...(autoSetPlaceholder && setTextPlaceholder(item))}
                 {...setComponentProps(item)}
                 {...(notRenderOptions.includes(item?.component as string) &&

+ 3 - 1
src/components/Form/src/componentMap.ts

@@ -18,6 +18,7 @@ import {
   ElAutocomplete,
   ElDivider
 } from 'element-plus'
+import { VInputPassword } from '@/components/InputPassword'
 
 const componentMap: Recordable<Component, ComponentName> = {
   Radio: ElRadioGroup,
@@ -38,7 +39,8 @@ const componentMap: Recordable<Component, ComponentName> = {
   Divider: ElDivider,
   TimeSelect: ElTimeSelect,
   SelectV2: ElSelectV2,
-  RadioButton: ElRadioGroup
+  RadioButton: ElRadioGroup,
+  InputPassword: VInputPassword
 }
 
 export { componentMap }

+ 8 - 5
src/components/Form/src/helper.ts

@@ -17,7 +17,7 @@ interface PlaceholderMoel {
  * @description 用于自动设置placeholder
  */
 export function setTextPlaceholder(schema: VFormSchema): PlaceholderMoel {
-  const textMap = ['Input', 'Autocomplete', 'InputNumber']
+  const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword']
   const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect']
   if (textMap.includes(schema?.component as string)) {
     return {
@@ -114,17 +114,20 @@ export function setItemComponentSlots(
  *
  * @param schema Form表单结构化数组
  * @param formModel FormMoel
+ * @returns FormMoel
  * @description 生成对应的formModel
  */
-export function setModel(schema: VFormSchema[], formModel: Recordable) {
+export function initModel(schema: VFormSchema[], formModel: Recordable) {
+  const model: Recordable = { ...formModel }
   schema.map((v) => {
     // 如果是hidden,就删除对应的值
     if (v.hidden) {
-      delete formModel[v.field]
+      delete model[v.field]
     } else {
-      const hasField = Reflect.has(formModel, v.field)
+      const hasField = Reflect.has(model, v.field)
       // 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值
-      formModel[v.field] = hasField ? formModel[v.field] : v.value !== void 0 ? v.value : ''
+      model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : ''
     }
   })
+  return model
 }

+ 3 - 0
src/components/InputPassword/index.ts

@@ -0,0 +1,3 @@
+import VInputPassword from './src/VInputPassword.vue'
+
+export { VInputPassword }

+ 137 - 0
src/components/InputPassword/src/VInputPassword.vue

@@ -0,0 +1,137 @@
+<script setup lang="ts">
+import { ref, unref, computed, watch } from 'vue'
+import { ElInput, ElIcon } from 'element-plus'
+import EyeInvisibleOutlinedE from '~icons/ant-design/eyeInvisibleOutlined'
+import EyeOutlined from '~icons/ant-design/eye-outlined'
+import { propTypes } from '@/utils/propTypes'
+import { useDesign } from '@/hooks/web/useDesign'
+import { useConfigGlobal } from '@/hooks/web/useConfigGlobal'
+const { configGlobal } = useConfigGlobal()
+import { zxcvbn } from '@zxcvbn-ts/core'
+import type { ZxcvbnResult } from '@zxcvbn-ts/core'
+
+defineProps({
+  // 是否显示密码强度
+  strength: propTypes.bool.def(false),
+  modelValue: propTypes.string.def('')
+})
+
+const emit = defineEmits(['update:modelValue'])
+
+// 生成class前缀
+const { getPrefixCls } = useDesign()
+const prefixCls = ref(getPrefixCls('inputpassword'))
+
+// 设置input的type属性
+const textType = ref<'password' | 'text'>('password')
+function changeTextType() {
+  textType.value = unref(textType) === 'text' ? 'password' : 'text'
+}
+
+// 输入框的值
+const valueRef = ref('')
+// 监听
+watch(
+  () => valueRef.value,
+  (val: string) => {
+    emit('update:modelValue', val)
+  }
+)
+// 获取密码强度
+const getPasswordStrength = computed(() => {
+  const value = unref(valueRef)
+  const zxcvbnRef = zxcvbn(unref(valueRef)) as ZxcvbnResult
+  return value ? zxcvbnRef.score : -1
+})
+</script>
+
+<template>
+  <div :class="[prefixCls, `${prefixCls}--${configGlobal?.size}`]">
+    <ElInput v-bind="$attrs" v-model="valueRef" :type="textType">
+      <template #suffix>
+        <ElIcon class="el-input__icon el-input__clear">
+          <EyeInvisibleOutlinedE v-if="textType === 'password'" @click="changeTextType" />
+          <EyeOutlined v-else @click="changeTextType" />
+        </ElIcon>
+      </template>
+    </ElInput>
+    <div
+      v-if="strength"
+      :class="`${prefixCls}__bar`"
+      class="relative h-6px mt-10px mb-6px mr-auto ml-auto"
+    >
+      <div :class="`${prefixCls}__bar--fill`" :data-score="getPasswordStrength"></div>
+    </div>
+  </div>
+</template>
+
+<style lang="less" scoped>
+@prefix-cls: ~'@{namespace}-inputpassword';
+
+.@{prefix-cls} {
+  &__bar {
+    background-color: var(--el-text-color-disabled-base);
+    border-radius: var(--el-border-radius-base);
+
+    &::before,
+    &::after {
+      position: absolute;
+      z-index: 10;
+      display: block;
+      width: 20%;
+      height: inherit;
+      background-color: transparent;
+      border-color: var(--el-color-white);
+      border-style: solid;
+      border-width: 0 5px 0 5px;
+      content: '';
+    }
+
+    &::before {
+      left: 20%;
+    }
+
+    &::after {
+      right: 20%;
+    }
+
+    &--fill {
+      position: absolute;
+      width: 0;
+      height: inherit;
+      background-color: transparent;
+      border-radius: inherit;
+      transition: width 0.5s ease-in-out, background 0.25s;
+
+      &[data-score='0'] {
+        width: 20%;
+        background-color: var(--el-color-danger);
+      }
+
+      &[data-score='1'] {
+        width: 40%;
+        background-color: var(--el-color-danger);
+      }
+
+      &[data-score='2'] {
+        width: 60%;
+        background-color: var(--el-color-warning);
+      }
+
+      &[data-score='3'] {
+        width: 80%;
+        background-color: var(--el-color-success);
+      }
+
+      &[data-score='4'] {
+        width: 100%;
+        background-color: var(--el-color-success);
+      }
+    }
+  }
+
+  &--mini > &__bar {
+    border-radius: var(--el-border-radius-small);
+  }
+}
+</style>

+ 9 - 0
src/hooks/web/useConfigGlobal.ts

@@ -0,0 +1,9 @@
+import { inject } from 'vue'
+
+export function useConfigGlobal() {
+  const configGlobal = inject('configGlobal', {}) as VConfigGlobalTypes
+
+  return {
+    configGlobal
+  }
+}

+ 18 - 0
src/hooks/web/useDesign.ts

@@ -0,0 +1,18 @@
+import variables from '@/styles/variables.module.less'
+
+export function useDesign() {
+  const lessVariables = variables
+
+  /**
+   * @param scope 类名
+   * @returns 返回空间名-类名
+   */
+  function getPrefixCls(scope: string) {
+    return `${lessVariables.namespace}-${scope}`
+  }
+
+  return {
+    variables: lessVariables,
+    getPrefixCls
+  }
+}

+ 3 - 1
src/locales/en.ts

@@ -42,6 +42,8 @@ export default {
     dateTimePicker: 'DateTimePicker',
     dateTimerange: 'Datetime Range',
     timePicker: 'Time Picker',
-    timeSelect: 'Time Select'
+    timeSelect: 'Time Select',
+    inputPassword: 'input Password',
+    passwordStrength: 'Password Strength'
   }
 }

+ 3 - 1
src/locales/zh-CN.ts

@@ -42,6 +42,8 @@ export default {
     dateTimePicker: '日期时间选择器',
     dateTimerange: '日期时间范围',
     timePicker: '时间选择器',
-    timeSelect: '时间选择'
+    timeSelect: '时间选择',
+    inputPassword: '密码输入框',
+    passwordStrength: '密码强度'
   }
 }

+ 0 - 2
src/styles/variables.less

@@ -1,2 +0,0 @@
-// 命名空间
-@namespace: v;

+ 7 - 0
src/styles/variables.module.less

@@ -0,0 +1,7 @@
+// 命名空间
+@namespace: v;
+
+// 导出变量
+:export {
+  namespace: @namespace;
+}

+ 1 - 0
src/types/componentType.d.ts

@@ -23,6 +23,7 @@ declare global {
     | 'Divider'
     | 'TimeSelect'
     | 'SelectV2'
+    | 'InputPassword'
 
   declare type ColProps = {
     span?: number

+ 3 - 0
src/types/configGlobal.d.ts

@@ -0,0 +1,3 @@
+declare interface VConfigGlobalTypes {
+  size?: ElememtPlusSzie
+}

+ 1 - 1
src/types/global.d.ts

@@ -6,7 +6,7 @@ declare type Nullable<T> = T | null
 
 declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>
 
-declare type ElememtPlusSzie = 'medium' | 'small' | 'mini'
+declare type ElememtPlusSzie = 'default' | 'medium' | 'small' | 'mini'
 
 declare type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger'
 

+ 1 - 1
tsconfig.json

@@ -26,7 +26,7 @@
     "types": [
       "@intlify/vite-plugin-vue-i18n/client",
       "vite/client",
-      "./node_modules/element-plus/global",
+      "element-plus/global",
       "unplugin-icons/types/vue"
     ],
     "typeRoots": ["./node_modules/@types/", "./src/types"]

+ 7 - 30
vite.config.ts

@@ -3,11 +3,8 @@ import { loadEnv } from 'vite'
 import type { UserConfig, ConfigEnv } from 'vite'
 import Vue from '@vitejs/plugin-vue'
 import WindiCSS from 'vite-plugin-windicss'
-// import Components from 'unplugin-vue-components/vite'
-// import AutoImport from 'unplugin-auto-import/vite'
 import VueJsx from '@vitejs/plugin-vue-jsx'
 import EslintPlugin from 'vite-plugin-eslint'
-// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 import VueI18n from '@intlify/vite-plugin-vue-i18n'
 import Icons from 'unplugin-icons/vite'
 import StyleImport, { ElementPlusResolve } from 'vite-plugin-style-import'
@@ -23,12 +20,11 @@ function pathResolve(dir: string) {
 export default ({ command, mode }: ConfigEnv): UserConfig => {
   let env = null
   if (command === 'serve') {
-    env = loadEnv(process.argv[4], root)
+    env = loadEnv(process.argv[3], root)
   }
   else {
     env = loadEnv(mode, root)
   }
-
   return {
     base: env.VITE_BASE_PATH,
     plugins: [
@@ -45,33 +41,10 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
           }
         }]
       }),
-      // AutoImport({
-      //   imports: [
-      //     'vue',
-      //     'vue-router',
-      //     'vue-i18n',
-      //     '@vueuse/core'
-      //   ],
-      //   dts: 'src/types/auto-imports.d.ts'
-      // }),
       Icons({
         compiler: 'vue3',
         autoInstall: true
       }),
-      // Components({
-      //   dirs: ['src/components'],
-      //   extensions: ['vue', 'md'],
-      //   include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
-      //   // custom resolvers
-      //   resolvers: [
-      //     ElementPlusResolver(),
-      //     IconsResolver({
-      //       prefix: false,
-      //       enabledCollections : ['ep']
-      //     })
-      //   ],
-      //   dts: 'src/types/components.d.ts'
-      // }),
       EslintPlugin({
         cache: false,
         include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件
@@ -86,12 +59,13 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
     css: {
       preprocessorOptions: {
         less: {
-          additionalData: '@import "./src/styles/variables.less";',
+          additionalData: '@import "./src/styles/variables.module.less";',
           javascriptEnabled: true
         }
       }
     },
     resolve: {
+      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.less', '.css'],
       alias: [
         {
           find: 'vue-i18n',
@@ -105,7 +79,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
     },
     build: {
       minify: 'terser',
-      outDir: env.VITE_OUT_DIR,
+      outDir: env.VITE_OUT_DIR || 'dist',
       sourcemap: env.VITE_SOURCEMAP === 'true' ? 'inline' : false,
       brotliSize: false,
       terserOptions: {
@@ -131,6 +105,9 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
           changeOrigin: true,
           rewrite: path => path.replace(/^\/fallback/, '')
         }
+      },
+      hmr: {
+        overlay: false
       }
     },
     optimizeDeps: {

+ 13 - 0
windi.config.ts

@@ -1,5 +1,9 @@
 import { defineConfig } from 'windicss/helpers'
 
+// function range(size, startAt = 1) {
+//   return Array.from(Array(size).keys()).map((i) => i + startAt)
+// }
+
 export default defineConfig({
   extract: {
     include: ['src/**/*.{vue,html,jsx,tsx}'],
@@ -16,5 +20,14 @@ export default defineConfig({
         xl: '1920px'
       }
     }
+    // height: {
+    //   ...range(50).map((i) => `h-${i}px`)
+    // },
+    // margin: {
+    //   // ...range(50).map((i) => `mt-${i}px`),
+    //   // ...range(50).map((i) => `mr-${i}px`),
+    //   // ...range(50).map((i) => `mb-${i}px`),
+    //   // ...range(50).map((i) => `ml-${i}px`)
+    // }
   }
 })

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác