原创

基于SpringBoot2+vue2的装饰工程管理系统

温馨提示:
本文最后更新于 2026年05月28日,已超过 13 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

1. 资源

浏览全文可获取

2. 项目简介

装饰工程管理系统,旨在对装修公司的工程项目进行全流程信息化管理。系统涵盖从项目立项、预算报价、合同管理、材料计划到装修进度汇报的核心业务环节。

系统支持管理员员工客户三种角色。管理员负责基础数据配置和核心业务审核;员工(如项目经理)负责创建项目、管理预算、合同、材料和进度;客户则可以登录系统查看与自己相关的项目信息、合同及报价。

3. 技术栈

  • 后端技术
    • 核心框架: Spring Boot 2.2.2.RELEASE
    • 持久层框架: MyBatis-Plus 2.3 + MyBatis
    • 安全控制: Apache Shiro 1.3.2 (用于权限控制)
    • 数据库: MySQL 5.7.32
    • 工具库: Hutool, Fastjson, Commons-lang3, Poi (用于Excel处理)
  • 前端技术
    • 核心框架: Vue.js (基于vue/cli构建)
    • UI库: Element UI
    • HTTP库: Axios
    • 图表库: ECharts
    • 其他: vue-router,, vue-json-excel

4. 详细介绍

系统通过定义清晰的数据库表和基于角色的权限控制,实现了装饰工程项目管理的核心业务逻辑。

4.1 核心功能模块

  1. 立项项目管理 (lixiangxiangmu): 项目的起点。员工可以发起新的项目,填写项目名称、客户信息、项目类型并上传项目文件。项目提交后需经过管理员审核,审核结果分为“通过”或“拒绝”,并可以填写审核原因。
  2. 预算报价管理 (yushuanbaojia): 针对已立项的项目,员工可以录入预算报价金额,系统会记录每次报价的添加时间。
  3. 合同管理 (hetong): 项目审核通过后,可以生成合同。合同信息关联立项项目,包含合同标题、合同文件(如Word文档)和合同详情。
  4. 合同报价 (hetongbaojia): 针对已生成的合同,可以进行报价。
  5. 装饰材料总计划 (zhuangshicailiao): 针对立项项目,可以制定详细的材料采购计划。包括材料名称、类型、价格、采购数量和单位等信息。
  6. 装修进度管理 (zhuangxiujindu): 员工可以上传项目的装修进度,包括进度标题、图片和详情描述,方便客户和管理员实时了解项目进展。
  7. 公告信息管理 (news): 管理员可以发布系统公告,支持富文本内容和图片上传,所有登录用户均可查看。

4.2 角色与权限

  • 管理员 (users 表):
    • 拥有系统最高权限。
    • 可以管理管理员账户
    • 管理所有基础数据:包括公告类型、项目类型、材料类型等字典数据。
    • 立项项目行使审核权限(通过/拒绝)。
    • 可以增删改查所有模块的数据。
  • 员工 (yonghu 表):
    • 核心业务操作者。
    • 可以新增和管理立项项目预算报价合同装饰材料计划装修进度
    • 只能查看公告信息,无法修改或删除。
  • 客户 (kehu 表):
    • 拥有有限的查看权限。
    • 可以查看与自己相关的立项项目合同预算报价材料计划装修进度
    • 只能查看公告信息。

4.3 核心业务流程

  1. 项目启动: 员工登录系统,创建新的立项项目,选择客户,填写项目信息。
  2. 项目审核: 管理员在后台查看待审核的立项项目,审核通过后项目状态变更。
  3. 合同与报价: 项目通过后,员工可以上传合同文件并创建合同报价,客户可以登录查看。
  4. 计划与执行: 员工为项目制定装饰材料总计划,并可在项目进行过程中,多次添加装修进度信息,形成进度跟踪记录。
  5. 客户查看: 客户登录系统,可以实时查看自己名下项目的状态、合同、预算和进度更新。

4.4 数据库设计亮点

  • 字典表 (dictionary): 系统大量使用了字典表来动态管理各种下拉选项(如项目类型、材料类型、审核结果等)。这不仅提高了数据维护的灵活性,也避免了在代码中硬编码枚举值。系统启动时会通过监听器 (DictionaryServletContextListener) 将所有字典数据加载到全局缓存中,并在后端通过dictionaryService.dictionaryConvert()方法自动将code_index转换为对应的index_name,方便前端展示。
  • 逻辑删除: 员工表 (yonghu) 和客户表 (kehu) 都设计了delete字段,数据删除操作为逻辑删除(更新标志位为2),而非物理删除,保障了数据的可追溯性。
  • 统一审计字段: 大部分业务表都包含create_time(创建时间)和insert_time(添加时间)字段,用于记录数据生命周期。

5. 部分代码

5.1 实体类示例 (LixiangxiangmuEntity.java)

// 立项项目实体类
@TableName("lixiangxiangmu")
public class LixiangxiangmuEntity<T> implements Serializable {
    @TableId(type = IdType.AUTO)
    private Integer id;                     // 主键
    private String lixiangxiangmuUuidNumber; // 项目编号
    private String lixiangxiangmuName;       // 项目名称
    private Integer yonghuId;                // 员工ID (外键)
    private Integer kehuId;                  // 客户ID (外键)
    private Integer lixiangxiangmuTypes;     // 项目类型 (对应字典表)
    private String lixiangxiangmuFile;       // 项目文件
    private Integer lixiangxiangmuYesnoTypes; // 审核结果 (对应字典表)
    private String lixiangxiangmuYesnoText;   // 审核原因
    private Date createTime;                 // 创建时间
    // ... getter/setter 省略
}

