From 74572ab2ee893d0fa24137e88230769ce3e0f5e9 Mon Sep 17 00:00:00 2001 From: "Apple\\Apple" Date: Tue, 6 May 2025 00:14:18 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20Support=20TailwindCSS=20V3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Apple\Apple --- web/package.json | 12 +- web/postcss.config.js | 6 + web/src/index.css | 323 +---------------------------------------- web/tailwind.config.js | 120 +++++++++++++++ web/vite.config.js | 20 +++ 5 files changed, 162 insertions(+), 319 deletions(-) create mode 100644 web/postcss.config.js create mode 100644 web/tailwind.config.js diff --git a/web/package.json b/web/package.json index e6ce588d..02118d34 100644 --- a/web/package.json +++ b/web/package.json @@ -12,21 +12,21 @@ "axios": "^0.27.2", "dayjs": "^1.11.11", "history": "^5.3.0", + "i18next": "^23.16.8", + "i18next-browser-languagedetector": "^7.2.0", "marked": "^4.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-fireworks": "^1.0.4", + "react-i18next": "^13.0.0", "react-router-dom": "^6.3.0", "react-telegram-login": "^1.1.2", "react-toastify": "^9.0.8", "react-turnstile": "^1.0.5", "semantic-ui-offline": "^2.5.0", "semantic-ui-react": "^2.1.3", - "sse": "https://github.com/mpetazzoni/sse.js", - "i18next": "^23.16.8", - "react-i18next": "^13.0.0", - "i18next-browser-languagedetector": "^7.2.0" + "sse": "https://github.com/mpetazzoni/sse.js" }, "scripts": { "dev": "vite", @@ -54,9 +54,13 @@ ] }, "devDependencies": { + "@douyinfe/semi-webpack-plugin": "^2.78.0", "@so1ve/prettier-config": "^3.1.0", "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.21", + "postcss": "^8.5.3", "prettier": "^3.0.0", + "tailwindcss": "^3.4.17", "typescript": "4.4.2", "vite": "^5.2.0" }, diff --git a/web/postcss.config.js b/web/postcss.config.js new file mode 100644 index 00000000..387612ed --- /dev/null +++ b/web/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/web/src/index.css b/web/src/index.css index c2e8ecd0..6530ae7c 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -1,320 +1,13 @@ -body { - margin: 0; - padding-top: 0; - font-family: - Lato, 'Helvetica Neue', Arial, Helvetica, 'Microsoft YaHei', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - scrollbar-width: none; - color: var(--semi-color-text-0) !important; - background-color: var(--semi-color-bg-0) !important; - height: 100vh; +@layer tailwind-base,semi,tailwind-components,tailwind-utils; + +@layer tailwind-base { + @tailwind base; } -#root { - height: 100%; - display: flex; - flex-direction: column; - overflow: hidden; +@layer tailwind-components { + @tailwind components; } -#root - > section - > header - > section - > div - > div - > div - > div.semi-navigation-header-list-outer - > div.semi-navigation-list-wrapper - > ul - > div - > a - > li - > span { - font-weight: 600 !important; +@layer tailwind-utils { + @tailwind utilities; } - -.semi-descriptions-double-small .semi-descriptions-item { - padding-right: 30px; -} - -@media only screen and (max-width: 767px) { - /*.semi-navigation-sub-wrap .semi-navigation-sub-title, .semi-navigation-item {*/ - /* padding: 0 0;*/ - /*}*/ - .topnav { - padding: 0 8px; - } - - .topnav .semi-navigation-item { - margin: 0 1px; - padding: 0 4px; - } - - .topnav .semi-navigation-list-wrapper { - max-width: calc(55vw - 20px); - overflow-x: auto; - scrollbar-width: none; - } - #root - > section - > header - > section - > div - > div - > div - > div.semi-navigation-footer - > div - > a - > li { - padding: 0 0; - } - #root - > section - > header - > section - > div - > div - > div - > div.semi-navigation-header-list-outer - > div.semi-navigation-list-wrapper - > ul - > div - > a - > li { - padding: 0 5px; - } - #root - > section - > header - > section - > div - > div - > div - > div.semi-navigation-footer - > div:nth-child(1) - > a - > li { - padding: 0 5px; - } - .semi-navigation-footer { - padding-left: 0; - padding-right: 0; - } - .semi-table-tbody, - .semi-table-row, - .semi-table-row-cell { - display: block !important; - width: auto !important; - padding: 2px !important; - } - .semi-table-row-cell { - border-bottom: 0 !important; - } - .semi-table-tbody > .semi-table-row { - border-bottom: 1px solid rgba(0, 0, 0, 0.1); - } - .semi-space { - /*display: block!important;*/ - display: flex; - flex-direction: row; - flex-wrap: wrap; - row-gap: 3px; - column-gap: 10px; - } - - .semi-navigation-horizontal .semi-navigation-header { - margin-right: 0; - } - - /* 确保移动端内容可滚动 */ - .semi-layout-content { - -webkit-overflow-scrolling: touch !important; - overscroll-behavior-y: auto !important; - } - - /* 修复移动端下拉刷新 */ - body { - overflow: visible !important; - overscroll-behavior-y: auto !important; - position: static !important; - height: 100% !important; - } - - /* 确保内容区域在移动端可以正常滚动 */ - #root { - overflow: visible !important; - height: 100% !important; - } - - /* 隐藏在移动设备上 */ - .hide-on-mobile { - display: none !important; - } -} - -.semi-table-tbody > .semi-table-row > .semi-table-row-cell { - padding: 16px 14px; -} - -.channel-table { - .semi-table-tbody > .semi-table-row > .semi-table-row-cell { - padding: 16px 8px; - } -} - -/*.semi-layout {*/ -/* height: 100%;*/ -/*}*/ - -.tableShow { - display: revert; -} - -.semi-chat { - padding-top: 0 !important; - padding-bottom: 0 !important; - height: 100%; -} - -.semi-chat-chatBox-content { - min-width: auto; - word-break: break-word; -} - -.tableHiddle { - display: none !important; -} - -body::-webkit-scrollbar { - display: none; -} - -code { - font-family: - source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; -} - -.semi-navigation-item { - margin-bottom: 0; -} - -/* 自定义侧边栏按钮悬停效果 */ -.semi-navigation-item:hover { - transform: translateX(2px); - box-shadow: 0 2px 8px rgba(var(--semi-color-primary-rgb), 0.2); -} - -/* 自定义侧边栏按钮选中效果 */ -.semi-navigation-item-selected { - position: relative; - overflow: hidden; -} - -.semi-navigation-item-selected::before { - content: ''; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 4px; - background-color: var(--semi-color-primary); - animation: slideIn 0.3s ease; -} - -@keyframes slideIn { - from { - transform: translateY(-100%); - } - to { - transform: translateY(0); - } -} - -/*.semi-navigation-vertical {*/ -/* !*flex: 0 0 auto;*!*/ -/* !*display: flex;*!*/ -/* !*flex-direction: column;*!*/ -/* !*width: 100%;*!*/ -/* height: 100%;*/ -/* overflow: hidden;*/ -/*}*/ - -.main-content { - padding: 4px; - height: 100%; -} - -.small-icon .icon { - font-size: 1em !important; -} - -.custom-footer { - font-size: 1.1em; -} - -/* 顶部栏样式 */ -.topnav { - padding: 0 16px; -} - -.topnav .semi-navigation-item { - border-radius: 4px; - margin: 0 2px; - transition: all 0.3s ease; -} - -.topnav .semi-navigation-item:hover { - background-color: var(--semi-color-primary-light-default); - transform: translateY(-2px); - box-shadow: 0 2px 8px rgba(var(--semi-color-primary-rgb), 0.2); -} - -.topnav .semi-navigation-item-selected { - background-color: var(--semi-color-primary-light-default); - color: var(--semi-color-primary); - font-weight: 600; -} - -/* 顶部栏文本样式 */ -.header-bar-text { - color: var(--semi-color-text-0); - font-weight: 500; - transition: all 0.3s ease; -} - -.header-bar-text:hover { - color: var(--semi-color-primary); -} - -/* 自定义滚动条样式 */ -.semi-layout-content::-webkit-scrollbar, -.semi-sider::-webkit-scrollbar { - width: 6px; - height: 6px; -} - -.semi-layout-content::-webkit-scrollbar-thumb, -.semi-sider::-webkit-scrollbar-thumb { - background: var(--semi-color-tertiary-light-default); - border-radius: 3px; -} - -.semi-layout-content::-webkit-scrollbar-thumb:hover, -.semi-sider::-webkit-scrollbar-thumb:hover { - background: var(--semi-color-tertiary); -} - -.semi-layout-content::-webkit-scrollbar-track, -.semi-sider::-webkit-scrollbar-track { - background: transparent; -} - -/* Custom sidebar shadow */ -/*.custom-sidebar-nav {*/ -/* box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08) !important;*/ -/* -webkit-box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08) !important;*/ -/* -moz-box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08) !important;*/ -/* min-height: 100%;*/ -/*}*/ diff --git a/web/tailwind.config.js b/web/tailwind.config.js new file mode 100644 index 00000000..66900002 --- /dev/null +++ b/web/tailwind.config.js @@ -0,0 +1,120 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + colors: { + "semi-color-white": "var(--semi-color-white)", + "semi-color-black": "var(--semi-color-black)", + "semi-color-primary": "var(--semi-color-primary)", + "semi-color-primary-hover": "var(--semi-color-primary-hover)", + "semi-color-primary-active": "var(--semi-color-primary-active)", + "semi-color-primary-disabled": "var(--semi-color-primary-disabled)", + "semi-color-primary-light-default": "var(--semi-color-primary-light-default)", + "semi-color-primary-light-hover": "var(--semi-color-primary-light-hover)", + "semi-color-primary-light-active": "var(--semi-color-primary-light-active)", + "semi-color-secondary": "var(--semi-color-secondary)", + "semi-color-secondary-hover": "var(--semi-color-secondary-hover)", + "semi-color-secondary-active": "var(--semi-color-secondary-active)", + "semi-color-secondary-disabled": "var(--semi-color-secondary-disabled)", + "semi-color-secondary-light-default": "var(--semi-color-secondary-light-default)", + "semi-color-secondary-light-hover": "var(--semi-color-secondary-light-hover)", + "semi-color-secondary-light-active": "var(--semi-color-secondary-light-active)", + "semi-color-tertiary": "var(--semi-color-tertiary)", + "semi-color-tertiary-hover": "var(--semi-color-tertiary-hover)", + "semi-color-tertiary-active": "var(--semi-color-tertiary-active)", + "semi-color-tertiary-light-default": "var(--semi-color-tertiary-light-default)", + "semi-color-tertiary-light-hover": "var(--semi-color-tertiary-light-hover)", + "semi-color-tertiary-light-active": "var(--semi-color-tertiary-light-active)", + "semi-color-default": "var(--semi-color-default)", + "semi-color-default-hover": "var(--semi-color-default-hover)", + "semi-color-default-active": "var(--semi-color-default-active)", + "semi-color-info": "var(--semi-color-info)", + "semi-color-info-hover": "var(--semi-color-info-hover)", + "semi-color-info-active": "var(--semi-color-info-active)", + "semi-color-info-disabled": "var(--semi-color-info-disabled)", + "semi-color-info-light-default": "var(--semi-color-info-light-default)", + "semi-color-info-light-hover": "var(--semi-color-info-light-hover)", + "semi-color-info-light-active": "var(--semi-color-info-light-active)", + "semi-color-success": "var(--semi-color-success)", + "semi-color-success-hover": "var(--semi-color-success-hover)", + "semi-color-success-active": "var(--semi-color-success-active)", + "semi-color-success-disabled": "var(--semi-color-success-disabled)", + "semi-color-success-light-default": "var(--semi-color-success-light-default)", + "semi-color-success-light-hover": "var(--semi-color-success-light-hover)", + "semi-color-success-light-active": "var(--semi-color-success-light-active)", + "semi-color-danger": "var(--semi-color-danger)", + "semi-color-danger-hover": "var(--semi-color-danger-hover)", + "semi-color-danger-active": "var(--semi-color-danger-active)", + "semi-color-danger-light-default": "var(--semi-color-danger-light-default)", + "semi-color-danger-light-hover": "var(--semi-color-danger-light-hover)", + "semi-color-danger-light-active": "var(--semi-color-danger-light-active)", + "semi-color-warning": "var(--semi-color-warning)", + "semi-color-warning-hover": "var(--semi-color-warning-hover)", + "semi-color-warning-active": "var(--semi-color-warning-active)", + "semi-color-warning-light-default": "var(--semi-color-warning-light-default)", + "semi-color-warning-light-hover": "var(--semi-color-warning-light-hover)", + "semi-color-warning-light-active": "var(--semi-color-warning-light-active)", + "semi-color-focus-border": "var(--semi-color-focus-border)", + "semi-color-disabled-text": "var(--semi-color-disabled-text)", + "semi-color-disabled-border": "var(--semi-color-disabled-border)", + "semi-color-disabled-bg": "var(--semi-color-disabled-bg)", + "semi-color-disabled-fill": "var(--semi-color-disabled-fill)", + "semi-color-shadow": "var(--semi-color-shadow)", + "semi-color-link": "var(--semi-color-link)", + "semi-color-link-hover": "var(--semi-color-link-hover)", + "semi-color-link-active": "var(--semi-color-link-active)", + "semi-color-link-visited": "var(--semi-color-link-visited)", + "semi-color-border": "var(--semi-color-border)", + "semi-color-nav-bg": "var(--semi-color-nav-bg)", + "semi-color-overlay-bg": "var(--semi-color-overlay-bg)", + "semi-color-fill-0": "var(--semi-color-fill-0)", + "semi-color-fill-1": "var(--semi-color-fill-1)", + "semi-color-fill-2": "var(--semi-color-fill-2)", + "semi-color-bg-0": "var(--semi-color-bg-0)", + "semi-color-bg-1": "var(--semi-color-bg-1)", + "semi-color-bg-2": "var(--semi-color-bg-2)", + "semi-color-bg-3": "var(--semi-color-bg-3)", + "semi-color-bg-4": "var(--semi-color-bg-4)", + "semi-color-text-0": "var(--semi-color-text-0)", + "semi-color-text-1": "var(--semi-color-text-1)", + "semi-color-text-2": "var(--semi-color-text-2)", + "semi-color-text-3": "var(--semi-color-text-3)", + "semi-color-highlight-bg": "var(--semi-color-highlight-bg)", + "semi-color-highlight": "var(--semi-color-highlight)", + "semi-color-data-0": "var(--semi-color-data-0)", + "semi-color-data-1": "var(--semi-color-data-1)", + "semi-color-data-2": "var(--semi-color-data-2)", + "semi-color-data-3": "var(--semi-color-data-3)", + "semi-color-data-4": "var(--semi-color-data-4)", + "semi-color-data-5": "var(--semi-color-data-5)", + "semi-color-data-6": "var(--semi-color-data-6)", + "semi-color-data-7": "var(--semi-color-data-7)", + "semi-color-data-8": "var(--semi-color-data-8)", + "semi-color-data-9": "var(--semi-color-data-9)", + "semi-color-data-10": "var(--semi-color-data-10)", + "semi-color-data-11": "var(--semi-color-data-11)", + "semi-color-data-12": "var(--semi-color-data-12)", + "semi-color-data-13": "var(--semi-color-data-13)", + "semi-color-data-14": "var(--semi-color-data-14)", + "semi-color-data-15": "var(--semi-color-data-15)", + "semi-color-data-16": "var(--semi-color-data-16)", + "semi-color-data-17": "var(--semi-color-data-17)", + "semi-color-data-18": "var(--semi-color-data-18)", + "semi-color-data-19": "var(--semi-color-data-19)" + }, + extend: { + borderRadius: { + "semi-border-radius-extra-small": "var(--semi-border-radius-extra-small)", + "semi-border-radius-small": "var(--semi-border-radius-small)", + "semi-border-radius-medium": "var(--semi-border-radius-medium)", + "semi-border-radius-large": "var(--semi-border-radius-large)", + "semi-border-radius-circle": "var(--semi-border-radius-circle)", + "semi-border-radius-full": "var(--semi-border-radius-full)", + } + } + }, + plugins: [], +} \ No newline at end of file diff --git a/web/vite.config.js b/web/vite.config.js index 450f3772..784b246a 100644 --- a/web/vite.config.js +++ b/web/vite.config.js @@ -20,6 +20,26 @@ export default defineConfig({ }, }, react(), + { + name: 'semi-css-layer', + transformIndexHtml(html) { + // Add layer to Semi CSS by prepending style tag + return html.replace( + /<\/head>/, + `` + ); + }, + transform(code, id) { + if (id.includes('@douyinfe/semi-ui') && id.endsWith('.css')) { + // Wrap Semi CSS in a layer + return { + code: `@layer semi { ${code} }`, + map: null + }; + } + return null; + } + } ], optimizeDeps: { force: true,