首页/新闻资讯/正文详情

SSM员工管理系统开发实战:从骨架搭建到CRUD联调部署

发布时间:2026/9/26 12:06:16 来源:云帆数科 栏目:资讯中心
SSM员工管理系统开发实战:从骨架搭建到CRUD联调部署
简介这是一套基于SSM架构的员工管理系统完整项目适合Java Web初学者、毕业设计或课程实训参考。系统覆盖员工管理、薪酬管理、用户管理、通知管理、文件管理等核心模块并区分超级管理员、普通管理员、临时管理员三类权限可用于理解MVC分层、SSM整合及权限控制思路。资源共447个文件约93.17MB包含Java源码、JSP页面、XML配置、SQL数据库脚本及配套文档源码与配置可直接导入IDEA2019配合Tomcat和MySQL运行目录结构清晰便于按模块阅读与二次开发。作者还提供了一份Markdown说明文件帮助快速理清项目结构与启动步骤。目前已有413人学习下载适合需要一套可运行、可讲解、可改造的员工管理项目作为练习或答辩支撑的开发者。1. 基于SSM架构的员工管理系统为什么今天还值得照着做一个员工管理系统要做的事不外乎登录、分页查员工、增删改查但很多新手把代码写完后前端页面却不知道跟后端怎么对上。SSM架构就是Spring、SpringMVC、MyBatis三个框架的合称Spring管对象和事务SpringMVC收HTTP请求MyBatis把SQL和Java方法绑在一起。它是Spring Boot流行前Java Web的主力至今仍是理解三层架构最好的教材也是很多课设、毕设和小型内部系统在用的方案。适合想弄懂Java Web前后端交互全过程的初学者也适合要交付一个能跑、能演示、有配套文档和SQL脚本的完整项目的从业者。这篇笔记按搭建顺序来写从骨架到CRUD再到坑最集中的联调阶段。2. 搭SSM员工管理系统的骨架项目结构、依赖与最小可运行配置2.1 为什么选SSM而不直接上Spring Boot配置即教材一个员工管理系统在功能上其实很小员工表、部门表、账号表、登录拦截、增删改查。用Spring Boot做三十分钟就能把一个空壳跑起来用MyBatis-Plus连单表CRUD都可以少写SQL。可问题是当系统在Tomcat里报了404、或者SQL参数没传进去Spring Boot的自动配置会把真正的原因挡在黑匣子里新手排查时不知道该看哪个配置。SSM恰恰相反每一层都是显式的。DispatcherServlet在哪、Spring容器加载哪个XML、Mapper接口怎么和SQL绑定都在配置文件里摆着。对这些配置理解得越透后面换成Spring Boot或其他前后端分离项目也越快。另一点是这类员工管理系统最常见的交付场景课设、毕设、企业内部的小型人事模块。评审或甲方要的不是多新的技术栈而是你讲得清楚请求怎么进来、数据怎么落库。SSM加JSP或HTML加Tomcat部署正好满足一套完整的演示链路。要是我自己接这类小项目也会先问一句用户后续会不会加复杂的权限、工作流如果不会SSM足够如果会再考虑Spring Boot加Vue前后端分离也不迟。2.2 目录结构与Maven依赖分清楚controller、service、mapper三层一个工程拿到手先看包结构。常见的SSM员工管理系统会按controller、service、mapper、entity、interceptor这样分包src/main/java/com/company/ems/ ├── controller/ # 接收HTTP请求做参数绑定和简单校验 ├── service/ # 业务逻辑事务在这一层声明 │ └── impl/ ├── mapper/ # MyBatis的Mapper接口对应XML里的SQL ├── entity/ # 对应数据库表的实体类 ├── interceptor/ # 登录拦截、权限拦截 └── config/ # 如果不用XML也可以放注解配置 src/main/resources/ ├── mapper/ # EmployeeMapper.xml、DepartmentMapper.xml ├── jdbc.properties ├── spring-mvc.xml ├── applicationContext.xml └── mybatis-config.xml src/main/webapp/ ├── WEB-INF/ │ ├── web.xml │ └── views/ # JSP页面前后端没分离时放这里 ├── static/ # css/js/images └── index.jspentity还有个别名叫pojo或model叫法不同作用相同。controller层尽量只做参数接收和视图转发不做SQL拼装service层承担事务和业务规则mapper层只负责与数据库对话。这样分工的好处是出问题时顺着请求链路逐层定位不用在Servlet里找业务代码。Maven依赖我一般这样给去掉了和具体版本强绑定的写法只看必需项dependencies !-- Spring MVC 与 Spring 核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.x/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-jdbc/artifactId version5.3.x/version /dependency !-- MyBatis 与 Spring 整合 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.x/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.x/version /dependency !-- 数据库驱动与连接池。注意 mysql 8.x 驱动类名和 5.x 不同 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.x/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.x/version /dependency !-- 分页插件 -- dependency groupIdcom.github.pagehelper/groupId artifactIdpagehelper/artifactId version5.3.x/version /dependency !-- JSON 转换前后端联调时靠它 -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.13.x/version /dependency !-- Servlet API 和 JSTL打包成 war 时需要 provided 范围 -- dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency dependency groupIdjstl/groupId artifactIdjstl/artifactId version1.2/version /dependency /dependencies这里有两个参数要特别留意。第一个是MySQL驱动类名mysql-connector-java 5.x 用 com.mysql.jdbc.Driver8.x 用 com.mysql.cj.jdbc.Driver写错启动时立刻报 ClassNotFoundException。第二个是servlet-api的scope必须配provided否则和Tomcat自带的Servlet实现冲突部署后会出现奇怪的方法签名错误。提示真实落地时把版本号里的 x 替换成你本机仓库里能拉到的最新小版本。这里不写死是因为不同Spring版本和MyBatis版本之间有兼容边界照抄固定版本反而容易在小版本上翻车。2.3 让Tomcat能跑起来的三份配置web.xml、Spring与SpringMVC的加载顺序配置是SSM里最容易翻车的地方。顺序上web.xml最先被Tomcat读取Spring根容器和SpringMVC子容器都在这里装配?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 !-- 编码过滤器放在所有过滤器最前面解决POST中文乱码 -- filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping !-- Spring 根容器 -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:applicationContext.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener !-- SpringMVC 前端控制器拦截所有请求 -- servlet servlet-namedispatcher/servlet-name servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-mvc.xml/param-value /init-param load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namedispatcher/servlet-name url-pattern//url-pattern /servlet-mapping /web-app加载顺序是Tomcat先创建ContextLoaderListener加载applicationContext.xml里的数据源、service、mapper这些根容器bean随后创建DispatcherServlet加载spring-mvc.xml里的controller、视图解析器、静态资源映射。父子容器的规则是子容器能看见父容器的bean反向不行。所以事务拦截器写在applicationContext.xml里controller扫描写在spring-mvc.xml里是SSM的标准切法。spring-mvc.xml里常翻车的是静态资源。把DispatcherServlet映射到/之后css和js默认会被它拦截前端页面就变得光秃秃。常见做法是单独放一行资源映射context:component-scan base-packagecom.company.ems.controller/ mvc:annotation-driven/ !-- 放行静态资源否则css/js全部404 -- mvc:resources mapping/static/** location/static// bean classorg.springframework.web.servlet.view.InternalResourceViewResolver property nameprefix value/WEB-INF/views// property namesuffix value.jsp/ /beanInternalResourceViewResolver的prefix和suffix要按实际目录改这里写成/WEB-INF/views/下放JSP。很多人把JSP放在webapp根目录也能跑但放在WEB-INF里更安全用户不能直接通过URL访问到页面源码。applicationContext.xml承载数据源和事务是最容易看出一个人功底的文件context:property-placeholder locationclasspath:jdbc.properties/ bean iddataSource classcom.alibaba.druid.pool.DruidDataSource property namedriverClassName value${jdbc.driver}/ property nameurl value${jdbc.url}/ property nameusername value${jdbc.username}/ property namepassword value${jdbc.password}/ /bean bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ property namemapperLocations valueclasspath:mapper/*.xml/ property nametypeAliasesPackage valuecom.company.ems.entity/ property nameplugins array bean classcom.github.pagehelper.PageInterceptor property nameproperties valuehelperDialectmysql/value /property /bean /array /property /bean bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.company.ems.mapper/ /bean bean idtxManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean tx:annotation-driven transaction-managertxManager/mapperLocations、typeAliasesPackage、basePackage这三个属性只要有一个写错启动时不会立刻报错等到调用Mapper方法才提示找不到SQL或不能创建代理。另外事务管理器配好后记得在service实现类上用Transactional不然一个方法里先插员工后插部门第二句失败时第一句不会回滚。3. 员工模块核心功能的实现路径Controller、Service、Mapper各管什么3.1 员工表和实体类字段类型决定后面的所有参数先建表再写代码。员工管理系统的SQL脚本一般包含三张表员工表、部门表、账号表。账号表承载登录员工表和部门表做外键关联CREATE TABLE dept ( id int NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE employee ( id int NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL, gender tinyint NOT NULL COMMENT 0女 1男, birthday date DEFAULT NULL, phone varchar(20) DEFAULT NULL, dept_id int NOT NULL, entry_date date DEFAULT NULL, status tinyint DEFAULT 1 COMMENT 1在职 0离职, PRIMARY KEY (id), KEY idx_dept (dept_id), CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES dept (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段注释为什么建议全写上因为配套文档和SQL脚本是要给别人看的。离职状态用status不用delete_flag走逻辑删除这个小系统里尽量少做一版复杂设计性别用tinyint存0/1比字符串省空间也更好扩展但前端显示时要记得做转换。对应的实体类这样写public class Employee { private Integer id; private String name; private Integer gender; // 0女 1男避免和boolean的语义混淆 JsonFormat(pattern yyyy-MM-dd) private Date birthday; // 注意日期序列化后面联调会用到 private String phone; private Integer deptId; JsonFormat(pattern yyyy-MM-dd) private Date entryDate; private Integer status; private String deptName; // 冗余字段用于列表显示部门名称 // getter/setter 省略 }注意表里的是dept_idJava里是deptIdMyBatis默认驼峰映射。如果连接参数里没有配置mapUnderscoreToCamelCasetrue查出来dept_id赋值不到deptId上值是null。这个开关一般在mybatis-config.xml里打开属于新手最不容易发现的隐藏坑。3.2 分页查询的Service层设计为什么用PageHelper而不是手写limit很多项目里员工表也就几百上千行手写limit分页完全够用。可一旦排序条件、筛选条件一多每个方法都要重复算total、写count语句容易在SQL里拼出注入点。PageHelper的做法是在执行查询之前用拦截器把下一条SQL改写成带limit的查询并自动补一条count。SSM里集成的参数上一章已经见过property nameplugins array bean classcom.github.pagehelper.PageInterceptor property nameproperties valuehelperDialectmysql/value /property /bean /array /propertyService接口与实现public interface EmployeeService { PageInfoEmployee page(int pageNum, int pageSize, String keyword); Employee getById(Integer id); int add(Employee employee); int update(Employee employee); } Service public class EmployeeServiceImpl implements EmployeeService { Autowired private EmployeeMapper employeeMapper; Override Transactional(readOnly true) public PageInfoEmployee page(int pageNum, int pageSize, String keyword) { PageHelper.startPage(pageNum, pageSize); // 这之后的第一条查询会被PageInterceptor改写 ListEmployee list employeeMapper.selectByCondition(keyword); return new PageInfo(list); } }两个参数要说明白。pageNum是第几页从1开始不是0。pageSize是每页条数前端下拉里常见10、20、50。PageHelper有个坑startPage后面必须紧跟第一条Mapper查询中间不能插别的SQL否则拦截器会把无关查询改写成分页导致数据错乱。还有一种常见误用是页面传入pageSize0PageHelper会把0当成不分页然后返回全部数据接口响应时间突然变长排查时先看前端有没有把初始化值写对。PageInfo里封装了total、pages、list等属性Controller拿到后直接转JSON返回给前端。这样前端分页组件不需要自己做total计算。3.3 新增与更新前端字段名与后端对象的对齐CRUD里的C和U最常见的翻车点是前端提交的字段名和后端实体类对不上。比如前端表单写deptId后端对象叫dept_idSpringMVC在参数绑定时找不到对应setter员工新增后部门永远是null。下面是一个标准的新增接口写法Controller RequestMapping(/employee) public class EmployeeController { Autowired private EmployeeService employeeService; PostMapping(/add) ResponseBody public Result add(RequestBody Employee employee) { // 先做简单校验name为空和deptId非法直接拒绝 if (employee.getName() null || employee.getName().trim().isEmpty()) { return Result.error(姓名不能为空); } if (employee.getDeptId() null) { return Result.error(必须选择部门); } int rows employeeService.add(employee); return rows 0 ? Result.success() : Result.error(新增失败); } }用RequestBody时前端发的是JSON字段名必须与Java属性名一致。如果项目里习惯用表单提交就把RequestBody去掉改成form表单的key-value实体类同样能接收。两种方式不要混着用前后端联调时最常出现的415错误多半就是后端在等JSON、前端却用表单提交。前端对应的提交片段fetch(/ems/employee/add, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({ name: document.querySelector(#name).value, gender: parseInt(document.querySelector(#gender).value), birthday: document.querySelector(#birthday).value, phone: document.querySelector(#phone).value, deptId: parseInt(document.querySelector(#deptId).value) }) })birthday是date类型表单输入2024-05-01这种字符串SpringMVC需要配置日期转换器否则抛400。常见做法有两种实体字段加DateTimeFormat(pattern yyyy-MM-dd)或者在Controller里加InitBinder。前者更省事但注意它与JsonFormat的区别一个是接收参数时生效一个是返回JSON时生效两个都不要落下。更新操作和新增的区别在于必须传id。更新时前端一般把整行数据回显到表单改完再提交。后端update方法里要判断id是否为空不然MyBatis的update语句会把整张表都更新掉。SQL里习惯写成带条件update idupdateById update employee set if testname ! nullname #{name},/if if testphone ! nullphone #{phone},/if if testdeptId ! nulldept_id #{deptId},/if /set where id #{id} /update动态set的好处是前端只传改动过的字段也能更新其他字段保持原值。但有一个注意点如果前端把没改的字段也传成空字符串if testphone ! null仍然成立空字符串会被写进数据库。所以需要在前端提交前把空字符串转成null或者在后端单独做一次空串判断。这种细节写进配套文档里后面接手的人会感谢你。4. 前后端联调与SQL脚本五个必踩的坑和排查手法4.1 现象登录后刷新就丢session页面被拦回登录页点击登录跳转到主页一切正常。按F5刷新马上被拦回登录页。用浏览器看cookieJSESSIONID还在但每次刷新值都在变。原因前后端不在同一个端口或同一个上下文路径时Cookie的path不匹配。SSM项目如果用JSP渲染页面地址是/ems/index.jsp请求接口走/ems/employee/list通常没问题。但一旦把前端页面独立成另一个端口比如前端8081、后端8080浏览器不会把后端的JSESSIONID自动带给前端发起的跨域请求。解决先分清楚部署形态。SSM最省事的做法是前后端不分离JSP直接放WEB-INF所有请求同源Cookie自动生效。真要做前后端分离就统一用Token方案而不是依赖Session。若坚持用Session后端接口要配置允许跨域携带凭据前端fetch也要加credentials: include。这三个条件缺一个登录状态必丢。4.2 现象接口返回的员工生日变成一串数字列表接口返回的birthday字段是1700000000000这样的毫秒时间戳前端格式化后显示成2033年或直接空白。原因Jackson默认把java.util.Date序列化成时间戳。实体里只有DateTimeFormat没有JsonFormat导致接收参数时正常返回JSON时失真。解决最省事是在实体日期字段上加JsonFormat(pattern yyyy-MM-dd)。要是全项目日期格式统一就在spring-mvc.xml里配置一个全局的ObjectMappermvc:annotation-driven mvc:message-converters bean classorg.springframework.http.converter.json.MappingJackson2HttpMessageConverter property nameobjectMapper bean classcom.fasterxml.jackson.databind.ObjectMapper property namedateFormat bean classjava.text.SimpleDateFormat constructor-arg valueyyyy-MM-dd HH:mm:ss/ /bean /property /bean /property /bean /mvc:message-converters /mvc:annotation-driven全局配置和字段注解二选一即可两个都配时以字段注解优先。4.3 现象分页查询慢SQL与SQL注入索引失效比慢更危险员工表加了几条筛选条件后查询从几十毫秒变成几百毫秒。数据量其实只有几千行但explain一看type是ALL整表扫描。原因最典型的两种。一是对索引列用了函数比如where year(entry_date) 2024索引失效。二是前端传了排序字段后端直接用${order}拼进SQL排序字段没法用#{}预编译同时也成了SQL注入点。解决日期范围查询改成entry_date ? and entry_date ?的形式让索引生效。排序字段采用白名单校验String[] allowed {id, name, entry_date, dept_id}; if (!Arrays.asList(allowed).contains(sortField)) { sortField id; // 不在白名单里就回退默认排序 }这比任何参数过滤都直观。先看执行计划EXPLAIN SELECT * FROM employee WHERE name LIKE %张三%; -- 如果 typeALL说明这条查询在走全表扫描explain看到possible_keys有值但key为null基本就是where条件写法破坏了索引。另外MyBatis里能用#{}的地方不要用${}尤其在like模糊匹配时拼接%要放在参数里if testkeyword ! null and keyword ! and (name like concat(%, #{keyword}, %) or phone like concat(%, #{keyword}, %)) /if4.4 现象Tomcat部署前后端分离项目时页面404本地IDE里直接运行Tomcat一切正常打成war包丢进webapps后访问首页404或者页面出来了但css/js全是404。原因两件事最容易出问题。第一期望的访问路径是/ems但war包名不叫ems.warTomcat解压后的上下文路径和包名不一致。第二页面里的静态资源用了绝对路径/src部署到/ems下就解析到根目录去了。解决war包直接命名为ems.war或者启动时指定上下文路径。页面里的资源链接统一用${pageContext.request.contextPath}拼前缀link relstylesheet href${pageContext.request.contextPath}/static/css/main.css如果是前后端分离前端是一个独立静态项目部署时把它放到Tomcat的webapps/ems目录下后端API也部署在同一Tomcat里按/ems/api/**约定路径就不会有跨域和404双重问题。这是tomcat部署前后端分离项目最常见、也最不容易出幺蛾子的做法。4.5 现象SQL脚本导入中文乱码或字段对不上把配套的sql文件在Navicat或命令行里source导入表建好了但中文全是问号要么导入时报错字段太长、外键失败。原因SQL脚本文件本身的编码和数据库连接编码不一致。最常见的是.sql文件是UTF-8但连接参数没带characterEncodingutf8导入时被当成latin1处理字段长度问题则多是utf8mb4下varchar(20)存emoji或长部门名超出长度。解决数据库连接串统一带上参数jdbc.urljdbc:mysql://localhost:3306/ems?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse建表SQL文件第一行加上SET NAMES utf8mb4;导入后用SELECT name, HEX(name) FROM employee查一下中文正常就说明编码链路通了。外键导入失败时先检查两张表的字符集是否一致再检查外键字段类型是否完全一样int和bigint即使值相等建外键也会被MySQL拒掉。这些写完记得同步到配套文档因为换一台机器部署时会原样踩一遍。5. 部署到Tomcat的验证清单一个能拿去答辩或交接的收尾套路5.1 打包命令与部署路径到项目根目录执行mvn clean package确保target下产出ems.war。把war包复制到Tomcat的webapps目录启动bin/startup.sh或startup.bat。注意检查CATALINA_HOME配置Windows上很多人从这里开始翻车环境变量配了系统级JRE却找不到catalina。验证清单可以按这个顺序过一遍检查项验证动作预期结果启动日志看catalina.out无ClassNotFoundException、无端口占用上下文路径访问/ems/跳转到登录页登录会话登录后刷新仍保持登录状态CRUD新增、修改、删除各一次数据库对应数据变化分页第二页、每页10条total正确、无重复数据日期字段列表与详情接口返回yyyy-MM-dd注入测试搜索框输入 or 11无报错、无全量返回乱码新增一条中文员工库里显示正常5.2 交付前的一小时我一般会额外做两件事。把数据库导出一份干净的sql里面只留初始化数据和少量演示数据别把测试期间产生的垃圾数据一起交出去。再写一个README把Tomcat版本、JDK版本、数据库连接配置、默认账号密码、部署步骤这五项写全。配套文档不一定要多长但这五项缺一不可因为接手的同事或评委老师大概率不是写这套代码的人。这个小习惯帮我省了无数次怎么连不上库默认密码是什么的重复解释。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

