添加前端项目和更新.gitignore配置
- 添加基于 Vite + React + TypeScript 的前端项目 - 配置 .gitignore 排除 node_modules 和构建产物 - 添加 web/.gitignore 用于前端项目的忽略规则 - 包含完整的源代码、配置文件和依赖锁定文件 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
805c4597af
commit
6120d051aa
7
.gitignore
vendored
7
.gitignore
vendored
@ -35,3 +35,10 @@ logs/
|
|||||||
# 临时文件
|
# 临时文件
|
||||||
tmp/
|
tmp/
|
||||||
temp/
|
temp/
|
||||||
|
|
||||||
|
# 前端构建产物和依赖
|
||||||
|
web/node_modules/
|
||||||
|
web/dist/
|
||||||
|
web/build/
|
||||||
|
web/.vite/
|
||||||
|
web/.cache/
|
||||||
|
|||||||
20
web/.eslintrc.cjs
Normal file
20
web/.eslintrc.cjs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: { browser: true, es2020: true },
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
],
|
||||||
|
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'warn',
|
||||||
|
},
|
||||||
|
}
|
||||||
30
web/.gitignore
vendored
Normal file
30
web/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# 依赖
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# 构建产物
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.vite/
|
||||||
|
|
||||||
|
# 缓存
|
||||||
|
.cache/
|
||||||
|
.parcel-cache/
|
||||||
|
|
||||||
|
# 环境变量
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# 编辑器
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# 测试覆盖率
|
||||||
|
coverage/
|
||||||
14
web/index.html
Normal file
14
web/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<meta name="description" content="AnKao 移动端应用" />
|
||||||
|
<title>AnKao</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
33
web/package.json
Normal file
33
web/package.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "ankao-web",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.21.3",
|
||||||
|
"antd-mobile": "^5.37.1",
|
||||||
|
"antd-mobile-icons": "^0.3.0",
|
||||||
|
"axios": "^1.6.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.48",
|
||||||
|
"@types/react-dom": "^18.2.18",
|
||||||
|
"@types/node": "^20.11.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||||
|
"@typescript-eslint/parser": "^6.19.0",
|
||||||
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
|
"eslint": "^8.56.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.5",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.0.11"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
web/src/App.tsx
Normal file
17
web/src/App.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
|
||||||
|
import Home from './pages/Home'
|
||||||
|
import About from './pages/About'
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Router>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Home />} />
|
||||||
|
<Route path="/about" element={<About />} />
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
3
web/src/components/DemoButton.module.css
Normal file
3
web/src/components/DemoButton.module.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
34
web/src/components/DemoButton.tsx
Normal file
34
web/src/components/DemoButton.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Button, Space } from 'antd-mobile'
|
||||||
|
import styles from './DemoButton.module.css'
|
||||||
|
|
||||||
|
interface DemoButtonProps {
|
||||||
|
text?: string
|
||||||
|
onClick?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const DemoButton: React.FC<DemoButtonProps> = ({
|
||||||
|
text = '示例按钮',
|
||||||
|
onClick
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Space direction="vertical" block>
|
||||||
|
<Button color="primary" block onClick={onClick}>
|
||||||
|
{text} - Primary
|
||||||
|
</Button>
|
||||||
|
<Button color="success" block onClick={onClick}>
|
||||||
|
{text} - Success
|
||||||
|
</Button>
|
||||||
|
<Button color="warning" block onClick={onClick}>
|
||||||
|
{text} - Warning
|
||||||
|
</Button>
|
||||||
|
<Button color="danger" block onClick={onClick}>
|
||||||
|
{text} - Danger
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DemoButton
|
||||||
18
web/src/index.css
Normal file
18
web/src/index.css
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
10
web/src/main.tsx
Normal file
10
web/src/main.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom/client'
|
||||||
|
import App from './App'
|
||||||
|
import './index.css'
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
)
|
||||||
12
web/src/pages/About.module.css
Normal file
12
web/src/pages/About.module.css
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
48
web/src/pages/About.tsx
Normal file
48
web/src/pages/About.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { NavBar, Card, List, Space, Button } from 'antd-mobile'
|
||||||
|
import styles from './About.module.css'
|
||||||
|
|
||||||
|
const About: React.FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<NavBar onBack={() => navigate(-1)}>关于</NavBar>
|
||||||
|
|
||||||
|
<div className={styles.content}>
|
||||||
|
<Card title="项目信息">
|
||||||
|
<Space direction="vertical" block>
|
||||||
|
<List>
|
||||||
|
<List.Item extra="1.0.0">版本</List.Item>
|
||||||
|
<List.Item extra="AnKao Team">开发者</List.Item>
|
||||||
|
<List.Item extra="MIT">许可证</List.Item>
|
||||||
|
</List>
|
||||||
|
|
||||||
|
<Card title="功能特性">
|
||||||
|
<List>
|
||||||
|
<List.Item>✅ 响应式移动端设计</List.Item>
|
||||||
|
<List.Item>✅ TypeScript 类型安全</List.Item>
|
||||||
|
<List.Item>✅ Vite 快速构建</List.Item>
|
||||||
|
<List.Item>✅ antd-mobile 组件库</List.Item>
|
||||||
|
<List.Item>✅ React Router 路由</List.Item>
|
||||||
|
<List.Item>✅ API 代理配置</List.Item>
|
||||||
|
</List>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
block
|
||||||
|
onClick={() => navigate('/')}
|
||||||
|
>
|
||||||
|
返回首页
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default About
|
||||||
13
web/src/pages/Home.module.css
Normal file
13
web/src/pages/Home.module.css
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
}
|
||||||
95
web/src/pages/Home.tsx
Normal file
95
web/src/pages/Home.tsx
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
NavBar,
|
||||||
|
TabBar,
|
||||||
|
List,
|
||||||
|
Card,
|
||||||
|
Space,
|
||||||
|
Toast
|
||||||
|
} from 'antd-mobile'
|
||||||
|
import {
|
||||||
|
AppOutline,
|
||||||
|
UnorderedListOutline,
|
||||||
|
UserOutline
|
||||||
|
} from 'antd-mobile-icons'
|
||||||
|
import styles from './Home.module.css'
|
||||||
|
|
||||||
|
const Home: React.FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const [activeKey, setActiveKey] = React.useState('home')
|
||||||
|
|
||||||
|
const handleButtonClick = () => {
|
||||||
|
Toast.show({
|
||||||
|
content: '欢迎使用 AnKao!',
|
||||||
|
duration: 2000,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
key: 'home',
|
||||||
|
title: '首页',
|
||||||
|
icon: <AppOutline />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'list',
|
||||||
|
title: '列表',
|
||||||
|
icon: <UnorderedListOutline />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'profile',
|
||||||
|
title: '我的',
|
||||||
|
icon: <UserOutline />,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<NavBar back={null}>AnKao</NavBar>
|
||||||
|
|
||||||
|
<div className={styles.content}>
|
||||||
|
<Card title="欢迎使用 AnKao">
|
||||||
|
<Space direction="vertical" block>
|
||||||
|
<p>这是一个基于 React + TypeScript + Vite + antd-mobile 构建的移动端应用</p>
|
||||||
|
|
||||||
|
<List header="技术栈">
|
||||||
|
<List.Item>⚛️ React 18</List.Item>
|
||||||
|
<List.Item>📘 TypeScript</List.Item>
|
||||||
|
<List.Item>⚡ Vite</List.Item>
|
||||||
|
<List.Item>📱 antd-mobile 5</List.Item>
|
||||||
|
<List.Item>🔧 Go Gin 后端</List.Item>
|
||||||
|
</List>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
block
|
||||||
|
onClick={handleButtonClick}
|
||||||
|
>
|
||||||
|
点击体验
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color="default"
|
||||||
|
size="large"
|
||||||
|
block
|
||||||
|
onClick={() => navigate('/about')}
|
||||||
|
>
|
||||||
|
关于页面
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TabBar activeKey={activeKey} onChange={setActiveKey}>
|
||||||
|
{tabs.map(item => (
|
||||||
|
<TabBar.Item key={item.key} icon={item.icon} title={item.title} />
|
||||||
|
))}
|
||||||
|
</TabBar>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home
|
||||||
79
web/src/utils/common.ts
Normal file
79
web/src/utils/common.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* 格式化日期
|
||||||
|
*/
|
||||||
|
export const formatDate = (date: Date | string | number, format = 'YYYY-MM-DD HH:mm:ss'): string => {
|
||||||
|
const d = new Date(date)
|
||||||
|
const year = d.getFullYear()
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(d.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(d.getMinutes()).padStart(2, '0')
|
||||||
|
const seconds = String(d.getSeconds()).padStart(2, '0')
|
||||||
|
|
||||||
|
return format
|
||||||
|
.replace('YYYY', String(year))
|
||||||
|
.replace('MM', month)
|
||||||
|
.replace('DD', day)
|
||||||
|
.replace('HH', hours)
|
||||||
|
.replace('mm', minutes)
|
||||||
|
.replace('ss', seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防抖函数
|
||||||
|
*/
|
||||||
|
export const debounce = <T extends (...args: any[]) => any>(
|
||||||
|
fn: T,
|
||||||
|
delay: number
|
||||||
|
): ((...args: Parameters<T>) => void) => {
|
||||||
|
let timer: NodeJS.Timeout | null = null
|
||||||
|
return (...args: Parameters<T>) => {
|
||||||
|
if (timer) clearTimeout(timer)
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
fn(...args)
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节流函数
|
||||||
|
*/
|
||||||
|
export const throttle = <T extends (...args: any[]) => any>(
|
||||||
|
fn: T,
|
||||||
|
delay: number
|
||||||
|
): ((...args: Parameters<T>) => void) => {
|
||||||
|
let lastTime = 0
|
||||||
|
return (...args: Parameters<T>) => {
|
||||||
|
const now = Date.now()
|
||||||
|
if (now - lastTime >= delay) {
|
||||||
|
fn(...args)
|
||||||
|
lastTime = now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地存储工具
|
||||||
|
*/
|
||||||
|
export const storage = {
|
||||||
|
get: <T = any>(key: string): T | null => {
|
||||||
|
const value = localStorage.getItem(key)
|
||||||
|
if (value) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(value) as T
|
||||||
|
} catch {
|
||||||
|
return value as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
set: (key: string, value: any): void => {
|
||||||
|
localStorage.setItem(key, JSON.stringify(value))
|
||||||
|
},
|
||||||
|
remove: (key: string): void => {
|
||||||
|
localStorage.removeItem(key)
|
||||||
|
},
|
||||||
|
clear: (): void => {
|
||||||
|
localStorage.clear()
|
||||||
|
},
|
||||||
|
}
|
||||||
75
web/src/utils/request.ts
Normal file
75
web/src/utils/request.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
|
||||||
|
|
||||||
|
// 创建 axios 实例
|
||||||
|
const instance: AxiosInstance = axios.create({
|
||||||
|
baseURL: '/api', // 通过 Vite 代理转发到 Go 后端
|
||||||
|
timeout: 10000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
// 可以在这里添加 token 等认证信息
|
||||||
|
const token = localStorage.getItem('token')
|
||||||
|
if (token && config.headers) {
|
||||||
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
(response: AxiosResponse) => {
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// 统一错误处理
|
||||||
|
if (error.response) {
|
||||||
|
switch (error.response.status) {
|
||||||
|
case 401:
|
||||||
|
// 未授权,跳转到登录页
|
||||||
|
console.error('未授权,请登录')
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
console.error('没有权限访问')
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
console.error('请求的资源不存在')
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
console.error('服务器错误')
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
console.error('请求失败:', error.response.data)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('网络错误:', error.message)
|
||||||
|
}
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 封装请求方法
|
||||||
|
export const request = {
|
||||||
|
get: <T = any>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
||||||
|
return instance.get(url, config)
|
||||||
|
},
|
||||||
|
post: <T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {
|
||||||
|
return instance.post(url, data, config)
|
||||||
|
},
|
||||||
|
put: <T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {
|
||||||
|
return instance.put(url, data, config)
|
||||||
|
},
|
||||||
|
delete: <T = any>(url: string, config?: AxiosRequestConfig): Promise<T> => {
|
||||||
|
return instance.delete(url, config)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default instance
|
||||||
1
web/src/vite-env.d.ts
vendored
Normal file
1
web/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
31
web/tsconfig.json
Normal file
31
web/tsconfig.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
/* Path mapping */
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
10
web/tsconfig.node.json
Normal file
10
web/tsconfig.node.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
26
web/vite.config.ts
Normal file
26
web/vite.config.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 3000,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:8080',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
assetsDir: 'assets',
|
||||||
|
},
|
||||||
|
})
|
||||||
2067
web/yarn.lock
Normal file
2067
web/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user