1. 数据库创建
用户表 user
- id:
id
字段设置为自增字段,避免认为操作导致数据重复。设置为自增之后,每次往user
表里新增数据,都会默认id
加 1,就算你删除了前面的数据,是不会影响到id
的自增。后续通过鉴权,生成用户信息。账单表的存储,都会以用户作为出发点。相当于A
用户,存储自己的账单时,都会将A
用户的id
带上,相当于这份账单标记了用户A
的id
。 - username:用于存储用户登录名称。
- password:用于存储用户登录密码。
- signature:根据上图,还需要一个
signature
字段作为个性签名。 - avatar:用于存储用户头像信息。
- ctime:用于存储用户创建时间字段。
账单表 bill
- id:每张表都需要一个主键,我们照旧,用
id
作为「账单表」的属性。 - pay_type:账单类型,账单无非就是两种类型,支出和收入,我们用
pay_type
作为类型字段,这里约定好1
为支出,2
为收入。 - amount:账单价格,每个账单都需有一个价格属性,表示该笔账单你消费或收入了多少钱。
- date:账单日期,日期可自由选择,以时间戳的形式存储。
- type_id:账单标签 id,如餐饮、交通、日用、学习、购物等。
- type_name:账单标签名称,如餐饮、交通、日用、学习、购物等。
- user_id:账单归属的用户
id
,本小册制作的是多用户项目,相当于可以有多个用户来注册使用,所以存储账单的时候,需要将用户的id
带上,便于后面查询账单列表之时,过滤出该用户的账单。 - remark:账单备注。
标签表 type
- id:唯一标识,设为主键。
- name:标签名称,如餐饮、交通、日用、学习、购物等。
- type:标签类型,默认
1
为收入,2
为支出。 - user_id:保留字段,设置该标签的用户归属,默认 0 为全部用户可见,某个用户单独设置的标签,
user_id
就是该用户的用户id
,在获取列表的时候,方便过滤。
2. 登录注册,用户鉴权
- egg-jwt 插件的使用
- egg 中间件编写
- token 鉴权
egg-jwt 插件
npm i egg-jwt -S
在 config/plugin.js
下添加插件:
js
js 代码解读复制代码...
jwt: {
enable: true,
package: 'egg-jwt',
}
...
紧接着前往 config/config.default.js
下添加自定义加密字符串:
js
js 代码解读复制代码config.jwt = {
secret: '加密字符串',
};
鉴权的机制,分为四种:
- HTTP Basic Authentication
- session-cookie
- Token 令牌
- OAuth(开放授权)
登录接口
3. 前端h5页面
安装react
bash
npm init vite@latest my-vite-app --template react
安装react-router-dom
css
npm i react-router-dom -S
引入 Zarm UI 组件库
npm install zarm -S
修改 App.jsx
的代码,全局引入样式和中文包:
jsx
import React, { useState } from 'react'
import {
BrowserRouter as Router,
Switch,
Route
} from "react-router-dom"
import { ConfigProvider } from 'zarm'
import zhCN from 'zarm/lib/config-provider/locale/zh_CN'
import 'zarm/dist/zarm.css'
import routes from '../src/router'
function App() {
return <Router>
<ConfigProvider primaryColor={'#007fff'} locale={zhCN}>
<Switch>
{
routes.map(route => <Route exact key={route.path} path={route.path}>
<route.component />
</Route>)
}
</Switch>
</ConfigProvider>
</Router>
}
export default App
配置「按需引入」
npm i vite-plugin-style-import -D
在 vite.config.js
配置文件内添加如下内容:
js
export default defineConfig({
plugins: [reactRefresh(), styleImport(
{
libs: [
{
libraryName: 'zarm',
esModule: true,
resolveStyle: (name) => {
return `zarm/es/${name}/style/css`;
},
}
]
}
)],
配置CSS预处理器Less
npm i less -D
修改 vite.config.js
js
{
plugins: [...]
css: {
modules: {
localsConvention: 'dashesOnly'
},
preprocessorOptions: {
less: {
// 支持内联 JavaScript
javascriptEnabled: true,
}
}
},
}
移动端项目适配 rem
安装 lib-flexible
npm i lib-flexible -S
在 main.jsx
中引入它:
jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import "zarm/dist/zarm.min.css"; // 引入 Zarm 的样式
import 'lib-flexible/flexible'
createRoot(document.getElementById("root")).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);
安装 postcss-pxtorem
postcss-pxtorem
是一个 PostCSS 插件,它将你的 CSS 中的 px
单位转换为 rem
单位,这在移动端开发中非常有用,因为它可以使得不同设备上的字体大小更加统一和响应式。
textnpm install postcss postcss-pxtorem --save-dev
在项目根目录新建 postcss.config.js
:
js
// postcss.config.js
// 用 vite 创建项目,配置 postcss 需要使用 post.config.js,之前使用的 .postcssrc.js 已经被抛弃
// 具体配置可以去 postcss-pxtorem 仓库看看文档
module.exports = {
"plugins": [
require("postcss-pxtorem")({
rootValue: 37.5,
propList: ['*'],
selectorBlackList: ['.norem'] // 过滤掉.norem-开头的class,不进行rem转换
})
]
}
二次封装 axios
npm i axios -S
在 src
目录下新建 utils
目录,并新建 axios.js
脚本
js
import axios from "axios";
import {
Toast
} from "zarm";
const MODE =
import.meta.env.MODE // 环境变量
//设置请求的基础路径
axios.defaults.baseURL = MODE === 'development' ? '/api' : 'http://127.0.0.1:7001'
axios.defaults.withCredentials = true
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
axios.defaults.headers['Authorization'] = `${localStorage.getItem('token') || null}`
axios.defaults.headers.post['Content-Type'] = 'application/json'
// 配置 post 请求,使用的请求体,这里默认设置成 application/json 的形式。
// interceptors 拦截器 拦截每一次请求
axios.interceptors.response.use(res => {
if (typeof res.data !== 'object') {
Toast.show('服务器异常!')
return Promise.reject(res)
}
// //判断请求内容,如果非 200,则提示错误信息
if (res.data.code !== 200) {
if (res.data.msg) Toast.show(res.data.msg)
//401 的话,就是没有登录的用户
if (res.data.code === 401) {
window.location.href = '/login'
}
// 则 return res.data
return Promise.reject(res.data)
}
return res.data
})
export default axios
代理配置
配置代理,打开 vite.config.js
,添加如下代码
javascript
server: {
proxy: {
'/api': {
// 当遇到 /api 路径时,将其转换成 target 的值
target: 'http://127.0.0.1:7001',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''), // 将 /api 重写为空
}
}
}
resolve.alias 别名设置
打开 vite.config.js
,添加配置如下:
javascript
import path from 'path'
export default defineConfig({
...
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // src 路径
'config': path.resolve(__dirname, 'src/config') // src 路径
}
},
})