Browse Source

feat: add license plugin

vben 10 months ago
parent
commit
16ed5a05ba

+ 13 - 0
.github/semantic.yml

@@ -0,0 +1,13 @@
+titleAndCommits: true
+types:
+  - feat
+  - fix
+  - docs
+  - chore
+  - style
+  - refactor
+  - perf
+  - test
+  - build
+  - ci
+  - revert

+ 1 - 0
internal/node-utils/package.json

@@ -31,6 +31,7 @@
     "@changesets/git": "^3.0.0",
     "@manypkg/get-packages": "^2.2.1",
     "consola": "^3.2.3",
+    "dayjs": "^1.11.11",
     "find-up": "^7.0.0",
     "nanoid": "^5.0.7",
     "pkg-types": "^1.1.1",

+ 10 - 0
internal/node-utils/src/date.ts

@@ -0,0 +1,10 @@
+import dayjs from 'dayjs';
+import timezone from 'dayjs/plugin/timezone';
+import utc from 'dayjs/plugin/utc';
+
+dayjs.extend(utc);
+dayjs.extend(timezone);
+
+const dateUtil = dayjs().tz('Asia/Shanghai');
+
+export { dateUtil };

+ 3 - 7
internal/node-utils/src/index.ts

@@ -1,13 +1,9 @@
-export { UNICODE } from './constants';
+export * from './constants';
+export * from './date';
 export * from './git';
 export { add as gitAdd, getStagedFiles } from './git';
 export { generatorContentHash } from './hash';
-export {
-  findMonorepoRoot,
-  getPackage,
-  getPackages,
-  getPackagesSync,
-} from './monorepo';
+export * from './monorepo';
 export { toPosixPath } from './path';
 export { prettierFormat } from './prettier';
 export type { Package } from '@manypkg/get-packages';

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

