基于Java+SpringBoot+vue前后端分离体育馆使用预约平台设计实现

news2024/12/26 11:26:37

博主介绍全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战

🍅文末获取源码联系🍅

👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

2022-2024年最全的计算机软件毕业设计选题大全:1000个热门选题推荐✅

Java项目精品实战案例《100套》

Java微信小程序项目实战《100套》

 

系统介绍:

如今社会上各行各业,都在用属于自己专用的软件来进行工作,互联网发展到这个时候,人们已经发现离不开了互联网。互联网的发展,离不开一些新的技术,而新技术的产生往往是为了解决现有问题而产生的。针对于场地预约信息管理方面的不规范,容错率低,管理人员处理数据费工费时,采用新开发的体育馆使用预约平台可以从根源上规范整个数据处理流程的正规性和合法性。

体育馆使用预约平台能够实现场地管理,用户管理,论坛管理,公告管理,场地订单管理等功能。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。

体育馆使用预约平台可以提高场地预约信息管理问题的解决效率,优化场地预约信息处理流程,并且能够保证存储数据的安全,它是一个非常可靠,非常安全的应用程序。

图4.1即为设计的管理员功能结构,管理员权限操作的功能包括对注册用户信息的管理,对场地,场地预约订单,公告,论坛帖子等信息的管理。

 图4.1 管理员功能结构

图4.2即为设计的用户功能结构,用户权限操作的功能包括参与论坛帖子发布与评论,查看公告,预约场地,收藏场地等。

 图4.2 用户功能结构

程序上交给用户进行使用时,需要提供程序的操作流程图,这样便于用户容易理解程序的具体工作步骤,现如今程序的操作流程都有一个大致的标准,即先通过登录页面提交登录数据,通过程序验证正确之后,用户才能在程序功能操作区页面操作对应的功能。

程序操作流程图

功能截图:

 编程人员在搭建的开发环境中,运用编程技术实现本系统设计的各个操作权限的功能。在本节中,就展示部分操作权限的功能与界面。

5.1 管理员后台功能实现

5.1.1 论坛管理

图5.1 即为编码实现的论坛管理界面,管理员在该界面中查看论坛回复信息,修改论坛帖子内容,可以删除论坛帖子。论坛信息包含帖子标题,用户姓名,用户手机号,用户身份证,查询的时候可以通过这些信息查询出来结果,添加内容的时候需要输入帖子类型,帖子标题,发布内容。

图5.1 论坛管理界面

管理员添加论坛:

@RequestMapping("/save")
public R save(@RequestBody ForumEntity forum, HttpServletRequest request){
    logger.debug("save方法:,,Controller:{},,forum:{}",this.getClass().getName(),forum.toString());

    String role = String.valueOf(request.getSession().getAttribute("role"));
    if(StringUtil.isEmpty(role))
        return R.error(511,"权限为空");
    else if("用户".equals(role))
        forum.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));
    else if("管理员".equals(role))
        forum.setUsersId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));

    Wrapper<ForumEntity> queryWrapper = new EntityWrapper<ForumEntity>()
        .eq("forum_name", forum.getForumName())
        .eq("yonghu_id", forum.getYonghuId())
        .eq("users_id", forum.getUsersId())
        .eq("super_ids", forum.getSuperIds())
        .eq("forum_types", forum.getForumTypes())
        .eq("forum_state_types", forum.getForumStateTypes())
        ;

    logger.info("sql语句:"+queryWrapper.getSqlSegment());
    ForumEntity forumEntity = forumService.selectOne(queryWrapper);
    if(forumEntity==null){
        forum.setInsertTime(new Date());
        forum.setCreateTime(new Date());
        forumService.insert(forum);
        return R.ok();
    }else {
        return R.error(511,"表中有相同数据");
    }
}

5.1.2 用户管理

图5.2 即为编码实现的用户管理界面,管理员在该界面中为注册系统的用户重置密码,更改用户的头像,电子邮箱等基础信息,删除需要删除的用户。用户信息包含账号,密码,手机号,身份证,头像,性别,电子信箱,余额等。查询的时候只需要提供用户姓名,手机号,身份证就可以查询。

图5.2 用户管理界面

用户添加:

@RequestMapping("/save")
public R save(@RequestBody YonghuEntity yonghu, HttpServletRequest request){
    logger.debug("save方法:,,Controller:{},,yonghu:{}",this.getClass().getName(),yonghu.toString());

    String role = String.valueOf(request.getSession().getAttribute("role"));
    if(StringUtil.isEmpty(role))
        return R.error(511,"权限为空");

    Wrapper<YonghuEntity> queryWrapper = new EntityWrapper<YonghuEntity>()
        .eq("username", yonghu.getUsername())
        .or()
        .eq("yonghu_phone", yonghu.getYonghuPhone())
        .or()
        .eq("yonghu_id_number", yonghu.getYonghuIdNumber())
        ;

    logger.info("sql语句:"+queryWrapper.getSqlSegment());
    YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper);
    if(yonghuEntity==null){
        yonghu.setCreateTime(new Date());
        yonghu.setPassword("123456");
        yonghuService.insert(yonghu);
        return R.ok();
    }else {
        return R.error(511,"账户或者用户手机号或者用户身份证号已经被使用");
    }
}

5.1.3 场地管理

图5.3 即为编码实现的场地管理界面,管理员在该界面中可以更改场地信息,新增新的场地信息,删除需要删除的场地资料。场地搜索只需要输入场地名称,场地类型就可以查到结果。新增场地则需要输入场地编号,场地名称,照片,类型,原价,现价,时间段,半全场,推荐吃饭地点,场地介绍等。

图5.3 场地管理界面

场地修改:

@RequestMapping("/update")
public R update(@RequestBody ChangdiEntity changdi, HttpServletRequest request){
    logger.debug("update方法:,,Controller:{},,changdi:{}",this.getClass().getName(),changdi.toString());
    String role = String.valueOf(request.getSession().getAttribute("role"));
    Wrapper<ChangdiEntity> queryWrapper = new EntityWrapper<ChangdiEntity>()
        .notIn("id",changdi.getId())
        .andNew()
        .eq("changdi_uuid_number", changdi.getChangdiUuidNumber())
        .eq("changdi_name", changdi.getChangdiName())
        .eq("changdi_types", changdi.getChangdiTypes())
        .eq("shijianduan", changdi.getShijianduan())
        .eq("shijianduan_ren", changdi.getShijianduanRen())
        .eq("changdi_clicknum", changdi.getChangdiClicknum())
        .eq("banquan_types", changdi.getBanquanTypes())
        .eq("shangxia_types", changdi.getShangxiaTypes())
        .eq("tuijian", changdi.getTuijian())
        .eq("changdi_delete", changdi.getChangdiDelete())
        ;

    logger.info("sql语句:"+queryWrapper.getSqlSegment());
    ChangdiEntity changdiEntity = changdiService.selectOne(queryWrapper);
    if("".equals(changdi.getChangdiPhoto()) || "null".equals(changdi.getChangdiPhoto())){
            changdi.setChangdiPhoto(null);
    }
    if(changdiEntity==null){
       changdiService.updateById(changdi);//根据id更新
        return R.ok();
    }else {
        return R.error(511,"表中有相同数据");
    }
}

5.1.4 场地订单管理

图5.4 即为编码实现的场地订单管理界面,管理员在该界面中对用户预约的场地订单进行查询,更改等,查看场地预约订单的预约时间段信息以及订单类型等信息。可以通过输入场地名称,类型,用户姓名,用户手机号,用户身份证号来进行查询场地预约信息。

图5.4 场地订单管理界面

场地订单列表:

/**
* 后端列表
*/
@RequestMapping("/page")
public R page(@RequestParam Map<String, Object> params, HttpServletRequest request){
    logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params));
    String role = String.valueOf(request.getSession().getAttribute("role"));
    if(StringUtil.isEmpty(role))
        return R.error(511,"权限为空");
    else if("用户".equals(role))
        params.put("yonghuId",request.getSession().getAttribute("userId"));
    if(params.get("orderBy")==null || params.get("orderBy")==""){
        params.put("orderBy","id");
    }
    PageUtils page = changdiOrderService.queryPage(params);

    //字典表数据转换
    List<ChangdiOrderView> list =(List<ChangdiOrderView>)page.getList();
    for(ChangdiOrderView c:list){
        //修改对应字典表字段
        dictionaryService.dictionaryConvert(c, request);
    }
    return R.ok().put("data", page);
}

5.1.5 公告信息管理

图5.5 即为编码实现的公告信息管理界面,管理员在该界面中负责发布公告信息,更改公告信息的部分信息,删除需要删除的公告。

图5.5 公告信息管理界面

5.2 用户前台功能实现

5.2.1 场地信息

图5.6 即为编码实现的场地信息界面,用户在该界面中对场地进行预定,或收藏场地方便下次查看场地信息。可以看到的场地名称,类型,原价,现价,人数,点击次数,半全场,推荐吃饭地点,订购日期,订购时间段详情介绍。

图5.6 场地信息界面

场地预约:

@RequestMapping("/add")
public R add(@RequestBody ChangdiOrderEntity changdiOrder, HttpServletRequest request){
    logger.debug("add方法:,,Controller:{},,changdiOrder:{}",this.getClass().getName(),changdiOrder.toString());
    String role = String.valueOf(request.getSession().getAttribute("role"));
    if("用户".equals(role)){
        ChangdiEntity changdiEntity = changdiService.selectById(changdiOrder.getChangdiId());
        if(changdiEntity == null){
            return R.error(511,"查不到该场地");
        }
        if(changdiEntity.getChangdiNewMoney() == null){
            return R.error(511,"场地价格不能为空");
        }

        Integer userId = (Integer) request.getSession().getAttribute("userId");
        YonghuEntity yonghuEntity = yonghuService.selectById(userId);
        if(yonghuEntity == null)
            return R.error(511,"用户不能为空");
        if(yonghuEntity.getNewMoney() == null)
            return R.error(511,"用户金额不能为空");
        double balance = yonghuEntity.getNewMoney() - changdiEntity.getChangdiNewMoney();//余额
        if(balance<0)
            return R.error(511,"余额不够支付");

        List<Integer> changdiOrderTypes = new ArrayList<>();
        changdiOrderTypes.add(2);
        String buyTime = new SimpleDateFormat("yyyy-MM-dd").format(changdiOrder.getBuyTime());
        List<ChangdiOrderEntity> changdiOrderEntities = changdiOrderService.selectList(new EntityWrapper<ChangdiOrderEntity>().notIn("changdi_order_types", changdiOrderTypes).eq("shijianduan", changdiOrder.getShijianduan()).eq("buy_time",buyTime));

        if(changdiOrderEntities != null && changdiOrderEntities.size()>0)
            return R.error(511,buyTime+" 那天的 "+changdiOrder.getShijianduan()+" 的时间段已经被预约了");

        changdiOrder.setYonghuId(userId); //设置订单支付人id
        changdiOrder.setInsertTime(new Date());
        changdiOrder.setCreateTime(new Date());
        changdiOrder.setChangdiOrderTypes(1);
        changdiOrder.setChangdiOrderTruePrice(changdiEntity.getChangdiNewMoney());
        changdiOrder.setChangdiOrderUuidNumber(String.valueOf(new Date().getTime()));
        changdiOrderService.insert(changdiOrder);//新增订单
        yonghuEntity.setNewMoney(balance);//设置金额
        yonghuService.updateById(yonghuEntity);
        return R.ok();
    }else{
        return R.error(511,"您没有权限支付订单");
    }
}

5.2.2 在线论坛

图5.7 即为编码实现的在线论坛界面,用户在该界面中对论坛所有帖子进行查看,查看帖子之后可以发布帖子评论,用户也能点击发布帖子链接进入新界面发布自己的帖子。主要可以看到帖子标题,发布人权限,发布时间,可以对这些帖子进行回复操作。

 

图5.7 在线论坛界面

代码实现:

/**
 * 登录相关
 */
@RequestMapping("users")
@RestController
public class UserController{
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private TokenService tokenService;

