├── 项目代码 ├── server │ ├── public │ │ └── robots.txt │ ├── src │ │ ├── modules │ │ │ ├── signToken.js │ │ │ ├── email.js │ │ │ ├── getAllRouter.js │ │ │ └── auth.js │ │ ├── db │ │ │ └── index.js │ │ ├── routes │ │ │ ├── index.js │ │ │ ├── commodity │ │ │ │ ├── detail.js │ │ │ │ ├── update-state.js │ │ │ │ ├── store-id.js │ │ │ │ ├── recommend-index.js │ │ │ │ ├── list.js │ │ │ │ ├── update.js │ │ │ │ ├── recommend.js │ │ │ │ └── create.js │ │ │ ├── warehouse_list │ │ │ │ ├── detail.js │ │ │ │ ├── update-state.js │ │ │ │ ├── list.js │ │ │ │ ├── update.js │ │ │ │ └── create.js │ │ │ ├── store │ │ │ │ ├── update-state.js │ │ │ │ ├── password.js │ │ │ │ ├── detail.js │ │ │ │ ├── auth │ │ │ │ │ ├── info.js │ │ │ │ │ └── sign.js │ │ │ │ ├── list.js │ │ │ │ ├── update.js │ │ │ │ └── create.js │ │ │ ├── user │ │ │ │ ├── user-info.js │ │ │ │ ├── data.js │ │ │ │ ├── sign.js │ │ │ │ ├── sign-up.js │ │ │ │ ├── update.js │ │ │ │ └── list.js │ │ │ ├── banner │ │ │ │ ├── list.js │ │ │ │ ├── delete.js │ │ │ │ ├── update.js │ │ │ │ └── create.js │ │ │ ├── admin │ │ │ │ ├── user-info.js │ │ │ │ ├── update.js │ │ │ │ └── sign.js │ │ │ ├── article │ │ │ │ ├── delete.js │ │ │ │ ├── list-store.js │ │ │ │ ├── create.js │ │ │ │ ├── update.js │ │ │ │ ├── detail.js │ │ │ │ ├── list.js │ │ │ │ ├── list-client-store.js │ │ │ │ ├── list-commodity.js │ │ │ │ └── search.js │ │ │ ├── collection │ │ │ │ ├── info.js │ │ │ │ ├── delete.js │ │ │ │ ├── create.js │ │ │ │ └── list.js │ │ │ ├── reservation │ │ │ │ ├── update.js │ │ │ │ ├── info.js │ │ │ │ ├── note-update.js │ │ │ │ ├── create.js │ │ │ │ ├── refuse.js │ │ │ │ ├── delete.js │ │ │ │ └── list.js │ │ │ ├── notice │ │ │ │ ├── delete.js │ │ │ │ ├── create.js │ │ │ │ └── list.js │ │ │ ├── upload.js │ │ │ ├── comment │ │ │ │ ├── create.js │ │ │ │ ├── delete.js │ │ │ │ └── list.js │ │ │ ├── message │ │ │ │ ├── list.js │ │ │ │ ├── list-store.js │ │ │ │ ├── list-user.js │ │ │ │ └── create.js │ │ │ ├── tools │ │ │ │ ├── location.js │ │ │ │ ├── data.js │ │ │ │ └── order-search.js │ │ │ ├── notice-history │ │ │ │ └── create.js │ │ │ └── order │ │ │ │ ├── list.js │ │ │ │ └── create.js │ │ ├── utils │ │ │ └── id.js │ │ ├── index.js │ │ └── socket │ │ │ └── index.js │ └── package.json ├── 图片.png ├── admin │ ├── src │ │ ├── style │ │ │ └── index.scss │ │ ├── assets │ │ │ ├── logo.jpg │ │ │ ├── user.png │ │ │ ├── blue-v.png │ │ │ ├── empty.png │ │ │ └── custom-empty-image.png │ │ ├── utils │ │ │ └── showImg.js │ │ ├── pages │ │ │ ├── store │ │ │ │ ├── index.vue │ │ │ │ ├── message │ │ │ │ │ ├── [id].vue │ │ │ │ │ └── index.vue │ │ │ │ ├── article │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── [id].vue │ │ │ │ │ └── list.vue │ │ │ │ ├── commodity │ │ │ │ │ ├── create │ │ │ │ │ │ └── [id].vue │ │ │ │ │ ├── [id].vue │ │ │ │ │ ├── list.vue │ │ │ │ │ └── index.vue │ │ │ │ ├── sign.vue │ │ │ │ ├── set │ │ │ │ │ └── index.vue │ │ │ │ ├── order │ │ │ │ │ └── index.vue │ │ │ │ └── notice │ │ │ │ │ └── index.vue │ │ │ ├── index.vue │ │ │ ├── 404.vue │ │ │ ├── client │ │ │ │ ├── article │ │ │ │ │ └── search.vue │ │ │ │ ├── user │ │ │ │ │ └── index.vue │ │ │ │ ├── message │ │ │ │ │ └── index.vue │ │ │ │ ├── sign.vue │ │ │ │ ├── order │ │ │ │ │ └── index.vue │ │ │ │ ├── index.vue │ │ │ │ ├── sign-up.vue │ │ │ │ ├── reservation │ │ │ │ │ └── index.vue │ │ │ │ └── set │ │ │ │ │ └── index.vue │ │ │ └── admin │ │ │ │ ├── commodity │ │ │ │ ├── create.vue │ │ │ │ ├── [id].vue │ │ │ │ └── list.vue │ │ │ │ ├── store │ │ │ │ ├── create.vue │ │ │ │ ├── [id].vue │ │ │ │ └── list.vue │ │ │ │ ├── password │ │ │ │ └── index.vue │ │ │ │ ├── index.vue │ │ │ │ ├── sign.vue │ │ │ │ ├── user │ │ │ │ └── index.vue │ │ │ │ ├── notice │ │ │ │ ├── create.vue │ │ │ │ └── index.vue │ │ │ │ └── banner │ │ │ │ └── index.vue │ │ ├── store │ │ │ └── useUserData.js │ │ ├── App.vue │ │ ├── plugin │ │ │ └── axios.js │ │ ├── components │ │ │ ├── user │ │ │ │ ├── Navigate.vue │ │ │ │ └── ArticleList │ │ │ │ │ └── index.vue │ │ │ ├── VantUpload.vue │ │ │ ├── Upload.vue │ │ │ ├── admin │ │ │ │ ├── StoreForm.vue │ │ │ │ ├── Navigate.vue │ │ │ │ └── BannerDialog │ │ │ │ │ └── index.vue │ │ │ ├── store │ │ │ │ ├── Navigate.vue │ │ │ │ └── ArticleEdit │ │ │ │ │ └── Edit.vue │ │ │ └── MultipleUpload.vue │ │ ├── layouts │ │ │ ├── client-empty.vue │ │ │ ├── client.vue │ │ │ ├── store.vue │ │ │ └── admin.vue │ │ ├── main.js │ │ └── hooks │ │ │ └── useFetch.js │ ├── postcss.config.cjs │ ├── tailwind.config.cjs │ ├── index.html │ ├── package.json │ ├── vite.config.js │ └── public │ │ └── logo.svg ├── dev.bat ├── intall.bat └── start.bat ├── 调研报告.doc ├── 答辩PPT.pptx ├── 学号+姓名+任务书模板.doc ├── .gitattributes ├── 22201011801-潘卓-毕业论文学生手册.doc ├── 22201011801-潘卓-本科毕业设计(论文)开题报告(1)(1).doc ├── .gitignore └── README.md /项目代码/server/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow:/ -------------------------------------------------------------------------------- /调研报告.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/调研报告.doc -------------------------------------------------------------------------------- /答辩PPT.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/答辩PPT.pptx -------------------------------------------------------------------------------- /项目代码/图片.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/图片.png -------------------------------------------------------------------------------- /学号+姓名+任务书模板.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/学号+姓名+任务书模板.doc -------------------------------------------------------------------------------- /项目代码/admin/src/style/index.scss: -------------------------------------------------------------------------------- 1 | // @tailwind base; 2 | @tailwind utilities; 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /22201011801-潘卓-毕业论文学生手册.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/22201011801-潘卓-毕业论文学生手册.doc -------------------------------------------------------------------------------- /项目代码/dev.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | start cmd /k "cd server&&yarn dev" 3 | start cmd /k "cd admin&&yarn dev" 4 | -------------------------------------------------------------------------------- /项目代码/admin/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /项目代码/admin/src/assets/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/admin/src/assets/logo.jpg -------------------------------------------------------------------------------- /项目代码/admin/src/assets/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/admin/src/assets/user.png -------------------------------------------------------------------------------- /项目代码/intall.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | start cmd /k "cd server&&yarn&& exit" 3 | start cmd /k "cd admin&&yarn&& exit" 4 | -------------------------------------------------------------------------------- /项目代码/admin/src/assets/blue-v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/admin/src/assets/blue-v.png -------------------------------------------------------------------------------- /项目代码/admin/src/assets/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/admin/src/assets/empty.png -------------------------------------------------------------------------------- /项目代码/admin/src/utils/showImg.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | export default url => axios.defaults.baseURL + url; 3 | -------------------------------------------------------------------------------- /22201011801-潘卓-本科毕业设计(论文)开题报告(1)(1).doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/22201011801-潘卓-本科毕业设计(论文)开题报告(1)(1).doc -------------------------------------------------------------------------------- /项目代码/admin/src/assets/custom-empty-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/car-mall/HEAD/项目代码/admin/src/assets/custom-empty-image.png -------------------------------------------------------------------------------- /项目代码/start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | start cmd /k "npm config set registry https://registry.npmmirror.com/&&npm i yarn vite nodemon -g&&yarn config set registry https://registry.npmmirror.com/" 3 | -------------------------------------------------------------------------------- /项目代码/server/src/modules/signToken.js: -------------------------------------------------------------------------------- 1 | let jwt = require("jsonwebtoken"); 2 | function sign(obj) { 3 | const token = jwt.sign(obj, "key"); 4 | return token; 5 | } 6 | module.exports = sign; 7 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/message/[id].vue: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/message/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /项目代码/server/src/db/index.js: -------------------------------------------------------------------------------- 1 | const mysql = require("mysql2/promise"); 2 | const connection = mysql.createPool({ 3 | host: "localhost", 4 | user: "root", 5 | database: "car_shop", 6 | // password: "", 7 | }); 8 | module.exports = connection; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules/**/* 2 | 3 | dist 4 | .next 5 | .idea 6 | .vscode 7 | .DS_Store 8 | *.local 9 | 论文.doc 10 | /项目代码代/** 11 | 基于Vue的卓尔汽车销售Web App的设计与实现_简洁报告.pdf 12 | /**/public/**/*.avif 13 | /**/public/**/*.jpg 14 | /**/public/**/*.png 15 | /**/public/**/*.webp -------------------------------------------------------------------------------- /项目代码/admin/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/index.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | let router = new Router(); 3 | 4 | router.get("/", async ctx => { 5 | ctx.body = ` 6 | 7 |

8 | Koa server 9 |

10 | `; 11 | }); 12 | module.exports = router; 13 | -------------------------------------------------------------------------------- /项目代码/admin/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | corePlugins: { 4 | preflight: false 5 | }, 6 | content: ["./index.html", "./src/**/*.vue"], 7 | theme: { 8 | extend: { 9 | colors: { 10 | } 11 | } 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /项目代码/admin/src/store/useUserData.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | import { ref } from "vue"; 3 | 4 | export const useUserData = defineStore("user-data", () => { 5 | const userData = ref(null); 6 | function set(val) { 7 | userData.value = val; 8 | } 9 | return { userData, set }; 10 | }); 11 | -------------------------------------------------------------------------------- /项目代码/admin/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 16 | -------------------------------------------------------------------------------- /项目代码/admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Vue + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/detail.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/commodity/:id", async ctx => { 6 | const [result] = await db.query(`select * from commodity where id=${ctx.params.id};`); 7 | 8 | ctx.body = { 9 | success: result.length, 10 | data: result[0], 11 | }; 12 | }); 13 | 14 | module.exports = router; 15 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/404.vue: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /项目代码/admin/src/plugin/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import cookie from "js-cookie"; 3 | 4 | axios.defaults.baseURL = "http://localhost:3000/"; 5 | 6 | axios.interceptors.request.use( 7 | function (config) { 8 | // 在发送请求之前做些什么 9 | config.headers.authorization = cookie.get("token"); 10 | return config; 11 | }, 12 | function (error) { 13 | // 对请求错误做些什么 14 | return Promise.reject(error); 15 | } 16 | ); 17 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/warehouse_list/detail.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/warehouse-list/:id", async ctx => { 6 | const [result] = await db.query( 7 | `SELECT 8 | * 9 | FROM 10 | warehouse_list where id=${ctx.params.id}; 11 | ` 12 | ); 13 | 14 | ctx.body = { 15 | success: !!result.length, 16 | data: result[0], 17 | }; 18 | }); 19 | 20 | module.exports = router; 21 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/user/Navigate.vue: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/update-state.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/store/state/:id", auth(), async ctx => { 7 | const id = ctx.params.id; 8 | const { state } = ctx.request.body; 9 | const [result] = await db.query(`UPDATE chain_store SET state = ? WHERE id = ?`, [state, id]); 10 | 11 | ctx.body = { 12 | success: !!result?.affectedRows, 13 | }; 14 | }); 15 | 16 | module.exports = router; 17 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/update-state.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/commodity/state/:id", auth(), async ctx => { 7 | const id = ctx.params.id; 8 | const { state } = ctx.request.body; 9 | const [result] = await db.query(`UPDATE commodity SET state = ? WHERE id = ?`, [state, id]); 10 | 11 | ctx.body = { 12 | success: !!result?.affectedRows, 13 | }; 14 | }); 15 | 16 | module.exports = router; 17 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/password.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/store/password", auth(), async ctx => { 7 | const { password } = ctx.request.body; 8 | const [result] = await db.query(`UPDATE chain_store SET password = ? WHERE id = ?`, [ 9 | password, 10 | ctx.id, 11 | ]); 12 | 13 | ctx.body = { 14 | success: !!result?.affectedRows, 15 | }; 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/detail.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/store/:id", async ctx => { 6 | const [result] = await db.query( 7 | `SELECT 8 | id, 9 | email, 10 | cover_pic, 11 | name, 12 | address, 13 | create_time, 14 | state 15 | FROM 16 | chain_store where id=${ctx.params.id}; 17 | ` 18 | ); 19 | 20 | ctx.body = { 21 | success: !!result.length, 22 | data: result[0], 23 | }; 24 | }); 25 | 26 | module.exports = router; 27 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/warehouse_list/update-state.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/warehouse-list/state/:id", auth(), async ctx => { 7 | const id = ctx.params.id; 8 | const { state } = ctx.request.body; 9 | const [result] = await db.query(`UPDATE warehouse_list SET state = ? WHERE id = ?`, [state, id]); 10 | 11 | ctx.body = { 12 | success: !!result?.affectedRows, 13 | }; 14 | }); 15 | 16 | module.exports = router; 17 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/user-info.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | let db = require("@/db"); 3 | let auth = require("@/modules/auth"); 4 | let router = new Router(); 5 | 6 | router.get("/user/info", auth(), async ctx => { 7 | try { 8 | let [res] = await db.query(`select * from user where id=?`, [ctx.id]); 9 | ctx.body = { 10 | success: !!res.length, 11 | data: { id: res[0]?.id, name: res[0]?.name, avatar: res[0]?.avatar }, 12 | }; 13 | } catch (error) { 14 | ctx.body = { success: false }; 15 | } 16 | }); 17 | module.exports = router; 18 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/data.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | let db = require("@/db"); 3 | let auth = require("@/modules/auth"); 4 | let router = new Router(); 5 | 6 | router.get("/user", auth(), async ctx => { 7 | try { 8 | let [res] = await db.query(`select * from user where id=?`, [ctx.id]); 9 | if (res[0]) { 10 | delete res[0].password; 11 | } 12 | ctx.body = { 13 | success: !!res.length, 14 | data: res[0], 15 | }; 16 | } catch (error) { 17 | ctx.body = { success: false }; 18 | } 19 | }); 20 | module.exports = router; 21 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/auth/info.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | let db = require("@/db"); 3 | let auth = require("@/modules/auth"); 4 | let router = new Router(); 5 | 6 | router.get("/store/info", auth(), async ctx => { 7 | try { 8 | let [res] = await db.query(`select * from chain_store where id=?`, [ctx.id]); 9 | ctx.body = { 10 | success: !!res.length, 11 | data: { id: res[0]?.id, username: res[0]?.name, state: res[0]?.state }, 12 | }; 13 | } catch (error) { 14 | ctx.body = { success: false }; 15 | } 16 | }); 17 | module.exports = router; 18 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/banner/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/banner", async ctx => { 6 | try { 7 | const [result] = await db.query(`select * from banner;`); 8 | 9 | ctx.body = { 10 | success: true, 11 | message: "查询Banner列表", 12 | data: result, 13 | }; 14 | } catch (error) { 15 | console.log(error); 16 | ctx.body = { 17 | success: false, 18 | error: error.message, 19 | message: "查询失败", 20 | }; 21 | } 22 | }); 23 | 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/admin/user-info.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | const sign = require("@/modules/signToken"); 3 | let db = require("@/db"); 4 | let auth = require("@/modules/auth"); 5 | let router = new Router(); 6 | 7 | router.get("/admin/info", auth(), async ctx => { 8 | try { 9 | let [res] = await db.query(`select * from admin where id=?`, [ctx.id]); 10 | ctx.body = { 11 | success: !!res.length, 12 | data: { id: res[0]?.id, username: res[0]?.username }, 13 | }; 14 | } catch (error) { 15 | ctx.body = { success: false }; 16 | } 17 | }); 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/banner/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.delete("/banner/:id", async ctx => { 6 | try { 7 | const bannerId = ctx.params.id; 8 | 9 | const [result] = await db.query(`DELETE FROM banner WHERE id = ?`, [bannerId]); 10 | 11 | ctx.body = { 12 | success: !!result?.affectedRows, 13 | message: "删除成功", 14 | }; 15 | } catch (error) { 16 | console.log(error); 17 | ctx.body = { 18 | success: false, 19 | error: error.message, 20 | message: "删除失败", 21 | }; 22 | } 23 | }); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /项目代码/server/src/utils/id.js: -------------------------------------------------------------------------------- 1 | function random(min, max) { 2 | return Math.floor(Math.random() * (max - min + 1)) + min; 3 | } 4 | 5 | const WorkerID = Math.min( 6 | process.env.NODE_APP_INSTANCE ? +process.env.NODE_APP_INSTANCE : random(0, 9), 7 | 9 8 | ); 9 | 10 | const BaseTime = +new Date("2023-12-27"); 11 | 12 | let lastTimeTick; 13 | 14 | let lastRandomNumberTick = random(1, 3); 15 | 16 | function id() { 17 | let timestamp = +new Date() - BaseTime; 18 | lastRandomNumberTick = timestamp == lastTimeTick ? ++lastRandomNumberTick : random(0, 3); 19 | lastTimeTick = timestamp; 20 | 21 | return +`${timestamp}${WorkerID}${lastRandomNumberTick}`; 22 | } 23 | 24 | 25 | module.exports = id; 26 | 27 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.delete("/article/:id", async ctx => { 6 | const articleId = ctx.params.id; 7 | 8 | try { 9 | const [result] = await db.query("UPDATE article SET state = 0 WHERE id = ?", [articleId]); 10 | 11 | ctx.body = { 12 | success: !!result?.affectedRows, 13 | message: result?.affectedRows ? "文章删除成功" : "文章不存在或已被删除", 14 | }; 15 | } catch (error) { 16 | console.log(error); 17 | ctx.body = { 18 | success: false, 19 | error: error.message, 20 | message: "文章删除失败", 21 | }; 22 | } 23 | }); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/store", async ctx => { 6 | const [result] = await db.query( 7 | ctx.query.state 8 | ? `SELECT 9 | id, 10 | email, 11 | cover_pic, 12 | name, 13 | address, 14 | create_time, 15 | state 16 | FROM 17 | chain_store where state=${ctx.query.state}; 18 | ` 19 | : `SELECT 20 | id, 21 | email, 22 | cover_pic, 23 | name, 24 | address, 25 | create_time, 26 | state 27 | FROM 28 | chain_store; 29 | ` 30 | ); 31 | 32 | ctx.body = { 33 | success: true, 34 | data: result, 35 | }; 36 | }); 37 | 38 | module.exports = router; 39 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/article/search.vue: -------------------------------------------------------------------------------- 1 | 5 | 17 | 18 | 19 | { 20 | "meta": { 21 | "layout": "client-empty" 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/store-id.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/commodity/store/:id", auth(), async ctx => { 7 | try { 8 | let query = `SELECT * FROM commodity WHERE store=${ctx.params.id}`; 9 | 10 | // 执行数据库查询 11 | const [result] = await db.query(query); 12 | 13 | ctx.body = { 14 | success: true, 15 | data: result, 16 | message: "查询成功", 17 | }; 18 | } catch (error) { 19 | console.log(error); 20 | ctx.body = { 21 | success: false, 22 | error: error.message, 23 | message: "查询失败", 24 | }; 25 | } 26 | }); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/sign.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | const sign = require("@/modules/signToken"); 3 | let db = require("@/db"); 4 | let router = new Router(); 5 | 6 | router.post("/user/sign", async ctx => { 7 | try { 8 | let [res] = await db.query(`select * from user where email=? and password=?`, [ 9 | ctx.request.body.email, 10 | ctx.request.body.password, 11 | ]); 12 | 13 | ctx.body = { 14 | success: !!res.length, 15 | data: { id: res[0]?.id, name: res[0]?.name, avatar: res[0]?.avatar }, 16 | token: sign({ id: res[0]?.id, username: res[0]?.name, type: "user" }), 17 | }; 18 | } catch (error) { 19 | ctx.body = { success: false }; 20 | } 21 | }); 22 | module.exports = router; 23 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/admin/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); // 你的数据库模块 3 | const auth = require("@/modules/auth"); // 你的权限验证模块 4 | 5 | const router = new Router(); 6 | 7 | router.put("/admin/password", auth(), async ctx => { 8 | try { 9 | const { id } = ctx; 10 | const { password } = ctx.request.body; 11 | 12 | await db.query("UPDATE admin SET password = ? WHERE id = ?", [password, id]); 13 | 14 | ctx.body = { 15 | success: true, 16 | message: "密码修改成功", 17 | }; 18 | } catch (error) { 19 | console.error(error); 20 | ctx.body = { 21 | success: false, 22 | message: "密码修改失败", 23 | error: error.message, 24 | }; 25 | } 26 | }); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/collection/info.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/collection/:id", auth(), async ctx => { 7 | try { 8 | // 查询是否收藏 9 | const result = await db.query( 10 | "SELECT COUNT(*) AS count FROM collection WHERE user_id = ? AND item_id = ?", 11 | [ctx.id, ctx.params.id] 12 | ); 13 | 14 | ctx.body = { 15 | success: true, 16 | data: result[0][0]?.count > 0, 17 | }; 18 | } catch (error) { 19 | console.error(error); 20 | ctx.body = { 21 | success: false, 22 | message: "查询收藏状态失败", 23 | error: error.message, 24 | }; 25 | } 26 | }); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/admin/sign.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | const sign = require("@/modules/signToken"); 3 | let db = require("@/db"); 4 | let auth = require("@/modules/auth"); 5 | let router = new Router(); 6 | 7 | router.post("/admin/sign", async ctx => { 8 | try { 9 | let [res] = await db.query(`select * from admin where username=? and password=?`, [ 10 | ctx.request.body.username, 11 | ctx.request.body.password, 12 | ]); 13 | ctx.body = { 14 | success: !!res.length, 15 | data: { id: res[0]?.id, username: res[0]?.username }, 16 | token: sign({ id: res[0]?.id, username: res[0]?.username, type: "admin" }), 17 | }; 18 | } catch (error) { 19 | ctx.body = { success: false }; 20 | } 21 | }); 22 | module.exports = router; 23 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/banner/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.put("/banner/:id", async ctx => { 6 | try { 7 | const bannerId = ctx.params.id; 8 | const { url, cover } = ctx.request.body; 9 | 10 | const [result] = await db.query(`UPDATE banner SET url = ?, cover = ? WHERE id = ?`, [ 11 | url, 12 | cover, 13 | bannerId, 14 | ]); 15 | 16 | ctx.body = { 17 | success: !!result?.affectedRows, 18 | message: "修改成功", 19 | }; 20 | } catch (error) { 21 | console.log(error); 22 | ctx.body = { 23 | success: false, 24 | error: error.message, 25 | message: "修改失败", 26 | }; 27 | } 28 | }); 29 | 30 | module.exports = router; 31 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/collection/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.delete("/collection/:id", auth(), async ctx => { 7 | try { 8 | 9 | // 删除收藏记录 10 | const result = await db.query("DELETE FROM collection WHERE user_id = ? AND item_id = ?", [ 11 | ctx.id, 12 | ctx.params.id, 13 | ]); 14 | 15 | ctx.body = { 16 | success: !!result[0]?.affectedRows, 17 | message: "商品收藏已取消", 18 | }; 19 | } catch (error) { 20 | console.error(error); 21 | ctx.body = { 22 | success: false, 23 | message: "取消商品收藏失败", 24 | error: error.message, 25 | }; 26 | } 27 | }); 28 | 29 | module.exports = router; 30 | -------------------------------------------------------------------------------- /项目代码/admin/src/layouts/client-empty.vue: -------------------------------------------------------------------------------- 1 | 4 | 34 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/commodity/create.vue: -------------------------------------------------------------------------------- 1 | 4 | 24 | 25 | -------------------------------------------------------------------------------- /项目代码/server/src/modules/email.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | 3 | const transporter = nodemailer.createTransport({ 4 | service: "qq", 5 | port: 587, 6 | secure: false, 7 | auth: { 8 | user: `1974109227@qq.com `, 9 | pass: `xogjwbswikrwfddf`, 10 | }, 11 | }); 12 | 13 | function sendEmail(params) { 14 | return new Promise((resolve, reject) => { 15 | const mailOptions = { 16 | from: `1974109227@qq.com `, 17 | to: params.target, 18 | subject: params.subject, 19 | html: params.content, 20 | }; 21 | transporter.sendMail(mailOptions, (error, info) => { 22 | if (error) { 23 | reject(error); 24 | } else { 25 | resolve(); 26 | } 27 | }); 28 | }); 29 | } 30 | 31 | module.exports = sendEmail; 32 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/store/:id", auth(), async ctx => { 7 | try { 8 | const id = ctx.params.id; 9 | const { email, cover_pic, name, address } = ctx.request.body; 10 | 11 | const result = await db.query( 12 | `UPDATE chain_store SET email = ?, cover_pic = ?, name = ?, address = ? WHERE id = ?`, 13 | [email, cover_pic, name, address, id] 14 | ); 15 | 16 | ctx.body = { 17 | success: !!result[0]?.affectedRows, 18 | }; 19 | } catch (error) { 20 | console.log(error); 21 | ctx.body = { success: false, error: error.message }; 22 | } 23 | }); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/reservation/:id", auth(), async ctx => { 7 | try { 8 | const { id } = ctx.params; 9 | const { state } = ctx.request.body; 10 | 11 | // 更新预约状态 12 | const result = await db.query(`UPDATE reservation SET state = ? WHERE id = ?`, [state, id]); 13 | 14 | ctx.body = { 15 | success: !!result[0]?.affectedRows, 16 | message: "预约状态更新成功", 17 | }; 18 | } catch (error) { 19 | console.error(error); 20 | ctx.body = { 21 | success: false, 22 | message: "预约状态更新失败", 23 | error: error.message, 24 | }; 25 | } 26 | }); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/warehouse_list/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/warehouse-list", auth(), async ctx => { 7 | try { 8 | let query = `select * from warehouse_list where 1=1`; 9 | 10 | if (ctx.query.state) { 11 | query += `and state=${ctx.query.state}`; 12 | } 13 | 14 | const [result] = await db.query(query); 15 | 16 | ctx.body = { 17 | success: true, 18 | message: "查询成功", 19 | data: result, 20 | }; 21 | } catch (error) { 22 | console.log(error); 23 | ctx.body = { 24 | success: false, 25 | message: "查询失败", 26 | error: error.message, 27 | }; 28 | } 29 | }); 30 | 31 | module.exports = router; 32 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/banner/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | const id = require("@/utils/id"); 5 | 6 | router.post("/banner", async ctx => { 7 | try { 8 | const { url, cover } = ctx.request.body; 9 | 10 | const [result] = await db.query( 11 | `INSERT INTO banner (id, url, cover, create_time) VALUES (?, ?, ?, NOW())`, 12 | [id(), /^[\s\S]*.*[^\s][\s\S]*$/.test(url) ? url : null, cover] 13 | ); 14 | 15 | ctx.body = { 16 | success: !!result?.affectedRows, 17 | message: "添加成功", 18 | }; 19 | } catch (error) { 20 | console.log(error); 21 | ctx.body = { 22 | success: false, 23 | error: error.message, 24 | message: "添加失败", 25 | }; 26 | } 27 | }); 28 | 29 | module.exports = router; 30 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/notice/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.delete("/notice/:id", auth(), async ctx => { 7 | try { 8 | const noticeId = ctx.params.id; 9 | 10 | // 删除 notice_history 记录 11 | await db.query(`DELETE FROM notice_history WHERE notice_id = ${noticeId}`); 12 | 13 | // 删除 notice 记录 14 | await db.query(`DELETE FROM notice WHERE id = ${noticeId}`); 15 | 16 | ctx.body = { 17 | success: true, 18 | message: "公告删除成功", 19 | }; 20 | } catch (error) { 21 | console.error(error); 22 | ctx.body = { 23 | success: false, 24 | message: "公告删除失败", 25 | error: error.message, 26 | }; 27 | } 28 | }); 29 | 30 | module.exports = router; 31 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/store/create.vue: -------------------------------------------------------------------------------- 1 | 6 | 30 | 31 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const id = require("@/utils/id"); 5 | const router = new Router(); 6 | 7 | router.post("/store", auth(), async ctx => { 8 | try { 9 | const { email, cover_pic, name, address } = ctx.request.body; 10 | 11 | const result = await db.query( 12 | `INSERT INTO chain_store (id,email,cover_pic, name, address, create_time,password) VALUES (?, ?, ?, ?, ?, NOW(),?)`, 13 | [id(), email, cover_pic, name, address, email] 14 | ); 15 | 16 | ctx.body = { 17 | success: !!result[0]?.affectedRows, 18 | }; 19 | } catch (error) { 20 | console.log(error); 21 | ctx.body = { success: false, error: error.message }; 22 | } 23 | }); 24 | 25 | module.exports = router; 26 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/upload.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | let multer = require("@koa/multer"); 3 | let fs = require("fs"); 4 | let { v4 } = require("uuid"); 5 | let router = new Router(); 6 | 7 | let uploadOption = multer({ 8 | storage: multer.memoryStorage(), 9 | limits: { 10 | files: 1, 11 | fileSize: 1024 * 1024 * 10, //5MB 12 | }, 13 | }); 14 | router.post("/static", uploadOption.single("image"), async ctx => { 15 | try { 16 | let buffer = ctx.file.buffer; 17 | let fileName = `${v4().replace(/-/g, "")}.${ctx.file.originalname.split(".").slice(-1)[0]}`; 18 | fs.writeFileSync(`public/${fileName}`, buffer); 19 | ctx.body = { success: true, message: "上传成功", data: fileName }; 20 | } catch (error) { 21 | ctx.body = { success: false, message: "上传错误" }; 22 | } 23 | }); 24 | module.exports = router; 25 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/article/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 30 | 31 | -------------------------------------------------------------------------------- /项目代码/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "dev": "nodemon ./src/index.js" 8 | }, 9 | "dependencies": { 10 | "@koa/cors": "^4.0.0", 11 | "@koa/multer": "^3.0.2", 12 | "axios": "^1.6.5", 13 | "cheerio": "^1.0.0-rc.10", 14 | "cookie": "^0.6.0", 15 | "cross-env": "^7.0.3", 16 | "jsonwebtoken": "^8.5.1", 17 | "koa": "^2.13.4", 18 | "koa-bodyparser": "^4.4.1", 19 | "koa-router": "^10.1.1", 20 | "koa-static": "^5.0.0", 21 | "lru-cache": "^7.10.1", 22 | "module-alias": "^2.2.2", 23 | "moment": "^2.29.1", 24 | "morgan": "^1.10.0", 25 | "multer": "^1.4.4", 26 | "mysql2": "^3.6.2", 27 | "nodemailer": "^6.9.8", 28 | "nodemon": "^2.0.14", 29 | "socket.io": "^4.7.4", 30 | "uuid": "^9.0.1" 31 | }, 32 | "devDependencies": {} 33 | } 34 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/info.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/reservation/info", auth(), async ctx => { 7 | 8 | try { 9 | // 查询用户的预约信息 10 | const [result] = await db.query( 11 | `SELECT COUNT(*) AS count FROM reservation WHERE user_id = ? AND (state = 1 OR state = 2) AND time < NOW()`, 12 | [ctx.id] 13 | ); 14 | const hasActiveReservation = result?.[0]?.count > 0; 15 | 16 | ctx.body = { 17 | success: true, 18 | data: hasActiveReservation, 19 | message: `false是没有预约,true是有预约`, 20 | }; 21 | } catch (error) { 22 | console.error(error); 23 | ctx.body = { 24 | success: false, 25 | message: "获取信息失败", 26 | error: error.message, 27 | }; 28 | } 29 | }); 30 | 31 | module.exports = router; 32 | -------------------------------------------------------------------------------- /项目代码/admin/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | import { createRouter, createWebHistory, createWebHashHistory } from "vue-router"; 4 | 5 | import "@/style/index.scss"; 6 | import "@/plugin/axios"; 7 | import { createPinia } from "pinia"; 8 | import Vant from "vant"; 9 | import "vant/lib/index.css"; 10 | import "moment/dist/locale/zh-cn"; 11 | const app = createApp(App); 12 | 13 | import ElementPlus from "element-plus"; 14 | import "element-plus/dist/index.css"; 15 | 16 | import axios from "axios"; 17 | axios.defaults.baseURL = "http://localhost:3000"; 18 | 19 | import { setupLayouts } from "virtual:generated-layouts"; 20 | import pages from "~pages"; 21 | 22 | const routes = setupLayouts(pages); 23 | const router = createRouter({ 24 | history: createWebHashHistory(), 25 | routes, 26 | }); 27 | 28 | app.use(router).use(createPinia()).use(Vant).use(ElementPlus).mount("#app"); 29 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/list-store.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/article/store/:id", async ctx => { 6 | const [result] = await db.query( 7 | `SELECT 8 | * 9 | FROM 10 | article where store_id=? and state=1; 11 | `, 12 | [ctx.params.id] 13 | ); 14 | const [commodity] = await db.query( 15 | `SELECT 16 | * 17 | FROM 18 | commodity where store_id=? ; 19 | `, 20 | [ctx.params.id] 21 | ); 22 | 23 | for (let index = 0; index < result.length; index++) { 24 | let item = result[index]; 25 | if (item?.commodity_id) { 26 | result[index].commodity_data = commodity.find( 27 | item => item.id == result[index]["commodity_id"] 28 | ); 29 | } 30 | } 31 | 32 | ctx.body = { 33 | success: true, 34 | data: result, 35 | }; 36 | }); 37 | 38 | module.exports = router; 39 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/comment/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const id = require("@/utils/id"); 5 | const router = new Router(); 6 | 7 | router.post("/comment", auth(), async ctx => { 8 | try { 9 | const { content, article_id, reply } = ctx.request.body; 10 | 11 | // 插入评论到数据库 12 | const result = await db.query( 13 | `INSERT INTO comment (id, content, user_id, article_id,reply, create_time) VALUES (?, ?, ?, ?,?, NOW())`, 14 | [id(), content, ctx.id, +article_id, reply] 15 | ); 16 | 17 | ctx.body = { 18 | success: !!result[0]?.affectedRows, 19 | message: "评论成功", 20 | }; 21 | } catch (error) { 22 | console.error(error); 23 | ctx.body = { 24 | success: false, 25 | message: "评论失败", 26 | error: error.message, 27 | }; 28 | } 29 | }); 30 | 31 | module.exports = router; 32 | -------------------------------------------------------------------------------- /项目代码/server/src/index.js: -------------------------------------------------------------------------------- 1 | // 变量别名 2 | const moduleAlias = require("module-alias"); 3 | moduleAlias.addAlias("@", __dirname); 4 | let Koa = require("koa"); 5 | const app = new Koa(); 6 | let staticFiles = require("koa-static"); 7 | let Body = require("koa-bodyparser"); 8 | let cors = require("@koa/cors"); 9 | app.use(staticFiles("public")); 10 | app.use(cors()); 11 | app.use(Body()); 12 | 13 | let getAllRouter = require("@/modules/getAllRouter"); 14 | (async () => { 15 | // console.log((await getAllRouter()).length); 16 | (await getAllRouter()).forEach(item => { 17 | app.use(require(item).routes()); 18 | }); 19 | })(); 20 | 21 | const port = 3000; 22 | 23 | const http = require("http"); 24 | const server = http.createServer(app.callback()); //包装app保证http和socket监听同一端口 25 | module.exports = { 26 | server, 27 | }; 28 | require("@/socket/index"); 29 | 30 | server.listen(port, function () { 31 | console.log(`项目运行于: ${port} 端口`); 32 | }); 33 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | const id = require("@/utils/id"); 5 | const auth = require("@/modules/auth"); 6 | 7 | router.post("/article", auth(), async ctx => { 8 | try { 9 | const { title, content, commodity_id, cover } = ctx.request.body; 10 | 11 | const [result] = await db.query( 12 | `INSERT INTO article (id, title, content, commodity_id, cover,store_id, create_time) VALUES (?, ?, ?, ?, ?,?, NOW())`, 13 | [id(), title, content, commodity_id, JSON.stringify(cover),ctx.id] 14 | ); 15 | 16 | ctx.body = { 17 | success: !!result?.affectedRows, 18 | message: "发布成功", 19 | }; 20 | } catch (error) { 21 | console.error(error); 22 | ctx.body = { 23 | success: false, 24 | error: error.message, 25 | message: "发布失败", 26 | }; 27 | } 28 | }); 29 | 30 | module.exports = router; 31 | -------------------------------------------------------------------------------- /项目代码/admin/src/hooks/useFetch.js: -------------------------------------------------------------------------------- 1 | import { ref, reactive, watchEffect } from "vue"; 2 | import axios from "axios"; 3 | 4 | function useFetch(url, options = { method: "get" }, manual = false) { 5 | const data = ref(null); 6 | const error = ref(null); 7 | const isLoading = ref(!manual); 8 | 9 | const fetchData = async () => { 10 | isLoading.value = true; 11 | 12 | try { 13 | const response = await axios({ 14 | url, 15 | ...options, 16 | }); 17 | data.value = response.data; 18 | } catch (error) { 19 | error.value = error; 20 | } finally { 21 | isLoading.value = false; 22 | } 23 | }; 24 | 25 | if (!manual) { 26 | watchEffect(() => { 27 | fetchData(); 28 | }); 29 | } 30 | 31 | const refetch = () => { 32 | fetchData(); 33 | }; 34 | 35 | return { 36 | data, 37 | error, 38 | isLoading, 39 | refetch, 40 | }; 41 | } 42 | 43 | export default useFetch; 44 | -------------------------------------------------------------------------------- /项目代码/server/src/modules/getAllRouter.js: -------------------------------------------------------------------------------- 1 | const fs=require('fs') 2 | const path = require("path"); 3 | 4 | async function fileDisplay(filePath) { 5 | let fileList = []; 6 | function _fileDisplay(filePath) { 7 | let files = fs.readdirSync(filePath); 8 | for (let index = 0; index < files.length; index++) { 9 | let filename = files[index]; 10 | let filedir = path.join(filePath, filename); //拼接路径用于app.use 11 | let stats = fs.statSync(filedir); 12 | let isFile = stats.isFile(); 13 | let isDir = stats.isDirectory(); 14 | if (isFile) { 15 | fileList.push(filedir); 16 | } 17 | if (isDir) { 18 | _fileDisplay(filedir); 19 | } 20 | } 21 | } 22 | _fileDisplay(filePath); 23 | return fileList; 24 | } 25 | let src = path.join(__dirname, "../routes"); 26 | async function getAllRouter() { 27 | let fileList = await fileDisplay(src); 28 | return fileList; 29 | } 30 | module.exports = getAllRouter; 31 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.put("/article/:id", async ctx => { 6 | const articleId = ctx.params.id; 7 | const { title, content, commodity_id, cover } = ctx.request.body; 8 | console.log(title, content, commodity_id, cover); 9 | 10 | try { 11 | const [result] = await db.query( 12 | "UPDATE article SET title = ?, content = ?, commodity_id = ?, cover = ? WHERE id = ? ", 13 | [title, content, commodity_id, JSON.stringify(cover), +articleId] 14 | ); 15 | 16 | ctx.body = { 17 | success: !!result?.affectedRows, 18 | message: result?.affectedRows ? "文章修改成功" : "文章不存在或已被删除", 19 | }; 20 | } catch (error) { 21 | console.log(error); 22 | ctx.body = { 23 | success: false, 24 | error: error.message, 25 | message: "文章修改失败", 26 | }; 27 | } 28 | }); 29 | 30 | module.exports = router; 31 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/message/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | 5 | const router = new Router(); 6 | 7 | router.get("/message", auth(), async ctx => { 8 | try { 9 | const { store_id, user_id } = ctx.query; 10 | const [messages] = await db.query( 11 | ` 12 | SELECT m.*, u.name AS user_name, s.name AS store_name,s.cover_pic AS store_cover,u.avatar AS user_avatar 13 | FROM message m 14 | LEFT JOIN user u ON m.user_id = u.id 15 | LEFT JOIN chain_store s ON m.store_id = s.id 16 | WHERE m.store_id = ? AND m.user_id = ? 17 | ORDER BY m.create_time DESC 18 | `, 19 | [store_id || ctx.id, user_id || ctx.id] 20 | ); 21 | 22 | ctx.body = { success: false, data: messages }; 23 | } catch (error) { 24 | console.error(error); 25 | ctx.body = { success: false, data: [] }; 26 | } 27 | }); 28 | 29 | module.exports = router; 30 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/commodity/create/[id].vue: -------------------------------------------------------------------------------- 1 | 10 | 30 | 31 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/note-update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const id = require("@/utils/id"); 4 | const router = new Router(); 5 | 6 | router.put("/reservation/:id/note", async ctx => { 7 | try { 8 | const { id: reservationId } = ctx.params; 9 | const { notes } = ctx.request.body; 10 | 11 | const result = await db.query(`UPDATE reservation SET notes = ? WHERE id = ? `, [ 12 | notes, 13 | reservationId, 14 | ]); 15 | 16 | if (result[0]?.affectedRows > 0) { 17 | ctx.body = { 18 | success: true, 19 | message: "更新预约备注成功", 20 | }; 21 | } else { 22 | ctx.body = { 23 | success: false, 24 | message: "未找到匹配的预约记录或无权限更新", 25 | }; 26 | } 27 | } catch (error) { 28 | ctx.body = { 29 | success: false, 30 | message: "更新预约备注失败", 31 | error: error.message, 32 | }; 33 | } 34 | }); 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const id = require("@/utils/id"); 5 | const router = new Router(); 6 | 7 | router.post("/reservation", auth(), async ctx => { 8 | try { 9 | const { store_id, notes, commodity_id, time } = ctx.request.body; 10 | 11 | // 插入预约到数据库 12 | const result = await db.query( 13 | `INSERT INTO reservation (id, user_id, store_id, notes, commodity_id, time, create_time, state) VALUES (?, ?, ?, ?, ?, ?, NOW(), 2)`, 14 | [id(), ctx.id, store_id, notes, commodity_id, time] 15 | ); 16 | 17 | ctx.body = { 18 | success: !!result[0]?.affectedRows, 19 | message: "预约成功", 20 | }; 21 | } catch (error) { 22 | console.error(error); 23 | ctx.body = { 24 | success: false, 25 | message: "预约失败", 26 | error: error.message, 27 | }; 28 | } 29 | }); 30 | 31 | module.exports = router; 32 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/refuse.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const id = require("@/utils/id"); 4 | const router = new Router(); 5 | 6 | router.put("/reservation/:id/refuse", async ctx => { 7 | try { 8 | const { id: reservationId } = ctx.params; 9 | const { reply } = ctx.request.body; 10 | 11 | const result = await db.query(`UPDATE reservation SET reply = ?, state = 0 WHERE id = ?`, [ 12 | reply, 13 | reservationId, 14 | ]); 15 | 16 | if (result[0]?.affectedRows > 0) { 17 | ctx.body = { 18 | success: true, 19 | message: "更新预约备注成功", 20 | }; 21 | } else { 22 | ctx.body = { 23 | success: false, 24 | message: "未找到匹配的预约记录或无权限更新", 25 | }; 26 | } 27 | } catch (error) { 28 | ctx.body = { 29 | success: false, 30 | message: "更新预约备注失败", 31 | error: error.message, 32 | }; 33 | } 34 | }); 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/recommend-index.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | function padData(data) { 6 | const maxLength = 4; 7 | const paddedData = [...data]; 8 | 9 | while (paddedData.length < maxLength) { 10 | paddedData.push(null); 11 | } 12 | 13 | return paddedData; 14 | } 15 | 16 | router.get("/commodity/recommend/index", auth(), async ctx => { 17 | try { 18 | const [result] = await db.query( 19 | ` 20 | SELECT * FROM commodity WHERE state=1; 21 | ` 22 | ); 23 | 24 | ctx.body = { 25 | success: true, 26 | data: padData(result).slice(0,4), 27 | }; 28 | } catch (error) { 29 | console.error(error); 30 | ctx.body = { 31 | success: false, 32 | message: "查询失败", 33 | error: error.message, 34 | }; 35 | } 36 | }); 37 | 38 | module.exports = router; 39 | 40 | module.exports = router; 41 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/store/auth/sign.js: -------------------------------------------------------------------------------- 1 | let Router = require("koa-router"); 2 | const sign = require("@/modules/signToken"); 3 | let db = require("@/db"); 4 | let router = new Router(); 5 | 6 | router.post("/store/sign", async ctx => { 7 | try { 8 | let [res] = await db.query( 9 | `select * from chain_store where email=? and password=? and state=1`, 10 | [ctx.request.body.email, ctx.request.body.password] 11 | ); 12 | 13 | if (!res.length) { 14 | ctx.body = { 15 | success: false, 16 | message: "账号或密码错误", 17 | }; 18 | return; 19 | } 20 | ctx.body = { 21 | success: !!res.length, 22 | data: { id: res[0]?.id, username: res[0]?.name, state: res[0]?.state }, 23 | message: "登录成功", 24 | token: sign({ id: res[0]?.id, username: res[0]?.name, type: "store" }), 25 | }; 26 | } catch (error) { 27 | console.log(error); 28 | ctx.body = { success: false, message: "登录失败" }; 29 | } 30 | }); 31 | module.exports = router; 32 | -------------------------------------------------------------------------------- /项目代码/server/src/modules/auth.js: -------------------------------------------------------------------------------- 1 | let jwt = require("jsonwebtoken"); 2 | 3 | async function verify(token) { 4 | return new Promise((resolve, reject) => { 5 | jwt.verify(token, "key", async function (err, decoded) { 6 | if (err) { 7 | reject(); 8 | } else { 9 | resolve(decoded); 10 | } 11 | }); 12 | }); 13 | } 14 | 15 | function auth(isAdmin) { 16 | return async (ctx, next) => { 17 | let token = ctx.headers.authorization; 18 | if (!token) { 19 | ctx.status = 401; 20 | return; 21 | } 22 | 23 | await verify(token) 24 | .then(async decoded => { 25 | if (isAdmin && decoded.type != "admin") { 26 | ctx.status = 401; 27 | } else { 28 | ctx.id = decoded.id; 29 | ctx.auth = decoded.type; 30 | ctx.username = decoded.username; 31 | await next(); 32 | } 33 | }) 34 | .catch(err => { 35 | ctx.status = 401; 36 | }); 37 | }; 38 | } 39 | module.exports = auth; 40 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/commodity", auth(), async ctx => { 7 | try { 8 | let query = `SELECT * FROM commodity WHERE 1=1`; 9 | 10 | // 如果是 store,要求 store_id 是 ctx.id 11 | if (ctx.auth === "store" || ctx.query.store_id) { 12 | query += ` AND store_id = ${ctx.query.store_id || ctx.id}`; 13 | } 14 | 15 | // 如果存在 ctx.query.state,要求 state 是 ctx.query.state 16 | if (ctx.query.state !== undefined) { 17 | query += ` AND state = ${ctx.query.state}`; 18 | } 19 | 20 | // 执行数据库查询 21 | const [result] = await db.query(query); 22 | 23 | ctx.body = { 24 | success: true, 25 | data: result, 26 | }; 27 | } catch (error) { 28 | console.log(error); 29 | ctx.body = { 30 | success: false, 31 | error: error.message, 32 | message: "查询失败", 33 | }; 34 | } 35 | }); 36 | 37 | module.exports = router; 38 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/message/list-store.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | 5 | const router = new Router(); 6 | 7 | // 店铺聊天页面左侧栏信息 8 | router.get("/message/store/list", auth(), async ctx => { 9 | try { 10 | const [messages] = await db.query( 11 | ` 12 | SELECT m.*, u.name AS user_name, s.name AS store_name,s.cover_pic AS store_cover,u.avatar AS user_avatar 13 | FROM message m 14 | LEFT JOIN user u ON m.user_id = u.id 15 | LEFT JOIN chain_store s ON m.store_id = s.id 16 | WHERE m.store_id = ? 17 | ORDER BY m.create_time DESC 18 | `, 19 | [ctx.id] 20 | ); 21 | let list = []; 22 | messages.forEach(item => { 23 | if (!list.some(el => el.user_id == item.user_id)) { 24 | list.push(item); 25 | } 26 | }); 27 | 28 | ctx.body = { success: true, data: list }; 29 | } catch (error) { 30 | console.error(error); 31 | ctx.body = { success: false, data: [] }; 32 | } 33 | }); 34 | 35 | module.exports = router; 36 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/message/list-user.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | 5 | const router = new Router(); 6 | 7 | // 用户聊天页面列表 8 | router.get("/message/user/list", auth(), async ctx => { 9 | try { 10 | const [messages] = await db.query( 11 | ` 12 | SELECT m.*, u.name AS user_name, s.name AS store_name,s.cover_pic AS store_cover,u.avatar AS user_avatar 13 | FROM message m 14 | LEFT JOIN user u ON m.user_id = u.id 15 | LEFT JOIN chain_store s ON m.store_id = s.id 16 | WHERE m.user_id = ? 17 | ORDER BY m.create_time DESC 18 | `, 19 | [ctx.id] 20 | ); 21 | let list = []; 22 | messages.forEach(item => { 23 | if (!list.some(el => el.store_id == item.store_id)) { 24 | list.push(item); 25 | } 26 | }); 27 | 28 | ctx.body = { success: true, data: list }; 29 | } catch (error) { 30 | console.error(error); 31 | ctx.body = { success: false, data: [] }; 32 | } 33 | }); 34 | 35 | module.exports = router; 36 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/sign-up.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | const id = require("@/utils/id"); 5 | 6 | router.post("/user", async ctx => { 7 | try { 8 | const { name, email, password, avatar } = ctx.request.body; 9 | 10 | const [repeat] = await db.query(`select count(id) from user where email=?`, [email]); 11 | if (repeat[0]["count(id)"]) { 12 | ctx.body = { 13 | success: false, 14 | message: "已有重复邮箱", 15 | }; 16 | return; 17 | } 18 | 19 | const result = await db.query( 20 | `INSERT INTO user (id,name, email, password,avatar, create_time) VALUES (?, ?, ?,?,?, NOW())`, 21 | [id(), name, email, password, avatar] 22 | ); 23 | 24 | ctx.body = { 25 | success: !!result[0]?.affectedRows, 26 | message: "注册成功", 27 | }; 28 | } catch (error) { 29 | console.log(error); 30 | ctx.body = { 31 | success: false, 32 | error: error.message, 33 | message: "注册失败", 34 | }; 35 | } 36 | }); 37 | 38 | module.exports = router; 39 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/detail.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/article/:id", async ctx => { 6 | const [article] = await db.query( 7 | `SELECT 8 | * 9 | FROM 10 | article where id=? and state=1; 11 | `, 12 | [ctx.params.id] 13 | ); 14 | 15 | if (!!article.length) { 16 | const [store] = await db.query( 17 | `SELECT 18 | cover_pic,id,name 19 | FROM 20 | chain_store where id=?; 21 | `, 22 | [article[0].store_id] 23 | ); 24 | if (store.length) { 25 | article[0].store_data = store[0]; 26 | } 27 | 28 | if (article[0].commodity_id) { 29 | const [commodity] = await db.query( 30 | `SELECT 31 | * 32 | FROM 33 | commodity where id=?; 34 | `, 35 | [article[0].commodity_id] 36 | ); 37 | if (commodity.length) { 38 | article[0].commodity_data = commodity[0]; 39 | } 40 | } 41 | } 42 | 43 | ctx.body = { 44 | success: !!article.length, 45 | data: article[0], 46 | }; 47 | }); 48 | 49 | module.exports = router; 50 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/article", async ctx => { 6 | try { 7 | const [result] = await db.query( 8 | `SELECT 9 | a.id AS article_id, 10 | a.title, 11 | a.content, 12 | a.cover, 13 | a.create_time AS article_create_time, 14 | a.state AS article_state, 15 | s.id AS store_id, 16 | s.name AS store_name, 17 | COUNT(c.id) AS comment_count 18 | FROM 19 | article a 20 | JOIN 21 | chain_store s ON a.store_id = s.id 22 | LEFT JOIN 23 | comment c ON a.id = c.article_id 24 | WHERE 25 | a.state = 1 26 | GROUP BY 27 | a.id 28 | ORDER BY 29 | a.create_time DESC; 30 | ` 31 | ); 32 | 33 | ctx.body = { 34 | success: true, 35 | data: result, 36 | message: "查询文章列表", 37 | }; 38 | } catch (error) { 39 | console.log(error); 40 | ctx.body = { 41 | success: false, 42 | error: error.message, 43 | message: "查询文章列表错误", 44 | }; 45 | } 46 | }); 47 | 48 | module.exports = router; 49 | -------------------------------------------------------------------------------- /项目代码/admin/src/layouts/client.vue: -------------------------------------------------------------------------------- 1 | 9 | 47 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/VantUpload.vue: -------------------------------------------------------------------------------- 1 | 9 | 43 | 44 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/commodity/[id].vue: -------------------------------------------------------------------------------- 1 | 14 | 34 | 35 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/warehouse_list/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/warehouse-list/:id", auth(), async ctx => { 7 | try { 8 | const warehouseListId = ctx.params.id; 9 | const { name, description, cover, banner, price, market_time, configuration } = 10 | ctx.request.body; 11 | 12 | // 进行数据库更新操作,注意根据实际情况拼接 SQL 语句 13 | const result = await db.query( 14 | `UPDATE warehouse_list SET name=?, description=?, cover=?, banner=?, price=?, market_time=? ,configuration=? WHERE id=?`, 15 | [ 16 | name, 17 | description, 18 | cover, 19 | JSON.stringify(banner), 20 | price, 21 | market_time, 22 | JSON.stringify(configuration), 23 | warehouseListId, 24 | ] 25 | ); 26 | 27 | ctx.body = { 28 | success: !!result[0]?.affectedRows, 29 | message: "更新成功", 30 | }; 31 | } catch (error) { 32 | console.log(error); 33 | ctx.body = { success: false, error: error.message, message: "更新失败" }; 34 | } 35 | }); 36 | 37 | module.exports = router; 38 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/list-client-store.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/article/store/list/:id", async ctx => { 6 | try { 7 | const [result] = await db.query( 8 | `SELECT 9 | a.id AS article_id, 10 | a.title, 11 | a.content, 12 | a.cover, 13 | a.create_time AS article_create_time, 14 | a.state AS article_state, 15 | s.id AS store_id, 16 | s.name AS store_name, 17 | COUNT(c.id) AS comment_count 18 | FROM 19 | article a 20 | JOIN 21 | chain_store s ON a.store_id = s.id 22 | LEFT JOIN 23 | comment c ON a.id = c.article_id 24 | WHERE 25 | a.state = 1 and store_id=? 26 | GROUP BY 27 | a.id 28 | ORDER BY 29 | a.create_time DESC; 30 | `, 31 | [ctx.params.id] 32 | ); 33 | 34 | ctx.body = { 35 | success: true, 36 | data: result, 37 | message: "客户端查询店铺下的文章", 38 | }; 39 | } catch (error) { 40 | console.log(error); 41 | ctx.body = { 42 | success: false, 43 | error: error.message, 44 | message: "查询文章列表错误", 45 | }; 46 | } 47 | }); 48 | 49 | module.exports = router; 50 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/list-commodity.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | 5 | router.get("/article/commodity/:id", async ctx => { 6 | try { 7 | const [result] = await db.query( 8 | `SELECT 9 | a.id AS article_id, 10 | a.title, 11 | a.content, 12 | a.cover, 13 | a.create_time AS article_create_time, 14 | a.state AS article_state, 15 | s.id AS store_id, 16 | s.name AS store_name, 17 | COUNT(c.id) AS comment_count 18 | FROM 19 | article a 20 | JOIN 21 | chain_store s ON a.store_id = s.id 22 | LEFT JOIN 23 | comment c ON a.id = c.article_id 24 | WHERE 25 | a.state = 1 and commodity_id=? 26 | GROUP BY 27 | a.id 28 | ORDER BY 29 | a.create_time DESC; 30 | `, 31 | [ctx.params.id] 32 | ); 33 | 34 | ctx.body = { 35 | success: true, 36 | data: result, 37 | message: "查询讲解对应车辆的文章列表", 38 | }; 39 | } catch (error) { 40 | console.log(error); 41 | ctx.body = { 42 | success: false, 43 | error: error.message, 44 | message: "查询文章列表错误", 45 | }; 46 | } 47 | }); 48 | 49 | module.exports = router; 50 | -------------------------------------------------------------------------------- /项目代码/admin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "site", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@vueuse/head": "^1.0.22", 13 | "@wangeditor/editor": "^5.1.23", 14 | "@wangeditor/editor-for-vue": "^5.1.12", 15 | "axios": "^1.2.1", 16 | "copy-to-clipboard": "^3.3.3", 17 | "echarts": "^5.4.3", 18 | "element-plus": "^2.4.1", 19 | "js-cookie": "^3.0.5", 20 | "moment": "^2.30.1", 21 | "pinia": "^2.0.28", 22 | "socket.io-client": "^4.7.4", 23 | "unplugin-auto-import": "^0.17.3", 24 | "vant": "^4.5.0", 25 | "vue": "^3.2.45", 26 | "vue-countup-v3": "^1.4.1", 27 | "vue-router": "^4.1.6", 28 | "vue-waterfall-plugin-next": "^2.3.1" 29 | }, 30 | "devDependencies": { 31 | "@types/node": "^18.11.17", 32 | "@vitejs/plugin-vue": "^4.0.0", 33 | "cssnano": "^5.1.14", 34 | "postcss": "^8.4.20", 35 | "sass": "^1.57.1", 36 | "tailwindcss": "3.3.2", 37 | "vite": "^4.0.0", 38 | "vite-plugin-pages": "^0.32.0", 39 | "vite-plugin-vue-layouts": "^0.11.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/commodity/[id].vue: -------------------------------------------------------------------------------- 1 | 14 | 36 | 37 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/comment/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.delete("/comment/:id", auth(), async ctx => { 7 | try { 8 | const id = ctx.params.id; 9 | 10 | let IDList = [+id]; //被删除的ID数组 11 | async function fun(id) { 12 | const [result] = await db.query(`select id from comment where reply=?`, [id]); 13 | if (result.length) { 14 | for (let index = 0; index < result.length; index++) { 15 | const item = result[index]; 16 | IDList.push(item.id); 17 | await fun(item.id); 18 | } 19 | } 20 | } 21 | await fun(id); 22 | const [result] = await db.query( 23 | ` 24 | DELETE FROM comment 25 | WHERE id IN (?); 26 | `, 27 | [IDList] 28 | ); 29 | ctx.body = { 30 | success: !!result?.affectedRows, 31 | message: !!result?.affectedRows ? "删除成功" : "删除", 32 | }; 33 | } catch (error) { 34 | console.error(error); 35 | ctx.body = { 36 | success: false, 37 | message: "删除失败", 38 | error: error.message, 39 | }; 40 | } 41 | }); 42 | 43 | module.exports = router; 44 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/tools/location.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const axios = require("axios"); 3 | 4 | function getClientIP(req) { 5 | let ip = 6 | req.headers["x-forwarded-for"] || 7 | req.ip || 8 | req.connection.remoteAddress || 9 | req.socket.remoteAddress || 10 | req.connection.socket.remoteAddress || 11 | ""; 12 | if (ip) { 13 | ip = ip.replace("::ffff:", ""); 14 | } 15 | return ip; 16 | } 17 | 18 | let router = new Router(); 19 | 20 | router.get("/location", async ctx => { 21 | try { 22 | const response = await axios.get("https://api.map.baidu.com/location/ip", { 23 | params: { 24 | coor: "bd09ll", 25 | ak: `E1xIzplbXNHbqehCW36mGK5oiDPec4Mq`, 26 | ip: getClientIP(ctx.req), 27 | }, 28 | }); 29 | const address_detail = response.data?.content?.address_detail; 30 | 31 | ctx.body = { 32 | success: true, 33 | message: "查询成功", 34 | data: { city: address_detail.city || null, province: address_detail.province || null }, 35 | }; 36 | } catch (error) { 37 | ctx.body = { 38 | success: true, 39 | message: "查询成功", 40 | data: { city: "大连市", province: "辽宁省" }, 41 | }; 42 | } 43 | }); 44 | 45 | module.exports = router; 46 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/notice/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); // 假设有一个 db 模块用于执行数据库操作 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | const id = require("@/utils/id"); 6 | 7 | router.post("/notice", auth(), async ctx => { 8 | try { 9 | const { title, target, content, isTop } = ctx.request.body; 10 | 11 | // 检查参数是否完整 12 | if (!title || !target || !content) { 13 | ctx.body = { 14 | success: false, 15 | message: "参数不完整", 16 | }; 17 | return; 18 | } 19 | 20 | // 在数据库中插入通知记录 21 | const insertNoticeQuery = ` 22 | INSERT INTO notice (id,title, target, content, isTop, create_time) 23 | VALUES (?,?, ?, ?, ?, NOW()) 24 | `; 25 | const [insertResult] = await db.query(insertNoticeQuery, [ 26 | id(), 27 | title, 28 | JSON.stringify(target), 29 | content, 30 | isTop, 31 | ]); 32 | 33 | ctx.body = { 34 | success: true, 35 | message: "通知添加成功", 36 | }; 37 | } catch (error) { 38 | console.error(error); 39 | ctx.body = { 40 | success: false, 41 | message: "通知添加失败", 42 | error: error.message, 43 | }; 44 | } 45 | }); 46 | 47 | module.exports = router; 48 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/tools/data.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | 4 | let router = new Router(); 5 | 6 | router.get("/statistics", async ctx => { 7 | const [totalStores] = await db.query("SELECT COUNT(*) AS totalStores FROM chain_store"); 8 | const [totalUsers] = await db.query("SELECT COUNT(*) AS totalUsers FROM user"); 9 | const [totalWarehouses] = await db.query( 10 | "SELECT COUNT(*) AS totalWarehouses FROM warehouse_list" 11 | ); 12 | const [totalOrders] = await db.query("SELECT COUNT(*) AS totalOrders FROM orders"); 13 | 14 | const [ordersLast7Days] = await db.query(` 15 | SELECT 16 | DATE(create_time) AS orderDate, 17 | COUNT(*) AS orderCount 18 | FROM 19 | orders 20 | WHERE 21 | create_time >= NOW() - INTERVAL 7 DAY 22 | GROUP BY 23 | orderDate 24 | ORDER BY 25 | orderDate 26 | `); 27 | 28 | ctx.body = { 29 | success: true, 30 | data: { 31 | totalStores: totalStores[0].totalStores, 32 | totalUsers: totalUsers[0].totalUsers, 33 | totalWarehouses: totalWarehouses[0].totalWarehouses, 34 | totalOrders: totalOrders[0].totalOrders, 35 | ordersLast7Days, 36 | }, 37 | }; 38 | }); 39 | 40 | module.exports = router; 41 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/collection/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const id = require("@/utils/id"); 5 | const router = new Router(); 6 | 7 | router.post("/collection", auth(), async ctx => { 8 | try { 9 | const { item_id, type } = ctx.request.body; 10 | 11 | // 检查是否已经收藏 12 | const existingCollection = await db.query( 13 | "SELECT id FROM collection WHERE user_id = ? AND item_id = ?", 14 | [ctx.id, item_id] 15 | ); 16 | 17 | if (existingCollection[0]?.length > 0) { 18 | ctx.body = { 19 | success: false, 20 | message: "商品已经被收藏过了", 21 | }; 22 | return; 23 | } 24 | 25 | // 插入收藏到数据库 26 | const result = await db.query( 27 | "INSERT INTO collection (id, user_id, item_id,type, create_time) VALUES (?, ?, ?,?, NOW())", 28 | [id(), ctx.id, item_id, type] 29 | ); 30 | 31 | ctx.body = { 32 | success: !!result[0]?.affectedRows, 33 | message: "商品收藏成功", 34 | }; 35 | } catch (error) { 36 | console.error(error); 37 | ctx.body = { 38 | success: false, 39 | message: "商品收藏失败", 40 | error: error.message, 41 | }; 42 | } 43 | }); 44 | 45 | module.exports = router; 46 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/store/[id].vue: -------------------------------------------------------------------------------- 1 | 14 | 40 | 41 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/notice-history/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); // 你的数据库模块 3 | const auth = require("@/modules/auth"); // 你的权限验证模块 4 | const id = require("@/utils/id"); 5 | 6 | const router = new Router(); 7 | 8 | router.post("/notice/history", auth(), async ctx => { 9 | try { 10 | const { id: storeId } = ctx; 11 | const { noticeId } = ctx.request.body; 12 | 13 | const [existingHistory] = await db.query( 14 | "SELECT * FROM notice_history WHERE store_id = ? AND notice_id = ?", 15 | [storeId, noticeId] 16 | ); 17 | 18 | if (existingHistory.length === 0) { 19 | await db.query("INSERT INTO notice_history (id,store_id, notice_id) VALUES (?,?, ?)", [ 20 | id(), 21 | storeId, 22 | noticeId, 23 | ]); 24 | 25 | ctx.body = { 26 | success: true, 27 | message: "成功添加通知历史记录", 28 | }; 29 | } else { 30 | ctx.body = { 31 | success: true, 32 | message: "通知历史记录已存在", 33 | }; 34 | } 35 | } catch (error) { 36 | console.error(error); 37 | ctx.status = 500; 38 | ctx.body = { 39 | success: false, 40 | message: "添加通知历史记录失败", 41 | error: error.message, 42 | }; 43 | } 44 | }); 45 | 46 | module.exports = router; 47 | -------------------------------------------------------------------------------- /项目代码/admin/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | import path from "path"; 4 | import Pages from "vite-plugin-pages"; 5 | import Layouts from "vite-plugin-vue-layouts"; 6 | import AutoImport from "unplugin-auto-import/vite"; 7 | 8 | export default defineConfig({ 9 | resolve: { 10 | alias: { 11 | "@": path.resolve(__dirname, "./src"), 12 | }, 13 | extensions: [".js", ".vue"], 14 | }, 15 | base: "./", 16 | server: { 17 | proxy: {}, 18 | }, 19 | plugins: [ 20 | vue(), 21 | Pages({ 22 | dirs: "src/pages", 23 | extensions: ["vue"], 24 | extendRoute(route) { 25 | if (route.path.startsWith("/admin") && !route.path.includes("sign")) { 26 | route.meta = Object.assign(route.meta || {}, { layout: "admin" }); 27 | } 28 | 29 | if (route.path.startsWith("/store") && !route.path.includes("sign")) { 30 | route.meta = Object.assign(route.meta || {}, { layout: "store" }); 31 | } 32 | 33 | return route; 34 | }, 35 | }), 36 | Layouts(), 37 | AutoImport({ 38 | imports: ["vue", "vue-router", "vuex"], 39 | dts: "src/auto-import.d.ts", 40 | // include: [/\.[tj]sx?$/, /\.vue$/, /\.vue\?vue/], 41 | }), 42 | ], 43 | }); 44 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/article/search.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/article/list/search", async ctx => { 7 | try { 8 | const { keyword } = ctx.query; 9 | 10 | // 使用 LIKE 运算符进行模糊匹配 11 | const result = await db.query( 12 | `SELECT 13 | a.id AS article_id, 14 | a.title, 15 | a.content, 16 | a.cover, 17 | a.create_time AS article_create_time, 18 | a.state AS article_state, 19 | s.id AS store_id, 20 | s.name AS store_name, 21 | COUNT(c.id) AS comment_count 22 | FROM 23 | article a 24 | JOIN 25 | chain_store s ON a.store_id = s.id 26 | LEFT JOIN 27 | comment c ON a.id = c.article_id 28 | WHERE 29 | a.state = 1 30 | AND (a.title LIKE ? OR a.content LIKE ?) 31 | GROUP BY 32 | a.id 33 | ORDER BY 34 | a.create_time DESC;`, 35 | [`%${keyword}%`, `%${keyword}%`] 36 | ); 37 | 38 | ctx.body = { 39 | success: true, 40 | data: result[0], 41 | }; 42 | } catch (error) { 43 | console.error(error); 44 | ctx.body = { 45 | success: false, 46 | message: "搜索失败", 47 | error: error.message, 48 | }; 49 | } 50 | }); 51 | 52 | module.exports = router; 53 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/warehouse_list/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const id = require("@/utils/id"); 5 | const router = new Router(); 6 | 7 | router.post("/warehouse-list", auth(), async ctx => { 8 | try { 9 | const { name, description, cover, banner, price, market_time, configuration } = 10 | ctx.request.body; 11 | 12 | // 设置默认值 13 | const create_time = new Date(); 14 | const state = 1; 15 | 16 | const result = await db.query( 17 | `INSERT INTO warehouse_list (id, name, description, cover, banner, price, market_time, create_time, state, configuration) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 18 | [ 19 | id(), 20 | name, 21 | description, 22 | cover, 23 | JSON.stringify(banner), 24 | price, 25 | market_time, 26 | create_time, 27 | state, 28 | JSON.stringify(configuration), 29 | ] 30 | ); 31 | 32 | ctx.body = { 33 | success: !!result[0]?.affectedRows, 34 | message: "添加成功", 35 | }; 36 | } catch (error) { 37 | console.log(error); 38 | ctx.body = { 39 | success: false, 40 | message: "添加失败", 41 | error: error.message, 42 | }; 43 | } 44 | }); 45 | 46 | module.exports = router; 47 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/commodity/:id", auth(), async ctx => { 7 | try { 8 | const commodityId = ctx.params.id; 9 | const { name, description, cover, banner, price, configuration, inventory } = ctx.request.body; 10 | 11 | // 构建 SQL 更新语句 12 | const updateQuery = ` 13 | UPDATE commodity 14 | SET 15 | name = ?, 16 | description = ?, 17 | cover = ?, 18 | banner = ?, 19 | price = ?, 20 | configuration = ?, 21 | inventory = ? 22 | WHERE id = ? 23 | `; 24 | 25 | // 执行数据库更新操作 26 | const result = await db.query(updateQuery, [ 27 | name, 28 | description, 29 | cover, 30 | JSON.stringify(banner), 31 | price, 32 | JSON.stringify(configuration), 33 | inventory, 34 | commodityId, 35 | ]); 36 | 37 | ctx.body = { 38 | success: !!result[0]?.affectedRows, 39 | message: "更新成功", 40 | }; 41 | } catch (error) { 42 | console.log(error); 43 | ctx.body = { 44 | success: false, 45 | error: error.message, 46 | message: "更新失败", 47 | }; 48 | } 49 | }); 50 | 51 | module.exports = router; 52 | -------------------------------------------------------------------------------- /项目代码/admin/src/layouts/store.vue: -------------------------------------------------------------------------------- 1 | 13 | 54 | -------------------------------------------------------------------------------- /项目代码/admin/src/layouts/admin.vue: -------------------------------------------------------------------------------- 1 | 13 | 55 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/article/[id].vue: -------------------------------------------------------------------------------- 1 | 14 | 44 | 45 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/user/index.vue: -------------------------------------------------------------------------------- 1 | 25 | 35 | 36 | 37 | { 38 | "meta": { 39 | "layout": "client" 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /项目代码/admin/public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 基于 Node.js 的“大维”体育商城的设计与实现 2 | 3 | ## 系统说明 4 | 5 | **系统包含论文 1 篇付费提供** 6 | 7 | ## 功能 8 | 9 | 参照文件夹中的答辩 PPT、开题报告、和毕设手册 10 | 系统内 3 个权限:用户、管理员。主要是门店 用户 管理员共14个数据表,可以使用webscoket在线聊天。 11 | 12 | ![演示视频](./项目代码/图片.png "功能") 13 | 14 | [演示视频](https://disk.blogweb.cn/video/%E5%9F%BA%E4%BA%8EVue%E7%9A%84%E5%8D%93%E5%B0%94%E6%B1%BD%E8%BD%A6%E9%94%80%E5%94%AEWeb%20App%E7%9A%84%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0.mp4 "演示视频") 15 | 16 | ## 相关技术 17 | 18 | 前端:Vue.js、Vite、Tailwind CSS、Element Plus、Vant UI 19 | 服务端:Koa2 20 | 数据库:MySQL 21 | 22 | ## 其他版本 23 | 24 | 付费提供部分其他毕设程序、论文的成品,同时可以定制和讲解毕设,联系下方联系方式即可 25 | 26 | 可联系 QQ:1974109227 微信:webzhizhuo 27 | 28 | ## 联系方式 29 | 30 | 可以开发其他项目、毕业设计、毕业论文等 31 | 32 |
33 | QQ 34 | 微信 35 |
36 | 37 | ### 启动 38 | 39 | #### 环境 40 | 41 | 1. Node.js 20+ 42 | 2. MySQL 8.x 43 | 44 | #### 启动步骤 45 | 46 | 1. 如果项目代码中有 start.bat 则双击执行 47 | 48 | 否则运行以下命令安装 yarn 以及部分插件同时进行换源 49 | 50 | ```bash 51 | npm config set registry https://registry.npmmirror.com/&&npm i yarn vite nodemon -g&&yarn config set registry https://registry.npmmirror.com/ 52 | ``` 53 | 54 | 2. 如果项目代码中有 install.bat 则双击运行否则 55 | 56 | 通常 admin/font 是前端,server/api 是服务端,cd 进入前端或者服务器文件夹,文件夹名称并不固定 57 | 58 | ```bash 59 | cd server 60 | 61 | yarn 62 | ``` 63 | 64 | ```bash 65 | cd admin 66 | 67 | yarn 68 | ``` 69 | 70 | 3. 如果有 dev.bat 则双击运行,否则 cd 进入文件夹都使用`yarn dev`运行 71 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/collection/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/collection", auth(), async ctx => { 7 | try { 8 | const [result] = await db.query( 9 | `SELECT 10 | c.id AS collection_id, 11 | c.item_id, 12 | c.user_id, 13 | c.create_time AS collection_time, 14 | c.type, 15 | s.id AS store_id, 16 | s.name AS store_name, 17 | s.cover_pic AS store_cover, 18 | s.email AS store_email, 19 | s.address AS store_address, 20 | s.create_time AS store_create_time, 21 | c2.id AS commodity_id, 22 | c2.name AS commodity_name, 23 | c2.description AS commodity_description, 24 | c2.cover AS commodity_cover, 25 | c2.banner AS commodity_banner, 26 | c2.price AS commodity_price, 27 | c2.market_time AS commodity_market_time, 28 | c2.create_time AS commodity_create_time 29 | FROM 30 | collection c 31 | LEFT JOIN 32 | chain_store s ON c.item_id = s.id AND c.type = 'store' 33 | LEFT JOIN 34 | commodity c2 ON c.item_id = c2.id AND c.type = 'commodity' 35 | WHERE 36 | c.user_id = ? 37 | ORDER BY 38 | c.create_time DESC; 39 | `, 40 | [ctx.id] 41 | ); 42 | 43 | ctx.body = { 44 | success: true, 45 | data: result, 46 | }; 47 | } catch (error) { 48 | console.error(error); 49 | ctx.body = { 50 | success: false, 51 | message: "查询收藏列表", 52 | error: error.message, 53 | }; 54 | } 55 | }); 56 | 57 | module.exports = router; 58 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/message/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); // Assuming your database module is in './db' 3 | const id = require("@/utils/id"); 4 | const io = require("@/socket/index"); 5 | const auth = require("@/modules/auth"); 6 | 7 | const router = new Router(); 8 | 9 | router.post("/message", auth(), async ctx => { 10 | try { 11 | const { user_id, store_id, content, picture } = ctx.request.body; 12 | 13 | let _id = id(); 14 | const result = await db.query( 15 | "INSERT INTO message (id,user_id, store_id, content, picture,sender, create_time) VALUES (?,?, ?, ?, ?,?, NOW())", 16 | [ 17 | _id, 18 | ctx.auth == "user" ? ctx.id : user_id, 19 | ctx.auth == "store" ? ctx.id : store_id, 20 | picture ? "" : content, 21 | picture || null, 22 | ctx.auth, 23 | ] 24 | ); 25 | 26 | const [insertedMessage] = await db.query( 27 | `SELECT m.*, u.name AS user_name, s.name AS store_name,s.cover_pic AS store_cover,u.avatar AS user_avatar 28 | FROM message m 29 | LEFT JOIN user u ON m.user_id = u.id 30 | LEFT JOIN chain_store s ON m.store_id = s.id 31 | WHERE m.id = ?`, 32 | [_id] 33 | ); 34 | 35 | ctx.body = { success: true, message: "发送成功", data: insertedMessage[0] }; 36 | if (ctx.auth == "user") { 37 | io.to(store_id).emit("message", insertedMessage[0]); 38 | } else { 39 | io.to(user_id).emit("message", insertedMessage[0]); 40 | } 41 | } catch (error) { 42 | console.error(error); 43 | ctx.body = { success: false, message: "发送失败" }; 44 | } 45 | }); 46 | 47 | module.exports = router; 48 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/delete.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.delete("/reservation", auth(), async ctx => { 7 | try { 8 | const { commodity_id } = ctx.request.query; 9 | 10 | // 查询符合条件的预约 11 | const reservations = await db.query( 12 | "SELECT id, state FROM reservation WHERE user_id = ? AND commodity_id = ? AND time > NOW() OR state=1 OR state=2;", 13 | [ctx.id, commodity_id] 14 | ); 15 | 16 | if (reservations[0]?.length === 0) { 17 | ctx.body = { 18 | success: false, 19 | message: "符合条件的预约不存在", 20 | }; 21 | return; 22 | } 23 | 24 | // 取消符合条件的预约 25 | let canceledCount = 0; 26 | for (const reservation of reservations[0]) { 27 | const currentState = reservation.state; 28 | 29 | // 检查是否可以取消 30 | if (currentState !== 1 && currentState !== 2) { 31 | continue; 32 | } 33 | 34 | // 更新预约状态为已取消(3),并且只有状态为1或2的才允许取消 35 | const result = await db.query( 36 | "UPDATE reservation SET state = 3 WHERE id = ? AND (state = 1 OR state = 2)", 37 | [reservation.id] 38 | ); 39 | 40 | canceledCount += result[0]?.affectedRows || 0; 41 | } 42 | 43 | ctx.body = { 44 | success: canceledCount > 0, 45 | message: canceledCount > 0 ? "取消预约成功" : "无符合条件的预约可取消", 46 | }; 47 | } catch (error) { 48 | console.error(error); 49 | ctx.body = { 50 | success: false, 51 | message: "取消预约失败", 52 | error: error.message, 53 | }; 54 | } 55 | }); 56 | 57 | module.exports = router; 58 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/order/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/order", auth(), async ctx => { 7 | try { 8 | const { auth, id } = ctx; 9 | let query = ` 10 | SELECT 11 | o.*, 12 | u.id AS user_id, 13 | u.name AS user_name, 14 | u.avatar AS user_avatar, 15 | c.id AS commodity_id, 16 | c.sample_id AS commodity_sample_id, 17 | c.name AS commodity_name, 18 | s.id AS store_id, 19 | s.name AS store_name, 20 | s.cover_pic AS store_cover 21 | FROM 22 | orders o 23 | LEFT JOIN 24 | user u ON o.user_id = u.id 25 | LEFT JOIN 26 | commodity c ON o.commodity_id = c.id 27 | LEFT JOIN 28 | chain_store s ON o.store_id = s.id 29 | WHERE`; 30 | 31 | if (auth === "user") { 32 | query += ` o.user_id = ${id}`; 33 | } else if (auth === "store") { 34 | query += ` o.store_id = ${id}`; 35 | } else if (auth === "admin") { 36 | query += ` 1=1`; // 占位 37 | } 38 | 39 | if (ctx.query.id) { 40 | query += ` AND o.id = ${ctx.query.id}`; 41 | } 42 | 43 | query += ` ORDER BY o.create_time DESC`; 44 | 45 | const [result] = await db.query(query); 46 | 47 | ctx.body = { 48 | success: true, 49 | data: result, 50 | }; 51 | } catch (error) { 52 | console.error(error); 53 | ctx.body = { 54 | success: false, 55 | message: "订单查询失败", 56 | error: error.message, 57 | }; 58 | } 59 | }); 60 | 61 | module.exports = router; 62 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/update.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.put("/user", auth(), async ctx => { 7 | try { 8 | const { name, email, avatar, password } = ctx.request.body; 9 | 10 | // 构建 SQL 语句 11 | let updateFields = []; 12 | let values = []; 13 | 14 | if (name) { 15 | updateFields.push("name = ?"); 16 | values.push(name); 17 | } 18 | 19 | if (email) { 20 | updateFields.push("email = ?"); 21 | values.push(email); 22 | } 23 | 24 | if (avatar) { 25 | updateFields.push("avatar = ?"); 26 | values.push(avatar); 27 | } 28 | 29 | if (password) { 30 | updateFields.push("password = ?"); 31 | values.push(password); 32 | } 33 | 34 | if (updateFields.length === 0) { 35 | ctx.body = { 36 | success: false, 37 | message: "未提供任何要修改的字段", 38 | }; 39 | return; 40 | } 41 | 42 | const userId = ctx.id; 43 | 44 | const result = await db.query(`UPDATE user SET ${updateFields.join(", ")} WHERE id = ?`, [ 45 | ...values, 46 | userId, 47 | ]); 48 | 49 | if (result[0]?.affectedRows > 0) { 50 | ctx.body = { 51 | success: true, 52 | message: "用户信息修改成功", 53 | }; 54 | } else { 55 | ctx.body = { 56 | success: false, 57 | message: "未找到匹配的用户记录或无权限修改", 58 | }; 59 | } 60 | } catch (error) { 61 | ctx.body = { 62 | success: false, 63 | message: "用户信息修改失败", 64 | error: error.message, 65 | }; 66 | } 67 | }); 68 | 69 | module.exports = router; 70 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/recommend.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/commodity/recommend/list", auth(), async ctx => { 7 | try { 8 | const { province, city } = ctx.query; 9 | 10 | let queryCondition = "WHERE state=1"; 11 | let queryParams = []; 12 | 13 | if (province === "全部") { 14 | // 查询全部连锁店 15 | queryCondition = "WHERE state = 1"; 16 | } else { 17 | // 查询特定省份和城市的连锁店 18 | queryCondition = "WHERE state = 1 AND address LIKE ?"; 19 | queryParams.push(`%${province}%`); 20 | 21 | if (city && city !== "全部") { 22 | queryCondition += " AND address LIKE ?"; 23 | queryParams.push(`%${city}%`); 24 | } 25 | } 26 | 27 | const [result] = await db.query( 28 | ` 29 | SELECT id,name FROM chain_store 30 | ${queryCondition}; 31 | `, 32 | queryParams 33 | ); 34 | 35 | for (let index = 0; index < result.length; index++) { 36 | const item = result[index]; 37 | const [commodity] = await db.query( 38 | `SELECT * FROM commodity where state=1 and store_id=?`, 39 | item.id 40 | ); 41 | result[index].commodity_list = commodity; 42 | } 43 | 44 | ctx.body = { 45 | success: true, 46 | data: result.filter(item => item?.commodity_list?.length > 0), 47 | }; 48 | } catch (error) { 49 | console.error(error); 50 | ctx.body = { 51 | success: false, 52 | message: "查询失败", 53 | error: error.message, 54 | }; 55 | } 56 | }); 57 | 58 | module.exports = router; 59 | 60 | module.exports = router; 61 | -------------------------------------------------------------------------------- /项目代码/server/src/socket/index.js: -------------------------------------------------------------------------------- 1 | const { server } = require("@/index"); 2 | const { Server } = require("socket.io"); 3 | const Cookie = require("cookie"); 4 | const jwt = require("jsonwebtoken"); 5 | const db = require("@/db"); // 假设你的数据库操作模块是在 './db' 中 6 | 7 | const io = new Server(server, { 8 | path: "/online-message", 9 | cors: "*", 10 | }); 11 | 12 | io.use((socket, next) => { 13 | let cookie = Cookie.parse(socket.handshake.headers.cookie || ""); 14 | let token = cookie.token || ""; 15 | jwt.verify(token, "key", async function (err, decoded) { 16 | if (err) { 17 | } else { 18 | socket.id = decoded.id; 19 | next(); 20 | } 21 | }); 22 | next(); 23 | }); 24 | // 监听连接事件 25 | io.on("connection", socket => { 26 | socket.on("chat message", async msg => { 27 | console.log("message: " + msg); 28 | 29 | try { 30 | const result = await db.query( 31 | "INSERT INTO message (user_id, store_id, content, create_time) VALUES (?, ?, ?, NOW())", 32 | [msg.user_id, msg.store_id, msg.content] 33 | ); 34 | 35 | // 获取接收消息的用户的 socket.id 36 | const receiverSocketId = await db.query("SELECT socket_id FROM user WHERE id = ?", [ 37 | msg.receiver_user_id, 38 | ]); 39 | 40 | // 向发送消息的客户端发送确认消息 41 | io.to(socket.id).emit("chat message", "Message sent successfully"); 42 | 43 | // 向接收消息的用户发送实时消息提醒 44 | io.to(receiverSocketId).emit("message notification", "You have a new message"); 45 | } catch (error) { 46 | console.error(error); 47 | // 向发送消息的客户端发送错误消息 48 | io.to(socket.id).emit("chat message", "Failed to send message"); 49 | } 50 | }); 51 | 52 | // 监听断开连接事件 53 | socket.on("disconnect", () => {}); 54 | }); 55 | module.exports = io; 56 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/commodity/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | const id = require("@/utils/id"); 6 | 7 | router.post("/commodity", auth(), async ctx => { 8 | try { 9 | const { 10 | name, 11 | description, 12 | cover, 13 | banner, 14 | price, 15 | market_time, 16 | configuration, 17 | inventory, 18 | sample_id, 19 | } = ctx.request.body; 20 | 21 | let [repeat] = await db.query( 22 | `select count(id) from commodity where store_id=? and sample_id=?;`, 23 | [ctx.id, sample_id] 24 | ); 25 | 26 | if (repeat[0]["count(id)"] > 0) { 27 | ctx.body = { 28 | success: false, 29 | message: "本店已有同类商品", 30 | }; 31 | return; 32 | } 33 | 34 | const result = await db.query( 35 | `INSERT INTO commodity (id,name, description, cover, banner, price, market_time, configuration, inventory, store_id, create_time, state,sample_id) VALUES (?,?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), 1,?)`, 36 | [ 37 | id(), 38 | name, 39 | description, 40 | cover, 41 | JSON.stringify(banner), 42 | price, 43 | market_time, 44 | JSON.stringify(configuration), 45 | inventory, 46 | ctx.id, 47 | +sample_id, 48 | ] 49 | ); 50 | 51 | ctx.body = { 52 | success: !!result[0]?.affectedRows, 53 | message: "添加成功", 54 | }; 55 | } catch (error) { 56 | console.log(error); 57 | ctx.body = { 58 | success: false, 59 | error: error.message, 60 | message: "添加失败", 61 | }; 62 | } 63 | }); 64 | 65 | module.exports = router; 66 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/tools/order-search.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const router = new Router(); 4 | const auth = require("@/modules/auth"); 5 | 6 | router.get("/order/create/search", auth(), async ctx => { 7 | try { 8 | const { type, keyword } = ctx.query; 9 | 10 | if (!type || !keyword) { 11 | ctx.body = { 12 | success: false, 13 | message: "缺少必要的参数", 14 | }; 15 | return; 16 | } 17 | 18 | let result; 19 | 20 | if (type === "user") { 21 | // 搜索用户 22 | result = await searchUser(keyword); 23 | } else if (type === "commodity") { 24 | // 搜索商品 25 | result = await searchCommodity(keyword, ctx.id); 26 | } else { 27 | ctx.body = { 28 | success: false, 29 | message: "无效的搜索类型", 30 | }; 31 | return; 32 | } 33 | 34 | ctx.body = { 35 | success: true, 36 | data: result, 37 | }; 38 | } catch (error) { 39 | console.log(error); 40 | ctx.body = { 41 | success: false, 42 | message: "搜索失败", 43 | error: error.message, 44 | }; 45 | } 46 | }); 47 | 48 | // 搜索用户 49 | async function searchUser(keyword) { 50 | const result = await db.query( 51 | "SELECT id, name, email, avatar FROM user WHERE id = ? OR email LIKE ?", 52 | [keyword, `%${keyword}%`] 53 | ); 54 | return result[0]; 55 | } 56 | 57 | // 搜索商品 58 | async function searchCommodity(keyword, id) { 59 | const result = await db.query( 60 | "SELECT id, name, description,cover FROM commodity WHERE id = ? OR name LIKE ? OR description LIKE ? and store_id=? and state=1 and inventory>0", 61 | [keyword, `%${keyword}%`, `%${keyword}%`, id] 62 | ); 63 | return result[0]; 64 | } 65 | 66 | module.exports = router; 67 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/Upload.vue: -------------------------------------------------------------------------------- 1 | 14 | 35 | 36 | 43 | 44 | 66 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/message/index.vue: -------------------------------------------------------------------------------- 1 | 38 | 49 | 50 | 51 | { 52 | "meta": { 53 | "layout": "client" 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/comment/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/comment/:article_id", auth(), async ctx => { 7 | try { 8 | const [list] = await db.query(`select * from comment where article_id=? and reply is null;`, [ 9 | ctx.params.article_id, 10 | ]); 11 | 12 | // 为用户设置用户名和头像 13 | for (let index = 0; index < list.length; index++) { 14 | const item = list[index]; 15 | const [user] = await db.query(`select name,id,avatar from user where id=?;`, [item.user_id]); 16 | list[index].user_data = user[0]; 17 | list[index].children = []; 18 | } 19 | 20 | // 回复 21 | const [reply] = await db.query( 22 | `select * from comment where article_id=? and reply is not null order by create_time asc;`, 23 | [ctx.params.article_id] 24 | ); 25 | for (let index = 0; index < reply.length; index++) { 26 | // 为用户设置用户名和头像 27 | const item = reply[index]; 28 | const [user] = await db.query(`select name,id,avatar from user where id=?;`, [item.user_id]); 29 | reply[index].user_data = user[0]; 30 | // 设置二级回复以及底层回复 31 | list.forEach((_item, index, array) => { 32 | let result = [_item, ..._item.children].find(el => el.id == item.reply); 33 | if (result) { 34 | list[index].children.push( 35 | Object.assign(item, { 36 | reply_data: { id: result.user_data.id, name: result.user_data.name }, 37 | }) 38 | ); 39 | } 40 | }); 41 | } 42 | 43 | 44 | ctx.body = { 45 | success: true, 46 | message: "文章中的评论列表", 47 | data: list, 48 | }; 49 | } catch (error) { 50 | console.error(error); 51 | ctx.body = { 52 | success: false, 53 | message: "文章中的评论列表查询失败", 54 | error: error.message, 55 | }; 56 | } 57 | }); 58 | 59 | module.exports = router; 60 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/admin/StoreForm.vue: -------------------------------------------------------------------------------- 1 | 27 | 60 | 61 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/store/Navigate.vue: -------------------------------------------------------------------------------- 1 | 51 | 65 | 66 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/user/ArticleList/index.vue: -------------------------------------------------------------------------------- 1 | 50 | 59 | 60 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/admin/Navigate.vue: -------------------------------------------------------------------------------- 1 | 55 | 70 | 71 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/MultipleUpload.vue: -------------------------------------------------------------------------------- 1 | 20 | 72 | 79 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/sign.vue: -------------------------------------------------------------------------------- 1 | 39 | 72 | 73 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/password/index.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 78 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/notice/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/notice", auth(), async ctx => { 7 | try { 8 | const { auth, id } = ctx; 9 | 10 | let query = ` 11 | SELECT 12 | n.id, n.title, n.target, n.content, n.isTop, n.create_time 13 | FROM 14 | notice n 15 | WHERE`; 16 | 17 | if (auth === "admin") { 18 | query += ` 1=1`; // 查询全部 19 | query += ` ORDER BY n.create_time DESC`; 20 | } else if (auth === "store") { 21 | query += ` (JSON_CONTAINS(n.target, '${id}') OR JSON_LENGTH(n.target) = 0)`; 22 | query += ` ORDER BY n.isTop DESC, n.create_time DESC`; 23 | } 24 | 25 | const [notices] = await db.query(query); 26 | 27 | // 管理员查询时。插入通知的store列表信息 28 | if (auth == "admin") { 29 | const storeIds = notices.reduce((ids, notice) => { 30 | return ids.concat(notice.target); 31 | }, []); 32 | 33 | if (storeIds.length > 0) { 34 | // 查询 store 信息 35 | const [stores] = await db.query( 36 | `SELECT id, name, cover_pic FROM chain_store WHERE id IN (${storeIds.join(",")})` 37 | ); 38 | 39 | // 将 store 信息插入到通知列表中的 store_list 字段 40 | notices.forEach(notice => { 41 | notice.store_list = stores.filter(store => notice.target.includes(store.id)); 42 | }); 43 | } 44 | } 45 | // store查询时判断每条信息是否被查询并且排序 46 | if (auth == "store") { 47 | for (let index = 0; index < notices.length; index++) { 48 | const item = notices[index]; 49 | const [exist] = await db.query( 50 | `select * from notice_history where store_id=? and notice_id=?;`, 51 | [ctx.id, item.id] 52 | ); 53 | notices[index].isRead = !!exist.length; 54 | } 55 | // 排序 56 | notices.sort((a, b) => { 57 | // 首先按照isTop降序排列 58 | if (b.isTop - a.isTop !== 0) { 59 | return b.isTop - a.isTop; 60 | } 61 | // 然后按照isRead升序排列 62 | return a.isRead - b.isRead; 63 | }); 64 | } 65 | ctx.body = { 66 | success: true, 67 | data: notices, 68 | }; 69 | } catch (error) { 70 | console.error(error); 71 | ctx.body = { 72 | success: false, 73 | message: "查询通知列表失败", 74 | error: error.message, 75 | }; 76 | } 77 | }); 78 | 79 | module.exports = router; 80 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/order/create.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const id = require("@/utils/id"); 4 | const auth = require("@/modules/auth"); 5 | const router = new Router(); 6 | 7 | router.post("/order", auth(), async ctx => { 8 | try { 9 | const { user_id, commodity_id, payment_method, notes } = ctx.request.body; 10 | 11 | // 查询商品信息 12 | const [commodityQuery] = await db.query("SELECT * FROM commodity WHERE id = ?", [commodity_id]); 13 | if (!commodityQuery?.length) { 14 | ctx.body = { 15 | success: false, 16 | message: "未找到对应的商品信息", 17 | }; 18 | return; 19 | } 20 | 21 | if (commodityQuery[0].inventory <= 0) { 22 | ctx.body = { 23 | success: false, 24 | message: "该商品的库存不足", 25 | }; 26 | return; 27 | } 28 | 29 | const commodityInfo = commodityQuery[0]; 30 | 31 | // 构建订单数据 32 | const orderData = { 33 | id: id(), 34 | user_id, 35 | store_id: commodityInfo.store_id, 36 | commodity_id, 37 | detail_data: JSON.stringify(commodityInfo), 38 | payment_method, 39 | notes, 40 | create_time: new Date(), 41 | }; 42 | 43 | // 插入订单到数据库 44 | const result = await db.query( 45 | "INSERT INTO orders (id, user_id, store_id, commodity_id, detail_data, payment_method, notes, create_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", 46 | [ 47 | orderData.id, 48 | orderData.user_id, 49 | orderData.store_id, 50 | orderData.commodity_id, 51 | orderData.detail_data, 52 | orderData.payment_method, 53 | orderData.notes, 54 | orderData.create_time, 55 | ] 56 | ); 57 | 58 | ctx.body = { 59 | success: !!result[0]?.affectedRows, 60 | message: "订单添加成功", 61 | }; 62 | 63 | // 商品库存-1 64 | // db.query( 65 | // `UPDATE commodity 66 | // SET inventory = inventory - 1 67 | // WHERE id = ?; 68 | // `, 69 | // [orderData.commodity_id] 70 | // ); 71 | 72 | // 商品库存-1 73 | for (let index = 0; index < commodity_data.length; index++) { 74 | const item = commodity_data[index]; 75 | db.query( 76 | `UPDATE commodity 77 | SET inventory = inventory - ${item.count} 78 | WHERE id=${item.id}; 79 | ` 80 | ); 81 | } 82 | } catch (error) { 83 | console.error(error); 84 | ctx.body = { 85 | success: false, 86 | message: "订单添加失败", 87 | error: error.message, 88 | }; 89 | } 90 | }); 91 | 92 | module.exports = router; 93 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/order/index.vue: -------------------------------------------------------------------------------- 1 | 44 | 67 | 68 | 69 | { 70 | "meta": { 71 | "layout": "client-empty" 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/index.vue: -------------------------------------------------------------------------------- 1 | 27 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/reservation/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); // 请根据实际情况替换成你的数据库操作库 3 | const auth = require("@/modules/auth"); 4 | 5 | const router = new Router(); 6 | 7 | router.get("/reservation", auth(), async ctx => { 8 | try { 9 | let query; 10 | 11 | if (ctx.auth === "user") { 12 | query = ` 13 | SELECT 14 | r.id AS reservation_id, 15 | r.user_id, 16 | r.store_id, 17 | r.notes, 18 | r.state, 19 | r.time AS reservation_time, 20 | r.create_time AS reservation_create_time, 21 | r.reply, 22 | r.commodity_id, 23 | u.name AS user_name, 24 | u.avatar AS user_avatar, 25 | s.name AS store_name, 26 | s.cover_pic AS store_cover, 27 | s.address AS store_address, 28 | c.id AS commodity_id, 29 | c.name AS commodity_name, 30 | c.cover AS commodity_cover, 31 | c.price AS commodity_price 32 | FROM 33 | reservation r 34 | LEFT JOIN 35 | user u ON r.user_id = u.id 36 | LEFT JOIN 37 | chain_store s ON r.store_id = s.id 38 | LEFT JOIN 39 | commodity c ON r.commodity_id = c.id 40 | WHERE 41 | r.user_id = ? 42 | ORDER BY 43 | r.create_time DESC; 44 | `; 45 | } else if (ctx.auth === "store") { 46 | // 如果是店铺,根据 user_id 查询用户信息,不查询 store 的信息 47 | query = ` 48 | SELECT 49 | r.id AS reservation_id, 50 | r.user_id, 51 | r.store_id, 52 | r.notes, 53 | r.state, 54 | r.time AS reservation_time, 55 | r.create_time AS reservation_create_time, 56 | r.reply, 57 | r.commodity_id, 58 | u.name AS user_name, 59 | u.avatar AS user_avatar, 60 | c.id AS commodity_id, 61 | c.name AS commodity_name, 62 | c.cover AS commodity_cover, 63 | c.price AS commodity_price 64 | FROM 65 | reservation r 66 | LEFT JOIN 67 | user u ON r.user_id = u.id 68 | LEFT JOIN 69 | commodity c ON r.commodity_id = c.id 70 | WHERE 71 | r.store_id = ? and r.state<>3 72 | ORDER BY 73 | r.create_time DESC; 74 | `; 75 | } 76 | 77 | // 执行查询 78 | const [reservations] = await db.query(query, [ctx.id]); 79 | 80 | ctx.body = { success: true, data: reservations }; 81 | } catch (error) { 82 | console.error(error); 83 | ctx.body = { success: false, data: [] }; 84 | } 85 | }); 86 | 87 | module.exports = router; 88 | -------------------------------------------------------------------------------- /项目代码/server/src/routes/user/list.js: -------------------------------------------------------------------------------- 1 | const Router = require("koa-router"); 2 | const db = require("@/db"); 3 | const auth = require("@/modules/auth"); 4 | const router = new Router(); 5 | 6 | router.get("/user-list", auth(), async ctx => { 7 | try { 8 | const query = ` 9 | SELECT 10 | u.id AS user_id, 11 | u.name AS user_name, 12 | u.email AS user_email, 13 | u.avatar AS user_avatar, 14 | o.id AS order_id, 15 | o.create_time AS order_create_time, 16 | o.notes AS order_notes, 17 | o.payment_method AS order_payment_method, 18 | o.store_id AS store_id, 19 | s.name AS store_name, 20 | s.cover_pic AS store_cover, 21 | s.email AS email, 22 | c.id AS commodity_id, 23 | c.name AS commodity_name, 24 | c.cover AS commodity_cover, 25 | c.price AS commodity_price 26 | FROM 27 | user u 28 | LEFT JOIN 29 | orders o ON u.id = o.user_id 30 | LEFT JOIN 31 | chain_store s ON o.store_id = s.id 32 | LEFT JOIN 33 | commodity c ON o.commodity_id = c.id 34 | ORDER BY u.id, o.create_time DESC; 35 | `; 36 | 37 | const [result] = await db.query(query); 38 | 39 | const userList = []; 40 | let currentUser = null; 41 | 42 | for (const row of result) { 43 | if (!currentUser || currentUser.id !== row.user_id) { 44 | // 新的用户 45 | currentUser = { 46 | id: row.user_id, 47 | name: row.user_name, 48 | email: row.user_email, 49 | avatar: row.user_avatar, 50 | orders: [], 51 | }; 52 | userList.push(currentUser); 53 | } 54 | 55 | if (row.order_id) { 56 | // 用户的订单 57 | const order = { 58 | id: row.order_id, 59 | create_time: row.order_create_time, 60 | notes: row.order_notes, 61 | payment_method: row.order_payment_method, 62 | store: { 63 | id: row.store_id, 64 | name: row.store_name, 65 | email: row.email, 66 | cover: row.store_cover, 67 | }, 68 | commodity: { 69 | id: row.commodity_id, 70 | name: row.commodity_name, 71 | price: row.commodity_price, 72 | cover: row.commodity_cover, 73 | }, 74 | }; 75 | currentUser.orders.push(order); 76 | } 77 | } 78 | 79 | ctx.body = { 80 | success: true, 81 | data: userList, 82 | }; 83 | } catch (error) { 84 | console.error(error); 85 | ctx.body = { 86 | success: false, 87 | message: "查询用户列表失败", 88 | error: error.message, 89 | }; 90 | } 91 | }); 92 | 93 | module.exports = router; 94 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/article/list.vue: -------------------------------------------------------------------------------- 1 | 53 | 75 | 76 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/store/list.vue: -------------------------------------------------------------------------------- 1 | 61 | 80 | 81 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/store/ArticleEdit/Edit.vue: -------------------------------------------------------------------------------- 1 | 19 | 98 | 106 | -------------------------------------------------------------------------------- /项目代码/admin/src/components/admin/BannerDialog/index.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 76 | 83 | 84 | 108 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/index.vue: -------------------------------------------------------------------------------- 1 | 48 | 76 | 86 | 87 | { 88 | "meta": { 89 | "layout": "client" 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/sign-up.vue: -------------------------------------------------------------------------------- 1 | 64 | 99 | 100 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/reservation/index.vue: -------------------------------------------------------------------------------- 1 | 62 | 86 | 87 | 88 | { 89 | "meta": { 90 | "layout": "client-empty" 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/sign.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 74 | 75 | 120 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/sign.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 74 | 75 | 120 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/user/index.vue: -------------------------------------------------------------------------------- 1 | 61 | 82 | 83 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/client/set/index.vue: -------------------------------------------------------------------------------- 1 | 61 | 106 | 107 | 108 | { 109 | "meta": { 110 | "layout": "client-empty" 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/notice/create.vue: -------------------------------------------------------------------------------- 1 | 54 | 113 | 114 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/banner/index.vue: -------------------------------------------------------------------------------- 1 | 60 | 113 | 114 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/commodity/list.vue: -------------------------------------------------------------------------------- 1 | 63 | 107 | 108 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/notice/index.vue: -------------------------------------------------------------------------------- 1 | 72 | 101 | 102 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/admin/commodity/list.vue: -------------------------------------------------------------------------------- 1 | 63 | 107 | 108 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/commodity/index.vue: -------------------------------------------------------------------------------- 1 | 64 | 108 | 109 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/set/index.vue: -------------------------------------------------------------------------------- 1 | 41 | 115 | 116 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/order/index.vue: -------------------------------------------------------------------------------- 1 | 73 | 114 | 115 | -------------------------------------------------------------------------------- /项目代码/admin/src/pages/store/notice/index.vue: -------------------------------------------------------------------------------- 1 | 86 | 110 | 111 | --------------------------------------------------------------------------------