Browse Source

fix: stylelint not work

vben 10 months ago
parent
commit
59b4f7d9f8
32 changed files with 528 additions and 320 deletions
  1. 2 1
      .vscode/settings.json
  2. 1 1
      internal/lint-configs/stylelint-config/package.json
  3. 1 1
      internal/lint-configs/stylelint-config/src/index.ts
  4. 3 0
      internal/tailwind-config/package.json
  5. 1 8
      internal/tailwind-config/src/index.ts
  6. 3 0
      internal/tailwind-config/src/module.d.ts
  7. 0 22
      internal/tailwind-config/src/plugins.ts
  8. 2 1
      internal/tailwind-config/src/postcss.config.ts
  9. 0 5
      internal/vite-config/src/config/application.ts
  10. 1 1
      package.json
  11. 7 0
      packages/@vben-core/shared/chche/build.config.ts
  12. 43 0
      packages/@vben-core/shared/chche/package.json
  13. 1 0
      packages/@vben-core/shared/chche/src/index.ts
  14. 104 0
      packages/@vben-core/shared/chche/src/storage-cache.test.ts
  15. 145 0
      packages/@vben-core/shared/chche/src/storage-cache.ts
  16. 17 0
      packages/@vben-core/shared/chche/src/types.ts
  17. 5 0
      packages/@vben-core/shared/chche/tsconfig.json
  18. 2 0
      packages/@vben-core/shared/design-tokens/src/dark/index.scss
  19. 3 0
      packages/@vben-core/shared/design-tokens/src/default/index.scss
  20. 1 1
      packages/@vben-core/shared/design/build.config.ts
  21. 1 1
      packages/@vben-core/shared/design/src/scss/common/base.scss
  22. 15 4
      packages/@vben-core/shared/design/src/tailwind.css
  23. 1 1
      packages/business/common-ui/src/authentication/qrcode-login.vue
  24. 1 1
      packages/business/common-ui/src/fallback/fallback.vue
  25. 1 1
      packages/business/common-ui/src/preference/trigger.vue
  26. 1 3
      packages/business/common-ui/src/spinner/spinner.vue
  27. 1 1
      packages/business/layouts/src/authentication/authentication.vue
  28. 1 3
      packages/business/layouts/src/authentication/from-view.vue
  29. 0 2
      packages/styles/src/tokens/dark.scss
  30. 158 262
      pnpm-lock.yaml
  31. 2 0
      turbo.json
  32. 4 0
      vben-admin.code-workspace

+ 2 - 1
.vscode/settings.json

@@ -134,7 +134,8 @@
 
   "stylelint.enable": true,
   "stylelint.packageManager": "pnpm",
-  "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
+  "stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
+  "stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
 
   "typescript.inlayHints.enumMemberValues.enabled": true,
   "typescript.preferences.preferTypeOnlyAutoImports": true,

+ 1 - 1
internal/lint-configs/stylelint-config/package.json

@@ -40,7 +40,7 @@
     "postcss-html": "^1.7.0",
     "postcss-scss": "^4.0.9",
     "prettier": "^3.2.5",
-    "stylelint": "^16.6.0",
+    "stylelint": "^16.6.1",
     "stylelint-config-recommended": "^14.0.0",
     "stylelint-config-recommended-scss": "^14.0.0",
     "stylelint-config-recommended-vue": "^1.5.0",

+ 1 - 1
internal/lint-configs/stylelint-config/src/index.ts

