Compare commits

..

2 Commits

Author SHA1 Message Date
gct acdf1bd1e9 1
3 months ago
P-Jhao d9bdac19a6 快递系统后端v1.0
3 months ago

@ -0,0 +1,5 @@
DB_NAME = "uml"
DB_USER = "root"
DB_PASSWORD = "123456"
DB_HOST = "localhost"
JWT_SECRET = "PJH"

@ -1,3 +0,0 @@
{
"recommendations": ["Vue.volar"]
}

@ -1,5 +1,3 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
# 111
# 111
# 快递系统

@ -0,0 +1,57 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors');
//优先读取环境变量
require("dotenv").config()
//引入数据库连接
require("./dao/db")
//引入路由
const userRouter = require('./routes/user');
const expressRouter = require("./routes/express")
var app = express();
//配置cors
const corsOptions = {
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['Authentication', 'X-Custom-Header'],
credentials: true,
}
//为所有源跨域
app.use(cors(corsOptions))
//使用各种中间件
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//使用路由中间件
app.use('/user', userRouter);
app.use("/express", expressRouter)
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// 错误捕获
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
});
module.exports = app;

@ -0,0 +1,91 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('backend:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string' ?
'Pipe ' + port :
'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string' ?
'pipe ' + addr :
'port ' + addr.port;
debug('Listening on ' + bind);
console.log("监听3000端口")
}

@ -0,0 +1,58 @@
const sequelize = require("./dbConnect")
const userModel = require("./model/userModel")
const expressModel = require("./model/expressModel")
const md5 = require("md5")
const {
getRandomExpressId
} = require("../utils/tools")
//将数据模型和表进行同步
async function test() {
await sequelize.sync({
alter: true
})
//将需要数据的表初始化
const userCount = await userModel.count()
if (!userCount) {
//需要初始化
await userModel.create({
loginId: "test",
loginPwd: md5("123")
})
console.log("用户数据初始化完毕")
}
const expressCount = await expressModel.count()
if (!expressCount) {
expressModel.bulkCreate([{
expressId: getRandomExpressId(),
senderCity: "深圳市",
senderName: "冰凉凉1",
receiverCity: "福州市",
receiverName: "叶丽丽",
isSigned: 1,
signedTime: "2024-10-24 11:58"
}, {
expressId: getRandomExpressId(),
senderCity: "深圳市",
senderName: "冰凉凉2",
receiverCity: "福州市",
receiverName: "叶丽丽",
isSigned: 1,
signedTime: "2024-10-24 11:58"
}, {
expressId: getRandomExpressId(),
senderCity: "深圳市",
senderName: "冰凉凉3",
receiverCity: "福州市",
receiverName: "叶丽丽",
isSigned: 1,
signedTime: "2024-10-24 11:58"
}])
console.log("express初始化完成")
}
console.log("数据库数据准备完成")
}
test()

@ -0,0 +1,12 @@
const {
Sequelize
} = require("sequelize")
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: "mysql",
logging: false
});
module.exports = sequelize

@ -0,0 +1,30 @@
const {
handleArrayDaoData
} = require("../utils/tools")
const expressModel = require("./model/expressModel")
module.exports.getExpressDao = async function () {
return handleArrayDaoData(await expressModel.findAll())
}
module.exports.addExpressDao = async function (expData) {
await expressModel.create(expData)
return handleArrayDaoData(await expressModel.findAll())
}
module.exports.updateExpressDao = async function (expData) {
await expressModel.update(expData, {
where: {
id: expData.id
}
})
return handleArrayDaoData(await expressModel.findAll())
}
module.exports.deleteExpressDao = async function (id) {
console.log(id, "deleteId")
await expressModel.destroy({
where: {
id
}
})
return handleArrayDaoData(await expressModel.findAll())
}

@ -0,0 +1,37 @@
const sequelize = require("../dbConnect")
const {
DataTypes
} = require("sequelize")
module.exports = sequelize.define("express", {
expressId: {
type: DataTypes.STRING,
allowNull: false
},
senderName: {
type: DataTypes.STRING,
allowNull: false
},
senderCity: {
type: DataTypes.STRING,
allowNull: false
},
receiverName: {
type: DataTypes.STRING,
allowNull: false
},
receiverCity: {
type: DataTypes.STRING,
allowNull: false
},
isSigned: {
type: DataTypes.INTEGER,
allowNull: false
},
signedTime: DataTypes.STRING
}, {
freezeTableName: true,
createdAt: false,
updatedAt: false,
})

@ -0,0 +1,27 @@
const sequelize = require("../dbConnect")
const {
DataTypes
} = require("sequelize")
module.exports = sequelize.define("user", {
loginId: {
type: DataTypes.STRING,
allowNull: false
},
loginPwd: {
type: DataTypes.STRING,
allowNull: false
},
sex: DataTypes.STRING,
brithday: DataTypes.STRING,
region: DataTypes.STRING,
number: DataTypes.STRING,
isAdmin: {
type: DataTypes.BOOLEAN,
defaultValue: false
}
}, {
freezeTableName: true,
createdAt: false,
updatedAt: false,
})

@ -0,0 +1,32 @@
const userModel = require("./model/userModel")
module.exports.loginDao = async function ({
loginId,
loginPwd
}) {
return await userModel.findOne({
where: {
loginId,
loginPwd
}
})
}
module.exports.updateUserDao = async function (loginInfo) {
return await userModel.update(loginInfo, {
where: {
loginId: loginInfo.loginId,
}
})
}
module.exports.getUserInfoDao = async function (loginId) {
return await userModel.findOne({
where: {
loginId,
}
})
}
module.exports.addUserDao = async function (userInfo) {
return await userModel.create(userInfo)
}

@ -1,17 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
<!-- -->
</html>

1917
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,22 +1,23 @@
{
"name": "lesson1_vite",
"private": true,
"name": "backend",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"start": "nodemon -x npm run server",
"server": "node ./bin/www"
},
"dependencies": {
"axios": "^1.2.1",
"element-plus": "^2.9.0",
"pinia": "2.0.27",
"vue": "^3.4.37",
"vue-router": "4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.2",
"vite": "^5.4.1"
"cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9",
"dotenv": "^16.4.5",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"jsonwebtoken": "^9.0.2",
"md5": "^2.3.0",
"morgan": "~1.9.1",
"mysql2": "^3.11.4",
"sequelize": "^6.37.5"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

@ -0,0 +1,8 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,33 @@
const express = require("express")
const router = express.Router()
const {
getExpressServices,
addExpressServices,
updateExpressServices,
deleteExpressServices
} = require("../services/expressService")
const {
formatResponse
} = require("../utils/tools")
router.get("/", async function (req, res, next) {
const data = await getExpressServices()
res.send(formatResponse(0, "", data))
})
router.post("/", async function (req, res, next) {
const data = await addExpressServices(req.body)
res.send(formatResponse(0, "", data))
})
router.put("/", async function (req, res, next) {
const data = await updateExpressServices(req.body)
res.send(formatResponse(0, "", data))
})
router.delete("/", async function (req, res, next) {
const data = await deleteExpressServices(req.body)
res.send(formatResponse(0, "", data))
})
module.exports = router

@ -0,0 +1,52 @@
var express = require('express');
var router = express.Router();
const {
loginService,
updateUserInfoService,
getUserInfoService,
addUserService
} = require("../services/userService")
const {
formatResponse,
analysisToken
} = require("../utils/tools")
/* GET home page. */
router.post('/login', async function (req, res, next) {
//移交service处理
const result = await loginService(req.body)
if (result.token) {
//有token登陆成功
console.log(result.data)
res.setHeader("authentication", result.token)
res.send(formatResponse(0, "", result.data))
} else {
// throw new Error("账号或密码错误")
res.send(formatResponse(401, "账号或密码错误", null))
}
});
router.get("/whoami", async function (req, res, next) {
//获取token,然后进行解析
const {
loginId,
} = analysisToken(req.get("authorization"))
const {
loginPwd,
...data
} = await getUserInfoService(loginId)
res.send(formatResponse(0, "", data))
})
router.put("/", async function (req, res, next) {
const data = await updateUserInfoService(req.body)
res.send(formatResponse(0, "", data))
})
router.post("/", async function (req, res, next) {
const data = await addUserService(req.body)
res.send(formatResponse(0, "", data))
})
module.exports = router;

@ -0,0 +1,35 @@
const {
getExpressDao,
addExpressDao,
updateExpressDao,
deleteExpressDao
} = require("../dao/expressDao")
const {
getRandomExpressId
} = require("../utils/tools")
module.exports.getExpressServices = async function () {
return await getExpressDao()
}
module.exports.addExpressServices = async function (expData) {
//获取的对象需要补充"expressId", "isSigned"
const data = {
expressId: getRandomExpressId(),
isSigned: 0,
...expData,
}
return await addExpressDao(data)
}
module.exports.updateExpressServices = async function (expData) {
//这里需要提供id
return await updateExpressDao(expData)
}
module.exports.deleteExpressServices = async function ({
id
}) {
return await deleteExpressDao(
id
)
}

@ -0,0 +1,54 @@
const md5 = require('md5');
const {
loginDao,
updateUserDao,
getUserInfoDao,
addUserDao
} = require("../dao/userDao")
const jwt = require("jsonwebtoken");
const {
getJwtToken
} = require('../utils/tools');
module.exports.loginService = async function (loginInfo) {
//将明文密码转换为加密密码
loginInfo.loginPwd = md5(loginInfo.loginPwd);
let userInfo = await loginDao(loginInfo)
if (userInfo) {
const {
loginPwd,
id,
...data
} = userInfo.dataValues
//添加token后返回
let token = ""
token = getJwtToken(data)
return {
token,
data
}
}
return {
data: userInfo
}
}
module.exports.updateUserInfoService = async function (userInfo) {
// userInfo.loginPwd = md5(userInfo.loginPwd)
await updateUserDao(userInfo)
const result = await getUserInfoDao(userInfo.loginId)
return result.dataValues
}
module.exports.getUserInfoService = async function (loginId) {
const data = await getUserInfoDao(loginId)
return data.dataValues
}
module.exports.addUserService = async function (userInfo) {
userInfo.loginPwd = md5(userInfo.loginPwd)
const data = await addUserDao(userInfo)
return data.dataValues
}

@ -1,184 +0,0 @@
<template>
<el-row class="main">
<el-row class="send-container">
<el-row class="panel send-panel send-panel1">
<el-row class="send-container">
<el-button class="send-btn"></el-button>
<el-row>
<el-button>地址簿</el-button>
<el-button>智能填写</el-button>
</el-row>
</el-row>
<el-form label-width="auto" class="form">
<el-form-item>
<template #label>
<span class="required">*</span>姓名
</template>
<el-input placeholder="请填写发件人姓名" v-model="formRef.senderName"></el-input>
</el-form-item>
</el-form>
<el-form label-width="auto" class="form">
<el-form-item>
<template #label>
<span class="required">*</span>省市区
</template>
<el-input placeholder="请输入目前省市区" v-model="formRef.senderCity"></el-input>
</el-form-item>
</el-form>
<el-form label-width="auto" class="form">
<el-form-item label="公司名称">
<el-input placeholder="请填写公司名称" v-model="senderCompanyRef"></el-input>
</el-form-item>
</el-form>
</el-row>
<el-image src="/arrow.png"></el-image>
<el-row class="panel send-panel send-panel1">
<el-row class="send-container">
<el-button class="send-btn receiver-btn"></el-button>
<el-row>
<el-button>地址簿</el-button>
<el-button>智能填写</el-button>
</el-row>
</el-row>
<el-form label-width="auto" class="form">
<el-form-item>
<template #label>
<span class="required">*</span>姓名
</template>
<el-input placeholder="请填写收件人姓名" v-model="formRef.receiverName"></el-input>
</el-form-item>
</el-form>
<el-form label-width="auto" class="form">
<el-form-item>
<template #label>
<span class="required">*</span>收件的省市区
</template>
<el-input placeholder="请输入收件城市" v-model="formRef.receiverCity"></el-input>
</el-form-item>
</el-form>
<el-form label-width="auto" class="form">
<el-form-item label="公司名称">
<el-input placeholder="请填写公司名称" v-model="receiverCompanyRef"></el-input>
</el-form-item>
</el-form>
</el-row>
</el-row>
<el-row class="panel send-panel">
<el-text class="send-label">寄件方式</el-text>
<el-radio-group v-model="sendType">
<el-radio value="0" size="large">预约上门取件</el-radio>
<el-radio value="1" size="large">自行联系快递员</el-radio>
</el-radio-group>
</el-row>
<el-row class="panel send-panel">
<el-button class="confirm-btn" @click="handleExpressSender"></el-button>
</el-row>
</el-row>
</template>
<script setup>
import { ref } from 'vue';
import { getExpressForm } from '../../utils/tools';
import { useExpressStore } from '../../store';
import { ElMessage } from 'element-plus'
const expressStore = useExpressStore()
const formRef = ref(getExpressForm())
const senderCompanyRef = ref("")
const receiverCompanyRef = ref("")
const sendType = ref("0");
function handleExpressSender() {
let { senderName, receiverName, senderCity, receiverCity } = formRef.value
if (senderCompanyRef.value) {
senderName = senderCompanyRef.value + " " + senderName
senderCompanyRef.value = ""
}
if (receiverCompanyRef.value) {
receiverName = receiverCompanyRef.value + " " + receiverName
receiverCompanyRef.value = ""
}
if (!senderName || !receiverName || !senderCity || !receiverCity) {
ElMessage({
message: '请填写完必填信息',
type: 'error',
plain: true,
})
return
}
expressStore.addExpress(formRef.value)
formRef.value = getExpressForm()
ElMessage({
message: '下单成功',
type: 'success',
plain: true,
})
}
</script>
<style>
.send-container {
display: flex;
width: 100%;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.panel {
display: flex;
flex-direction: column;
background-color: white;
justify-content: center;
align-items: flex-start;
width: 100%;
}
.send-panel {
padding: 10px;
margin-top: 10px;
line-height: 40px;
}
.send-panel1 {
width: 40%;
align-items: center;
}
.send-btn {
background-color: black;
color: white;
border-radius: 100%;
padding: 10px;
}
.receiver-btn {
background-color: red;
}
.form {
margin-top: 10px;
width: 80%;
}
.send-label {
font-weight: 600;
align-self: flex-start;
}
.confirm-btn {
background-color: red;
color: white;
}
.required {
color: red;
}
</style>

@ -1,26 +0,0 @@
<script>
</script>
<template>
<div>
<router-view></router-view>
</div>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

Before

Width:  |  Height:  |  Size: 496 B

@ -1,19 +0,0 @@
import {
createApp
} from 'vue';
import './style.css'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router.js'
import {
createPinia
} from 'pinia'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(ElementPlus)
app.use(router)
app.mount('#app')

@ -1,20 +0,0 @@
import axios from "axios";
const req = axios.create({
baseURL: "http://localhost:3000",
timeout: 2000
})
// 添加请求拦截器
req.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if (localStorage.getItem("token")) {
//有token则默认发送给服务器
config.headers.Authorization = `Bearer ${localStorage.getItem("token")}`
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
export default req

@ -1,126 +0,0 @@
import {
createRouter,
createWebHistory
} from 'vue-router';
import {
userStore,
useExpressStore
} from './store';
import {
ElMessage
} from 'element-plus';
import request from "./request"
const router = createRouter({
history: createWebHistory(),
routes: [{
path: "/",
redirect: "login"
},
{
path: '/login',
name: 'Login',
component: () => import("./view/login.vue")
},
{
path: "/register",
name: "Register",
component: () => import("./view/register.vue")
},
{
path: '/user',
name: 'User',
redirect: localStorage.getItem("isAdmin") ? '/user/expressList' : '/user/myInfo',
component: () => import("./view/user/index.vue"),
children: [{
path: 'myInfo',
component: () => import("./view/user/MyInfo.vue"),
},
{
path: 'expressList',
component: () => import("./view/user/ExpressList.vue"),
},
{
path: 'expressForm',
component: () => import("./view/user/ExpressForm.vue"),
},
{
path: "signed",
component: () => import("./view/user/SignedList.vue"),
}
]
},
]
});
router.beforeEach((to, from, next) => {
const userStore_ = userStore()
if (to.name === 'Login' || to.name === "Register") {
next();
} else {
const token = localStorage.getItem("token")
if (token) {
//重新请求express
const expressStore = useExpressStore()
request({
method: "get",
url: "/express",
}).then(({
data
}) => {
if (data.code === 0) {
expressStore.setExpress(data.data)
console.log(data.data, "重新设置express成功")
}
})
//有秘钥重新请求userInfo
request({
method: "get",
url: "/user/whoami",
}).then(({
data
}) => {
//获取用户信息
if (data.code === 0) {
//重新设置信息
userStore_.setUserInfo(data.data)
//重新设置秘钥
userStore_.setToken(token)
userStore_.setAdmin(localStorage.getItem("isAdmin"))
console.log("重新响应成功", data.data)
if (localStorage.getItem("isAdmin") && token.name === "User") {
next({
path: "/user/expressList"
})
} else {
next()
}
} else {
//获取失败,秘钥过期
ElMessage({
message: "登录已过期,请重新登录",
type: "error"
})
//将过期的token删除
localStorage.removeItem("token")
next({
name: "Login"
})
}
})
//有秘钥就通过
} else {
next({
name: "Login"
})
}
}
})
export default router;

@ -1,48 +0,0 @@
import {
defineStore
} from 'pinia';
import {
ElMessage
} from 'element-plus'
import req from "../request"
export const useAdminStore = defineStore('adminStore', {
state: () => ({
adminInfo: {},
adminAccount: [{
loginId: "test1234",
loginPwd: "test1234"
}]
}),
getters: {
async getAdminInfo() {
return this.getAdminInfo
}
},
actions: {
addAdminAccount(loginInfo) {
this.adminAccount.push({
loginId: loginInfo.loginId,
loginPwd: loginInfo.loginPwd,
})
ElMessage({
message: "注册快递员账号成功",
type: "success"
})
},
loginAdmin(loginInfo) {
let hasAccount = false
this.adminAccount.forEach((item, index) => {
if (item.loginId === loginInfo.loginId && item.loginPwd === loginInfo.loginPwd) {
this.adminInfo = this.adminAccount[index]
hasAccount = true;
}
})
localStorage.setItem("isAdmin", true)
return hasAccount
}
}
});

@ -1,83 +0,0 @@
import {
defineStore
} from 'pinia';
import {
ElMessage
} from 'element-plus'
import req from "../request"
export const useExpressStore = defineStore('expressStore', {
state: () => ({
expressList: []
}),
getters: {
getExpressList() {
return this.expressList
},
getSignedList() {
return this.expressList.filter(item => item.isSigned)
},
getUnSignedList() {
return this.expressList.filter(item => !item.isSigned)
}
},
actions: {
modifyExpress(form, formIndex) {
let item = this.expressList[formIndex]
const formTable = form.value
item.senderCity = formTable.senderCity
item.senderName = formTable.senderName
item.receiverCity = formTable.receiverCity
item.receiverName = formTable.receiverName
item.signedTime = formTable.signedTime
if (item.signedTime) {
item.isSigned = 1
}
req({
method: "put",
url: "/express",
data: item
}).then(({
data
}) => {
console.log(data, "modifyedData")
ElMessage({
message: '修改成功',
type: 'success',
plain: true,
})
})
},
addExpress(form) {
req({
method: "post",
url: "/express",
data: form
}).then((res) => {
console.log(res.data, "addExpressData")
})
this.expressList.push(form);
},
setExpress(datas) {
this.expressList = datas
},
deleteExpress(form, formIndex) {
let item = this.expressList[formIndex]
this.expressList.splice(formIndex, 1)
req({
method: "delete",
url: "/express",
data: item
}).then(({
data
}) => {
console.log(data, "deletedData")
ElMessage({
message: '删除成功',
type: 'success',
plain: true,
})
})
}
}
});

@ -1,13 +0,0 @@
import {
useExpressStore
} from "./expressStore"
import {
userStore
} from "./userStore"
export {
userStore,
useExpressStore
}

@ -1,71 +0,0 @@
import {
defineStore
} from 'pinia';
import {
ElMessage
} from 'element-plus';
import req from "../request"
export const userStore = defineStore('userStore', {
state: () => ({
token: "",
userInfo: {},
isAdmin: false
}),
getters: {
getToken() {
return this.token
},
getUserInfo() {
return this.userInfo
},
getIsAdmin() {
return this.userInfo.isAdmin
}
},
actions: {
setLoginState(state) {
this.loginState = state;
localStorage.setItem('isLoggedIn', state); // 将登录状态存储到 localStorage
},
setToken(token) {
this.token = token;
localStorage.setItem("token", token)
},
setUserInfo(data) {
this.userInfo = data;
console.log(this.data, "userStoreData")
},
updateUserInfo(data) {
req({
method: "put",
url: "/user",
data,
}).then(({
data
}) => {
if (data.code === 0) {
this.setUserInfo(data.data)
ElMessage({
message: "修改成功",
type: "success"
})
}
})
},
logoutUser() {
localStorage.removeItem("token")
location.reload(true);
ElMessage({
message: '注销成功',
type: 'success',
plain: true,
})
},
setAdmin(value) {
this.isAdmin = value
}
}
});

@ -1,79 +0,0 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

@ -1,11 +0,0 @@
export function getExpressForm() {
return {
"expressid": "",
"senderCity": "",
"senderName": "",
"receiverCity": "",
"receiverName": "",
"signedTime": "",
"isSigned": false
}
}

@ -1,497 +0,0 @@
<template>
<div class="sf-city-services">
<div class="header">
<div class="logo">
<img src="/logo.png" alt="Logo" class="logo-image">
<span class="title">顺丰快递</span>
</div>
<nav>
<ul>
<a href="">
<li><router-link to="">首页</router-link></li>
</a>
<a href="">
<li><router-link to="">物流服务</router-link></li>
</a>
<a href="">
<li><router-link to="">智慧科技</router-link></li>
</a>
<a href="">
<li><router-link to="">服务支持</router-link></li>
</a>
<a href="">
<li><router-link to="">可持续发展</router-link></li>
</a>
<a href="">
<li><router-link to="">投资者关系</router-link></li>
</a>
<a href="">
<li><router-link to="">关于我们</router-link></li>
</a>
</ul>
</nav>
<div @click="loginToRouter" class="auth">快速登录/注册</div>
</div>
<div class="carousel">
<div v-for="(item, index) in carouselItems" :key="index" class="carousel-item"
:class="{ active: currentIndex === index }">
<img :src="item.image" alt="轮播图" />
<div class="carousel-caption">
<h2>{{ item.title }}</h2>
<p>{{ item.description }}</p>
</div>
</div>
<button @click="prevSlide" class="carousel-control prev"><i class="fas fa-angle-left"></i></button>
<button @click="nextSlide" class="carousel-control next"><i class="fas fa-angle-right"></i></button>
</div>
<div class="main-content">
<h1 style="text-align: center;">旭日城市服务</h1>
<h2 style="text-align: center;">批发市场寄递方案</h2>
<p style="text-align: center;">满足多重寄递需求灵活高效价更优</p>
<div class="search-section">
<input type="text" placeholder="您可以输运单号进行查询" class="search-input" />
<button class="search-button">马上查单</button>
</div>
<div class="services-grid">
<div class="service-item">
<img src="/a1.png" alt="服务图片" />
<h3>快递服务</h3>
<p>快速安全可靠</p>
</div>
<div class="service-item">
<img src="/a2.png" alt="服务图片" />
<h3>快运服务</h3>
<p>大件物品运输专家</p>
</div>
<div class="service-item">
<img src="/a3.png" alt="服务图片" />
<h3>冷运服务</h3>
<p>全程冷链新鲜保障</p>
</div>
<div class="service-item">
<img src="/a4.png" alt="服务图片" />
<h3>医药服务</h3>
<p>专业医药物流解决方案</p>
</div>
</div>
<div class="additional-services">
<h3 style="text-align: center;">顺丰特快</h3>
<p>旭日致力于成为连接亚洲与世界的全球领先物流企业未来顺丰将继续稳固国内市场领导地位持续扩大在亚洲和全球市场影响力携手客户共同成长共创价值</p>
<div class="customer-service">
<h4 class="contact-title" style="text-align: center;">联系客服</h4>
<p style="text-align: center;">整车直达</p>
<p style="text-align: center;">满足客户一辆或多辆整车发货需求的定制的整车直达产品</p>
</div>
</div>
</div>
<footer class="footer">
<div class="footer-content">
<div class="footer-section">
<h4>关于我们</h4>
<a href="">
<p>公司简介</p>
</a>
<a href="">
<p>企业文化</p>
</a>
<a href="">
<p>发展历程</p>
</a>
</div>
<div class="footer-section">
<h4>联系我们</h4>
<p>电话123-456-7890</p>
<p>邮箱info@sf-express.com</p>
<p>地址中国福建省福州市</p>
</div>
<div class="footer-section">
<h4>关注我们</h4>
<p>QQ123456789</p>
<p>微博旭日快递</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 旭日速运有限公司. 版权所有</p>
</div>
</footer>
</div>
</template>
<script setup>
import {
ref,
computed,
onMounted
} from "vue";
import {
useRouter
} from "vue-router";
const router = useRouter();
const currentIndex = ref(0);
const carouselItems = ref([{
image: '/1.png',
title: '全程保障,畅行无忧',
description: '精确时效,完美物流体验'
},
{
image: '/2.png',
title: '智能物流,开创未来',
description: '深度融合科技,提升运输效率'
},
{
image: '/3.png',
title: '绿色运输,保护环境',
description: '低碳排放,绿色物流,让未来更美好'
}
]);
const nextSlide = () => {
currentIndex.value = (currentIndex.value + 1) % carouselItems.value.length;
};
const prevSlide = () => {
currentIndex.value = (currentIndex.value - 1 + carouselItems.value.length) % carouselItems.value.length;
};
const loginToRouter = () => {
router.push({
name: "login"
});
};
onMounted(() => {
setInterval(() => {
nextSlide();
}, 5000); // 5
});
</script>
<style scoped>
.sf-city-services {
font-family: 'Helvetica Neue', Arial, sans-serif;
background-color: #f5f5f5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background-color: #409EFF;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.logo {
display: flex;
align-items: center;
}
.logo-image {
width: 50px;
margin-right: 10px;
}
.title {
font-size: 1.8em;
font-weight: bold;
color: #fff;
letter-spacing: 1px;
}
nav ul {
list-style: none;
display: flex;
gap: 30px;
padding: 0;
margin-right: auto;
}
nav ul li a {
text-decoration: none;
color: #fff;
font-weight: bold;
transition: color 0.3s ease, opacity 0.3s ease;
font-size: 1.1em;
}
nav ul li a:hover {
color: #ffd700;
opacity: 0.8;
}
.auth {
font-size: 16px;
color: #fff;
padding: 10px 20px;
cursor: pointer;
border: 2px solid #ffd700;
border-radius: 5px;
transition: background-color 0.3s ease, color 0.3s ease;
}
.auth:hover {
background-color: #ffd700;
color: #409EFF;
opacity: 0.9;
}
.carousel {
position: relative;
overflow: hidden;
height: 500px;
width: 100%;
margin: 40px 0;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.carousel-item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
transition: transform 0.5s ease;
}
.carousel-item.active {
display: block;
}
.carousel-item img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 8px;
}
.carousel-caption {
position: absolute;
bottom: 30px;
left: 30px;
color: #fff;
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 4px;
}
.carousel-caption h2 {
font-size: 32px;
margin-bottom: 10px;
font-weight: 700;
}
.carousel-caption p {
font-size: 20px;
}
.carousel-control {
position: absolute;
top: 50%;
transform: translateY(-50%);
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
border: none;
padding: 15px;
cursor: pointer;
border-radius: 50%;
transition: background-color 0.3s ease;
}
.carousel-control:hover {
background-color: rgba(0, 0, 0, 0.7);
}
.carousel-control.prev {
left: 20px;
}
.carousel-control.next {
right: 20px;
}
.carousel-control i {
font-size: 30px;
}
.main-content {
max-width: 1200px;
margin: 40px auto;
background-color: #fff;
padding: 40px;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
flex: 1;
}
.main-content h1 {
font-size: 36px;
color: #333;
margin-bottom: 20px;
font-weight: 700;
}
.main-content h2 {
font-size: 28px;
color: #555;
margin-bottom: 20px;
}
.main-content p {
color: #666;
line-height: 1.8;
margin-bottom: 40px;
font-size: 18px;
}
.search-section {
display: flex;
gap: 15px;
margin-bottom: 40px;
align-items: center;
}
.search-input {
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
flex-grow: 1;
transition: border-color 0.3s ease;
font-size: 16px;
}
.search-input:focus {
border-color: #409EFF;
outline: none;
}
.search-button {
padding: 15px 25px;
background-color: #409EFF;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
font-size: 16px;
}
.search-button:hover {
background-color: #357bb3;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 30px;
margin-bottom: 40px;
}
.service-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
background-color: #fff;
transition: transform 0.3s ease, box-shadow 0.3s ease;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.service-item:hover {
transform: translateY(-5px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.service-item img {
width: 100%;
max-height: 150px;
object-fit: contain;
margin-bottom: 15px;
border-radius: 8px;
}
.additional-services {
text-align: center;
margin-bottom: 40px;
}
.additional-services h3 {
font-size: 32px;
color: #333;
font-weight: 700;
margin-bottom: 15px;
}
.additional-services p {
font-size: 18px;
color: #666;
line-height: 1.8;
max-width: 800px;
margin: 0 auto 30px;
}
.customer-service {
background-color: #f7f7f7;
padding: 40px;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.customer-service h4 {
font-size: 24px;
color: #333;
margin-bottom: 15px;
}
.footer {
background-color: #333;
color: #fff;
padding: 40px 20px;
}
.footer-content {
display: flex;
justify-content: space-between;
}
.footer-section {
flex: 1;
margin-right: 30px;
}
.footer-section:last-child {
margin-right: 0;
}
.footer-section h4 {
font-size: 20px;
margin-bottom: 15px;
font-weight: 700;
}
.footer-section p {
font-size: 14px;
color: #ccc;
margin: 5px 0;
}
.footer-bottom {
text-align: center;
font-size: 14px;
color: #ccc;
margin-top: 20px;
}
.footer-bottom p {
margin: 0;
}
</style>

@ -1,117 +0,0 @@
<template>
<div class="body-view">
<el-text class="mx-1">顺丰快递</el-text>
<el-text>{{ message }}</el-text>
<el-form class="form-view">
<el-form-item label="账号:" class="ipt-lbl">
<el-input placeholder="请输入账号" class="ipt" v-model="form.account" ></el-input>
</el-form-item>
<el-form-item label="密码:">
<el-input placeholder="请输入密码" type="password" class="ipt" v-model="form.password"></el-input>
</el-form-item>
<el-form-item class="btn-view">
<el-button class="btn" type="primary" @click="login"></el-button>
<el-button class="btn cancel-btn" type="primary" @click="register"></el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import request from '../request';
// import { request } from "../api"
import { useRouter } from 'vue-router';
import { userStore } from '../store';
import axios from "axios"
const store = userStore()
const isAdminRef = ref(false)
const form = reactive({
account: "",
password: ""
});
const router = useRouter();
const login = async () => {
try {
request({
method: 'post',
url: "/user/login",
data: {
loginId: form.account,
loginPwd: form.password
}
}).then(res => {
const token = res.headers["authentication"]
if (token) {
//
store.setToken(token)
store.setUserInfo(res.data.data)
if (store.getIsAdmin) {
router.push({ path: "/user/expressList" })
} else {
router.push({ path: "/user/myInfo" });
}
ElMessage({ message: "登录成功", type: "success" })
} else {
//
ElMessage({ message: res.data.msg, type: "error" })
}
})
}
catch (err) {
console.error(err, "请求错误")
}
}
function register() {
router.push({ name: "Register" });
}
</script>
<style>
.body-view {
border: 1px solid black;
width: 490px;
height: 425px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.mx-1 {
font-size: 25px;
margin-bottom: 20px;
}
.ipt-lbl {
font-size: 18px;
}
.ipt {
border: 1px solid black;
height: 50px;
}
.btn {
height: 40px;
width: 90px;
background-color: #0f63ff;
}
.btn-view {
margin-top: 30px;
margin-left: 15px;
}
.cancel-btn {
margin-left: 70px !important;
}
</style>

@ -1,201 +0,0 @@
<template>
<div class="body-view">
<el-text class="title">注册</el-text>
<el-form class="form-view" @submit.prevent="handleRegister">
<el-form-item label="账号:" :error="usernameError">
<el-input v-model="username" placeholder="请输入账号" class="ipt" @input="validateUsername"></el-input>
</el-form-item>
<el-form-item label="密码:" :error="passwordError">
<el-input type="password" v-model="password" placeholder="请输入密码" class="ipt"
@input="validatePassword"></el-input>
</el-form-item>
<el-form-item label="确认密码:" :error="confirmPasswordError">
<el-input type="password" v-model="confirmPassword" placeholder="请再次输入密码" class="ipt"
@input="validateConfirmPassword"></el-input>
</el-form-item>
<el-form-item>
<el-checkbox v-model="isAdminRef">
<span class="checkbox-label">我是快递员</span>
</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="isAgreed">
<span class="checkbox-label">我已阅读并同意用户协议</span>
</el-checkbox>
</el-form-item>
<el-form-item class="btn-view">
<div class="button-container">
<el-button class="btn" type="primary" @click="handleRegister"
:disabled="!isAgreed || !canRegister">注册</el-button>
<el-button class="btn cancel-btn" type="primary" @click="goToLogin"></el-button>
</div>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import req from '../request';
const username = ref('');
const password = ref('');
const confirmPassword = ref('');
const isAgreed = ref(false);
const usernameError = ref('');
const passwordError = ref('');
const confirmPasswordError = ref('');
const isAdminRef = ref(false);
const router = useRouter();
//
const isUsernameUnique = () => {
const accounts = JSON.parse(localStorage.getItem('accounts') || '[]');
return !accounts.some(account => account.username === username.value);
};
// 8
const validateUsername = () => {
if (!isUsernameUnique()) {
usernameError.value = '该账号已存在,请选择其他账号';
return false;
}
usernameError.value = '';
return true;
};
// 8
const validatePassword = () => {
if (password.value.length < 8) {
passwordError.value = '密码长度至少为8位';
return false;
}
if (!/[a-zA-Z]/.test(password.value) || !/\d/.test(password.value)) {
passwordError.value = '密码必须包含字母和数字';
return false;
}
passwordError.value = '';
return true;
};
//
const validateConfirmPassword = () => {
if (confirmPassword.value !== password.value) {
confirmPasswordError.value = '两次输入的密码不一致';
return false;
}
confirmPasswordError.value = '';
return true;
};
//
const canRegister = computed(() => validateUsername() && validatePassword() && validateConfirmPassword());
//
const handleRegister = () => {
if (canRegister.value) {
// localStorage
const data = {
loginId: username.value,
loginPwd: password.value
}
if (isAdminRef.value) {
data.isAdmin = true
}
req({
method: "POST",
url: "/user",
data
}).then((res) => {
ElMessage.success('注册成功!请返回登录');
router.push('/login'); // 使 Vue Router /login
})
} else {
ElMessage.error('请确保填写正确的信息');
}
};
//
const goToLogin = () => {
router.push('/login'); // 使 Vue Router /login
};
</script>
<style>
.body-view {
background-color: #f7f9fc;
border-radius: 12px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
width: 400px;
padding: 40px;
margin: 60px auto;
}
.title {
font-size: 32px;
font-weight: bold;
color: #007bff;
text-align: center;
margin-bottom: 25px;
}
.ipt {
border: 1px solid #ced4da;
height: 50px;
border-radius: 8px;
transition: border-color 0.3s;
}
.ipt:focus {
border-color: #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
}
.button-container {
display: flex;
justify-content: center;
gap: 10px;
width: 100%;
}
.btn {
height: 50px;
width: 100px;
background-color: #007bff;
border: none;
color: white;
margin: 0 30px;
font-size: 16px;
border-radius: 8px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #0056b3;
}
.btn-view {
margin-top: 30px;
text-align: center;
}
.checkbox-label {
font-size: 14px;
}
.el-checkbox {
margin-bottom: 5px;
}
</style>

@ -1,219 +0,0 @@
<template>
<el-row class="page">
<el-row class="block-view" v-for="(item, index) in expressList">
<el-row class="top">
<el-text>运单号: {{ item.expressid }}</el-text>
<el-text class="top-time">签收时间: {{ item.signedTime }}</el-text>
</el-row>
<el-row class="express-view">
<el-row class="express-no-view">
<el-text class="city">{{ item.senderCity }}</el-text>
<el-text class="user">{{ item.senderName }}</el-text>
</el-row>
<el-row class="express-no-view">
<el-image class="arrow" src="/arrow.png" />
<el-text class="sign">{{ item.isSigned ? "已签收" : "未签收" }}</el-text>
</el-row>
<el-row class="express-no-view">
<el-text class="city">{{ item.receiverCity }}</el-text>
<el-text class="user">{{ item.receiverName }}</el-text>
</el-row>
<el-row class="express-icon-view">
<el-icon @click="deleteByIndex(index)">
<Delete />
</el-icon>
<el-icon @click="modify(item, index)">
<Edit />
</el-icon>
</el-row>
</el-row>
<el-row class="line-view"></el-row>
</el-row>
<el-dialog v-model="dialogVisible" title="警告" width="500" :before-close="handleClose">
<span>你确定要删除这条快递信息吗</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="deleteByIndexConfirm()">
确定
</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="dialogFormVisible" title="快递表单修改" width="500">
<el-form :model="form">
<el-form-item label="寄送城市" :label-width="formLabelWidth">
<el-input v-model="form.senderCity" autocomplete="off" />
</el-form-item>
<el-form-item label="寄送人" :label-width="formLabelWidth">
<el-input v-model="form.senderName" autocomplete="off" />
</el-form-item>
<el-form-item label="收件城市" :label-width="formLabelWidth">
<el-input v-model="form.receiverCity" autocomplete="off" />
</el-form-item>
<el-form-item label="收件人" :label-width="formLabelWidth">
<el-input v-model="form.receiverName" autocomplete="off" />
</el-form-item>
<el-form-item label="签收时间" :label-width="formLabelWidth">
<el-input v-model="form.signedTime" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="modifyConfirm()">
确定
</el-button>
</div>
</template>
</el-dialog>
</el-row>
</template>
<script setup>
import { Delete, Edit } from '@element-plus/icons-vue';
import { ref, watchEffect, onMounted } from 'vue';
import { ElMessageBox } from 'element-plus';
import { useExpressStore } from "../../store"
import { getExpressForm } from "../../utils/tools"
const expressStore = useExpressStore()
const expressList = ref(expressStore.getUnSignedList)
// watchEffect(async () => {
// if (expressStore.expressList.length === 0) {
// await expressStore.getExpress();
// }
// expressList.value = expressStore.expressList;
// });
const form = ref(getExpressForm())
const dialogVisible = ref(false)
const dialogFormVisible = ref(false)
const formLabelWidth = '140px'
//
let formIndex = -1
const deleteByIndex = (index) => {
dialogVisible.value = true
formIndex = index
}
const deleteByIndexConfirm = () => {
dialogVisible.value = false
expressStore.deleteExpress(form, formIndex)
}
const modify = (item, index) => {
dialogFormVisible.value = true
const formTable = form.value
formTable.senderCity = item.senderCity
formTable.senderName = item.senderName
formTable.receiverCity = item.receiverCity
formTable.receiverName = item.receiverName
formTable.signedTime = item.signedTime
formIndex = index
}
const modifyConfirm = () => {
dialogFormVisible.value = false
expressStore.modifyExpress(form, formIndex)
}
const handleClose = (done) => {
ElMessageBox.confirm('你确定要关闭吗?')
.then(() => {
done()
})
.catch(() => {
// catch error
})
}
</script>
<style>
.page {
display: flex;
flex-direction: column;
width: 100%;
background-color: white;
line-height: 20px;
}
.block-view {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.top {
display: flex;
justify-content: flex-start;
width: 100%;
/* margin-left: 20px; */
padding-left: 20px;
color: gray;
font-size: 12px;
}
.top-time {
margin-left: 690px;
}
.express-view {
display: flex;
flex-flow: row;
justify-content: space-between;
width: 100%;
padding-left: 20px;
}
.express-no-view {
display: flex;
flex-direction: column;
/* justify-content: space-around; */
}
.arrow {
width: 40px;
height: 10px;
}
.city {
font-size: 20px;
margin-bottom: 10px;
}
.user {
color: gray;
}
.sign {
color: red;
margin-top: 10px;
}
.express-icon-view {
/* width: 100%; */
width: 50px;
margin-right: 50px;
justify-content: space-around;
flex-direction: row;
}
.line-view {
height: 0.5px;
width: 95%;
background-color: lightgray;
margin-top: 20px;
margin-bottom: 20px;
}
</style>

@ -1,98 +0,0 @@
<template>
<div>
<el-row class="top">
<el-col :span="6" class="col">个人信息</el-col>
<el-col :span="6" class="col-exit" @click="userStore_.logoutUser"></el-col>
</el-row>
<el-row class="body">
<el-image class="user-img" src="/user.png"></el-image>
<el-text class="phone">{{ userInfo.loginId }}</el-text>
<el-form label-width="auto" style="max-width: 600px;">
<el-form-item label="性别">
<el-select v-model="userInfo.sex" placeholder="男">
<el-option>
<el-radio-group v-model="userInfo.sex">
<el-radio value="男" size="large"></el-radio>
<el-radio value="女" size="large"></el-radio>
</el-radio-group>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="生日">
<el-date-picker v-model="userInfo.brithday" type="date" placeholder="Pick a day"
format="YYYY-MM-DD" />
</el-form-item>
<el-form-item label="地区">
<el-input v-model="userInfo.region"></el-input>
</el-form-item>
<el-form-item label="绑定手机">
<el-input v-model="userInfo.number"></el-input>
</el-form-item>
<el-button class="btn" type="primary" @click="updateUserInfo"></el-button>
</el-form>
</el-row>
</div>
</template>
<script setup>
import { userStore } from '../../store';
import { reactive } from 'vue';
const userStore_ = userStore()
const userInfo = reactive({ ...userStore_.getUserInfo })
function updateUserInfo() {
console.log(userInfo)
//
userStore_.updateUserInfo(userInfo)
}
</script>
<style>
.top {
background-color: white;
height: 50px;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
border-radius: 10px;
}
.col {
font-size: 20px;
display: flex;
flex-direction: row;
justify-content: flex-start;
padding-left: 20px;
}
.col-exit {
font-size: 12px;
display: flex;
flex-direction: row;
justify-content: flex-start;
padding-left: 20px;
}
.body {
background-color: white;
margin-top: 20px;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
line-height: 0px;
}
.user-img {
width: 100px;
height: 100px;
}
.phone {
margin-top: 20px;
font-size: 14px;
margin-bottom: 20px;
}
</style>

@ -1,219 +0,0 @@
<template>
<el-row class="page">
<el-row class="block-view" v-for="(item, index) in expressList">
<el-row class="top">
<el-text>运单号: {{ item.expressid }}</el-text>
<el-text class="top-time">签收时间: {{ item.signedTime }}</el-text>
</el-row>
<el-row class="express-view">
<el-row class="express-no-view">
<el-text class="city">{{ item.senderCity }}</el-text>
<el-text class="user">{{ item.senderName }}</el-text>
</el-row>
<el-row class="express-no-view">
<el-image class="arrow" src="/arrow.png" />
<el-text class="sign">{{ item.isSigned ? "已签收" : "未签收" }}</el-text>
</el-row>
<el-row class="express-no-view">
<el-text class="city">{{ item.receiverCity }}</el-text>
<el-text class="user">{{ item.receiverName }}</el-text>
</el-row>
<el-row class="express-icon-view">
<el-icon @click="deleteByIndex(index)">
<Delete />
</el-icon>
<el-icon @click="modify(item, index)">
<Edit />
</el-icon>
</el-row>
</el-row>
<el-row class="line-view"></el-row>
</el-row>
<el-dialog v-model="dialogVisible" title="警告" width="500" :before-close="handleClose">
<span>你确定要删除这条快递信息吗</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="deleteByIndexConfirm()">
确定
</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="dialogFormVisible" title="快递表单修改" width="500">
<el-form :model="form">
<el-form-item label="寄送城市" :label-width="formLabelWidth">
<el-input v-model="form.senderCity" autocomplete="off" />
</el-form-item>
<el-form-item label="寄送人" :label-width="formLabelWidth">
<el-input v-model="form.senderName" autocomplete="off" />
</el-form-item>
<el-form-item label="收件城市" :label-width="formLabelWidth">
<el-input v-model="form.receiverCity" autocomplete="off" />
</el-form-item>
<el-form-item label="收件人" :label-width="formLabelWidth">
<el-input v-model="form.receiverName" autocomplete="off" />
</el-form-item>
<el-form-item label="签收时间" :label-width="formLabelWidth">
<el-input v-model="form.signedTime" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="modifyConfirm()">
确定
</el-button>
</div>
</template>
</el-dialog>
</el-row>
</template>
<script setup>
import { Delete, Edit } from '@element-plus/icons-vue';
import { ref, watchEffect, onMounted } from 'vue';
import { ElMessageBox } from 'element-plus';
import { useExpressStore } from "../../store"
import { getExpressForm } from "../../utils/tools"
const expressStore = useExpressStore()
const expressList = ref(expressStore.getSignedList)
// watchEffect(async () => {
// if (expressStore.expressList.length === 0) {
// await expressStore.getExpress();
// }
// expressList.value = expressStore.expressList;
// });
const form = ref(getExpressForm())
const dialogVisible = ref(false)
const dialogFormVisible = ref(false)
const formLabelWidth = '140px'
//
let formIndex = -1
const deleteByIndex = (index) => {
dialogVisible.value = true
formIndex = index
}
const deleteByIndexConfirm = () => {
dialogVisible.value = false
expressStore.deleteExpress(form, formIndex)
}
const modify = (item, index) => {
dialogFormVisible.value = true
const formTable = form.value
formTable.senderCity = item.senderCity
formTable.senderName = item.senderName
formTable.receiverCity = item.receiverCity
formTable.receiverName = item.receiverName
formTable.signedTime = item.signedTime
formIndex = index
}
const modifyConfirm = () => {
dialogFormVisible.value = false
expressStore.modifyExpress(form, formIndex)
}
const handleClose = (done) => {
ElMessageBox.confirm('你确定要关闭吗?')
.then(() => {
done()
})
.catch(() => {
// catch error
})
}
</script>
<style>
.page {
display: flex;
flex-direction: column;
width: 100%;
background-color: white;
line-height: 20px;
}
.block-view {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.top {
display: flex;
justify-content: flex-start;
width: 100%;
/* margin-left: 20px; */
padding-left: 20px;
color: gray;
font-size: 12px;
}
.top-time {
margin-left: 690px;
}
.express-view {
display: flex;
flex-flow: row;
justify-content: space-between;
width: 100%;
padding-left: 20px;
}
.express-no-view {
display: flex;
flex-direction: column;
/* justify-content: space-around; */
}
.arrow {
width: 40px;
height: 10px;
}
.city {
font-size: 20px;
margin-bottom: 10px;
}
.user {
color: gray;
}
.sign {
color: red;
margin-top: 10px;
}
.express-icon-view {
/* width: 100%; */
width: 50px;
margin-right: 50px;
justify-content: space-around;
flex-direction: row;
}
.line-view {
height: 0.5px;
width: 95%;
background-color: lightgray;
margin-top: 20px;
margin-bottom: 20px;
}
</style>

@ -1,153 +0,0 @@
<template>
<div class="common-layout">
<el-container>
<el-header>
<el-menu class="el-menu-demo" mode="horizontal">
<el-menu-item index="1">
<el-image class="logo" src="/logo.png"></el-image>
</el-menu-item>
<el-menu-item index="1">
<el-text>首页</el-text>
</el-menu-item>
<el-menu-item index="2">
<el-sub-menu>
<template #title>物流服务</template>
<el-menu-item index="2-1">即使配送</el-menu-item>
<el-menu-item index="2-2">快递配送</el-menu-item>
<el-menu-item index="2-3">国际服务</el-menu-item>
<el-sub-menu index="2-4">
<template #title>附加费</template>
<el-menu-item index="2-4-1">长途</el-menu-item>
<el-menu-item index="2-4-2">短途</el-menu-item>
<el-menu-item index="2-4-3">跨国</el-menu-item>
</el-sub-menu>
</el-sub-menu>
</el-menu-item>
<el-menu-item index="4">欢迎您 {{ userStore_.getUserInfo.loginId }} {{ userStore_.getIsAdmin ? "快递员" :
"用户" }}</el-menu-item>
<el-menu-item index="5" @click="userStore_.logoutUser">退</el-menu-item>
</el-menu>
</el-header>
<el-container>
<el-aside width="200px" class="el-aside">
<el-row class="tac">
<el-col>
<el-menu default-active="2" class="el-menu-vertical-demo" v-if="!userStore_.getIsAdmin">
<el-sub-menu index="1">
<template #title>
<el-icon>
<location />
</el-icon>
<span>我要寄件</span>
</template>
<el-menu-item-group>
<router-link to="/user/expressform">
<el-menu-item index="1-1">寄快递</el-menu-item>
<el-menu-item index="1-2">批量寄</el-menu-item>
</router-link>
</el-menu-item-group>
</el-sub-menu>
<el-menu-item index="2">
<router-link to="/user/myInfo">
<el-icon>
<document />
</el-icon>
<span>我的资料</span>
</router-link>
</el-menu-item>
</el-menu>
<el-menu default-active="2" class="el-menu-vertical-demo" v-else>
<el-menu-item index="1">
<router-link to="/user/expressList">
<el-icon><icom-menu /></el-icon>
<span>未签收</span>
</router-link>
</el-menu-item>
<el-menu-item index="2">
<router-link to="/user/signed">
<el-icon><icom-menu /></el-icon>
<span>已签收</span>
</router-link>
</el-menu-item>
</el-menu>
</el-col>
</el-row>
</el-aside>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup>
import { userStore } from '../../store';
import { ref, onBeforeMount } from "vue"
const userStore_ = userStore()
</script>
<style>
.common-layout {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.el-header,
.el-footer {
background-color: white;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #d9ecff;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #ecf5ff;
color: #333;
text-align: center;
line-height: 160px;
}
.el-container {
height: 100%;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
.logo {
height: 58px;
}
.el-menu--horizontal>.el-menu-item:nth-child(3) {
margin-right: auto;
}
</style>

@ -0,0 +1,37 @@
const jwt = require("jsonwebtoken")
const md5 = require("md5")
module.exports.formatResponse = function (code, msg, data) {
return {
code,
msg,
data
}
}
module.exports.analysisToken = function (token) {
return jwt.verify(token.split(" ")[1], md5(process.env.JWT_SECRET))
}
module.exports.getJwtToken = function (payload) {
let loginPeriod = 1; //默认记住一天
return jwt.sign(payload, md5(process.env.JWT_SECRET), {
expiresIn: 60 * 60 * 24 * loginPeriod
})
}
module.exports.getRandomExpressId = function () {
return "SF" + Math.floor(Math.random() * 1000000000000)
}
module.exports.handleArrayDaoData = function (arr) {
const result = []
// for (const item of arr) {
// result.push(item.dataValues)
// }
//倒叙输出
for (let i = arr.length - 1; i >= 0; i--) {
result.push(arr[i].dataValues)
}
return result
}

@ -1,16 +0,0 @@
import {
defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
// export default defineConfig({
// plugins: [vue()],
// })
export default {
plugins: [vue()],
server: {
port: 3001
}
};

@ -1,478 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/helper-string-parser@^7.24.8":
version "7.24.8"
resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz"
integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
"@babel/helper-validator-identifier@^7.24.7":
version "7.24.7"
resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz"
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
"@babel/parser@^7.24.7":
version "7.25.4"
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.4.tgz"
integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==
dependencies:
"@babel/types" "^7.25.4"
"@babel/types@^7.25.4":
version "7.25.4"
resolved "https://registry.npmmirror.com/@babel/types/-/types-7.25.4.tgz"
integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==
dependencies:
"@babel/helper-string-parser" "^7.24.8"
"@babel/helper-validator-identifier" "^7.24.7"
to-fast-properties "^2.0.0"
"@ctrl/tinycolor@^3.4.1":
version "3.6.1"
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
"@element-plus/icons-vue@^2.3.1":
version "2.3.1"
resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz"
integrity sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==
"@esbuild/win32-x64@0.21.5":
version "0.21.5"
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz"
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
"@floating-ui/core@^1.6.0":
version "1.6.8"
resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz"
integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
dependencies:
"@floating-ui/utils" "^0.2.8"
"@floating-ui/dom@^1.0.1":
version "1.6.11"
resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz"
integrity sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==
dependencies:
"@floating-ui/core" "^1.6.0"
"@floating-ui/utils" "^0.2.8"
"@floating-ui/utils@^0.2.8":
version "0.2.8"
resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz"
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
"@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0"
resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7":
version "2.11.7"
resolved "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz"
integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==
"@rollup/rollup-win32-x64-msvc@4.21.1":
version "4.21.1"
resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz"
integrity sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==
"@types/estree@1.0.5":
version "1.0.5"
resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
"@types/lodash-es@*", "@types/lodash-es@^4.17.6":
version "4.17.12"
resolved "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz"
integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==
dependencies:
"@types/lodash" "*"
"@types/lodash@*", "@types/lodash@^4.14.182":
version "4.17.12"
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.12.tgz"
integrity sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==
"@types/web-bluetooth@^0.0.16":
version "0.0.16"
resolved "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz"
integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==
"@vitejs/plugin-vue@^5.1.2":
version "5.1.2"
resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.1.2.tgz"
integrity sha512-nY9IwH12qeiJqumTCLJLE7IiNx7HZ39cbHaysEUd+Myvbz9KAqd2yq+U01Kab1R/H1BmiyM2ShTYlNH32Fzo3A==
"@vue/compiler-core@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.38.tgz"
integrity sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==
dependencies:
"@babel/parser" "^7.24.7"
"@vue/shared" "3.4.38"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz"
integrity sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==
dependencies:
"@vue/compiler-core" "3.4.38"
"@vue/shared" "3.4.38"
"@vue/compiler-sfc@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz"
integrity sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==
dependencies:
"@babel/parser" "^7.24.7"
"@vue/compiler-core" "3.4.38"
"@vue/compiler-dom" "3.4.38"
"@vue/compiler-ssr" "3.4.38"
"@vue/shared" "3.4.38"
estree-walker "^2.0.2"
magic-string "^0.30.10"
postcss "^8.4.40"
source-map-js "^1.2.0"
"@vue/compiler-ssr@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz"
integrity sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==
dependencies:
"@vue/compiler-dom" "3.4.38"
"@vue/shared" "3.4.38"
"@vue/devtools-api@^6.4.5", "@vue/devtools-api@^6.6.4":
version "6.6.4"
resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz"
integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==
"@vue/reactivity@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.38.tgz"
integrity sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==
dependencies:
"@vue/shared" "3.4.38"
"@vue/runtime-core@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.38.tgz"
integrity sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==
dependencies:
"@vue/reactivity" "3.4.38"
"@vue/shared" "3.4.38"
"@vue/runtime-dom@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz"
integrity sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==
dependencies:
"@vue/reactivity" "3.4.38"
"@vue/runtime-core" "3.4.38"
"@vue/shared" "3.4.38"
csstype "^3.1.3"
"@vue/server-renderer@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.38.tgz"
integrity sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==
dependencies:
"@vue/compiler-ssr" "3.4.38"
"@vue/shared" "3.4.38"
"@vue/shared@3.4.38":
version "3.4.38"
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.38.tgz"
integrity sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==
"@vueuse/core@^9.1.0":
version "9.13.0"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz"
integrity sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==
dependencies:
"@types/web-bluetooth" "^0.0.16"
"@vueuse/metadata" "9.13.0"
"@vueuse/shared" "9.13.0"
vue-demi "*"
"@vueuse/metadata@9.13.0":
version "9.13.0"
resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz"
integrity sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==
"@vueuse/shared@9.13.0":
version "9.13.0"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz"
integrity sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==
dependencies:
vue-demi "*"
async-validator@^4.2.5:
version "4.2.5"
resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz"
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.2.1:
version "1.2.1"
resolved "https://registry.npmmirror.com/axios/-/axios-1.2.1.tgz"
integrity sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
dayjs@^1.11.13:
version "1.11.13"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
element-plus@^2.9.0:
version "2.9.0"
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.0.tgz"
integrity sha512-ccOFXKsauo2dtokAr4OX7gZsb7TuAoVxA2zGRZo5o2yyDDBLBaZxOoFQPoxITSLcHbBfQuNDGK5Iag5hnyKkZA==
dependencies:
"@ctrl/tinycolor" "^3.4.1"
"@element-plus/icons-vue" "^2.3.1"
"@floating-ui/dom" "^1.0.1"
"@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7"
"@types/lodash" "^4.14.182"
"@types/lodash-es" "^4.17.6"
"@vueuse/core" "^9.1.0"
async-validator "^4.2.5"
dayjs "^1.11.13"
escape-html "^1.0.3"
lodash "^4.17.21"
lodash-es "^4.17.21"
lodash-unified "^1.0.2"
memoize-one "^6.0.0"
normalize-wheel-es "^1.2.0"
entities@^4.5.0:
version "4.5.0"
resolved "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
esbuild@^0.21.3:
version "0.21.5"
resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz"
integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==
optionalDependencies:
"@esbuild/aix-ppc64" "0.21.5"
"@esbuild/android-arm" "0.21.5"
"@esbuild/android-arm64" "0.21.5"
"@esbuild/android-x64" "0.21.5"
"@esbuild/darwin-arm64" "0.21.5"
"@esbuild/darwin-x64" "0.21.5"
"@esbuild/freebsd-arm64" "0.21.5"
"@esbuild/freebsd-x64" "0.21.5"
"@esbuild/linux-arm" "0.21.5"
"@esbuild/linux-arm64" "0.21.5"
"@esbuild/linux-ia32" "0.21.5"
"@esbuild/linux-loong64" "0.21.5"
"@esbuild/linux-mips64el" "0.21.5"
"@esbuild/linux-ppc64" "0.21.5"
"@esbuild/linux-riscv64" "0.21.5"
"@esbuild/linux-s390x" "0.21.5"
"@esbuild/linux-x64" "0.21.5"
"@esbuild/netbsd-x64" "0.21.5"
"@esbuild/openbsd-x64" "0.21.5"
"@esbuild/sunos-x64" "0.21.5"
"@esbuild/win32-arm64" "0.21.5"
"@esbuild/win32-ia32" "0.21.5"
"@esbuild/win32-x64" "0.21.5"
escape-html@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
estree-walker@^2.0.2:
version "2.0.2"
resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
follow-redirects@^1.15.0:
version "1.15.9"
resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
form-data@^4.0.0:
version "4.0.1"
resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz"
integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
lodash-es@*, lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash-unified@^1.0.2:
version "1.0.3"
resolved "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz"
integrity sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==
lodash@*, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
magic-string@^0.30.10:
version "0.30.11"
resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz"
integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
memoize-one@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz"
integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
normalize-wheel-es@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz"
integrity sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==
picocolors@^1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz"
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
pinia@2.0.27:
version "2.0.27"
resolved "https://registry.npmjs.org/pinia/-/pinia-2.0.27.tgz"
integrity sha512-nOnXP0OFeL8R4WjAHsterU+11vptda643gH02xKNtSCDPiRzVfRYodOLihLDoa0gL1KKuQKV+KOzEgdt3YvqEw==
dependencies:
"@vue/devtools-api" "^6.4.5"
vue-demi "*"
postcss@^8.4.40, postcss@^8.4.41:
version "8.4.41"
resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.41.tgz"
integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.1"
source-map-js "^1.2.0"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
rollup@^4.20.0:
version "4.21.1"
resolved "https://registry.npmmirror.com/rollup/-/rollup-4.21.1.tgz"
integrity sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==
dependencies:
"@types/estree" "1.0.5"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.21.1"
"@rollup/rollup-android-arm64" "4.21.1"
"@rollup/rollup-darwin-arm64" "4.21.1"
"@rollup/rollup-darwin-x64" "4.21.1"
"@rollup/rollup-linux-arm-gnueabihf" "4.21.1"
"@rollup/rollup-linux-arm-musleabihf" "4.21.1"
"@rollup/rollup-linux-arm64-gnu" "4.21.1"
"@rollup/rollup-linux-arm64-musl" "4.21.1"
"@rollup/rollup-linux-powerpc64le-gnu" "4.21.1"
"@rollup/rollup-linux-riscv64-gnu" "4.21.1"
"@rollup/rollup-linux-s390x-gnu" "4.21.1"
"@rollup/rollup-linux-x64-gnu" "4.21.1"
"@rollup/rollup-linux-x64-musl" "4.21.1"
"@rollup/rollup-win32-arm64-msvc" "4.21.1"
"@rollup/rollup-win32-ia32-msvc" "4.21.1"
"@rollup/rollup-win32-x64-msvc" "4.21.1"
fsevents "~2.3.2"
source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
vite@^5.0.0, vite@^5.4.1:
version "5.4.2"
resolved "https://registry.npmmirror.com/vite/-/vite-5.4.2.tgz"
integrity sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.41"
rollup "^4.20.0"
optionalDependencies:
fsevents "~2.3.3"
vue-demi@*:
version "0.14.10"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz"
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
vue-router@4:
version "4.4.5"
resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.4.5.tgz"
integrity sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==
dependencies:
"@vue/devtools-api" "^6.6.4"
"vue@^2.6.14 || ^3.2.0", "vue@^3.0.0-0 || ^2.6.0", vue@^3.2.0, vue@^3.2.25, vue@^3.4.37, vue@3.4.38:
version "3.4.38"
resolved "https://registry.npmmirror.com/vue/-/vue-3.4.38.tgz"
integrity sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==
dependencies:
"@vue/compiler-dom" "3.4.38"
"@vue/compiler-sfc" "3.4.38"
"@vue/runtime-dom" "3.4.38"
"@vue/server-renderer" "3.4.38"
"@vue/shared" "3.4.38"
Loading…
Cancel
Save