RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/xin-lai/CodeSpirit

Cursor rule

.cursor/rules/js.mdc

CodeSpirit JavaScript 开发规范 - AMIS集成、模块模式、API请求、Token管理

Cursor rules

Quality

46/100

Scores the file, not the repository.

Length

1,243 words

29 headings · 20 code blocks

Repository

56

— · pushed 134 days ago

Last changed

3 days ago

First indexed 3 days ago.
xin-lai/CodeSpirit/.cursor/rules/js.mdcRawGitHub
1---
2description: CodeSpirit JavaScript 开发规范 - AMIS集成、模块模式、API请求、Token管理
3globs: *.js
4alwaysApply: false
5---
6 
7# JavaScript 开发规范
8 
9## 模块模式
10 
11### IIFE 包装
12 
13所有 JS 文件使用立即调用函数表达式(IIFE)包装,启用严格模式:
14 
15```javascript
16/**
17 * 模块说明
18 * @module ModuleName
19 */
20(function() {
21 'use strict';
22
23 // 模块代码
24
25 // 导出到全局
26 window.ModuleName = {
27 // 公共 API
28 };
29})();
30```
31 
32### 命名空间导出
33 
34全局对象使用 `window` 命名空间导出:
35 
36```javascript
37// ✅ 正确:使用 window 命名空间
38window.TokenManager = (function() {
39 'use strict';
40
41 function getToken() { /* ... */ }
42
43 return {
44 getToken,
45 setToken,
46 clearToken
47 };
48})();
49 
50// ✅ 正确:使用 CodeSpirit 命名空间
51window.CodeSpirit = window.CodeSpirit || {};
52window.CodeSpirit.i18n = {
53 t: function(key, params) { /* ... */ }
54};
55 
56// ✅ 正确:ES6 类导出
57class NotificationClient {
58 constructor(hubUrl = '/notification-hub') {
59 this.hubUrl = hubUrl;
60 }
61}
62window.NotificationClient = NotificationClient;
63```
64 
65## 文档注释规范
66 
67### 文件头注释
68 
69```javascript
70/**
71 * 考试系统API请求管理器
72 * 负责处理API地址转换和统一的请求处理
73 * @module ExamApiManager
74 * @version 2.0.0
75 * @author CodeSpirit Team
76 */
77```
78 
79### 函数注释(JSDoc)
80 
81```javascript
82/**
83 * 设置认证token
84 * @param {string} token - 访问token
85 * @param {number} [expiryInHours=24] - 过期时间(小时)
86 * @returns {void}
87 * @throws {Error} 当token为空时抛出错误
88 */
89function setToken(token, expiryInHours = 24) {
90 if (!token || typeof token !== 'string') {
91 throw new Error('Token must be a non-empty string');
92 }
93 // ...
94}
95 
96/**
97 * 统一的API请求函数
98 * @param {string} url - API路径
99 * @param {Object} [options={}] - fetch选项
100 * @returns {Promise<Object>} API响应数据
101 * @example
102 * const data = await ExamApiManager.request('/exam/api/questions', { method: 'GET' });
103 */
104async function request(url, options = {}) {
105 // ...
106}
107```
108 
109## AMIS 框架集成
110 
111### 主题配置
112 
113项目使用 **antd** 主题 [[memory:8912919]]:
114 
115```javascript
116// 初始化 AMIS
117let amisScoped = amis.embed('#root', amisJSON, {
118 location: history.location,
119 data: {},
120 context: {
121 WEB_HOST: webHost
122 }
123}, {
124 theme: 'antd' // 必须使用 antd 主题
125});
126```
127 
128### 事件系统
129 
130使用 `onEvent` 配置事件监听:
131 
132```javascript
133{
134 type: 'form',
135 api: '/identity/api/identity/auth/login',
136 onEvent: {
137 // 表单提交成功事件
138 submitSucc: {
139 actions: [
140 {
141 actionType: 'custom',
142 script: `
143 const token = event.data.token;
144 TokenManager.setToken(token, 24);
145 window.location.href = '/';
146 `
147 }
148 ]
149 },
150 // 数据初始化完成事件
151 fetchInited: {
152 actions: [
153 {
154 actionType: 'custom',
155 script: 'window.fetchUnreadNotificationCount();'
156 }
157 ]
158 }
159 }
160}
161```
162 
163### 行为类型
164 
165优先使用 AMIS 内置行为类型(actionType):
166 
167```javascript
168// ✅ 核心行为
169{ actionType: 'ajax', api: 'POST:/api/submit' }
170{ actionType: 'link', link: '/dashboard' }
171{ actionType: 'dialog', dialog: { /* ... */ } }
172{ actionType: 'reload', target: 'crud' }
173{ actionType: 'copy', content: '${text}' }
174 
175// ✅ 表单行为
176{ actionType: 'submit' }
177{ actionType: 'reset' }
178{ actionType: 'clear' }
179 
180// ✅ 自定义脚本(仅在必要时使用)
181{
182 actionType: 'custom',
183 script: `
184 const tenantId = event.data.tenantId;
185 window.location.href = '/' + tenantId + '/login';
186 `
187}
188```
189 
190### 请求适配器
191 
192使用 `requestAdaptor` 和 `adaptor` 处理请求和响应:
193 
194```javascript
195api: {
196 method: 'post',
197 url: '/identity/api/identity/auth/login',
198
199 // 请求适配器 - 添加认证头
200 requestAdaptor: function(api) {
201 const token = TokenManager.getToken();
202 api.headers = api.headers || {};
203 api.headers['Authorization'] = token ? 'Bearer ' + token : '';
204 api.headers['X-Forwarded-With'] = 'CodeSpirit';
205 api.headers['X-Tenant-Id'] = window.tenantId || 'system';
206 return api;
207 },
208
209 // 响应适配器 - 处理响应数据
210 adaptor: function(payload, response, api) {
211 if (response.status === 401) {
212 window.location.href = '/login';
213 return { msg: '登录过期!' };
214 }
215
216 if (payload.status === 0 && payload.data) {
217 TokenManager.setToken(payload.data.token, 24);
218 }
219
220 return payload;
221 }
222}
223```
224 
225## Token 管理
226 
227### TokenManager 使用
228 
229使用 `TokenManager` 统一管理认证状态:
230 
231```javascript
232// 初始化模式
233TokenManager.initSystemMode(); // 系统平台
234TokenManager.initTenantMode('tenant-id'); // 租户平台
235TokenManager.initClientMode('tenant-id', 'exam'); // 客户端平台
236 
237// Token 操作
238TokenManager.setToken('access-token', 24); // 设置 token(24小时过期)
239const token = TokenManager.getToken(); // 获取 token
240TokenManager.clearToken(); // 清除 token
241TokenManager.hasToken(); // 检查是否有 token
242TokenManager.isTokenExpired(); // 检查是否过期
243TokenManager.isAuthenticated(); // 检查是否已认证
244 
245// 扩展功能
246TokenManager.setTokenExtended(accessToken, refreshToken, expiresIn, tenantId);
247TokenManager.getRefreshToken();
248TokenManager.getAuthHeaders(); // 获取认证请求头
249TokenManager.setUserInfo(userInfo);
250TokenManager.getUserInfo();
251```
252 
253### 认证请求头
254 
255所有 API 请求必须携带认证头:
256 
257```javascript
258const headers = {
259 'Authorization': token ? 'Bearer ' + token : '',
260 'X-Forwarded-With': 'CodeSpirit',
261 'X-Tenant-Id': tenantId || 'system',
262 'Content-Type': 'application/json'
263};
264```
265 
266## API 请求规范
267 
268### 服务发现路径
269 
270API 路径必须附带服务短名:
271 
272```javascript
273// ✅ 正确:附带服务名
274'/identity/api/identity/profile'
275'/exam/api/exam/questions'
276'/messaging/api/messaging/messages/my/list'
277'/survey/api/surveys/${surveyId}'
278 
279// ❌ 错误:缺少服务名
280'/api/identity/profile'
281'/api/questions'
282```
283 
284### API 管理器模式
285 
286使用统一的 API 管理器处理请求:
287 
288```javascript
289/**
290 * API管理器
291 */
292window.ExamApiManager = {
293 /**
294 * 统一的API请求函数
295 * @param {string} url - API路径
296 * @param {Object} options - fetch选项
297 * @returns {Promise} API响应数据
298 */
299 request: async function(url, options = {}) {
300 const token = window.TokenManager?.getToken();
301
302 const requestConfig = {
303 ...options,
304 headers: {
305 'Authorization': token ? 'Bearer ' + token : '',
306 'X-Tenant-Id': window.tenantId,
307 'X-Forwarded-With': 'CodeSpirit',
308 'Content-Type': 'application/json',
309 ...options.headers
310 }
311 };
312 
313 const response = await fetch(url, requestConfig);
314
315 // 处理认证失败
316 if (response.status === 401) {
317 window.location.href = '/login';
318 throw new Error('认证失败,请重新登录');
319 }
320
321 if (!response.ok) {
322 throw new Error(`HTTP ${response.status}: ${response.statusText}`);
323 }
324
325 const result = await response.json();
326
327 if (result.status !== undefined && result.status !== 0) {
328 throw new Error(result.msg || '请求失败');
329 }
330
331 return result.data || result;
332 },
333 
334 get: function(url, options = {}) {
335 return this.request(url, { ...options, method: 'GET' });
336 },
337 
338 post: function(url, data = null, options = {}) {
339 return this.request(url, {
340 ...options,
341 method: 'POST',
342 body: data ? JSON.stringify(data) : undefined
343 });
344 }
345};
346```
347 
348## 缓存管理
349 
350### 缓存键命名
351 
352使用租户隔离的缓存键:
353 
354```javascript
355// 格式:{module}_cache_{tenantId}_{key}
356const cacheKey = `exam_cache_${tenantId}_login_config`;
357const cacheKey = `survey_cache_${tenantId}_form_data`;
358```
359 
360### 缓存工具类
361 
362```javascript
363const CacheManager = {
364 /**
365 * 获取缓存数据
366 * @param {string} key - 缓存key
367 * @param {string} tenantId - 租户ID
368 * @returns {Object|null} 缓存的数据
369 */
370 get: function(key, tenantId) {
371 try {
372 const cacheKey = `exam_cache_${tenantId}_${key}`;
373 const cached = sessionStorage.getItem(cacheKey);
374 if (!cached) return null;
375 
376 const data = JSON.parse(cached);
377
378 // 检查是否过期
379 if (data.expiry && Date.now() > data.expiry) {
380 sessionStorage.removeItem(cacheKey);
381 return null;
382 }
383
384 return data.value;
385 } catch (error) {
386 console.error('[缓存读取失败]', error);
387 return null;
388 }
389 },
390 
391 /**
392 * 设置缓存数据
393 * @param {string} key - 缓存key
394 * @param {string} tenantId - 租户ID
395 * @param {Object} value - 要缓存的数据
396 * @param {number} ttl - 过期时间(毫秒)
397 */
398 set: function(key, tenantId, value, ttl = 30 * 60 * 1000) {
399 try {
400 const cacheKey = `exam_cache_${tenantId}_${key}`;
401 const data = {
402 value: value,
403 expiry: ttl ? Date.now() + ttl : null
404 };
405 sessionStorage.setItem(cacheKey, JSON.stringify(data));
406 } catch (error) {
407 console.error('[缓存写入失败]', error);
408 }
409 }
410};
411```
412 
413## 国际化
414 
415使用 `CodeSpirit.i18n` 进行翻译:
416 
417```javascript
418// 初始化(服务器端调用)
419window.CodeSpirit.i18n.init('zh-CN', {
420 'Login.Title': '用户登录',
421 'Login.Success': '登录成功,欢迎 {userName}!'
422});
423 
424// 获取翻译文本
425const title = CodeSpirit.i18n.t('Login.Title');
426const message = CodeSpirit.i18n.t('Login.Success', { userName: 'John' });
427 
428// 切换语言
429CodeSpirit.i18n.switchLanguage('en');
430```
431 
432## 类定义规范
433 
434使用 ES6 class 语法:
435 
436```javascript
437/**
438 * 通知客户端
439 * 提供与通知服务的连接和消息处理功能
440 */
441class NotificationClient {
442 /**
443 * @param {string} hubUrl - SignalR Hub URL
444 */
445 constructor(hubUrl = '/notification-hub') {
446 this.hubUrl = hubUrl;
447 this.connection = null;
448 this.handlers = new Map();
449 }
450 
451 /**
452 * 连接到通知服务
453 * @returns {Promise} 连接Promise
454 */
455 async connect() {
456 this.connection = new signalR.HubConnectionBuilder()
457 .withUrl(this.hubUrl)
458 .withAutomaticReconnect()
459 .build();
460 
461 await this.connection.start();
462 console.log('通知连接已建立');
463 }
464 
465 /**
466 * 注册消息处理器
467 * @param {string} topic - 主题名称
468 * @param {string} type - 消息类型
469 * @param {Function} handler - 处理函数
470 */
471 on(topic, type, handler) {
472 const key = `${topic}:${type}`;
473 if (!this.handlers.has(key)) {
474 this.handlers.set(key, []);
475 }
476 this.handlers.get(key).push(handler);
477 }
478}
479 
480window.NotificationClient = NotificationClient;
481```
482 
483## 代码质量要求
484 
485### 函数长度限制
486 
487一个函数不超过 30 行代码,复杂逻辑拆分为多个小函数:
488 
489```javascript
490// ✅ 正确:拆分为多个小函数
491function handleLoginSuccess(payload) {
492 saveToken(payload.data.token);
493 redirectToTarget();
494}
495 
496function saveToken(token) {
497 TokenManager.setToken(token, 24);
498}
499 
500function redirectToTarget() {
501 const redirectUrl = getRedirectUrl();
502 if (isValidRedirect(redirectUrl)) {
503 window.location.href = redirectUrl;
504 } else {
505 window.location.href = '/';
506 }
507}
508```
509 
510### 样式分离
511 
512样式写入独立的 CSS 文件,不在 JS 中内联样式:
513 
514```javascript
515// ✅ 正确:使用 CSS 类名
516element.className = 'survey-container loading';
517 
518// ❌ 避免:内联样式
519element.style.backgroundColor = '#fff';
520element.style.padding = '20px';
521```
522 
523### 响应式支持
524 
525界面需要支持响应式布局和移动端适配:
526 
527```javascript
528// AMIS 配置中使用响应式断点
529{
530 type: 'grid',
531 columns: [
532 {
533 xs: 12, // 手机:全宽
534 sm: 6, // 平板:半宽
535 md: 4, // 桌面:三分之一
536 lg: 3, // 大屏:四分之一
537 body: { /* ... */ }
538 }
539 ]
540}
541```
542 
543## 禁止事项
544 
545```javascript
546// ❌ 禁止:自定义 DOM 事件(使用 AMIS 事件系统)
547document.getElementById('btn').addEventListener('click', handler);
548 
549// ❌ 禁止:直接操作 DOM(除非必要)
550document.getElementById('content').innerHTML = html;
551 
552// ❌ 禁止:使用 var 声明变量
553var token = getToken();
554 
555// ❌ 禁止:缺少错误处理
556const response = await fetch(url);
557const data = await response.json();
558 
559// ❌ 禁止:硬编码敏感信息
560const apiKey = 'sk-xxxxxxxx';
561```
562 
563## AMIS 官方文档
564 
565- 📖 组件文档:https://aisuda.bce.baidu.com/amis/zh-CN/docs/index
566- 🎨 事件系统:https://aisuda.bce.baidu.com/amis/zh-CN/components/action#%E4%BA%8B%E4%BB%B6%E8%A1%A8
567- 🔘 行为按钮:https://aisuda.bce.baidu.com/amis/zh-CN/components/action
568- 📝 表单组件:https://aisuda.bce.baidu.com/amis/zh-CN/components/form/index
569 