    /**
     * 登录
     */
    @IgnoreAuth
    @PostMapping(value = "/login")
    public R login(String username, String password, String role, HttpServletRequest request) {
        UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
        if(user != null){
            if(!user.getRole().equals(role)){
                return R.error("权限不正常");
            }
            if(user==null || !user.getPassword().equals(password)) {
                return R.error("账号或密码不正确");
            }
            String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());
            return R.ok().put("token", token);
        }else{
            return R.error("账号或密码或权限不对");
        }

    }
    
    /**
     * 注册
     */
    @IgnoreAuth
    @PostMapping(value = "/register")
    public R register(@RequestBody UserEntity user){
//        ValidatorUtils.validateEntity(user);
        if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
            return R.error("用户已存在");
        }
        userService.insert(user);
        return R.ok();
    }

    /**
     * 退出
     */
    @GetMapping(value = "logout")
    public R logout(HttpServletRequest request) {
        request.getSession().invalidate();
        return R.ok("退出成功");
    }
    
    /**
     * 密码重置
     */
    @IgnoreAuth
    @RequestMapping(value = "/resetPass")
    public R resetPass(String username, HttpServletRequest request){
        UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
        if(user==null) {
            return R.error("账号不存在");
        }
        user.setPassword("123456");
        userService.update(user,null);
        return R.ok("密码已重置为:123456");
    }
    
    /**
     * 列表
     */
    @RequestMapping("/page")
    public R page(@RequestParam Map<String, Object> params,UserEntity user){
        EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();
        PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));
        return R.ok().put("data", page);
    }

    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") String id){
        UserEntity user = userService.selectById(id);
        return R.ok().put("data", user);
    }
    
    /**
     * 获取用户的session用户信息
     */
    @RequestMapping("/session")
    public R getCurrUser(HttpServletRequest request){
        Integer id = (Integer)request.getSession().getAttribute("userId");
        UserEntity user = userService.selectById(id);
        return R.ok().put("data", user);
    }

    /**
     * 保存
     */
    @PostMapping("/save")
    public R save(@RequestBody UserEntity user){
//        ValidatorUtils.validateEntity(user);
        if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
            return R.error("用户已存在");
        }
        userService.insert(user);
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody UserEntity user){
//        ValidatorUtils.validateEntity(user);
        userService.updateById(user);//全部更新
        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Integer[] ids){
        userService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }
}

论文参考:

​​​​​​​

源码获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

 精彩专栏推荐订阅下方专栏👇🏻

2022-2024年最全的计算机软件毕业设计选题大全:1000个热门选题推荐✅

Java项目精品实战案例《100套》

Java微信小程序项目实战《100套》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/929604.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tensor-动手学深度学习-李沐_笔记

介绍 Tensor&#xff0c;又称"张量"&#xff0c;其实就是n维度数组。不同维度的Tensor示意图如下&#xff1a; 关于Tensor.reshape reshape函数可以处理总元素个数相同的任何新形状&#xff0c;【3&#xff0c;2&#xff0c;5】->【3&#xff0c;10】->【5&a…

论文笔记: One Fits All:Power General Time Series Analysis by Pretrained LM

1 intro 时间序列领域预训练模型/foundation 模型的研究还不是很多 主要挑战是缺乏大量的数据来训练用于时间序列分析的基础模型——>论文利用预训练的语言模型进行通用的时间序列分析 为各种时间序列任务提供了一个统一的框架 论文还调查了为什么从语言领域预训练的Transf…

GEE/PIE遥感大数据处理与典型案例丨数据整合Reduce、云端数据可视化、数据导入导出及资产管理、机器学习算法等

目录 ​专题一&#xff1a;初识GEE和PIE遥感云平台 专题二&#xff1a;GEE和PIE影像大数据处理基础 专题三&#xff1a;数据整合Reduce 专题四&#xff1a;云端数据可视化 专题五&#xff1a;数据导入导出及资产管理 专题六&#xff1a;机器学习算法 专题七&#xff1a;…

Spring Cloud Nacos详解

目录 1、Spring Cloud Nacos详细介绍2、Spring Cloud Nacos具体案列 Spring Cloud Nacos 是一个由阿里巴巴集团开发的开源分布式系统服务发现、配置管理和服务管理的平台。Nacos 支持多种服务发现方式&#xff0c;包括 DNS 方式、HTTP 和 RPC 方式&#xff0c;同时提供了灵活的…

GFPGAN 集成Flask 接口化改造

GFPGAN是一款腾讯开源的人脸高清修复模型&#xff0c;基于github上提供的demo&#xff0c;可以简单的集成Flask以实现功能接口化。 GFPGAN的安装&#xff0c;Flask的安装请参见其他文章。 如若使用POSTMAN进行测试&#xff0c;需使用POST方式&#xff0c;form-data的请求体&am…

camshift, pca,协方差

最近复习opencv的东西&#xff0c; 看到camshift https://www.youtube.com/watch?va9KZjQ4e6IA&listPL6Yc5OUgcoTmTGACTa__vnifNA744Cz-q&index30 https://medium.com/claudio.vindimian/understanding-and-implementing-the-camshift-object-tracking-algorithm-pyt…

【现场问题】oracle 11g 和12c 使用jdbc链接,兼容的问题

oracle不同版本 问题是什么寻找解决方式首先Oracle的jdbc链接有几种形式?Oracle 11g的链接是什么呢Oracle 12C的链接是什么呢我的代码是哪种&#xff01;&#xff1f;发现问题没 解决问题代码 问题是什么 项目上建立Oracle数据源&#xff0c;以前大部分都是&#xff0c;11g的…

树模型与集成学习:LightGBM

目录 树模型与集成学习 LightGBM 的贡献 LightGBM 的贡献&#xff1a;单边梯度抽样算法 LightGBM 的贡献&#xff1a;直方图算法 LightGBM 的贡献&#xff1a;互斥特征捆绑算法 LightGBM 的贡献&#xff1a;深度限制的 Leaf-wise 算法 树模型与集成学习 树模型是非常好的…

目标检测(Object Detection):Fast R-CNN,YOLO v3

目录 目标检测(Object Detection) R-CNN SPPNet Fast R-CNN YOLO v1 YOLO v2 YOLO v3 目标检测(Object Detection) 任务是计算机视觉中非常重要的基础问题&#xff0c;也是解决图像分割、目标跟踪、图像描述等问题的基础。目标检测是检测输入图像是否存在给定类别的物体…

“梯媒广告商”分众传媒,能否凭借AI更“香”?

“你没事儿吧&#xff1f;你没事儿吧&#xff1f;没事儿就吃溜溜梅”“婚纱照&#xff0c;想去哪拍&#xff0c;就去哪拍&#xff0c;铂爵旅拍”“0糖0脂0卡&#xff0c;我喝元气森林”……相信不少人都被这些魔性、好记的广告词洗脑过&#xff0c;而这些脍炙人口的经典广告语背…

ssm+vue农家乐信息平台源码和论文

ssmvue农家乐信息平台源码和论文066 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 1、研究现状 国外&#xff0c;农家乐都被作为潜在的发展农村经济&#xff0c;增加农民收入的重要手段&#xff0c;让农户广…

从开源到商业化:成功的转型策略

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

研磨设计模式day09原型模式

目录 场景 代码实现 有何问题 解决方案 代码改造 模式讲解 原型与new 原型实例与克隆出来的实例 浅度克隆和深度克隆 原型模式的优缺点 思考 何时选用&#xff1f; 相关模式 场景 代码实现 定义订单接口 package com.zsp.bike.day08原型模式;/*** 订单的接口*…

大数据时代的软件开发实践:利用云计算和AI赋能创新

文章目录 云计算的赋能弹性资源管理远程协作与分布式开发持续集成和持续交付成本效益 人工智能的赋能数据驱动的决策自动化智能预测和优化自适应系统 创新的实践方法数据驱动的创新智能化产品开放式创新迭代和反馈 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;…

开源的安全性:挑战与机会

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Spring和mybatis整合

一、Spring整合MyBatis 1. 导入pom依赖 1.1 添加spring相关依赖(5.0.2.RELEASE) spring-core spring-beans spring-context spring-orm spring-tx spring-aspects spring-web 1.2 添加mybatis相关依赖 mybatis核心&#xff1a;mybatis(3.4.5) Mybatis分页&#xff1a;pagehel…

基于Python的小区监控图像拼接系统设计与实现【源码+论文+演示视频+包运行成功】

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java、Python等技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; …

华为云渲染实践

// 编者按&#xff1a;云计算与网络基础设施发展为云端渲染提供了更好的发展机会&#xff0c;华为云随之长期在自研图形渲染引擎、工业领域渲染和AI加速渲染三大方向进行云渲染方面的探索与研究。本次LiveVideoStackCon 2023上海站邀请了来自华为云的陈普&#xff0c;为大家分…

研磨设计模式day11代理模式

目录 场景 代码实现 ​编辑 解析 定义 代理模式调用示意图 代理模式的特点 本质 ​编辑何时选用 场景 我有一个订单类&#xff0c;包含订单数、用户名和商品名&#xff0c;有一个订单接口包含了对订单类的getter和setter 现在有一个需求&#xff0c;a创建的订单只…

位运算(包括OR,AND,XOR,NOR,NAND,XNOR,以及0xFF等常见应用)

目录 ​编辑 1、按位与操作 2、按位或操作 3、取反运算 4、异或运算 不同为1&#xff0c;相同为0 ​编辑 5、左移运算 6、右移运算 常见用途&#xff1a; C语言位运算讲解&#xff1a; 位运算&#xff08;包括OR,AND,XOR,NOR,NAND,XNOR&#xff0c;以及&0xFF等常…