@@ -11,7 +11,7 @@ export default {
   overrides: [
     {
       customSyntax: 'postcss-html',
-      files: ['**/*.(css|html|vue)'],
+      files: ['*.(html|vue)', '**/*.(html|vue)'],
       rules: {
         'selector-pseudo-class-no-unknown': [
           true,

+ 3 - 0
internal/tailwind-config/package.json

@@ -48,16 +48,19 @@
     "@iconify/json": "^2.2.214",
     "@iconify/tailwind": "^1.1.1",
     "@tailwindcss/forms": "^0.5.7",
+    "@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
     "@tailwindcss/typography": "^0.5.13",
     "autoprefixer": "^10.4.19",
     "cssnano": "^7.0.1",
     "postcss": "^8.4.38",
     "postcss-antd-fixes": "^0.2.0",
+    "postcss-import": "^16.1.0",
     "postcss-preset-env": "^9.5.14",
     "tailwindcss": "^3.4.3",
     "tailwindcss-animate": "^1.0.7"
   },
   "devDependencies": {
+    "@types/postcss-import": "^14.0.3",
     "@vben/node-utils": "workspace:*"
   }
 }

+ 1 - 8
internal/tailwind-config/src/index.ts

@@ -8,7 +8,6 @@ import typographyPlugin from '@tailwindcss/typography';
 import { fs, getPackagesSync } from '@vben/node-utils';
 import animate from 'tailwindcss-animate';
 
-import { plugins } from './plugins';
 // import defaultTheme from 'tailwindcss/defaultTheme';
 
 const { packages } = getPackagesSync();
@@ -30,13 +29,7 @@ export default {
     ),
   ],
   darkMode: 'class',
-  plugins: [
-    ...plugins,
-    animate,
-    formsPlugin,
-    typographyPlugin,
-    addDynamicIconSelectors(),
-  ],
+  plugins: [animate, formsPlugin, typographyPlugin, addDynamicIconSelectors()],
   prefix: '',
   safelist: ['dark'],
   theme: {

+ 3 - 0
internal/tailwind-config/src/module.d.ts

@@ -0,0 +1,3 @@
+declare module '@tailwindcss/nesting' {
+  export default any;
+}

+ 0 - 22
internal/tailwind-config/src/plugins.ts

@@ -1,22 +0,0 @@
-import type { Config } from 'tailwindcss';
-
-import plugin from 'tailwindcss/plugin';
-
-const flexCenterStyles = {
-  'align-items': 'center',
-  display: 'flex',
-  'justify-content': 'center',
-};
-
-const plugins = [
-  plugin(({ addUtilities }) => {
-    addUtilities({
-      '.flex-center': flexCenterStyles,
-      '.flex-col-center': {
-        ...flexCenterStyles,
-      },
-    });
-  }),
-] as unknown as Config['plugins'][];
-
-export { plugins };

+ 2 - 1
internal/tailwind-config/src/postcss.config.ts

@@ -7,8 +7,9 @@ export default {
     autoprefixer: {},
     // 修复 element-plus 和 ant-design-vue 的样式和tailwindcss冲突问题
     'postcss-antd-fixes': { prefixes: ['ant', 'el'] },
+    'postcss-import': {},
     'postcss-preset-env': {},
-    // here to share the same config across the entire monorepo
     tailwindcss: { config },
+    'tailwindcss/nesting': {},
   },
 };

+ 0 - 5
internal/vite-config/src/config/application.ts

@@ -55,11 +55,6 @@ function defineApplicationConfig(options: DefineAppcationOptions = {}) {
         legalComments: 'none',
       },
       plugins,
-      // css: {
-      //   preprocessorOptions: {
-      //     scss: {
-      //       additionalData: `@import "@vben-core/design/global";`,
-      //   },
       resolve: {
         alias: [
           {

+ 1 - 1
package.json

@@ -44,7 +44,7 @@
     "version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
   },
   "devDependencies": {
-    "@changesets/cli": "^2.27.3",
+    "@changesets/cli": "^2.27.5",
     "@ls-lint/ls-lint": "^2.2.3",
     "@types/jsdom": "^21.1.6",
     "@types/node": "^20.12.12",

+ 7 - 0
packages/@vben-core/shared/chche/build.config.ts

@@ -0,0 +1,7 @@
+import { defineBuildConfig } from 'unbuild';
+
+export default defineBuildConfig({
+  clean: true,
+  declaration: true,
+  entries: ['src/index'],
+});

+ 43 - 0
packages/@vben-core/shared/chche/package.json

@@ -0,0 +1,43 @@
+{
+  "name": "@vben-core/cache",
+  "version": "1.0.0",
+  "type": "module",
+  "license": "MIT",
+  "homepage": "https://github.com/vbenjs/vue-vben-admin",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
+    "directory": "packages/@vben-core/shared/toolkit"
+  },
+  "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
+  "scripts": {
+    "build": "pnpm unbuild",
+    "stub": "pnpm unbuild --stub"
+  },
+  "files": [
+    "dist"
+  ],
+  "sideEffects": false,
+  "main": "./dist/index.mjs",
+  "module": "./dist/index.mjs",
+  "imports": {
+    "#*": "./src/*"
+  },
+  "exports": {
+    ".": {
+      "types": "./src/index.ts",
+      "development": "./src/index.ts",
+      "default": "./dist/index.mjs"
+    }
+  },
+  "publishConfig": {
+    "exports": {
+      ".": {
+        "types": "./dist/index.d.ts",
+        "default": "./dist/index.mjs"
+      }
+    }
+  },
+  "dependencies": {},
+  "devDependencies": {}
+}

+ 1 - 0
packages/@vben-core/shared/chche/src/index.ts

@@ -0,0 +1 @@
+export * from './storage-cache';

+ 104 - 0
packages/@vben-core/shared/chche/src/storage-cache.test.ts

@@ -0,0 +1,104 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+
+import { StorageCache } from './storage-cache';
+
+describe('storageCache', () => {
+  let localStorageCache: StorageCache;
+  let sessionStorageCache: StorageCache;
+
+  beforeEach(() => {
+    localStorageCache = new StorageCache('prefix_', 'localStorage');
+    sessionStorageCache = new StorageCache('prefix_', 'sessionStorage');
+    localStorage.clear();
+    sessionStorage.clear();
+    vi.useFakeTimers();
+  });
+
+  afterEach(() => {
+    vi.useRealTimers();
+  });
+
+  it('should set and get an item with prefix in localStorage', () => {
+    localStorageCache.setItem('testKey', 'testValue');
+    const value = localStorageCache.getItem<string>('testKey');
+    expect(value).toBe('testValue');
+    expect(localStorage.getItem('prefix_testKey')).not.toBeNull();
+  });
+
+  it('should set and get an item with prefix in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey', 'testValue');
+    const value = sessionStorageCache.getItem<string>('testKey');
+    expect(value).toBe('testValue');
+    expect(sessionStorage.getItem('prefix_testKey')).not.toBeNull();
+  });
+
+  it('should return null for expired item in localStorage', () => {
+    localStorageCache.setItem('testKey', 'testValue', 1 / 60); // 1 second expiry
+    vi.advanceTimersByTime(2000); // Fast-forward 2 seconds
+    const value = localStorageCache.getItem<string>('testKey');
+    expect(value).toBeNull();
+  });
+
+  it('should return null for expired item in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey', 'testValue', 1 / 60); // 1 second expiry
+    vi.advanceTimersByTime(2000); // Fast-forward 2 seconds
+    const value = sessionStorageCache.getItem<string>('testKey');
+    expect(value).toBeNull();
+  });
+
+  it('should remove an item with prefix in localStorage', () => {
+    localStorageCache.setItem('testKey', 'testValue');
+    localStorageCache.removeItem('testKey');
+    const value = localStorageCache.getItem<string>('testKey');
+    expect(value).toBeNull();
+    expect(localStorage.getItem('prefix_testKey')).toBeNull();
+  });
+
+  it('should remove an item with prefix in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey', 'testValue');
+    sessionStorageCache.removeItem('testKey');
+    const value = sessionStorageCache.getItem<string>('testKey');
+    expect(value).toBeNull();
+    expect(sessionStorage.getItem('prefix_testKey')).toBeNull();
+  });
+
+  it('should clear all items in localStorage', () => {
+    localStorageCache.setItem('testKey1', 'testValue1');
+    localStorageCache.setItem('testKey2', 'testValue2');
+    localStorageCache.clear();
+    expect(localStorageCache.length()).toBe(0);
+  });
+
+  it('should clear all items in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey1', 'testValue1');
+    sessionStorageCache.setItem('testKey2', 'testValue2');
+    sessionStorageCache.clear();
+    expect(sessionStorageCache.length()).toBe(0);
+  });
+
+  it('should return correct length in localStorage', () => {
+    localStorageCache.setItem('testKey1', 'testValue1');
+    localStorageCache.setItem('testKey2', 'testValue2');
+    expect(localStorageCache.length()).toBe(2);
+  });
+
+  it('should return correct length in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey1', 'testValue1');
+    sessionStorageCache.setItem('testKey2', 'testValue2');
+    expect(sessionStorageCache.length()).toBe(2);
+  });
+
+  it('should return correct key by index in localStorage', () => {
+    localStorageCache.setItem('testKey1', 'testValue1');
+    localStorageCache.setItem('testKey2', 'testValue2');
+    expect(localStorageCache.key(0)).toBe('prefix_testKey1');
+    expect(localStorageCache.key(1)).toBe('prefix_testKey2');
+  });
+
+  it('should return correct key by index in sessionStorage', () => {
+    sessionStorageCache.setItem('testKey1', 'testValue1');
+    sessionStorageCache.setItem('testKey2', 'testValue2');
+    expect(sessionStorageCache.key(0)).toBe('prefix_testKey1');
+    expect(sessionStorageCache.key(1)).toBe('prefix_testKey2');
+  });
+});

