前言
✨ **博主介绍:**一线全栈工程师,毕设实战引路人。技术栈覆盖Java、Python、C#、PHP、Node.js及UniApp跨端开发,擅长多语言项目落地与架构设计。持续分享毕设源码、开题报告、技术选型心得与职场踩坑经验。用工程化思维写代码,帮你把毕设做成作品集。👍👍
👇精彩专栏 推荐订阅👇
✅获取源码请私信✅
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以找我咨询,希望帮助更多的人❤️
系统模块的实现
登录模块
微信小程序端登录模块
用户首次进入小程序时,调用wx.login()获取临时登录凭证code,发送至后端/api/auth/wxLogin接口;后端通过微信官方接口换取openid并查询用户是否存在。若为新用户,则自动创建基础账户并返回token;若为老用户,则校验状态并返回完整用户信息。前端将token与用户数据存入本地缓存wx.setStorageSync('userInfo'),后续请求携带token进行身份认证。

后台管理系统登录模块
管理员在登录页面输入账号与密码,点击"登录"按钮后,前端调用loginApi向后端/admin/auth/login发起POST请求。后端验证账号密码及角色权限,成功后生成JWT令牌并返回。前端将token存入Vuex与localStorage,后续所有管理接口请求均在Authorization头中携带该token,未认证或权限不足的请求将被拦截并跳转至登录页。

后台管理系统登录界面
系统用户管理模块
管理员管理
在后台"系统用户管理"页面,管理员可查看所有注册用户列表,筛选角色为"管理员"的账户。通过操作栏的"编辑"按钮,可修改其姓名、手机号或重置密码;点击"禁用"则调用userController.disableAdmin(id)接口,将该账户状态设为无效,使其无法登录后台系统,保障权限安全。

管理员管理界面
普通用户管理
管理员在用户管理界面选择角色为"普通用户"的条目,可执行查看详情、冻结账户或删除操作。当用户存在违规行为时,点击"冻结"按钮触发userController.freezeUser(id)请求,后端更新用户状态字段,前端同步刷新列表。被冻结用户在小程序端登录时将收到"账户已被限制"提示,无法继续使用核心功能。

普通用户管理界面
非遗项目管理模块
微信小程序端非遗项目
用户进入"非遗项目"页面后,小程序向/api/heritage/list接口发起分页请求,获取项目缩略图、名称、类型及简介。点击任一项目卡片,跳转至详情页,加载视频、语音讲解、文化故事等富媒体内容,并显示关联传承人信息。页面底部集成点赞、收藏、分享按钮,用户交互后实时更新状态并同步至服务器。

非遗项目展示界面
非遗项目发布
普通用户在"我的"页面点击"发布非遗项目",需先完成实名认证。进入表单页后,填写项目名称、类型、来源、详细描述,并上传视频与图片素材。提交时调用/api/heritage/submit接口,数据暂存为"待审核"状态。发布成功后提示"已提交,等待管理员审核",用户可在"我的发布"中查看审核进度。

非遗项目发布界面
管理员后台非遗项目管理
管理员在"非遗项目管理"界面查看所有待审、已发布及驳回的项目列表。点击"审核"按钮进入详情页,可预览用户提交的全部内容。若信息真实合规,点击"通过"触发heritageController.approve(id)请求,项目状态变更为"已发布"并同步至小程序端;若资料不全或存疑,则点击"驳回"并填写原因,用户将收到通知并可重新编辑提交。

管理员审核非遗项目界面
传承人管理模块
微信小程序端传承人展示
用户在首页或非遗项目详情页点击"传承人"标签,跳转至传承人列表页。每个传承人卡片展示姓名、技艺类别、所在地及头像。点击进入个人主页,可查看详细介绍、代表作品。

传承人展示界面
后台管理员发布传承人
管理员在"传承人管理"页面点击"新增传承人",填写姓名、所属非遗项目、传承地址、联系电话、技艺特点及个人简介,并上传形象照。提交后调用inheritorController.createInheritor()接口,数据写入数据库并与对应非遗项目建立关联。保存成功后,该传承人信息立即在小程序端同步展示。

发布传承人界面
非遗活动管理模块
微信小程序端非遗活动
非遗活动展示
用户进入"非遗活动"页面,系统调用/api/activity/list获取近期活动列表,按时间倒序排列。每项活动显示标题、类型、时间、地点及封面图。点击进入详情页,可查看完整介绍、参与须知及当前报名人数,页面底部提供"立即报名"按钮,引导用户完成后续流程。

非遗活动展示界面
非遗活动报名
用户在活动详情页点击"立即报名",若未登录则先触发登录流程。登录后,小程序调用/api/activity/register接口,携带用户ID与活动ID提交报名申请。后端校验活动是否开放、名额是否充足,成功后返回报名编号,前端提示"报名成功,请留意通知",并在"我的报名"中记录该活动状态。

非遗活动报名界面
后台管理员非遗活动报名管理
管理员在后台"活动报名管理"界面查看待处理的报名记录,列表包含用户昵称、手机号、报名时间及活动名称。点击某条记录可查看详情,确认无误后点击"审核通过"按钮,触发registrationController.approve(id)请求,更新报名状态为"已确认";若发现信息不符或超额报名,则点击"拒绝"并填写理由,用户端将同步收到审核结果通知。

审核报名活动界面
数据库参考
sql
CREATE TABLE `message_inform` (
`inform_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '通知ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '通知人ID',
`title` varchar(255) DEFAULT NULL COMMENT '标题',
`state` varchar(255) DEFAULT NULL COMMENT '状态',
`type` varchar(64) DEFAULT NULL COMMENT '分类',
`content` varchar(255) DEFAULT NULL COMMENT '内容',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`inform_id`) USING BTREE,
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='通知记录';
DROP TABLE IF EXISTS `sensitive_vocabulary`;
CREATE TABLE `sensitive_vocabulary` (
`sensitive_vocabulary_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '敏感词汇ID',
`sensitive_vocabulary` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '敏感词汇',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`sensitive_vocabulary_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='敏感词汇';
DROP TABLE IF EXISTS `user_group`;
CREATE TABLE `user_group` (
`group_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户组ID',
`display` smallint(4) unsigned NOT NULL DEFAULT '100' COMMENT '显示顺序',
`name` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '名称',
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '描述',
`source_table` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '来源表',
`source_field` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '来源字段',
`source_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID',
`register` smallint(1) unsigned DEFAULT '0' COMMENT '注册位置',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`group_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户组';
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`article_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章id',
`title` varchar(125) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '标题',
`type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '文章分类',
`hits` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '点击数',
`praise_len` int(11) NOT NULL DEFAULT '0' COMMENT '点赞数',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '来源',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '来源地址',
`tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '标签',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '正文',
`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '封面图',
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '文章描述',
PRIMARY KEY (`article_id`,`title`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='文章';
DROP TABLE IF EXISTS `access_token`;
CREATE TABLE `access_token` (
`token_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '临时访问牌ID',
`token` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '临时访问牌',
`info` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '信息',
`maxage` int(2) NOT NULL DEFAULT '2' COMMENT '最大寿命:默认2小时',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户编号',
PRIMARY KEY (`token_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='登陆访问时长';
DROP TABLE IF EXISTS `code_token`;
CREATE TABLE `code_token` (
`code_token_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '验证码ID',
`token` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL COMMENT '令牌',
`code` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL COMMENT '验证码',
`expire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '失效时间',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`code_token_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT COMMENT='验证码';
DROP TABLE IF EXISTS `collect`;
CREATE TABLE `collect` (
`collect_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '收藏ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '收藏人ID',
`source_table` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '来源表',
`source_field` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '来源字段',
`source_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '来源ID',
`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '标题',
`img` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '封面',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`collect_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='收藏';
代码参考
java
package com.project.demo.controller;
import com.project.demo.entity.IntangibleCulturalHeritageProject;
import com.project.demo.service.IntangibleCulturalHeritageProjectService;
import com.alibaba.fastjson.JSON;
import com.project.demo.controller.base.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* 非遗项目:(IntangibleCulturalHeritageProject)表控制层
*
*/
@RestController
@RequestMapping("/intangible_cultural_heritage_project")
public class IntangibleCulturalHeritageProjectController extends BaseController<IntangibleCulturalHeritageProject, IntangibleCulturalHeritageProjectService> {
/**
* 非遗项目对象
*/
@Autowired
public IntangibleCulturalHeritageProjectController(IntangibleCulturalHeritageProjectService service) {
setService(service);
}
@PostMapping("/add")
@Transactional
public Map<String, Object> add(HttpServletRequest request) throws IOException {
Map<String,Object> paramMap = service.readBody(request.getReader());
paramMap.entrySet().removeIf(entry -> {
Object value = entry.getValue();
return value instanceof String && ((String) value).isEmpty();
});
IntangibleCulturalHeritageProject intangible_cultural_heritage_project = new IntangibleCulturalHeritageProject();
intangible_cultural_heritage_project.setProject_name(paramMap.get("project_name")==null?null:String.valueOf(paramMap.get("project_name")));
intangible_cultural_heritage_project.setType_of_intangible_cultural_heritage(paramMap.get("type_of_intangible_cultural_heritage")==null?null:String.valueOf(paramMap.get("type_of_intangible_cultural_heritage")));
intangible_cultural_heritage_project.setCover_chart(paramMap.get("cover_chart")==null?null:String.valueOf(paramMap.get("cover_chart")));
intangible_cultural_heritage_project.setInheritance_personnel(paramMap.get("inheritance_personnel")==null?null:String.valueOf(paramMap.get("inheritance_personnel")));
intangible_cultural_heritage_project.setSource_of_inheritance(paramMap.get("source_of_inheritance")==null?null:String.valueOf(paramMap.get("source_of_inheritance")));
intangible_cultural_heritage_project.setIntangible_cultural_heritage_vuser_ideo(paramMap.get("intangible_cultural_heritage_vuser_ideo")==null?null:String.valueOf(paramMap.get("intangible_cultural_heritage_vuser_ideo")));
intangible_cultural_heritage_project.setIntelligent_voice(paramMap.get("intelligent_voice")==null?null:String.valueOf(paramMap.get("intelligent_voice")));
intangible_cultural_heritage_project.setSpecificsed_introduction(paramMap.get("specificsed_introduction")==null?null:String.valueOf(paramMap.get("specificsed_introduction")));
intangible_cultural_heritage_project.setCultural_story(paramMap.get("cultural_story")==null?null:String.valueOf(paramMap.get("cultural_story")));
intangible_cultural_heritage_project.setPublisher(paramMap.get("publisher")==null?null:Integer.valueOf(String.valueOf(paramMap.get("publisher"))));
intangible_cultural_heritage_project.setHits(paramMap.get("hits")==null?null:Integer.valueOf(String.valueOf(paramMap.get("hits"))));
intangible_cultural_heritage_project.setPraise_len(paramMap.get("praise_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("praise_len"))));
intangible_cultural_heritage_project.setCollect_len(paramMap.get("collect_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("collect_len"))));
intangible_cultural_heritage_project.setComment_len(paramMap.get("comment_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("comment_len"))));
intangible_cultural_heritage_project.setExamine_state(paramMap.get("examine_state")==null?null:String.valueOf(paramMap.get("examine_state")));
intangible_cultural_heritage_project.setExamine_reply(paramMap.get("examine_reply")==null?null:String.valueOf(paramMap.get("examine_reply")));
intangible_cultural_heritage_project.setCreate_by(paramMap.get("create_by")==null?null:Integer.valueOf(String.valueOf(paramMap.get("create_by"))));
this.addEntity(intangible_cultural_heritage_project);
System.out.println("非遗项目新增成功");
return success(1);
}
@PostMapping("/set")
@Transactional
public Map<String, Object> set(HttpServletRequest request) throws IOException {
Map<String,String> queryMap = service.readQuery(request);
Map<String,String> configMap = service.readConfig(request);
Map<String,Object> paramMap = service.readBody(request.getReader());
paramMap.entrySet().removeIf(entry -> {
Object value = entry.getValue();
return value instanceof String && ((String) value).isEmpty();
});
IntangibleCulturalHeritageProject intangible_cultural_heritage_project = new IntangibleCulturalHeritageProject();
intangible_cultural_heritage_project.setProject_name(paramMap.get("project_name")==null?null:String.valueOf(paramMap.get("project_name")));
intangible_cultural_heritage_project.setType_of_intangible_cultural_heritage(paramMap.get("type_of_intangible_cultural_heritage")==null?null:String.valueOf(paramMap.get("type_of_intangible_cultural_heritage")));
intangible_cultural_heritage_project.setCover_chart(paramMap.get("cover_chart")==null?null:String.valueOf(paramMap.get("cover_chart")));
intangible_cultural_heritage_project.setInheritance_personnel(paramMap.get("inheritance_personnel")==null?null:String.valueOf(paramMap.get("inheritance_personnel")));
intangible_cultural_heritage_project.setSource_of_inheritance(paramMap.get("source_of_inheritance")==null?null:String.valueOf(paramMap.get("source_of_inheritance")));
intangible_cultural_heritage_project.setIntangible_cultural_heritage_vuser_ideo(paramMap.get("intangible_cultural_heritage_vuser_ideo")==null?null:String.valueOf(paramMap.get("intangible_cultural_heritage_vuser_ideo")));
intangible_cultural_heritage_project.setIntelligent_voice(paramMap.get("intelligent_voice")==null?null:String.valueOf(paramMap.get("intelligent_voice")));
intangible_cultural_heritage_project.setSpecificsed_introduction(paramMap.get("specificsed_introduction")==null?null:String.valueOf(paramMap.get("specificsed_introduction")));
intangible_cultural_heritage_project.setCultural_story(paramMap.get("cultural_story")==null?null:String.valueOf(paramMap.get("cultural_story")));
intangible_cultural_heritage_project.setPublisher(paramMap.get("publisher")==null?null:Integer.valueOf(String.valueOf(paramMap.get("publisher"))));
intangible_cultural_heritage_project.setHits(paramMap.get("hits")==null?null:Integer.valueOf(String.valueOf(paramMap.get("hits"))));
intangible_cultural_heritage_project.setPraise_len(paramMap.get("praise_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("praise_len"))));
intangible_cultural_heritage_project.setCollect_len(paramMap.get("collect_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("collect_len"))));
intangible_cultural_heritage_project.setComment_len(paramMap.get("comment_len")==null?null:Integer.valueOf(String.valueOf(paramMap.get("comment_len"))));
intangible_cultural_heritage_project.setExamine_state(paramMap.get("examine_state")==null?null:String.valueOf(paramMap.get("examine_state")));
intangible_cultural_heritage_project.setExamine_reply(paramMap.get("examine_reply")==null?null:String.valueOf(paramMap.get("examine_reply")));
this.setEntity(queryMap,configMap,intangible_cultural_heritage_project);
System.out.println("非遗项目修改成功");
return success(1);
}
/**
* 协同过滤算法
*/
@RequestMapping("/get_hits_list")
public Map<String, Object> getHits(HttpServletRequest request) {
Map<String,String> paramMap = service.readQuery(request);
if (paramMap.get("user_id")==null||paramMap.get("user_id").equals("")){
return this.getList(request);
}else{
try {
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
paramMap.put("examine_state", URLDecoder.decode(paramMap.get("examine_state"), "UTF-8"));
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//查询该用户收藏
String hitsSource = "SELECT COUNT( collect_id ) AS hits_count, source_id FROM collect WHERE source_table = 'intangible_cultural_heritage_project' AND user_id = "+paramMap.get("user_id")+" GROUP BY source_id ORDER BY create_time desc";
List<Map<String,Object>> hitsSourceList = service.selectMapBaseList(hitsSource);
//判断是否为空,代表当前用户暂无点击数据,那么取其他用户的最常点击
if (hitsSourceList==null || hitsSourceList.size()<=0){
hitsSource = "SELECT COUNT( collect_id ) AS hits_count, source_id FROM collect WHERE source_table = 'intangible_cultural_heritage_project' GROUP BY source_id ORDER BY create_time desc";
hitsSourceList = service.selectMapBaseList(hitsSource);
}
String table_name = "intangible_cultural_heritage_project";
String table_id = "intangible_cultural_heritage_project_id";
String type_name = "type_of_intangible_cultural_heritage";
//二次处理-如果依旧为空则取添加时间前12条数据
if (hitsSourceList==null || hitsSourceList.size()<=0){
String sql = "SELECT * FROM " + table_name;
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
sql = sql + " where examine_state = '"+paramMap.get("examine_state")+"'";
}
sql = sql + " ORDER BY create_time DESC LIMIT 0,12";
List list = service.selectBaseList(sql);
Map<String, Object> map=new HashMap<>();
map.put("list",list);
map.put("count",list.size());
return success(map);
}else {
//对用户点击量进行排序取得最大值
double max = 0.0;
int maxSourceId = 0;
for (Map<String,Object> map:hitsSourceList) {
double hitsCount = Double.parseDouble(String.valueOf(map.get("hits_count")));
if (hitsCount > max){
max = hitsCount;
maxSourceId = Integer.parseInt(String.valueOf(map.get("source_id")));
}
}
//查询该用户点击最大值的种类
String typeSql = "SELECT " + type_name + " FROM " + table_name + " WHERE " + table_id + " = " + maxSourceId;
List<Map<String,Object>> typeList = service.selectMapBaseList(typeSql);
//如果为空则取添加时间前12条数据
if (typeList==null || typeList.size()<=0){
String sql = "SELECT * FROM " + table_name;
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
sql = sql + " where examine_state = '"+paramMap.get("examine_state")+"'";
}
sql = sql + " ORDER BY create_time DESC LIMIT 0,12";
List list = service.selectBaseList(sql);
Map<String, Object> map=new HashMap<>();
map.put("list",list);
map.put("count",list.size());
return success(map);
}else {
String typeName = String.valueOf(typeList.get(0).get(type_name));
//查询该种类的数据
String sql = "SELECT * FROM " + table_name + " WHERE " + type_name + " = '"+typeName+"'" ;
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
sql = sql + " and examine_state = '"+paramMap.get("examine_state")+"' ORDER BY create_time DESC limit 0,12";
}else {
sql = sql + " ORDER BY create_time DESC limit 0,12";
}
List resultList = service.selectBaseList(sql);
//如果为空则取添加时间前12条数据
if (resultList==null || resultList.size()<=0){
sql = "SELECT * FROM " + table_name;
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
sql = sql + " where examine_state = '"+paramMap.get("examine_state")+"'";
}
sql = sql + " ORDER BY create_time DESC LIMIT 0,12";
List list = service.selectBaseList(sql);
Map<String, Object> map=new HashMap<>();
map.put("list",list);
map.put("count",list.size());
return success(map);
}else {
//对结果排序-冒泡排序
for (int i = resultList.size() - 1; i > 0; i--) {
// 是否发生交换
boolean swapped = false;
for (int j = 0; j < i; j++) {
IntangibleCulturalHeritageProject leftMap = (IntangibleCulturalHeritageProject) resultList.get(j);
IntangibleCulturalHeritageProject rightMap = (IntangibleCulturalHeritageProject) resultList.get(j + 1);
if (leftMap.getHits()<rightMap.getHits()){
IntangibleCulturalHeritageProject temp = rightMap;
rightMap = leftMap;
leftMap = temp;
swapped = true;
}
}
if (!swapped) {
// 没有发生交换,则说明数组已有序,停止冒泡
break;
}
}
//判断是否有12条-如果不足则计算其他类型和用户当前点击最多的余弦相似度,依次往下取得数据
if (resultList.size()<12) {
String typeCosSql = "SELECT " + type_name + " FROM " + table_name + " WHERE " + type_name + " <> '" + typeName + "' GROUP BY " + type_name;
List<Map<String, Object>> typeCosList = service.selectMapBaseList(typeCosSql);
if (typeCosList != null && typeCosList.size() > 0) {
for (Map<String, Object> typeCos : typeCosList) {
typeCos.put("cosSim", calculateCosineSimilarity(typeName, String.valueOf(typeCos.get(type_name))));
}
//冒泡根据相似度排序
for (int i = typeCosList.size() - 1; i > 0; i--) {
// 是否发生交换
boolean swapped = false;
for (int j = 0; j < i; j++) {
Map<String, Object> leftMap = typeCosList.get(j);
Map<String, Object> rightMap = typeCosList.get(j + 1);
if (Double.parseDouble(String.valueOf(leftMap.get("cosSim" ))) < Double.parseDouble(String.valueOf(rightMap.get("cosSim" )))) {
Map<String, Object> temp = rightMap;
rightMap = leftMap;
leftMap = temp;
swapped = true;
}
}
if (!swapped) {
// 没有发生交换,则说明数组已有序,停止冒泡
break;
}
}
//逐条加入数据
for (Map<String, Object> typeCos : typeCosList) {
sql = "SELECT * FROM " + table_name + " WHERE " + type_name + " = '" + String.valueOf(typeCos.get(type_name)) + "'";
if (paramMap.get("examine_state")!=null && !paramMap.get("examine_state").equals("")){
sql = sql + " and examine_state = '"+paramMap.get("examine_state")+"'";
}
sql = sql + " ORDER BY create_time DESC LIMIT 0," + (12 - resultList.size());
List list = service.selectBaseList(sql);
if (list != null && list.size() > 0) {
resultList.addAll(list);
}
if (resultList.size() >= 12) {
break;
}
}
}
}
Map<String, Object> map=new HashMap<>();
map.put("list",resultList);
map.put("count",resultList.size());
return success(map);
}
}
}
}
}
/**
* 计算余弦相似度
*/
private double calculateCosineSimilarity(String text1, String text2) {
// 将文本分词并转换为向量表示
Map<Character, Integer> wordCount1 = getWordCount(text1);
Map<Character, Integer> wordCount2 = getWordCount(text2);
double dotProduct = 0.0;
double magnitude1 = 0.0;
double magnitude2 = 0.0;
for (Character word : wordCount1.keySet()) {
int count1 = wordCount1.get(word);
int count2 = wordCount2.getOrDefault(word, 0);
dotProduct += count1 * count2;
magnitude1 += Math.pow(count1, 2);
}
for (Integer count : wordCount2.values()) {
magnitude2 += Math.pow(count, 2);
}
magnitude1 = Math.sqrt(magnitude1);
magnitude2 = Math.sqrt(magnitude2);
if (magnitude1 == 0.0 || magnitude2 == 0.0) {
return 0.0;
}
return dotProduct / (magnitude1 * magnitude2);
}
private static Map<Character, Integer> getWordCount(String text) {
Map<Character, Integer> wordCount = new HashMap<>();
for (char c : text.toCharArray()) {
wordCount.put(c, wordCount.getOrDefault(c, 0) + 1);
}
return wordCount;
}
/**
* 修改审核状态
*
* @param id 要修改的记录ID
* @param newState 新的审核状态
* @return 提示信息:审核成功/失败
*/
@Transactional
@GetMapping("/update_examine_state")
public String updateExamineState(Long id, String newState) throws IOException {
// 检查传入的状态是否合法
if (!newState.equals("未审核") && !newState.equals("已通过") && !newState.equals("未通过")) {
return "非法的审核状态";
}
Map<String,String> queryMap = new HashMap<>();
queryMap.put("id",String.valueOf(id));
// 根据ID查找记录
IntangibleCulturalHeritageProject intangible_cultural_heritage_project = service.findOne(queryMap);
if (intangible_cultural_heritage_project!=null) {
// 更新审核状态
intangible_cultural_heritage_project.setExamine_state(newState);
this.setEntity(queryMap,new HashMap<>(),intangible_cultural_heritage_project);
return "审核成功";
} else {
return "审核失败:记录不存在";
}
}
}
package com.project.demo.controller;
import com.alibaba.fastjson.JSON;
import com.project.demo.entity.Slides;
import com.project.demo.service.SlidesService;
import com.project.demo.controller.base.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
/**
* 轮播图:(Slides)表控制层
*/
@RestController
@RequestMapping("slides")
public class SlidesController extends BaseController<Slides, SlidesService> {
/**
* 服务对象
*/
@Autowired
public SlidesController(SlidesService service) {
setService(service);
}
@PostMapping("/add")
@Transactional
public Map<String, Object> add(HttpServletRequest request) throws IOException {
Map<String, Object> addMap = service.readBody(request.getReader());
validateParameters(addMap);
removeUnnecessaryFields(addMap);
// 插入数据
this.service.insert(addMap);
System.out.println("轮播图新增成功");
return success(1);
}
@PostMapping("/set")
@Transactional
public Map<String, Object> set(HttpServletRequest request) throws IOException {
Map<String,Object> body = this.service.readBody(request.getReader());
Slides slides = JSON.parseObject(JSON.toJSONString(body),Slides.class);
this.service.updateEntity(service.readQuery(request), service.readConfig(request), slides);
return success(1);
}
@RequestMapping(value = "/del")
@Transactional
public Map<String, Object> del(HttpServletRequest request) {
// 读取查询条件
Map<String, String> query = service.readQuery(request);
if (query == null || query.isEmpty()) {
throw new IllegalArgumentException("查询条件不能为空");
}
Map<String, String> config = service.readConfig(request);
this.service.delete(query, config);
return success(1);
}
@RequestMapping("/get_list")
public Map<String, Object> getList(HttpServletRequest request) {
// 读取查询条件
Map<String, String> query = service.readQuery(request);
Map<String, String> config = service.readConfig(request);
Map<String,Object> map = new HashMap<>();
List list = this.service.selectBaseList(this.service.select(query, config));
map.put("list",list);
map.put("count",this.service.selectBaseCount(this.service.count(query,config)));
return success(map);
}
/**
* 验证参数是否合法
*/
private void validateParameters(Map<String, Object> addMap) {
if (addMap.get("title") == null) {
throw new IllegalArgumentException("标题不能为空");
}
}
/**
* 移除不需要的字段
*/
private void removeUnnecessaryFields(Map<String, Object> addMap) {
addMap.remove("create_time");
addMap.remove("update_time");
}
}
**前端:**基于uni-app框架构建跨平台用户界面,使用HTML5、CSS3和JavaScript/Vue.js实现页面结构与交互逻辑,通过uni-app内置路由或Vue Router管理页面导航,Vuex或Pinia维护全局状态。采用uni-ui或uView等组件库快速搭建界面,使用uni.request或Axios(经适配)封装HTTP请求实现与后端的数据通信,同时可调用uni-app提供的丰富原生API(如相机、定位、支付等)增强移动端能力。
**后端:**基于Spring Boot框架搭建,遵循Controller-Service-Mapper三层架构。Controller层接收前端请求并校验参数,Service层处理核心业务逻辑,Mapper层通过MyBatis或MyBatis-Plus完成数据库操作。使用Spring Security或Shiro结合JWT实现用户认证与权限控制。
**数据库:**采用MySQL存储持久化数据,Redis缓存热点信息以提升系统性能。
开发工具: 使用HBuilderX或VSCode开发前端(uni-app),IDEA开发后端,Git进行版本管理,Maven管理后端依赖,npm或yarn管理前端依赖,并通过HBuilderX的App发布功能或命令行工具完成多端(iOS、Android、H5、各小程序)打包发布。
源码获取
私信联系我即可~
大家点赞、收藏、关注、评论啦
👇精彩专栏 推荐订阅👇
✅获取源码请私信✅
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以找我咨询,希望帮助更多的人❤️