docs:更新文档

This commit is contained in:
张益铭 2021-03-01 15:06:11 +08:00
parent 1542135ab0
commit 9064b372e8
5835 changed files with 904126 additions and 161722 deletions

BIN
.DS_Store vendored

Binary file not shown.

11
.gitignore vendored
View File

@ -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
View File

@ -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.

View File

@ -1,43 +1,17 @@
# Vue3.0版本已开发完成!
Vue3.0+TypeScript+NodeJS+MySql编写的一套后台管理框架
# 后端管理项目文档
## 文档地址
https://xiaoxian521.github.io/zh/standard/
## 安装依赖
```
npm install
```
## 结构介绍
① frontend为前端项目存放文件夹
② backend为后端项目存放文件夹
③ doc为文档编写存放文件夹
## 文档启动
```
npm run docs
```
## Structure introduction
① Frontend stores the folder for the front-end project
② Backend stores the folder for the back-end project
③ Doc write storage folder for documents
## 前端对应代码存放目录
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
## 文档打包
```
npm run docs:build
```
打包后会在.vitepress文件夹下生成dist目录

View File

@ -1,8 +0,0 @@
# Port
PORT=3000
# JWT_SECRET
JWT_SECRET = '708DD1DC5BC5A169'
# Debug
LOG_LEVEL='debug'

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

View File

@ -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>

View File

@ -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>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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,
}

View File

@ -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}`) // 自动打开默认浏览器

View File

@ -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
}

View File

@ -1,19 +0,0 @@
// 状态码
export const enum Code {
failCode = -1,
successCode = 0
}
// 返回信息
export enum Info {
"请输入正确的验证码",
"账号尚未被注册",
"登录成功",
"密码错误",
"密码长度不能小于6位",
"账号已被注册",
"账号注册成功",
"修改成功",
"删除成功",
"搜索信息不能为空",
}

View File

@ -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}表创建成功`)
})
}

View File

@ -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"
]
}

View File

@ -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": []
}

View File

@ -1,19 +0,0 @@
# simplicity
简约而不简单的文档
## 安装依赖
```
npm install
```
## 文档启动
```
npm run docs
```
## 文档打包
```
npm run docs:build
```
打包后会在.vitepress文件夹下生成dist目录

View File

@ -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"
}
}

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 541 KiB

After

Width:  |  Height:  |  Size: 541 KiB

View File

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 243 KiB

View File

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 252 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 541 KiB

After

Width:  |  Height:  |  Size: 541 KiB

View File

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

BIN
frontend/.DS_Store vendored

Binary file not shown.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
# angular-ts

View File

@ -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"
}
}

View File

@ -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
}
}));
}
};

View File

@ -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));
});
});

View File

@ -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();
}
}

View File

@ -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"
]
}
}

View File

@ -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
});
};

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}

View File

@ -1,11 +0,0 @@
{
"/api": {
"target": "http://192.168.15.213:3000/",
"secure": false,
"pathRewrite": {
"^/api": ""
},
"changeOrigin": true,
"logLevel": "debug"
}
}

View File

@ -1 +0,0 @@
<p>err404 works!</p>

View File

@ -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 {
}
}

View File

@ -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 { }

View File

@ -1 +0,0 @@
export * from './error/err404/err404.module';

View File

@ -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 { }

View File

@ -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,
) {
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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>;
}

View File

@ -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);
}
}
}

View File

@ -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 { }

View File

@ -1 +0,0 @@
<router-outlet></router-outlet>

View File

@ -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!');
});
});

View File

@ -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(
) {
}
}

View File

@ -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 { }

View File

@ -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);
}
}

View File

@ -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 { }

View File

@ -1 +0,0 @@
<p>login works!</p>

View File

@ -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 {
}
}

View File

@ -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 { }

View File

@ -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';
}
}

View File

@ -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 { }

View File

@ -1 +0,0 @@
<div id='map' style='width: 100%; height: 100%'></div>

Some files were not shown because too many files have changed in this diff Show More