Compare commits

..

48 Commits
jhj ... main

Author SHA1 Message Date
云静雪夏 7a0e9bbc48 Merge branch 'main' of https://bdgit.educoder.net/fdzcxy212206413/jty
5 months ago
云静雪夏 36c0a9dbee 前端部分代码
5 months ago
fdzcxy212206413 77a83d6869 Merge pull request '所有项目代码' (#1) from grs into main
5 months ago
yjxx 70959b00f0 所有项目完成!
5 months ago
yjxx 157de6830e 所有项目完成!
5 months ago
yjxx 4ae25f1c6b 所有项目完成!
6 months ago
yjxx 6b54e769fd 所有项目完成!
6 months ago
yjxx 8f3c97fa52 小修改
6 months ago
yjxx 83e365d75d 终于尼玛调试完了用户,就差代取和快递员了!!!!
6 months ago
yjxx 0abbaab6f8 小修改
6 months ago
yjxx 7101d6b7d2 封装快递记录查询
6 months ago
yjxx e8d409bd38 修改用户查看别人发给自己的消息
6 months ago
yjxx 754d59c9b4 小修改
6 months ago
yjxx 42b288d23c 寄件和收件不能是同一个地方
6 months ago
yjxx ce7718f68c 寄件和收件不能是同一个地方
6 months ago
yjxx cf59446afc 添加了重量自定义注解
6 months ago
yjxx 9ef8ec7a6b 真对寄件进行修改
6 months ago
yjxx 8a149c54b6 小修改
6 months ago
yjxx d3382cda09 用户功能的用户查询快递
6 months ago
yjxx 3b1fb1aa13 管理员功能全部实现
7 months ago
yjxx 7dd2f481ac 管理员获取正在留言的人的所有聊天记录
7 months ago
yjxx c97c4a15db 小修改
7 months ago
yjxx 59db863195 小修改
7 months ago
yjxx 90cfec7d93 管理员获取所有快递信息
7 months ago
yjxx 31ba23d47f 小修改
7 months ago
yjxx 53aa97a461 小修改
7 months ago
yjxx 8e1250df12 小修改
7 months ago
yjxx de12494bbd 小修改
7 months ago
yjxx ba7d5d8709 小修改
7 months ago
yjxx b320b3e34c 小修改
7 months ago
yjxx 2e3d44d4f9 阶段四:快递员功能
7 months ago
yjxx c1766f3259 阶段四:快递员功能
7 months ago
yjxx 9c33185231 管理员和用户功能成功通过Postman测试验收
7 months ago
yjxx 93febaf68e 小修改
7 months ago
yjxx 7a12313da6 项目三阶段:用户功能(未测试版本)
7 months ago
yjxx 1b19f8ee70 项目三阶段:用户功能(未测试版本)
7 months ago
yjxx 038760b094 项目一阶段和二阶段通过测试验收
7 months ago
yjxx 9e65e55290 小修改
7 months ago
yjxx 5eef15f557 小修改
7 months ago
yjxx 1b0cb41766 小修改
7 months ago
yjxx 71a93b0515 验收通用功能并进行修改
7 months ago
yjxx 0bfdba7e35 验收通用功能并进行修改
7 months ago
yjxx bdaec402ed 项目阶段二:管理员功能
7 months ago
yjxx c202b4f240 项目一阶段: 细节修改
7 months ago
yjxx 180019adae 项目一阶段功能增加:用户禁用功能
7 months ago
yjxx a65b2c1f2b Merge branch 'grs' of https://bdgit.educoder.net/fdzcxy212206413/jty into grs
7 months ago
yjxx bc581dbe4f 项目一阶段:完成用户 管理员 快递员的通用功能
7 months ago
fdzcxy212206413 5f807caef5 Delete 'README.md'
7 months ago

2
.gitattributes vendored

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

33
.gitignore vendored

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -0,0 +1,20 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
distributionSha256Sum=4ec3f26fb1a692473aea0235c300bd20f0f9fe741947c82c1234cefd76ac3a3c

@ -1,2 +0,0 @@
# jty

@ -1,191 +0,0 @@
/*
Navicat Premium Dump SQL
Source Server : GRS
Source Server Type : MySQL
Source Server Version : 80039 (8.0.39)
Source Host : localhost:3306
Source Schema : distribution
Target Server Type : MySQL
Target Server Version : 80039 (8.0.39)
File Encoding : 65001
Date: 01/11/2024 16:28:33
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for address
-- ----------------------------
DROP TABLE IF EXISTS `address`;
CREATE TABLE `address` (
`id` bigint NOT NULL COMMENT '地址id',
`user_id` bigint NOT NULL COMMENT '用户id',
`address` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id`(`user_id` ASC) USING BTREE,
CONSTRAINT `address_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of address
-- ----------------------------
INSERT INTO `address` VALUES (1848323292988100610, 1848316858330193922, '福建省福州市仓山区上三路83号程埔市场二期807单元');
INSERT INTO `address` VALUES (1848533495658516482, 1848316858330193922, '福建省福州市鼓楼区洪山镇杨桥西路50号福州大学至诚学院');
-- ----------------------------
-- Table structure for code
-- ----------------------------
DROP TABLE IF EXISTS `code`;
CREATE TABLE `code` (
`id` bigint NOT NULL COMMENT '取件码id',
`goods_id` bigint NOT NULL COMMENT '快递id',
`claim` varchar(24) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '快递取件码',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `claim`(`claim` ASC) USING BTREE,
INDEX `goods_id`(`goods_id` ASC) USING BTREE,
CONSTRAINT `code_ibfk_1` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of code
-- ----------------------------
INSERT INTO `code` VALUES (1848543466148241409, 1848543466089521153, 'YT20241022095441280761');
INSERT INTO `code` VALUES (1848543555377864707, 1848543555310755841, 'YT20241022095502ba779d');
INSERT INTO `code` VALUES (1848543604971315203, 1848543604904206338, 'YT20241022095514d79301');
INSERT INTO `code` VALUES (1848543646071300098, 1848543645941276674, 'YT20241022095524a92edc');
INSERT INTO `code` VALUES (1848544752541249538, 1848544752499306498, 'YT20241022095947f33114');
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` bigint NOT NULL COMMENT '快递id',
`send_user_id` bigint NOT NULL COMMENT '发件人',
`get_user_id` bigint NOT NULL COMMENT '收件人',
`express_code` varchar(24) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '快递码',
`name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '快递名称',
`quality` int NOT NULL COMMENT '快递重量',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `express_code`(`express_code` ASC) USING BTREE,
INDEX `send_user_id`(`send_user_id` ASC) USING BTREE,
INDEX `get_user_id`(`get_user_id` ASC) USING BTREE,
CONSTRAINT `goods_ibfk_1` FOREIGN KEY (`send_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `goods_ibfk_2` FOREIGN KEY (`get_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES (1848543466089521153, 1848316858330193922, 1848523815259402241, 'YT202410220954413b5cce41', 'java开发手册', 1);
INSERT INTO `goods` VALUES (1848543555310755841, 1848316858330193922, 1848523815259402241, 'YT202410220955028c641f14', '高考一百天冲刺卷子', 1);
INSERT INTO `goods` VALUES (1848543604904206338, 1848316858330193922, 1848523815259402241, 'YT20241022095514a6640e96', 'gsl的秘密', 1);
INSERT INTO `goods` VALUES (1848543645941276674, 1848316858330193922, 1848523815259402241, 'YT20241022095524ea6ed7b3', 'Linux手册', 1);
INSERT INTO `goods` VALUES (1848544752499306498, 1848523815259402241, 1848316858330193922, 'YT20241022095947a0dbda6c', '犯罪指南', 1);
-- ----------------------------
-- Table structure for message
-- ----------------------------
DROP TABLE IF EXISTS `message`;
CREATE TABLE `message` (
`id` bigint NOT NULL COMMENT '消息id',
`content` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL COMMENT '留言',
`send_user_id` bigint NOT NULL COMMENT '留言者',
`get_user_id` bigint NOT NULL COMMENT '给谁留言的',
`mark` int NULL DEFAULT 1 COMMENT '0: 留言被查看 1: 留言暂未查看',
`create_time` datetime NULL DEFAULT NULL COMMENT '发送时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '确认消息时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `message_ibfk_1`(`send_user_id` ASC) USING BTREE,
INDEX `message_ibfk_2`(`get_user_id` ASC) USING BTREE,
CONSTRAINT `message_ibfk_1` FOREIGN KEY (`send_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `message_ibfk_2` FOREIGN KEY (`get_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of message
-- ----------------------------
INSERT INTO `message` VALUES (1848314247455617026, '快递员一号你好,我是管理员', 1848310231438860290, 1848313214998306817, 1, '2024-10-21 18:43:51', '2024-10-21 18:43:51');
INSERT INTO `message` VALUES (1848318276436901890, '快递员一号你好我是grs可以找你帮我发快递吗', 1848316858330193922, 1848313214998306817, 1, '2024-10-21 18:59:52', '2024-10-21 18:59:52');
INSERT INTO `message` VALUES (1848320484234637313, '官榕胜同学你好', 1848310231438860290, 1848316858330193922, 0, '2024-10-21 19:08:38', '2024-10-21 19:08:38');
INSERT INTO `message` VALUES (1848891911719559169, '官榕胜同学,请签收一下你的快递,谢谢了', 1848313214998306817, 1848316858330193922, 1, '2024-10-23 08:59:17', '2024-10-23 08:59:17');
-- ----------------------------
-- Table structure for records
-- ----------------------------
DROP TABLE IF EXISTS `records`;
CREATE TABLE `records` (
`id` bigint NOT NULL COMMENT '快递记录id',
`send_user_id` bigint NOT NULL COMMENT '寄件人',
`get_user_id` bigint NOT NULL COMMENT '收件人',
`addressee_id` bigint NULL DEFAULT NULL COMMENT '签收者',
`express_id` bigint NOT NULL COMMENT '快递员',
`address_id` bigint NOT NULL COMMENT '送到哪里',
`goods_id` bigint NOT NULL COMMENT '物品信息',
`mark` int NULL DEFAULT 0 COMMENT '0: 未签收 1: 已签收',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `send_user_id`(`send_user_id` ASC) USING BTREE,
INDEX `get_user_id`(`get_user_id` ASC) USING BTREE,
INDEX `addressee_id`(`addressee_id` ASC) USING BTREE,
INDEX `goods_id`(`goods_id` ASC) USING BTREE,
INDEX `express_id`(`express_id` ASC) USING BTREE,
INDEX `address_id`(`address_id` ASC) USING BTREE,
CONSTRAINT `records_ibfk_1` FOREIGN KEY (`send_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `records_ibfk_2` FOREIGN KEY (`get_user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `records_ibfk_3` FOREIGN KEY (`addressee_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `records_ibfk_4` FOREIGN KEY (`goods_id`) REFERENCES `goods` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `records_ibfk_5` FOREIGN KEY (`express_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT,
CONSTRAINT `records_ibfk_6` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of records
-- ----------------------------
INSERT INTO `records` VALUES (1848543466089521154, 1848316858330193922, 1848523815259402241, NULL, 1848313214998306817, 1848533495658516482, 1848543466089521153, 0, '2024-10-22 09:54:41');
INSERT INTO `records` VALUES (1848543555377864706, 1848316858330193922, 1848523815259402241, NULL, 1848313214998306817, 1848533495658516482, 1848543555310755841, 0, '2024-10-22 09:55:03');
INSERT INTO `records` VALUES (1848543604971315202, 1848316858330193922, 1848523815259402241, NULL, 1848313214998306817, 1848533495658516482, 1848543604904206338, 0, '2024-10-22 09:55:14');
INSERT INTO `records` VALUES (1848543646008385538, 1848316858330193922, 1848523815259402241, 1848316858330193922, 1848313214998306817, 1848533495658516482, 1848543645941276674, 1, '2024-10-22 09:55:24');
INSERT INTO `records` VALUES (1848544752541249537, 1848523815259402241, 1848316858330193922, 1848316858330193922, 1848313214998306817, 1848323292988100610, 1848544752499306498, 1, '2024-10-22 09:59:48');
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint NOT NULL COMMENT '用户id',
`user_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户名',
`account` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户账号',
`phone` varchar(11) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '手机号',
`password` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户密码',
`identity` varchar(18) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '身份证',
`likes` int NULL DEFAULT 0 COMMENT '点赞次数',
`mark` int NULL DEFAULT 0 COMMENT '用户标识: 0普通用户 1快递员 2管理员',
`disabled` int NULL DEFAULT 0 COMMENT '禁用标志 0: 没有 1: 禁用',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`login_time` datetime NULL DEFAULT NULL COMMENT '最近一次登录时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '最近更新时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `user_name`(`user_name` ASC) USING BTREE,
UNIQUE INDEX `account`(`account` ASC) USING BTREE,
UNIQUE INDEX `phone`(`phone` ASC) USING BTREE,
UNIQUE INDEX `identity`(`identity` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1848310231438860290, 'admin', 'admin', '18750117167', '21232f297a57a5a743894a0e4a801fc3', '350104200211271554', 0, 2, 0, '2024-10-21 18:27:54', '2024-11-01 16:27:11', '2024-10-21 18:32:23');
INSERT INTO `user` VALUES (1848313214998306817, 'emOne', 'emOne', '18750117166', '17f6fe1d6e8824aa95cd823a04a1735e', '350104200211271553', 2, 1, 0, '2024-10-21 18:39:45', '2024-10-23 08:51:35', '2024-10-21 18:39:45');
INSERT INTO `user` VALUES (1848316858330193922, 'grs', 'grs', '18750117160', 'a1ca50b49044afbeeed4b5e31dbece6c', '350104200211271550', 0, 0, 0, '2024-10-21 18:54:14', '2024-10-23 09:00:15', '2024-10-21 18:54:14');
INSERT INTO `user` VALUES (1848523815259402241, 'chj', 'chj', '18750117161', 'c4904bd9b0fe86a6809ba6cb57e1ad30', '350104200211271551', 0, 0, 0, '2024-10-22 08:36:36', '2024-10-22 09:58:47', '2024-10-22 08:36:36');
INSERT INTO `user` VALUES (1848544937652662274, 'emTwo', 'emTwo', '18750117162', '9d5c7143c7e105331d7aed75d17b59c3', '350104200211271559', 0, 1, 0, '2024-10-22 10:00:32', NULL, '2024-10-22 10:00:32');
INSERT INTO `user` VALUES (1849639443382857730, 'jhj', 'jhj', '18750334576', '20fc6e83c7e38bb5cb5260cb8a0cbda5', '350104200211261554', 0, 0, 0, '2024-10-25 10:29:43', NULL, '2024-10-25 10:29:43');
INSERT INTO `user` VALUES (1851869410121809921, '陈金三', 'cjh', '17829653387', '15b697eae54fd4ab7143c616df92334c', '350104200810311552', 0, 1, 0, '2024-10-31 14:10:48', NULL, '2024-10-31 14:10:48');
INSERT INTO `user` VALUES (1852266092133793794, 'TestUSER1', 'TestUSER1', '18750117777', '2188eb4e691ab2f44faa2f22d02a6c36', '350104200711271554', 0, 0, 1, '2024-11-01 16:27:04', NULL, '2024-11-01 16:27:04');
SET FOREIGN_KEY_CHECKS = 1;

@ -17,3 +17,27 @@ export const disabledControllerService = (id, operation) => {
params: { operation: operation },
})
}
// 获取所有的快递记录以及信息
export const expressRecordsService = (page, pageSize) => {
return request.get('/admin/express', {
params: {
page: page,
pageSize: pageSize,
},
})
}
// 获取管理员和谁准备聊天的记录
export const getMessageToWhoService = id => {
return request.get('/admin/allMessage', {
params: {
toId: id,
},
})
}
// 管理员发送消息
export const sendMessageService = sendMessage => {
return request.post('/admin/sendMessage', sendMessage)
}

@ -14,3 +14,13 @@ export const registerService = registerModelData => {
export const getInfoService = () => {
return request.get('common/info')
}
// 更新个人信息
export const updateInfoService = infoData => {
return request.put('/common/modify', infoData)
}
// 修改密码
export const modifyPasswordService = userModifyPasswordDTO => {
return request.put('/common/rePassword', userModifyPasswordDTO)
}

@ -0,0 +1,24 @@
import request from '@/utils/request.js'
export const sendMessageService = model => {
return request.post('/user/sendMessage', model)
}
// 查询自己派送过得所有订单
export const sendExpressService = (page, pageSize) => {
return request.get('/employee/express', {
params: {
page: page,
pageSize: pageSize,
},
})
}
// 快递员查询快递
export const searchExpressService = expressCode => {
return request.post('/employee/expressInfo', null, {
params: {
expressCode: expressCode,
},
})
}

@ -0,0 +1,118 @@
import request from '@/utils/request.js'
// 用户查询快递
export const queryExpressService = (queryCode, queryId) => {
return request.get('/user/query', {
params: {
queryCode: queryCode,
queryId: queryId,
},
})
}
// 用户获取寄件人名字
export const getSendUserService = otherId => {
return request.get('/user/queryInfo', {
params: {
otherId: otherId,
},
})
}
// 用户获取单个快递历史
export const getSingleistory = goodsId => {
return request.get('/user/singleHistory', {
params: {
goodsId: goodsId,
},
})
}
// 用户获取自己写过的快递地址
export const getAddressListService = id => {
return request.get('/user/getAddress', {
params: {
id: id,
},
})
}
// 用户新建快递地址
export const addAddressService = addressModel => {
return request.post('/user/addAddress', addressModel)
}
// 用户寄件
export const sendExpressService = goodsModel => {
return request.post('/user/shipment', goodsModel)
}
// 用户获取别人发给自己的消息
export const getMessageFromService = id => {
return request.get('/user/getFromMessage', {
params: {
id: id,
},
})
}
// 用户查看自己所有快递记录
export const getAllHistoryService = (page, pageSize) => {
return request.get('/user/history', {
params: {
page: page,
pageSize: pageSize,
},
})
}
// 用户取件
export const getExpressService = addresseeDTO => {
return request.post('/user/addressee', addresseeDTO)
}
// 用户确认查看的消息
export const userConfirmMessageService = id => {
return request.post('/user/confirmMessage', null, {
params: {
id: id,
},
})
}
// 用户删除消息
export const userDeleteMessageService = id => {
return request.delete('/user/deleteMsg', {
params: {
id: id,
},
})
}
// 用户给快递员点赞
export const userLikesService = id => {
return request.post('/user/likes', null, {
params: {
id: id,
},
})
}
// 用户查看发给别人的消息
export const userSendMsgToWho = toUserName => {
return request.get('/user/sendToMessage', {
params: {
toUserName: toUserName,
},
})
}
// 用户发送消息
export const userSendMessage = model => {
return request.post('/user/sendMessage', model)
}
// 用户代取快递
export const pickUpExpressService = PickUpExpressDTO => {
return request.post('/user/pickUp', PickUpExpressDTO)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -0,0 +1,139 @@
<!-- eslint-disable no-unused-vars -->
<script setup>
import { ref } from 'vue'
import { useInfoStore } from '@/stores/info.js'
import { ElMessage } from 'element-plus'
import { updateInfoService } from '@/api/common.js'
const userInfoStore = useInfoStore()
//
const userInfo = ref({ ...userInfoStore.info })
//
const updateUserInfo = async () => {
const temp = {
userName: userInfo.value.userName,
phone: userInfo.value.phone,
}
try {
let result = await updateInfoService(temp)
if (result.code !== 200) {
ElMessage({
message: result.message ? result.message : '更新用户信息失败,请重试',
grouping: true,
type: 'error',
})
} else {
ElMessage({
message: result.message ? result.message : '用户信息更新成功',
grouping: true,
type: 'success',
})
userInfoStore.info = result.data
userInfo.value = { ...userInfoStore.info }
}
} catch (error) {
ElMessage({
message: '更新用户信息失败,请重试',
grouping: true,
type: 'error',
})
}
}
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>基本资料</span>
</div>
</template>
<el-row>
<el-col :span="12">
<el-form :model="userInfo" label-width="100px" size="large">
<el-form-item label="用户账号">
<el-input
v-model="userInfo.account"
disabled
class="account"
></el-input>
</el-form-item>
<el-form-item label="用户昵称">
<el-input v-model="userInfo.userName"></el-input>
</el-form-item>
<el-form-item label="身份证">
<el-input v-model="userInfo.identity" disabled></el-input>
</el-form-item>
<el-form-item label="电话号码">
<el-input v-model="userInfo.phone"></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="updateUserInfo"
:disabled="updateDisabled"
class="modify-button"
><span>提交修改</span></el-button
>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-card>
</template>
<style scoped lang="scss">
.page-container {
.modify-button {
display: inline-block;
width: 150px;
height: 50px;
border-radius: 10px;
border: 1px solid #03045e;
position: relative;
overflow: hidden;
transition: all 0.5s ease-in;
z-index: 1;
}
.modify-button::before,
.modify-button::after {
content: '';
position: absolute;
top: 0;
width: 0;
height: 100%;
transform: skew(15deg);
transition: all 0.5s;
overflow: hidden;
z-index: -1;
}
.modify-button::before {
left: -10px;
background: #240046;
}
.modify-button::after {
right: -10px;
background: #5a189a;
}
.modify-button:hover::before,
.modify-button:hover::after {
width: 58%;
}
.modify-button:hover span {
color: #e0aaff;
transition: 0.3s;
}
.modify-button span {
color: #03045e;
font-size: 18px;
transition: all 0.3s ease-in;
}
}
</style>

@ -0,0 +1,134 @@
<script setup>
import { onMounted, ref } from 'vue'
import { expressRecordsService } from '@/api/admin.js'
const parentBorder = ref(true)
const childBorder = ref(true)
const pageNum = ref(1) //
const total = ref(10) //
const pageSize = ref(15) //
const recordsWithDataList = ref([])
//
const onSizeChange = size => {
pageSize.value = size
recordsWith()
}
//
const onCurrentChange = num => {
pageNum.value = num
recordsWith()
}
//
const recordsWith = async () => {
let result = await expressRecordsService(pageNum.value, pageSize.value)
total.value = result.data.total
recordsWithDataList.value = result.data.records
}
onMounted(() => {
recordsWith()
})
//
const formatDate = (row, column, cellValue) => {
if (!cellValue) return '暂无登录'
const date = new Date(cellValue)
return date.toLocaleString()
}
const formatSignStatus = (row, column, cellValue) => {
if (cellValue === 0) {
return '未签收'
} else if (cellValue === 1) {
return '已签收'
}
}
const formatAddressee = (row, column, cellValue) => {
if (cellValue == null) {
return '快递暂未签收'
}
return cellValue
}
const formatQuality = (row, column, cellValue) => {
return cellValue + 'kg'
}
const rowData = data => {
console.log(data)
}
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>快递记录</span>
</div>
</template>
<el-table
:data="recordsWithDataList"
:border="parentBorder"
style="width: 100%"
>
<el-table-column type="expand">
<template #default="props">
<div m="4">
<h3>记录详情</h3>
<el-table
:data="[props.row]"
:border="childBorder"
@click="rowData(props.row)"
>
<el-table-column label="寄件人" prop="sender.userName" />
<el-table-column label="收件人" prop="recipient.userName" />
<el-table-column
label="签收者"
prop="addressee.userName"
:formatter="formatAddressee"
/>
<el-table-column label="邮寄方" prop="addressFrom.address" />
<el-table-column label="邮寄地址" prop="addressTo.address" />
<el-table-column label="派送快递员" prop="courier.userName" />
<el-table-column
label="快递重量"
prop="goods.quality"
:formatter="formatQuality"
/>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column label="序号" width="100" type="index"></el-table-column>
<el-table-column label="快递名称" prop="goods.name"></el-table-column>
<el-table-column
label="签收状态"
prop="records.mark"
:formatter="formatSignStatus"
/>
<el-table-column
label="发送日期"
prop="records.createTime"
:formatter="formatDate"
/>
/>
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[15]"
layout="jumper, total, sizes, prev, pager, next"
background
:total="total"
@size-change="onSizeChange"
@current-change="onCurrentChange"
style="margin-top: 10px; justify-content: center"
/>
</el-card>
</template>

@ -14,22 +14,22 @@ const pageSize = ref(5) // 每页条数
//
const onSizeChange = size => {
pageSize.value = size
getInoList()
getInfoList()
}
//
const onCurrentChange = num => {
pageNum.value = num
getInoList()
getInfoList()
}
//
const onMarkChange = () => {
getInoList()
getInfoList()
}
//
const getInoList = async () => {
const getInfoList = async () => {
let result = await getInfoListService(
pageNum.value,
pageSize.value,
@ -39,7 +39,7 @@ const getInoList = async () => {
infoList.value = result.data.records
}
//
//
const formatDate = cellValue => {
if (!cellValue) return '暂无登录'
const date = new Date(cellValue)
@ -47,7 +47,7 @@ const formatDate = cellValue => {
}
onMounted(() => {
getInoList()
getInfoList()
})
</script>
@ -118,7 +118,7 @@ onMounted(() => {
<el-pagination
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[1, 5, 10, 15]"
:page-sizes="[5]"
layout="jumper, total, sizes, prev, pager, next"
background
:total="total"

@ -0,0 +1,229 @@
<!-- eslint-disable no-unused-vars -->
<script setup>
import { ElMessage } from 'element-plus'
import { ref } from 'vue'
import { useTokenStore } from '@/stores/token.js'
import router from '@/router'
import { useInfoStore } from '@/stores/info.js'
import { modifyPasswordService } from '@/api/common.js'
const resetPassword = ref({
oldPassword: '',
newPassword: '',
reNewPassword: '',
identity: '',
})
const tokenStore = useTokenStore()
const userInfoStore = useInfoStore()
//
const reset = async () => {
try {
let result = await modifyPasswordService(resetPassword.value)
if (result.code !== 200) {
ElMessage({
message: result.message ? result.message : '更新用户信息失败,请重试',
grouping: true,
type: 'error',
})
} else {
ElMessage({
message: result.message ? result.message : '密码修改成功, 请重新登陆',
grouping: true,
type: 'success',
})
//
tokenStore.removeToken()
userInfoStore.removeInfo()
router.push('/login')
}
} catch (error) {
ElMessage({
message: '更新用户信息失败,请重试',
grouping: true,
type: 'error',
})
}
}
//
const resetPasswordRules = {
oldPassword: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
validator: (rule, value, callback) => {
const regex = /^.+$/
if (!value) {
callback(new Error('请输入密码'))
} else if (!regex.test(value)) {
callback(new Error('密码不能为空'))
} else {
callback()
}
},
trigger: 'blur',
},
],
newPassword: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
validator: (rule, value, callback) => {
const regex = /^.+$/
if (!value) {
callback(new Error('请输入密码'))
} else if (!regex.test(value)) {
callback(new Error('密码不能为空'))
} else {
callback()
}
},
trigger: 'blur',
},
],
reNewPassword: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
validator: (rule, value, callback) => {
const regex = /^.+$/
if (!value) {
callback(new Error('请输入密码'))
} else if (!regex.test(value)) {
callback(new Error('密码不能为空'))
} else if (value !== resetPassword.value.newPassword) {
// reNewPasswordnewPassword
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
},
trigger: 'blur',
},
],
identity: [{ require: true, message: '请输入身份证', trigger: 'blur' }],
}
</script>
<template>
<el-card class="page-container">
<template #header>
<div class="header">
<span>修改密码</span>
</div>
</template>
<el-row>
<el-col :span="12">
<el-form
:model="resetPassword"
:rules="resetPasswordRules"
label-width="140px"
size="large"
>
<el-form-item label="旧密码" prop="oldPassword">
<el-input
v-model="resetPassword.oldPassword"
show-password
></el-input>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input
v-model="resetPassword.newPassword"
show-password
></el-input>
</el-form-item>
<el-form-item label="再次输入新密码" prop="reNewPassword">
<el-input
v-model="resetPassword.reNewPassword"
show-password
></el-input>
</el-form-item>
<el-form-item label="身份证" prop="identity">
<el-input v-model="resetPassword.identity" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="reset" class="modify-button"
>修改密码</el-button
>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-card>
</template>
<style scoped lang="scss">
/* From Uiverse.io by mrhyddenn */
.page-container {
.modify-button {
position: relative;
padding: 10px 20px;
border-radius: 7px;
border: 1px solid rgb(61, 106, 255);
font-size: 14px;
text-transform: uppercase;
font-weight: 600;
letter-spacing: 2px;
background: transparent;
color: rgb(40, 40, 96);
overflow: hidden;
box-shadow: 0 0 0 0 transparent;
-webkit-transition: all 0.2s ease-in;
-moz-transition: all 0.2s ease-in;
transition: all 0.2s ease-in;
}
.modify-button:hover {
background: rgb(61, 106, 255);
box-shadow: 0 0 30px 5px rgba(0, 142, 236, 0.815);
-webkit-transition: all 0.2s ease-out;
-moz-transition: all 0.2s ease-out;
transition: all 0.2s ease-out;
}
.modify-button:hover::before {
-webkit-animation: sh02 0.5s 0s linear;
-moz-animation: sh02 0.5s 0s linear;
animation: sh02 0.5s 0s linear;
}
.modify-button::before {
content: '';
display: block;
width: 0px;
height: 86%;
position: absolute;
top: 7%;
left: 0%;
opacity: 0;
background: #fff;
box-shadow: 0 0 50px 30px #fff;
-webkit-transform: skewX(-20deg);
-moz-transform: skewX(-20deg);
-ms-transform: skewX(-20deg);
-o-transform: skewX(-20deg);
transform: skewX(-20deg);
}
@keyframes sh02 {
from {
opacity: 0;
left: 0%;
}
50% {
opacity: 1;
}
to {
opacity: 0;
left: 100%;
}
}
.modify-button:active {
box-shadow: 0 0 0 0 transparent;
-webkit-transition: box-shadow 0.2s ease-in;
-moz-transition: box-shadow 0.2s ease-in;
transition: box-shadow 0.2s ease-in;
}
}
</style>

@ -0,0 +1,237 @@
<script setup>
import { ref, computed } from 'vue'
import {
getInfoListService,
getMessageToWhoService,
sendMessageService,
} from '@/api/admin.js'
import { ElMessage } from 'element-plus'
const mark = ref(0)
const pageNum = ref(1)
const total = ref(10)
const pageSize = ref(5)
const infoList = ref([])
const chatPersonId = ref()
const chatMessageTo = ref([]) //
const chatMessageFrom = ref([]) //
const ToFromMessageBox = ref([])
const searchQuery = ref('')
const currentChatWithWho = ref('')
const message = ref('')
const getUserId = row => {
currentChatWithWho.value = row.userName
chatPersonId.value = row.id
getChatMessage()
}
const getChatMessage = async () => {
let result = await getMessageToWhoService(chatPersonId.value)
chatMessageTo.value = result.data[0]
chatMessageFrom.value = result.data[1]
mergeAndSort()
}
//
const mergeAndSort = () => {
ToFromMessageBox.value = []
// chatMessageTo chatMessageFrom
const combinedMessages = [
...chatMessageTo.value.map(msg => ({ ...msg, direction: 'to' })),
...chatMessageFrom.value.map(msg => ({ ...msg, direction: 'from' })),
]
// createTime
ToFromMessageBox.value = combinedMessages.sort((a, b) => {
return new Date(a.createTime) - new Date(b.createTime)
})
}
const onMarkChange = () => {
getInfoList()
}
const getInfoList = async () => {
let result = await getInfoListService(
pageNum.value,
pageSize.value,
mark.value,
)
total.value = result.data.total
infoList.value = result.data.records
}
const filteredInfoList = computed(() => {
if (!searchQuery.value) {
return infoList.value
}
return infoList.value.filter(item =>
item.userName.toLowerCase().includes(searchQuery.value.toLowerCase()),
)
})
getInfoList()
//
const sendMessage = async () => {
const model = ref({
toUserName: currentChatWithWho.value,
content: message,
})
let result = await sendMessageService(model.value)
if (result.code == 200) {
ElMessage({
message: '留言成功',
type: 'success',
grouping: true,
})
getChatMessage()
message.value = ''
}
}
</script>
<template>
<div id="home">
<div class="left">
<el-radio-group
v-model.number="mark"
@change="onMarkChange"
class="radio-group"
>
<el-radio-button :value="0" label="用户" />
<el-radio-button :value="1" label="快递员" />
</el-radio-group>
<br />
<!-- 搜索框 -->
<el-input
v-model="searchQuery"
placeholder="搜索用户名"
clearable
style="margin-bottom: 20px"
/>
<el-table :data="filteredInfoList" @row-click="getUserId">
<el-table-column label="用户名" prop="userName" :sortable="true" />
</el-table>
</div>
<!-- 内容主体区 -->
<div class="mainbox">
<div class="title">
<p>
当前留言对象:
<span :style="{ color: currentChatWithWho ? 'blue' : 'inherit' }">{{
currentChatWithWho ? currentChatWithWho : '请选择你的聊天对象'
}}</span>
</p>
</div>
<hr />
<div class="talk">
<div
v-for="item in ToFromMessageBox"
:key="item.id"
:class="['message', item.direction]"
>
<div class="message-content">
{{ item.content }}
<span v-if="item.mark === 1" class="unread-dot"></span>
<!-- 添加红点 -->
</div>
</div>
</div>
<div class="send">
<textarea
v-model="message"
placeholder="输入消息..."
class="input-box"
@keydown="handleKeyDown"
></textarea>
<button @click="sendMessage" class="send-button">发送</button>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
#home {
background-color: #d2bbef;
margin: auto;
width: 1200px;
height: 600px;
display: flex;
.mainbox {
flex: 200;
background-color: #d8b8a0;
display: flex;
flex-direction: column; /* 使用列方向布局 */
justify-content: space-between; /* 使子元素间距均匀分配 */
overflow: hidden; /* 隐藏多余部分,防止内容溢出 */
}
.talk {
flex: 1; /* 使聊天内容区域灵活扩展,占用剩余空间 */
overflow-y: auto; /* 如果内容超过显示区域则出现滚动条 */
padding: 10px; /* 添加内边距使内容不紧贴边缘 */
}
.message {
margin: 10px 0; /* 每条消息之间的间隔 */
padding: 8px 12px; /* 消息内容的内边距 */
border-radius: 8px; /* 消息框的圆角 */
max-width: 70%; /* 最大宽度 */
word-wrap: break-word; /* 防止单词过长 */
}
.to {
background-color: #cce5ff; /* 发给用户的消息背景色 */
align-self: flex-end; /* 右对齐 */
}
.from {
background-color: #e2e3e5; /* 从用户收到的消息背景色 */
align-self: flex-start; /* 左对齐 */
}
.unread-dot {
display: inline-block; /* 使红点作为行内块元素 */
width: 8px; /* 红点的宽度 */
height: 8px; /* 红点的高度 */
background-color: red; /* 红点的颜色 */
border-radius: 50%; /* 圆形 */
margin-left: 5px; /* 左侧间隔 */
}
.send {
width: 100%;
height: 100px; /* 可以根据需求调整高度 */
display: flex; /* 使用flex布局以便于排列子元素 */
align-items: center; /* 垂直居中对齐 */
padding: 10px; /* 添加内边距 */
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1); /* 可选:添加阴影效果 */
}
.input-box {
flex: 1; /* 输入框占用剩余空间 */
height: 100%; /* 填满父容器高度 */
padding: 10px;
box-sizing: border-box; /* 包括内边距在内 */
resize: none; /* 禁止用户手动调整大小 */
border: 1px solid #ccc;
border-radius: 4px;
margin-right: 10px; /* 输入框与按钮之间的间隔 */
}
.send-button {
padding: 10px 15px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.send-button:hover {
background-color: #0056b3;
}
}
</style>

