@smartos-lib/components 1.7.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.eslintrc +12 -0
  2. package/.eslintrc-auto-import.json +332 -0
  3. package/Components.code-workspace +143 -0
  4. package/LICENSE +21 -0
  5. package/dist/smart-docx-editor/index.d.ts +2 -0
  6. package/dist/smart-docx-editor/index.js +68 -0
  7. package/dist/smart-file-preview/index.d.ts +18 -0
  8. package/dist/smart-file-preview/index.js +37 -0
  9. package/dist/smart-upload/index.d.ts +2 -0
  10. package/dist/smart-upload/index.js +800 -0
  11. package/index.html +16 -0
  12. package/package.json +23 -0
  13. package/public/favicon.svg +6 -0
  14. package/scripts/components.vite.config.ts +96 -0
  15. package/scripts/shared.ts +9 -0
  16. package/src/App.vue +28 -0
  17. package/src/components/Logo/index.vue +15 -0
  18. package/src/components-private/.gitkeep +0 -0
  19. package/src/composables/useElementStyle.ts +23 -0
  20. package/src/composables/useNaiveStyle.ts +43 -0
  21. package/src/composables/useNaiveTheme.ts +71 -0
  22. package/src/composables/useSmart.ts +36 -0
  23. package/src/layouts/default.vue +3 -0
  24. package/src/main.ts +33 -0
  25. package/src/modules/pinia/index.ts +8 -0
  26. package/src/modules/progress/index.ts +12 -0
  27. package/src/modules/router/install.ts +9 -0
  28. package/src/modules/router/routes.ts +40 -0
  29. package/src/pages/[...all].vue +21 -0
  30. package/src/pages/frame/component/[name].vue +14 -0
  31. package/src/pages/frame/index.vue +81 -0
  32. package/src/pages/index/composables/useTabsManage.ts +46 -0
  33. package/src/pages/index/index.vue +111 -0
  34. package/src/pages/index/type.ts +13 -0
  35. package/src/pages/index/utils/index.ts +41 -0
  36. package/src/settings.ts +9 -0
  37. package/src/shared/components.ts +52 -0
  38. package/src/shared/env.ts +11 -0
  39. package/src/shared/unocss.theme.ts +1600 -0
  40. package/src/stores/theme.ts +29 -0
  41. package/src/styles/element.scss +3 -0
  42. package/src/styles/styles.scss +21 -0
  43. package/src/types.ts +20 -0
  44. package/src/utils/callCustomElementExposed.ts +6 -0
  45. package/src/utils/deepCloneESModule.ts +10 -0
  46. package/src/utils/defineCustomElements.ts +18 -0
  47. package/src/utils/formatComponentsGlob.ts +16 -0
  48. package/src/utils/getFileMD5.ts +31 -0
  49. package/src/utils/getFileNameAndExt.ts +11 -0
  50. package/src/utils/isFileEqual.ts +13 -0
  51. package/src/utils/jsonToFormData.ts +8 -0
  52. package/src/web-components/smart-docx-drive-page/App.vue +37 -0
  53. package/src/web-components/smart-docx-drive-page/apis/doc.ts +85 -0
  54. package/src/web-components/smart-docx-drive-page/apis/file.ts +278 -0
  55. package/src/web-components/smart-docx-drive-page/apis/folder.ts +72 -0
  56. package/src/web-components/smart-docx-drive-page/children/Home.vue +8 -0
  57. package/src/web-components/smart-docx-drive-page/children/Me.vue +47 -0
  58. package/src/web-components/smart-docx-drive-page/components/CustomImage.vue +26 -0
  59. package/src/web-components/smart-docx-drive-page/components/CustomPopover.vue +62 -0
  60. package/src/web-components/smart-docx-drive-page/components/DocxDir.vue +99 -0
  61. package/src/web-components/smart-docx-drive-page/components/DocxDoc.vue +132 -0
  62. package/src/web-components/smart-docx-drive-page/components/DocxDownloadPopoverItem.vue +41 -0
  63. package/src/web-components/smart-docx-drive-page/components/DocxFileList.vue +156 -0
  64. package/src/web-components/smart-docx-drive-page/components/DocxPreview.vue +33 -0
  65. package/src/web-components/smart-docx-drive-page/components/DocxUpload.vue +164 -0
  66. package/src/web-components/smart-docx-drive-page/components/FileIcon.vue +62 -0
  67. package/src/web-components/smart-docx-drive-page/components-private/Header.vue +65 -0
  68. package/src/web-components/smart-docx-drive-page/components-private/Logo.vue +15 -0
  69. package/src/web-components/smart-docx-drive-page/components-private/Menu.vue +34 -0
  70. package/src/web-components/smart-docx-drive-page/components-private/Navbar.vue +36 -0
  71. package/src/web-components/smart-docx-drive-page/composables/useFullscreenElDialog.ts +41 -0
  72. package/src/web-components/smart-docx-drive-page/composables/usePrompt.ts +73 -0
  73. package/src/web-components/smart-docx-drive-page/data.ts +10 -0
  74. package/src/web-components/smart-docx-drive-page/external-style/custom-popover.sass +8 -0
  75. package/src/web-components/smart-docx-drive-page/external-style/index.sass +1 -0
  76. package/src/web-components/smart-docx-drive-page/index.ts +20 -0
  77. package/src/web-components/smart-docx-drive-page/index.vue +39 -0
  78. package/src/web-components/smart-docx-drive-page/info.ts +2 -0
  79. package/src/web-components/smart-docx-drive-page/stores/menu.ts +60 -0
  80. package/src/web-components/smart-docx-drive-page/types.ts +51 -0
  81. package/src/web-components/smart-docx-drive-page/utils/file-actions.ts +63 -0
  82. package/src/web-components/smart-docx-drive-page/utils/file.ts +31 -0
  83. package/src/web-components/smart-docx-editor/App.vue +32 -0
  84. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components/Markdown.vue +202 -0
  85. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components/Menu.vue +100 -0
  86. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components/types.ts +6 -0
  87. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/Markdown.tsx +71 -0
  88. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/MarkdownElement.tsx +81 -0
  89. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/Blockquote/index.sass +6 -0
  90. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/Blockquote/index.tsx +12 -0
  91. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/Heading/index.sass +14 -0
  92. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/Heading/index.tsx +17 -0
  93. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/List/index.scss +16 -0
  94. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/elements/List/index.tsx +39 -0
  95. package/src/web-components/smart-docx-editor/MarkdownShortcuts/components-react/types/custom-types.d.ts +69 -0
  96. package/src/web-components/smart-docx-editor/MarkdownShortcuts/composables/useTextSelection.ts +50 -0
  97. package/src/web-components/smart-docx-editor/MarkdownShortcuts/index.sass +19 -0
  98. package/src/web-components/smart-docx-editor/MarkdownShortcuts/index.vue +21 -0
  99. package/src/web-components/smart-docx-editor/MarkdownShortcuts/shared/const.ts +23 -0
  100. package/src/web-components/smart-docx-editor/MarkdownShortcuts/utils/slateHelpers.ts +23 -0
  101. package/src/web-components/smart-docx-editor/data.ts +38 -0
  102. package/src/web-components/smart-docx-editor/demo.vue +11 -0
  103. package/src/web-components/smart-docx-editor/index.md +3 -0
  104. package/src/web-components/smart-docx-editor/index.ts +5 -0
  105. package/src/web-components/smart-docx-editor/index.vue +12 -0
  106. package/src/web-components/smart-docx-editor/info.ts +2 -0
  107. package/src/web-components/smart-file-preview/category/Code.vue +171 -0
  108. package/src/web-components/smart-file-preview/category/Image.vue +49 -0
  109. package/src/web-components/smart-file-preview/category/Pdf.vue +14 -0
  110. package/src/web-components/smart-file-preview/category/Video.vue +27 -0
  111. package/src/web-components/smart-file-preview/demo.vue +34 -0
  112. package/src/web-components/smart-file-preview/index.md +5 -0
  113. package/src/web-components/smart-file-preview/index.ts +29 -0
  114. package/src/web-components/smart-file-preview/index.vue +56 -0
  115. package/src/web-components/smart-file-preview/info.ts +2 -0
  116. package/src/web-components/smart-file-preview/shared/const.ts +4 -0
  117. package/src/web-components/smart-file-preview/types.ts +38 -0
  118. package/src/web-components/smart-upload/index.ts +5 -0
  119. package/src/web-components/smart-upload/index.vue +101 -0
  120. package/src/web-components/smart-upload/info.ts +2 -0
  121. package/src/web-components/smart-upload/types.ts +28 -0
  122. package/tsconfig.json +15 -0
  123. package/types/auto-imports.d.ts +975 -0
  124. package/types/components.d.ts +14 -0
  125. package/types/env.d.ts +8 -0
  126. package/types/shims.d.ts +6 -0
  127. package/unocss.config.ts +23 -0
  128. package/vite.config.ts +60 -0
