From 89ea9547431951c87f8a23aa0612c87b9c15532b Mon Sep 17 00:00:00 2001 From: zhangyahui Date: Thu, 14 May 2026 15:10:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BD=AE=E6=92=AD=E5=9B=BE=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc.json | 10 + package.json | 4 +- pnpm-lock.yaml | 92 ++++--- src/pages/home/components/Carousel.vue | 181 +++++++++++++ src/pages/home/index.vue | 95 +++++++ src/routes.ts | 2 +- src/style.css | 356 +------------------------ src/types/kagol-vue-carousel.d.ts | 18 ++ vite.config.ts | 3 + 9 files changed, 361 insertions(+), 400 deletions(-) create mode 100644 .prettierrc.json create mode 100644 src/pages/home/components/Carousel.vue create mode 100644 src/pages/home/index.vue create mode 100644 src/types/kagol-vue-carousel.d.ts diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..fc1273c --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 4, + "singleQuote": true, + "printWidth": 100, + "useTabs": true, + "trailingComma": "none", + "vueIndentScriptAndStyle": true +} diff --git a/package.json b/package.json index 70819f4..c5f2e91 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "Codecreate", + "name": "code-create", "private": true, "version": "0.0.0", "type": "module", @@ -9,7 +9,9 @@ "preview": "vite preview" }, "dependencies": { + "@kagol/vue-carousel": "^0.1.2", "@unhead/vue": "^2.1.15", + "unhead": "2.1.15", "vite-ssg": "^28.3.0", "vue": "^3.5.34", "vue-router": "^4.6.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eaef8d5..6ddfdf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,18 @@ importers: .: dependencies: + '@kagol/vue-carousel': + specifier: ^0.1.2 + version: 0.1.2(typescript@6.0.3) '@unhead/vue': specifier: ^2.1.15 version: 2.1.15(vue@3.5.34(typescript@6.0.3)) + unhead: + specifier: 2.1.15 + version: 2.1.15 vite-ssg: specifier: ^28.3.0 - version: 28.3.0(unhead@3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1)))(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3)) + version: 28.3.0(unhead@2.1.15)(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3)) vue: specifier: ^3.5.34 version: 3.5.34(typescript@6.0.3) @@ -140,9 +146,6 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -156,6 +159,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@kagol/vue-carousel@0.1.2': + resolution: {integrity: sha512-znX+G+QxksjXve0XoTuPT4Sgbqa9XeMDTMlrlY312BDMdbbLWZOUifr0b16ExxHvBOzrBKVPo5e1Zs5JNRoqww==} + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: @@ -260,6 +266,16 @@ packages: '@rolldown/pluginutils@1.0.0-rc.13': resolution: {integrity: sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==} + '@rollup/rollup-darwin-x64@4.14.1': + resolution: {integrity: sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-x64-gnu@4.14.1': + resolution: {integrity: sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==} + cpu: [x64] + os: [linux] + '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -673,18 +689,6 @@ packages: unhead@2.1.15: resolution: {integrity: sha512-MCt5T90mCWyr3Z6pUCdM9lVRXoMoVBlL7z7U4CYVIiaDiuzad/UCfLuMqz5MeNmpZUgoBCQnrucJimU7EZR+XA==} - unhead@3.1.0: - resolution: {integrity: sha512-SH1PAjAMspLIoBjAjE/R8hty2NYo7YcIrdu5I+PVfiW4QmmwEG4pgoiKG0MCs6WRSwiatzeha+4lqSqvHW9PEg==} - peerDependencies: - vite: '>=6.4.2' - peerDependenciesMeta: - vite: - optional: true - - unplugin@3.0.0: - resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} - engines: {node: ^20.19.0 || >=22.12.0} - vite-ssg-sitemap@0.10.0: resolution: {integrity: sha512-OIja4fqUMcvWl5+bxQARe3LgzWTd8U/dWHWgrqiC7vv3AmTn0YnhMNUAimQ0M/0Aa9myEIAGLV0yKlYbKP8BJQ==} @@ -771,6 +775,9 @@ packages: typescript: optional: true + vueuse-components@0.0.1: + resolution: {integrity: sha512-VaodJj28CTwBEuUdAYkx2qmgUI18AnVrzu7gjwCfVSfnuUoQZDF33px9WNdbmEKpoUGXbhVDM1j/kv3xVcAlKQ==} + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -779,9 +786,6 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} - webpack-virtual-modules@0.6.2: - resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - whatwg-mimetype@5.0.0: resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} engines: {node: '>=20'} @@ -885,11 +889,6 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/source-map@0.3.11': @@ -904,6 +903,16 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@kagol/vue-carousel@0.1.2(typescript@6.0.3)': + dependencies: + vue: 3.5.34(typescript@6.0.3) + vueuse-components: 0.0.1(typescript@6.0.3) + optionalDependencies: + '@rollup/rollup-darwin-x64': 4.14.1 + '@rollup/rollup-linux-x64-gnu': 4.14.1 + transitivePeerDependencies: + - typescript + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 @@ -966,6 +975,12 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.13': {} + '@rollup/rollup-darwin-x64@4.14.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.14.1': + optional: true + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -975,9 +990,9 @@ snapshots: dependencies: undici-types: 7.16.0 - '@unhead/dom@2.1.15(unhead@3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1)))': + '@unhead/dom@2.1.15(unhead@2.1.15)': dependencies: - unhead: 3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1)) + unhead: 2.1.15 '@unhead/vue@2.1.15(vue@3.5.34(typescript@6.0.3))': dependencies: @@ -1395,24 +1410,11 @@ snapshots: dependencies: hookable: 6.1.1 - unhead@3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1)): - dependencies: - hookable: 6.1.1 - unplugin: 3.0.0 - optionalDependencies: - vite: 8.0.12(@types/node@24.12.4)(terser@5.47.1) - - unplugin@3.0.0: - dependencies: - '@jridgewell/remapping': 2.3.5 - picomatch: 4.0.4 - webpack-virtual-modules: 0.6.2 - vite-ssg-sitemap@0.10.0: {} - vite-ssg@28.3.0(unhead@3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1)))(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3)): + vite-ssg@28.3.0(unhead@2.1.15)(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3)): dependencies: - '@unhead/dom': 2.1.15(unhead@3.1.0(vite@8.0.12(@types/node@24.12.4)(terser@5.47.1))) + '@unhead/dom': 2.1.15(unhead@2.1.15) '@unhead/vue': 2.1.15(vue@3.5.34(typescript@6.0.3)) ansis: 4.3.0 cac: 6.7.14 @@ -1464,14 +1466,18 @@ snapshots: optionalDependencies: typescript: 6.0.3 + vueuse-components@0.0.1(typescript@6.0.3): + dependencies: + vue: 3.5.34(typescript@6.0.3) + transitivePeerDependencies: + - typescript + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 webidl-conversions@8.0.1: {} - webpack-virtual-modules@0.6.2: {} - whatwg-mimetype@5.0.0: {} whatwg-url@16.0.1: diff --git a/src/pages/home/components/Carousel.vue b/src/pages/home/components/Carousel.vue new file mode 100644 index 0000000..e98a274 --- /dev/null +++ b/src/pages/home/components/Carousel.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/src/pages/home/index.vue b/src/pages/home/index.vue new file mode 100644 index 0000000..509ed66 --- /dev/null +++ b/src/pages/home/index.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/routes.ts b/src/routes.ts index b2192ee..1d52d4d 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -1,7 +1,7 @@ import type { RouteRecordRaw } from 'vue-router' import AboutView from './pages/AboutView.vue' import ContactView from './pages/ContactView.vue' -import HomeView from './pages/HomeView.vue' +import HomeView from './pages/home/index.vue' import ProductsView from './pages/ProductsView.vue' export const routes: RouteRecordRaw[] = [ diff --git a/src/style.css b/src/style.css index d025515..75a203c 100644 --- a/src/style.css +++ b/src/style.css @@ -1,365 +1,11 @@ -:root { - --text: #6b6375; - --text-h: #08060d; - --bg: #fff; - --border: #e5e4e7; - --code-bg: #f4f3ec; - --accent: #aa3bff; - --accent-bg: rgba(170, 59, 255, 0.1); - --accent-border: rgba(170, 59, 255, 0.5); - --social-bg: rgba(244, 243, 236, 0.5); - --shadow: - rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px; - - --sans: system-ui, 'Segoe UI', Roboto, sans-serif; - --heading: system-ui, 'Segoe UI', Roboto, sans-serif; - --mono: ui-monospace, Consolas, monospace; - - font: 18px/145% var(--sans); - letter-spacing: 0.18px; - color-scheme: light dark; - color: var(--text); - background: var(--bg); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - @media (max-width: 1024px) { - font-size: 16px; - } -} - -@media (prefers-color-scheme: dark) { - :root { - --text: #9ca3af; - --text-h: #f3f4f6; - --bg: #16171d; - --border: #2e303a; - --code-bg: #1f2028; - --accent: #c084fc; - --accent-bg: rgba(192, 132, 252, 0.15); - --accent-border: rgba(192, 132, 252, 0.5); - --social-bg: rgba(47, 48, 58, 0.5); - --shadow: - rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px; - } - - #social .button-icon { - filter: invert(1) brightness(2); - } -} - -body { +html,body{ margin: 0; -} - -h1, -h2 { - font-family: var(--heading); - font-weight: 500; - color: var(--text-h); -} - -h1 { - font-size: 56px; - letter-spacing: -1.68px; - margin: 32px 0; - @media (max-width: 1024px) { - font-size: 36px; - margin: 20px 0; - } -} -h2 { - font-size: 24px; - line-height: 118%; - letter-spacing: -0.24px; - margin: 0 0 8px; - @media (max-width: 1024px) { - font-size: 20px; - } -} -p { - margin: 0; -} - -code, -.counter { - font-family: var(--mono); - display: inline-flex; - border-radius: 4px; - color: var(--text-h); -} - -code { - font-size: 15px; - line-height: 135%; - padding: 4px 8px; - background: var(--code-bg); -} - -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; - - &:hover { - border-color: var(--accent-border); - } - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.site-pages { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 10px; -} - -.site-page-link { - min-width: 92px; - padding: 8px 14px; - border: 1px solid var(--border); - border-radius: 6px; - color: var(--text-h); - background: var(--social-bg); - font-size: 15px; - line-height: 1.2; - text-decoration: none; - box-sizing: border-box; - transition: - border-color 0.2s, - color 0.2s, - box-shadow 0.2s; - - &:hover, - &:focus-visible, - &.router-link-active { - border-color: var(--accent-border); - color: var(--accent); - } - - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } - - @media (max-width: 480px) { - flex: 1 1 calc(50% - 10px); - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) - scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) - scale(0.8); - } -} - -#app { - width: 1126px; - max-width: 100%; - margin: 0 auto; - text-align: center; - border-inline: 1px solid var(--border); - min-height: 100svh; - display: flex; - flex-direction: column; - box-sizing: border-box; -} - -#center { - display: flex; - flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; - - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; - } -} - -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; - - & > div { - flex: 1 1 0; - padding: 32px; - @media (max-width: 1024px) { - padding: 24px 20px; - } - } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } -} - -#docs { - border-right: 1px solid var(--border); - - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; padding: 0; - display: flex; - gap: 8px; - margin: 32px 0 0; - - .logo { - height: 18px; - } - - a { - color: var(--text-h); - font-size: 16px; - border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; - - &:hover { - box-shadow: var(--shadow); - } - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; - } - } } -#spacer { - height: 88px; - border-top: 1px solid var(--border); - @media (max-width: 1024px) { - height: 48px; - } -} -.ticks { - position: relative; - width: 100%; - &::before, - &::after { - content: ''; - position: absolute; - top: -4.5px; - border: 5px solid transparent; - } - &::before { - left: 0; - border-left-color: var(--border); - } - &::after { - right: 0; - border-right-color: var(--border); - } -} -.placeholder-page { - min-height: 100svh; - padding: 96px 24px; - box-sizing: border-box; - display: flex; - flex-direction: column; - place-content: center; - place-items: center; - gap: 16px; -} -.placeholder-page p { - max-width: 560px; -} -.placeholder-page a { - color: var(--accent); - text-decoration-thickness: 2px; - text-underline-offset: 4px; -} - -.placeholder-kicker { - color: var(--accent); - font-family: var(--mono); - font-size: 14px; - letter-spacing: 0; - text-transform: uppercase; -} diff --git a/src/types/kagol-vue-carousel.d.ts b/src/types/kagol-vue-carousel.d.ts new file mode 100644 index 0000000..749393b --- /dev/null +++ b/src/types/kagol-vue-carousel.d.ts @@ -0,0 +1,18 @@ +declare module '@kagol/vue-carousel' { + import type { Component, Plugin } from 'vue' + + export const Carousel: Component + export const CarouselIndicator: Component + export const CarouselPrev: Component + export const CarouselNext: Component + export const usePage: (initialPage?: number) => { + pageIndex: { value: number } + setPageIndex: (pageIndex: number) => void + jumpPage: (step: number) => void + prevPage: () => void + nextPage: () => void + } + + const plugin: Plugin + export default plugin +} diff --git a/vite.config.ts b/vite.config.ts index 0b2b8fe..3387961 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,6 +8,9 @@ import generateSitemap from 'vite-ssg-sitemap' const config = { base: '/', plugins: [vue()], + ssr: { + noExternal: ['@kagol/vue-carousel'] + }, ssgOptions: { dirStyle: 'nested', script: 'defer',