new project

main
yezhen 2026-02-01 00:16:13 +08:00
parent ff96be1a35
commit fa80ee7eae
10 changed files with 2037 additions and 195 deletions

View File

@ -17,5 +17,5 @@
"version": "detect" "version": "detect"
} }
}, },
"extends": ["ali", "ali/react"] "extends": ["ali", "ali/react", "plugin:prettier/recommended"]
} }

6
.prettierrc.json Normal file
View File

@ -0,0 +1,6 @@
{
"printWidth": 100,
"singleQuote": false,
"trailingComma": "none",
"semi": true
}

10
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
}

1789
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,9 +5,13 @@
"scripts": { "scripts": {
"dev": "webpack serve --mode development", "dev": "webpack serve --mode development",
"build": "webpack --mode production", "build": "webpack --mode production",
"lint": "eslint src --ext .js,.jsx" "lint": "eslint src --ext .js,.jsx",
"lint:fix": "eslint src --ext .js,.jsx --fix",
"format": "prettier . --write"
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.3.0",
"antd": "^5.15.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },
@ -22,11 +26,13 @@
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^6.1.1", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"html-webpack-plugin": "^5.6.0", "html-webpack-plugin": "^5.6.0",
"style-loader": "^3.3.4", "style-loader": "^3.3.4",
"prettier": "^3.2.5",
"webpack": "^5.90.0", "webpack": "^5.90.0",
"webpack-cli": "^5.1.4", "webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1" "webpack-dev-server": "^4.15.1"

Binary file not shown.

View File

@ -1,12 +1,30 @@
import React from "react"; import React from "react";
import {
Button,
Card,
Col,
Divider,
Dropdown,
Layout,
Menu,
Row,
Space,
Statistic,
Table,
Typography
} from "antd";
import { DownOutlined } from "@ant-design/icons";
import logoWhite from "../assets/images/logo-white2.png"; import logoWhite from "../assets/images/logo-white2.png";
import "../css/home.css"; import "../css/home.css";
const { Header, Content } = Layout;
const { Title, Paragraph, Text } = Typography;
const navItems = ["探索", "类目", "店铺", "达人", "商品", "视频与广告", "直播"]; const navItems = ["探索", "类目", "店铺", "达人", "商品", "视频与广告", "直播"];
const stats = [ const stats = [
{ value: "2亿+", label: "商品数据" }, { value: "3亿+", label: "商品数据" },
{ value: "2.5亿+", label: "电商达人数据" }, { value: "3.5亿+", label: "电商达人数据" },
{ value: "4亿+", label: "直播与短视频数据" }, { value: "5亿+", label: "直播与短视频数据" },
{ value: "1000天", label: "历史数据" } { value: "1000天", label: "历史数据" }
]; ];
const logos = [ const logos = [
@ -21,139 +39,173 @@ const logos = [
"MADAME GIE" "MADAME GIE"
]; ];
const langItems = [
{ key: "zh", label: "中文(简体)" },
{ key: "en", label: "English(US)" }
];
const tableColumns = [
{ title: "排名", dataIndex: "rank", key: "rank" },
{
title: "商品",
dataIndex: "product",
key: "product",
render: () => <span className="home-section-product" />
},
{ title: "价格", dataIndex: "price", key: "price" },
{ title: "销量", dataIndex: "sales", key: "sales" },
{
title: "趋势",
dataIndex: "trend",
key: "trend",
render: () => <span className="home-section-chart" />
}
];
const tableData = [1, 2, 3].map((item) => ({
key: item,
rank: `Top${item}`,
price: "¥99.20",
sales: "9276"
}));
export default function Home() { export default function Home() {
return ( return (
<div className="home"> <Layout className="home">
<header className="home-header"> <Header className="home-header">
<div className="home-brand"> <div className="home-brand">
<span className="home-logo-wrap"> <span className="home-logo-wrap">
<img className="home-logo" src={logoWhite} alt="Kalodata" /> <img className="home-logo" src={logoWhite} alt="Kalodata" />
</span> </span>
</div> </div>
<nav className="home-nav"> <Menu
{navItems.map((item) => ( className="home-nav-menu"
<button key={item} className="home-nav-item" type="button"> mode="horizontal"
{item} items={navItems.map((item) => ({
</button> key: item,
))} label: item
</nav> }))}
selectable={false}
/>
<div className="home-actions"> <div className="home-actions">
<div className="home-lang">中文(简体)</div> <Dropdown
<div className="home-divider" /> menu={{ items: langItems }}
<div className="home-user">Spark</div> trigger={["hover"]}
placement="bottomRight"
>
<Button className="home-lang-trigger" type="text">
<Space size={6}>
中文(简体)
<DownOutlined />
</Space>
</Button>
</Dropdown>
<Divider type="vertical" className="home-divider" />
<Text className="home-user">Spark</Text>
</div> </div>
</header> </Header>
<main> <Content>
<section className="home-hero"> <div className="home-hero">
<div className="home-hero-content"> <div className="home-hero-content">
<h1> <Title level={1} className="home-hero-title">
全球用户 <span>首选</span> 深耕<span>TikTok</span>电商
<br /> <br />
TikTok电商 全球用户<span>优选</span>
<br /> <br />
数据洞察平台 数据洞察平台
</h1> </Title>
<p>
爆品挖掘达人建联视频创意直播设计广告优化竞对分析
<br />
我们助您抓住TikTok的每一次机会
</p>
<div className="home-hero-stats"> <div className="home-hero-stats">
{stats.map((stat) => ( {stats.map((stat) => (
<div key={stat.label} className="home-hero-stat"> <div key={stat.label} className="home-hero-stat">
<strong>{stat.value}</strong> <Statistic value={stat.value} title={stat.label} />
<span>{stat.label}</span>
</div> </div>
))} ))}
</div> </div>
<button className="home-cta" type="button"> <Paragraph className="home-hero-desc">
爆品挖掘达人建联视频创意直播设计广告优化竞对分析
<br />
我们助您抓住TikTok的每一次机会
</Paragraph>
<Button className="home-cta" type="primary" size="large">
7天免费试用 7天免费试用
</button> </Button>
</div> </div>
<div className="home-hero-art"> </div>
<div className="home-hero-pattern" />
</div>
</section>
<section className="home-logos"> <section className="home-logos">
{logos.map((logo) => ( <Row gutter={[8, 8]}>
<div key={logo} className="home-logo-item"> {logos.map((logo) => (
{logo} <Col key={logo} xs={8} md={4} lg>
</div> <Text className="home-logo-item">{logo}</Text>
))} </Col>
))}
</Row>
</section> </section>
<section className="home-section"> <section className="home-section">
<div className="home-section-header"> <div className="home-section-header">
<span className="home-section-number">01</span> <span className="home-section-number">01</span>
<h2>爆品追踪</h2> <Title level={2}>爆品追踪</Title>
</div>
<div className="home-section-body">
<div className="home-section-card">
<div className="home-section-sidebar">
<div className="home-section-filter-title">筛选</div>
<div className="home-section-filter-item">日期</div>
<div className="home-section-filter-item">类目</div>
<div className="home-section-filter-item">价格</div>
</div>
<div className="home-section-content">
<div className="home-section-table">
<div className="home-section-row is-header">
<span>排名</span>
<span>商品</span>
<span>价格</span>
<span>销量</span>
<span>趋势</span>
</div>
{[1, 2, 3].map((item) => (
<div key={item} className="home-section-row">
<span>Top{item}</span>
<span className="home-section-product" />
<span>¥99.20</span>
<span>9276</span>
<span className="home-section-chart" />
</div>
))}
</div>
<div className="home-section-preview">
<div className="home-section-preview-card">
<div className="home-section-preview-image" />
<div className="home-section-preview-data">
<div>
<strong>¥920.18k</strong>
<span>成交金额</span>
</div>
<div>
<strong>9276</strong>
<span>销量</span>
</div>
<div>
<strong>¥99.20</strong>
<span>成交均价</span>
</div>
</div>
<div className="home-section-preview-metrics">
<div>
<strong>¥64.47k</strong>
<span>直播</span>
</div>
<div>
<strong>¥0.00</strong>
<span>短视频</span>
</div>
<div>
<strong>¥225.71k</strong>
<span>商城</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<Card className="home-section-card" bordered={false}>
<Row gutter={24}>
<Col xs={24} lg={6} className="home-section-sidebar">
<Text className="home-section-filter-title">筛选</Text>
<Space direction="vertical" size={8} className="home-filter-list">
<Text className="home-section-filter-item">日期</Text>
<Text className="home-section-filter-item">类目</Text>
<Text className="home-section-filter-item">价格</Text>
</Space>
</Col>
<Col xs={24} lg={18}>
<Row gutter={20}>
<Col xs={24} lg={14}>
<Table
className="home-section-table"
columns={tableColumns}
dataSource={tableData}
pagination={false}
size="small"
/>
</Col>
<Col xs={24} lg={10}>
<Card
className="home-section-preview-card"
bordered={false}
>
<div className="home-section-preview-image" />
<Row gutter={[12, 12]}>
<Col span={8}>
<Statistic value="¥920.18k" title="成交金额" />
</Col>
<Col span={8}>
<Statistic value="9276" title="销量" />
</Col>
<Col span={8}>
<Statistic value="¥99.20" title="成交均价" />
</Col>
</Row>
<Divider />
<Row gutter={[12, 12]}>
<Col span={8}>
<Statistic value="¥64.47k" title="直播" />
</Col>
<Col span={8}>
<Statistic value="¥0.00" title="短视频" />
</Col>
<Col span={8}>
<Statistic value="¥225.71k" title="商城" />
</Col>
</Row>
</Card>
</Col>
</Row>
</Col>
</Row>
</Card>
</section> </section>
</main> </Content>
</div> </Layout>
); );
} }

View File

@ -3,6 +3,14 @@ body {
color: #1f2a37; color: #1f2a37;
} }
@font-face {
font-family: "TencentW7";
src: url("../assets/fonts/tencent-W7.407ed34a.otf") format("opentype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
.home { .home {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Helvetica Neue", Arial, sans-serif; "Helvetica Neue", Arial, sans-serif;
@ -12,9 +20,11 @@ body {
.home-header { .home-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: flex-start;
padding: 0px 24px; padding: 0px 24px;
height: 56px; height: 56px;
gap: 24px;
background: #f5f7fb;
} }
.home-brand { .home-brand {
@ -31,24 +41,22 @@ body {
.home-logo { .home-logo {
height: auto; height: auto;
width: 128px; width: 108px;
display: block; display: block;
transform: scale(1.4); transform: scale(1.4);
transform-origin: center; transform-origin: center;
} }
.home-nav { .home-nav-menu {
display: flex; flex: 1;
gap: 20px; background: transparent;
font-size: 14px; border-bottom: 0;
} }
.home-nav-item { .home-nav-menu .ant-menu-item {
background: transparent; padding: 0 10px;
border: 0; margin: 0;
color: #1f2a37; font-size: 14px;
cursor: pointer;
padding: 6px 8px;
} }
.home-actions { .home-actions {
@ -58,6 +66,12 @@ body {
font-size: 14px; font-size: 14px;
} }
.home-lang-trigger {
font-size: 12px;
color: #1f2a37;
padding: 4px 6px;
}
.home-divider { .home-divider {
width: 1px; width: 1px;
height: 14px; height: 14px;
@ -65,20 +79,33 @@ body {
} }
.home-hero { .home-hero {
background-color: rgb(243, 247, 252);
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) 360px; grid-template-columns: minmax(0, 1fr) 360px;
gap: 24px; gap: 24px;
padding: 40px 48px 20px; padding: 40px 48px 20px;
align-items: center; align-items: center;
text-align: center;
width: 100%;
margin: 0 auto;
} }
.home-hero-content h1 { .home-hero-content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin: 0 auto;
}
.home-hero-title.ant-typography {
margin: 0 0 16px; margin: 0 0 16px;
font-size: 42px; font-size: 72px;
line-height: 1.2; line-height: 1.1;
font-family: "TencentW7", "PingFang SC", "Segoe UI", sans-serif;
} }
.home-hero-content h1 span { .home-hero-title.ant-typography span {
color: #1f6feb; color: #1f6feb;
} }
@ -91,21 +118,29 @@ body {
display: grid; display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px; gap: 16px;
margin-top: 74px;
margin-bottom: 24px; margin-bottom: 24px;
} }
.home-hero-stat { .home-hero-stats .ant-statistic {
display: grid; display: flex;
gap: 4px; flex-direction: column-reverse;
align-items: center;
text-align: center;
} }
.home-hero-stat strong { .home-hero-stats .ant-statistic-title {
font-size: 20px; writing-mode: horizontal-tb;
white-space: nowrap;
font-size: 24px;
font-family: "TencentW7", "PingFang SC", "Segoe UI", sans-serif;
} }
.home-hero-stat span { .home-hero-stats .ant-statistic-content {
font-size: 12px; writing-mode: horizontal-tb;
color: #5f6b7c; white-space: nowrap;
font-size: 36px;
font-family: "TencentW7", "PingFang SC", "Segoe UI", sans-serif;
} }
.home-cta { .home-cta {
@ -186,11 +221,6 @@ body {
box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08); box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08);
} }
.home-section-body {
display: grid;
gap: 20px;
}
.home-section-sidebar { .home-section-sidebar {
width: 200px; width: 200px;
border-right: 1px solid #eef2f7; border-right: 1px solid #eef2f7;
@ -208,38 +238,8 @@ body {
padding: 6px 0; padding: 6px 0;
} }
.home-section-content {
display: grid;
grid-template-columns: 1fr 280px;
gap: 20px;
}
.home-section-card {
display: grid;
grid-template-columns: 200px 1fr;
gap: 20px;
}
.home-section-table { .home-section-table {
display: grid; width: 100%;
gap: 8px;
}
.home-section-row {
display: grid;
grid-template-columns: 80px 1fr 80px 80px 100px;
gap: 12px;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #eef2f7;
font-size: 13px;
color: #5f6b7c;
}
.home-section-row.is-header {
font-weight: 600;
color: #1f2a37;
border-bottom: 1px solid #dde6f2;
} }
.home-section-product { .home-section-product {
@ -268,21 +268,6 @@ body {
background: linear-gradient(135deg, #f2f6ff, #dfe9ff); background: linear-gradient(135deg, #f2f6ff, #dfe9ff);
} }
.home-section-preview-data,
.home-section-preview-metrics {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
font-size: 12px;
color: #64748b;
}
.home-section-preview-data strong,
.home-section-preview-metrics strong {
display: block;
color: #1f2a37;
font-size: 14px;
}
@media (max-width: 1080px) { @media (max-width: 1080px) {
.home-hero { .home-hero {
@ -290,20 +275,13 @@ body {
} }
.home-hero-stats { .home-hero-stats {
margin-top: 74px;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
} }
.home-logos { .home-logos {
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
} }
.home-section-card {
grid-template-columns: 1fr;
}
.home-section-content {
grid-template-columns: 1fr;
}
} }
@media (max-width: 720px) { @media (max-width: 720px) {
@ -313,10 +291,6 @@ body {
align-items: flex-start; align-items: flex-start;
} }
.home-nav {
flex-wrap: wrap;
}
.home-hero { .home-hero {
padding: 24px; padding: 24px;
} }

View File

@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import App from "./App"; import App from "./App";
import "antd/dist/reset.css";
import "./index.css"; import "./index.css";
const root = createRoot(document.getElementById("root")); const root = createRoot(document.getElementById("root"));

View File

@ -29,6 +29,10 @@ module.exports = {
{ {
test: /\.(png|jpe?g|gif|svg)$/i, test: /\.(png|jpe?g|gif|svg)$/i,
type: "asset/resource" type: "asset/resource"
},
{
test: /\.(woff2?|eot|ttf|otf)$/i,
type: "asset/resource"
} }
] ]
}, },