package/index.html ADDED
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta http-equiv="Expires" content="0">
7
+ <meta http-equiv="Pragma" content="no-cache">
8
+ <meta http-equiv="Cache-control" content="no-cache">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
10
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml">
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ <script type="module" src="/src/main.ts"></script>
15
+ </body>
16
+ </html>
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@smartos-lib/components",
3
+ "type": "module",
4
+ "version": "1.7.0-beta.0",
5
+ "packageManager": "pnpm@8.14.3",
6
+ "author": "Wei Zhang <https://github.com/Zhang-Wei-666>",
7
+ "devDependencies": {
8
+ "@rollup/pluginutils": "^5.1.0",
9
+ "@types/prompts": "^2.4.9",
10
+ "pinia": "^2.1.7",
11
+ "prompts": "^2.4.2",
12
+ "vite-plugin-inspect": "^0.8.2",
13
+ "vite-plugin-pages": "^0.32.0",
14
+ "vite-plugin-vue-layouts": "^0.11.0",
15
+ "vue-router": "^4.2.5"
16
+ },
17
+ "scripts": {
18
+ "dev": "pnpm install && vite --host",
19
+ "build": "cd ../../ && pnpm build:components-prompts",
20
+ "build:editor": "pnpm install && vite build:components-prompts",
21
+ "preview": "pnpm install && vite build && vite preview --host"
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ <svg width="234" height="234" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M187.197 10h46.797L117.001 224.805.008 10h89.5L117 59.81 143.91 10h43.287Z" fill="#41B883"/>
3
+ <path d="M.008 10 117 224.805 233.994 10h-46.797l-70.196 128.883L46.221 10H.007Z" fill="#41B883"/>
4
+ <path d="M46.219 10 117 139.506 187.196 10h-43.288L117 59.81 89.506 10H46.22Z" fill="#35495E"/>
5
+ <path d="M210.562 138.833v14.557h-78.124v-14.557h78.124Zm0-7.278h-78.124c-2.073 0-4.06.767-5.525 2.131-1.465 1.365-2.288 3.217-2.288 5.147v14.557c0 1.93.823 3.781 2.288 5.146 1.465 1.365 3.452 2.132 5.525 2.132h78.124c2.073 0 4.06-.767 5.525-2.132 1.465-1.365 2.288-3.216 2.288-5.146v-14.557c0-1.93-.823-3.782-2.288-5.147-1.465-1.364-3.452-2.131-5.525-2.131Zm-62.5 43.67v36.391h-15.624v-36.391h15.624Zm0-7.279h-15.624c-2.073 0-4.06.767-5.525 2.132-1.465 1.365-2.288 3.216-2.288 5.147v36.391c0 1.93.823 3.782 2.288 5.147 1.465 1.365 3.452 2.131 5.525 2.131h15.624c2.073 0 4.06-.766 5.525-2.131 1.465-1.365 2.288-3.217 2.288-5.147v-36.391c0-1.931-.823-3.782-2.288-5.147-1.465-1.365-3.452-2.132-5.525-2.132Zm62.5 7.279v36.391H171.5v-36.391h39.062Zm0-7.279H171.5c-2.072 0-4.059.767-5.524 2.132-1.465 1.365-2.288 3.216-2.288 5.147v36.391c0 1.93.823 3.782 2.288 5.147 1.465 1.365 3.452 2.131 5.524 2.131h39.062c2.073 0 4.06-.766 5.525-2.131 1.465-1.365 2.288-3.217 2.288-5.147v-36.391c0-1.931-.823-3.782-2.288-5.147-1.465-1.365-3.452-2.132-5.525-2.132Z" fill="#000"/>
6
+ </svg>
@@ -0,0 +1,96 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import type { UserConfig } from 'vite';
4
+ import { defineConfig } from 'vite';
5
+ import Vue from '@vitejs/plugin-vue';
6
+ import VueJsx from '@vitejs/plugin-vue-jsx';
7
+ import React from '@vitejs/plugin-react';
8
+ import Unocss from 'unocss/vite';
9
+ import Components from 'unplugin-vue-components/vite';
10
+ import IconsResolver from 'unplugin-icons/resolver';
11
+ import { ElementPlusResolver, NaiveUiResolver } from 'unplugin-vue-components/resolvers';
12
+ import { viteVueCESubStyle } from '@unplugin-vue-ce/sub-style';
13
+ import ViteCommonPlugins from '../../.vitepress/vite.common.plugins';
14
+ import { isCustomElementRE, viteCssConfig } from './shared';
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+
18
+ export default (options: CreateViteBaseConfigOptions = {}) => {
19
+ const plugins = options.plugins || [];
20
+
21
+ return defineConfig({
22
+ plugins: [
23
+ ...plugins,
24
+
25
+ // Vue 3 支持
26
+ Vue({
27
+ customElement: [isCustomElementRE],
28
+ script: {
29
+ defineModel: true,
30
+ },
31
+ template: {
32
+ compilerOptions: {
33
+ isCustomElement: tag => tag.startsWith('smart-'),
34
+ },
35
+ },
36
+ }),
37
+ // Vue JSX 支持
38
+ {
39
+ ...VueJsx({
40
+ exclude: [/[/\\]components-react[\\/$]+/],
41
+ }),
42
+ enforce: 'pre',
43
+ },
44
+ {
45
+ config: () => ({
46
+ esbuild: {
47
+ include: /\.[jt]sx*$/,
48
+ },
49
+ }),
50
+ },
51
+ // React 支持
52
+ React(),
53
+ // 子组件样式支持
54
+ viteVueCESubStyle(),
55
+ // 原子化 CSS 引擎 ( 供 Web Components 使用 )
56
+ Unocss({
57
+ configFile: resolve(__dirname, '../unocss.config.ts'),
58
+ mode: 'vue-scoped',
59
+ content: {
60
+ pipeline: {
61
+ include: [isCustomElementRE],
62
+ },
63
+ },
64
+ }),
65
+ // 自动导入使用到的组件
66
+ Components({
67
+ dts: resolve(__dirname, '../types/components.d.ts'),
68
+ dirs: [
69
+ resolve(__dirname, '../src/components'),
70
+ resolve(__dirname, '../src/components-private'),
71
+ ],
72
+ resolvers: [
73
+ // 自动导入图标组件
74
+ IconsResolver({ prefix: 'i' }),
75
+ // 自动导入 Naive UI 组件
76
+ NaiveUiResolver(),
77
+ // 自动导入 Element Plus 组件
78
+ ElementPlusResolver({ importStyle: false }),
79
+ ],
80
+ }),
81
+
82
+ ...ViteCommonPlugins({
83
+ autoImportDirs: [
84
+ resolve(__dirname, '../src/composables'),
85
+ resolve(__dirname, '../src/stores'),
86
+ ],
87
+ }),
88
+ ],
89
+ css: viteCssConfig,
90
+ });
91
+ };
92
+
93
+ interface CreateViteBaseConfigOptions {
94
+ /** 需要额外插入的 vite 插件 */
95
+ plugins?: UserConfig['plugins']
96
+ }
@@ -0,0 +1,9 @@
1
+ export const isCustomElementRE = /\/web-components\/.*\/.*\.vue$/;
2
+
3
+ export const viteCssConfig = {
4
+ preprocessorOptions: {
5
+ scss: {
6
+ additionalData: '@use "~/styles/element.scss" as *;',
7
+ },
8
+ },
9
+ };
package/src/App.vue ADDED
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <!-- 全局化配置 ( 主题 ) -->
3
+ <NConfigProvider :theme="theme" :theme-overrides="themeOverrides" :locale="zhCN" :date-locale="dateZhCN" abstract>
4
+ <!-- 加载条 ( 页面加载进度 ) -->
5
+ <NLoadingBarProvider>
6
+ <router-view />
7
+ <GetAppEnv />
8
+ </NLoadingBarProvider>
9
+ <!-- 全局样式 ( 写入一些样式至 body 层 ) -->
10
+ <NGlobalStyle />
11
+ </NConfigProvider>
12
+ </template>
13
+
14
+ <script lang="ts" setup>
15
+ import { useLoadingBar } from 'naive-ui';
16
+ import { app } from '@/shared/env';
17
+ import { settings } from '@/settings';
18
+
19
+ /** 主题相关 */
20
+ const { theme, themeOverrides, zhCN, dateZhCN } = useNaiveTheme();
21
+
22
+ /** 获取当前应用的一些环境变量 */
23
+ function GetAppEnv() {
24
+ app.loadingBar = useLoadingBar();
25
+ }
26
+
27
+ useTitle(settings.name);
28
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="relative" :class="props.size">
3
+ <i-logos-vue class="size-full" />
4
+ <i-carbon-template class="size-1/2 absolute right-0 bottom-0" />
5
+ </div>
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ const props = defineProps({
10
+ size: {
11
+ type: String,
12
+ default: 'size-12',
13
+ },
14
+ });
15
+ </script>
File without changes
@@ -0,0 +1,23 @@
1
+ /* eslint-disable @typescript-eslint/indent */
2
+
3
+ import elementPlusStyle from 'element-plus/theme-chalk/src/index.scss?inline';
4
+
5
+ /**
6
+ * 挂载 Element Plus UI 的样式到 web components 组件中
7
+ */
8
+ export function useElementStyle() {
9
+ const el = useCurrentElement();
10
+
11
+ onMounted(() => {
12
+ const shadowRoot = el.value!.parentNode!;
13
+ const style = document.createElement('style');
14
+ style.setAttribute('namespace', 'smart');
15
+
16
+ // 添加 element-plus 的样式到组件中
17
+ shadowRoot.appendChild(style).textContent = elementPlusStyle;
18
+
19
+ // 添加 element-plus 的样式到 document.head 中
20
+ // 因为 MessageBox、Notification 等组件是挂载在 document.body 上的, 否则样式不生效
21
+ document.querySelector('style[namespace="smart"]') || (document.head.appendChild(style.cloneNode()).textContent = elementPlusStyle);
22
+ });
23
+ }
@@ -0,0 +1,43 @@
1
+ import { uniqueKeyCustomizer } from 'mixte';
2
+
3
+ /**
4
+ * 挂载 Naive UI 的样式到 web components 组件中
5
+ * @param classPrefix 自定义组件的类的前缀, 默认为随机字符串
6
+ * @example
7
+ *
8
+ * // js
9
+ * const classPrefix = useNaiveStyle();
10
+ *
11
+ * // template
12
+ * <n-config-provider :cls-prefix="classPrefix">
13
+ * <n-select />
14
+ * </n-config-provider>
15
+ */
16
+ export function useNaiveStyle(classPrefix = uniqueKeyCustomizer()) {
17
+ const el = useCurrentElement();
18
+ const selectors = `style[cssr-id^="${classPrefix}-"]`;
19
+
20
+ onMounted(() => {
21
+ // Naive UI 的样式是动态插入到 document.head 中的
22
+ // 所以监听 document.head 中样式的变化, 并将同样前缀的样式其插入到组件中
23
+ function insertStyle() {
24
+ const shadowRoot = el.value!.parentNode!;
25
+
26
+ shadowRoot.querySelectorAll(selectors).forEach((style) => {
27
+ shadowRoot.removeChild(style);
28
+ });
29
+
30
+ Array.from(document.querySelectorAll(selectors)).forEach((style) => {
31
+ shadowRoot.appendChild(style.cloneNode()).textContent = style.textContent;
32
+ });
33
+ }
34
+
35
+ useMutationObserver(document.head, insertStyle, {
36
+ childList: true,
37
+ });
38
+
39
+ insertStyle();
40
+ });
41
+
42
+ return classPrefix;
43
+ }
@@ -0,0 +1,71 @@
1
+ import type { GlobalThemeOverrides } from 'naive-ui';
2
+ import { darkTheme, dateZhCN, zhCN } from 'naive-ui';
3
+ import { deepMerge } from 'mixte';
4
+ import { colors, fontFamily } from '@/shared/unocss.theme';
5
+
6
+ /** 通用主题变量覆盖 */
7
+ export const commonOverrides: GlobalThemeOverrides = {
8
+ common: {
9
+ // 默认字体
10
+ fontFamily: fontFamily.sans,
11
+ // 等宽字体
12
+ fontFamilyMono: fontFamily.mono,
13
+
14
+ // Primary 颜色
15
+ primaryColor: colors.primary,
16
+ primaryColorHover: colors['primary-hover'],
17
+ primaryColorPressed: colors['primary-active'],
18
+ primaryColorSuppl: colors.primary,
19
+ // Info 颜色
20
+ infoColor: colors.info,
21
+ infoColorHover: colors['info-hover'],
22
+ infoColorPressed: colors['info-active'],
23
+ infoColorSuppl: colors.info,
24
+ // Success 颜色
25
+ successColor: colors.success,
26
+ successColorHover: colors['success-hover'],
27
+ successColorPressed: colors['success-active'],
28
+ successColorSuppl: colors.success,
29
+ // Warning 颜色
30
+ warningColor: colors.warning,
31
+ warningColorHover: colors['warning-hover'],
32
+ warningColorPressed: colors['warning-active'],
33
+ warningColorSuppl: colors.warning,
34
+ // Error 颜色
35
+ errorColor: colors.error,
36
+ errorColorHover: colors['error-hover'],
37
+ errorColorPressed: colors['error-active'],
38
+ errorColorSuppl: colors.error,
39
+ },
40
+ };
41
+
42
+ /** 亮色主题变量覆盖 */
43
+ export const lightThemeOverrides: GlobalThemeOverrides = deepMerge({}, commonOverrides, {
44
+
45
+ });
46
+ /** 深色主题变量覆盖 */
47
+ export const darkThemeOverrides: GlobalThemeOverrides = deepMerge({}, commonOverrides, {
48
+ Button: {
49
+ textColorPrimary: '#FFF',
50
+ textColorHoverPrimary: '#FFF',
51
+ textColorPressedPrimary: '#FFF',
52
+ textColorFocusPrimary: '#FFF',
53
+ textColorDisabledPrimary: '#FFF',
54
+ },
55
+ });
56
+
57
+ export const useNaiveTheme = createSharedComposable(() => {
58
+ const themeStore = useThemeStore();
59
+
60
+ /** 当前 Naive UI 主题 */
61
+ const theme = computed(() => themeStore.dark ? darkTheme : null);
62
+ /** 对当前 NaiveUI 主题的变量覆盖 */
63
+ const themeOverrides = computed(() => themeStore.dark ? darkThemeOverrides : lightThemeOverrides);
64
+
65
+ return {
66
+ theme,
67
+ themeOverrides,
68
+ zhCN,
69
+ dateZhCN,
70
+ };
71
+ });
@@ -0,0 +1,36 @@
1
+ /* eslint-disable @typescript-eslint/indent */
2
+
3
+ import { version } from '@@/package.json';
4
+
5
+ /**
6
+ * SmartOS 相关组件的公用处理逻辑
7
+ */
8
+ export function useSmart() {
9
+ const el = useCurrentElement();
10
+
11
+ onMounted(() => {
12
+ const shadowRoot = el.value!.parentNode!; // @ts-expect-error
13
+ const { tailwindResetStyle, elementPlusStyle } = globalThis.SmartCore?.[version] ?? {};
14
+
15
+ // 挂载 Tailwind Reset 的样式
16
+ if (tailwindResetStyle)
17
+ shadowRoot.appendChild(document.createElement('style')).textContent = tailwindResetStyle;
18
+
19
+ // 挂载 Element Plus UI 的样式
20
+ if (elementPlusStyle) {
21
+ const style = document.createElement('style');
22
+ style.setAttribute('namespace', 'smart');
23
+
24
+ // 添加 element-plus 的样式到组件中
25
+ shadowRoot.appendChild(style).textContent = elementPlusStyle;
26
+
27
+ // 添加 element-plus 的样式到 document.head 中
28
+ // 因为 MessageBox、Notification 等组件是挂载在 document.body 上的, 否则样式不生效
29
+ document.querySelector('style[namespace="smart"]') || (document.head.appendChild(style.cloneNode()).textContent = elementPlusStyle);
30
+ }
31
+ });
32
+
33
+ return {
34
+ classPrefix: useNaiveStyle(),
35
+ };
36
+ }
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <router-view />
3
+ </template>
package/src/main.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { isString } from 'mixte';
2
+ import App from './App.vue';
3
+ import type { UserModule } from './types';
4
+ import router from '@/modules/router/install';
5
+
6
+ import '@unocss/reset/tailwind.css';
7
+ import 'uno.css';
8
+ import '@/styles/styles.scss';
9
+
10
+ // 修复 Naive UI 和 Tailwind Reset 的样式冲突
11
+ document.head.insertAdjacentHTML('beforeend', '<meta name="naive-ui-style" />');
12
+
13
+ const app = createApp(App);
14
+
15
+ app.use(router);
16
+
17
+ Object.values(import.meta.glob<{ install: UserModule }>('./modules/**/index.ts', { eager: true })).forEach(m => m.install?.({ app, router }));
18
+
19
+ router.isReady().then(() => {
20
+ app.mount('#app');
21
+ });
22
+
23
+ const { warn, info } = console;
24
+
25
+ console.warn = (message?: any, ...optionalParams: any[]) => {
26
+ if (isString(message) && message.startsWith('[Vue warn]: Extraneous non-props attributes (data')) return;
27
+ warn.call(console, message, ...optionalParams);
28
+ };
29
+
30
+ console.info = (message?: any, ...optionalParams: any[]) => { // eslint-disable-line no-console
31
+ if (isString(message) && message.includes('Download the React DevTools')) return;
32
+ info.call(console, message, ...optionalParams);
33
+ };
@@ -0,0 +1,8 @@
1
+ import { createPinia } from 'pinia';
2
+ import type { UserModule } from '@/types';
3
+
4
+ export const install: UserModule = ({ app }) => {
5
+ const pinia = createPinia();
6
+
7
+ app.use(pinia);
8
+ };
@@ -0,0 +1,12 @@
1
+ import type { UserModule } from '@/types';
2
+ import { app } from '@/shared/env';
3
+
4
+ export const install: UserModule = ({ router }) => {
5
+ router.beforeEach(() => {
6
+ app.loadingBar?.start();
7
+ });
8
+
9
+ router.afterEach(() => {
10
+ app.loadingBar?.finish();
11
+ });
12
+ };
@@ -0,0 +1,9 @@
1
+ import { createRouter, createWebHistory } from 'vue-router';
2
+ import routes from './routes';
3
+
4
+ const router = createRouter({
5
+ history: createWebHistory(),
6
+ routes,
7
+ });
8
+
9
+ export default router;
@@ -0,0 +1,40 @@
1
+ import type { RouteComponent, RouteRecordRaw } from 'vue-router';
2
+ import { isESModule, isFunction, isPlainObject, leastRun } from 'mixte';
3
+ import { camelCase, upperFirst } from 'lodash-es';
4
+ import { setupLayouts } from 'virtual:generated-layouts';
5
+ import generatedRoutes from 'virtual:generated-pages';
6
+
7
+ /** 定义页面组件名称为路由名称 */
8
+ function defineComponentName(route: RouteRecordRaw, component: RouteComponent) {
9
+ if (component.name) return component;
10
+ return Object.assign({}, component, {
11
+ name: upperFirst(camelCase(route.name as string)),
12
+ });
13
+ }
14
+
15
+ /** 遍历路由 */
16
+ function eachRoutes(routes: RouteRecordRaw[]) {
17
+ routes.forEach((route) => {
18
+ const component = route.component;
19
+
20
+ // 对象形式的页面组件
21
+ if (isPlainObject(component)) {
22
+ route.component = defineComponentName(route, component);
23
+ }
24
+ // 页面组件是一个方法
25
+ else if (isFunction(component)) {
26
+ // @ts-expect-error
27
+ route.component = () => leastRun(0, component).then((m) => {
28
+ return defineComponentName(route, isESModule(m) ? m.default : m);
29
+ });
30
+ }
31
+
32
+ // 存在子路由
33
+ if (route.children)
34
+ eachRoutes(route.children);
35
+ });
36
+ }
37
+
38
+ eachRoutes(generatedRoutes);
39
+
40
+ export default setupLayouts(generatedRoutes);
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <div class="px-4 py-10 text-center">
3
+ <div class="text-5xl">
4
+ <i-bx-message-alt-x class="inline-block" />
5
+ </div>
6
+
7
+ <div class="mt-1">
8
+ 未找到页面
9
+ </div>
10
+
11
+ <div class="mt-6">
12
+ <NButton type="primary" @click="router.back()">
13
+ 返回
14
+ </NButton>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script lang="ts" setup>
20
+ const router = useRouter();
21
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <Index :component="name" />
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import Index from '../index.vue';
7
+
8
+ const route = useRoute();
9
+ const name = computed(() => route.params.name as string);
10
+ </script>
11
+
12
+ <route lang="yaml">
13
+ name: Frame/Component
14
+ </route>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <div class="min-h-screen flex">
3
+ <div class="w-full flex-grow">
4
+ <template v-if="tab && isReady">
5
+ <component :is="tab.component" v-bind="finalData" />
6
+ </template>
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <script lang="ts" setup>
12
+ import { isFunction } from 'mixte';
13
+ import { setConfigProvider } from '@smartos-lib/core';
14
+ import type { Tab } from '../index/type';
15
+ import { LOGIN_AJAX_CONFIG, createAxiosInstance } from '../../../../apis/test-utils/env';
16
+ import { components } from '@/shared/components';
17
+
18
+ interface Props {
19
+ /** 指定渲染的组件名称 */
20
+ component?: string
21
+ }
22
+
23
+ const props = defineProps<Props>();
24
+
25
+ /** 组件是否加载完成 */
26
+ const isReady = ref(false);
27
+
28
+ /** 所有的选项卡信息 */
29
+ const tabs = useLocalStorage<Tab[]>('st-tabs', []);
30
+ /** 当前选项卡信息 */
31
+ const tab = computed(() => props.component ? ({ component: props.component } as Tab) : tabs.value.find(tab => tab.id === window.name));
32
+ /** 当前选项卡测试数据 */
33
+ const data = computed(() => components[tab.value?.component as string]?.data?.[tab.value?.data as string] || {});
34
+ /** 最终使用的选项卡数据 - 支持使用函数返回测试数据 */
35
+ const finalData = computed(() => {
36
+ return isFunction(data.value) ? data.value({ reloadCount: tab.value?.dataReloadCount ?? 0 }) : data.value;
37
+ });
38
+
39
+ /** Token */
40
+ const token = ref('');
41
+ /** 创建一个新的 axios 实例 */
42
+ const request = createAxiosInstance('/', token);
43
+
44
+ /** 发起登录请求 */
45
+ const login = useRequest(() => {
46
+ return request(LOGIN_AJAX_CONFIG);
47
+ });
48
+
49
+ login.onSuccess(() => {
50
+ token.value = login.data.value?.access_token;
51
+ });
52
+
53
+ // 加载组件
54
+ watchEffect(async () => {
55
+ const name = tab.value?.component;
56
+ const component = components[name as string];
57
+
58
+ if (component) {
59
+ // SmartOS 组件库, 需要先加载 '@smartos-lib/core/componentsProvider' 依赖
60
+ if (name!.startsWith('smart-')) {
61
+ setConfigProvider({ request });
62
+ login.execute();
63
+ await import('@smartos-lib/core/componentsProvider');
64
+ }
65
+
66
+ component?.index().then(() => {
67
+ isReady.value = true;
68
+
69
+ // 云文档云服务页, 依赖这几个组件, 所以也需要加载过来
70
+ if (name === 'smart-docx-drive-page') {
71
+ components['smart-file-preview']?.index();
72
+ components['smart-docx-editor']?.index();
73
+ }
74
+ });
75
+ }
76
+ });
77
+ </script>
78
+
79
+ <route lang="yaml">
80
+ name: Frame
81
+ </route>
@@ -0,0 +1,46 @@
1
+ import { uniqueKey } from 'mixte';
2
+ import type { Tab } from '../type';
3
+ import { components } from '@/shared/components';
4
+
5
+ /** 选项卡管理 */
6
+ export function useTabsManage() {
7
+ /** 所有的选项卡信息 */
8
+ const tabs = useLocalStorage<Tab[]>('st-tabs', []);
9
+ /** 当前激活的选项卡 ID */
10
+ const activeTabId = useLocalStorage<string>('st-active-tab-id', '');
11
+ /** 当前激活的选项卡 */
12
+ const activeTab = computed(() => tabs.value.find(tab => tab.id === activeTabId.value));
13
+ /** 当前激活的选项卡的测试数据 */
14
+ const activeTabData = computed(() => components[activeTab.value?.component as string]?.data);
15
+
16
+ /** 创建一个新选项卡 */
17
+ function createTab(component: string) {
18
+ const id = uniqueKey(tabs.value);
19
+
20
+ tabs.value.push({
21
+ id,
22
+ component,
23
+ });
24
+
25
+ activeTabId.value = id;
26
+ }
27
+
28
+ /** 关闭一个选项卡 */
29
+ function closeTab(id: string) {
30
+ const index = tabs.value.findIndex(tab => tab.id === id);
31
+
32
+ if (index > -1) {
33
+ tabs.value.splice(index, 1);
34
+ activeTabId.value === id && (activeTabId.value = tabs.value[Math.min(index, tabs.value.length - 1)]?.id);
35
+ }
36
+ }
37
+
38
+ return {
39
+ activeTab,
40
+ activeTabId,
41
+ activeTabData,
42
+ tabs,
43
+ createTab,
44
+ closeTab,
45
+ };
46
+ }