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"
}
},
"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": {
"dev": "webpack serve --mode development",
"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": {
"@ant-design/icons": "^5.3.0",
"antd": "^5.15.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
@ -22,11 +26,13 @@
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"html-webpack-plugin": "^5.6.0",
"style-loader": "^3.3.4",
"prettier": "^3.2.5",
"webpack": "^5.90.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"

Binary file not shown.

View File

@ -1,12 +1,30 @@
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 "../css/home.css";
const { Header, Content } = Layout;
const { Title, Paragraph, Text } = Typography;
const navItems = ["探索", "类目", "店铺", "达人", "商品", "视频与广告", "直播"];
const stats = [
{ value: "2亿+", label: "商品数据" },
{ value: "2.5亿+", label: "电商达人数据" },
{ value: "4亿+", label: "直播与短视频数据" },
{ value: "3亿+", label: "商品数据" },
{ value: "3.5亿+", label: "电商达人数据" },
{ value: "5亿+", label: "直播与短视频数据" },
{ value: "1000天", label: "历史数据" }
];
const logos = [
@ -21,139 +39,173 @@ const logos = [
"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() {
return (
<div className="home">
<header className="home-header">
<Layout className="home">
<Header className="home-header">
<div className="home-brand">
<span className="home-logo-wrap">
<img className="home-logo" src={logoWhite} alt="Kalodata" />
</span>
</div>
<nav className="home-nav">
{navItems.map((item) => (
<button key={item} className="home-nav-item" type="button">
{item}
</button>
))}
</nav>
<Menu
className="home-nav-menu"
mode="horizontal"
items={navItems.map((item) => ({
key: item,
label: item
}))}
selectable={false}
/>
<div className="home-actions">
<div className="home-lang">中文(简体)</div>
<div className="home-divider" />
<div className="home-user">Spark</div>
<Dropdown
menu={{ items: langItems }}
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>
</header>
</Header>
<main>
<section className="home-hero">
<Content>
<div className="home-hero">
<div className="home-hero-content">
<h1>
全球用户 <span>首选</span>
<Title level={1} className="home-hero-title">
深耕<span>TikTok</span>电商
<br />
TikTok电商
全球用户<span>优选</span>
<br />
数据洞察平台
</h1>
<p>
爆品挖掘达人建联视频创意直播设计广告优化竞对分析
<br />
我们助您抓住TikTok的每一次机会
</p>
</Title>
<div className="home-hero-stats">
{stats.map((stat) => (
<div key={stat.label} className="home-hero-stat">
<strong>{stat.value}</strong>
<span>{stat.label}</span>
<Statistic value={stat.value} title={stat.label} />
</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天免费试用
</button>
</Button>
</div>
<div className="home-hero-art">
<div className="home-hero-pattern" />
</div>
</section>
<section className="home-logos">
<Row gutter={[8, 8]}>
{logos.map((logo) => (
<div key={logo} className="home-logo-item">
{logo}
</div>
<Col key={logo} xs={8} md={4} lg>
<Text className="home-logo-item">{logo}</Text>
</Col>
))}
</Row>
</section>
<section className="home-section">
<div className="home-section-header">
<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">
<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" />
<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>
<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>
</main>
</div>
</Content>
</Layout>
);
}

View File

@ -3,6 +3,14 @@ body {
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 {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Helvetica Neue", Arial, sans-serif;
@ -12,9 +20,11 @@ body {
.home-header {
display: flex;
align-items: center;
justify-content: space-between;
justify-content: flex-start;
padding: 0px 24px;
height: 56px;
gap: 24px;
background: #f5f7fb;
}
.home-brand {
@ -31,24 +41,22 @@ body {
.home-logo {
height: auto;
width: 128px;
width: 108px;
display: block;
transform: scale(1.4);
transform-origin: center;
}
.home-nav {
display: flex;
gap: 20px;
font-size: 14px;
.home-nav-menu {
flex: 1;
background: transparent;
border-bottom: 0;
}
.home-nav-item {
background: transparent;
border: 0;
color: #1f2a37;
cursor: pointer;
padding: 6px 8px;
.home-nav-menu .ant-menu-item {
padding: 0 10px;
margin: 0;
font-size: 14px;
}
.home-actions {
@ -58,6 +66,12 @@ body {
font-size: 14px;
}
.home-lang-trigger {
font-size: 12px;
color: #1f2a37;
padding: 4px 6px;
}
.home-divider {
width: 1px;
height: 14px;
@ -65,20 +79,33 @@ body {
}
.home-hero {
background-color: rgb(243, 247, 252);
display: grid;
grid-template-columns: minmax(0, 1fr) 360px;
gap: 24px;
padding: 40px 48px 20px;
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;
font-size: 42px;
line-height: 1.2;
font-size: 72px;
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;
}
@ -91,21 +118,29 @@ body {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
margin-top: 74px;
margin-bottom: 24px;
}
.home-hero-stat {
display: grid;
gap: 4px;
.home-hero-stats .ant-statistic {
display: flex;
flex-direction: column-reverse;
align-items: center;
text-align: center;
}
.home-hero-stat strong {
font-size: 20px;
.home-hero-stats .ant-statistic-title {
writing-mode: horizontal-tb;
white-space: nowrap;
font-size: 24px;
font-family: "TencentW7", "PingFang SC", "Segoe UI", sans-serif;
}
.home-hero-stat span {
font-size: 12px;
color: #5f6b7c;
.home-hero-stats .ant-statistic-content {
writing-mode: horizontal-tb;
white-space: nowrap;
font-size: 36px;
font-family: "TencentW7", "PingFang SC", "Segoe UI", sans-serif;
}
.home-cta {
@ -186,11 +221,6 @@ body {
box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08);
}
.home-section-body {
display: grid;
gap: 20px;
}
.home-section-sidebar {
width: 200px;
border-right: 1px solid #eef2f7;
@ -208,38 +238,8 @@ body {
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 {
display: grid;
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;
width: 100%;
}
.home-section-product {
@ -268,21 +268,6 @@ body {
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) {
.home-hero {
@ -290,20 +275,13 @@ body {
}
.home-hero-stats {
margin-top: 74px;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.home-logos {
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) {
@ -313,10 +291,6 @@ body {
align-items: flex-start;
}
.home-nav {
flex-wrap: wrap;
}
.home-hero {
padding: 24px;
}

View File

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

View File

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