破解‘千年完整代码’压缩包:归档抢救与可复现交付指南
破解‘千年完整代码’压缩包:归档抢救与可复现交付指南

简介:本资源是一份面向Delphi开发者的历史项目源码合集,聚焦于“千年”这一长期演进的软件系统,适用于代码考古、旧系统维护、Delphi组件学习及跨版本兼容性研究。压缩包共含数十个关键文件与目录,涵盖FastNet网络通信库&#xff… · 2026/9/26 12:06:16

Win10/Win11运行红警2闪退花屏黑屏修复全攻略:兼容性设置与DDraw补丁详解
Win10/Win11运行红警2闪退花屏黑屏修复全攻略:兼容性设置与DDraw补丁详解

1. 为什么经典红警在新系统上跑不起来 1.1 一个老玩家的真实困境 如果你最近翻出尘封已久的《红色警戒2:共和国之辉》,兴冲冲地装到Win10或者Win11上,结果双击图标之后要么黑屏几秒直接闪退,要么进去之后画面花得像电视机雪花&am… · 2026/9/26 12:06:09

【R329真机评测(三)】——Zhouyi-AIPU / Model_zoo/mobilenetv2 跑通后,用 TaoToken 统一 Key 管理多工具配置
【R329真机评测(三)】——Zhouyi-AIPU / Model_zoo/mobilenetv2 跑通后,用 TaoToken 统一 Key 管理多工具配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:06:08