+ 145 - 0
packages/@vben-core/shared/chche/src/storage-cache.ts

@@ -0,0 +1,145 @@
+import type { IStorageCache, StorageType, StorageValue } from './types';
+
+class StorageCache implements IStorageCache {
+  protected prefix: string;
+  protected storage: Storage;
+
+  constructor(prefix: string = '', storageType: StorageType = 'localStorage') {
+    this.prefix = prefix;
+    this.storage =
+      storageType === 'localStorage' ? localStorage : sessionStorage;
+  }
+
+  // 获取带前缀的键名
+  private getFullKey(key: string): string {
+    return this.prefix + key;
+  }
+
+  // 获取项之后的钩子方法
+  protected afterGetItem<T>(_key: string, _value: T | null): void {}
+
+  // 设置项之后的钩子方法
+  protected afterSetItem<T>(
+    _key: string,
+    _value: T,
+    _expiryInMinutes?: number,
+  ): void {}
+
+  // 获取项之前的钩子方法
+  protected beforeGetItem(_key: string): void {}
+
+  // 设置项之前的钩子方法
+  protected beforeSetItem<T>(
+    _key: string,
+    _value: T,
+    _expiryInMinutes?: number,
+  ): void {}
+
+  /**
+   * 清空存储
+   */
+  clear(): void {
+    try {
+      this.storage.clear();
+    } catch (error) {
+      console.error('Error clearing storage', error);
+    }
+  }
+
+  /**
+   * 获取存储项
+   * @param key 存储键
+   * @returns 存储值或 null
+   */
+  getItem<T>(key: string): T | null {
+    const fullKey = this.getFullKey(key);
+    this.beforeGetItem(fullKey);
+
+    let value: T | null = null;
+    try {
+      const item = this.storage.getItem(fullKey);
+      if (item) {
+        const storageValue: StorageValue<T> = JSON.parse(item);
+        if (storageValue.expiry && storageValue.expiry < Date.now()) {
+          this.storage.removeItem(fullKey);
+        } else {
+          value = storageValue.data;
+        }
+      }
+    } catch (error) {
+      console.error('Error getting item from storage', error);
+    }
+
+    this.afterGetItem(fullKey, value);
+    return value;
+  }
+
+  /**
+   * 获取存储中的键
+   * @param index 键的索引
+   * @returns 存储键或 null
+   */
+  key(index: number): null | string {
+    try {
+      return this.storage.key(index);
+    } catch (error) {
+      console.error('Error getting key from storage', error);
+      return null;
+    }
+  }
+
+  /**
+   * 获取存储项的数量
+   * @returns 存储项的数量
+   */
+  length(): number {
+    try {
+      return this.storage.length;
+    } catch (error) {
+      console.error('Error getting storage length', error);
+      return 0;
+    }
+  }
+
+  /**
+   * 删除存储项
+   * @param key 存储键
+   */
+  removeItem(key: string): void {
+    const fullKey = this.getFullKey(key);
+    try {
+      this.storage.removeItem(fullKey);
+    } catch (error) {
+      console.error('Error removing item from storage', error);
+    }
+  }
+
+  /**
+   * 设置存储项
+   * @param key 存储键
+   * @param value 存储值
+   * @param expiryInMinutes 过期时间(分钟)
+   */
+  setItem<T>(key: string, value: T, expiryInMinutes?: number): void {
+    const fullKey = this.getFullKey(key);
+    this.beforeSetItem(fullKey, value, expiryInMinutes);
+
+    const now = Date.now();
+    const expiry = expiryInMinutes ? now + expiryInMinutes * 60_000 : null;
+
+    const storageValue: StorageValue<T> = {
+      data: value,
+      expiry,
+    };
+
+    try {
+      this.storage.setItem(fullKey, JSON.stringify(storageValue));
+    } catch (error) {
+      console.error('Error setting item in storage', error);
+    }
+
+    this.afterSetItem(fullKey, value, expiryInMinutes);
+  }
+}
+
+export { StorageCache };

