Skip to content

1. 数据库创建

用户表 user

  • idid 字段设置为自增字段,避免认为操作导致数据重复。设置为自增之后,每次往 user 表里新增数据,都会默认 id 加 1,就算你删除了前面的数据,是不会影响到 id 的自增。后续通过鉴权,生成用户信息。账单表的存储,都会以用户作为出发点。相当于 A 用户,存储自己的账单时,都会将 A 用户的 id 带上,相当于这份账单标记了用户 Aid
  • 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(开放授权)

img

登录接口

img

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 单位,这在移动端开发中非常有用,因为它可以使得不同设备上的字体大小更加统一和响应式。

text
npm 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 路径
    }
  },
})