服务设计与客户旅程地图:跨部门统一客户价值认知的实战方法
服务设计与客户旅程地图:跨部门统一客户价值认知的实战方法

1. 一场真实的跨部门会议:四个团队嘴里说着四种"客户价值"去年我在一家做企业服务的公司帮忙推进服务设计落地,第一次跨部门对齐会开了三个小时,最后市场总监和产品总监差点拍桌子。市场部坚持客户价值是"品牌感知和信任度&qu… · 2026/9/26 12:45:35

大屏可视化设计:信息优先级的三层模型与实战落地
大屏可视化设计:信息优先级的三层模型与实战落地

一块大屏真正上墙之后,很多人会发现一个残酷现实:数据都放上去了,图表也都做了,配色看着也不算差,可客户站在三米外看了半天,最后问了一句——这一屏到底先看哪里?做可视化大屏这行越久&#xf… · 2026/9/26 12:45:35

MindSpore Transformers 训练监控:TensorBoard 接入与调优实践
MindSpore Transformers 训练监控:TensorBoard 接入与调优实践

1. 为什么训练监控这件事值得单独拿出来聊搞深度学习训练的人都有一个共识:模型跑起来之后,最怕的不是报错,而是“静悄悄地烂掉”。Loss 不降、梯度爆炸、学习率调度出错、数据管道堵塞——这些问题不会让程序崩溃,但会让你白白烧… · 2026/9/26 12:45:35

彻底搞懂 MCP (Model Context Protocol):用 TaoToken 统一 Key 打通大模型“数据孤岛”
彻底搞懂 MCP (Model Context Protocol):用 TaoToken 统一 Key 打通大模型“数据孤岛”

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:45:23

你的企业可能正在“多付利息”:2026年贷款贴息政策自查指南
你的企业可能正在“多付利息”:2026年贷款贴息政策自查指南

“我们公司去年贷款3000万,一年利息一百多万。后来才知道,如果早三个月申请贴息,能省下近50万。” 这是一位制造业企业主的真实反馈。他不是个例。2026年,国家推出了多项中小微企业贷款贴息政策,但大量符合条件的企业因… · 2026/9/26 12:45:23

免费大纲生成到付费全文中间的能力差距,2026 年该怎么逐项补齐
免费大纲生成到付费全文中间的能力差距,2026 年该怎么逐项补齐

不少人是先摸到免费大纲生成这一步,才决定要不要继续往下付费的。60 秒拿到一份二至三级的章节骨架,图表、公式、代码该插在哪一段也先标好——这是大纲层给得出的东西。可骨架要变成正文,中间要补的是四类落到正文里的活:文献、成… · 2026/9/26 12:45:23

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码