+ 17 - 0
packages/@vben-core/shared/chche/src/types.ts

@@ -0,0 +1,17 @@
+type StorageType = 'localStorage' | 'sessionStorage';
+
+interface StorageValue<T> {
+  data: T;
+  expiry: null | number;
+}
+
+interface IStorageCache {
+  clear(): void;
+  getItem<T>(key: string): T | null;
+  key(index: number): null | string;
+  length(): number;
+  removeItem(key: string): void;
+  setItem<T>(key: string, value: T, expiryInMinutes?: number): void;
+}
+
+export type { IStorageCache, StorageType, StorageValue };

+ 5 - 0
packages/@vben-core/shared/chche/tsconfig.json

@@ -0,0 +1,5 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "extends": "@vben/tsconfig/library.json",
+  "include": ["src"]
+}

+ 2 - 0
packages/@vben-core/shared/design-tokens/src/dark/index.scss

@@ -76,4 +76,6 @@
 
   /* 基本圆角大小 */
   --radius-base: 0.5rem;
+
+  color-scheme: dark;
 }

+ 3 - 0
packages/@vben-core/shared/design-tokens/src/default/index.scss

@@ -89,5 +89,8 @@
   // --color-menu-opened-dark: 225deg 12.12% 11%;
   --color-menu: 0deg 0% 100%;
   --color-menu-darken: 0deg 0% 95%;
+
+  accent-color: var(--color-primary);
+  color-scheme: light;
   // --color-menu-opened: 0deg 0% 100%;
 }

+ 1 - 1
packages/@vben-core/shared/design/build.config.ts

@@ -14,7 +14,7 @@ export default defineBuildConfig({
     {
       builder: 'mkdist',
       input: './src',
-      // loaders: ['postcss'],
+      loaders: ['postcss'],
       outDir: './dist',
       pattern: ['tailwind.css'],
     },

+ 1 - 1
packages/@vben-core/shared/design/src/scss/common/base.scss

@@ -34,7 +34,7 @@ html {
   font-synthesis-weight: none;
   scroll-behavior: smooth;
   text-rendering: optimizelegibility;
-  -webkit-tap-highlight-color: rgb(128 128 128 / 50%);
+  -webkit-tap-highlight-color: transparent;
 }
 
 a,

+ 15 - 4
packages/@vben-core/shared/design/src/tailwind.css

@@ -8,20 +8,31 @@
   }
 }
 
-@layer components {
+@layer utilities {
+  .flex-center {
+    @apply flex items-center justify-center;
+  }
+
+  .flex-col-center {
+    @apply flex flex-col items-center justify-center;
+  }
+
   .outline-box {
-    &:after {
+    @apply outline-border relative  cursor-pointer rounded-md p-1 outline outline-1;
+
+    &::after {
       @apply absolute left-1/2 top-1/2 z-20 h-0 w-[1px] rounded-sm opacity-0 outline outline-2 outline-transparent transition-all duration-300 content-[''];
     }
 
     &.outline-box-active {
       @apply outline-primary outline outline-2;
-      &:after {
+
+      &::after {
         display: none;
       }
     }
 
-    &:not(.outline-box-active):hover:after {
+    &:not(.outline-box-active):hover::after {
       @apply outline-primary left-0 top-0 h-full w-full p-1 opacity-100;
     }
   }

+ 1 - 1
packages/business/common-ui/src/authentication/qrcode-login.vue

@@ -37,7 +37,7 @@ function handleGo(path: string) {
       </template>
     </Title>
 
-    <div class="mt-6 flex flex-col items-center justify-center">
+    <div class="flex-col-center mt-6">
       <img :src="qrcode" alt="qrcode" class="w-1/2" />
       <p class="text-muted-foreground mt-4 text-sm">
         {{ $t('authentication.qrcode-prompt') }}

+ 1 - 1
packages/business/common-ui/src/fallback/fallback.vue

@@ -63,7 +63,7 @@ function back() {
   >
     <img v-if="image" :src="image" class="md:1/3 w-1/2 lg:w-1/4" />
     <FeedbackIcon v-else class="md:1/3 h-1/3 w-1/2 lg:w-1/4" />
-    <div class="flex flex-col items-center justify-center">
+    <div class="flex-col-center">
       <p class="text-foreground mt-12 text-3xl md:text-4xl lg:text-5xl">
         {{ titleText }}
       </p>

+ 1 - 1
packages/business/common-ui/src/preference/trigger.vue

@@ -12,7 +12,7 @@ defineOptions({
 
 <template>
   <VbenButton
-    class="bg-primary flex-center h-9 w-9 cursor-pointer flex-col rounded-l-md rounded-r-none border-none"
+    class="bg-primary flex-col-center h-9 w-9 cursor-pointer rounded-l-md rounded-r-none border-none"
     :title="$t('preference.preferences')"
   >
     <IconSetting class="text-lg" />

+ 1 - 3
packages/business/common-ui/src/spinner/spinner.vue

@@ -59,9 +59,7 @@ watch(
   </div>
 </template>
 
-<style lang="scss" scoped>
-@import '@vben-core/design/global';
-
+<style scoped>
 @keyframes jump-ani {
   15% {
     border-bottom-right-radius: 3px;

+ 1 - 1
packages/business/layouts/src/authentication/authentication.vue

@@ -47,7 +47,7 @@ const { authPanelCenter, authPanelLeft, authPanelRight } = usePreference();
       <div
         class="absolute inset-0 h-full w-full bg-[var(--color-authentication)]"
       >
-        <div class="flex-center mr-20 flex h-full flex-col">
+        <div class="flex-col-center mr-20 h-full">
           <SloganIcon
             :alt="preference.appName"
             class="animate-float h-64 w-2/5"

+ 1 - 3
packages/business/layouts/src/authentication/from-view.vue

@@ -8,9 +8,7 @@ defineOptions({
 });
 </script>
 <template>
-  <div
-    class="relative flex flex-col items-center justify-center px-6 py-10 lg:flex-initial lg:px-8"
-  >
+  <div class="flex-col-center relative px-6 py-10 lg:flex-initial lg:px-8">
     <slot name="toolbar">
       <Toolbar />
     </slot>

+ 0 - 2
packages/styles/src/tokens/dark.scss

@@ -1,6 +1,4 @@
 :root.dark {
   /* authentication */
   --color-authentication: hsl(240deg 11% 2%);
-
-  color-scheme: dark;
 }

File diff suppressed because it is too large
+ 158 - 262
pnpm-lock.yaml


+ 2 - 0
turbo.json

@@ -20,6 +20,8 @@
     },
     "stub": {},
     "dev": {
+      "dependsOn": ["^build"],
+      "outputs": [""],
       "cache": false,
       "persistent": true
     },

+ 4 - 0
vben-admin.code-workspace

@@ -40,6 +40,10 @@
       "name": "@vben/vite-config",
       "path": "internal/vite-config",
     },
+    {
+      "name": "@vben-core/cache",
+      "path": "packages/@vben-core/shared/chche",
+    },
     {
       "name": "@vben-core/design",
       "path": "packages/@vben-core/shared/design",

Some files were not shown because too many files changed in this diff