@ -58,7 +58,7 @@ const disabledController = async row => {
//
const deleteAccount = row => {
ElMessageBox.confirm('您确认要退出登录吗', '温馨提示', {
ElMessageBox.confirm('您确认要删除用户吗', '温馨提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',

@ -0,0 +1,205 @@
<script setup>
import { ref, onMounted } from 'vue'
import { userSendMsgToWho } from '@/api/user.js'
import { useRoute } from 'vue-router'
import { sendMessageService } from '@/api/employee.js'
import { ElMessage } from 'element-plus'
import router from '@/router'
defineOptions({
name: 'CourierGetIndex',
})
const route = useRoute()
// onMounted otherName GON
onMounted(async () => {
userName.value = route.params.userName // otherName
await GON() // otherName GON
})
const GON = async () => {
let result = await userSendMsgToWho(userName.value) // 使 otherName.value
messages.value = result.data
}
const messages = ref([])
const userName = ref('')
const newMessage = ref('')
const sendMessage = async () => {
const model = ref({
toUserName: userName.value,
content: newMessage.value,
})
let result = await sendMessageService(model.value)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
clear()
GON()
}
}
const clear = () => {
newMessage.value = ''
}
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
</script>
<template>
<div class="chat-container">
<div class="chat-header">
<el-button
class="back-button"
type="primary"
round
style="background-color: black"
@click="router.push('/emLogin')"
>返回首页</el-button
>
<div style="flex-grow: 1; text-align: center">{{ userName }}</div>
</div>
<div class="chat-window">
<div class="messages-container">
<div v-for="message in messages" :key="message.id" class="sent">
<div class="message-avatar me"></div>
<div class="message-content">
<div class="message-text">
{{ message.content }}
<hr />
{{ formatDate(message.createTime) }}
</div>
</div>
</div>
</div>
<div class="input-container">
<input
v-model="newMessage"
@keyup.enter="sendMessage"
placeholder="输入消息..."
type="text"
/>
<button @click="sendMessage"></button>
</div>
</div>
</div>
</template>
<style scoped>
.chat-container {
width: 100%;
max-width: 1000px;
margin: 0 auto;
box-sizing: border-box;
font-family: Arial, sans-serif;
}
.chat-header {
display: flex; /* 使用 Flexbox */
justify-content: center; /* 默认居中对齐 */
align-items: center; /* 垂直居中对齐 */
position: relative; /* 设置相对定位,以便绝对定位按钮 */
padding: 20px;
background-color: #007bff;
color: white;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.back-button {
position: absolute; /* 使用绝对定位使按钮在左侧 */
left: 20px; /* 距离左边的距离 */
}
.chat-window {
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.messages-container {
padding: 10px;
height: 600px; /* 增加高度 */
overflow-y: auto;
background-color: #f9f9f9;
}
.message {
display: flex;
margin-bottom: 10px;
}
.message-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #007bff;
margin-right: 10px;
}
.message-avatar.me {
order: 1;
margin-left: 10px;
margin-right: 0;
background-color: #28a745;
}
.message-content {
background-color: white;
padding: 10px;
border-radius: 8px;
max-width: 80%;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.message-content.sent {
align-self: flex-end;
}
.message-text {
word-wrap: break-word;
}
.message-timestamp {
font-size: 0.875em;
color: #888;
margin-top: 5px;
}
.input-container {
display: flex;
padding: 10px;
background-color: #f1f1f1;
border-top: 1px solid #ddd;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
/* 可以根据需要调整 input-container 的 padding 或其他属性 */
}
input[type='text'] {
flex: 1;
padding: 10px;
border: none;
outline: none;
font-size: 1em;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
margin-left: 10px;
}
button:hover {
background-color: #0056b3;
}
</style>

@ -0,0 +1,97 @@
<script setup>
defineOptions({
name: 'CourierGetIndex',
})
import { onMounted, ref } from 'vue'
import { sendExpressService } from '@/api/employee.js'
import router from '@/router'
//
const pageNum = ref(1) //
const total = ref(10) //
const pageSize = ref(15) //
//
const onSizeChange = size => {
pageSize.value = size
getAllExpressHistory()
}
//
const onCurrentChange = num => {
pageNum.value = num
getAllExpressHistory()
}
//
const getAllExpressHistory = async () => {
let result = await sendExpressService(pageNum.value, pageSize.value)
total.value = result.data.total
tableData.value = result.data.records
}
onMounted(() => {
getAllExpressHistory()
})
const tableData = ref([])
</script>
<template>
<div class="container">
<el-button
class="back-button"
type="primary"
round
style="background-color: black"
@click="router.push('/emLogin')"
>返回首页</el-button
>
<br />
<span>
<div class="demo-collapse">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="sendUser.userName" label="寄件人" />
<el-table-column prop="getUser.userName" label="收件人" />
<el-table-column prop="goods.name" label="快递名称" width="180" />
<el-table-column prop="addressFrom.address" label="发货地址" />
<el-table-column prop="addressTo.address" label="送达地址" />
<el-table-column label="快递状态">
<template v-slot="scope">
<span>
{{ scope.row.records.mark === 0 ? '未签收' : '已签收' }}
</span>
</template>
</el-table-column>
<el-table-column prop="addressee.userName" label="签收人" />
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[10, 15]"
layout="jumper, total, sizes, prev, pager, next"
background
:total="total"
@size-change="onSizeChange"
@current-change="onCurrentChange"
style="margin-top: 10px; justify-content: center"
/>
</div>
</span>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
</style>

@ -0,0 +1,148 @@
<script setup>
defineOptions({
name: 'ResearchIndex',
})
import { ref } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import router from '@/router'
import { searchExpressService } from '@/api/employee.js'
const expressCode = ref('')
const model = ref('')
const fetchInfo = async () => {
let result = await searchExpressService(expressCode.value)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
model.value = result.data
} else {
ElMessage({
message: result.message,
type: 'error',
grouping: true,
})
}
expressCode.value = ''
}
</script>
<template>
<div class="container">
<el-button
class="back-button"
type="primary"
round
style="background-color: black"
@click="router.push('/emLogin')"
>返回首页</el-button
>
<div class="title">
<strong>运单查询</strong>
</div>
<div class="query-form">
<el-input
v-model="expressCode"
placeholder="请输入快递码"
size="large"
class="input-field"
/>
<el-button type="primary" class="query-button" @click="fetchInfo"
>点击查询</el-button
>
</div>
<div class="result-area" v-if="model">
<p class="detail-item">邮寄方{{ model.sendUser }}</p>
<p class="detail-item">邮寄方地址{{ model.addressFrom }}</p>
<p class="detail-item">收件方{{ model.getUser }}</p>
<p class="detail-item">收件方地址{{ model.addressTo }}</p>
<p class="detail-item">货物名称{{ model.name }}</p>
<p class="detail-item">货物重量{{ model.quality }} kg</p>
<p class="detail-item">
签收状态{{ model.mark == 0 ? '未签收' : '已签收' }}
</p>
<p class="detail-item" v-if="model.addressee">
签收者{{ model.addressee }}
</p>
<p class="detail-item">快递员{{ model.employee }}</p>
</div>
<div class="no-result" v-else>
<p>查无此快递</p>
</div>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
font-family: Arial, sans-serif;
}
.container {
width: 80%;
max-width: 600px;
margin: 0 auto;
background-color: white;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.title {
font-size: 2.5rem; /* 使用rem单位以更好地适应不同屏幕尺寸 */
color: #ff4d4f; /* 更改颜色为更柔和的红色 */
letter-spacing: 2px;
margin-bottom: 20px;
text-align: center;
}
.query-form {
display: flex;
flex-direction: column;
align-items: flex-start; /* 改为从左边对齐 */
}
.input-field {
width: 100%; /* 使输入框占满父容器宽度 */
margin-bottom: 15px;
padding: 10px;
border-radius: 4px;
border: 1px solid #dcdcdc;
box-sizing: border-box;
}
.query-button {
width: 100%; /* 使按钮占满父容器宽度 */
padding: 10px;
background-color: #409eff; /* Element Plus默认的主按钮颜色 */
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
}
.query-button:hover {
background-color: #66b1ff; /* 悬停时更改按钮颜色 */
}
.result-area {
margin-top: 20px;
}
.detail-item {
font-size: 1rem;
color: #333;
margin-bottom: 10px;
}
.no-result {
margin-top: 20px;
text-align: center;
color: #999;
}
</style>

@ -0,0 +1,738 @@
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import { getInfoService } from '@/api/common.js'
import { useInfoStore } from '@/stores/info.js'
import {
getMessageFromService,
userConfirmMessageService,
getSendUserService,
userDeleteMessageService,
} from '@/api/user.js'
const visible = ref(false)
const infoStore = useInfoStore()
onMounted(() => {
getInfo() //
getMessageFromOthers() //
})
//
const getInfo = async () => {
let result = await getInfoService()
infoStore.setInfo(result.data)
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
const msgList = ref([])
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const goToChat = userName => {
router.push({
name: 'emChat',
params: {
userName: userName,
},
})
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/CourierGet')">
查看派送快递
</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/research')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<!-- 消息列表 -->
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<div class="lbt"></div>
<div class="searchArea">
<span class="searchButtom">
<img src="@/assets/gsl/icon-wdcx-s.png" class="funcImg" />
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
>
网点查询
</p>
</span>
<span class="searchButtom">
<img src="@/assets/gsl/icon-psfw-s.png" class="funcImg" />
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
>
配送范围
</p>
</span>
<div style="margin-bottom: 50px; display: inline-block; margin-top: 20px">
<input type="text" class="search" />
</div>
<el-icon
style="
width: 1em;
height: 1em;
font-size: 25px;
position: absolute;
left: 1115px;
top: 62px;
cursor: pointer;
"
><Search
/></el-icon>
</div>
<div class="introArea">
<div>
<p class="introduction1">
性能强大安全稳定的物流科技产品
</p>
<p class="introduction2">猫咪物流多年技术沉淀</p>
</div>
</div>
<div class="productions">
<div class="row">
<div class="corner top-left">
<img
src="@/assets/gsl/static_images_home_img-product-01.png"
style="width: 240px; height: 240px"
/>
<p>货到人系统</p>
</div>
<div class="corner top-right">
<img
src="@/assets/gsl/img-product-03.png"
style="width: 240px; height: 240px"
/>
<p>搬运系统</p>
</div>
</div>
<div class="row">
<div class="corner bottom-left">
<img
src="@/assets/gsl/img-product-04.png"
style="width: 240px; height: 240px"
/>
<p>智能快递车</p>
</div>
<div class="corner bottom-right">
<img
src="@/assets/gsl/img-product-05.png"
style="width: 240px; height: 240px"
/>
<p>自动分播墙系统</p>
</div>
</div>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 囊括热门行业 </p>
<p class="introduction2" style="margin-left: 285px">
猫咪物流完善的服务体系为企业保驾护航
</p>
</div>
</div>
<div class="marketArea">
<img src="@/assets/gsl/bg-settle-03.jpg" class="img1" />
<p class="p1">电商</p>
<img src="@/assets/gsl/bg-settle-02.jpg" class="img2" />
<p class="p2">服装</p>
<img src="@/assets/gsl/bg-settle-01.png" class="img3" />
<p class="p3">家电</p>
<img src="@/assets/gsl/bg-settle-05.jpg" class="img4" />
<p class="p4">更多行业...</p>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 物流网络 </p>
<p class="introduction2" style="margin-left: 190px">
遍布全福州的基础设施为物流提供快速稳定智能可靠的服务
</p>
</div>
</div>
<div class="digitIntroduction">
<div class="digit1">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
6
</p>
<p style="font-size: 18; color: #333333; display: inline">大网络</p>
<br />
<p style="margin-top: 15px">
仓储网络综合运输网络最后一公里配送网络大件网络冷链物流网络和跨境物流网络
</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
1600
</p>
<p style="font-size: 18; color: #333333; display: inline">个仓库</p>
<br />
<p style="margin-top: 15px">猫咪物流运营超1600个仓库</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
3200
</p>
<p style="font-size: 18; color: #333333; display: inline">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
<br />
<p style="margin-top: 15px">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
</div>
<div class="serveIntro">
<strong style="font-size: 24px; color: black; margin-left: 25px"
>全网覆盖</strong
>
<strong style="font-size: 24px; color: black; margin-left: 185px"
>数实融合</strong
>
<strong style="font-size: 24px; color: black; margin-left: 210px"
>全链共生</strong
>
<strong style="font-size: 24px; color: black; margin-left: 200px"
>7x24小时服务</strong
>
</div>
</div>
<br />
<div class="relateInfo">
<img src="@/assets/gsl/wx.png" class="InfoImg" />
<img src="@/assets/gsl/wb.png" class="InfoImg" />
<img src="@/assets/gsl/dy.png" class="InfoImg" />
</div>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 390vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.lbt {
width: 1167px;
height: 350px;
background-color: beige;
}
.searchArea {
position: relative;
width: 1167px;
height: 147px;
background-color: #fa4b4b;
}
.searchButtom {
cursor: pointer;
display: inline-block;
width: 96px;
height: 119px;
margin-left: 100px;
}
.funcImg {
width: 96px;
height: 96px;
}
.search {
position: absolute;
top: 50px;
width: 350px;
height: 50px;
background-color: #ffa9a9;
border-radius: 10px;
margin-left: 215px;
}
.search:focus,
.search:hover {
font-size: 15px;
outline: none;
box-shadow: none;
}
.introArea {
width: 1247px;
height: 170px;
margin-top: 200px;
margin-left: -30px;
display: flex;
justify-content: center;
align-items: center;
}
.introduction1 {
font-size: 23px;
color: #333333;
}
.introduction2 {
font-size: 14px;
color: #686363;
margin-left: 455px;
margin-top: 40px;
}
.productions {
width: 1180px;
height: 574px;
margin: 0 auto;
display: flex;
flex-direction: column;
padding-left: 180px;
padding-right: 180px;
}
.row {
display: flex;
flex: 1;
}
.corner {
flex: 2;
width: 425px;
height: 272px;
position: relative;
}
.corner > p {
position: absolute;
left: 77px;
top: 250px;
font-size: 20px;
color: #333333;
}
.top-left,
.bottom-left {
justify-content: flex-start;
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.top-left,
.top-right {
display: flex;
align-items: flex-start;
}
.bottom-left,
.bottom-right {
display: flex;
align-items: flex-end;
}
.marketArea {
position: relative;
width: 1180px;
height: 720px;
/* background-color: aquamarine; */
margin: 0 auto;
}
.img1 {
position: absolute;
width: 570px;
height: 327px;
left: 40px;
top: 50px;
}
.img2 {
position: absolute;
width: 531px;
height: 440px;
left: 619px;
top: 50px;
}
.img3 {
position: absolute;
width: 570px;
height: 327px;
top: 385px;
left: 40px;
}
.img4 {
position: absolute;
width: 531px;
height: 212px;
left: 619px;
top: 500px;
}
.p1 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 330px;
}
.p2 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 440px;
}
.p3 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 660px;
}
.p4 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 660px;
}
.digitIntroduction {
width: 1169px;
height: 520px;
background-color: #f2f2f2;
position: relative;
}
.digit1 {
margin-left: 50px;
}
.digit2 {
margin-left: 50px;
margin-top: 100px;
}
.serveIntro {
position: absolute;
top: 480px;
left: 30px;
border-radius: 5px;
width: 1120px;
height: 120px;
background-color: white;
/* text-align: left; */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
text-align: center;
padding-top: 40px;
}
.relateInfo {
margin-top: 90px;
width: 1169px;
height: 100px;
background-color: #f2f2f2;
padding-top: 20px;
}
.InfoImg {
margin-left: 30px;
cursor: pointer;
}
</style>

@ -0,0 +1,588 @@
<script setup>
defineOptions({
name: 'ChatIndex',
})
import { computed, onMounted, ref } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import {
getMessageFromService,
getSendUserService,
userConfirmMessageService,
userDeleteMessageService,
userSendMsgToWho,
userSendMessage,
} from '@/api/user.js'
import { useInfoStore } from '@/stores/info.js'
import { useRoute } from 'vue-router'
const infoStore = useInfoStore()
const visible = ref(false)
const msgList = ref([])
const route = useRoute()
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const getotherNameMsg = ref([])
const otherName = ref('')
const GON = async () => {
let result = await userSendMsgToWho(otherName.value) // 使 otherName.value
getotherNameMsg.value = result.data
}
// onMounted otherName GON
onMounted(async () => {
otherName.value = route.params.userName // otherName
await GON() // otherName GON
})
const count = ref(0)
const load = () => {
count.value += 2
}
const msg = ref('')
//
const sendMessage = async () => {
const model = ref({
toUserName: otherName.value,
content: msg.value,
})
let result = await userSendMessage(model.value)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
msg.value = ''
GON()
}
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3" @click="router.push('/alLogin')">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/get')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/send')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/query')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span>发件人{{ item.senderName }} </span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<div class="talkArea">
<el-row style="margin-left: 24px; font-size: 18px">
{{ otherName }}
</el-row>
<el-divider />
<ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto">
<li
v-for="item in getotherNameMsg"
:key="item.id"
class="infinite-list-item"
>
{{ item.content }}
</li>
</ul>
<el-divider />
<el-input
v-model="msg"
style="width: 100%"
:rows="2"
type="textarea"
placeholder="Please input"
/>
<br />
<button
class="btt"
@click="sendMessage(msg)"
style="position: relative; left: 1000px; bottom: -20px"
>
<div class="blob1"></div>
<div class="blob2"></div>
<div class="inner">发送</div>
</button>
</div>
</div>
</template>
<style scoped>
body {
background: #dcdee0;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit;
text-decoration: none;
}
a:hover {
text-decoration: none;
cursor: auto;
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.title {
width: 1169px;
height: 150px;
text-align: center;
padding-top: 50px;
}
.queryArea {
display: flex;
align-items: center;
margin-top: 100px;
margin-left: 315px;
}
.el-button,
.el-button.is-round {
padding: 20px 20px;
}
:root {
--el-border-radius-base: 1px 5px 5px 1px;
}
.el-input__wrapper {
border-radius: 5px 0 0 5px;
}
.demo-collapse {
position: absolute;
left: 11%;
}
.item {
margin-top: 10px;
margin-right: 10px;
}
.btn {
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
border: none;
background-color: transparent;
position: relative;
}
.btn:hover > .icon {
transform: scale(1.2);
cursor: pointer;
transition: 0.2s linear;
}
.btn:focus > .icon {
fill: #fd1853;
animation: grosseur 0.2s linear;
}
@keyframes grosseur {
0% {
width: 50px;
height: 50px;
fill: #fd1853;
}
100% {
width: 30px;
height: 30px;
fill: #fd1853;
}
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.talkArea {
width: 1096px;
height: 800px;
margin: 0 auto;
background-color: white;
border: 1px solid #c0c4cc;
border-radius: 20px;
padding-top: 20px;
}
.el-textarea {
--el-input-text-color: var(--el-text-color-regular);
--el-input-border: var(--el-border);
--el-input-hover-border: var(--el-border-color-hover);
--el-input-focus-border: var(--el-color-primary);
--el-input-transparent-border: 0 0 0 1px transparent inset;
--el-input-border-color: #fff;
--el-input-border-radius: var(--el-border-radius-base);
--el-input-bg-color: var(--el-fill-color-blank);
--el-input-icon-color: var(--el-text-color-placeholder);
--el-input-placeholder-color: var(--el-text-color-placeholder);
--el-input-clear-hover-color: var(--el-text-color-secondary);
--el-input-width: 100%;
display: inline-block;
font-size: var(--el-font-size-base);
position: relative;
vertical-align: bottom;
width: 100%;
}
.el-textarea__inner:focus {
box-shadow: 0 0 0 1px #ffffff inset !important;
outline: none;
}
.el-textarea__inner:hover {
box-shadow: 0 0 0 1px #fff inset !important;
}
.infinite-list {
height: 500px;
padding: 0;
margin: 0;
list-style: none;
}
.infinite-list .infinite-list-item {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
background: var(--el-color-primary-light-9);
margin: 10px;
color: var(--el-color-primary);
}
.infinite-list .infinite-list-item + .list-item {
margin-top: 10px;
}
/* From Uiverse.io by Spacious74 */
.btt {
cursor: pointer;
font-size: 1.4rem;
border-radius: 16px;
border: none;
padding: 2px;
background: radial-gradient(circle 80px at 80% -10%, #ffffff, #181b1b);
position: relative;
}
.btt::after {
content: '';
position: absolute;
width: 65%;
height: 60%;
border-radius: 120px;
top: 0;
right: 0;
box-shadow: 0 0 20px #ffffff38;
z-index: -1;
}
.blob1 {
position: absolute;
width: 70px;
height: 100%;
border-radius: 16px;
bottom: 0;
left: 0;
background: radial-gradient(
circle 60px at 0% 100%,
#3fe9ff,
#0000ff80,
transparent
);
box-shadow: -10px 10px 30px #0051ff2d;
}
.inner {
padding: 14px 25px;
border-radius: 14px;
color: #fff;
z-index: 3;
position: relative;
background: radial-gradient(circle 80px at 80% -50%, #777777, #0f1111);
}
.inner::before {
content: '';
width: 100%;
height: 100%;
left: 0;
top: 0;
border-radius: 14px;
background: radial-gradient(
circle 60px at 0% 100%,
#00e1ff1a,
#0000ff11,
transparent
);
position: absolute;
}
</style>

@ -0,0 +1,645 @@
<script setup>
defineOptions({
name: 'GetIndex',
})
import { computed, onMounted, ref } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import {
getAllHistoryService,
getExpressService,
getMessageFromService,
getSendUserService,
userConfirmMessageService,
userDeleteMessageService,
userLikesService,
} from '@/api/user.js'
import { useInfoStore } from '@/stores/info.js'
const dialogFormVisible = ref(false)
const formLabelWidth = '140px'
const infoStore = useInfoStore()
const visible = ref(false)
const msgList = ref([])
//
const pageNum = ref(1) //
const total = ref(10) //
const pageSize = ref(10) //
//
const onSizeChange = size => {
pageSize.value = size
getAllExpressHistory()
}
//
const onCurrentChange = num => {
pageNum.value = num
getAllExpressHistory()
}
const claimCode = ref('')
const list = ref([])
// expanded
const toggleExpand = index => {
list.value[index].expanded = !list.value[index].expanded
}
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
//
const getAllExpressHistory = async () => {
let result = await getAllHistoryService(pageNum.value, pageSize.value)
total.value = result.data.total
list.value = result.data.records
}
getMessageFromOthers()
//
const markState = mark => {
if (mark == 0) {
return '未签收'
} else {
return '已签收'
}
}
onMounted(() => {
getAllExpressHistory()
})
//
const confirmGetExpress = async goodsId => {
const addresseeDTO = ref({
goodsId: goodsId,
claimCode: claimCode.value,
})
let result = await getExpressService(addresseeDTO.value)
if (result.code == 200) {
ElMessage({
message: '取件成功',
type: 'success',
grouping: true,
})
getAllExpressHistory()
} else {
ElMessage({
message: '取件失败',
type: 'error',
grouping: true,
})
}
}
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
//
const likes = async id => {
let result = await userLikesService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getAllExpressHistory()
}
}
const goToChat = userName => {
router.push({
name: 'Chat',
params: {
userName: userName,
},
})
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3" @click="router.push('/alLogin')">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs">收件</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/send')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/query')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<br />
<span>
<div class="demo-collapse">
<div
v-for="(item, index) in list"
:key="index"
:class="{ expandable: true, expanded: item?.expanded }"
@click="toggleExpand(index)"
style="cursor: pointer"
>
<p style="margin-left: 20px; margin-top: 8px">
{{ item.goods.name }}
<span v-if="infoStore.info.id == item.goods.sendUserId"
>(您发送的快递)</span
>
</p>
<div
v-if="item?.expanded"
class="hidden-content"
style="margin-left: 20px; margin-top: 8px; position: relative"
@click="
event => {
event.stopPropagation()
}
"
>
<div>快递状态{{ markState(item.record.mark) }}</div>
<div>快递编码{{ item.goods.expressCode }}</div>
<div>邮寄人姓名{{ item.sendUser.userName }}</div>
<div>邮寄人地址{{ item.addressFrom.address }}</div>
<button class="btn" @click="likes(item.employee.id)">
<svg
class="icon"
width="30"
height="30"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"
></path>
</svg>
</button>
<div>快递员: {{ item.employee.userName }}</div>
<div>收件人姓名: {{ item.getUserId.userName }}</div>
<div>收件地址: {{ item.addressTo.address }}</div>
<div>取件码: {{ item.code.claim }}</div>
<div v-if="item.addressee">
签收者姓名{{ item.addressee.userName }}
</div>
<el-button
type="primary"
style="bottom: 10px; position: absolute; right: 2%"
v-if="
infoStore.info.id == item.goods.getUserId &&
item.record.mark == 0
"
@click="(dialogFormVisible = true), (claimCode = '')"
>取件</el-button
>
<el-dialog v-model="dialogFormVisible" title="取件" width="500">
<el-form>
<el-form-item
label="请输入取件码"
:label-width="formLabelWidth"
>
<el-input v-model="claimCode" 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="
(dialogFormVisible = false),
confirmGetExpress(item.goods.id)
"
>
确认
</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
<!-- 分页 -->
<el-pagination
v-model:current-page="pageNum"
v-model:page-size="pageSize"
:page-sizes="[5, 10, 15]"
layout="jumper, total, sizes, prev, pager, next"
background
:total="total"
@size-change="onSizeChange"
@current-change="onCurrentChange"
style="margin-top: 10px; justify-content: center"
/>
</div>
</span>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.title {
width: 1169px;
height: 150px;
/* background-color: aqua; */
text-align: center;
padding-top: 50px;
}
.queryArea {
display: flex;
align-items: center; /* 垂直居中对齐 */
margin-top: 100px;
margin-left: 315px;
}
.el-button,
.el-button.is-round {
padding: 20px 20px;
}
:root {
--el-border-radius-base: 1px 5px 5px 1px;
}
.el-input__wrapper {
border-radius: 5px 0 0 5px;
}
.item {
margin-top: 10px;
margin-right: 40px;
}
.demo-collapse {
position: absolute;
left: 10%;
}
.item {
margin-top: 10px;
margin-right: 10px;
}
.goodsInfo {
width: 1000px;
height: 50px;
border-radius: 25px;
background-color: #eea8b8;
margin-bottom: 20px;
}
.goodsInfo > p {
margin-top: 15px;
margin-left: 16px;
}
.goodsInfo:hover {
background-color: pink;
height: 200px;
}
.btn {
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
border: none;
background-color: transparent;
position: relative;
}
.btn:hover > .icon {
transform: scale(1.2);
cursor: pointer;
transition: 0.2s linear;
}
.btn:focus > .icon {
fill: #fd1853;
animation: grosseur 0.2s linear;
}
@keyframes grosseur {
0% {
width: 50px;
height: 50px;
fill: #fd1853;
}
100% {
width: 30px;
height: 30px;
fill: #fd1853;
}
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.expandable {
width: 1000px;
height: 50px;
background-color: #eea8b8;
border-radius: 25px;
margin-bottom: 25px;
overflow: hidden;
transition: all 1s ease;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.05);
}
.expandable.expanded {
height: auto; /* 或者设置具体的像素值 */
}
.hidden-content {
display: none;
transition:
opacity 0.8s ease,
max-height 0.8s ease;
}
.expandable.expanded .hidden-content {
display: block;
}
</style>

@ -0,0 +1,753 @@
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import { getInfoService } from '@/api/common.js'
import { useInfoStore } from '@/stores/info.js'
import {
getMessageFromService,
userConfirmMessageService,
getSendUserService,
userDeleteMessageService,
} from '@/api/user.js'
const visible = ref(false)
const infoStore = useInfoStore()
onMounted(() => {
getInfo() //
getMessageFromOthers() //
})
//
const getInfo = async () => {
let result = await getInfoService()
infoStore.setInfo(result.data)
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
const msgList = ref([])
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const goToChat = userName => {
router.push({
name: 'Chat',
params: {
userName: userName,
},
})
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/get')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/send')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/query')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<!-- 消息列表 -->
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<div class="lbt"></div>
<div class="searchArea">
<span class="searchButtom" @click="router.push('/send')">
<img src="@/assets/gsl/icon-wyjj-s.png" class="funcImg" />
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
>
我要寄件
</p>
</span>
<span class="searchButtom">
<img src="@/assets/gsl/icon-wdcx-s.png" class="funcImg" />
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
>
网点查询
</p>
</span>
<span class="searchButtom">
<img src="@/assets/gsl/icon-psfw-s.png" class="funcImg" />
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
>
配送范围
</p>
</span>
<div style="margin-bottom: 50px; display: inline-block; margin-top: 20px">
<input type="text" class="search" />
</div>
<el-icon
style="
width: 1em;
height: 1em;
font-size: 25px;
position: absolute;
left: 1115px;
top: 62px;
cursor: pointer;
"
><Search
/></el-icon>
</div>
<div class="introArea">
<div>
<p class="introduction1">
性能强大安全稳定的物流科技产品
</p>
<p class="introduction2">猫咪物流多年技术沉淀</p>
</div>
</div>
<div class="productions">
<div class="row">
<div class="corner top-left">
<img
src="@/assets/gsl/static_images_home_img-product-01.png"
style="width: 240px; height: 240px"
/>
<p>货到人系统</p>
</div>
<div class="corner top-right">
<img
src="@/assets/gsl/img-product-03.png"
style="width: 240px; height: 240px"
/>
<p>搬运系统</p>
</div>
</div>
<div class="row">
<div class="corner bottom-left">
<img
src="@/assets/gsl/img-product-04.png"
style="width: 240px; height: 240px"
/>
<p>智能快递车</p>
</div>
<div class="corner bottom-right">
<img
src="@/assets/gsl/img-product-05.png"
style="width: 240px; height: 240px"
/>
<p>自动分播墙系统</p>
</div>
</div>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 囊括热门行业 </p>
<p class="introduction2" style="margin-left: 285px">
猫咪物流完善的服务体系为企业保驾护航
</p>
</div>
</div>
<div class="marketArea">
<img src="@/assets/gsl/bg-settle-03.jpg" class="img1" />
<p class="p1">电商</p>
<img src="@/assets/gsl/bg-settle-02.jpg" class="img2" />
<p class="p2">服装</p>
<img src="@/assets/gsl/bg-settle-01.png" class="img3" />
<p class="p3">家电</p>
<img src="@/assets/gsl/bg-settle-05.jpg" class="img4" />
<p class="p4">更多行业...</p>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 物流网络 </p>
<p class="introduction2" style="margin-left: 190px">
遍布全福州的基础设施为物流提供快速稳定智能可靠的服务
</p>
</div>
</div>
<div class="digitIntroduction">
<div class="digit1">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
6
</p>
<p style="font-size: 18; color: #333333; display: inline">大网络</p>
<br />
<p style="margin-top: 15px">
仓储网络综合运输网络最后一公里配送网络大件网络冷链物流网络和跨境物流网络
</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
1600
</p>
<p style="font-size: 18; color: #333333; display: inline">个仓库</p>
<br />
<p style="margin-top: 15px">猫咪物流运营超1600个仓库</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
3200
</p>
<p style="font-size: 18; color: #333333; display: inline">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
<br />
<p style="margin-top: 15px">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
</div>
<div class="serveIntro">
<strong style="font-size: 24px; color: black; margin-left: 25px"
>全网覆盖</strong
>
<strong style="font-size: 24px; color: black; margin-left: 185px"
>数实融合</strong
>
<strong style="font-size: 24px; color: black; margin-left: 210px"
>全链共生</strong
>
<strong style="font-size: 24px; color: black; margin-left: 200px"
>7x24小时服务</strong
>
</div>
</div>
<br />
<div class="relateInfo">
<img src="@/assets/gsl/wx.png" class="InfoImg" />
<img src="@/assets/gsl/wb.png" class="InfoImg" />
<img src="@/assets/gsl/dy.png" class="InfoImg" />
</div>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 390vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.lbt {
width: 1167px;
height: 350px;
background-color: beige;
}
.searchArea {
position: relative;
width: 1167px;
height: 147px;
background-color: #fa4b4b;
}
.searchButtom {
cursor: pointer;
display: inline-block;
width: 96px;
height: 119px;
margin-left: 100px;
}
.funcImg {
width: 96px;
height: 96px;
}
.search {
position: absolute;
top: 50px;
width: 350px;
height: 50px;
background-color: #ffa9a9;
border-radius: 10px;
margin-left: 215px;
}
.search:focus,
.search:hover {
font-size: 15px;
outline: none;
box-shadow: none;
}
.introArea {
width: 1247px;
height: 170px;
margin-top: 200px;
margin-left: -30px;
display: flex;
justify-content: center;
align-items: center;
}
.introduction1 {
font-size: 23px;
color: #333333;
}
.introduction2 {
font-size: 14px;
color: #686363;
margin-left: 455px;
margin-top: 40px;
}
.productions {
width: 1180px;
height: 574px;
margin: 0 auto;
display: flex;
flex-direction: column;
padding-left: 180px;
padding-right: 180px;
}
.row {
display: flex;
flex: 1;
}
.corner {
flex: 2;
width: 425px;
height: 272px;
position: relative;
}
.corner > p {
position: absolute;
left: 77px;
top: 250px;
font-size: 20px;
color: #333333;
}
.top-left,
.bottom-left {
justify-content: flex-start;
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.top-left,
.top-right {
display: flex;
align-items: flex-start;
}
.bottom-left,
.bottom-right {
display: flex;
align-items: flex-end;
}
.marketArea {
position: relative;
width: 1180px;
height: 720px;
/* background-color: aquamarine; */
margin: 0 auto;
}
.img1 {
position: absolute;
width: 570px;
height: 327px;
left: 40px;
top: 50px;
}
.img2 {
position: absolute;
width: 531px;
height: 440px;
left: 619px;
top: 50px;
}
.img3 {
position: absolute;
width: 570px;
height: 327px;
top: 385px;
left: 40px;
}
.img4 {
position: absolute;
width: 531px;
height: 212px;
left: 619px;
top: 500px;
}
.p1 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 330px;
}
.p2 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 440px;
}
.p3 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 660px;
}
.p4 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 660px;
}
.digitIntroduction {
width: 1169px;
height: 520px;
background-color: #f2f2f2;
position: relative;
}
.digit1 {
margin-left: 50px;
}
.digit2 {
margin-left: 50px;
margin-top: 100px;
}
.serveIntro {
position: absolute;
top: 480px;
left: 30px;
border-radius: 5px;
width: 1120px;
height: 120px;
background-color: white;
/* text-align: left; */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
text-align: center;
padding-top: 40px;
}
.relateInfo {
margin-top: 90px;
width: 1169px;
height: 100px;
background-color: #f2f2f2;
padding-top: 20px;
}
.InfoImg {
margin-left: 30px;
cursor: pointer;
}
</style>

@ -0,0 +1,564 @@
<script setup>
import { useTokenStore } from '@/stores/token.js'
import { useInfoStore } from '@/stores/info.js'
import { ElMessage } from 'element-plus'
import router from '@/router'
const tokenStore = useTokenStore()
const infoStore = useInfoStore()
const checkLogin = () => {
if (tokenStore.token == '') {
ElMessage({
message: '请先进行登录',
type: 'warning',
grouping: false,
})
} else {
if (infoStore.info.mark == 2) {
ElMessage({
message: '管理员您好',
type: 'success',
grouping: false,
})
router.push('/admin')
} else {
ElMessage({
message: '欢迎使用猫咪物流',
type: 'success',
grouping: false,
})
router.push('/alLogin')
}
}
}
const RL = () => {
router.push('/login')
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="checkLogin"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="checkLogin"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="checkLogin"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="checkLogin"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<el-col :span="3" @click="RL">
<p class="div-p">注册/登录</p>
</el-col>
</el-row>
</div>
<div class="lbt"></div>
<div class="searchArea">
<span class="searchButtom">
<img
src="@/assets/gsl/icon-wyjj-s.png"
class="funcImg"
@click="checkLogin"
/>
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
@click="checkLogin"
>
我要寄件
</p>
</span>
<span class="searchButtom">
<img
src="@/assets/gsl/icon-wdcx-s.png"
class="funcImg"
@click="checkLogin"
/>
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
@click="checkLogin"
>
网点查询
</p>
</span>
<span class="searchButtom">
<img
src="@/assets/gsl/icon-psfw-s.png"
class="funcImg"
@click="checkLogin"
/>
<p
style="
font-size: 20px;
color: white;
text-align: center;
margin-top: -10px;
"
@click="checkLogin"
>
配送范围
</p>
</span>
<div style="margin-bottom: 50px; display: inline-block; margin-top: 20px">
<input type="text" class="search" />
</div>
<el-icon
style="
width: 1em;
height: 1em;
font-size: 25px;
position: absolute;
left: 1115px;
top: 62px;
cursor: pointer;
"
><Search
/></el-icon>
</div>
<div class="introArea">
<div>
<p class="introduction1">
性能强大安全稳定的物流科技产品
</p>
<p class="introduction2">猫咪物流多年技术沉淀</p>
</div>
</div>
<div class="productions">
<div class="row">
<div class="corner top-left">
<img
src="@/assets/gsl/static_images_home_img-product-01.png"
style="width: 240px; height: 240px"
/>
<p>货到人系统</p>
</div>
<div class="corner top-right">
<img
src="@/assets/gsl/img-product-03.png"
style="width: 240px; height: 240px"
/>
<p>搬运系统</p>
</div>
</div>
<div class="row">
<div class="corner bottom-left">
<img
src="@/assets/gsl/img-product-04.png"
style="width: 240px; height: 240px"
/>
<p>智能快递车</p>
</div>
<div class="corner bottom-right">
<img
src="@/assets/gsl/img-product-05.png"
style="width: 240px; height: 240px"
/>
<p>自动分播墙系统</p>
</div>
</div>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 囊括热门行业 </p>
<p class="introduction2" style="margin-left: 285px">
猫咪物流完善的服务体系为企业保驾护航
</p>
</div>
</div>
<div class="marketArea">
<img src="@/assets/gsl/bg-settle-03.jpg" class="img1" />
<p class="p1">电商</p>
<img src="@/assets/gsl/bg-settle-02.jpg" class="img2" />
<p class="p2">服装</p>
<img src="@/assets/gsl/bg-settle-01.png" class="img3" />
<p class="p3">家电</p>
<img src="@/assets/gsl/bg-settle-05.jpg" class="img4" />
<p class="p4">更多行业...</p>
</div>
<div class="introArea">
<div>
<p class="introduction1"> 物流网络 </p>
<p class="introduction2" style="margin-left: 190px">
遍布全福州的基础设施为物流提供快速稳定智能可靠的服务
</p>
</div>
</div>
<div class="digitIntroduction">
<div class="digit1">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
6
</p>
<p style="font-size: 18; color: #333333; display: inline">大网络</p>
<br />
<p style="margin-top: 15px">
仓储网络综合运输网络最后一公里配送网络大件网络冷链物流网络和跨境物流网络
</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
1600
</p>
<p style="font-size: 18; color: #333333; display: inline">个仓库</p>
<br />
<p style="margin-top: 15px">猫咪物流运营超1600个仓库</p>
</div>
<div class="digit2">
<p
style="
font-size: 28px;
color: red;
display: inline;
margin-right: 15px;
"
>
3200
</p>
<p style="font-size: 18; color: #333333; display: inline">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
<br />
<p style="margin-top: 15px">
含云仓生态平台的管理面积在内猫咪物流仓储总面积超3200万平方米
</p>
</div>
<div class="serveIntro">
<strong style="font-size: 24px; color: black; margin-left: 25px"
>全网覆盖</strong
>
<strong style="font-size: 24px; color: black; margin-left: 185px"
>数实融合</strong
>
<strong style="font-size: 24px; color: black; margin-left: 210px"
>全链共生</strong
>
<strong style="font-size: 24px; color: black; margin-left: 200px"
>7x24小时服务</strong
>
</div>
</div>
<br />
<div class="relateInfo">
<img src="@/assets/gsl/wx.png" class="InfoImg" />
<img src="@/assets/gsl/wb.png" class="InfoImg" />
<img src="@/assets/gsl/dy.png" class="InfoImg" />
</div>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 390vh;
background-color: white;
margin: 0 auto;
position: relative;
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.lbt {
width: 1167px;
height: 350px;
background-color: beige;
}
.searchArea {
position: relative;
width: 1167px;
height: 147px;
background-color: #fa4b4b;
}
.searchButtom {
cursor: pointer;
display: inline-block;
width: 96px;
height: 119px;
margin-left: 100px;
}
.funcImg {
width: 96px;
height: 96px;
}
.search {
position: absolute;
top: 50px;
width: 350px;
height: 50px;
background-color: #ffa9a9;
border-radius: 10px;
margin-left: 215px;
}
.search:focus,
.search:hover {
font-size: 15px;
outline: none;
box-shadow: none;
}
.introArea {
width: 1247px;
height: 170px;
margin-top: 200px;
margin-left: -30px;
display: flex;
justify-content: center;
align-items: center;
}
.introduction1 {
font-size: 23px;
color: #333333;
}
.introduction2 {
font-size: 14px;
color: #686363;
margin-left: 455px;
margin-top: 40px;
}
.productions {
width: 1180px;
height: 574px;
margin: 0 auto;
display: flex;
flex-direction: column;
padding-left: 180px;
}
.row {
display: flex;
flex: 1;
}
.corner {
flex: 2;
width: 425px;
height: 272px;
position: relative;
}
.corner > p {
position: absolute;
left: 77px;
top: 250px;
font-size: 20px;
color: #333333;
}
.top-left,
.bottom-left {
justify-content: flex-start;
}
.top-left,
.top-right {
display: flex;
align-items: flex-start;
}
.bottom-left,
.bottom-right {
display: flex;
align-items: flex-end;
}
.marketArea {
position: relative;
width: 1180px;
height: 720px;
/* background-color: aquamarine; */
margin: 0 auto;
}
.img1 {
position: absolute;
width: 570px;
height: 327px;
left: 40px;
top: 50px;
}
.img2 {
position: absolute;
width: 531px;
height: 440px;
left: 619px;
top: 50px;
}
.img3 {
position: absolute;
width: 570px;
height: 327px;
top: 385px;
left: 40px;
}
.img4 {
position: absolute;
width: 531px;
height: 212px;
left: 619px;
top: 500px;
}
.p1 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 330px;
}
.p2 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 440px;
}
.p3 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 50px;
top: 660px;
}
.p4 {
position: absolute;
font-size: 28px;
color: #f5f7fa;
left: 630px;
top: 660px;
}
.digitIntroduction {
width: 1169px;
height: 520px;
background-color: #f2f2f2;
position: relative;
}
.digit1 {
margin-left: 50px;
}
.digit2 {
margin-left: 50px;
margin-top: 100px;
}
.serveIntro {
position: absolute;
top: 480px;
left: 30px;
border-radius: 5px;
width: 1120px;
height: 120px;
background-color: white;
/* text-align: left; */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
text-align: center;
padding-top: 40px;
}
.relateInfo {
margin-top: 90px;
width: 1169px;
height: 100px;
background-color: #f2f2f2;
padding-top: 20px;
}
.InfoImg {
margin-left: 30px;
cursor: pointer;
}
</style>

@ -0,0 +1,468 @@
<script setup>
defineOptions({
name: 'QueryIndex',
})
import { ref, computed } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import { useInfoStore } from '@/stores/info.js'
import {
queryExpressService,
getSendUserService,
getSingleistory,
getMessageFromService,
userConfirmMessageService,
userDeleteMessageService,
} from '@/api/user.js'
import router from '@/router'
const vision = ref(false)
const input1 = ref('')
const infoStore = useInfoStore()
const goodsInfo = ref('')
const personInfo = ref({
sendUser: '',
getUser: '',
mark: '',
addressee: '',
})
const visible = ref(false)
const queryInfo = async () => {
//
let result = await queryExpressService(input1.value, infoStore.info.id)
if (result.data == null) {
ElMessage({
message: '查询失败,请输入正确的快递码或由本人进行查询',
type: 'error',
grouping: true,
})
return
}
ElMessage({
message: '查询成功',
type: 'success',
grouping: true,
})
goodsInfo.value = result.data
//
result = await getSendUserService(goodsInfo.value.sendUserId)
personInfo.value.sendUser = result.data
//
result = await getSendUserService(goodsInfo.value.getUserId)
personInfo.value.getUser = result.data
//
result = await getSingleistory(goodsInfo.value.id)
personInfo.value.mark = result.data.mark
//
if (result.data.addresseeId !== null) {
result = await getSendUserService(result.data.addresseeId)
personInfo.value.addressee = result.data
}
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
const msgList = ref([])
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const goToChat = userName => {
router.push({
name: 'Chat',
params: {
userName: userName,
},
})
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3" @click="router.push('/alLogin')">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/get')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/send')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">查询快递</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<div>
<div class="title">
<strong style="font-size: 50px; color: red; letter-spacing: 5px"
>运单查询</strong
>
</div>
<div class="queryArea">
<div class="flex gap-4 mb-4 items-center">
<el-input
v-model="input1"
style="width: 500px"
size="large"
placeholder="请输入快递码"
/>
</div>
<el-popover
placement="bottom"
title="物流信息"
:width="600"
trigger="click"
v-model:visible="vision"
>
<template #default>
<div class="popover-content">
<div v-if="goodsInfo !== ''">
<p>邮寄方{{ personInfo.sendUser }}</p>
<p>收件方{{ personInfo.getUser }}</p>
<p>货物{{ goodsInfo.name }}</p>
<p>重量{{ goodsInfo.quality }} kg</p>
<p>
签收状态
<span v-if="personInfo.mark === 1"></span>
<span v-else></span>
</p>
<p v-if="personInfo.addressee !== ''">
签收者{{ personInfo.addressee }}
</p>
<el-button type="text" @click="vision = false">关闭</el-button>
</div>
<div v-else>
<p>查无此快递</p>
</div>
</div>
</template>
<template #reference>
<el-button type="primary" @click="queryInfo"></el-button>
</template>
</el-popover>
</div>
</div>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.title {
width: 1169px;
height: 150px;
/* background-color: aqua; */
text-align: center;
padding-top: 50px;
}
.queryArea {
display: flex;
align-items: center; /* 垂直居中对齐 */
margin-top: 100px;
margin-left: 315px;
}
.el-button,
.el-button.is-round {
padding: 20px 20px;
}
:root {
--el-border-radius-base: 1px 5px 5px 1px;
}
.el-input__wrapper {
border-radius: 5px 0 0 5px;
}
.GoodInfo {
width: 600px;
height: 100px;
background-color: bisque;
margin-left: 315px;
margin-top: 21px;
}
</style>

@ -0,0 +1,745 @@
<script setup>
defineOptions({
name: 'SendIndex',
})
import { onMounted, computed } from 'vue'
import { ref } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import { useInfoStore } from '@/stores/info.js'
import {
getAddressListService,
addAddressService,
sendExpressService,
getMessageFromService,
getSendUserService,
userConfirmMessageService,
userDeleteMessageService,
} from '@/api/user.js'
const visible = ref(false)
const infoStore = useInfoStore()
const addressList = ref([])
// do not use same name with ref
const sendform = ref({
company: 'MM',
name: '',
quality: '',
addressFrom: '',
})
const receiveform = ref({
getUserName: '',
addressTo: '',
})
//
const dialogVisible = ref(false)
const dialogVisible2 = ref(false)
const title = ref('')
//
const addressFrom = ref('')
//
const addressTo = ref('')
//
const onSubmit = async () => {
const goodsModel = ref({
company: sendform.value.company,
getUserName: receiveform.value.getUserName,
name: sendform.value.name,
quality: sendform.value.quality,
addressFrom: sendform.value.addressFrom,
addressTo: receiveform.value.addressTo,
})
let result = await sendExpressService(goodsModel.value)
if (result.code == 200) {
ElMessage({
message: '寄件成功, 等待对方收件',
type: 'success',
grouping: true,
})
clearAllData()
}
}
const clearAllData = () => {
sendform.value.company = 'MM'
sendform.value.name = ''
sendform.value.quality = ''
sendform.value.addressFrom = ''
receiveform.value.getUserName = ''
receiveform.value.addressTo = ''
}
//
const getAddress = async () => {
let result = await getAddressListService(infoStore.info.id)
addressList.value = result.data
}
onMounted(() => {
getAddress()
})
//
const addAddress = async () => {
dialogVisible.value = false
const addressModel = ref({
userId: infoStore.info.id,
address: addressFrom.value,
})
let result = await addAddressService(addressModel.value)
if (result.code == 200) {
ElMessage({
message: '发货地址新建成功',
type: 'success',
grouping: true,
})
getAddress()
}
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
const msgList = ref([])
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const goToChat = userName => {
router.push({
name: 'Chat',
params: {
userName: userName,
},
})
}
</script>
<template>
<div>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3" @click="router.push('/alLogin')">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/get')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">寄件</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/query')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge
v-if="item.mark == 1"
is-dot
class="item"
></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<br /><br />
<!-- 寄件人信息 -->
<div class="sender">
<img src="@/assets/gsl/send_icon.png" style="display: inline" />
<p style="display: inline; margin-left: 15px">寄件人信息填写</p>
<br /><br />
<el-form :model="sendform" label-width="auto" style="max-width: 600px">
<el-form-item label="寄件人姓名">
<el-input :value="infoStore.info.userName" disabled />
</el-form-item>
<el-form-item label="寄件人身份证">
<el-input
:value="infoStore.info.identity"
disabled
type="password"
/>
</el-form-item>
<el-form-item label="寄件人手机号">
<el-input :value="infoStore.info.phone" disabled />
</el-form-item>
<el-form-item label="快递名称">
<el-input v-model="sendform.name" placeholder="请填写快递名称" />
</el-form-item>
<el-form-item label="快递公司">
<el-select v-model="sendform.company" placeholder="选择快递公司">
<el-option label="猫咪物流" value="MM" />
<el-option label="顺丰物流" value="SF" />
<el-option label="京东物流" value="JD" />
<el-option label="圆通快递" value="YT" />
<el-option label="韵达快递" value="YD" />
<el-option label="德邦物流" value="DB" />
<el-option label="邮政快递" value="YZ" />
</el-select>
</el-form-item>
<el-form-item label="发货地址">
<el-select
v-model="sendform.addressFrom"
placeholder="选择发货地址"
>
<el-option
v-for="address in addressList"
:key="address.id"
:label="address.address"
:value="address.address"
></el-option>
</el-select>
<el-button
class="btn-shine"
style="margin-top: 8px"
@click="
(dialogVisible = true),
(title = '新建发货地址'),
(addressFrom = '')
"
>新建地址</el-button
>
<el-dialog v-model="dialogVisible" :title="title" width="500">
<el-form>
<el-form-item label="发货地址" label-width="140px">
<el-input v-model="addressFrom"></el-input
></el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button
@click="(dialogVisible = false), (addressFrom = '')"
>取消</el-button
>
<el-button type="primary" @click="addAddress">
确认
</el-button>
</div>
</template>
</el-dialog>
</el-form-item>
<el-form-item label="货物重量">
<el-input
v-model.number="sendform.quality"
type="number"
step="0.01"
style="width: 150px; display: inline-block"
/>
<span style="margin-left: 10px">kg</span>
</el-form-item>
<br />
</el-form>
</div>
<br /><br /><br />
<!-- 收件人信息 -->
<div class="sender">
<img src="@/assets/gsl/receive_icon.png" style="display: inline" />
<p style="display: inline; margin-left: 15px">收件人信息填写</p>
<br /><br />
<el-form
:model="receiveform"
label-width="auto"
style="max-width: 600px"
>
<el-form-item label="收件人姓名">
<el-input v-model="receiveform.getUserName" />
</el-form-item>
<el-form-item label="收件地址">
<el-select
v-model="receiveform.addressTo"
placeholder="选择收件地址"
>
<el-option
v-for="address in addressList"
:key="address.id"
:label="address.address"
:value="address.address"
></el-option>
</el-select>
<el-button
class="btn-shine"
style="margin-top: 8px"
@click="
(dialogVisible = true),
(title = '新建收货地址'),
(addressFrom = '')
"
>新建地址</el-button
>
<el-dialog v-model="dialogVisible2" :title="title" width="500">
<el-form>
<el-form-item label="收货地址" label-width="140px">
<el-input v-model="addressTo"></el-input
></el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="(dialogVisible2 = false), (addressTo = '')"
>取消</el-button
>
<el-button type="primary" @click="addAddress">
确认
</el-button>
</div>
</template>
</el-dialog>
</el-form-item>
<br />
</el-form>
</div>
<div class="mb-4">
<el-button
type="primary"
style="margin-left: 350px; margin-top: 15px; margin-bottom: 20px"
class="btn2"
@click="onSubmit"
>提交</el-button
>
</div>
</div>
<br /><br />
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.sender {
background-color: #eee;
border-radius: 5px;
}
/* From Uiverse.io by vikiWayne */
.btn2 {
padding: 1em 2em;
border: none;
border-radius: 5px;
font-weight: bold;
letter-spacing: 5px;
text-transform: uppercase;
cursor: pointer;
color: black;
transition: all 1000ms;
font-size: 15px;
position: relative;
overflow: hidden;
outline: 2px solid #2c9caf;
}
.btn2:hover {
color: #ffffff;
transform: scale(1.1);
outline: 2px solid #70bdca;
box-shadow: 4px 5px 17px -4px #268391;
}
.btn2::before {
content: '';
position: absolute;
left: -50px;
top: 0;
width: 0;
height: 100%;
background-color: #2c9caf;
transform: skewX(45deg);
z-index: -1;
transition: width 1000ms;
}
.btn2:hover::before {
width: 250%;
}
/* From Uiverse.io by mobinkakei */
.btn-shine {
position: relative;
margin: 0;
padding: 17px 35px;
outline: none;
text-decoration: none;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
text-transform: uppercase;
background-color: #fff;
border: 1px solid rgba(22, 76, 167, 0.6);
border-radius: 10px;
color: #1d89ff;
font-weight: 400;
font-family: inherit;
z-index: 0;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.02, 0.01, 0.47, 1);
}
.btn-shine span {
color: #164ca7;
font-size: 14px;
font-weight: 500;
letter-spacing: 0.7px;
}
.btn-shine:hover {
animation: rotate624 0.7s ease-in-out both;
}
.btn-shine:hover span {
animation: storm1261 0.7s ease-in-out both;
animation-delay: 0.06s;
}
@keyframes rotate624 {
0% {
transform: rotate(0deg) translate3d(0, 0, 0);
}
25% {
transform: rotate(3deg) translate3d(0, 0, 0);
}
50% {
transform: rotate(-3deg) translate3d(0, 0, 0);
}
75% {
transform: rotate(1deg) translate3d(0, 0, 0);
}
100% {
transform: rotate(0deg) translate3d(0, 0, 0);
}
}
@keyframes storm1261 {
0% {
transform: translate3d(0, 0, 0) translateZ(0);
}
25% {
transform: translate3d(4px, 0, 0) translateZ(0);
}
50% {
transform: translate3d(-3px, 0, 0) translateZ(0);
}
75% {
transform: translate3d(2px, 0, 0) translateZ(0);
}
100% {
transform: translate3d(0, 0, 0) translateZ(0);
}
}
.btn-shine {
border: 1px solid;
overflow: hidden;
position: relative;
}
.btn-shine span {
z-index: 20;
}
.btn-shine:after {
background: #38ef7d;
content: '';
height: 155px;
left: -75px;
opacity: 0.4;
position: absolute;
top: -50px;
transform: rotate(35deg);
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
width: 50px;
z-index: -10;
}
.btn-shine:hover:after {
left: 120%;
transition: all 550ms cubic-bezier(0.19, 1, 0.22, 1);
}
</style>

@ -0,0 +1,618 @@
<script setup>
defineOptions({
name: 'TakeIndex',
})
import { computed, ref } from 'vue'
import { ElButton, ElDrawer, ElMessage } from 'element-plus'
import { CircleCloseFilled } from '@element-plus/icons-vue'
import router from '@/router'
import {
getMessageFromService,
getSendUserService,
userConfirmMessageService,
userDeleteMessageService,
pickUpExpressService,
} from '@/api/user.js'
import { useInfoStore } from '@/stores/info.js'
const infoStore = useInfoStore()
const visible = ref(false)
const msgList = ref([])
//
const getMessageFromOthers = async () => {
let result = await getMessageFromService(infoStore.info.id)
for (const msg of result.data) {
msg.senderName = await getWhoSendMsg(msg.sendUserId) //
}
msgList.value = result.data
}
getMessageFromOthers()
const getWhoSendMsg = async id => {
let result = await getSendUserService(id)
return result.data
}
//
const confirm = async id => {
let result = await userConfirmMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
const calculate = computed(() => {
return msgList.value.filter(msg => msg.mark === 1).length
})
//
const formatDate = cellValue => {
const date = new Date(cellValue)
return date.toLocaleString()
}
//
const deleteMsg = async id => {
let result = await userDeleteMessageService(id)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
getMessageFromOthers()
}
}
//
const clearDot = async () => {
const unreadMessages = msgList.value.filter(msg => msg.mark === 1)
if (unreadMessages.length === 0) {
ElMessage({
message: '没有未读消息!',
type: 'warning',
})
return
}
//
for (const msg of unreadMessages) {
// ID
let result = await userConfirmMessageService(msg.id)
if (result.code !== 200) {
//
ElMessage({
message: `消息ID ${msg.id} 确认失败: ${result.message}`,
type: 'error',
})
}
}
ElMessage({
message: '消息确认成功!',
type: 'success',
})
//
getMessageFromOthers()
}
const goToChat = userName => {
router.push({
name: 'Chat',
params: {
userName: userName,
},
})
}
//
const PickUpExpressDTO = ref({
master: '',
expressCode: '',
claimCode: '',
})
//
const pickUp = async () => {
let result = await pickUpExpressService(PickUpExpressDTO.value)
if (result.code == 200) {
ElMessage({
message: result.message,
type: 'success',
grouping: true,
})
} else {
ElMessage({
message: result.message,
type: 'warning',
grouping: true,
})
}
clear()
}
const clear = () => {
;(PickUpExpressDTO.value.master = ''),
(PickUpExpressDTO.value.expressCode = ''),
(PickUpExpressDTO.value.claimCode = '')
}
</script>
<template>
<div class="container">
<div class="bg">
<el-row :gutter="0">
<el-col :span="3">
<img
src="@/assets/gsl/logo1.png"
style="width: 100px; height: 100px; margin: 0 25px"
/>
</el-col>
<el-col :span="3" @click="router.push('/alLogin')">
<p class="div-p">首页</p>
</el-col>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">快递服务</p>
</el-col>
</template>
<div class="funcs" @click="router.push('/get')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/send')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/query')"></div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs" @click="router.push('/take')"></div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">可持续发展</p>
</el-col>
</template>
<div class="funcs">ESG</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">零碳未来</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">社会关怀</div>
</el-popover>
<el-popover placement="bottom" :width="150" trigger="hover">
<template #reference>
<el-col :span="3">
<p class="div-p">关于我们</p>
</el-col>
</template>
<div class="funcs">企业介绍</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">联系方式</div>
<el-divider style="margin-top: 10px; margin-bottom: 10px" />
<div class="funcs">开发人员</div>
</el-popover>
<div class="userPic">
<button class="inbox-btn" @click="visible = true">
<svg
viewBox="0 0 512 512"
height="16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"
></path>
</svg>
<!-- msg-count是新消息的数量 -->
<span class="msg-count">{{ calculate }}</span>
</button>
<el-drawer v-model="visible" :show-close="false">
<template #header="{ close, titleId, titleClass }">
<!-- 消息头 -->
<h4 :id="titleId" :class="titleClass">消息列表</h4>
<!-- 一键已读功能按钮 -->
<p class="readAll" @click="clearDot"></p>
<!-- 关闭抽屉功能 -->
<el-button type="danger" @click="close">
<el-icon class="el-icon--left"><CircleCloseFilled /></el-icon>
Close
</el-button>
<div></div>
<br /><br />
</template>
<!-- 卡片数组名叫 msgList-->
<el-card
style="max-width: 560px; margin-bottom: 10px"
v-for="item in msgList"
:key="item.id"
>
<template #header>
<div class="card-header">
<!-- 发件人 -->
<el-badge v-if="item.mark == 1" is-dot class="item"></el-badge
><span @click="goToChat(item.senderName)"
>发件人{{ item.senderName }}
</span>
<br />
<span>发送时间{{ formatDate(item.createTime) }}</span>
<!-- 删除功能 -->
<el-icon
color="red"
style="float: right; cursor: pointer"
@click="deleteMsg(item.id)"
><Close
/></el-icon>
</div>
</template>
<!-- 内容 -->
<p class="text item">{{ item.content }}</p>
<!-- 确认功能 -->
<el-button
size="default"
type="primary"
style="float: right; margin-bottom: 10px"
@click="confirm(item.id)"
v-if="item.mark == 1"
>确认</el-button
>
</el-card>
</el-drawer>
</div>
</el-row>
</div>
<br />
<span>
<div class="title">
<strong style="font-size: 50px; color: red; letter-spacing: 5px"
>代取快递</strong
>
</div>
<!-- 代取主体 -->
<form class="form" :model="PickUpExpressDTO">
<input
placeholder="请输入快递主人姓名"
class="input2"
type="text"
v-model="PickUpExpressDTO.master"
/>
<input
placeholder="请输入快递码"
class="input2"
type="text"
v-model="PickUpExpressDTO.expressCode"
/>
<input
placeholder="请输入取件码"
class="input2"
type="text"
v-model="PickUpExpressDTO.claimCode"
/>
<button @click="pickUp" class="pButton" type="button">代取</button>
</form>
</span>
</div>
</template>
<style scoped>
body {
background: #f5f7fa;
}
.container {
width: 125vh;
height: 100vh;
background-color: white;
margin: 0 auto;
position: relative;
}
a {
color: inherit; /* 使链接文本颜色继承父元素的颜色 */
text-decoration: none; /* 移除下划线 */
}
/* 如果你还想改变鼠标悬停时的样式 */
a:hover {
text-decoration: none; /* 悬停时仍然没有下划线 */
cursor: auto; /* 改变鼠标指针样式为默认,或根据需要设置其他样式 */
}
.el-row {
margin-bottom: 20px;
justify-content: space-between;
}
.el-col {
border-radius: 4px;
margin-right: 50px;
width: 100px;
height: 100px;
}
.userPic {
height: 90px;
width: 90px;
margin-top: 15px;
}
.el-col:last-child {
margin-right: 0px;
}
.el-row:last-child {
margin-bottom: 0;
}
.inbox-btn {
width: 50px;
height: 50px;
border-radius: 50%;
border: none;
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.082);
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #464646;
cursor: pointer;
transition: all 0.3s;
}
.inbox-btn svg path {
fill: white;
}
.inbox-btn svg {
height: 17px;
transition: all 0.3s;
}
.msg-count {
position: absolute;
top: -5px;
right: -5px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
font-size: 0.7em;
color: red;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.inbox-btn:hover {
transform: scale(1.1);
}
.div-p {
font-size: 13px;
text-align: center;
margin-top: 20%;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.el-col:hover {
cursor: pointer;
border-bottom: 1px solid red;
color: red;
}
.funcs {
text-align: center;
cursor: pointer;
}
.funcs:hover {
color: red;
}
.title {
width: 1169px;
height: 150px;
/* background-color: aqua; */
text-align: center;
padding-top: 50px;
}
.queryArea {
display: flex;
align-items: center; /* 垂直居中对齐 */
margin-top: 100px;
margin-left: 315px;
}
.el-button,
.el-button.is-round {
padding: 20px 20px;
}
:root {
--el-border-radius-base: 1px 5px 5px 1px;
}
.el-input__wrapper {
border-radius: 5px 0 0 5px;
}
.item {
margin-top: 10px;
margin-right: 40px;
}
.demo-collapse {
position: absolute;
left: 10%;
}
.item {
margin-top: 10px;
margin-right: 10px;
}
.goodsInfo {
width: 1000px;
height: 50px;
border-radius: 25px;
background-color: #eea8b8;
margin-bottom: 20px;
}
.goodsInfo > p {
margin-top: 15px;
margin-left: 16px;
}
.goodsInfo:hover {
background-color: pink;
height: 200px;
}
.btn {
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
border: none;
background-color: transparent;
position: relative;
}
.btn:hover > .icon {
transform: scale(1.2);
cursor: pointer;
transition: 0.2s linear;
}
.btn:focus > .icon {
fill: #fd1853;
animation: grosseur 0.2s linear;
}
@keyframes grosseur {
0% {
width: 50px;
height: 50px;
fill: #fd1853;
}
100% {
width: 30px;
height: 30px;
fill: #fd1853;
}
}
.readAll {
font-size: 10px;
margin-right: 20px;
cursor: pointer;
}
.readAll:hover {
color: deepskyblue;
}
.expandable {
width: 1000px;
height: 50px;
background-color: #eea8b8;
border-radius: 25px;
margin-bottom: 25px;
overflow: hidden;
transition: all 1s ease;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.05);
}
.expandable.expanded {
height: auto; /* 或者设置具体的像素值 */
}
.hidden-content {
display: none;
transition:
opacity 0.8s ease,
max-height 0.8s ease;
}
.expandable.expanded .hidden-content {
display: block;
}
/* From Uiverse.io by aboalsim114 */
.form {
margin-left: 25%;
width: 600px;
position: relative;
display: flex;
flex-direction: column;
gap: 10px;
padding: 20px;
background: linear-gradient(to bottom, #0077be, #3b8df2);
border-radius: 10px;
overflow: hidden;
perspective: 1000px;
transform-style: preserve-3d;
transform: rotateX(-10deg);
transition: all 0.3s ease-in-out;
box-shadow:
rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
animation: form-animation 0.5s ease-in-out;
}
@keyframes form-animation {
from {
transform: rotateX(-30deg);
opacity: 0;
}
to {
transform: rotateX(0deg);
opacity: 1;
}
}
.input2 {
padding: 10px;
border-radius: 5px;
background-color: transparent;
transition:
border-color 0.3s ease-in-out,
background-color 0.3s ease-in-out,
transform 0.3s ease-in-out,
box-shadow 0.3s ease-in-out;
transform-style: preserve-3d;
backface-visibility: hidden;
color: rgb(255, 255, 255);
border: 2px solid #3b8df2;
box-shadow:
rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
}
.input2::placeholder {
color: #fff;
}
.input2:hover,
.input2:focus {
border-color: #3b8df2;
background-color: rgba(255, 255, 255, 0.2);
transform: scale(1.05) rotateY(20deg);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3);
outline: none;
}
.pButton {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #3b8df2;
color: #fff;
font-size: 16px;
cursor: pointer;
transform-style: preserve-3d;
backface-visibility: hidden;
transform: rotateX(-10deg);
transition: all 0.3s ease-in-out;
box-shadow:
rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
}
.pButton:hover {
background-color: #0077be;
font-size: 17px;
transform: scale(1.05) rotateY(20deg) rotateX(10deg);
box-shadow:
rgba(0, 0, 0, 0.4) 0px 2px 4px,
rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
}
</style>

@ -1,17 +1,42 @@
import { createRouter, createWebHistory } from 'vue-router'
import Login from '@/views/Login.vue'
import Common from '@/views/Common.vue'
import Admin from '@/views/Admin.vue'
import HomePage from '@/components/Admin/HomePage.vue'
import UserController from '@/components/Admin/UserController.vue'
import employeeController from '@/components/Admin/employeeController.vue'
import BaseData from '@/components/Admin/BaseData.vue'
import ModifyPassword from '@/components/Admin/ModifyPassword.vue'
import ExpressController from '@/components/Admin/ExpressController.vue'
import SendMessage from '@/components/Admin/SendMessage.vue'
import MainPageUnLogin from '@/components/User/MainPage(UnLogin).vue'
import MainPageLogin from '@/components/User/MainPage(Login).vue'
import Query from '@/components/User/Query.vue'
import Send from '@/components/User/Send.vue'
import Get from '@/components/User/Get.vue'
import Chat from '@/components/User/Chat.vue'
import Take from '@/components/User/Take.vue'
import CourierChat from '@/components/Employee/CourierChat.vue'
import MainPageEmployee from '@/components/Employee/MainPage(employee).vue'
import CourierGet from '@/components/Employee/CourierGet.vue'
import CourierResearch from '@/components/Employee/CourierResearch.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{ path: '/', component: MainPageUnLogin },
{ path: '/alLogin', component: MainPageLogin },
{ path: '/query', component: Query },
{ path: '/send', component: Send },
{ path: '/get', component: Get },
{ path: '/chat/:userName', name: 'Chat', component: Chat },
{ path: '/take', component: Take },
{ path: '/emLogin', component: MainPageEmployee },
{ path: '/courierChat/:userName', name: 'emChat', component: CourierChat },
{ path: '/courierGet', component: CourierGet },
{ path: '/research', component: CourierResearch },
{
path: '/',
component: Common,
path: '/login',
component: Login,
},
{
path: '/admin',
@ -24,12 +49,12 @@ const router = createRouter({
component: UserController,
},
{ path: '/employeeController', component: employeeController },
{ path: '/profile', component: BaseData },
{ path: '/modifyPassword', component: ModifyPassword },
{ path: '/express', component: ExpressController },
{ path: '/sendMessage', component: SendMessage },
],
},
{
path: '/login',
component: Login,
},
],
})

@ -8,11 +8,21 @@ import router from '@/router'
import { useTokenStore } from '@/stores/token.js'
import { useInfoStore } from '@/stores/info.js'
import { getInfoService } from '@/api/common.js'
import { onMounted } from 'vue'
import { onMounted, ref } from 'vue'
const tokenStore = useTokenStore()
const infoStore = useInfoStore()
const jumpTo = ref({
home: '/home',
userAccount: '/userAccount',
employeeController: '/employeeController',
profile: '/profile',
modifyPassword: '/modifyPassword',
express: '/express',
message: '/sendMessage',
})
onMounted(() => {
getInfo() //
})
@ -23,7 +33,7 @@ const getInfo = async () => {
infoStore.setInfo(result.data)
}
//
//
const handleCommand = command => {
if (command == 'logout') {
ElMessageBox.confirm('您确认要退出登录吗', '温馨提示', {
@ -42,11 +52,11 @@ const handleCommand = command => {
handleElMessage('管理员取消了退出登录', 'info')
})
} else {
router.push('/user/' + command)
router.push('/' + command)
}
}
//ElMessage
// ElMessage
const handleElMessage = (message, type) => {
ElMessage({
message: message,
@ -67,7 +77,7 @@ const handleElMessage = (message, type) => {
text-color="#fff"
router
>
<el-menu-item index="/home">
<el-menu-item :index="jumpTo.home">
<el-icon><Odometer /></el-icon>
<span>首页</span>
</el-menu-item>
@ -76,20 +86,24 @@ const handleElMessage = (message, type) => {
<el-icon><Operation /></el-icon>
<span>账号管理</span>
</template>
<el-menu-item index="/userAccount">
<el-menu-item :index="jumpTo.userAccount">
<el-icon><User /></el-icon>
<span>用户账号</span>
</el-menu-item>
<el-menu-item index="/employeeController">
<el-menu-item :index="jumpTo.employeeController">
<el-icon><Box /></el-icon>
<span>快递员账号</span>
</el-menu-item>
</el-sub-menu>
<el-menu-item index="">
<el-menu-item :index="jumpTo.express">
<el-icon>
<Promotion />
</el-icon>
<span>文章管理</span>
<span>快递记录</span>
</el-menu-item>
<el-menu-item :index="jumpTo.message">
<el-icon><ChatLineRound /></el-icon>
<span>发送消息</span>
</el-menu-item>
<!-- 子菜单 -->
<el-sub-menu>
@ -99,19 +113,11 @@ const handleElMessage = (message, type) => {
</el-icon>
<span>个人中心</span>
</template>
<el-menu-item index="">
<el-icon>
<User />
</el-icon>
<el-menu-item :index="jumpTo.profile">
<el-icon><Avatar /></el-icon>
<span>基本资料</span>
</el-menu-item>
<el-menu-item index="">
<el-icon>
<Crop />
</el-icon>
<span>更换头像</span>
</el-menu-item>
<el-menu-item index="">
<el-menu-item :index="jumpTo.modifyPassword">
<el-icon>
<EditPen />
</el-icon>
@ -136,13 +142,10 @@ const handleElMessage = (message, type) => {
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="info" :icon="User"
<el-dropdown-item command="profile" :icon="User"
>基本资料</el-dropdown-item
>
<el-dropdown-item command="avatar" :icon="Crop"
>更换头像</el-dropdown-item
>
<el-dropdown-item command="resetPassword" :icon="EditPen"
<el-dropdown-item command="modifyPassword" :icon="EditPen"
>重置密码</el-dropdown-item
>
<el-dropdown-item command="logout" :icon="SwitchButton"

@ -1,9 +0,0 @@
<script setup>
defineOptions({
name: 'CommonIndex',
})
</script>
<template></template>
<style scoped></style>

@ -1,5 +1,4 @@
<script setup>
// alias
defineOptions({
name: 'LoginIndex',
})
@ -16,9 +15,9 @@ const registerLoading = ref(false)
//
const loginModelData = ref({
account: 'admin',
password: 'admin',
mark: 2,
account: '',
password: '',
mark: 1,
})
//
@ -110,8 +109,10 @@ const login = () => {
tokenStore.setToken(result.data)
if (loginModelData.value.mark == 2) {
router.push('/admin')
} else if (loginModelData.value.mark == 0) {
router.push('/alLogin')
} else {
router.push('/')
router.push('/emLogin')
}
} else {
ElMessage({

259
mvnw vendored

@ -0,0 +1,259 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

149
mvnw.cmd vendored

@ -0,0 +1,149 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.2
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
if ($env:MAVEN_USER_HOME) {
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
}
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>jty</groupId>
<artifactId>ExpressDistributionSystem</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ExpressDistributionSystem</name>
<description>ExpressDistributionSystem</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 参数校验依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Mybatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- 工具类: 字符串处理、数字处理、对象操作等 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- 支持将 Java 对象转换为 JSON 格式,以及将 JSON 字符串解析为 Java 对象 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.0</version>
</dependency>
<!-- JWT令牌 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<!-- 注解 -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,14 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class AddresseeDTO {
@NotNull
private Long goodsId;
@NotBlank(message = "取件码不能为空")
private String claimCode;
}

@ -0,0 +1,19 @@
package jty.expressdistributionsystem.DTO;
import jty.expressdistributionsystem.entity.Address;
import jty.expressdistributionsystem.entity.Goods;
import jty.expressdistributionsystem.entity.Records;
import jty.expressdistributionsystem.entity.User;
import lombok.Data;
@Data
public class EmExpressDTO {
private User sendUser;
private User getUser;
private User addressee;
private User express;
private Address addressTo;
private Goods goods;
private Address addressFrom;
private Records records;
}

@ -0,0 +1,30 @@
package jty.expressdistributionsystem.DTO;
import jty.expressdistributionsystem.entity.Address;
import jty.expressdistributionsystem.entity.Goods;
import jty.expressdistributionsystem.entity.Records;
import jty.expressdistributionsystem.entity.User;
import lombok.Data;
@Data
public class ExpressListDTO {
private Records records;
private Goods goods;
private User sender; // 寄件人
private User recipient; // 收件人
private User addressee; // 签收者
private User courier; // 派送的快递员
private Address addressFrom; // 从哪里送的
private Address addressTo; // 送到哪里
public ExpressListDTO(Records records, Goods goods, User sender, User recipient, User addressee, User courier, Address addressFrom, Address addressTo) {
this.records = records;
this.goods = goods;
this.sender = sender;
this.recipient = recipient;
this.addressee = addressee;
this.courier = courier;
this.addressFrom = addressFrom;
this.addressTo = addressTo;
}
}

@ -0,0 +1,33 @@
package jty.expressdistributionsystem.DTO;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jty.expressdistributionsystem.validation.inter.ValidQuality;
import lombok.Data;
@Data
public class GoodsDTO {
@NotBlank(message = "请选择快递公司")
private String company;
@NotBlank(message = "收件人名字不能为空")
private String getUserName;
@NotBlank(message = "快递名称不能为空")
private String name;
/**
* 使 @NotBlank
* NotBlank
*/
@ValidQuality
private Double quality;
@NotBlank(message = "发货地不能为空")
private String addressFrom;
@NotBlank(message = "收件地址不能为空")
private String addressTo;
}

@ -0,0 +1,16 @@
package jty.expressdistributionsystem.DTO;
import lombok.Data;
@Data
public class GoodsEmDTO {
private String name;
private String sendUser;
private String getUser;
private String employee;
private Double quality;
private String addressFrom;
private String addressTo;
private Integer mark;
private String addressee;
}

@ -0,0 +1,16 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class PickUpExpressDTO {
@NotBlank(message = "收件人名字不能为空")
private String master;
@NotBlank(message = "快递码不能为空")
private String expressCode;
@NotBlank(message = "取件码不能为空")
private String claimCode;
}

@ -0,0 +1,17 @@
package jty.expressdistributionsystem.DTO;
import jty.expressdistributionsystem.entity.*;
import lombok.Data;
@Data
public class RecordsListDTO {
private Goods goods; // 查看货物名称
private Address addressFrom; // 查看发货地
private Address addressTo; // 查看发到哪里
private User employee; // 查看快递员
private User addressee; // 查看谁签收的
private User sendUser; // 查看谁发的
private User getUserId; // 查看发给谁的
private Code code; // 快递取件码
private Records record; // 查看是否被签收
}

@ -0,0 +1,13 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class SendMessageDTO {
@NotBlank(message = "请选择你的聊天对象")
private String toUserName;
@NotBlank(message = "消息不能为空")
private String content;
}

@ -0,0 +1,20 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Data
public class UserLoginByAccountDTO {
@NotBlank(message = "账号不能为空")
@Pattern(regexp = "^(?!\\s)([A-Za-z0-9]{1,10})$", message = "账号长度在1-10位之间")
private String account;
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^.+$", message = "密码不能为空")
private String password;
@NotNull
private Integer mark;
}

@ -0,0 +1,15 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Data
public class UserModifyInfoDTO {
@NotBlank(message = "用户名不能为空")
private String userName;
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号不存在")
private String phone;
}

@ -0,0 +1,25 @@
package jty.expressdistributionsystem.DTO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Data
public class UserModifyPasswordDTO {
@NotBlank(message = "旧密码不能为空")
@Pattern(regexp = "^.+$", message = "旧密码不能为空")
private String oldPassword;
@NotBlank(message = "新密码不能为空")
@Pattern(regexp = "^.+$", message = "新密码不能为空")
private String newPassword;
@NotBlank(message = "再次输入的密码不能为空")
@Pattern(regexp = "^.+$", message = "再次输入的密码不能为空")
private String reNewPassword;
@NotBlank(message = "身份证不能为空")
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\\d{3}(\\d|X|x)$",
message = "身份证格式不正确")
private String identity;
}

@ -0,0 +1,20 @@
package jty.expressdistributionsystem;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@MapperScan("jty.expressdistributionsystem.mapper")
@EnableTransactionManagement
@Slf4j
public class ExpressDistributionSystemApplication {
public static void main(String[] args) {
SpringApplication.run(ExpressDistributionSystemApplication.class, args);
log.info("猫咪物流启动成功");
}
}

@ -0,0 +1,19 @@
package jty.expressdistributionsystem.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CrossOriginConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
//允许所有的请求方法访问该跨域资源服务器
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With");
}
}

@ -0,0 +1,22 @@
package jty.expressdistributionsystem.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
this.strictInsertFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
}

@ -0,0 +1,21 @@
package jty.expressdistributionsystem.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
// 分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
return interceptor;
}
}

@ -0,0 +1,18 @@
package jty.expressdistributionsystem.config;
import jakarta.annotation.Resource;
import jty.expressdistributionsystem.interceptors.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).excludePathPatterns("/common/register", "/common/loginByAccount");
}
}

@ -0,0 +1,131 @@
package jty.expressdistributionsystem.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jty.expressdistributionsystem.DTO.ExpressListDTO;
import jty.expressdistributionsystem.DTO.SendMessageDTO;
import jty.expressdistributionsystem.entity.*;
import jty.expressdistributionsystem.service.*;
import jty.expressdistributionsystem.utils.GetIdUtil;
import jty.expressdistributionsystem.utils.SendMessageUtil;
import jty.expressdistributionsystem.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/admin")
@Slf4j
public class AdminController {
@Resource
private UserService userService;
@Resource
private MessageService messageService;
@Resource
private RecordsService recordsService;
@Resource
private GoodsService goodsService;
@Resource
private AddressService addressService;
// 管理员查看用户或者快递员信息(finish)
@GetMapping("/infoList")
public Result<Page<User>> getUserList(@RequestParam int page, @RequestParam int pageSize, @RequestParam int mark) {
if (page <= 0 || pageSize <= 0) {
return new Result<>(400, "页码和每页大小必须大于0", null);
}
// 分页
Page<User> pageInfo = new Page<>(page, pageSize);
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// 添加查询条件
queryWrapper.eq(User::getMark, mark);
// 排序
queryWrapper.orderByDesc(User::getLoginTime)
.orderByDesc(User::getCreateTime);
userService.page(pageInfo, queryWrapper);
return new Result<>(200, "", pageInfo);
}
// 拉黑删除快递员或者用户(finish)
@DeleteMapping("/delete/{id}")
public Result<String> delete(@PathVariable Long id, @RequestParam @NotNull String operation) {
User user = userService.getById(id);
if (user == null) {
return new Result<>(401, "账号不存在", "");
}
switch (operation) {
// 禁用
case "0" -> user.setDisabled(1);
// 解除禁用
case "1" -> user.setDisabled(0);
// 直接删除
case "2" -> {
userService.removeById(user.getId());
return new Result<>(200, "删除成功", "");
}
}
userService.updateById(user);
return new Result<>(200, "操作成功", "");
}
// 管理员发送消息(finish)
@PostMapping("/sendMessage")
public Result<String> sendMessage(@RequestBody @Validated SendMessageDTO sendMessageDTO) {
Message message = SendMessageUtil.sendMessage(sendMessageDTO, userService);
messageService.save(message);
return new Result<>(200, "发送成功", "");
}
// 获取正在留言的人的所有聊天记录(finish)
@GetMapping("/allMessage")
public Result<List<List<Message>>> getAllMessage(@RequestParam Long toId) {
Long meId = GetIdUtil.getId();
LambdaQueryWrapper<Message> messageLambdaQueryWrapper = new LambdaQueryWrapper<>();
List<List<Message>> list = new ArrayList<>();
// 先获取自己发给那个人的
messageLambdaQueryWrapper.eq(Message::getSendUserId, meId)
.eq(Message::getGetUserId, toId);
list.add(messageService.list(messageLambdaQueryWrapper));
// 再获取别人发给自己的
messageLambdaQueryWrapper.clear();
messageLambdaQueryWrapper.eq(Message::getGetUserId, meId)
.eq(Message::getSendUserId, toId);
list.add(messageService.list(messageLambdaQueryWrapper));
return new Result<>(200, "", list);
}
// 管理员获取所有快递信息(finish)
@GetMapping("/express")
public Result<Page<ExpressListDTO>> getAllExpress(@RequestParam int page, @RequestParam int pageSize) {
Page<Records> recordsPage = new Page<>(page, pageSize);
recordsService.page(recordsPage);
List<ExpressListDTO> expressListDTOList = new ArrayList<>();
// 获取所有的快递记录
List<Records> recordsList = recordsService.list();
for (Records records : recordsList) {
Goods goods = goodsService.getById(records.getGoodsId());
// 查询寄件人、收件人、签收者、快递员信息
User sender = userService.getById(records.getSendUserId());
User recipient = userService.getById(records.getGetUserId());
User addressee = userService.getById(records.getAddresseeId());
User courier = userService.getById(records.getExpressId());
// 查询地址信息: 从哪里送的 送到哪里
Address addressTo = addressService.getById(records.getAddressId());
Address addressFrom = addressService.getById(records.getAddressFrom());
ExpressListDTO expressListDTO = new ExpressListDTO(records, goods, sender, recipient, addressee, courier, addressFrom, addressTo);
expressListDTOList.add(expressListDTO);
}
Page<ExpressListDTO> expressDTOPage = new Page<>(recordsPage.getCurrent(), recordsPage.getSize(), recordsPage.getTotal());
expressDTOPage.setRecords(expressListDTOList);
return new Result<>(200, "", expressDTOPage);
}
}

@ -0,0 +1,160 @@
package jty.expressdistributionsystem.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import jakarta.annotation.Resource;
import jty.expressdistributionsystem.DTO.UserLoginByAccountDTO;
import jty.expressdistributionsystem.DTO.UserModifyInfoDTO;
import jty.expressdistributionsystem.DTO.UserModifyPasswordDTO;
import jty.expressdistributionsystem.entity.Result;
import jty.expressdistributionsystem.entity.User;
import jty.expressdistributionsystem.service.UserService;
import jty.expressdistributionsystem.utils.GetIdUtil;
import jty.expressdistributionsystem.utils.JwtUtil;
import jty.expressdistributionsystem.utils.Md5Util;
import jty.expressdistributionsystem.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {
@Resource
private UserService userService;
@Resource
private StringRedisTemplate stringRedisTemplate;
// 注册(finish)
@PostMapping("/register")
public Result<String> register(@RequestBody @Validated @NotNull User user) {
// 查找用户是否存在
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", user.getUserName())
.or()
.eq("account", user.getAccount())
.or()
.eq("phone", user.getPhone());
User u = userService.getOne(queryWrapper);
if (u != null) {
return new Result<>(409, "账号或用户名或手机号已存在", "");
}
// 密码加密
user.setPassword(Md5Util.getMD5String(user.getPassword()));
// 用户数据入库
userService.save(user);
return new Result<>(200, "注册成功", "");
}
// 通过账号登录(finish)
@PostMapping("/loginByAccount")
public Result<String> login(@RequestBody @Validated @NotNull UserLoginByAccountDTO userLoginByAccountDTO) {
// 删除ThreadLocal存储信息
ThreadLocalUtil.remove();
// 查询用户是否存在
Optional<User> optionalUser = Optional.ofNullable(userService.getOne(new QueryWrapper<User>()
.eq("account", userLoginByAccountDTO.getAccount())));
if (optionalUser.isEmpty() || !Md5Util.getMD5String(userLoginByAccountDTO.getPassword()).equals(optionalUser.get().getPassword())) {
return new Result<>(401, "账号或者密码错误", "");
}
User user = optionalUser.get();
if (!Objects.equals(userLoginByAccountDTO.getMark(), user.getMark())) {
return new Result<>(401, "请选择正确身份", "");
}
if (user.getDisabled() == 1) {
return new Result<>(403, "该账号已被禁用, 请联系管理员", "");
}
user.setLoginTime(LocalDateTime.now());
userService.update(user, new UpdateWrapper<User>().eq("id", user.getId()));
// 校验通过
Map<String, Object> claims = new HashMap<>();
claims.put("id", user.getId());
ThreadLocalUtil.set(user.getId());
claims.put("account", userLoginByAccountDTO.getAccount());
// 获取token
String token = JwtUtil.genToken(claims);
// 存放token到redis当中进行持久化存储
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
// 设置过期时间(1天)
stringStringValueOperations.set(token, token, 1, TimeUnit.DAYS);
// 返回token给前端
return new Result<>(200, "登录成功", token);
}
// 修改个人信息
@PutMapping("/modify")
public Result<Object> modifyInfo(@RequestBody @Validated @NotNull UserModifyInfoDTO userModifyInfoDTO) {
// 获取登录用户id
Long id = GetIdUtil.getId();
User user = userService.getById(id);
// 检查phone和userName是否与当前用户信息一致
boolean isPhoneSame = user.getPhone().equals(userModifyInfoDTO.getPhone());
boolean isUserNameSame = user.getUserName().equals(userModifyInfoDTO.getUserName());
if (isPhoneSame && isUserNameSame) {
return new Result<>(400, "请修改您的信息", "");
}
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (!isPhoneSame) {
queryWrapper.eq("phone", userModifyInfoDTO.getPhone());
if (userService.getOne(queryWrapper) != null) {
return new Result<>(400, "该手机号已被注册", "");
}
user.setPhone(userModifyInfoDTO.getPhone());
}
queryWrapper.clear();
if (!isUserNameSame) {
queryWrapper.eq("user_name", userModifyInfoDTO.getUserName());
if (userService.getOne(queryWrapper) != null) {
return new Result<>(400, "该用户名已被使用", "");
}
user.setUserName(userModifyInfoDTO.getUserName());
}
user.setUpdateTime(null);
userService.updateById(user);
return new Result<>(200, "用户信息修改成功", user);
}
// 修改个人密码
@PutMapping("/rePassword")
public Result<String> modifyPassword(
@RequestBody @Validated @NotNull UserModifyPasswordDTO userModifyPasswordDTO) {
// 判断密码
if (userModifyPasswordDTO.getOldPassword().equals(userModifyPasswordDTO.getNewPassword())) {
return new Result<>(409, "新密码不得和旧密码一致", "");
}
if (!userModifyPasswordDTO.getNewPassword().equals(userModifyPasswordDTO.getReNewPassword())) {
return new Result<>(409, "两次输入密码不相同", "");
}
Long id = GetIdUtil.getId();
User user = userService.getById(id);
if (!user.getIdentity().equals(userModifyPasswordDTO.getIdentity())) {
return new Result<>(409, "身份证有误", "");
}
user.setPassword(Md5Util.getMD5String(userModifyPasswordDTO.getNewPassword()));
user.setUpdateTime(null);
userService.updateById(user);
// 删除当前线程的存储信息
ThreadLocalUtil.remove();
return new Result<>(200, "密码修改成功, 请重新登陆", "");
}
// 获取个人信息(finish)
@GetMapping("/info")
public Result<User> getInfo() {
Long id = GetIdUtil.getId();
User user = userService.getById(id);
return new Result<>(200, "", user);
}
}

@ -0,0 +1,110 @@
package jty.expressdistributionsystem.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jty.expressdistributionsystem.DTO.EmExpressDTO;
import jty.expressdistributionsystem.DTO.GoodsEmDTO;
import jty.expressdistributionsystem.entity.*;
import jty.expressdistributionsystem.service.AddressService;
import jty.expressdistributionsystem.service.GoodsService;
import jty.expressdistributionsystem.service.RecordsService;
import jty.expressdistributionsystem.service.UserService;
import jty.expressdistributionsystem.utils.GetIdUtil;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Resource
private RecordsService recordsService;
@Resource
private GoodsService goodsService;
@Resource
private UserService userService;
@Resource
private AddressService addressService;
// 查询所有自己派送的快递(finish)
@GetMapping("/express")
public Result<Page<EmExpressDTO>> getAllExpress(@RequestParam int page, @RequestParam int pageSize) {
if (page <= 0 || pageSize <= 0) {
return new Result<>(400, "页码和每页大小必须大于0", null);
}
Long expressId = GetIdUtil.getId(); // 获取当前用户的 ID假设此方法返回当前用户的 expressId
// 根据 expressId 查询 Records 表中的快递记录
LambdaQueryWrapper<Records> recordsQueryWrapper = new LambdaQueryWrapper<>();
recordsQueryWrapper.eq(Records::getExpressId, expressId)
.orderByDesc(Records::getCreateTime); // 按时间降序排序
Page<Records> recordsPage = recordsService.page(new Page<>(page, pageSize), recordsQueryWrapper);
List<EmExpressDTO> emExpressDTOList = new ArrayList<>();
for (Records record : recordsPage.getRecords()) {
EmExpressDTO emExpressDTO = new EmExpressDTO();
// 查询相关用户(发送者、接收者)
User sendUser = userService.getById(record.getSendUserId());
User getUser = userService.getById(record.getGetUserId());
User addressee = userService.getById(record.getAddresseeId());
// 查询地址信息
Address addressFrom = addressService.getById(record.getAddressFrom());
Address addressTo = addressService.getById(record.getAddressId());
// 查询商品信息
Goods goods = goodsService.getById(record.getGoodsId());
emExpressDTO.setSendUser(sendUser);
emExpressDTO.setGetUser(getUser);
emExpressDTO.setAddressee(addressee);
emExpressDTO.setAddressFrom(addressFrom);
emExpressDTO.setAddressTo(addressTo);
emExpressDTO.setGoods(goods);
emExpressDTO.setRecords(record);
emExpressDTOList.add(emExpressDTO);
}
Page<EmExpressDTO> resultPage = new Page<>(page, pageSize);
resultPage.setRecords(emExpressDTOList);
resultPage.setTotal(recordsPage.getTotal());
return new Result<>(200, "查询成功", resultPage);
}
// 查询单件快递信息
@PostMapping("/expressInfo")
public Result<GoodsEmDTO> getExpressInfo(@RequestParam String expressCode) {
if (expressCode.isEmpty()) {
return new Result<>(404, "快递不存在", null);
}
LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
goodsLambdaQueryWrapper.eq(Goods::getExpressCode, expressCode);
Goods goods = goodsService.getOne(goodsLambdaQueryWrapper);
if (goods == null) {
return new Result<>(404, "快递不存在", null);
}
LambdaQueryWrapper<Records> recordsLambdaQueryWrapper = new LambdaQueryWrapper<>();
recordsLambdaQueryWrapper.eq(Records::getGoodsId, goods.getId());
Records records = recordsService.getOne(recordsLambdaQueryWrapper);
User sendUser = userService.getById(goods.getSendUserId());
User getUser = userService.getById(goods.getGetUserId());
User employee = userService.getById(records.getExpressId());
Address addressFrom = addressService.getById(records.getAddressFrom());
Address addressTo = addressService.getById(records.getAddressId());
User addressee = userService.getById(records.getAddresseeId());
// 填充DTO
GoodsEmDTO goodsEmDTO = new GoodsEmDTO();
goodsEmDTO.setName(goods.getName());
goodsEmDTO.setSendUser(sendUser.getUserName());
goodsEmDTO.setGetUser(getUser.getUserName());
goodsEmDTO.setQuality(goods.getQuality());
goodsEmDTO.setAddressFrom(addressFrom.getAddress());
goodsEmDTO.setAddressTo(addressTo.getAddress());
goodsEmDTO.setMark(records.getMark());
goodsEmDTO.setEmployee(employee.getUserName());
if (addressee != null) {
goodsEmDTO.setAddressee(addressee.getUserName());
}
return new Result<>(200, "查询成功", goodsEmDTO);
}
}

@ -0,0 +1,336 @@
package jty.expressdistributionsystem.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jty.expressdistributionsystem.DTO.*;
import jty.expressdistributionsystem.entity.*;
import jty.expressdistributionsystem.service.*;
import jty.expressdistributionsystem.utils.ClaimCodeUtil;
import jty.expressdistributionsystem.utils.ExpressCodeUtil;
import jty.expressdistributionsystem.utils.GetIdUtil;
import jty.expressdistributionsystem.utils.SendMessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@Resource
private MessageService messageService;
@Resource
private RecordsService recordsService;
@Resource
private CodeService codeService;
@Resource
private GoodsService goodsService;
@Resource
private AddressService addressService;
// 用户发消息(finish)
@PostMapping("/sendMessage")
public Result<String> sendMessage(@Validated @RequestBody SendMessageDTO sendMessageDTO) {
Message message = SendMessageUtil.sendMessage(sendMessageDTO, userService);
messageService.save(message);
return new Result<>(200, "发送成功", "");
}
// 给快递员点赞(finish)
@PostMapping("/likes")
public Result<String> like(@RequestParam Long id) {
User employee = userService.getById(id);
employee.setLikes(employee.getLikes() + 1);
userService.updateById(employee);
return new Result<>(200, "点赞成功", "");
}
// 用户查看发给别人消息(finish)
@GetMapping("/sendToMessage")
public Result<List<Message>> sendToMessage(@RequestParam String toUserName) {
LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
userLambdaQueryWrapper.eq(User::getUserName, toUserName);
User toUser = userService.getOne(userLambdaQueryWrapper);
Long userId = GetIdUtil.getId();
LambdaQueryWrapper<Message> messageLambdaQueryWrapper = new LambdaQueryWrapper<>();
messageLambdaQueryWrapper.eq(Message::getSendUserId, userId)
.eq(Message::getGetUserId, toUser.getId());
List<Message> list = messageService.list(messageLambdaQueryWrapper);
return new Result<>(200, "", list);
}
// 用户查看别人发给自己的消息(finish)
@GetMapping("/getFromMessage")
public Result<List<Message>> getFromMessage(@RequestParam Long id) {
LambdaQueryWrapper<Message> messageLambdaQueryWrapper = new LambdaQueryWrapper<>();
messageLambdaQueryWrapper.eq(Message::getGetUserId, id);
messageLambdaQueryWrapper.orderByDesc(Message::getMark)
.orderByDesc(Message::getCreateTime);
List<Message> list = messageService.list(messageLambdaQueryWrapper);
return new Result<>(200, "", list);
}
// 用户确认查看消息(finish)
@PostMapping("/confirmMessage")
public Result<String> confirmMessage(@RequestParam Long id) {
Message message = messageService.getById(id);
message.setMark(0);
messageService.updateById(message);
return new Result<>(200, "消息查看成功", "");
}
// 用户删除聊天消息(finish)
@DeleteMapping("/deleteMsg")
public Result<String> deleteMessage(@RequestParam Long id) {
messageService.removeById(id);
return new Result<>(200, "消息删除成功", "");
}
// 用户新建快递地址(finish)
@PostMapping("/addAddress")
public Result<String> addAddress(@RequestBody @Validated Address address) {
// 查询快递地址是否已经存在
LambdaQueryWrapper<Address> addressLambdaQueryWrapper = new LambdaQueryWrapper<>();
addressLambdaQueryWrapper.eq(Address::getAddress, address.getAddress());
Address getAddress = addressService.getOne(addressLambdaQueryWrapper);
if (getAddress != null) {
return new Result<>(409, "该地址已存在", "");
}
addressService.save(address);
return new Result<>(200, "地址创建成功", "");
}
// 用户获取自己写过的地址(finish)
@GetMapping("/getAddress")
public Result<List<Address>> listAddress(@RequestParam Long id) {
LambdaQueryWrapper<Address> addressLambdaQueryWrapper = new LambdaQueryWrapper<>();
addressLambdaQueryWrapper.eq(Address::getUserId, id)
.orderByDesc(Address::getAddress);
List<Address> list = addressService.list(addressLambdaQueryWrapper);
return new Result<>(200, "", list);
}
// 用户获取自己所有的快递记录(finish)
@GetMapping("/history")
public Result<Page<RecordsListDTO>> getHistory(@RequestParam int page, @RequestParam int pageSize) {
if (page <= 0 || pageSize <= 0) {
return new Result<>(400, "页码和每页大小必须大于0", null);
}
Long userId = GetIdUtil.getId(); // 获取当前用户的ID
List<Records> recordsList = new ArrayList<>();
// 查询作为收件人的快递记录
LambdaQueryWrapper<Records> recordsLambdaQueryWrapper = new LambdaQueryWrapper<>();
recordsLambdaQueryWrapper.eq(Records::getGetUserId, userId);
// 添加排序条件
recordsLambdaQueryWrapper.orderByAsc(Records::getMark)
.orderByDesc(Records::getCreateTime);
List<Records> receivedRecords = recordsService.list(recordsLambdaQueryWrapper);
recordsLambdaQueryWrapper.clear();
recordsList.addAll(receivedRecords);
// 查询作为寄件人的快递记录
recordsLambdaQueryWrapper.eq(Records::getSendUserId, userId);
// 添加排序条件
recordsLambdaQueryWrapper.orderByAsc(Records::getMark)
.orderByDesc(Records::getCreateTime);
List<Records> sentRecords = recordsService.list(recordsLambdaQueryWrapper);
recordsList.addAll(sentRecords);
// 分页处理
int totalRecords = recordsList.size();
int fromIndex = Math.min(pageSize * (page - 1), totalRecords);
int toIndex = Math.min(fromIndex + pageSize, totalRecords);
List<Records> pagedRecords = recordsList.subList(fromIndex, toIndex);
// 封装成GoodsListDTO
List<RecordsListDTO> recordsListDTOList = new ArrayList<>();
for (Records records : pagedRecords) {
Goods goods = goodsService.getById(records.getGoodsId());
User sender = userService.getById(records.getSendUserId());
User recipient = userService.getById(records.getGetUserId());
User addressee = userService.getById(records.getAddresseeId());
User courier = userService.getById(records.getExpressId());
Address addressFrom = addressService.getById(records.getAddressFrom());
Address addressTo = addressService.getById(records.getAddressId());
LambdaQueryWrapper<Code> codeLambdaQueryWrapper = new LambdaQueryWrapper<>();
codeLambdaQueryWrapper.eq(Code::getGoodsId, goods.getId());
Code code = codeService.getOne(codeLambdaQueryWrapper);
RecordsListDTO recordsListDTO = new RecordsListDTO();
recordsListDTO.setGoods(goods);
recordsListDTO.setAddressFrom(addressFrom);
recordsListDTO.setAddressTo(addressTo);
recordsListDTO.setEmployee(courier);
recordsListDTO.setAddressee(addressee);
recordsListDTO.setSendUser(sender);
recordsListDTO.setGetUserId(recipient);
recordsListDTO.setCode(code);
recordsListDTO.setRecord(records);
recordsListDTOList.add(recordsListDTO);
}
Page<RecordsListDTO> goodsDTOPage = new Page<>(page, pageSize, totalRecords);
goodsDTOPage.setRecords(recordsListDTOList);
return new Result<>(200, "", goodsDTOPage);
}
// 用户寄件(完成)
@PostMapping("/shipment")
public Result<String> shipmentExpress(@RequestBody @Validated @NotNull GoodsDTO goodsDTO) {
// 判断用户是否存在
LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
userLambdaQueryWrapper.eq(User::getUserName, goodsDTO.getGetUserName());
User getUser = userService.getOne(userLambdaQueryWrapper);
if (getUser == null) {
return new Result<>(404, "用户不存在", null);
}
userLambdaQueryWrapper.clear();
// 判断地址是否存在
LambdaQueryWrapper<Address> addressLambdaQueryWrapper = new LambdaQueryWrapper<>();
addressLambdaQueryWrapper.eq(Address::getAddress, goodsDTO.getAddressTo());
Address address = addressService.getOne(addressLambdaQueryWrapper);
if (address == null) {
return new Result<>(404, "地址不存在", null);
}
addressLambdaQueryWrapper.clear();
// 如果寄件和收件是一个地方,禁止
if (goodsDTO.getAddressFrom().equals(goodsDTO.getAddressTo())) {
return new Result<>(400, "寄件和收件不能是同一个地方", null);
}
// 生成快递码
String expressCode = ExpressCodeUtil.getExpressCode(goodsDTO.getCompany());
// 生成取件码
String claimCode = ClaimCodeUtil.getClaimCode(goodsDTO.getCompany());
Goods goods = new Goods();
goods.setSendUserId(GetIdUtil.getId());
goods.setGetUserId(getUser.getId());
goods.setExpressCode(expressCode);
goods.setName(goodsDTO.getName());
goods.setQuality(goodsDTO.getQuality());
goodsService.save(goods);
// 存进历史记录
// 寄件方位置
addressLambdaQueryWrapper.eq(Address::getAddress, goodsDTO.getAddressFrom());
Address addressFrom = addressService.getOne(addressLambdaQueryWrapper);
Records records = new Records();
records.setAddressFrom(addressFrom.getId());
records.setSendUserId(GetIdUtil.getId());
records.setGetUserId(getUser.getId());
records.setAddressId(address.getId());
records.setGoodsId(goods.getId());
// 系统自动分配快递员
userLambdaQueryWrapper.eq(User::getMark, 1);
List<User> list = userService.list(userLambdaQueryWrapper);
Collections.shuffle(list);
User user = list.get(0);
records.setExpressId(user.getId());
recordsService.save(records);
Code code = new Code();
code.setClaim(claimCode);
code.setGoodsId(goods.getId());
codeService.save(code);
return new Result<>(200, "寄件成功", "");
}
// 用户收件(finish)
@PostMapping("/addressee")
public Result<String> addressee(@Validated @RequestBody AddresseeDTO addresseeDTO) {
// 判断是不是自己的快递
Long goodsId = addresseeDTO.getGoodsId();
Goods goods = goodsService.getById(goodsId);
if (goods.getGetUserId().compareTo(GetIdUtil.getId()) != 0) {
return new Result<>(401, "签收他人快递请选择代取功能", "");
}
QueryWrapper<Code> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("goods_id", goodsId);
Code code = codeService.getOne(queryWrapper);
// 判断取件码是否输入正确
if (!code.getClaim().equals(addresseeDTO.getClaimCode())) {
return new Result<>(401, "请输入正确的取件码", "");
}
QueryWrapper<Records> recordsQueryWrapper = new QueryWrapper<>();
recordsQueryWrapper.eq("goods_id", goodsId);
Records records = recordsService.getOne(recordsQueryWrapper);
records.setMark(1);
// 设置取件人
records.setAddresseeId(GetIdUtil.getId());
recordsService.updateById(records);
return new Result<>(200, "取件成功", "");
}
// 用户代取快递(finish)
@PostMapping("/pickUp")
public Result<String> pickUpExpress(@RequestBody @Validated PickUpExpressDTO pickUpExpressDTO) {
// 查询快递原主人信息
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("user_name", pickUpExpressDTO.getMaster());
User master = userService.getOne(userQueryWrapper);
if (master == null) {
return new Result<>(404, "该用户不存在", "");
}
// 查询快递信息
QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
goodsQueryWrapper.eq("express_code", pickUpExpressDTO.getExpressCode());
Goods goods = goodsService.getOne(goodsQueryWrapper);
if (goods == null) {
return new Result<>(404, "快递不存在", "");
}
// 代取
QueryWrapper<Records> recordsQueryWrapper = new QueryWrapper<>();
recordsQueryWrapper.eq("goods_id", goods.getId());
Records records = recordsService.getOne(recordsQueryWrapper);
if (records.getMark() == 1) {
return new Result<>(404, "快递已被签收", "");
}
records.setMark(1);
records.setAddresseeId(GetIdUtil.getId());
recordsService.updateById(records);
return new Result<>(200, "代取成功", "");
}
// 用户查询快递(完成)
@GetMapping("/query")
public Result<Goods> queryGoods(@RequestParam String queryCode, @RequestParam Long queryId) {
if (queryCode.isEmpty()) {
return new Result<>(400, "查询失败", null);
}
Long id = GetIdUtil.getId();
LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
if (Objects.equals(id, queryId)) {
goodsLambdaQueryWrapper.eq(Goods::getExpressCode, queryCode);
Goods goods = goodsService.getOne(goodsLambdaQueryWrapper);
return new Result<>(200, "查询成功", goods);
} else {
goodsLambdaQueryWrapper.eq(Goods::getExpressCode, queryCode)
.eq(Goods::getGetUserId, queryId);
Goods goods = goodsService.getOne(goodsLambdaQueryWrapper);
if (goods == null) {
return new Result<>(404, "请输入正确的快递单号, 或您不是快递的收件人或者邮寄人", null);
} else {
return new Result<>(200, "查询成功", goods);
}
}
}
// 用户查询用户信息(完成)
@GetMapping("/queryInfo")
public Result<String> queryInfo(@RequestParam Long otherId) {
User user = userService.getById(otherId);
return new Result<>(200, "", user.getUserName());
}
// 用户获取单个快递历史记录(完成)
@GetMapping("/singleHistory")
public Result<Records> singleHistory(@RequestParam String goodsId) {
LambdaQueryWrapper<Records> recordsLambdaQueryWrapper = new LambdaQueryWrapper<>();
recordsLambdaQueryWrapper.eq(Records::getGoodsId, goodsId);
Records records = recordsService.getOne(recordsLambdaQueryWrapper);
return new Result<>(200, "", records);
}
}

@ -0,0 +1,33 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@TableName("address")
public class Address implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("user_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long userId;
@TableField("address")
@NotBlank(message = "地址不能为空")
private String address;
}

@ -0,0 +1,33 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@TableName("code")
public class Code implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("goods_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long goodsId;
@TableField("claim")
@NotBlank(message = "取件码不能为空")
private String claim;
}

@ -0,0 +1,48 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jty.expressdistributionsystem.validation.inter.ValidQuality;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@TableName("goods")
@Data
public class Goods implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("send_user_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long sendUserId;
@TableField("get_user_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long getUserId;
@TableField("express_code")
@NotBlank(message = "快递码未生成, 请重新填写信息")
private String expressCode;
@TableField("name")
@NotBlank(message = "快递名称不能为空")
private String name;
@TableField("quality")
@NotBlank(message = "快递重量不能为空")
@ValidQuality
private Double quality;
}

@ -0,0 +1,50 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName("message")
public class Message implements Serializable {
public Message() {
}
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("content")
private String content;
@TableField("send_user_id")
@NotNull
@JsonSerialize(using = ToStringSerializer.class)
private Long sendUserId;
@TableField("get_user_id")
@NotNull
@JsonSerialize(using = ToStringSerializer.class)
private Long getUserId;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField("mark")
private Integer mark;
}

@ -0,0 +1,65 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName("records")
public class Records implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("send_user_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long sendUserId;
@TableField("get_user_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long getUserId;
@TableField("express_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long expressId;
@TableField("goods_id")
@JsonSerialize(using = ToStringSerializer.class)
@NotNull
private Long goodsId;
@TableField("mark")
private Integer mark;
// 从哪里送的
@TableField("address_from")
@JsonSerialize(using = ToStringSerializer.class)
private Long addressFrom;
// 送到哪里
@TableField("address_id")
@JsonSerialize(using = ToStringSerializer.class)
private Long addressId;
@TableField("addressee_id")
@JsonSerialize(using = ToStringSerializer.class)
private Long addresseeId;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

@ -0,0 +1,18 @@
package jty.expressdistributionsystem.entity;
import lombok.Data;
@Data
public class Result<T> {
private int code;
private String message;
private T data;
public Result(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
}

@ -0,0 +1,69 @@
package jty.expressdistributionsystem.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName("user")
public class User implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableId("id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@TableField("user_name")
@NotBlank(message = "用户名不能为空")
private String userName;
@TableField("account")
@NotBlank(message = "账号不能为空")
@Pattern(regexp = "^(?!\\s)([A-Za-z0-9]{1,10})$", message = "账号长度在1-10位之间")
private String account;
@TableField("phone")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号有误")
private String phone;
@TableField("password")
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^.+$", message = "密码不能为空")
private String password;
@TableField("identity")
@NotBlank(message = "身份证不能为空")
@Pattern(regexp = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\\d{3}(\\d|X|x)$",
message = "身份证有误")
private String identity;
@TableField("mark")
private Integer mark;
@TableField("likes")
private Integer likes;
@TableField("disabled")
private Integer disabled;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(value = "login_time")
private LocalDateTime loginTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

@ -0,0 +1,22 @@
package jty.expressdistributionsystem.interceptors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
}

@ -0,0 +1,52 @@
package jty.expressdistributionsystem.interceptors;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jty.expressdistributionsystem.utils.JwtUtil;
import jty.expressdistributionsystem.utils.ThreadLocalUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Map;
//注入到IOC容器
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
// 令牌验证
String token = request.getHeader("Authorization");
try {
// 从redis获取相同的token
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
String redisToken = stringStringValueOperations.get(token);
if (redisToken == null) {
// 说明token失效
throw new RuntimeException();
}
Map<String, Object> claims = JwtUtil.parseToken(token);
// 把数据存储到ThreadLocal当中
ThreadLocalUtil.set(claims);
// 放行
return true;
} catch (Exception e) {
// http响应状态码为401
response.setStatus(401);
// 不放行
return false;
}
}
@Override
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) {
// 清空ThreadLocal当中的数据防止内存泄露
ThreadLocalUtil.remove();
}
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.Address;
public interface AddressMapper extends BaseMapper<Address> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.Code;
public interface CodeMapper extends BaseMapper<Code> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.Goods;
public interface GoodsMapper extends BaseMapper<Goods> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.Message;
public interface MessageMapper extends BaseMapper<Message> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.Records;
public interface RecordsMapper extends BaseMapper<Records> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import jty.expressdistributionsystem.entity.User;
public interface UserMapper extends BaseMapper<User> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.Address;
public interface AddressService extends IService<Address> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.Code;
public interface CodeService extends IService<Code> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.Goods;
public interface GoodsService extends IService<Goods> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.Message;
public interface MessageService extends IService<Message> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.Records;
public interface RecordsService extends IService<Records> {
}

@ -0,0 +1,7 @@
package jty.expressdistributionsystem.service;
import com.baomidou.mybatisplus.extension.service.IService;
import jty.expressdistributionsystem.entity.User;
public interface UserService extends IService<User> {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.Address;
import jty.expressdistributionsystem.mapper.AddressMapper;
import jty.expressdistributionsystem.service.AddressService;
import org.springframework.stereotype.Service;
@Service
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements AddressService {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.Code;
import jty.expressdistributionsystem.mapper.CodeMapper;
import jty.expressdistributionsystem.service.CodeService;
import org.springframework.stereotype.Service;
@Service
public class CodeServiceImpl extends ServiceImpl<CodeMapper, Code> implements CodeService {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.Goods;
import jty.expressdistributionsystem.mapper.GoodsMapper;
import jty.expressdistributionsystem.service.GoodsService;
import org.springframework.stereotype.Service;
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.Message;
import jty.expressdistributionsystem.mapper.MessageMapper;
import jty.expressdistributionsystem.service.MessageService;
import org.springframework.stereotype.Service;
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.Records;
import jty.expressdistributionsystem.mapper.RecordsMapper;
import jty.expressdistributionsystem.service.RecordsService;
import org.springframework.stereotype.Service;
@Service
public class RecordsServiceImpl extends ServiceImpl<RecordsMapper, Records> implements RecordsService {
}

@ -0,0 +1,11 @@
package jty.expressdistributionsystem.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jty.expressdistributionsystem.entity.User;
import jty.expressdistributionsystem.mapper.UserMapper;
import jty.expressdistributionsystem.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

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

Loading…
Cancel
Save