diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b559d64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ + + +.idea/ +.trae/ +target + +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* diff --git a/amms_front/.gitignore b/amms_front/.gitignore new file mode 100644 index 0000000..8ee54e8 --- /dev/null +++ b/amms_front/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/amms_front/src/App.vue b/amms_front/src/App.vue new file mode 100644 index 0000000..7e961a2 --- /dev/null +++ b/amms_front/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/amms_front/src/api/announcement.js b/amms_front/src/api/announcement.js new file mode 100644 index 0000000..16b1f64 --- /dev/null +++ b/amms_front/src/api/announcement.js @@ -0,0 +1,51 @@ +import axios from '@/utils/request' + +// 查询公告列表 +export function listAnnouncement(query) { + return axios.get('/announcement/list',{ + params: { + ...query + } + }) +} + +// 查询全部公告列表 +export function listAllAnnouncement(query) { + return axios.get('/announcement/listAll', { + params: { + ...query + } + }) +} + +// 查询公告详细 +export function getAnnouncement(id) { + return axios.get('/announcement/info/' + id) +} + +// 新增公告 +export function addAnnouncement(data) { + return axios.post('/announcement/add', { + ...data + }) +} + +// 修改公告 +export function updateAnnouncement(data) { + return axios.put('/announcement', data) +} + +// 设为置顶(保证仅一个置顶) +export function setTopAnnouncement(id) { + return axios.put('/announcement/setTop/' + id) +} + +// 删除公告 +export function delAnnouncement(id) { + return axios.delete('/announcement/' + id) +} + +// 游客端公告列表(置顶 + 普通分页) +export function listTouristAnnouncements(params) { + return axios.get('/announcement/touristList', { params }) +} diff --git a/amms_front/src/assets/base.css b/amms_front/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/amms_front/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/amms_front/src/assets/css/apple-input.css b/amms_front/src/assets/css/apple-input.css new file mode 100644 index 0000000..9f649ca --- /dev/null +++ b/amms_front/src/assets/css/apple-input.css @@ -0,0 +1,89 @@ +/* + Apple风格Element Plus输入框公共样式 + 使用方法:在需要应用样式的el-input上添加 class="apple-input" + 示例: +*/ + +/* 基础样式 - 通过自定义类名限定范围 */ +.el-input.apple-input .el-input__wrapper { + background-color: rgba(255, 255, 255, 0.28) !important; + border: 1px solid rgba(255, 255, 255, 0.2) !important; + border-radius: 0.5rem !important; + padding: 0 1rem !important; + height: 2.75rem !important; + transition: all 0.3s ease !important; +} + +/* 悬停状态 */ +.el-input.apple-input .el-input__wrapper:hover { + border-color: rgba(255, 255, 255, 0.3) !important; + box-shadow: none !important; +} + +/* 聚焦状态 */ +.el-input.apple-input .el-input__wrapper:focus-within { + border-color: #0071e3 !important; /* Apple标志性蓝色 */ + box-shadow: 0 0 0 1px #0071e3 !important; +} + +/* 输入文本样式 */ +.el-input.apple-input .el-input__input { + color: white !important; + padding: 0 !important; + height: 100% !important; +} + +/* 占位符样式 */ +.el-input.apple-input .el-input__input::placeholder { + color: white !important; +} + +/* 后缀图标(如密码可见性切换) */ +.el-input.apple-input .el-input__suffix-inner { + color: rgba(255, 255, 255, 0.6) !important; +} + +.el-input.apple-input .el-input__suffix-inner:hover { + color: white !important; +} + +/* 清除按钮 */ +.el-input.apple-input .el-input__clear { + color: rgba(255, 255, 255, 0.6) !important; +} + +.el-input.apple-input .el-input__clear:hover { + color: white !important; + background-color: rgba(255, 255, 255, 0.1) !important; +} + +/* 前缀图标 */ +.el-input.apple-input .el-input__prefix { + color: rgba(255, 255, 255, 0.6) !important; +} + +/* 可选变体:更大的输入框 */ +.el-input.apple-input.large .el-input__wrapper { + height: 3.25rem !important; + font-size: 1rem !important; +} + +/* 可选变体:更小的输入框 */ +.el-input.apple-input.small .el-input__wrapper { + height: 2.25rem !important; + font-size: 0.875rem !important; +} + +/* 可选变体:浅色模式适配 */ +.el-input.apple-input.light .el-input__wrapper { + background-color: rgba(0, 0, 0, 0.05) !important; + border: 1px solid rgba(0, 0, 0, 0.1) !important; +} + +.el-input.apple-input.light .el-input__input { + color: #1d1d1f !important; +} + +.el-input.apple-input.light .el-input__input::placeholder { + color: rgba(0, 0, 0, 0.4) !important; +} diff --git a/sql/amms.sql b/sql/amms.sql new file mode 100644 index 0000000..3d4e3f0 --- /dev/null +++ b/sql/amms.sql @@ -0,0 +1,215 @@ +-- 用户主表(共用属性) +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户id', + `username` varchar(30) NOT NULL COMMENT '账号', + `password` varchar(100) DEFAULT '' COMMENT '密码', + `nickname` varchar(30) NOT NULL COMMENT '昵称', + `avatar` varchar(100) DEFAULT '' COMMENT '头像地址', + `status` int DEFAULT 0 COMMENT '状态(0正常 1停用 2待审核)', + `role` varchar(10) NOT NULL COMMENT '角色(1超级管理员 2普通用户)', + `creator` bigint DEFAULT NULL COMMENT '创建者id', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `updater` bigint DEFAULT NULL COMMENT '更新者id', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `deleted` tinyint DEFAULT 0 COMMENT '删除标识(0未删 1已删)', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_sys_user_username` (`username`) +) COMMENT='用户主表'; +-- 超级管理员 admin 密码:123456 +INSERT INTO `sys_user` (`username`, `password`, `nickname`, `avatar`, `status`, `role`, `creator`, `create_time`, `updater`, `update_time`, `remark`, `deleted`) +VALUES ('admin', '$2a$10$sSTvaDj1QtrEIgEglkumguRT88m0WRs61gWw7Rgm/gpP6/eZ4ffwG', '超级管理员', '', 0, '1', NULL, NOW(), NULL, NOW(), '系统默认超级管理员', 0); + +-- 普通用户(游客) +DROP TABLE IF EXISTS `tourist`; +CREATE TABLE `tourist` ( + `id` bigint NOT NULL COMMENT '用户id(与sys_user.id一致)', + `real_name` varchar(30) DEFAULT NULL COMMENT '真实姓名', + `id_card` varchar(18) DEFAULT NULL COMMENT '身份证号', + `phone` varchar(11) DEFAULT NULL COMMENT '手机号', + `email` varchar(50) DEFAULT NULL COMMENT '邮箱', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_sys_user_normal_phone` (`phone`), + UNIQUE KEY `idx_sys_user_normal_email` (`email`) +) COMMENT='普通用户子表' + +-- 轮播图表 +DROP TABLE IF EXISTS `carousel`; +CREATE TABLE `carousel` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '轮播图id', + `title` varchar(50) NOT NULL COMMENT '标题', + `image_url` varchar(255) NOT NULL COMMENT '图片地址', + `link` varchar(255) DEFAULT NULL COMMENT '跳转链接', + `sort` int DEFAULT 0 COMMENT '排序序号', + `status` tinyint DEFAULT 1 COMMENT '状态(0隐藏 1显示)', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_carousel_status` (`status`) +) COMMENT='轮播图'; + +-- 博物馆简介表 +DROP TABLE IF EXISTS `museum_intro`; +CREATE TABLE `museum_intro` ( + `museum_name` varchar(100) NOT NULL COMMENT '博物馆名称(主键)', + `content` text NOT NULL COMMENT '内容', + `logo_url` varchar(255) DEFAULT NULL COMMENT 'Logo地址', + `address` varchar(100) DEFAULT NULL COMMENT '地址', + `phone` varchar(20) DEFAULT NULL COMMENT '联系电话', + `open_time` time DEFAULT NULL COMMENT '营业开始时间', + `close_time` time DEFAULT NULL COMMENT '营业结束时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `updater` bigint DEFAULT NULL COMMENT '更新者id', + PRIMARY KEY (`museum_name`) +) COMMENT='博物馆简介'; +INSERT INTO `museum_intro` ( + `museum_name`, + `content`, + `logo_url`, + `address`, + `phone`, + `open_time`, + `close_time`, + `update_time`, + `updater` +) VALUES ( + '邺城博物馆', + '邺城博物馆位于河北省邺城遗址保护区,致力于系统展示东魏、北齐时期的城市文明与考古成果。馆内设基本陈列、专题展厅与数字互动空间,重点呈现佛教造像、石刻艺术、陶瓷器与城址考古发掘成果,并提供文物保护科普、研学课程与公众教育服务。', + '/api/files/get?fileName=museum/logo/yecity.png', + '河北省临漳县邺城遗址博物馆', + '0310-8888888', + '09:00:00', + '17:30:00', + NOW(), + 1 +); + +-- 藏品分类表 +DROP TABLE IF EXISTS `item_category`; +CREATE TABLE `item_category` ( + `id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '分类ID', + `name` varchar(50) NOT NULL COMMENT '分类名称', + `creator` bigint NULL COMMENT '创建者', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` bigint NULL COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) NULL COMMENT '备注' +) COMMENT = '藏品分类'; + + +-- 藏品主表 +DROP TABLE IF EXISTS `relic`; +CREATE TABLE `relic` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '藏品id', + `name` varchar(100) NOT NULL COMMENT '名称', + `category_id` bigint NOT NULL COMMENT '分类ID', + `cover_image_url` varchar(255) NOT NULL COMMENT '封面图地址', + `age` varchar(50) DEFAULT NULL COMMENT '年代', + `material` varchar(50) DEFAULT NULL COMMENT '材质', + `excavation_info` text DEFAULT NULL COMMENT '出土信息', + `story` text DEFAULT NULL COMMENT '文物故事', + `model_url` text DEFAULT NULL COMMENT '3D/360°图地址', + `is_hot` tinyint DEFAULT 0 COMMENT '热门标识(0否 1是)', + `status` tinyint DEFAULT 1 COMMENT '状态(0隐藏 1显示)', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `creator` bigint DEFAULT NULL COMMENT '创建者id', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `updater` bigint DEFAULT NULL COMMENT '更新者id', + PRIMARY KEY (`id`) +) COMMENT = '藏品'; + +-- 测试数据:邺城博物馆热门/普通藏品(15条) +INSERT INTO `relic` (`name`, `category_id`, `cover_image_url`, `age`, `material`, `excavation_info`, `story`, `model_url`, `is_hot`, `status`, `create_time`, `creator`, `update_time`, `updater`) VALUES +('北齐石刻佛像', 1, '/api/files/get?fileName=relicCover/bei_qi_shike_foxiang.jpg', '北齐', '石质', '邺城遗址石窟区出土', '北齐时期石刻造像,线条劲挺,面相安详。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('东魏青釉瓷碗', 2, '/api/files/get?fileName=relicCover/dong_wei_qingyou_ciwang.jpg', '东魏', '陶瓷', '邺城城址文化层出土', '胎质细腻,通体青釉,器形规整。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('北齐石柱础', 1, '/api/files/get?fileName=relicCover/bei_qi_zhuchu.jpg', '北齐', '石质', '邺城宫殿区基址出土', '柱础覆莲纹,雕刻工整,体现工艺水准。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('东魏鎏金饰片', 3, '/api/files/get?fileName=relicCover/dong_wei_liujin_shipian.jpg', '东魏', '金属', '邺城遗址手工业作坊出土', '鎏金工艺精湛,纹饰细密。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('北齐陶俑', 2, '/api/files/get?fileName=relicCover/bei_qi_taoyong.jpg', '北齐', '陶', '邺城墓葬出土', '俑身比例匀称,服饰简洁,表情生动。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('邺城瓦当', 4, '/api/files/get?fileName=relicCover/yecity_wadang.jpg', '北齐', '陶', '邺城宫殿区瓦件堆积出土', '瓦当纹饰清晰,常见卷云与莲纹。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('邺城石刻残片', 1, '/api/files/get?fileName=relicCover/yecity_shike_canpian.jpg', '北齐', '石质', '邺城寺院区出土', '残片可见线刻与浅浮雕技法。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('北齐碑刻', 1, '/api/files/get?fileName=relicCover/bei_qi_beike.jpg', '北齐', '石质', '邺城遗址碑廓出土', '字迹峻拔,为研究书法与历史提供资料。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('邺城铜镜', 3, '/api/files/get?fileName=relicCover/yecity_tongjing.jpg', '北齐', '青铜', '邺城民居遗址出土', '背纹精美,折射古代生活审美。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('邺城陶灯', 2, '/api/files/get?fileName=relicCover/yecity_taodeng.jpg', '东魏', '陶', '邺城手工业区出土', '造型朴素,实用性强。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('邺城青铜器', 3, '/api/files/get?fileName=relicCover/yecity_qingtongqi.jpg', '北齐', '青铜', '邺城祭祀遗址出土', '铸造规整,纹饰典雅。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('石雕护法像', 1, '/api/files/get?fileName=relicCover/shidiao_hufa.jpg', '北齐', '石质', '邺城寺院区出土', '表情威严,衣纹流畅,守护佛法之象。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('鎏金佛像', 3, '/api/files/get?fileName=relicCover/liujin_foxiang.jpg', '北齐', '金属', '邺城佛教遗迹出土', '通体鎏金,庄严华美。', NULL, 1, 1, NOW(), 1, NOW(), 1), +('邺城瓷瓶', 2, '/api/files/get?fileName=relicCover/yecity_ciping.jpg', '东魏', '陶瓷', '邺城城址出土', '瓶身修长,青釉匀净。', NULL, 0, 1, NOW(), 1, NOW(), 1), +('石经残卷', 1, '/api/files/get?fileName=relicCover/shijing_canjuan.jpg', '北齐', '石质', '邺城经藏区出土', '石经残刻,见证佛教经典传播。', NULL, 0, 1, NOW(), 1, NOW(), 1); + +-- 公告表 +DROP TABLE IF EXISTS `announcement`; +CREATE TABLE `announcement` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '公告id', + `title` varchar(100) NOT NULL COMMENT '标题', + `content` text NOT NULL COMMENT '内容', + `is_top` tinyint DEFAULT 0 COMMENT '置顶标识(0否 1是)', + `status` tinyint DEFAULT 1 COMMENT '状态(0隐藏 1显示)', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间', + `creator` bigint DEFAULT NULL COMMENT '发布者id', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `updater` bigint DEFAULT NULL COMMENT '更新者id', + PRIMARY KEY (`id`) +) COMMENT='公告'; + +-- 预约时段表 +DROP TABLE IF EXISTS `reservation_time_slot`; +CREATE TABLE `reservation_time_slot` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '时段id', + `date` date NOT NULL COMMENT '预约日期', + `start_time` time NOT NULL COMMENT '开始时间', + `end_time` time NOT NULL COMMENT '结束时间', + `max_people` int NOT NULL COMMENT '最大人数', + `current_people` int DEFAULT 0 COMMENT '已预约人数', + `status` tinyint DEFAULT 1 COMMENT '状态(0不可约 1可约)', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `creator` bigint DEFAULT NULL COMMENT '创建者id', + PRIMARY KEY (`id`) +) COMMENT='预约时段'; + +-- 预约记录表 +DROP TABLE IF EXISTS `reservation`; +CREATE TABLE `reservation` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '预约id(主表ID)', + `user_id` bigint NOT NULL COMMENT '预约发起者id(关联sys_user.id)', + `time_slot_id` bigint NOT NULL COMMENT '预约时段id(关联reservation_time_slot.id)', + `total_visitors` int NOT NULL COMMENT '预约总人数(与明细表记录数一致)', + `reserve_time` time NOT NULL COMMENT '预约时间', + `qr_code` varchar(255) DEFAULT NULL COMMENT '预约凭证二维码(整单唯一)', + `status` tinyint DEFAULT 0 COMMENT '整单状态(0待审核 1已通过 2已取消 3已驳回)', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '预约提交时间', + `update_time` datetime DEFAULT NULL COMMENT '审核/更新时间', + `updater` bigint DEFAULT NULL COMMENT '审核者id(关联sys_user.id)', + `remark` varchar(500) DEFAULT NULL COMMENT '审核备注(如驳回原因)', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_time_slot_id` (`time_slot_id`), + KEY `idx_status` (`status`) +) COMMENT='预约'; + +-- 预约明细表 +DROP TABLE IF EXISTS `reservation_visitor`; +CREATE TABLE `reservation_visitor` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '明细ID', + `reservation_id` bigint NOT NULL COMMENT '预约id', + `real_name` varchar(30) NOT NULL COMMENT '游客真实姓名', + `id_card` varchar(18) NOT NULL COMMENT '游客身份证号(唯一标识游客)', + `phone` varchar(11) NOT NULL COMMENT '游客手机号', + `visitor_qr_code` varchar(500) DEFAULT NULL COMMENT '游客个人入场二维码(可选,如分人验证)', + `verify_status` tinyint DEFAULT 0 COMMENT '游客入场验证状态(0未验证 1已验证)', + `verify_time` datetime DEFAULT NULL COMMENT '入场验证时间', + PRIMARY KEY (`id`), + KEY `idx_reservation_id` (`reservation_id`), + KEY `idx_id_card` (`id_card`) +) COMMENT='游客预约明细'; + +-- 收藏表 +DROP TABLE IF EXISTS `item_collection`; +CREATE TABLE `item_collection` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '收藏id', + `user_id` bigint NOT NULL COMMENT '用户id', + `item_id` bigint NOT NULL COMMENT '藏品id', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '收藏时间', + PRIMARY KEY (`id`) +) COMMENT='收藏'; diff --git a/sql/app.sql b/sql/app.sql new file mode 100644 index 0000000..584c85c --- /dev/null +++ b/sql/app.sql @@ -0,0 +1,18 @@ +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + id bigint not null auto_increment primary key comment '用户ID', + username varchar(30) not null comment '用户账号', + nickname varchar(30) not null comment '用户昵称', + mobile varchar(11) null default '' comment '手机号码', + sex int null DEFAULT 0 comment '用户性别(0男 1女 2未知)', + avatar varchar(100) null default '' comment '头像地址', + password varchar(100) null default '' comment '密码', + status int null default 0 comment '帐号状态(0正常 1停用)', + role varchar(20) not null comment '角色 admin管理员', + creator bigint null default 1 comment '创建者', + create_time datetime null default null comment '创建时间', + updater bigint null default 1 comment '更新者', + update_time datetime null default null comment '更新时间', + remark varchar(500) null default null comment '备注', + deleted tinyint null default 0 comment '删除标识' +) comment = '用户'; diff --git a/src/main/java/com/amms/Application.java b/src/main/java/com/amms/Application.java new file mode 100644 index 0000000..d280227 --- /dev/null +++ b/src/main/java/com/amms/Application.java @@ -0,0 +1,13 @@ +package com.amms; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/src/main/java/com/amms/controller/AnnouncementController.java b/src/main/java/com/amms/controller/AnnouncementController.java new file mode 100644 index 0000000..66de09c --- /dev/null +++ b/src/main/java/com/amms/controller/AnnouncementController.java @@ -0,0 +1,106 @@ +package com.amms.controller; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import com.amms.domain.vo.Result; +import com.amms.domain.Announcement; +import com.amms.service.IAnnouncementService; + +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +/** + * 公告Controller + */ +@RestController +@RequestMapping("/announcement") +public class AnnouncementController { + + @Autowired + private IAnnouncementService announcementService; + + /** + * 查询公告列表 + */ + @GetMapping("/list") + public PageInfo list(Announcement announcement, @RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize) { + PageHelper.startPage(pageNum, pageSize); + List announcements = announcementService.selectAnnouncementList(announcement); + return new PageInfo(announcements); + } + + /** + * 查询全部公告列表 + */ + @GetMapping("/listAll") + public List listAll(Announcement announcement) { + return announcementService.selectAnnouncementList(announcement); + } + + /** + * 获取公告详细信息 + */ + @GetMapping(value = "/info/{id}") + public Result getInfo(@PathVariable("id") Long id) { + return Result.success(announcementService.selectAnnouncementById(id)); + } + + /** + * 新增公告 + */ + @PostMapping("/add") + public Result add(@RequestBody Announcement announcement) { + return announcementService.insertAnnouncement(announcement) > 0 ? Result.success("新增成功") : Result.error("新增失败"); + } + + /** + * 修改公告 + */ + @PutMapping + public Result update(@RequestBody Announcement announcement) { + return announcementService.updateAnnouncement(announcement) > 0 ? Result.success("修改成功") : Result.error("修改失败"); + } + + /** + * 删除公告 + */ + @DeleteMapping("/{id}") + public Result delete(@PathVariable Long id) { + return announcementService.deleteAnnouncementById(id) > 0 ? Result.success("删除成功") : Result.error("删除失败"); + } + + /** + * 设为置顶(全局仅一个置顶) + */ + @PutMapping("/setTop/{id}") + public Result setTop(@PathVariable Long id) { + return announcementService.setTop(id) > 0 ? Result.success("置顶成功") : Result.error("置顶失败"); + } + + /** + * 游客端公告列表(置顶 + 普通分页) + * + * 返回: + * topList - 置顶公告列表 + * list - 普通公告当前页数据 + * total - 普通公告总条数 + */ + @GetMapping("/touristList") + public Result touristList(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize, + @RequestParam(value = "title", required = false) String title) { + List topList = announcementService.selectTopAnnouncements(); + PageHelper.startPage(pageNum, pageSize); + Announcement filter = new Announcement(); + filter.setTitle(title); + List normals = announcementService.selectNormalAnnouncements(filter); + PageInfo pageInfo = new PageInfo(normals); + Map data = new HashMap<>(); + data.put("topList", topList); + data.put("list", pageInfo.getList()); + data.put("total", pageInfo.getTotal()); + return Result.success(data); + } +} diff --git a/src/main/java/com/amms/domain/Announcement.java b/src/main/java/com/amms/domain/Announcement.java new file mode 100644 index 0000000..8df6743 --- /dev/null +++ b/src/main/java/com/amms/domain/Announcement.java @@ -0,0 +1,133 @@ +package com.amms.domain; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 公告对象 announcement + */ +public class Announcement { + + /** 公告id */ + private Long id; + + /** 标题 */ + private String title; + + /** 内容 */ + private String content; + + /** 置顶标识(0否 1是) */ + private Long isTop; + + /** 状态(0隐藏 1显示) */ + private Long status; + + /** 发布者id */ + private Long creator; + + /** 更新者id */ + private Long updater; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setContent(String content) { + this.content = content; + } + + public String getContent() { + return content; + } + + public void setIsTop(Long isTop) { + this.isTop = isTop; + } + + public Long getIsTop() { + return isTop; + } + + public void setStatus(Long status) { + this.status = status; + } + + public Long getStatus() { + return status; + } + + + public void setCreator(Long creator) { + this.creator = creator; + } + + public Long getCreator() { + return creator; + } + + + public void setUpdater(Long updater) { + this.updater = updater; + } + + public Long getUpdater() { + return updater; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "Announcement{" + + "id=" + id + + ", title=" + title + + ", content=" + content + + ", isTop=" + isTop + + ", status=" + status + + ", createTime=" + createTime + + ", creator=" + creator + + ", updateTime=" + updateTime + + ", updater=" + updater + + '}'; + } +} diff --git a/src/main/java/com/amms/domain/dto/BatchAddReservationTimeSlotParam.java b/src/main/java/com/amms/domain/dto/BatchAddReservationTimeSlotParam.java new file mode 100644 index 0000000..c4de86f --- /dev/null +++ b/src/main/java/com/amms/domain/dto/BatchAddReservationTimeSlotParam.java @@ -0,0 +1,31 @@ +package com.amms.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class BatchAddReservationTimeSlotParam { + @JsonFormat(pattern = "yyyy-MM-dd") + private Date startDate; + @JsonFormat(pattern = "yyyy-MM-dd") + private Date endDate; + @JsonFormat(pattern = "HH:mm:ss") + private Date startTime; + @JsonFormat(pattern = "HH:mm:ss") + private Date endTime; + private Integer maxPeople; + private Long status; + + public Date getStartDate() { return startDate; } + public void setStartDate(Date startDate) { this.startDate = startDate; } + public Date getEndDate() { return endDate; } + public void setEndDate(Date endDate) { this.endDate = endDate; } + public Date getStartTime() { return startTime; } + public void setStartTime(Date startTime) { this.startTime = startTime; } + public Date getEndTime() { return endTime; } + public void setEndTime(Date endTime) { this.endTime = endTime; } + public Integer getMaxPeople() { return maxPeople; } + public void setMaxPeople(Integer maxPeople) { this.maxPeople = maxPeople; } + public Long getStatus() { return status; } + public void setStatus(Long status) { this.status = status; } +} diff --git a/src/main/java/com/amms/mapper/AnnouncementMapper.java b/src/main/java/com/amms/mapper/AnnouncementMapper.java new file mode 100644 index 0000000..a5fa8fe --- /dev/null +++ b/src/main/java/com/amms/mapper/AnnouncementMapper.java @@ -0,0 +1,62 @@ +package com.amms.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import com.amms.domain.Announcement; + +/** + * 公告Mapper接口 + */ +@Mapper +public interface AnnouncementMapper { + /** + * 查询公告 + * + * @param id 公告主键 + * @return 公告 + */ + public Announcement selectAnnouncementById(Long id); + + /** + * 查询公告列表 + * + * @param announcement 公告 + * @return 公告集合 + */ + public List selectAnnouncementList(Announcement announcement); + + /** + * 新增公告 + * + * @param announcement 公告 + * @return 结果 + */ + public int insertAnnouncement(Announcement announcement); + + /** + * 修改公告 + * + * @param announcement 公告 + * @return 结果 + */ + public int updateAnnouncement(Announcement announcement); + + /** + * 删除公告 + * + * @param id 公告主键 + * @return 结果 + */ + public int deleteAnnouncementById(Long id); + + /** + * 查询置顶公告(显示状态) + */ + public List selectTopAnnouncements(); + + /** + * 查询普通公告(非置顶且显示) + */ + public List selectNormalAnnouncements(Announcement filter); + +} diff --git a/src/main/java/com/amms/service/impl/AnnouncementServiceImpl.java b/src/main/java/com/amms/service/impl/AnnouncementServiceImpl.java new file mode 100644 index 0000000..1adbe9e --- /dev/null +++ b/src/main/java/com/amms/service/impl/AnnouncementServiceImpl.java @@ -0,0 +1,116 @@ +package com.amms.service.impl; + +import java.util.List; +import java.util.Date; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.amms.mapper.AnnouncementMapper; +import com.amms.domain.Announcement; +import com.amms.service.IAnnouncementService; +import com.amms.security.SecurityUtils; + +/** + * 公告Service业务层处理 + */ +@Service +public class AnnouncementServiceImpl implements IAnnouncementService { + + @Autowired + private AnnouncementMapper announcementMapper; + + /** + * 查询公告列表 + * + * @param announcement 公告 + * @return 公告 + */ + @Override + public List selectAnnouncementList(Announcement announcement) { + return announcementMapper.selectAnnouncementList(announcement); + } + + /** + * 查询公告 + * + * @param id 公告主键 + * @return 公告 + */ + @Override + public Announcement selectAnnouncementById(Long id) { + return announcementMapper.selectAnnouncementById(id); + } + + /** + * 新增公告 + * + * @param announcement 公告 + * @return 结果 + */ + @Override + public int insertAnnouncement(Announcement announcement) { + announcement.setCreateTime(new Date()); + announcement.setCreator(SecurityUtils.getCurrentUser().getId()); + return announcementMapper.insertAnnouncement(announcement); + } + + /** + * 修改公告 + * + * @param announcement 公告 + * @return 结果 + */ + @Override + public int updateAnnouncement(Announcement announcement) { + announcement.setUpdateTime(new Date()); + announcement.setUpdater(SecurityUtils.getCurrentUser().getId()); + return announcementMapper.updateAnnouncement(announcement); + } + + /** + * 删除公告信息 + * + * @param id 公告主键 + * @return 结果 + */ + @Override + public int deleteAnnouncementById(Long id) { + return announcementMapper.deleteAnnouncementById(id); + } + + @Override + public int setTop(Long id) { + Announcement query = new Announcement(); + query.setIsTop(1L); + List tops = announcementMapper.selectAnnouncementList(query); + Long currentTopId = (tops != null && !tops.isEmpty()) ? tops.get(0).getId() : null; + + Long userId = SecurityUtils.getCurrentUser().getId(); + Date now = new Date(); + + if (currentTopId != null && !currentTopId.equals(id)) { + Announcement clearTop = new Announcement(); + clearTop.setId(currentTopId); + clearTop.setIsTop(0L); + clearTop.setUpdater(userId); + clearTop.setUpdateTime(now); + announcementMapper.updateAnnouncement(clearTop); + } + + Announcement setTop = new Announcement(); + setTop.setId(id); + setTop.setIsTop(1L); + setTop.setUpdater(userId); + setTop.setUpdateTime(now); + return announcementMapper.updateAnnouncement(setTop); + } + + @Override + public List selectTopAnnouncements() { + return announcementMapper.selectTopAnnouncements(); + } + + @Override + public List selectNormalAnnouncements(Announcement filter) { + return announcementMapper.selectNormalAnnouncements(filter); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..b54de7f --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,70 @@ +spring: + application: + name: amms + jackson: + time-zone: GMT+8 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/mms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true + username: root + password: Ding1998@ + hikari: + max-lifetime: 3600000 # 最大生命周期 + maximum-pool-size: 30 # 最大连接数 + minimum-idle: 10 # 最小连接数 + idle-timeout: 60000 # 空闲连接超时时间 + connection-timeout: 60000 # 连接超时时间 + # 文件上传 + servlet: + multipart: + # 单个文件大小 + max-file-size: 500MB + # 设置总上传的文件大小 + max-request-size: 1000MB + data: + redis: + host: 127.0.0.1 + port: 6379 + password: + database: 1 + lettuce: + pool: + # 连接池最大连接数(使用负值表示没有限制): 8 + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制)默认为-1 + max-wait: -1 + # 连接池中的最大空闲连接 默认为8 + max-idle: 8 + # 连接池中的最小空闲连接 默认为0 + min-idle: 0 +server: + port: 8848 + servlet: + context-path: /amms +logging: + level: + root: info + sql: debug + web: info + file: + name: /Users/dmz/Work/Project/BS/2026/LogFiles/amms/log/app.log +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 120 +# MyBatis配置 +mybatis: + # 搜索指定包别名 + typeAliasesPackage: com.amms.domain + # 配置mapper的扫描,找到所有的mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的配置文件 + configLocation: classpath:mybatis/mybatis-config.xml + +# 文件上传参数 +files: + path: /Users/dmz/Work/Project/BS/2026/Files/ammsFiles diff --git a/src/main/resources/mapper/AnnouncementMapper.xml b/src/main/resources/mapper/AnnouncementMapper.xml new file mode 100644 index 0000000..67038b8 --- /dev/null +++ b/src/main/resources/mapper/AnnouncementMapper.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + select id, title, content, is_top, status, create_time, creator, update_time, updater from announcement + + + + + + + + + + + + + + insert into announcement + + title, + content, + is_top, + status, + create_time, + creator, + update_time, + updater, + + + #{title}, + #{content}, + #{isTop}, + #{status}, + #{createTime}, + #{creator}, + #{updateTime}, + #{updater}, + + + + + update announcement + + title = #{title}, + content = #{content}, + is_top = #{isTop}, + status = #{status}, + create_time = #{createTime}, + creator = #{creator}, + update_time = #{updateTime}, + updater = #{updater}, + + where id = #{id} + + + + delete from announcement where id = #{id} + + diff --git a/src/test/java/org/example/bsbase2025/ApplicationTests.java b/src/test/java/org/example/bsbase2025/ApplicationTests.java new file mode 100644 index 0000000..695a304 --- /dev/null +++ b/src/test/java/org/example/bsbase2025/ApplicationTests.java @@ -0,0 +1,14 @@ +package org.example.bsbase2025; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() throws JsonProcessingException { + } + +} diff --git a/文件/22150110017陈素霞任务书.docx b/文件/22150110017陈素霞任务书.docx new file mode 100644 index 0000000..b638c42 Binary files /dev/null and b/文件/22150110017陈素霞任务书.docx differ