with one click
domestic-stack
写 uniapp / 微信小程序 / SpringBoot 代码时使用。贴合国内主流技术栈的实战规范。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
写 uniapp / 微信小程序 / SpringBoot 代码时使用。贴合国内主流技术栈的实战规范。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | domestic-stack |
| description | 写 uniapp / 微信小程序 / SpringBoot 代码时使用。贴合国内主流技术栈的实战规范。 |
| category | china |
| tags | ["uniapp","小程序","springboot"] |
规则: 微信小程序和 uniapp 运行在专属运行时,没有 window、document、localStorage 等 DOM/BOM 对象;setData 是性能敏感操作,频繁调用或传大对象会直接卡顿;整包 + 分包体积有硬性上限(主包 2 MB,总包 20 MB)。
为什么: AI 训练数据以 web 代码为主,极容易写出 document.querySelector、window.location.href、localStorage.setItem 这类在小程序里直接报 ReferenceError 的代码。对 setData 的误用更隐蔽:AI 常常在循环里每次更新一个字段就调用一次 setData,或者把整个巨型列表塞进去,运行时帧率立刻掉到个位数。
怎么做:
wx.setStorageSync / uni.setStorageSync,路由用 wx.navigateTo / uni.navigateTo,DOM 操作改用数据绑定驱动视图。setData,用 path 精确更新而非替换整个对象(见正例)。规则: uniapp 跨 APP / 微信小程序 / H5 时,平台差异必须用 #ifdef APP-PLUS / #ifdef MP-WEIXIN / #ifdef H5 等条件编译块处理,不写死只在单端能跑的逻辑。
为什么: AI 在生成 uniapp 代码时经常直接调用 wx.* API 而不加条件编译,在 APP 端或 H5 端运行时这些调用会静默失败或抛异常。反过来也会犯:只写了 plus.* 的 APP 专属逻辑,发布 H5 版时整块功能缺失。这类 bug 在单端开发阶段完全看不出来,到多端上线时才暴露。
怎么做:
/* #ifdef MP-WEIXIN */ 包裹对应 CSS。规则: 微信登录必须走 wx.login 获取 code,再由后端调用 code2session 换取 openid 和 session_key;openid 和 session_key 不得存在前端,不得绕过授权步骤直接用 union_id 或手机号作为身份标识。
为什么: AI 经常写出把 session_key 存进 wx.setStorageSync 的代码——这违反微信安全规范,session_key 会失效且不能直接暴露给客户端。还有一种常见错误:前端直接拿 getUserInfo 返回的 openid(旧接口早已废弃)当登录凭证,绕过后端校验,既不安全也不符合现行微信能力。
怎么做:
wx.login → 拿到 code → 发给自己后端。code2session 接口,换回 openid / session_key,生成自己的登录态 token 返回前端。getPhoneNumber 组件 + 后端解密,不走已废弃的 getUserInfo。规则: Controller 只做参数接收与响应封装,业务逻辑全部下沉到 Service,数据库操作放 Mapper / Repository;统一异常处理用 @ControllerAdvice,参数校验用 @Valid + ConstraintValidator,不在 Controller 里写业务代码。
为什么: AI 写 SpringBoot 时极其容易把业务逻辑堆在 Controller 里——直接在 @GetMapping 方法里查库、算价格、拼 SQL——表面上能跑,但单元测试无法覆盖(Controller 层的业务很难 mock),复用性为零,后续需求一变就到处改。参数校验也常被忽略,AI 会直接用 if (name == null) 手写 if-else,而不是用注解在入口统一拦截。
怎么做:
ResponseEntity / 统一 Result<T>)。@NotNull、@Size、@Pattern 等注解 + @Valid,统一在 @ControllerAdvice 里捕获 MethodArgumentNotValidException。RuntimeException,在 @ControllerAdvice 里集中处理,返回标准错误格式。规则: 国内上线项目必须具备 ICP 备案、隐私政策、必要的数据合规措辞;npm 依赖用淘宝镜像(registry.npmmirror.com),Maven 依赖用阿里云镜像(maven.aliyun.com);静态资源走国内 CDN,不直接引用境外 CDN 地址。
为什么: AI 生成的项目配置默认指向境外镜像(registry.npmjs.org、repo.maven.apache.org),在国内 CI/CD 环境里拉包极慢甚至超时,导致构建失败。更严重的是 AI 生成的 HTML 模板常常引用 cdn.jsdelivr.net 或 unpkg.com,这些域名在国内访问不稳定,直接造成生产页面资源加载失败。隐私合规方面,AI 不会自动提醒你"需要 ICP 备案"或"用户协议需要说明数据收集范围",这些遗漏可能导致应用被下架。
怎么做:
.npmrc 或 package.json 的 publishConfig 指向淘宝镜像;settings.xml 的 <mirror> 指向阿里云。// 反例 — 每次只改一个字段,却替换整个列表对象,触发全量 diff + 全量渲染
Page({
data: {
list: [
{ id: 1, name: '商品A', count: 0 },
{ id: 2, name: '商品B', count: 0 },
]
},
addCount(index) {
const list = this.data.list
list[index].count += 1
this.setData({ list }) // ❌ 传整个数组,无论列表多大都全量更新
}
})
// 正例 — 用 path 语法精确更新变化的字段,渲染开销最小
Page({
data: {
list: [
{ id: 1, name: '商品A', count: 0 },
{ id: 2, name: '商品B', count: 0 },
]
},
addCount(index) {
const key = `list[${index}].count`
this.setData({
[key]: this.data.list[index].count + 1 // ✅ 只更新变化的路径,性能最优
})
}
})
// 反例 — 直接调用 wx.* API,APP 端和 H5 端运行时报错
export function saveToken(token) {
wx.setStorageSync('token', token) // ❌ APP 端没有 wx 对象,直接 ReferenceError
}
// 正例 — 用 uni.* 统一 API + 条件编译处理真正有差异的部分
export function saveToken(token) {
uni.setStorageSync('token', token) // ✅ uni.* 在所有端均可用
// #ifdef APP-PLUS
// APP 端额外写入原生 keychain(示例)
plus.storage.setItem('token', token)
// #endif
}
// 反例 — Controller 直接查库、写业务、手写 if-else 校验,什么都往里塞
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderMapper orderMapper;
@PostMapping("/create")
public Map<String, Object> createOrder(@RequestBody Map<String, Object> body) {
// ❌ 参数校验手写 if-else
if (body.get("userId") == null || body.get("amount") == null) {
return Map.of("code", 400, "msg", "参数缺失");
}
// ❌ 业务逻辑直接在 Controller 里算
double amount = Double.parseDouble(body.get("amount").toString());
if (amount <= 0) {
return Map.of("code", 400, "msg", "金额非法");
}
// ❌ 直接调 Mapper,绕过 Service 层
orderMapper.insert(body.get("userId"), amount);
return Map.of("code", 200, "msg", "创建成功");
}
}
// 正例 — Controller 只接参/返响应;业务在 Service;校验用注解统一处理
// DTO:用注解声明校验规则
public class CreateOrderRequest {
@NotNull(message = "userId 不能为空")
private Long userId;
@Positive(message = "金额必须大于 0")
private Double amount;
// getter / setter 省略
}
// Controller:只负责接参、调 Service、封装响应
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/create")
public Result<Long> createOrder(@Valid @RequestBody CreateOrderRequest req) {
// ✅ 校验由 @Valid 在入口统一拦截,Controller 无需 if-else
Long orderId = orderService.createOrder(req);
return Result.ok(orderId);
}
}
// Service:业务逻辑全在这里
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public Long createOrder(CreateOrderRequest req) {
// ✅ 业务逻辑集中,可独立单测
Order order = new Order(req.getUserId(), req.getAmount());
orderMapper.insert(order);
return order.getId();
}
}
// 全局异常处理:统一捕获校验异常,返回标准格式
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidation(MethodArgumentNotValidException ex) {
String msg = ex.getBindingResult().getFieldErrors()
.stream().map(FieldError::getDefaultMessage)
.collect(Collectors.joining("; "));
return Result.fail(400, msg); // ✅ 统一错误格式,前端好处理
}
}
window、document、localStorage——已换成小程序/uniapp 对应的 API。setData 调用都经过合并,且使用 path 语法只更新变化的字段,没有在循环里多次调用。#ifdef 条件编译包裹,没有写死单端 API。@ControllerAdvice 统一处理,没有散落的手写 if-else 校验。package.json / settings.xml 已配置国内镜像源,前端资源没有引用境外 CDN 链接。