5.2 MyBatis-Plus 服务实现类 (LixiangxiangmuServiceImpl.java)

// 立项项目 服务实现类
@Service("lixiangxiangmuService")
@Transactional
public class LixiangxiangmuServiceImpl extends ServiceImpl<LixiangxiangmuDao, LixiangxiangmuEntity> 
    implements LixiangxiangmuService {

    @Override
    public PageUtils queryPage(Map<String,Object> params) {
        // 处理分页参数
        if(params != null && (params.get("limit") == null || params.get("page") == null)){
            params.put("page","1");
            params.put("limit","10");
        }
        // 使用自定义的Dao方法进行分页查询,并返回结果
        Page<LixiangxiangmuView> page = new Query<LixiangxiangmuView>(params).getPage();
        page.setRecords(baseMapper.selectListView(page, params));
        return new PageUtils(page);
    }
}

5.3 控制器示例 (LixiangxiangmuController.java - 保存方法)

// 立项项目 后端接口保存方法
@RequestMapping("/save")
public R save(@RequestBody LixiangxiangmuEntity lixiangxiangmu, HttpServletRequest request){
    // ... 日志记录 ...

    // 根据当前登录角色,自动填充创建者ID
    String role = String.valueOf(request.getSession().getAttribute("role"));
    if ("员工".equals(role))
        lixiangxiangmu.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));
    else if ("客户".equals(role))
        lixiangxiangmu.setKehuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))));

    // 校验数据库中是否已存在相同数据
    Wrapper<LixiangxiangmuEntity> queryWrapper = new EntityWrapper<LixiangxiangmuEntity>()
        .eq("lixiangxiangmu_uuid_number", lixiangxiangmu.getLixiangxiangmuUuidNumber())
        .eq("lixiangxiangmu_name", lixiangxiangmu.getLixiangxiangmuName());
        // ... 其他条件 ...

    LixiangxiangmuEntity existingEntity = lixiangxiangmuService.selectOne(queryWrapper);
    if(existingEntity == null){
        // 设置初始审核状态为“未审核” (code_index = 1)
        lixiangxiangmu.setLixiangxiangmuYesnoTypes(1);
        lixiangxiangmu.setCreateTime(new Date());
        lixiangxiangmuService.insert(lixiangxiangmu);
        return R.ok();
    } else {
        return R.error(511,"表中有相同数据");
    }
}

5.4 字典表转换核心逻辑 (DictionaryServiceImpl.java)

// 通过Types字段的值,从全局字典Map中查找对应的Name,并赋值给对应的Value字段
public void dictionaryConvert(Object obj, HttpServletRequest request) {
    // ... 获取对象中所有以"Types"结尾的字段 ...
    // ... 从ServletContext中获取全局字典Map ...
    Map<String, Map<Integer, String>> dictionaryMap = (Map<String, Map<Integer, String>>) servletContext.getAttribute("dictionaryMap");

    for (String typesFieldName : fieldNameList) {
        // ... 通过反射获取types字段的值 ...
        int codeIndex = Integer.parseInt(String.valueOf(types.get(obj)));
        // 构建字典的key,例如将 "lixiangxiangmuTypes" 转换为 "lixiangxiangmu_types"
        String dicCode = buildDicCode(typesFieldName);
        // 从全局Map中取值
        String indexName = dictionaryMap.get(dicCode).get(codeIndex);
        // 通过反射为对应的Value字段赋值
        Field valueField = obj.getClass().getDeclaredField(typesFieldName.replace("Types", "Value"));
        valueField.setAccessible(true);
        valueField.set(obj, indexName);
    }
}

5.5 前端路由配置 (router-static.js - 节选)

// 路由配置节选,展示了模块与前端页面的映射关系
const routes = [{
    path: '/index',
    component: Index,
    children: [
        { path: '/', name: '首页', component: Home },
        { path: '/lixiangxiangmu', name: '立项项目', component: lixiangxiangmu },
        { path: '/hetong', name: '合同管理', component: hetong },
        { path: '/yushuanbaojia', name: '预算报价', component: yushuanbaojia },
        { path: '/zhuangshicailiao', name: '装饰材料总计划', component: zhuangshicailiao },
        { path: '/zhuangxiujindu', name: '装修进度', component: zhuangxiujindu },
        // ...
    ]
}]

6. 部分截图

img1
img2
img3
img4
img5
img6
img7
img8
img9
img10
img11
img12
img13
img14
img15
img16
img17
img18
img19
img20
img21
img22
img23

7. 项目总结

装饰工程管理系统是一个功能比较完整、结构清晰的Java Web项目,专为装饰装修行业的中小企业设计。

7.1 优点

  1. 业务逻辑清晰:系统围绕“项目”这一核心,完整串联了从立项、预算、合同到材料、进度的主流业务流程,符合行业实际应用场景。
  2. 基于角色的权限控制:通过Shiro框架和自定义拦截器,清晰地划分了管理员、员工、客户三者的操作权限,保障了数据安全。
  3. 高度可维护的字典管理:通过全局字典表和自动转换机制,避免硬编码,系统配置项(如下拉选项)的增删改查非常灵活,无需修改代码。
  4. 前后端分离架构:采用Vue + Spring Boot架构,前端界面响应快速,后端服务专注于API,易于扩展和维护。
  5. 数据完整性设计:使用了逻辑删除、统一审计字段、外键关联等设计,保证了数据的有效性和可追溯性。

总体而言,该系统提供了一个扎实的管理系统基础框架和实现,可以直接部署使用,也可作为二次开发的起点,具备良好的参考价值和实用性。

自助获取:https://fifteen.xiaobias.com/source/206

正文到此结束
本文目录