@@ -25,6 +25,7 @@ function defineApplicationConfig(options: DefineApplicationOptions = {}) {
       i18n: true,
       injectAppLoading: true,
       isBuild,
+      license: true,
       mock: true,
       mode,
       pwa: true,

+ 2 - 2
internal/vite-config/src/plugins/extra-app-config.ts

@@ -1,11 +1,11 @@
+import type { PluginOption } from 'vite';
+
 import {
   colors,
   generatorContentHash,
   readPackageJSON,
 } from '@vben/node-utils';
 
-import { type PluginOption } from 'vite';
-
 import { getEnvConfig } from '../utils/env';
 
 interface PluginOptions {

+ 6 - 1
internal/vite-config/src/plugins/index.ts

@@ -27,6 +27,7 @@ import viteVueDevTools from 'vite-plugin-vue-devtools';
 import { viteExtraAppConfigPlugin } from './extra-app-config';
 import { viteImportMapPlugin } from './importmap';
 import { viteInjectAppLoadingPlugin } from './inject-app-loading';
+import { viteLicensePlugin } from './license';
 
 /**
  * 获取条件成立的 vite 插件
@@ -94,12 +95,12 @@ async function getApplicationConditionPlugins(
     compress,
     compressTypes,
     extraAppConfig,
-
     html,
     i18n,
     importmap,
     importmapOptions,
     injectAppLoading,
+    license,
     mock,
     pwa,
     pwaOptions,
@@ -130,6 +131,10 @@ async function getApplicationConditionPlugins(
       condition: injectAppLoading,
       plugins: async () => [await viteInjectAppLoadingPlugin(!!isBuild, env)],
     },
+    {
+      condition: license,
+      plugins: async () => [await viteLicensePlugin()],
+    },
     {
       condition: pwa,
       plugins: () =>

+ 76 - 0
internal/vite-config/src/plugins/license.ts

@@ -0,0 +1,76 @@
+import type {
+  NormalizedOutputOptions,
+  OutputAsset,
+  OutputBundle,
+  OutputChunk,
+} from 'rollup';
+import type { PluginOption } from 'vite';
+
+import { EOL } from 'node:os';
+
+import { dateUtil, readPackageJSON } from '@vben/node-utils';
+
+/**
+ * 用于将配置文件抽离出来并注入到项目中
+ * @returns
+ */
+
+async function viteLicensePlugin(
+  root = process.cwd(),
+): Promise<PluginOption | undefined> {
+  const {
+    description = '',
+    homepage = '',
+    version = '',
+  } = await readPackageJSON(root);
+
+  return {
+    apply: 'build',
+    enforce: 'post',
+    generateBundle: {
+      handler: (_options: NormalizedOutputOptions, bundle: OutputBundle) => {
+        const date = dateUtil.format('YYYY-MM-DD ');
+
+        const copyrightText = `/*!
+  * Vben Admin Pro
+  * Version: ${version}
+  * Author: vben
+  * Copyright (C) 2024 Vben
+  * License: MIT License
+  * Description: ${description}
+  * Date Created: ${date}
+  * Homepage: ${homepage}
+  * Contact: ann.vben@gmail.com
+*/
+              `.trim();
+
+        for (const [, fileContent] of Object.entries(bundle)) {
+          if (
+            fileContent.type === 'asset' ||
+            (fileContent.type === 'chunk' && fileContent.isEntry)
+          ) {
+            const chunkContent = fileContent as OutputChunk;
+            const assetContent = fileContent as OutputAsset;
+            // 插入版权信息
+            const content =
+              typeof assetContent.source === 'string'
+                ? assetContent.source
+                : chunkContent.code;
+            const updatedContent = `${copyrightText}${EOL}${content}`;
+
+            // 更新bundle
+            if (assetContent.source === undefined) {
+              (fileContent as OutputChunk).code = updatedContent;
+            } else {
+              (fileContent as OutputAsset).source = updatedContent;
+            }
+          }
+        }
+      },
+      order: 'post',
+    },
+    name: 'vite:license',
+  };
+}
+
+export { viteLicensePlugin };

+ 2 - 0
internal/vite-config/src/typing.ts

@@ -67,6 +67,8 @@ interface ApplicationPluginOptions extends CommonPluginOptions {
   importmapOptions?: ImportmapPluginOptions;
   /** 是否注入app loading */
   injectAppLoading?: boolean;
+  /** 是否注入版权信息 */
+  license?: boolean;
   /** mock 插件配置 */
   mock?: boolean;
   /** 是否开启pwa */

+ 3 - 2
package.json

@@ -83,8 +83,9 @@
   "packageManager": "pnpm@9.4.0",
   "pnpm": {
     "overrides": {
-      "@ctrl/tinycolor": "4.1.0",
-      "clsx": "2.1.1",
+      "@ant-design/colors": "^7.0.2",
+      "@ctrl/tinycolor": "^4.1.0",
+      "clsx": "^2.1.1",
       "vue": "^3.4.30"
     },
     "neverBuiltDependencies": [

+ 1 - 2
packages/@core/uikit/menu-ui/src/components/normal-menu/normal-menu.vue

@@ -43,6 +43,7 @@ function handleMouseenter(menu: MenuRecordRaw) {
       is(theme, true),
       is('rounded', rounded),
     ]"
+    class="relative"
   >
     <template v-for="menu in menus" :key="menu.path">
       <li
@@ -66,9 +67,7 @@ function handleMouseenter(menu: MenuRecordRaw) {
   --menu-item-padding-x: 0px;
   --menu-item-radius: 0px;
   --menu-dark-background: 0deg 0% 100% / 10%;
-  // --menu-light-background: 240deg 5% 96%;
 
-  position: relative;
   height: calc(100% - 4px);
 
   @include is('rounded') {

+ 0 - 39
packages/@core/uikit/tabs-ui/src/components/chrome-tabs/chrome-tabs.scss

@@ -8,27 +8,11 @@
   --tabs-active-background: hsl(var(--primary) / 100%);
   --tabs-active: hsl(var(--primary-foreground));
 
-  position: relative;
-  width: 100%;
-  height: 100%;
-  padding-top: 4px;
   background-color: var(--tabs-background);
-
-  @include e('content') {
-    position: relative;
-    height: 32px;
-    overflow: hidden;
-  }
 }
 
 @include b('chrome-tab') {
-  position: absolute;
-  display: flex;
-  align-items: center;
-  height: 100%;
   color: hsl(var(--muted-foreground));
-  cursor: pointer;
-  user-select: none;
 
   @include is('active') {
     z-index: 2;
@@ -57,7 +41,6 @@
     position: absolute;
     right: 0;
     left: 0;
-    // z-index: 1;
     display: flex;
     align-items: center;
     height: 100%;
@@ -174,59 +157,37 @@
 }
 
 @include b('chrome-tab-background') {
-  position: absolute;
-  width: 100%;
-  height: 100%;
   padding: 0 calc(var(--tabs-gap) + 0px);
 
   @include e('divider') {
-    position: absolute;
-    left: 0;
     width: calc(100% - 14px);
-    height: 100%;
     margin: 0 7px;
 
     &::before {
-      position: absolute;
-      top: 20%;
-      right: 100%;
-      width: 1px;
-      height: 60%;
-      content: '';
       background-color: var(--tabs-divider);
     }
 
     &::after {
-      position: absolute;
-      top: 20%;
       left: calc(100% - 1px);
-      width: 1px;
-      height: 60%;
-      content: '';
       background-color: var(--tabs-divider);
     }
   }
 
   @include e('content') {
-    height: 100%;
     border-top-left-radius: 5px;
     border-top-right-radius: 5px;
     transition: background 0.15s ease;
   }
 
   @include e('before') {
-    position: absolute;
     bottom: -1px;
     left: -3px;
-    fill: transparent;
     transition: 0.15s;
   }
 
   @include e('after') {
-    position: absolute;
     right: -3px;
     bottom: -1px;
-    fill: transparent;
     transition: 0.15s;
   }
 }

+ 18 - 5
packages/@core/uikit/tabs-ui/src/components/chrome-tabs/tab-background.vue

@@ -9,13 +9,26 @@ const { b, e } = useNamespace('chrome-tab-background');
 </script>
 
 <template>
-  <div :class="b()">
-    <div :class="e('divider')"></div>
-    <div :class="e('content')"></div>
-    <svg :class="e('before')" height="10" width="10">
+  <div :class="b()" class="absolute size-full">
+    <div
+      :class="e('divider')"
+      class="absolute left-0 h-full before:absolute before:right-[100%] before:top-[15%] before:h-[60%] before:w-[1px] before:content-[''] after:absolute after:top-[15%] after:h-[60%] after:w-[1px] after:content-['']"
+    ></div>
+    <div :class="e('content')" class="h-full"></div>
+    <svg
+      :class="e('before')"
+      class="absolute fill-transparent"
+      height="10"
+      width="10"
+    >
       <path d="M 0 10 A 10 10 0 0 0 10 0 L 10 10 Z" />
     </svg>
-    <svg :class="e('after')" height="10" width="10">
+    <svg
+      :class="e('after')"
+      class="absolute fill-transparent"
+      height="10"
+      width="10"
+    >
       <path d="M 0 0 A 10 10 0 0 0 10 10 L 0 10 Z" />
     </svg>
   </div>

+ 4 - 1
packages/@core/uikit/tabs-ui/src/components/chrome-tabs/tab.vue

@@ -38,7 +38,10 @@ function handleUnPushPin() {
 </script>
 
 <template>
-  <div :class="[b()]">
+  <div
+    :class="[b()]"
+    class="absolute flex h-full cursor-pointer select-none items-center"
+  >
     <VbenContextMenu :handler-data="tab" :menus="menus" item-class="pr-4">
       <div class="h-full">
         <TabBackground />

+ 6 - 2
packages/@core/uikit/tabs-ui/src/components/chrome-tabs/tabs.vue

@@ -83,8 +83,12 @@ function handleUnPushPin(tab: TabItem) {
 </script>
 
 <template>
-  <div :class="b()">
-    <div ref="contentRef" :class="e('content')">
+  <div :class="b()" class="relative size-full pt-1">
+    <div
+      ref="contentRef"
+      :class="e('content')"
+      class="relative h-8 overflow-hidden"
+    >
       <TransitionGroup name="slide-down">
         <Tab
           v-for="(tab, i) in tabsView"

+ 10 - 13
pnpm-lock.yaml

@@ -5,8 +5,9 @@ settings:
   excludeLinksFromLockfile: false
 
 overrides:
-  '@ctrl/tinycolor': 4.1.0
-  clsx: 2.1.1
+  '@ant-design/colors': ^7.0.2
+  '@ctrl/tinycolor': ^4.1.0
+  clsx: ^2.1.1
   vue: ^3.4.30
 
 importers:
@@ -328,6 +329,9 @@ importers:
       consola:
         specifier: ^3.2.3
         version: 3.2.3
+      dayjs:
+        specifier: ^1.11.11
+        version: 1.11.11
       find-up:
         specifier: ^7.0.0
         version: 7.0.0
@@ -556,7 +560,7 @@ importers:
         specifier: ^7.0.2
         version: 7.0.2
       '@ctrl/tinycolor':
-        specifier: 4.1.0
+        specifier: ^4.1.0
         version: 4.1.0
 
   packages/@core/shared/design:
@@ -582,7 +586,7 @@ importers:
         specifier: ^3.4.30
         version: 3.4.30
       clsx:
-        specifier: 2.1.1
+        specifier: ^2.1.1
         version: 2.1.1
       dayjs:
         specifier: ^1.11.11
@@ -978,9 +982,6 @@ packages:
     resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
     engines: {node: '>=6.0.0'}
 
-  '@ant-design/colors@6.0.0':
-    resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
-
   '@ant-design/colors@7.0.2':
     resolution: {integrity: sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==}
 
@@ -8928,10 +8929,6 @@ snapshots:
       '@jridgewell/gen-mapping': 0.3.5
       '@jridgewell/trace-mapping': 0.3.25
 
-  '@ant-design/colors@6.0.0':
-    dependencies:
-      '@ctrl/tinycolor': 4.1.0
-
   '@ant-design/colors@7.0.2':
     dependencies:
       '@ctrl/tinycolor': 4.1.0
@@ -8940,7 +8937,7 @@ snapshots:
 
   '@ant-design/icons-vue@7.0.1(vue@3.4.30(typescript@5.5.2))':
     dependencies:
-      '@ant-design/colors': 6.0.0
+      '@ant-design/colors': 7.0.2
       '@ant-design/icons-svg': 4.4.2
       vue: 3.4.30(typescript@5.5.2)
 
@@ -12141,7 +12138,7 @@ snapshots:
 
   ant-design-vue@4.2.3(vue@3.4.30(typescript@5.5.2)):
     dependencies:
-      '@ant-design/colors': 6.0.0
+      '@ant-design/colors': 7.0.2
       '@ant-design/icons-vue': 7.0.1(vue@3.4.30(typescript@5.5.2))
       '@babel/runtime': 7.24.7
       '@ctrl/tinycolor': 4.1.0