├── backend ├── README.md ├── settings.js ├── my-database.db ├── package.json ├── accountRouter.js ├── app.js ├── tweetRouter.js └── db.js ├── front ├── public │ ├── favicon.ico │ └── index.html ├── babel.config.js ├── src │ ├── assets │ │ ├── CRUD.png │ │ ├── logo.png │ │ ├── background.png │ │ ├── registerImg.png │ │ └── assets.css │ ├── App.vue │ ├── store │ │ └── index.js │ ├── main.js │ ├── router │ │ └── index.js │ ├── views │ │ ├── Home.vue │ │ ├── Register.vue │ │ └── Skill.vue │ └── client.js ├── README.md └── package.json ├── README.md └── .gitignore /backend/README.md: -------------------------------------------------------------------------------- 1 | 所需安装包 2 | express 3 | md5-node 4 | jsonwebtoken 5 | sqlite3 6 | body-parser 7 | 8 | -------------------------------------------------------------------------------- /backend/settings.js: -------------------------------------------------------------------------------- 1 | //令牌加密规则,随便写 2 | module.exports = { 3 | accessTokenSecret: "qeocsajchsacsavd" 4 | } -------------------------------------------------------------------------------- /backend/my-database.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/backend/my-database.db -------------------------------------------------------------------------------- /front/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/front/public/favicon.ico -------------------------------------------------------------------------------- /front/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /front/src/assets/CRUD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/front/src/assets/CRUD.png -------------------------------------------------------------------------------- /front/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/front/src/assets/logo.png -------------------------------------------------------------------------------- /front/src/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/front/src/assets/background.png -------------------------------------------------------------------------------- /front/src/assets/registerImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoxian521/vue-node-sqlite3/HEAD/front/src/assets/registerImg.png -------------------------------------------------------------------------------- /front/src/assets/assets.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | width: 100%; 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | } -------------------------------------------------------------------------------- /front/src/App.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-node-sqlite3 2 | vue+node+sqlite3实现增删改查 3 | 4 | backend 后端文件 5 | 6 | front 前端文件 7 | 8 | 整体实现登录注册(jwt) 9 | 增删改查都需携带token 10 | 11 | 网上vue+node+sqlite3完整的实现这一套功能还是很少的,期待你的Star -------------------------------------------------------------------------------- /front/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: {}, 8 | mutations: {}, 9 | getters: {}, 10 | actions: {}, 11 | modules: {} 12 | }) -------------------------------------------------------------------------------- /front/README.md: -------------------------------------------------------------------------------- 1 | # crud 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorial-03", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "express": "^4.17.1", 15 | "jsonwebtoken": "^8.5.1", 16 | "md5-node": "^1.0.1", 17 | "sqlite3": "^4.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /front/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | //引入公共样式 6 | import './assets/assets.css' 7 | //引入ViewUI 8 | import ViewUI from 'view-design'; 9 | import 'view-design/dist/styles/iview.css'; 10 | Vue.use(ViewUI); 11 | //引入ElementUI 12 | import ElementUI from 'element-ui'; 13 | import 'element-ui/lib/theme-chalk/index.css'; 14 | Vue.use(ElementUI); 15 | 16 | Vue.config.productionTip = false 17 | 18 | new Vue({ 19 | router, 20 | store, 21 | render: h => h(App) 22 | }).$mount('#app') -------------------------------------------------------------------------------- /front/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | crud 10 | 11 | 12 | 13 | 17 |
18 |
Loading...
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /front/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | Vue.use(VueRouter) 5 | 6 | //路由懒加载 7 | function resolveView(view) { 8 | return () => import(`@/views/${view}`) 9 | } 10 | 11 | const routes = [{ 12 | path: '/', 13 | name: 'home', 14 | component: resolveView('Home') 15 | }, { 16 | path: '/Register', 17 | name: 'register', 18 | component: resolveView('Register') 19 | }, 20 | { 21 | path: '/Skill', 22 | name: 'skill', 23 | component: resolveView('Skill') 24 | } 25 | ] 26 | 27 | const router = new VueRouter({ 28 | mode: 'history', 29 | base: process.env.BASE_URL, 30 | routes 31 | }) 32 | 33 | export default router -------------------------------------------------------------------------------- /front/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crud", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.19.0", 11 | "core-js": "^3.3.2", 12 | "element-ui": "^2.12.0", 13 | "iview": "^1.0.1", 14 | "jwt-decode": "^2.2.0", 15 | "view-design": "^4.0.2", 16 | "vue": "^2.6.10", 17 | "vue-router": "^3.1.3", 18 | "vuex": "^3.0.1" 19 | }, 20 | "devDependencies": { 21 | "@vue/cli-plugin-babel": "^4.0.0", 22 | "@vue/cli-plugin-router": "^4.0.0", 23 | "@vue/cli-plugin-vuex": "^4.0.0", 24 | "@vue/cli-service": "^4.0.0", 25 | "sass": "^1.19.0", 26 | "sass-loader": "^8.0.0", 27 | "vue-template-compiler": "^2.6.10" 28 | }, 29 | "postcss": { 30 | "plugins": { 31 | "autoprefixer": {} 32 | } 33 | }, 34 | "browserslist": [ 35 | "> 1%", 36 | "last 2 versions" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /backend/accountRouter.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const db = require('./db') 3 | const md5 = require('md5-node') 4 | 5 | const router = express.Router() 6 | 7 | //添加用户信息 8 | router.post("/", function(request, response){ 9 | // 接收前端传过来的用户信息(解构赋值) 10 | const { username, password, passwordRepeat, email } = request.body 11 | //在后台定义用户注册时间才是符合规范的 12 | const creationTime = new Date().toLocaleString() 13 | if( 14 | typeof username != "string" || 15 | typeof password != "string" || 16 | typeof passwordRepeat != "string" || 17 | typeof email != "string" || 18 | typeof creationTime != "string" 19 | ){ 20 | response.status(422).end() 21 | return 22 | } 23 | //这里对用户所有密码都进行了加密 24 | db.createAccount(username, md5(password), md5(passwordRepeat), email, creationTime, function(error, id){ 25 | if(error){ 26 | if(error.message == "SQLITE_CONSTRAINT: UNIQUE constraint failed: accounts.username"){ 27 | response.status(400).json(["usernameTaken"]) 28 | }else{ 29 | response.status(500).end() 30 | } 31 | }else{ 32 | response.setHeader("Location", "/accounts/"+id) 33 | response.status(201).end() 34 | } 35 | }) 36 | 37 | }) 38 | 39 | module.exports = router -------------------------------------------------------------------------------- /backend/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const bodyParser = require('body-parser') 3 | const jwt = require('jsonwebtoken') 4 | const settings = require('./settings') 5 | const db = require('./db') 6 | const accountRouter = require('./accountRouter') 7 | const tweetRouter = require('./tweetRouter') 8 | const md5 = require('md5-node') 9 | 10 | const app = express() 11 | 12 | //解决跨域问题 13 | app.use(function (request, response, next) { 14 | response.setHeader("Access-Control-Allow-Origin", "*") 15 | response.setHeader("Access-Control-Allow-Methods", "*") 16 | response.setHeader("Access-Control-Allow-Headers", "*") 17 | response.setHeader("Access-Control-Expose-Headers", "*") 18 | next() 19 | }) 20 | 21 | //对POST请求过来的数据进行解析 22 | app.use(bodyParser.json()) 23 | app.use(bodyParser.urlencoded({ 24 | extended: false 25 | })) 26 | 27 | //使得accounts接口可用 28 | app.use("/accounts", accountRouter) 29 | //使得tweets接口可用 30 | app.use("/tweets", tweetRouter) 31 | 32 | // 用户登录并设置token令牌 33 | app.post("/tokens", function (request, response) { 34 | // 将前端传来的用户信息进行解构,直接获取里面的值 35 | const { grant_type, username, password } = request.body 36 | db.getAccountByUsername(username, function (error, account) { 37 | if (error) { 38 | response.status(500).end() 39 | } else if (!account || account.password != md5(password)) { 40 | response.status(400).json({ error: "invalid_client" }) 41 | } else { 42 | //生成jwt(token令牌) {expiresIn:3600}为token的过期时间,这里设置的是1小时 43 | const accessToken = jwt.sign({ 44 | accountId: account.id 45 | }, settings.accessTokenSecret, { expiresIn: 3600 }) 46 | const idToken = jwt.sign({ 47 | sub: account.id, 48 | preferred_username: account.username 49 | }, "some secret that doesn't matter") 50 | //返回token 51 | response.status(200).json({ 52 | access_token: accessToken, 53 | id_token: idToken 54 | }) 55 | } 56 | }) 57 | }) 58 | 59 | app.listen(3000, err => { 60 | if (!err) console.log('Successful Connection! Please Start Your Operation! The Port 3000') 61 | }) 62 | 63 | 64 | // Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. 头部 65 | // eyJhY2NvdW50SWQiOjEsImlhdCI6MTU3MjU5OTQ3MSwiZXhwIjoxNTcyNTk5NDgxfQ. 载荷 66 | // 01kCpXKp4qQqrofs9LEtssgb6k3V8ZWl_tqsuvRfXeM 签名 -------------------------------------------------------------------------------- /backend/tweetRouter.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const db = require('./db') 3 | const settings = require('./settings') 4 | const jwt = require('jsonwebtoken') 5 | 6 | const router = express.Router() 7 | 8 | //获取所有tweets信息 9 | router.get("/", function(request, response){ 10 | db.getAllTweets(function(error, tweets){ 11 | if(error){ 12 | response.status(500).end() 13 | }else{ 14 | response.status(200).json(tweets) 15 | } 16 | }) 17 | }) 18 | 19 | //根据ID获取Tweet信息 20 | router.get("/:id", function(request, response){ 21 | const id = request.params.id 22 | db.getTweetById(id, function(error, tweet){ 23 | if(error){ 24 | response.status(500).end() 25 | }else if(tweet){ 26 | response.status(200).json(tweet) 27 | }else{ 28 | response.status(404).end() 29 | } 30 | }) 31 | }) 32 | 33 | //根据ID对tweets信息进行 34 | router.delete("/:id", function(request, response){ 35 | const id = request.params.id 36 | db.deleteTweetById(id, function(error, tweet){ 37 | if(error){ 38 | response.status(500).end() 39 | }else if(tweet){ 40 | response.status(200).json(tweet) 41 | }else{ 42 | response.status(404).end() 43 | } 44 | }) 45 | }) 46 | 47 | //添加tweets信息 48 | router.post("/", function(request, response){ 49 | let payload = null 50 | try{ 51 | const authorizationHeader = request.get("Authorization") 52 | const accessToken = authorizationHeader.substr("Bearer ".length) 53 | payload = jwt.verify(accessToken, settings.accessTokenSecret) 54 | }catch(error){ 55 | response.status(401).end() 56 | return 57 | } 58 | const { accountId, message, createdAt, orders, payMethod,} = request.body 59 | if(payload == null || payload.accountId != accountId){ 60 | response.status(401).end() 61 | return 62 | } 63 | const errors = [] 64 | if(0 < errors.length){ 65 | response.status(400).json(errors) 66 | return 67 | } 68 | db.createTweet(accountId, message, createdAt, orders, payMethod, function(error, id){ 69 | if(error){ 70 | if(error.message == "SQLITE_CONSTRAINT: FOREIGN KEY constraint failed"){ 71 | response.status(400).json(["accountDoesNotExist"]) 72 | }else{ 73 | response.status(500).end() 74 | } 75 | }else{ 76 | response.setHeader("Location", "/tweets/"+id) 77 | response.status(201).end() 78 | } 79 | }) 80 | }) 81 | 82 | //根据ID修改tweets信息 83 | router.put("/:id", function(request, response){ 84 | const id = request.params.id 85 | const updatedAccountId = request.body.accountId 86 | const updatedMessage = request.body.message 87 | const updateCreatedAt = request.body.createdAt 88 | const updatedOrders = request.body.orders 89 | const updatedPayMethod = request.body.payMethod 90 | db.updateTweetById(id, updatedAccountId, updatedMessage, updateCreatedAt, updatedOrders, updatedPayMethod, function(error){ 91 | if(error){ 92 | if(error.message == "SQLITE_CONSTRAINT: FOREIGN KEY constraint failed"){ 93 | response.status(400).json(["accountDoesNotExist"]) 94 | }else{ 95 | response.status(500).end() 96 | } 97 | }else{ 98 | response.status(204).end() 99 | } 100 | }) 101 | }) 102 | 103 | module.exports = router -------------------------------------------------------------------------------- /backend/db.js: -------------------------------------------------------------------------------- 1 | const sqlite3 = require('sqlite3') 2 | const db = new sqlite3.Database("my-database.db") 3 | 4 | db.run("PRAGMA foreign_keys = ON") 5 | 6 | //CONSTRAINT unique_username UNIQUE(username) 对username做了唯一约束 7 | // 创建accounts用户表格的命令 8 | // CreationTime为创建时间 9 | db.run(` 10 | CREATE TABLE IF NOT EXISTS accounts ( 11 | id INTEGER PRIMARY KEY AUTOINCREMENT, 12 | username TEXT, 13 | password TEXT, 14 | passwordRepeat TEXT, 15 | email TEXT, 16 | creationTime TEXT, 17 | CONSTRAINT unique_username UNIQUE(username) 18 | ) 19 | `) 20 | // 创建Tweets表格的命令 21 | // id INTEGER主键自动递增 22 | db.run(` 23 | CREATE TABLE IF NOT EXISTS tweets ( 24 | id INTEGER PRIMARY KEY AUTOINCREMENT, 25 | accountId INTEGER, 26 | message TEXT, 27 | createdAt INTEGER, 28 | orders TEXT, 29 | payMethod TEXT, 30 | FOREIGN KEY (accountId) REFERENCES accounts(id) ON DELETE CASCADE 31 | ) 32 | `) 33 | 34 | //获取Tweet表格中的所有数据 35 | exports.getAllTweets = function(callback){ 36 | const query = "SELECT * FROM tweets" 37 | db.all(query, function(error, tweets){ 38 | callback(error, tweets) 39 | }) 40 | } 41 | 42 | //通过ID来查看Tweet表格中的数据 43 | exports.getTweetById = function(id, callback){ 44 | const query = "SELECT * FROM tweets WHERE id = ?" 45 | const values = [id] 46 | db.get(query, values, function(error, tweet){ 47 | callback(error, tweet) 48 | }) 49 | } 50 | 51 | //通过ID来删除Tweet表格中的数据 52 | exports.deleteTweetById = function(id, callback){ 53 | const query = "DELETE FROM tweets WHERE id = ?" 54 | const values = [id] 55 | db.run(query, values, function(error){ 56 | callback(error) 57 | }) 58 | } 59 | 60 | //创建Tweet表格 61 | exports.createTweet = function(accountId, message, createdAt, orders, payMethod, callback){ 62 | const query = "INSERT INTO tweets (accountId, message, createdAt, orders, payMethod) VALUES (?, ?, ?, ?, ?)" 63 | const values = [accountId, message, createdAt, orders, payMethod] 64 | db.run(query, values, function(error){ 65 | callback(error, this.lastID) 66 | }) 67 | } 68 | 69 | //通过ID来更新Tweet表格中的数据 70 | exports.updateTweetById = function(id, updatedAccountId, updatedMessage, updateCreatedAt, updatedOrders, updatedPayMethod, callback){ 71 | const query = ` 72 | UPDATE tweets SET 73 | accountId = ?, 74 | message = ?, 75 | createdAt = ?, 76 | orders = ?, 77 | payMethod = ? 78 | WHERE 79 | id = ? 80 | ` 81 | const values = [updatedAccountId, updatedMessage, updateCreatedAt, updatedOrders, updatedPayMethod, id] 82 | db.run(query, values, function(error){ 83 | callback(error) 84 | }) 85 | 86 | } 87 | 88 | //将前端传过来的用户信息插入 89 | exports.createAccount = function(username, password, passwordRepeat, email, creationTime, callback){ 90 | const query = "INSERT INTO accounts (username, password, passwordRepeat, email, creationTime) VALUES (?, ?, ?, ?, ?)" 91 | const values = [username,password,passwordRepeat,email,creationTime] 92 | db.run(query, values, function(error){ 93 | callback(error, this.lastID) 94 | }) 95 | } 96 | 97 | //通过姓名查找用户信息 98 | exports.getAccountByUsername = function(username, callback){ 99 | const query = "SELECT * FROM accounts WHERE username = ?" 100 | const values = [username] 101 | db.get(query, values, function(error, account){ 102 | callback(error, account) 103 | }) 104 | } -------------------------------------------------------------------------------- /front/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 125 | 126 | -------------------------------------------------------------------------------- /front/src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 154 | 155 | -------------------------------------------------------------------------------- /front/src/client.js: -------------------------------------------------------------------------------- 1 | const jwtDecode = require('jwt-decode') 2 | let accessToken = null 3 | 4 | //获取所有tweets信息接口 5 | export const getAllTweets = function (callback) { 6 | const request = new XMLHttpRequest() 7 | request.open("GET", "http://localhost:3000/tweets") 8 | request.send() 9 | request.addEventListener("load", () => { 10 | const status = request.status 11 | switch (status) { 12 | case 200: 13 | const bodyAsString = request.responseText 14 | const tweets = JSON.parse(bodyAsString) 15 | callback([], tweets) 16 | global.console.log(tweets) 17 | break 18 | case 500: 19 | callback(["Server error"]) 20 | break 21 | default: 22 | callback(["Server error"]) 23 | } 24 | }) 25 | } 26 | 27 | //根据ID搜索tweets信息接口 28 | export const getSearchTweets = function (searchId, callback) { 29 | const request = new XMLHttpRequest() 30 | request.open("GET", "http://localhost:3000/tweets/" + searchId) 31 | request.send() 32 | request.addEventListener("load", () => { 33 | const status = request.status 34 | switch (status) { 35 | case 200: 36 | const bodyAsString = request.responseText 37 | const tweets = JSON.parse(bodyAsString) 38 | callback([], tweets) 39 | break 40 | case 500: 41 | callback(["Server error"]) 42 | break 43 | default: 44 | callback(["Server error"]) 45 | } 46 | }) 47 | } 48 | 49 | //根据ID对tweets信息进行删除 50 | export const getDelTweets = function (infoId, callback) { 51 | const request = new XMLHttpRequest() 52 | request.open("DELETE", "http://localhost:3000/tweets/" + infoId) 53 | request.send() 54 | request.addEventListener("load", () => { 55 | const status = request.status 56 | switch (status) { 57 | case 200: 58 | callback(["Delete success"]) 59 | break 60 | case 500: 61 | callback(["Server error"]) 62 | break 63 | default: 64 | callback(["Server error"]) 65 | } 66 | }) 67 | } 68 | 69 | //修改tweets信息接口 70 | export const modifyTweet = function (id, accountId, message, createdAt, orders, payMethod, callback) { 71 | const tweet = { 72 | id, 73 | accountId, 74 | message, 75 | createdAt, 76 | orders, 77 | payMethod 78 | } 79 | const request = new XMLHttpRequest() 80 | request.open("PUT", "http://localhost:3000/tweets/" + id) 81 | request.send(JSON.stringify(tweet)) 82 | request.addEventListener("load", () => { 83 | const status = request.status 84 | switch (status) { 85 | case 201: 86 | const location = request.getResponseHeader("Location") 87 | callback([], location) 88 | break 89 | case 400: 90 | const errors = JSON.parse(request.responseText) 91 | callback(errors) 92 | break 93 | case 500: 94 | callback(["Unknown server error"]) 95 | break 96 | default: 97 | callback(["Unknown server error"]) 98 | } 99 | }) 100 | } 101 | 102 | //添加tweets信息接口 103 | export const createTweet = function (accountId, message, orders, payMethod, callback) { 104 | const tweet = { 105 | accountId, 106 | message, 107 | orders, 108 | payMethod, 109 | createdAt: Date.now() 110 | } 111 | const request = new XMLHttpRequest() 112 | request.open("POST", "http://localhost:3000/tweets") 113 | request.setRequestHeader("Content-Type", "application/json") 114 | request.setRequestHeader("Authorization", "Bearer " + accessToken) 115 | request.send(JSON.stringify(tweet)) 116 | global.console.log(JSON.stringify(tweet)) 117 | request.addEventListener("load", () => { 118 | const status = request.status 119 | switch (status) { 120 | case 201: 121 | const location = request.getResponseHeader("Location") 122 | callback([], location) 123 | break 124 | case 400: 125 | const errors = JSON.parse(request.responseText) 126 | callback(errors) 127 | break 128 | case 401: 129 | callback(["unauthorired"]) 130 | break 131 | case 500: 132 | callback(["Unknown server error"]) 133 | break 134 | default: 135 | callback(["Unknown server error"]) 136 | } 137 | }) 138 | } 139 | 140 | //用户注册接口 141 | export const createAccount = function (username, password, passwordRepeat, email, callback) { 142 | const account = { 143 | username, 144 | password, 145 | passwordRepeat, 146 | email 147 | } 148 | const request = new XMLHttpRequest() 149 | request.open("POST", "http://localhost:3000/accounts") 150 | request.setRequestHeader("Content-Type", "application/json") 151 | request.send(JSON.stringify(account)) 152 | global.console.log(account) 153 | request.addEventListener("load", () => { 154 | const status = request.status 155 | switch (status) { 156 | case 201: 157 | const location = request.getResponseHeader("Location") 158 | callback([], location) 159 | break 160 | case 400: 161 | const errors = JSON.parse(request.responseText) 162 | callback(errors) 163 | break 164 | case 500: 165 | callback(["Unknown server error"]) 166 | break 167 | default: 168 | callback(["Unknown server error"]) 169 | } 170 | }) 171 | } 172 | 173 | //用户登录接口 174 | export const login = function (username, password, callback) { 175 | const request = new XMLHttpRequest() 176 | request.open("POST", "http://localhost:3000/tokens") 177 | request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") 178 | request.send("grant_type=password&username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password)) 179 | request.addEventListener("load", () => { 180 | const status = request.status 181 | switch (status) { 182 | case 200: 183 | var body = JSON.parse(request.responseText) 184 | const idToken = body.id_token 185 | accessToken = body.access_token 186 | const userInfo = jwtDecode(idToken) 187 | const id = userInfo.sub 188 | const username = userInfo.preferred_username 189 | callback([], id, username) 190 | break 191 | case 400: 192 | var body = JSON.parse(request.responseText) 193 | callback([body.error]) 194 | break 195 | case 500: 196 | callback(["Unknown server error"]) 197 | break 198 | default: 199 | callback(["Unknown server error"]) 200 | } 201 | }) 202 | } -------------------------------------------------------------------------------- /front/src/views/Skill.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 272 | 273 | --------------------------------------------------------------------------------