feat: 本次提交更新内容如下

新项目模板初始化
This commit is contained in:
笔记本里的永平
2025-07-17 21:56:53 +08:00
parent 1c64a13058
commit 6a4e99885d
19 changed files with 339 additions and 0 deletions

4
nkebao/.env.development Normal file
View File

@@ -0,0 +1,4 @@
# 基础环境变量示例
VITE_API_BASE_URL=https://ckbapi.quwanzhi.com
VITE_APP_TITLE=Nkebao Base

4
nkebao/.env.production Normal file
View File

@@ -0,0 +1,4 @@
# 基础环境变量示例
VITE_API_BASE_URL=https://ckbapi.quwanzhi.com
VITE_APP_TITLE=Nkebao Base

21
nkebao/.eslintrc.js Normal file
View File

@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'react-app',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
parser: '@typescript-eslint/parser',
plugins: ['react', '@typescript-eslint', 'prettier'],
rules: {
'prettier/prettier': 'warn',
'react/react-in-jsx-scope': 'off',
'@typescript-eslint/no-unused-vars': 'warn',
},
};

6
nkebao/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
node_modules/
dist/
build/
yarn.lock
.env
.DS_Store

33
nkebao/README.md Normal file
View File

@@ -0,0 +1,33 @@
# Nkebao Base
基于 React + TypeScript + axios + sass + React Router v6 + antd + antd-mobile 的基础项目模板。
## 启动方式
```bash
yarn install
yarn start
```
## 技术栈
- React
- TypeScript
- axios
- sass
- React Router v6
- antd
- antd-mobile
- postcss-pxtorem (rem 适配)
## 目录结构
```
src/
api/ # axios 封装
pages/ # 页面组件
styles/ # 全局样式
App.tsx # 入口组件
main.tsx # 入口文件
public/
index.html # HTML 模板
```

13
nkebao/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nkebao Base</title>
<style>html{font-size:16px;}</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

37
nkebao/package.json Normal file
View File

@@ -0,0 +1,37 @@
{
"name": "nkebao-base",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^5.13.1",
"antd-mobile": "^5.39.1",
"axios": "^1.6.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.20.0"
},
"devDependencies": {
"@types/node": "^24.0.14",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@typescript-eslint/eslint-plugin": "^7.7.0",
"@typescript-eslint/parser": "^7.7.0",
"@vitejs/plugin-react": "^4.6.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.1",
"postcss": "^8.4.38",
"postcss-pxtorem": "^6.0.0",
"prettier": "^3.2.5",
"sass": "^1.75.0",
"typescript": "^5.4.5",
"vite": "^7.0.5"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}' --fix"
}
}

8
nkebao/postcss.config.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 16,
propList: ['*'],
},
},
};

23
nkebao/src/App.tsx Normal file
View File

@@ -0,0 +1,23 @@
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Button } from "antd";
import { Button as MobileButton } from "antd-mobile";
import Home from "./pages/Home";
import About from "./pages/About";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
<div style={{ margin: 16 }}>
<Button type="primary">Antd </Button>
<MobileButton color="primary">Antd-Mobile </MobileButton>
</div>
</BrowserRouter>
);
}
export default App;

View File

@@ -0,0 +1,22 @@
import { request } from '@/api/request';
export const list = (data?: any) =>
request('/cw/companyUser/list', data, 'GET');
export const joinAudit = (data: any) =>
request('/cw/companyUser/joinAudit', data, 'PUT');
export const listJoinAudit = (data?: any) =>
request('/cw/companyUser/listJoinAudit', data, 'GET');
export const CwCompanyUserApplyAdd = (data: any) =>
request('/cw/CwCompanyUserApply/add', data, 'PUT');
export const CwCompanyUserApplyAdminList = (data?: any) =>
request('/cw/CwCompanyUserApply/adminList', data, 'GET');
export const CwCompanyUserApplyAudit = (data: any) =>
request('/cw/CwCompanyUserApply/audit', data, 'POST');
export const CwCompanyUserApplyUserList = (data?: any) =>
request('/cw/CwCompanyUserApply/userList', data, 'GET');

64
nkebao/src/api/request.ts Normal file
View File

@@ -0,0 +1,64 @@
import axios, { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse } from 'axios';
const DEBOUNCE_GAP = 1000;
const debounceMap = new Map<string, number>();
const instance: AxiosInstance = axios.create({
baseURL: (import.meta as any).env?.VITE_API_BASE_URL || '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
instance.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers = config.headers || {};
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
});
instance.interceptors.response.use(
(res: AxiosResponse) => {
if (res.data && (res.data.code === 200 || res.data.success)) {
return res.data.data ?? res.data;
}
window?.alert?.(res.data?.msg || '接口错误');
return Promise.reject(res.data?.msg || '接口错误');
},
err => {
window?.alert?.(err.message || '网络异常');
return Promise.reject(err);
}
);
export function request(
url: string,
data?: any,
method: Method = 'GET',
config?: AxiosRequestConfig
): Promise<any> {
const key = `${method}_${url}_${JSON.stringify(data)}`;
const now = Date.now();
const last = debounceMap.get(key) || 0;
if (now - last < DEBOUNCE_GAP) {
return Promise.reject('请求过于频繁,请稍后再试');
}
debounceMap.set(key, now);
const axiosConfig: AxiosRequestConfig = {
url,
method,
...config,
};
if (method.toUpperCase() === 'GET') {
axiosConfig.params = data;
} else {
axiosConfig.data = data;
}
return instance(axiosConfig);
}
export default request;

7
nkebao/src/main.tsx Normal file
View File

@@ -0,0 +1,7 @@
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./styles/global.scss";
const root = createRoot(document.getElementById("root")!);
root.render(<App />);

View File

@@ -0,0 +1,7 @@
import React from "react";
const About: React.FC = () => {
return <h1> About</h1>;
};
export default About;

View File

@@ -0,0 +1,7 @@
import React from "react";
const Home: React.FC = () => {
return <h1> Home</h1>;
};
export default Home;

1
nkebao/src/react-app-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@@ -0,0 +1,18 @@
html, body {
height: 100%;
overflow: hidden; // 禁止 body 滚动和回弹
}
#root, .app-content {
height: 100vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch; // iOS 惯性滚动
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
background: #f5f5f5;
}

23
nkebao/tsconfig.json Normal file
View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}

15
nkebao/vite.config.ts Normal file
View File

@@ -0,0 +1,15 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve('src'),
},
},
server: {
open: true,
},
});

26
nkebao/技术栈.md Normal file
View File

@@ -0,0 +1,26 @@
## 使用技术栈
- React 18
- TypeScript
- Vite新一代前端构建工具
- axios
- sass (scss)
- React Router v6
- antd-mobile
- antd已设置基础单位为 rem配合 postcss-pxtorem
- postcss-pxtorempx 转 rem移动端适配
- ESLint + Prettier代码规范与自动格式化
- 路径别名 @ 指向 src 目录
## 关于兼容与工程化
- 自动化脚本yarn lint、yarn dev 等)
- 移动端 rem 适配html 根字体 + pxtorem
- iOS 浏览器滚动回弹兼容问题已通过全局样式处理
- 支持 VS Code 编辑器自动格式化(推荐配合 ESLint/Prettier 插件)
## 目录结构简要
- src/ 业务源码pages、api、styles、App.tsx、main.tsx 等)
- public/ 静态资源目录
- index.html 项目入口(根目录)
- vite.config.ts 构建与路径别名配置
- tsconfig.json TypeScript 配置
- .eslintrc.js 代码规范配置