试一下

This commit is contained in:
dmz 2025-12-05 23:08:31 +08:00
parent 28ef38a45a
commit 6bc968ca6f
18 changed files with 1176 additions and 0 deletions

31
.gitignore vendored Normal file
View File

@ -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*

30
amms_front/.gitignore vendored Normal file
View File

@ -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

10
amms_front/src/App.vue Normal file
View File

@ -0,0 +1,10 @@
<template>
<RouterView />
</template>
<script setup>
import { RouterView } from 'vue-router'
</script>
<style>
</style>

View File

@ -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 })
}

View File

@ -0,0 +1,86 @@
/* color palette from <https://github.com/vuejs/theme> */
: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;
}

View File

@ -0,0 +1,89 @@
/*
Apple风格Element Plus输入框公共样式
使用方法在需要应用样式的el-input上添加 class="apple-input"
示例<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;
}

215
sql/amms.sql Normal file
View File

@ -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='收藏';

18
sql/app.sql Normal file
View File

@ -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 = '用户';

View File

@ -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);
}
}

View File

@ -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<Announcement> announcements = announcementService.selectAnnouncementList(announcement);
return new PageInfo(announcements);
}
/**
* 查询全部公告列表
*/
@GetMapping("/listAll")
public List<Announcement> 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<Announcement> topList = announcementService.selectTopAnnouncements();
PageHelper.startPage(pageNum, pageSize);
Announcement filter = new Announcement();
filter.setTitle(title);
List<Announcement> normals = announcementService.selectNormalAnnouncements(filter);
PageInfo pageInfo = new PageInfo(normals);
Map<String, Object> data = new HashMap<>();
data.put("topList", topList);
data.put("list", pageInfo.getList());
data.put("total", pageInfo.getTotal());
return Result.success(data);
}
}

View File

@ -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 +
'}';
}
}

View File

@ -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; }
}

View File

@ -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<Announcement> 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<Announcement> selectTopAnnouncements();
/**
* 查询普通公告非置顶且显示
*/
public List<Announcement> selectNormalAnnouncements(Announcement filter);
}

View File

@ -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<Announcement> 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<Announcement> 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<Announcement> selectTopAnnouncements() {
return announcementMapper.selectTopAnnouncements();
}
@Override
public List<Announcement> selectNormalAnnouncements(Announcement filter) {
return announcementMapper.selectNormalAnnouncements(filter);
}
}

View File

@ -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

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.amms.mapper.AnnouncementMapper">
<resultMap type="com.amms.domain.Announcement" id="AnnouncementResult">
<result property="id" column="id" />
<result property="title" column="title" />
<result property="content" column="content" />
<result property="isTop" column="is_top" />
<result property="status" column="status" />
<result property="createTime" column="create_time" />
<result property="creator" column="creator" />
<result property="updateTime" column="update_time" />
<result property="updater" column="updater" />
</resultMap>
<sql id="selectAnnouncementVo">
select id, title, content, is_top, status, create_time, creator, update_time, updater from announcement
</sql>
<select id="selectAnnouncementList" parameterType="com.amms.domain.Announcement" resultMap="AnnouncementResult">
<include refid="selectAnnouncementVo"/>
<where>
<if test="title != null and title != ''"> and title = #{title}</if>
<if test="content != null and content != ''"> and content = #{content}</if>
<if test="isTop != null "> and is_top = #{isTop}</if>
<if test="status != null "> and status = #{status}</if>
<if test="creator != null "> and creator = #{creator}</if>
<if test="updater != null "> and updater = #{updater}</if>
</where>
</select>
<!-- 置顶公告(仅返回置顶且显示的记录),按更新时间倒序 -->
<select id="selectTopAnnouncements" resultMap="AnnouncementResult">
<include refid="selectAnnouncementVo"/>
where is_top = 1 and status = 1
order by create_time desc
</select>
<!-- 普通公告(非置顶且显示的记录),按更新时间倒序,分页在上层处理;支持标题模糊搜索 -->
<select id="selectNormalAnnouncements" parameterType="com.amms.domain.Announcement" resultMap="AnnouncementResult">
<include refid="selectAnnouncementVo"/>
<where>
(is_top is null or is_top = 0) and status = 1
<if test="title != null and title != ''">
and title like concat('%', #{title}, '%')
</if>
</where>
order by create_time desc
</select>
<select id="selectAnnouncementById" parameterType="Long" resultMap="AnnouncementResult">
<include refid="selectAnnouncementVo"/>
where id = #{id}
</select>
<insert id="insertAnnouncement" parameterType="com.amms.domain.Announcement" useGeneratedKeys="true" keyProperty="id">
insert into announcement
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null and title != ''">title,</if>
<if test="content != null and content != ''">content,</if>
<if test="isTop != null">is_top,</if>
<if test="status != null">status,</if>
<if test="createTime != null">create_time,</if>
<if test="creator != null">creator,</if>
<if test="updateTime != null">update_time,</if>
<if test="updater != null">updater,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null and title != ''">#{title},</if>
<if test="content != null and content != ''">#{content},</if>
<if test="isTop != null">#{isTop},</if>
<if test="status != null">#{status},</if>
<if test="createTime != null">#{createTime},</if>
<if test="creator != null">#{creator},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updater != null">#{updater},</if>
</trim>
</insert>
<update id="updateAnnouncement" parameterType="com.amms.domain.Announcement">
update announcement
<trim prefix="SET" suffixOverrides=",">
<if test="title != null and title != ''">title = #{title},</if>
<if test="content != null and content != ''">content = #{content},</if>
<if test="isTop != null">is_top = #{isTop},</if>
<if test="status != null">status = #{status},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="creator != null">creator = #{creator},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updater != null">updater = #{updater},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteAnnouncementById" parameterType="Long">
delete from announcement where id = #{id}
</delete>
</mapper>

View File

@ -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 {
}
}

Binary file not shown.