启动成功,但无法get访问
This commit is contained in:
commit
75ca8e4199
|
@ -0,0 +1,8 @@
|
|||
node_modules
|
||||
/target/
|
||||
|
||||
# .env*
|
||||
!.env.template
|
||||
|
||||
upload/*
|
||||
log/*
|
|
@ -0,0 +1,2 @@
|
|||
nvm
|
||||
yarn
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"restartable": "rs",
|
||||
"verbose": true,
|
||||
"watch": ["src"],
|
||||
"ext": "ts",
|
||||
"ignore": ["node_modules/**/node_modules"],
|
||||
"execMap": {
|
||||
"js": "node --harmony"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "koa2-template",
|
||||
"version": "0.0.1",
|
||||
"description": "init a project with me",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "pm2 start ./src/index.js",
|
||||
"dev": "nodemon ./src/index.js",
|
||||
"test": "node ./test/redis.test.js",
|
||||
"serve": "nodemon ./src/index.ts --config nodemon.json",
|
||||
"build": "npm run tslint && npm run build-ts",
|
||||
"build-ts": "tsc",
|
||||
"watch": "npm run tslint && npm run watch-ts",
|
||||
"watch-ts": "tsc -w",
|
||||
"tslint": "tslint -c tslint.json -p tsconfig.json"
|
||||
},
|
||||
"author": "Hawkin",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
"dotenv": "^16.0.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^5.0.0",
|
||||
"koa-parameter": "^3.0.1",
|
||||
"koa-router": "^10.1.1",
|
||||
"koa-static": "^5.0.0",
|
||||
"mariadb": "^3.0.0",
|
||||
"mongoose": "^6.3.2",
|
||||
"mysql2": "^2.3.3",
|
||||
"pm2": "^5.2.0",
|
||||
"redis": "^4.1.0",
|
||||
"redis-connection-pool": "^2.0.2",
|
||||
"sequelize": "^6.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.5",
|
||||
"@types/koa-logger": "^3.1.2",
|
||||
"@types/koa-router": "^7.4.4",
|
||||
"@types/koa-static": "^4.0.2",
|
||||
"@types/koa-views": "^7.0.0",
|
||||
"nodemon": "^2.0.19",
|
||||
"ts-node": "^10.9.1",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^4.7.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||
}
|
||||
ol,
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote,
|
||||
q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before,
|
||||
blockquote:after,
|
||||
q:before,
|
||||
q:after {
|
||||
content: "";
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
/*清除浮动*/
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
content: "";
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/*容器*/
|
||||
.container {
|
||||
margin: 10px auto 0px;
|
||||
width: 95%;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
# 问题
|
||||
- 无法访问
|
||||
|
||||
|
||||
# 项目结构
|
||||
```bash
|
||||
.
|
||||
├── node_modules
|
||||
├── public 静态资源
|
||||
├── src
|
||||
│ ├── index.js 项目入口文件
|
||||
│ ├── app 业务应用
|
||||
│ ├── config 业务配置
|
||||
│ ├── routers 路由
|
||||
│ ├── middlewares 中间件()
|
||||
│ ├── controller 控制器(业务方法)
|
||||
│ ├── services 数据库交互
|
||||
│ ├── models (数据库)模型对象
|
||||
│ ├── db 数据库连接对象
|
||||
│ ├── constant 常数定义
|
||||
│ ├── util 工具函数
|
||||
│ └── views 渲染模板
|
||||
├── test
|
||||
│ ├── .example.http
|
||||
│ └── redis.test.js
|
||||
├── package.json
|
||||
├── readme.md
|
||||
└── readme.en.md
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
# 删除项目中的 占位/示例 文件(.example.*),不影响项目内容
|
|
@ -0,0 +1,10 @@
|
|||
export default (err:any, ctx:any) => {
|
||||
let status;
|
||||
switch (err.code) {
|
||||
default:
|
||||
status = 500;
|
||||
}
|
||||
ctx.status = status;
|
||||
ctx.body = err;
|
||||
// console.log(err)
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
import path from "path";
|
||||
|
||||
import Koa from "koa";
|
||||
import KoaBody from "koa-body";
|
||||
import KoaStatic from "koa-static";
|
||||
const parameter = require("koa-parameter");
|
||||
|
||||
require("../config/env.config"); // 加载配置
|
||||
import { router } from "../routers"; // 加载路由
|
||||
import errHandler from "./errorHandler"; // 加载自定义异常
|
||||
|
||||
export const app = new Koa();
|
||||
|
||||
app.use(
|
||||
KoaBody({
|
||||
multipart: true,
|
||||
formidable: {
|
||||
uploadDir: path.join(__dirname, "../upload"),
|
||||
keepExtensions: true,
|
||||
},
|
||||
parsedMethods: ["POST", "PUT", "PATCH", "DELETE"],
|
||||
})
|
||||
);
|
||||
app.use(KoaStatic(path.join(__dirname, "../upload")));
|
||||
app.use(parameter(app));
|
||||
|
||||
app.use(router.routes()).use(router.allowedMethods());
|
||||
|
||||
// 统一的错误处理
|
||||
app.on("error", errHandler); // 监听全局异常事件
|
||||
|
||||
export default app;
|
|
@ -0,0 +1 @@
|
|||
APP_PORT = 3000
|
|
@ -0,0 +1,31 @@
|
|||
APP_PORT = 3000
|
||||
|
||||
MYSQL_DIALECT = mysql
|
||||
MYSQL_HOST =
|
||||
MYSQL_PORT = 3306
|
||||
MYSQL_DBNAME =
|
||||
MYSQL_USER =
|
||||
MYSQL_PASSWD =
|
||||
|
||||
MARIA_DIALECT = mariadb
|
||||
MARIA_HOST =
|
||||
MARIA_PORT = 3306
|
||||
MARIA_DBNAME =
|
||||
MARIA_USER =
|
||||
MARIA_PASSWD =
|
||||
|
||||
MONGO_DIALECT = mongodb
|
||||
MONGO_HOST =
|
||||
MONGO_PORT = 21017
|
||||
MONGO_DBNAME =
|
||||
MONGO_USER =
|
||||
MONGO_PASSWD =
|
||||
|
||||
REDIS_DIALECT = redis
|
||||
REDIS_HOST =
|
||||
REDIS_PORT = 6379
|
||||
REDIS_DBNAME =
|
||||
REDIS_USER =
|
||||
REDIS_PASSWD =
|
||||
|
||||
JWT_SECRET =
|
|
@ -0,0 +1,3 @@
|
|||
const { config } = require("dotenv");
|
||||
|
||||
config({ path: "./src/config/.env" });
|
|
@ -0,0 +1,87 @@
|
|||
module.exports = {
|
||||
userFormateError: {
|
||||
code: '10001',
|
||||
message: '用户名或密码为空',
|
||||
result: '',
|
||||
},
|
||||
userAlreadyExited: {
|
||||
code: '10002',
|
||||
message: '用户已经存在',
|
||||
result: '',
|
||||
},
|
||||
userRegisterError: {
|
||||
code: '10003',
|
||||
message: '用户注册错误',
|
||||
result: '',
|
||||
},
|
||||
userDoesNotExist: {
|
||||
code: '10004',
|
||||
message: '用户不存在',
|
||||
result: '',
|
||||
},
|
||||
userLoginError: {
|
||||
code: '10005',
|
||||
message: '用户登录失败',
|
||||
result: '',
|
||||
},
|
||||
invalidPassword: {
|
||||
code: '10006',
|
||||
message: '密码不匹配',
|
||||
result: '',
|
||||
},
|
||||
tokenExpiredError: {
|
||||
code: '10101',
|
||||
message: 'token已过期',
|
||||
result: '',
|
||||
},
|
||||
invalidToken: {
|
||||
code: '10102',
|
||||
message: '无效的token',
|
||||
result: '',
|
||||
},
|
||||
hasNotAdminPermission: {
|
||||
code: '10103',
|
||||
message: '没有管理员权限',
|
||||
result: '',
|
||||
},
|
||||
fileUploadError: {
|
||||
code: '10201',
|
||||
message: '商品图片上传失败',
|
||||
result: '',
|
||||
},
|
||||
unSupportedFileType: {
|
||||
code: '10202',
|
||||
message: '不支持的文件格式',
|
||||
result: '',
|
||||
},
|
||||
goodsFormatError: {
|
||||
code: '10203',
|
||||
message: '商品参数格式错误',
|
||||
result: '',
|
||||
},
|
||||
publishGoodsError: {
|
||||
code: '10204',
|
||||
message: '发布商品失败',
|
||||
result: '',
|
||||
},
|
||||
invalidGoodsID: {
|
||||
code: '10205',
|
||||
message: '无效的商品id',
|
||||
result: '',
|
||||
},
|
||||
cartFormatError: {
|
||||
code: '10301',
|
||||
message: '购物车数据格式错误',
|
||||
result: '',
|
||||
},
|
||||
addrFormatError: {
|
||||
code: '10401',
|
||||
message: '地址数据格式错误',
|
||||
result: '',
|
||||
},
|
||||
orderFormatError: {
|
||||
code: '10501',
|
||||
message: '订单数据格式错误',
|
||||
result: '',
|
||||
},
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import d from "../models/user";
|
||||
import Koa from "koa";
|
||||
|
||||
// class UserController {
|
||||
export async function register(ctx: any, next: any) {
|
||||
ctx.json({ code: 0, message: "success" });
|
||||
}
|
||||
|
||||
export function getUserList(ctx: any, next: any) {
|
||||
ctx.json('{ "code": 0, "message": "success" }')
|
||||
}
|
||||
// }
|
||||
// export default new UserController();
|
|
@ -0,0 +1,27 @@
|
|||
// connect to third-service of database or other.
|
||||
const { Sequelize } = require("sequelize");
|
||||
|
||||
const {
|
||||
MARIA_DIALECT,
|
||||
MARIA_HOST,
|
||||
MARIA_PORT,
|
||||
MARIA_DBNAME,
|
||||
MARIA_USRNAME,
|
||||
MARIA_PASSWD,
|
||||
} = process.env;
|
||||
|
||||
const seq = new Sequelize(MARIA_DBNAME, MARIA_USRNAME, MARIA_PASSWD, {
|
||||
host: MARIA_HOST,
|
||||
port: MARIA_PORT,
|
||||
dialect: 'mariadb',
|
||||
});
|
||||
|
||||
seq.authenticate()
|
||||
.then(() => {
|
||||
console.log('数据库连接成功')
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('数据库连接失败', err)
|
||||
})
|
||||
|
||||
module.exports = seq;
|
|
@ -0,0 +1,49 @@
|
|||
const redis = require("redis");
|
||||
// require("../config/env.config");
|
||||
|
||||
const { REDIS_HOST, REDIS_PORT, REDIS_DBNAME, REDIS_USER, REDIS_PASSWD } =
|
||||
process.env; // REDIS_USER 和 REDIS_PASSWD,需要服务器配置ACL用户名密码
|
||||
const URL = `redis://${REDIS_USER}:${REDIS_PASSWD}@${REDIS_HOST}:${REDIS_PORT}/${REDIS_DBNAME}`;
|
||||
|
||||
// https://github.com/redis/node-redis/tree/master/docs
|
||||
// module.exports = redis.createClient({URL});
|
||||
const client = redis.createClient({
|
||||
// url: URL,
|
||||
socket: { host: REDIS_HOST, port: REDIS_PORT },
|
||||
password: REDIS_PASSWD,
|
||||
// database: REDIS_DBNAME,
|
||||
// legacyMode: true, // 语法向后(v3)部分兼容
|
||||
});
|
||||
|
||||
client.on("error", (err) => console.log(`redis client ~ Error ${err}`));
|
||||
client.on("connect", () => console.log("redis client ~ connect"));
|
||||
client.on("reconnecting", () => console.log("redis client ~ reconnecting"));
|
||||
client.on("ready", () => console.log("redis client ~ ready"));
|
||||
client.on("end", () => console.log("redis client ~ end"));
|
||||
|
||||
client.connect();
|
||||
client.ping();
|
||||
// try {
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// }
|
||||
|
||||
module.exports = client;
|
||||
|
||||
//* 方式二:redis 连接池
|
||||
//! unusable
|
||||
/* var redisPool = require("redis-connection-pool")("myRedisPool", {
|
||||
host: REDIS_HOST, // default
|
||||
port: REDIS_PORT, //default
|
||||
max_clients: 30, // defalut
|
||||
perform_checks: false, // checks for needed push/pop functionality
|
||||
database: 0, // database number to use
|
||||
options: {
|
||||
auth_pass: REDIS_PASSWD,
|
||||
}, //options for createClient of node-redis, optional
|
||||
});
|
||||
redisPool.set("test-key", "foobar", function (err) {
|
||||
redisPool.get("test-key", function (err, reply) {
|
||||
console.log(reply); // 'foobar'
|
||||
});
|
||||
}); */
|
|
@ -0,0 +1,7 @@
|
|||
import {app} from "./app";
|
||||
|
||||
const { APP_PORT } = process.env;
|
||||
|
||||
app.listen((APP_PORT ?? 3000), () => {
|
||||
console.log(`server is running on http://localhost:${APP_PORT ?? 3000}`);
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const { JWT_SECRET } = require('../config/config.default')
|
||||
|
||||
const {
|
||||
tokenExpiredError,
|
||||
invalidToken,
|
||||
hasNotAdminPermission,
|
||||
} = require('../constant/error.type')
|
||||
|
||||
const auth = async (ctx, next) => {
|
||||
const { authorization = '' } = ctx.request.header
|
||||
const token = authorization.replace('Bearer ', '')
|
||||
// console.log(token)
|
||||
|
||||
try {
|
||||
// user中包含了payload的信息(id, user_name, is_admin)
|
||||
const user = jwt.verify(token, JWT_SECRET)
|
||||
ctx.state.user = user
|
||||
} catch (err) {
|
||||
switch (err.name) {
|
||||
case 'TokenExpiredError':
|
||||
console.error('token已过期', err)
|
||||
return ctx.app.emit('error', tokenExpiredError, ctx)
|
||||
case 'JsonWebTokenError':
|
||||
console.error('无效的token', err)
|
||||
return ctx.app.emit('error', invalidToken, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
// 判断:是否有管理员权限
|
||||
const hadAdminPermission = async (ctx, next) => {
|
||||
const { is_admin } = ctx.state.user
|
||||
|
||||
if (!is_admin) {
|
||||
console.error('该用户没有管理员的权限', ctx.state.user)
|
||||
return ctx.app.emit('error', hasNotAdminPermission, ctx)
|
||||
}
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
auth,
|
||||
hadAdminPermission,
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
const bcrypt = require('bcryptjs')
|
||||
|
||||
const { getUerInfo } = require('../service/user.service')
|
||||
const {
|
||||
userFormateError,
|
||||
userAlreadyExited,
|
||||
userRegisterError,
|
||||
userDoesNotExist,
|
||||
userLoginError,
|
||||
invalidPassword,
|
||||
} = require('../constant/error.type')
|
||||
|
||||
const userValidator = async (ctx, next) => {
|
||||
const { user_name, password } = ctx.request.body
|
||||
// 合法性
|
||||
if (!user_name || !password) {
|
||||
console.error('用户名或密码为空', ctx.request.body)
|
||||
ctx.app.emit('error', userFormateError, ctx)
|
||||
return
|
||||
}
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
const verifyUser = async (ctx, next) => {
|
||||
const { user_name } = ctx.request.body
|
||||
|
||||
// if (await getUerInfo({ user_name })) {
|
||||
// ctx.app.emit('error', userAlreadyExited, ctx)
|
||||
// return
|
||||
// }
|
||||
try {
|
||||
const res = await getUerInfo({ user_name })
|
||||
|
||||
if (res) {
|
||||
console.error('用户名已经存在', { user_name })
|
||||
ctx.app.emit('error', userAlreadyExited, ctx)
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取用户信息错误', err)
|
||||
ctx.app.emit('error', userRegisterError, ctx)
|
||||
return
|
||||
}
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
const crpytPassword = async (ctx, next) => {
|
||||
const { password } = ctx.request.body
|
||||
|
||||
const salt = bcrypt.genSaltSync(10)
|
||||
// hash保存的是 密文
|
||||
const hash = bcrypt.hashSync(password, salt)
|
||||
|
||||
ctx.request.body.password = hash
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
const verifyLogin = async (ctx, next) => {
|
||||
// 1. 判断用户是否存在(不存在:报错)
|
||||
const { user_name, password } = ctx.request.body
|
||||
|
||||
try {
|
||||
const res = await getUerInfo({ user_name })
|
||||
|
||||
if (!res) {
|
||||
console.error('用户名不存在', { user_name })
|
||||
ctx.app.emit('error', userDoesNotExist, ctx)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 密码是否匹配(不匹配: 报错)
|
||||
if (!bcrypt.compareSync(password, res.password)) {
|
||||
ctx.app.emit('error', invalidPassword, ctx)
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return ctx.app.emit('error', userLoginError, ctx)
|
||||
}
|
||||
|
||||
await next()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
userValidator,
|
||||
verifyUser,
|
||||
crpytPassword,
|
||||
verifyLogin,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { DataTypes } from 'sequelize'
|
||||
|
||||
import seq from '../db/mariadb'
|
||||
|
||||
// 创建模型(Model user -> 数据库表 users)
|
||||
const User = seq.define('user', {
|
||||
// id 会被sequelize自动创建, 管理
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
comment: '用户名, 唯一',
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.CHAR(64),
|
||||
allowNull: false,
|
||||
comment: '密码',
|
||||
},
|
||||
is_admin: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
comment: '是否为管理员: 0 不是管理员(默认); 1 是管理员',
|
||||
},
|
||||
})
|
||||
|
||||
// 强制同步数据库(创建数据表)
|
||||
// User.sync({ force: true })
|
||||
|
||||
export default User
|
|
@ -0,0 +1,6 @@
|
|||
import { getUserList } from "../controller/user";
|
||||
|
||||
import Router from "koa-router";
|
||||
export const router = new Router({ prefix: "/" });
|
||||
|
||||
router.get("/list", getUserList);
|
|
@ -0,0 +1,19 @@
|
|||
import { readdirSync } from "fs";
|
||||
|
||||
const Router = require("koa-router");
|
||||
export const router = new Router();
|
||||
import { getUserList } from "../controller/user";
|
||||
|
||||
router.get("/list", getUserList);
|
||||
// 自动载入同级目录中所有文件里的router
|
||||
readdirSync(__dirname).forEach(async (file) => {
|
||||
// console.log(file)
|
||||
if (file !== "index.ts") {
|
||||
let { router: r } = require("./" + file);
|
||||
// console.log(r)
|
||||
router.use(r.routes());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default router;
|
|
@ -0,0 +1,6 @@
|
|||
import { getUserList } from "../controller/user";
|
||||
|
||||
import Router from "koa-router";
|
||||
export const router = new Router({ prefix: "/user" });
|
||||
|
||||
router.get("/list", getUserList);
|
|
@ -0,0 +1,29 @@
|
|||
const redisClient = require("../../db/redis");
|
||||
|
||||
/**
|
||||
Object.prototype.toString = function () {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
*/
|
||||
|
||||
class RedisService {
|
||||
client = redisClient;
|
||||
|
||||
save2Redis(key, value) {
|
||||
redisClient.set(key, value);
|
||||
}
|
||||
|
||||
getByKey(key, callback = null) {
|
||||
if (callback) {
|
||||
redisClient.get(key, callback);
|
||||
} else {
|
||||
redisClient.get(key, (err, value) => {
|
||||
if (err) return null;
|
||||
console.log(value);
|
||||
// return value;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new RedisService();
|
|
@ -0,0 +1,42 @@
|
|||
const User = require('../models/user')
|
||||
|
||||
class UserService {
|
||||
async createUser(user_name, password) {
|
||||
// 插入数据
|
||||
// await表达式: promise对象的值
|
||||
const res = await User.create({ user_name, password })
|
||||
// console.log(res)
|
||||
return res.dataValues
|
||||
}
|
||||
|
||||
async getUerInfo({ id, user_name, password, is_admin }) {
|
||||
const whereOpt = {}
|
||||
|
||||
id && Object.assign(whereOpt, { id })
|
||||
user_name && Object.assign(whereOpt, { user_name })
|
||||
password && Object.assign(whereOpt, { password })
|
||||
is_admin && Object.assign(whereOpt, { is_admin })
|
||||
|
||||
const res = await User.findOne({
|
||||
attributes: ['id', 'user_name', 'password', 'is_admin'],
|
||||
where: whereOpt,
|
||||
})
|
||||
|
||||
return res ? res.dataValues : null
|
||||
}
|
||||
|
||||
async updateById({ id, user_name, password, is_admin }) {
|
||||
const whereOpt = { id }
|
||||
const newUser = {}
|
||||
|
||||
user_name && Object.assign(newUser, { user_name })
|
||||
password && Object.assign(newUser, { password })
|
||||
is_admin && Object.assign(newUser, { is_admin })
|
||||
|
||||
const res = await User.update(newUser, { where: whereOpt })
|
||||
// console.log(res)
|
||||
return res[0] > 0 ? true : false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new UserService()
|
|
@ -0,0 +1,5 @@
|
|||
const bcryptjs = require("bcryptjs");
|
||||
|
||||
class Bcrypt {}
|
||||
|
||||
module.exports = new Bcrypt();
|
|
@ -0,0 +1,9 @@
|
|||
import path, { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import fs, { readdir } from "fs";
|
||||
|
||||
export function getDirPath(importMetaUrl = import.meta.url) {
|
||||
return dirname(new URL(importMetaUrl).pathname).replace(/^\//,''); // /d:/...
|
||||
} // use by: getDirname() with real arg. //* 必须带实参,不然返回的还是本文件的目录路径
|
||||
|
||||
export default getDirPath;
|
|
@ -0,0 +1,18 @@
|
|||
const {
|
||||
client,
|
||||
save2Redis,
|
||||
getByKey,
|
||||
} = require("../src/service/redis/base.service");
|
||||
|
||||
save2Redis("key1", "i am string value");
|
||||
// redis 储存时默认调用 Object.toString 而非 JSON.stringify
|
||||
// save2Redis("key2", { key: "i am string value from Object.toString()" }); // value是object,报参数类型错误
|
||||
|
||||
getByKey("key2"); // 无console输出
|
||||
|
||||
client.rPush("alist", "abc");
|
||||
// client.rPush("alist", 123); // value是object,报参数类型错误
|
||||
client.lRange("alist", 0, -1, (err, v) => {
|
||||
console.log(v); // 无console输出
|
||||
client.disconnect();
|
||||
});
|
Loading…
Reference in New Issue