Sections

  • JavaScript 开发规范
  • 模块模式
  • IIFE 包装
  • 命名空间导出
  • 文档注释规范
  • 文件头注释
  • 函数注释(JSDoc)
  • AMIS 框架集成
  • 主题配置
  • 事件系统
  • 行为类型
  • 请求适配器
  • Token 管理
  • TokenManager 使用
  • 认证请求头
  • API 请求规范
  • 服务发现路径
  • API 管理器模式
  • 缓存管理
  • 缓存键命名
  • 缓存工具类
  • 国际化
  • 类定义规范
  • 代码质量要求
  • 函数长度限制
  • 样式分离
  • 响应式支持
  • 禁止事项
  • AMIS 官方文档

What it covers

apidocs

Stack — with the evidence

csharp

(1.00)

react

(0.70)

typescript

(0.60)

dotnet

(0.60)

kubernetes

(0.60)

github-actions

(0.60)

javascript

(0.50)

Glob targeting

  • *.js

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
xin-lai
Language
—
License
—
Archived
no

All configs in this repo

Also in xin-lai/CodeSpirit

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
xin-lai/CodeSpirit.cursor/rules/ai-development.mdc · 56Cursor rulescsharpreact+5api46/1003 days ago
xin-lai/CodeSpirit.cursor/rules/all.mdc · 56Cursor rulescsharpreact+5testing-strategyapi50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/amis-cards.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/api-design.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/controller.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/cs.mdc · 56Cursor rulescsharpreact+5no sections25/1003 days ago
xin-lai/CodeSpirit.cursor/rules/csproj.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/css.mdc · 56Cursor rulescsharpreact+5ui54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/database.mdc · 56Cursor rulescsharpreact+5no sections74/1003 days ago
xin-lai/CodeSpirit.cursor/rules/dependency-injection.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/dto.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/enum.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/i18n.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/naming-conventions.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/package-management.mdc · 56Cursor rulescsharpreact+5no sections74/1003 days ago
xin-lai/CodeSpirit.cursor/rules/performance.mdc · 56Cursor rulescsharpreact+5no sections54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/project-structure.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/security.mdc · 56Cursor rulescsharpreact+5database54/1003 days ago
xin-lai/CodeSpirit.cursor/rules/service.mdc · 56Cursor rulescsharpreact+5no sections50/1003 days ago
xin-lai/CodeSpirit.cursor/rules/startup-framework.mdc · 56Cursor rulescsharpreact+5api54/1003 days ago
Diff against .cursor/rules/ai-development.mdc Diff against .cursor/rules/all.mdc Diff against .cursor/rules/amis-cards.mdc Diff against .cursor/rules/api-design.mdc Diff against .cursor/rules/controller.mdc Diff against .cursor/rules/cs.mdc Diff against .cursor/rules/csproj.mdc Diff against .cursor/rules/css.mdc Diff against .cursor/rules/database.mdc Diff against .cursor/rules/dependency-injection.mdc Diff against .cursor/rules/dto.mdc Diff against .cursor/rules/enum.mdc Diff against .cursor/rules/i18n.mdc Diff against .cursor/rules/naming-conventions.mdc Diff against .cursor/rules/package-management.mdc Diff against .cursor/rules/performance.mdc Diff against .cursor/rules/project-structure.mdc Diff against .cursor/rules/security.mdc Diff against .cursor/rules/service.mdc Diff against .cursor/rules/startup-framework.mdc

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack