docs:更新文档
11
.gitignore
vendored
@ -1,11 +0,0 @@
|
|||||||
/doc/node_modules
|
|
||||||
/doc/docs/.vitepress/dist
|
|
||||||
|
|
||||||
/backend/node_modules
|
|
||||||
|
|
||||||
/frontend/angular-ts/node_modules
|
|
||||||
|
|
||||||
/frontend/react-ts/node_modules
|
|
||||||
|
|
||||||
/frontend/vue-ts/node_modules
|
|
||||||
/frontend/vue-ts/dist
|
|
21
LICENSE
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 和尚
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
54
README.md
@ -1,43 +1,17 @@
|
|||||||
# Vue3.0版本已开发完成!
|
# 后端管理项目文档
|
||||||
Vue3.0+TypeScript+NodeJS+MySql编写的一套后台管理框架
|
|
||||||
|
|
||||||
## 文档地址
|
## 安装依赖
|
||||||
https://xiaoxian521.github.io/zh/standard/
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
## 结构介绍
|
## 文档启动
|
||||||
① frontend为前端项目存放文件夹
|
```
|
||||||
② backend为后端项目存放文件夹
|
npm run docs
|
||||||
③ doc为文档编写存放文件夹
|
```
|
||||||
|
|
||||||
## Structure introduction
|
## 文档打包
|
||||||
① Frontend stores the folder for the front-end project
|
```
|
||||||
② Backend stores the folder for the back-end project
|
npm run docs:build
|
||||||
③ Doc write storage folder for documents
|
```
|
||||||
|
打包后会在.vitepress文件夹下生成dist目录
|
||||||
## 前端对应代码存放目录
|
|
||||||
vue => /frontend/vue-ts
|
|
||||||
react => /frontend/react-ts
|
|
||||||
angular => /frontend/angular-ts
|
|
||||||
|
|
||||||
## Front end corresponding code storage directory
|
|
||||||
vue => /frontend/vue-ts
|
|
||||||
react => /frontend/react-ts
|
|
||||||
angular => /frontend/angular-ts
|
|
||||||
|
|
||||||
## 注意点
|
|
||||||
① 接口文档使用Swagger
|
|
||||||
② 编写者必须严格遵守项目中tslint编写规则
|
|
||||||
③ 编写者必须严格遵循代码命名语义化、提高代码可读性
|
|
||||||
④ 编写者编写代码完毕必须经过单元测试,保证代码可用性
|
|
||||||
⑤ 编写必须完全使用TypeScript,保证代码严谨性、可维护性
|
|
||||||
⑥ 编写者提交代码发生冲突,必须先解决,在推送,严禁使用git push -f origin 分支
|
|
||||||
⑦ 编写者无须在项目中放置.gitignore文件,如需加入别的git忽略请放在CURD-TS文件夹跟目录的.gitignore文件
|
|
||||||
|
|
||||||
## Attention point
|
|
||||||
① Interface documents use swagger
|
|
||||||
② The author must strictly abide by the tslint writing rules in the project
|
|
||||||
③ The author must strictly follow the code naming semantics and improve the readability of the code
|
|
||||||
④ The author must go through the unit test to ensure the usability of the code
|
|
||||||
⑤ Typescript must be used completely to ensure code rigor and maintainability
|
|
||||||
⑥ If the code submitted by the writer conflicts, it must be resolved first. In pushing, GIT push - f origin branch is strictly prohibited
|
|
||||||
⑦ The author does not need to place the. Gitignore file in the project. If you want to add other git ignore, please put it in the curd-ts folder and the. Gitignore file in the directory
|
|
@ -1,8 +0,0 @@
|
|||||||
# Port
|
|
||||||
PORT=3000
|
|
||||||
|
|
||||||
# JWT_SECRET
|
|
||||||
JWT_SECRET = '708DD1DC5BC5A169'
|
|
||||||
|
|
||||||
# Debug
|
|
||||||
LOG_LEVEL='debug'
|
|
@ -1,27 +0,0 @@
|
|||||||
# 接口
|
|
||||||
|
|
||||||
## 安装依赖
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
## 项目启动
|
|
||||||
```
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Swagger文档访问地址
|
|
||||||
http://localhost:3000
|
|
||||||
|
|
||||||
## 在swagger中添加token验证
|
|
||||||
① 先请求验证码接口,拿到验证码(info字段就是验证码)
|
|
||||||
② 然后请求登录接口,你可以在网页的Network中拿到登录成功后返回的token,复制
|
|
||||||
③ 最后回到swagger,点击右上角的绿色边框Authorize,你会看到一个Value的输入框,将复制的token前面加上Bearer 粘贴上去,点确定即可(Authorize)
|
|
||||||
(注意Bearer后面有一个空格哦)
|
|
||||||
|
|
||||||
## 注意点
|
|
||||||
请先全局安装typescript、ts-node,如安装请忽略
|
|
||||||
```
|
|
||||||
npm install -g typescript
|
|
||||||
npm install -g ts-node
|
|
||||||
```
|
|
3752
backend/package-lock.json
generated
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "backend-ts",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "API接口",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"dev": "ts-node ./src/server.ts",
|
|
||||||
"start": "nodemon ./dist/server.js",
|
|
||||||
"prod": "npm run build && npm run start"
|
|
||||||
},
|
|
||||||
"author": "team",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
|
||||||
"nodemon": "^1.19.4",
|
|
||||||
"open": "^7.3.0",
|
|
||||||
"tslint": "^5.20.1",
|
|
||||||
"typescript": "^3.9.7"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/express": "^4.17.9",
|
|
||||||
"dotenv": "^8.2.0",
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"express-swagger-generator": "^1.1.17",
|
|
||||||
"jsonwebtoken": "^8.5.1",
|
|
||||||
"mysql2": "^2.2.5",
|
|
||||||
"svg-captcha": "^1.4.0",
|
|
||||||
"winston": "^3.3.3"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 665 B |
Before Width: | Height: | Size: 628 B |
@ -1,59 +0,0 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Swagger UI</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
|
||||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
|
||||||
<style>
|
|
||||||
html {
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: -moz-scrollbars-vertical;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*:before,
|
|
||||||
*:after {
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="swagger-ui"></div>
|
|
||||||
|
|
||||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
|
||||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
|
||||||
<script>
|
|
||||||
window.onload = function () {
|
|
||||||
// Begin Swagger UI call region
|
|
||||||
const ui = SwaggerUIBundle({
|
|
||||||
url: "http://localhost:3000/swagger.json",
|
|
||||||
dom_id: '#swagger-ui',
|
|
||||||
deepLinking: true,
|
|
||||||
presets: [
|
|
||||||
SwaggerUIBundle.presets.apis,
|
|
||||||
SwaggerUIStandalonePreset
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
SwaggerUIBundle.plugins.DownloadUrl
|
|
||||||
],
|
|
||||||
layout: "StandaloneLayout"
|
|
||||||
})
|
|
||||||
// End Swagger UI call region
|
|
||||||
|
|
||||||
window.ui = ui
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,74 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en-US">
|
|
||||||
<head>
|
|
||||||
<title>Swagger UI: OAuth2 Redirect</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
function run () {
|
|
||||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
|
||||||
var sentState = oauth2.state;
|
|
||||||
var redirectUrl = oauth2.redirectUrl;
|
|
||||||
var isValid, qp, arr;
|
|
||||||
|
|
||||||
if (/code|token|error/.test(window.location.hash)) {
|
|
||||||
qp = window.location.hash.substring(1);
|
|
||||||
} else {
|
|
||||||
qp = location.search.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
arr = qp.split("&")
|
|
||||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
|
||||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
|
||||||
function (key, value) {
|
|
||||||
return key === "" ? value : decodeURIComponent(value)
|
|
||||||
}
|
|
||||||
) : {}
|
|
||||||
|
|
||||||
isValid = qp.state === sentState
|
|
||||||
|
|
||||||
if ((
|
|
||||||
oauth2.auth.schema.get("flow") === "accessCode"||
|
|
||||||
oauth2.auth.schema.get("flow") === "authorizationCode"
|
|
||||||
) && !oauth2.auth.code) {
|
|
||||||
if (!isValid) {
|
|
||||||
oauth2.errCb({
|
|
||||||
authId: oauth2.auth.name,
|
|
||||||
source: "auth",
|
|
||||||
level: "warning",
|
|
||||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qp.code) {
|
|
||||||
delete oauth2.state;
|
|
||||||
oauth2.auth.code = qp.code;
|
|
||||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
|
||||||
} else {
|
|
||||||
let oauthErrorMsg
|
|
||||||
if (qp.error) {
|
|
||||||
oauthErrorMsg = "["+qp.error+"]: " +
|
|
||||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
|
||||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
oauth2.errCb({
|
|
||||||
authId: oauth2.auth.name,
|
|
||||||
source: "auth",
|
|
||||||
level: "error",
|
|
||||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
|
||||||
}
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', function () {
|
|
||||||
run();
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,31 +0,0 @@
|
|||||||
import * as express from "express"
|
|
||||||
import * as bodyParser from "body-parser"
|
|
||||||
|
|
||||||
class App {
|
|
||||||
public app: express.Application
|
|
||||||
constructor() {
|
|
||||||
this.app = express()
|
|
||||||
this.config()
|
|
||||||
}
|
|
||||||
private config(): void {
|
|
||||||
// 支持json编码的主体
|
|
||||||
this.app.use(bodyParser.json())
|
|
||||||
// 支持编码的主体
|
|
||||||
this.app.use(bodyParser.urlencoded({
|
|
||||||
extended: true,
|
|
||||||
}))
|
|
||||||
// 设置静态访问目录(Swagger)
|
|
||||||
this.app.use(express.static('public'))
|
|
||||||
// 设置跨域访问
|
|
||||||
this.app.all('*', (req, res, next) => {
|
|
||||||
res.header('Access-Control-Allow-Origin', '*')
|
|
||||||
res.header('Access-Control-Allow-Headers', 'content-type')
|
|
||||||
res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
|
|
||||||
res.header('X-Powered-By', ' 3.2.1')
|
|
||||||
res.header('Content-Type', 'application/json;charset=utf-8')
|
|
||||||
next()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new App().app
|
|
@ -1,66 +0,0 @@
|
|||||||
import * as dotenv from "dotenv"
|
|
||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || "development"
|
|
||||||
|
|
||||||
const envFound = dotenv.config()
|
|
||||||
if (envFound.error) {
|
|
||||||
|
|
||||||
throw new Error("⚠️ Couldn't find .env file ⚠️")
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
port: parseInt(process.env.PORT, 10),
|
|
||||||
databaseURL: process.env.MONGODB_URI,
|
|
||||||
jwtSecret: process.env.JWT_SECRET,
|
|
||||||
jwtAlgorithm: process.env.JWT_ALGO,
|
|
||||||
options: {
|
|
||||||
swaggerDefinition: {
|
|
||||||
info: {
|
|
||||||
description: 'CURD-TS专用接口',
|
|
||||||
title: 'Swagger',
|
|
||||||
version: require('../../package.json').version
|
|
||||||
},
|
|
||||||
host: `localhost:${parseInt(process.env.PORT, 10)}`,
|
|
||||||
basePath: '/',
|
|
||||||
produces: ['application/json', 'application/xml'],
|
|
||||||
schemes: ['http', 'https'],
|
|
||||||
securityDefinitions: {
|
|
||||||
JWT: {
|
|
||||||
type: 'apiKey',
|
|
||||||
in: 'header',
|
|
||||||
name: 'Authorization',
|
|
||||||
description: 'Bearer Authorization'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
route: {
|
|
||||||
url: './swagger-ui.html',
|
|
||||||
docs: '/swagger.json' //swagger文件 api
|
|
||||||
},
|
|
||||||
basedir: __dirname, //app absolute path
|
|
||||||
files: ['../router/api/*.ts'] //Path to the API handle folder
|
|
||||||
},
|
|
||||||
logs: {
|
|
||||||
level: process.env.LOG_LEVEL || 'silly',
|
|
||||||
},
|
|
||||||
agenda: {
|
|
||||||
dbCollection: process.env.AGENDA_DB_COLLECTION,
|
|
||||||
pooltime: process.env.AGENDA_POOL_TIME,
|
|
||||||
concurrency: parseInt(process.env.AGENDA_CONCURRENCY, 10),
|
|
||||||
},
|
|
||||||
mysql: {
|
|
||||||
host: 'localhost',
|
|
||||||
charset: 'utf8_general_ci',
|
|
||||||
user: 'root',
|
|
||||||
password: '123456789'
|
|
||||||
},
|
|
||||||
mongodb: {},
|
|
||||||
sqlite: {},
|
|
||||||
api: {
|
|
||||||
prefix: '/api',
|
|
||||||
},
|
|
||||||
emails: {
|
|
||||||
apiKey: process.env.MAILGUN_API_KEY,
|
|
||||||
domain: process.env.MAILGUN_DOMAIN
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
import config from "../config"
|
|
||||||
import * as winston from "winston"
|
|
||||||
|
|
||||||
const transports = []
|
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
|
||||||
transports.push(
|
|
||||||
new winston.transports.Console()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
transports.push(
|
|
||||||
new winston.transports.Console({
|
|
||||||
format: winston.format.combine(
|
|
||||||
winston.format.cli(),
|
|
||||||
winston.format.splat(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoggerInstance = winston.createLogger({
|
|
||||||
level: config.logs.level,
|
|
||||||
levels: winston.config.npm.levels,
|
|
||||||
format: winston.format.combine(
|
|
||||||
winston.format.timestamp({
|
|
||||||
format: 'YYYY-MM-DD HH:mm:ss'
|
|
||||||
}),
|
|
||||||
winston.format.errors({ stack: true }),
|
|
||||||
winston.format.splat(),
|
|
||||||
winston.format.json()
|
|
||||||
),
|
|
||||||
transports
|
|
||||||
})
|
|
||||||
|
|
||||||
export default LoggerInstance
|
|
@ -1,6 +0,0 @@
|
|||||||
// 创建用户表
|
|
||||||
const user = 'CREATE TABLE if not EXISTS users(id int PRIMARY key auto_increment,username varchar(32),password varchar(32),time DATETIME)'
|
|
||||||
|
|
||||||
export {
|
|
||||||
user
|
|
||||||
}
|
|
@ -1,347 +0,0 @@
|
|||||||
import * as mysql from "mysql2"
|
|
||||||
import secret from "../../config"
|
|
||||||
import * as jwt from "jsonwebtoken"
|
|
||||||
import { createHash } from "crypto"
|
|
||||||
import Logger from "../../loaders/logger"
|
|
||||||
import { Request, Response } from "express"
|
|
||||||
import { createMathExpr } from "svg-captcha"
|
|
||||||
import getFormatDate from "../../utils/date"
|
|
||||||
import { Code, Info } from "../../utils/infoEnum"
|
|
||||||
import { connection } from "../../utils/initMysql"
|
|
||||||
|
|
||||||
export interface dataModel {
|
|
||||||
length: number
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存验证码
|
|
||||||
let generateVerify: number
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Error
|
|
||||||
* @property {string} code.required
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Response
|
|
||||||
* @property {[integer]} code
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Login
|
|
||||||
* @property {string} username.required - 用户名 - eg: admin
|
|
||||||
* @property {string} password.required - 密码 - eg: 123456
|
|
||||||
* @property {integer} verify.required - 验证码
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route POST /login
|
|
||||||
* @param {Login.model} point.body.required - the new point
|
|
||||||
* @produces application/json application/xml
|
|
||||||
* @consumes application/json application/xml
|
|
||||||
* @summary 登录
|
|
||||||
* @group 用户登录、注册相关
|
|
||||||
* @returns {Response.model} 200
|
|
||||||
* @returns {Array.<Login>} Login
|
|
||||||
* @headers {integer} 200.X-Rate-Limit
|
|
||||||
* @headers {string} 200.X-Expires-After
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const login = async (req: Request, res: Response) => {
|
|
||||||
const { username, password, verify } = req.body
|
|
||||||
if (generateVerify !== verify) return res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[0]
|
|
||||||
})
|
|
||||||
let sql: string = 'select * from users where username=' + "'" + username + "'"
|
|
||||||
connection.query(sql, async function (err, data: dataModel) {
|
|
||||||
if (data.length == 0) {
|
|
||||||
await res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[1]
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
if (createHash('md5').update(password).digest('hex') == data[0].password) {
|
|
||||||
const accessToken = jwt.sign({
|
|
||||||
accountId: data[0].id
|
|
||||||
}, secret.jwtSecret, { expiresIn: 3600 })
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: Info[2],
|
|
||||||
accessToken
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[3]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Register
|
|
||||||
* @property {string} username.required - 用户名 - eg: admin
|
|
||||||
* @property {string} password.required - 密码 - eg: 123456
|
|
||||||
* @property {integer} verify.required - 验证码
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route POST /register
|
|
||||||
* @param {Register.model} point.body.required - the new point
|
|
||||||
* @produces application/json application/xml
|
|
||||||
* @consumes application/json application/xml
|
|
||||||
* @summary 注册
|
|
||||||
* @group 用户登录、注册相关
|
|
||||||
* @returns {Response.model} 200
|
|
||||||
* @returns {Array.<Register>} Register
|
|
||||||
* @headers {integer} 200.X-Rate-Limit
|
|
||||||
* @headers {string} 200.X-Expires-After
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const register = async (req: Request, res: Response) => {
|
|
||||||
const { username, password, verify } = req.body
|
|
||||||
if (generateVerify !== verify) return res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[0]
|
|
||||||
})
|
|
||||||
if (password.length < 6) return res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[4]
|
|
||||||
})
|
|
||||||
let sql: string = 'select * from users where username=' + "'" + username + "'"
|
|
||||||
connection.query(sql, async (err, data: dataModel) => {
|
|
||||||
if (data.length > 0) {
|
|
||||||
await res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[5]
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let time = await getFormatDate()
|
|
||||||
let sql: string = 'insert into users (username,password,time) value(' + "'" + username + "'" + ',' + "'" + createHash('md5').update(password).digest('hex') +
|
|
||||||
"'" + ',' + "'" + time + "'" + ')'
|
|
||||||
connection.query(sql, async function (err) {
|
|
||||||
if (err) {
|
|
||||||
Logger.error(err)
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: Info[6]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef UpdateList
|
|
||||||
* @property {string} username.required - 用户名 - eg: admin
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route PUT /updateList/{id}
|
|
||||||
* @summary 列表更新
|
|
||||||
* @param {UpdateList.model} point.body.required - 用户名
|
|
||||||
* @param {UpdateList.model} id.path.required - 用户id
|
|
||||||
* @group 用户管理相关
|
|
||||||
* @returns {object} 200
|
|
||||||
* @returns {Array.<UpdateList>} UpdateList
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const updateList = async (req: Request, res: Response) => {
|
|
||||||
const { id } = req.params
|
|
||||||
const { username } = req.body
|
|
||||||
let payload = null
|
|
||||||
try {
|
|
||||||
const authorizationHeader = req.get("Authorization")
|
|
||||||
const accessToken = authorizationHeader.substr("Bearer ".length)
|
|
||||||
payload = jwt.verify(accessToken, secret.jwtSecret)
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(401).end()
|
|
||||||
}
|
|
||||||
let modifySql: string = 'UPDATE users SET username = ? WHERE id = ?'
|
|
||||||
let sql: string = 'select * from users where id=' + id
|
|
||||||
connection.query(sql, function (err, data) {
|
|
||||||
connection.query(sql, function (err) {
|
|
||||||
if (err) {
|
|
||||||
Logger.error(err)
|
|
||||||
} else {
|
|
||||||
let modifyParams: string[] = [username, id]
|
|
||||||
// 改
|
|
||||||
connection.query(modifySql, modifyParams, async function (err, result) {
|
|
||||||
if (err) {
|
|
||||||
Logger.error(err)
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: Info[7]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef DeleteList
|
|
||||||
* @property {integer} id.required - 当前id
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route DELETE /deleteList/{id}
|
|
||||||
* @summary 列表删除
|
|
||||||
* @param {DeleteList.model} id.path.required - 用户id
|
|
||||||
* @group 用户管理相关
|
|
||||||
* @returns {object} 200
|
|
||||||
* @returns {Array.<DeleteList>} DeleteList
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const deleteList = async (req: Request, res: Response) => {
|
|
||||||
const { id } = req.params
|
|
||||||
let payload = null
|
|
||||||
try {
|
|
||||||
const authorizationHeader = req.get("Authorization")
|
|
||||||
const accessToken = authorizationHeader.substr("Bearer ".length)
|
|
||||||
payload = jwt.verify(accessToken, secret.jwtSecret)
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(401).end()
|
|
||||||
}
|
|
||||||
let sql: string = 'DELETE FROM users where id=' + "'" + id + "'"
|
|
||||||
connection.query(sql, async function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err)
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: Info[8]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef SearchPage
|
|
||||||
* @property {integer} page.required - 第几页 - eg: 1
|
|
||||||
* @property {integer} size.required - 数据量(条)- eg: 5
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route POST /searchPage
|
|
||||||
* @param {SearchPage.model} point.body.required - the new point
|
|
||||||
* @produces application/json application/xml
|
|
||||||
* @consumes application/json application/xml
|
|
||||||
* @summary 分页查询
|
|
||||||
* @group 用户管理相关
|
|
||||||
* @returns {Response.model} 200
|
|
||||||
* @returns {Array.<SearchPage>} SearchPage
|
|
||||||
* @headers {integer} 200.X-Rate-Limit
|
|
||||||
* @headers {string} 200.X-Expires-After
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const searchPage = async (req: Request, res: Response) => {
|
|
||||||
const { page, size } = req.body
|
|
||||||
let payload = null
|
|
||||||
try {
|
|
||||||
const authorizationHeader = req.get("Authorization")
|
|
||||||
const accessToken = authorizationHeader.substr("Bearer ".length)
|
|
||||||
payload = jwt.verify(accessToken, secret.jwtSecret)
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(401).end()
|
|
||||||
}
|
|
||||||
let sql: string = 'select * from users limit ' + size + ' offset ' + size * (page - 1)
|
|
||||||
connection.query(sql, async function (err, data) {
|
|
||||||
if (err) {
|
|
||||||
Logger.error(err)
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef SearchVague
|
|
||||||
* @property {string} username.required - 用户名 - eg: admin
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route POST /searchVague
|
|
||||||
* @param {SearchVague.model} point.body.required - the new point
|
|
||||||
* @produces application/json application/xml
|
|
||||||
* @consumes application/json application/xml
|
|
||||||
* @summary 模糊查询
|
|
||||||
* @group 用户管理相关
|
|
||||||
* @returns {Response.model} 200
|
|
||||||
* @returns {Array.<SearchVague>} SearchVague
|
|
||||||
* @headers {integer} 200.X-Rate-Limit
|
|
||||||
* @headers {string} 200.X-Expires-After
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const searchVague = async (req: Request, res: Response) => {
|
|
||||||
const { username } = req.body
|
|
||||||
let payload = null
|
|
||||||
try {
|
|
||||||
const authorizationHeader = req.get("Authorization")
|
|
||||||
const accessToken = authorizationHeader.substr("Bearer ".length)
|
|
||||||
payload = jwt.verify(accessToken, secret.jwtSecret)
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(401).end()
|
|
||||||
}
|
|
||||||
if (username === "" || username === null) return res.json({
|
|
||||||
code: Code.failCode,
|
|
||||||
info: Info[9]
|
|
||||||
})
|
|
||||||
let sql: string = 'select * from users'
|
|
||||||
sql += " WHERE username LIKE " + mysql.escape("%" + username + "%")
|
|
||||||
connection.query(sql, function (err, data) {
|
|
||||||
connection.query(sql, async function (err) {
|
|
||||||
if (err) {
|
|
||||||
Logger.error(err)
|
|
||||||
} else {
|
|
||||||
await res.json({
|
|
||||||
code: Code.successCode,
|
|
||||||
info: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @route GET /captcha
|
|
||||||
* @summary 图形验证码
|
|
||||||
* @group captcha - 图形验证码
|
|
||||||
* @returns {object} 200
|
|
||||||
* @security JWT
|
|
||||||
*/
|
|
||||||
|
|
||||||
const captcha = async (req: Request, res: Response) => {
|
|
||||||
const create = createMathExpr({
|
|
||||||
mathMin: 1,
|
|
||||||
mathMax: 4,
|
|
||||||
mathOperator: "+"
|
|
||||||
})
|
|
||||||
generateVerify = Number(create.text)
|
|
||||||
res.type('svg') // 响应的类型
|
|
||||||
res.json({ code: Code.successCode, info: create.text, svg: create.data })
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
login,
|
|
||||||
register,
|
|
||||||
updateList,
|
|
||||||
deleteList,
|
|
||||||
searchPage,
|
|
||||||
searchVague,
|
|
||||||
captcha,
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
import app from "./app"
|
|
||||||
import * as open from "open"
|
|
||||||
import config from "./config"
|
|
||||||
import { user } from "./models/mysql"
|
|
||||||
import Logger from "./loaders/logger"
|
|
||||||
import { queryTable } from "./utils/initMysql"
|
|
||||||
const expressSwagger = require("express-swagger-generator")(app)
|
|
||||||
expressSwagger(config.options)
|
|
||||||
|
|
||||||
queryTable(user)
|
|
||||||
|
|
||||||
import {
|
|
||||||
login,
|
|
||||||
register,
|
|
||||||
updateList,
|
|
||||||
deleteList,
|
|
||||||
searchPage,
|
|
||||||
searchVague,
|
|
||||||
captcha,
|
|
||||||
} from "./router/api/mysql"
|
|
||||||
|
|
||||||
app.post('/login', (req, res) => {
|
|
||||||
login(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/register', (req, res) => {
|
|
||||||
register(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.put('/updateList/:id', (req, res) => {
|
|
||||||
updateList(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.delete('/deleteList/:id', (req, res) => {
|
|
||||||
deleteList(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/searchPage', (req, res) => {
|
|
||||||
searchPage(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/searchVague', (req, res) => {
|
|
||||||
searchVague(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.get('/captcha', (req, res) => {
|
|
||||||
captcha(req, res)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.listen(config.port, () => {
|
|
||||||
Logger.info(`
|
|
||||||
################################################
|
|
||||||
🛡️ Swagger文档地址: http://localhost:${config.port} 🛡️
|
|
||||||
################################################
|
|
||||||
`)
|
|
||||||
}).on('error', err => {
|
|
||||||
Logger.error(err)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
open(`http://localhost:${config.port}`) // 自动打开默认浏览器
|
|
@ -1,23 +0,0 @@
|
|||||||
interface dateModel {
|
|
||||||
getMonth: () => any
|
|
||||||
getDate: () => string | number
|
|
||||||
getFullYear: () => string | number
|
|
||||||
getHours: () => string | number
|
|
||||||
getMinutes: () => string | number
|
|
||||||
getSeconds: () => string | number
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function getFormatDate(): Promise<Date | string> {
|
|
||||||
let date: dateModel = new Date()
|
|
||||||
let month: string | number = date.getMonth() + 1
|
|
||||||
let strDate = date.getDate()
|
|
||||||
if (month >= 1 && month <= 9) {
|
|
||||||
month = "0" + month
|
|
||||||
}
|
|
||||||
if (strDate >= 0 && strDate <= 9) {
|
|
||||||
strDate = "0" + strDate
|
|
||||||
}
|
|
||||||
let currentDate = date.getFullYear() + "-" + month + "-" + strDate +
|
|
||||||
" " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds()
|
|
||||||
return currentDate
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
// 状态码
|
|
||||||
export const enum Code {
|
|
||||||
failCode = -1,
|
|
||||||
successCode = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回信息
|
|
||||||
export enum Info {
|
|
||||||
"请输入正确的验证码",
|
|
||||||
"账号尚未被注册",
|
|
||||||
"登录成功",
|
|
||||||
"密码错误",
|
|
||||||
"密码长度不能小于6位",
|
|
||||||
"账号已被注册",
|
|
||||||
"账号注册成功",
|
|
||||||
"修改成功",
|
|
||||||
"删除成功",
|
|
||||||
"搜索信息不能为空",
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import * as mysql from "mysql2"
|
|
||||||
import mysqlConfig from "../config"
|
|
||||||
import Logger from "../loaders/logger"
|
|
||||||
|
|
||||||
//user数据库
|
|
||||||
export const connection = mysql.createConnection(Object.assign({ database: 'user' }, mysqlConfig.mysql))
|
|
||||||
|
|
||||||
export function queryTable(s: string): void {
|
|
||||||
connection.query(s, (err) => {
|
|
||||||
err ? Logger.error(err) : Logger.info(`${s}表创建成功`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"pretty": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"target": "es6",
|
|
||||||
"outDir": "./dist",
|
|
||||||
"baseUrl": "./lib"
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts", "src/router/api/user.js"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"defaultSeverity": "error",
|
|
||||||
"extends": [
|
|
||||||
"tslint:recommended"
|
|
||||||
],
|
|
||||||
"jsRules": {},
|
|
||||||
"rules": {
|
|
||||||
"interface-name": [
|
|
||||||
true,
|
|
||||||
"never-prefix"
|
|
||||||
],
|
|
||||||
"no-console": [
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"semicolon": [
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"quotemark": [
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"object-literal-sor t-keys": [
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"max-classes-per-file": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rulesDirectory": []
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
# simplicity
|
|
||||||
|
|
||||||
简约而不简单的文档
|
|
||||||
|
|
||||||
## 安装依赖
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
## 文档启动
|
|
||||||
```
|
|
||||||
npm run docs
|
|
||||||
```
|
|
||||||
|
|
||||||
## 文档打包
|
|
||||||
```
|
|
||||||
npm run docs:build
|
|
||||||
```
|
|
||||||
打包后会在.vitepress文件夹下生成dist目录
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "simplicity",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "简约而不简单的文档",
|
|
||||||
"author": "和尚",
|
|
||||||
"license": "ISC",
|
|
||||||
"scripts": {
|
|
||||||
"docs": "vitepress dev docs",
|
|
||||||
"docs:build": "vitepress build docs"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"vitepress": "^0.7.4"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 541 KiB |
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 243 KiB |
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 252 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 541 KiB |
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 243 KiB |
BIN
docs/zh/plugs/images/snip.gif
Normal file
After Width: | Height: | Size: 252 KiB |
BIN
frontend/.DS_Store
vendored
@ -1,17 +0,0 @@
|
|||||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
|
||||||
# For additional information regarding the format and rule options, please see:
|
|
||||||
# https://github.com/browserslist/browserslist#queries
|
|
||||||
|
|
||||||
# For the full list of supported browsers by the Angular framework, please see:
|
|
||||||
# https://angular.io/guide/browser-support
|
|
||||||
|
|
||||||
# You can see what browsers were selected by your queries by running:
|
|
||||||
# npx browserslist
|
|
||||||
|
|
||||||
last 1 Chrome version
|
|
||||||
last 1 Firefox version
|
|
||||||
last 2 Edge major versions
|
|
||||||
last 2 Safari major versions
|
|
||||||
last 2 iOS major versions
|
|
||||||
Firefox ESR
|
|
||||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
|
@ -1,16 +0,0 @@
|
|||||||
# Editor configuration, see https://editorconfig.org
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.ts]
|
|
||||||
quote_type = single
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
max_line_length = off
|
|
||||||
trim_trailing_whitespace = false
|
|
46
frontend/angular-ts/.gitignore
vendored
@ -1,46 +0,0 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# compiled output
|
|
||||||
/dist
|
|
||||||
/tmp
|
|
||||||
/out-tsc
|
|
||||||
# Only exists if Bazel was run
|
|
||||||
/bazel-out
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# profiling files
|
|
||||||
chrome-profiler-events*.json
|
|
||||||
speed-measure-plugin*.json
|
|
||||||
|
|
||||||
# IDEs and editors
|
|
||||||
/.idea
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.c9/
|
|
||||||
*.launch
|
|
||||||
.settings/
|
|
||||||
*.sublime-workspace
|
|
||||||
|
|
||||||
# IDE - VSCode
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.history/*
|
|
||||||
|
|
||||||
# misc
|
|
||||||
/.sass-cache
|
|
||||||
/connect.lock
|
|
||||||
/coverage
|
|
||||||
/libpeerconnection.log
|
|
||||||
npm-debug.log
|
|
||||||
yarn-error.log
|
|
||||||
testem.log
|
|
||||||
/typings
|
|
||||||
|
|
||||||
# System Files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
@ -1 +0,0 @@
|
|||||||
# angular-ts
|
|
@ -1,140 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
||||||
"version": 1,
|
|
||||||
"newProjectRoot": "projects",
|
|
||||||
"projects": {
|
|
||||||
"angular-ts": {
|
|
||||||
"projectType": "application",
|
|
||||||
"schematics": {
|
|
||||||
"@schematics/angular:component": {
|
|
||||||
"style": "scss"
|
|
||||||
},
|
|
||||||
"@schematics/angular:application": {
|
|
||||||
"strict": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "",
|
|
||||||
"sourceRoot": "src",
|
|
||||||
"prefix": "app",
|
|
||||||
"architect": {
|
|
||||||
"build": {
|
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
|
||||||
"options": {
|
|
||||||
"outputPath": "dist/angular-ts",
|
|
||||||
"index": "src/index.html",
|
|
||||||
"main": "src/main.ts",
|
|
||||||
"polyfills": "src/polyfills.ts",
|
|
||||||
"tsConfig": "tsconfig.app.json",
|
|
||||||
"aot": true,
|
|
||||||
"assets": [
|
|
||||||
"src/favicon.ico",
|
|
||||||
"src/assets"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"src/styles.scss",
|
|
||||||
"node_modules/leaflet/dist/leaflet.css"
|
|
||||||
],
|
|
||||||
"scripts": [
|
|
||||||
"node_modules/leaflet/dist/leaflet.js"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"fileReplacements": [
|
|
||||||
{
|
|
||||||
"replace": "src/environments/environment.ts",
|
|
||||||
"with": "src/environments/environment.prod.ts"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"optimization": true,
|
|
||||||
"outputHashing": "all",
|
|
||||||
"sourceMap": false,
|
|
||||||
"namedChunks": false,
|
|
||||||
"extractLicenses": true,
|
|
||||||
"vendorChunk": false,
|
|
||||||
"buildOptimizer": true,
|
|
||||||
"budgets": [
|
|
||||||
{
|
|
||||||
"type": "initial",
|
|
||||||
"maximumWarning": "500kb",
|
|
||||||
"maximumError": "1mb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "anyComponentStyle",
|
|
||||||
"maximumWarning": "2kb",
|
|
||||||
"maximumError": "4kb"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"serve": {
|
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
|
||||||
"options": {
|
|
||||||
"browserTarget": "angular-ts:build"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"browserTarget": "angular-ts:build:production"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extract-i18n": {
|
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
|
||||||
"options": {
|
|
||||||
"browserTarget": "angular-ts:build"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
|
||||||
"options": {
|
|
||||||
"main": "src/test.ts",
|
|
||||||
"polyfills": "src/polyfills.ts",
|
|
||||||
"tsConfig": "tsconfig.spec.json",
|
|
||||||
"karmaConfig": "karma.conf.js",
|
|
||||||
"assets": [
|
|
||||||
"src/favicon.ico",
|
|
||||||
"src/assets"
|
|
||||||
],
|
|
||||||
"styles": [
|
|
||||||
"src/styles.scss",
|
|
||||||
"node_modules/leaflet/dist/leaflet.css"
|
|
||||||
],
|
|
||||||
"scripts": [
|
|
||||||
"node_modules/leaflet/dist/leaflet.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint": {
|
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
|
||||||
"options": {
|
|
||||||
"tsConfig": [
|
|
||||||
"tsconfig.app.json",
|
|
||||||
"tsconfig.spec.json",
|
|
||||||
"e2e/tsconfig.json"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"**/node_modules/**"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"e2e": {
|
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
|
||||||
"options": {
|
|
||||||
"protractorConfig": "e2e/protractor.conf.js",
|
|
||||||
"devServerTarget": "angular-ts:serve"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"devServerTarget": "angular-ts:serve:production"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultProject": "angular-ts",
|
|
||||||
"cli": {
|
|
||||||
"analytics": "71d974d8-5195-475b-868c-8de76159c8c1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
// Protractor configuration file, see link for more information
|
|
||||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
|
||||||
|
|
||||||
const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type { import("protractor").Config }
|
|
||||||
*/
|
|
||||||
exports.config = {
|
|
||||||
allScriptsTimeout: 11000,
|
|
||||||
specs: [
|
|
||||||
'./src/**/*.e2e-spec.ts'
|
|
||||||
],
|
|
||||||
capabilities: {
|
|
||||||
browserName: 'chrome'
|
|
||||||
},
|
|
||||||
directConnect: true,
|
|
||||||
SELENIUM_PROMISE_MANAGER: false,
|
|
||||||
baseUrl: 'http://localhost:4200/',
|
|
||||||
framework: 'jasmine',
|
|
||||||
jasmineNodeOpts: {
|
|
||||||
showColors: true,
|
|
||||||
defaultTimeoutInterval: 30000,
|
|
||||||
print: function() {}
|
|
||||||
},
|
|
||||||
onPrepare() {
|
|
||||||
require('ts-node').register({
|
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
|
||||||
});
|
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({
|
|
||||||
spec: {
|
|
||||||
displayStacktrace: StacktraceOption.PRETTY
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,23 +0,0 @@
|
|||||||
import { AppPage } from './app.po';
|
|
||||||
import { browser, logging } from 'protractor';
|
|
||||||
|
|
||||||
describe('workspace-project App', () => {
|
|
||||||
let page: AppPage;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
page = new AppPage();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display welcome message', async () => {
|
|
||||||
await page.navigateTo();
|
|
||||||
expect(await page.getTitleText()).toEqual('angular-ts app is running!');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
// Assert that there are no errors emitted from the browser
|
|
||||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
|
||||||
expect(logs).not.toContain(jasmine.objectContaining({
|
|
||||||
level: logging.Level.SEVERE,
|
|
||||||
} as logging.Entry));
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,11 +0,0 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
|
||||||
|
|
||||||
export class AppPage {
|
|
||||||
async navigateTo(): Promise<unknown> {
|
|
||||||
return browser.get(browser.baseUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTitleText(): Promise<string> {
|
|
||||||
return element(by.css('app-root .content span')).getText();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
|
||||||
"extends": "../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "../out-tsc/e2e",
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es2018",
|
|
||||||
"types": [
|
|
||||||
"jasmine",
|
|
||||||
"node"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
// Karma configuration file, see link for more information
|
|
||||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
|
||||||
|
|
||||||
module.exports = function (config) {
|
|
||||||
config.set({
|
|
||||||
basePath: '',
|
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
|
||||||
plugins: [
|
|
||||||
require('karma-jasmine'),
|
|
||||||
require('karma-chrome-launcher'),
|
|
||||||
require('karma-jasmine-html-reporter'),
|
|
||||||
require('karma-coverage'),
|
|
||||||
require('@angular-devkit/build-angular/plugins/karma')
|
|
||||||
],
|
|
||||||
client: {
|
|
||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
|
||||||
},
|
|
||||||
coverageReporter: {
|
|
||||||
dir: require('path').join(__dirname, './coverage/angular-ts'),
|
|
||||||
subdir: '.',
|
|
||||||
reporters: [
|
|
||||||
{ type: 'html' },
|
|
||||||
{ type: 'text-summary' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
reporters: ['progress', 'kjhtml'],
|
|
||||||
port: 9876,
|
|
||||||
colors: true,
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
autoWatch: true,
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
singleRun: false,
|
|
||||||
restartOnFileChange: true
|
|
||||||
});
|
|
||||||
};
|
|
16044
frontend/angular-ts/package-lock.json
generated
@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "angular-ts",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"scripts": {
|
|
||||||
"ng": "ng",
|
|
||||||
"start": "ng serve --host=0.0.0.0",
|
|
||||||
"build": "ng build",
|
|
||||||
"test": "ng test",
|
|
||||||
"lint": "ng lint",
|
|
||||||
"e2e": "ng e2e"
|
|
||||||
},
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@angular/animations": "~11.0.0",
|
|
||||||
"@angular/common": "~11.0.0",
|
|
||||||
"@angular/compiler": "~11.0.0",
|
|
||||||
"@angular/core": "~11.0.0",
|
|
||||||
"@angular/forms": "~11.0.0",
|
|
||||||
"@angular/platform-browser": "~11.0.0",
|
|
||||||
"@angular/platform-browser-dynamic": "~11.0.0",
|
|
||||||
"@angular/router": "~11.0.0",
|
|
||||||
"@supermap/iclient-leaflet": "^10.1.1",
|
|
||||||
"html2canvas": "^1.0.0-rc.7",
|
|
||||||
"leaflet": "^1.7.1",
|
|
||||||
"localforage": "^1.5.0",
|
|
||||||
"lodash": "^4.17.20",
|
|
||||||
"moment": "^2.29.1",
|
|
||||||
"ngforage": "^6.0.0",
|
|
||||||
"rxjs": "~6.6.0",
|
|
||||||
"tsickle": "^0.39.1",
|
|
||||||
"tslib": "^2.0.0",
|
|
||||||
"zone.js": "~0.10.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@angular-devkit/build-angular": "~0.1100.1",
|
|
||||||
"@angular/cli": "~11.0.1",
|
|
||||||
"@angular/compiler-cli": "~11.0.0",
|
|
||||||
"@types/jasmine": "~3.6.0",
|
|
||||||
"@types/node": "^12.11.1",
|
|
||||||
"codelyzer": "^6.0.0",
|
|
||||||
"jasmine-core": "~3.6.0",
|
|
||||||
"jasmine-spec-reporter": "~5.0.0",
|
|
||||||
"karma": "~5.1.0",
|
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
|
||||||
"karma-coverage": "~2.0.3",
|
|
||||||
"karma-jasmine": "~4.0.0",
|
|
||||||
"karma-jasmine-html-reporter": "^1.5.0",
|
|
||||||
"ng-packagr": "^11.1.2",
|
|
||||||
"protractor": "~7.0.0",
|
|
||||||
"ts-node": "~8.3.0",
|
|
||||||
"tslint": "~6.1.0",
|
|
||||||
"typescript": "~4.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"/api": {
|
|
||||||
"target": "http://192.168.15.213:3000/",
|
|
||||||
"secure": false,
|
|
||||||
"pathRewrite": {
|
|
||||||
"^/api": ""
|
|
||||||
},
|
|
||||||
"changeOrigin": true,
|
|
||||||
"logLevel": "debug"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
<p>err404 works!</p>
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-err404',
|
|
||||||
templateUrl: './err404.component.html',
|
|
||||||
styleUrls: ['./err404.component.scss']
|
|
||||||
})
|
|
||||||
export class Err404Component implements OnInit {
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { Err404Component } from './err404.component';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [Err404Component],
|
|
||||||
imports: [
|
|
||||||
CommonModule
|
|
||||||
],
|
|
||||||
exports: [Err404Component]
|
|
||||||
})
|
|
||||||
export class Err404Module { }
|
|
@ -1 +0,0 @@
|
|||||||
export * from './error/err404/err404.module';
|
|
@ -1,13 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
|
|
||||||
import { DisabledDirective } from './disabled.directive';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [DisabledDirective],
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
],
|
|
||||||
exports: [DisabledDirective]
|
|
||||||
})
|
|
||||||
export class DirectivesModule { }
|
|
@ -1,19 +0,0 @@
|
|||||||
import { Directive, Input } from '@angular/core';
|
|
||||||
import { NgControl } from '@angular/forms';
|
|
||||||
|
|
||||||
@Directive({
|
|
||||||
selector: '[appDisabled]',
|
|
||||||
})
|
|
||||||
export class DisabledDirective {
|
|
||||||
|
|
||||||
@Input('appDisabled') set disabledDirective(condition: boolean) {
|
|
||||||
const action = condition ? 'enable' : 'disable';
|
|
||||||
setTimeout(() => this.ngControl.control[action](), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private ngControl: NgControl,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class SimpleReuseStrategy implements RouteReuseStrategy {
|
|
||||||
|
|
||||||
public static handlers: { [key: string]: DetachedRouteHandle } = {};
|
|
||||||
|
|
||||||
private static waitDelete: string;
|
|
||||||
|
|
||||||
/** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */
|
|
||||||
public shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
|
||||||
console.debug('===shouldDetach-route', route);
|
|
||||||
if (route.data.isPage) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */
|
|
||||||
public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
|
|
||||||
console.debug('===store-route', route, 'store-handle', handle);
|
|
||||||
SimpleReuseStrategy.handlers[this.getRouteUrl(route)] = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 若 path 在缓存中有的都认为允许还原路由 */
|
|
||||||
public shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
|
||||||
console.debug('===shouldAttach-route', route);
|
|
||||||
return !!SimpleReuseStrategy.handlers[this.getRouteUrl(route)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 从缓存中获取快照,若无则返回null */
|
|
||||||
public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
|
|
||||||
console.debug('===retrieve-route', route);
|
|
||||||
if (!route.routeConfig) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SimpleReuseStrategy.handlers[this.getRouteUrl(route)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 进入路由触发,判断是否同一路由 */
|
|
||||||
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
|
||||||
console.debug('===shouldReuseRoute-future', future, 'shouldReuseRoute-cur', curr);
|
|
||||||
return future.routeConfig === curr.routeConfig &&
|
|
||||||
JSON.stringify(future.params) == JSON.stringify(curr.params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getRouteUrl(route: ActivatedRouteSnapshot) {
|
|
||||||
var path = route['_routerState'].url.replace(/\//g, '_');
|
|
||||||
console.debug('---getRouteUrl-path', path);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static deleteRouteSnapshot(name: string): void {
|
|
||||||
if (SimpleReuseStrategy.handlers[name]) {
|
|
||||||
delete SimpleReuseStrategy.handlers[name];
|
|
||||||
} else {
|
|
||||||
SimpleReuseStrategy.waitDelete = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { HttpClient } from '@angular/common/http';
|
|
||||||
|
|
||||||
import { Observable, Subject } from 'rxjs';
|
|
||||||
import { NgForage } from 'ngforage';
|
|
||||||
import { HttpRequest } from './http-request';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class HttpRequestService extends HttpRequest{
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private http: HttpClient,
|
|
||||||
private ngforage: NgForage
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
get(url: string): Observable<any> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
post(url: string): Observable<any> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
put(url: string): Observable<any> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
delete(url: string): Observable<any> {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
authDelete(url: string): Observable<any> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
authGet(url: string): Observable<any> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
authPost(url: string): Observable<any> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
authPut(url: string): Observable<any> {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
export abstract class HttpRequest {
|
|
||||||
constructor() {}
|
|
||||||
abstract get(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract post(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract put(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract delete(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract authGet(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract authPost(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract authPut(url: string): Observable<any>;
|
|
||||||
|
|
||||||
abstract authDelete(url: string): Observable<any>;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { PreloadingStrategy, Route } from '@angular/router';
|
|
||||||
import { Observable, of } from 'rxjs';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class SelectivePreloadingStrategyService implements PreloadingStrategy {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
preload(route: Route, load: () => Observable<any>): Observable<any> {
|
|
||||||
if (route.data && route.data?.preload) {
|
|
||||||
return load();
|
|
||||||
} else {
|
|
||||||
return of(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
|
||||||
|
|
||||||
import { SelectivePreloadingStrategyService } from '../CX/services/selective-preloading-strategy.service';
|
|
||||||
import { AuthGuard } from './auth.guard';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
pathMatch: 'full',
|
|
||||||
redirectTo: 'page',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'page',
|
|
||||||
canActivate: [AuthGuard],
|
|
||||||
loadChildren: () => import('./pages/pages.module').then(m => m.PagesModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'login',
|
|
||||||
canActivate: [AuthGuard],
|
|
||||||
loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
RouterModule.forRoot(
|
|
||||||
routes,
|
|
||||||
{
|
|
||||||
useHash: true,
|
|
||||||
preloadingStrategy: SelectivePreloadingStrategyService
|
|
||||||
}
|
|
||||||
)],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
|
||||||
export class AppRoutingModule { }
|
|
@ -1 +0,0 @@
|
|||||||
<router-outlet></router-outlet>
|
|
@ -1,35 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [
|
|
||||||
RouterTestingModule
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create the app', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should have as title 'angular-ts'`, () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app.title).toEqual('angular-ts');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render title', () => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.nativeElement;
|
|
||||||
expect(compiled.querySelector('.content span').textContent).toContain('angular-ts app is running!');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { NgForage } from 'ngforage';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.scss']
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
title = 'angular-ts';
|
|
||||||
constructor(
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { RouteReuseStrategy } from '@angular/router';
|
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { HttpClientJsonpModule, HttpClientModule } from '@angular/common/http';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
import { SimpleReuseStrategy } from '../CX/services/SimpleReuseStrategy';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [
|
|
||||||
AppComponent
|
|
||||||
],
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
AppRoutingModule,
|
|
||||||
HttpClientModule,
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
HttpClientJsonpModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
FormsModule,
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: RouteReuseStrategy,
|
|
||||||
useClass: SimpleReuseStrategy
|
|
||||||
}
|
|
||||||
],
|
|
||||||
bootstrap: [AppComponent]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,68 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import {
|
|
||||||
CanActivate,
|
|
||||||
CanActivateChild,
|
|
||||||
CanDeactivate,
|
|
||||||
CanLoad,
|
|
||||||
Route,
|
|
||||||
UrlSegment,
|
|
||||||
ActivatedRouteSnapshot,
|
|
||||||
RouterStateSnapshot,
|
|
||||||
UrlTree,
|
|
||||||
Router,
|
|
||||||
Resolve
|
|
||||||
} from '@angular/router';
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { NgForage } from 'ngforage';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class AuthGuard implements CanActivate, CanActivateChild, CanDeactivate<unknown>, CanLoad, Resolve<any> {
|
|
||||||
constructor(
|
|
||||||
private ngForage: NgForage,
|
|
||||||
private router: Router
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
canActivate(
|
|
||||||
route: ActivatedRouteSnapshot,
|
|
||||||
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
|
||||||
this.ngForage.getItem('TOKEN').then(res => {
|
|
||||||
if (!!!res) {
|
|
||||||
this.router.navigate(['login']);
|
|
||||||
this.ngForage.setItem('TOKEN', 'aaaa74654sdf4as6d4');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log(route);
|
|
||||||
console.log(state);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
canActivateChild(
|
|
||||||
childRoute: ActivatedRouteSnapshot,
|
|
||||||
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
|
||||||
console.log(childRoute);
|
|
||||||
console.log(state);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
canDeactivate(
|
|
||||||
component: unknown,
|
|
||||||
currentRoute: ActivatedRouteSnapshot,
|
|
||||||
currentState: RouterStateSnapshot,
|
|
||||||
nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
canLoad(
|
|
||||||
route: Route,
|
|
||||||
segments: UrlSegment[]): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
|
|
||||||
console.log(route);
|
|
||||||
console.log(state);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
|
||||||
|
|
||||||
const routes: Routes = [];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
|
||||||
export class LoginRoutingModule { }
|
|
@ -1 +0,0 @@
|
|||||||
<p>login works!</p>
|
|
@ -1,15 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-login',
|
|
||||||
templateUrl: './login.component.html',
|
|
||||||
styleUrls: ['./login.component.scss']
|
|
||||||
})
|
|
||||||
export class LoginComponent implements OnInit {
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
|
|
||||||
import { LoginRoutingModule } from './login-routing.module';
|
|
||||||
import { LoginComponent } from './login.component';
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [LoginComponent],
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
LoginRoutingModule
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class LoginModule { }
|
|
@ -1,22 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
import {
|
|
||||||
Router, Resolve, RouterStateSnapshot,
|
|
||||||
ActivatedRouteSnapshot,
|
|
||||||
} from '@angular/router';
|
|
||||||
import { Observable, Subject } from 'rxjs';
|
|
||||||
import { map, take } from 'rxjs/operators';
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root',
|
|
||||||
})
|
|
||||||
export class DataResolverService implements Resolve<any>{
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
|
|
||||||
console.log(1);
|
|
||||||
return 'aaa';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
|
||||||
import { MapComponent } from './map.component';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: MapComponent
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
exports: [RouterModule]
|
|
||||||
})
|
|
||||||
export class MapRoutingModule { }
|
|
@ -1 +0,0 @@
|
|||||||
<div id='map' style='width: 100%; height: 100%'></div>
|
|