next-admin-svr 0.1.49 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -8,6 +8,7 @@ var mongodb = require('mongodb');
8
8
  var shared = require('@plugin-light/shared');
9
9
  var Fontmin = require('fontmin');
10
10
  var multer = require('multer');
11
+ var minimatch = require('minimatch');
11
12
  var crypto = require('@wecom/crypto');
12
13
  var agentSdk = require('@tencent-ai/agent-sdk');
13
14
  var croner = require('croner');
@@ -18,6 +19,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
18
19
  var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
19
20
  var Fontmin__default = /*#__PURE__*/_interopDefaultLegacy(Fontmin);
20
21
  var multer__default = /*#__PURE__*/_interopDefaultLegacy(multer);
22
+ var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
21
23
  var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto$1);
22
24
 
23
25
  const defaultModule = {
@@ -33,7 +35,9 @@ const defaultModule = {
33
35
  aggregate: () => Promise.resolve([]),
34
36
  },
35
37
  landun: {
38
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
36
39
  startPipeline: () => Promise.resolve({}),
40
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37
41
  startPipelineByRawApi: () => Promise.resolve({}),
38
42
  },
39
43
  auth: {
@@ -1319,6 +1323,7 @@ router$7.post('/mcp-upload', uploadWithSlice.single('file'), async (req, res) =>
1319
1323
  console.log('[mcp-upload] req.body', req.body);
1320
1324
  const parsedDir = getUploadDir(dir, cdn);
1321
1325
  const staffName = (req.header('rid') || 'developer');
1326
+ const toolName = (req.header('x-mcp-tool-name') || '');
1322
1327
  const newFileKey = `${parsedDir}/${qiniuKey}`;
1323
1328
  if (!cdn) {
1324
1329
  res.send({ r: -1, msg: '缺少 cdn 参数' });
@@ -1404,6 +1409,7 @@ router$7.post('/mcp-upload', uploadWithSlice.single('file'), async (req, res) =>
1404
1409
  mcpDB,
1405
1410
  mcpName,
1406
1411
  mcpVersion,
1412
+ toolName,
1407
1413
  imageDB,
1408
1414
  operationTool: coreModule.get().operation,
1409
1415
  });
@@ -1425,10 +1431,19 @@ router$6.post('/start-publish', async (req, res) => {
1425
1431
  }
1426
1432
  }
1427
1433
  const staffName = (req.header('rid') || 'developer');
1434
+ const toolName = (req.header('x-mcp-tool-name') || '');
1428
1435
  const { mcpName, mcpVersion, repo, branch, publishReason, subProjectName, } = req.body;
1436
+ if (!repo || !branch) {
1437
+ res.json({
1438
+ r: -1,
1439
+ code: -1,
1440
+ msg: '缺少必要参数: repo 和 branch 是必填项',
1441
+ });
1442
+ return;
1443
+ }
1429
1444
  const result = await shared.startMpCIPipeline({
1430
1445
  repo,
1431
- subProject: subProjectName,
1446
+ subProject: subProjectName || '',
1432
1447
  branch,
1433
1448
  staffName,
1434
1449
  isWeixin: true,
@@ -1437,8 +1452,46 @@ router$6.post('/start-publish', async (req, res) => {
1437
1452
  mcpVersion,
1438
1453
  operationTool: coreModule.get().operation,
1439
1454
  startPipeline: coreModule.get().landun.startPipeline,
1455
+ mcpDB: coreModule.get().mcpDB,
1456
+ toolName,
1440
1457
  });
1441
- res.send(result);
1458
+ // 获取审批人信息
1459
+ let auditorInfo = { auditor: '', shouldAudit: false };
1460
+ try {
1461
+ auditorInfo = await tComm.getAuditor({
1462
+ type: 'rainbow',
1463
+ configSource: async () => {
1464
+ const res = await tComm.fetchRainbowConfig('h5_publish_auditor', {
1465
+ appId: process.env.RAINBOW_APP_ID,
1466
+ userId: process.env.RAINBOW_USER_ID,
1467
+ secretKey: process.env.RAINBOW_SECRET_KEY,
1468
+ envName: 'Default',
1469
+ groupName: 'devops_open',
1470
+ }, {
1471
+ sdk: shared.getRainbowNodeSdk(),
1472
+ tryJsonParse: true,
1473
+ });
1474
+ console.log('auditor', res);
1475
+ return res;
1476
+ },
1477
+ rainbowOptions: {
1478
+ projectName: shared.extractRepoPath(repo),
1479
+ subProjectName: subProjectName || '',
1480
+ // @ts-ignore
1481
+ minimatch: minimatch__default["default"],
1482
+ },
1483
+ skipAudit: branch !== 'release',
1484
+ });
1485
+ }
1486
+ catch (e) {
1487
+ console.error('[MP Publish MCP] 获取审批人失败:', e);
1488
+ }
1489
+ // 在返回结果中追加审批人信息
1490
+ if (result.result && typeof result.result === 'object') {
1491
+ result.result.auditor = auditorInfo.auditor;
1492
+ result.result.shouldAudit = auditorInfo.shouldAudit;
1493
+ }
1494
+ res.json(result);
1442
1495
  });
1443
1496
 
1444
1497
  const router$5 = express__default["default"].Router();
@@ -1470,6 +1523,7 @@ router$4.post('/mcp-start', async (req, res) => {
1470
1523
  }
1471
1524
  }
1472
1525
  const staffName = (req.header('rid') || 'developer');
1526
+ const toolName = (req.header('x-mcp-tool-name') || '');
1473
1527
  const { mcpName, mcpVersion, repo, branch, publishReason, versionType, publishExternalNPM, publishPackage, } = req.body;
1474
1528
  console.log('[mcp-start]', {
1475
1529
  mcpName,
@@ -1503,7 +1557,42 @@ router$4.post('/mcp-start', async (req, res) => {
1503
1557
  mcpName,
1504
1558
  mcpVersion,
1505
1559
  operationTool: coreModule.get().operation,
1560
+ toolName,
1506
1561
  });
1562
+ // 获取审批人信息
1563
+ let auditorInfo = { auditor: '', shouldAudit: false };
1564
+ try {
1565
+ auditorInfo = await tComm.getAuditor({
1566
+ type: 'json',
1567
+ configSource: async () => {
1568
+ const res = await tComm.fetchRainbowConfig('library_publish_auditor', {
1569
+ appId: process.env.RAINBOW_APP_ID,
1570
+ userId: process.env.RAINBOW_USER_ID,
1571
+ secretKey: process.env.RAINBOW_SECRET_KEY,
1572
+ envName: 'Default',
1573
+ groupName: 'devops_open',
1574
+ }, {
1575
+ sdk: shared.getRainbowNodeSdk(),
1576
+ tryJsonParse: true,
1577
+ });
1578
+ console.log('auditor', res);
1579
+ return res;
1580
+ },
1581
+ jsonOptions: {
1582
+ projectName: shared.extractRepoPath(component.git),
1583
+ key: versionType,
1584
+ },
1585
+ });
1586
+ }
1587
+ catch (e) {
1588
+ console.error('[Pipeline Open] 获取审批人失败:', e);
1589
+ }
1590
+ console.log('[auditorInfo]', auditorInfo, component, versionType);
1591
+ // 在返回结果中追加审批人信息
1592
+ if (result?.result?.data && typeof result?.result?.data === 'object') {
1593
+ (result?.result?.data).auditor = auditorInfo.auditor;
1594
+ (result?.result?.data).shouldAudit = auditorInfo.shouldAudit;
1595
+ }
1507
1596
  res.send(result);
1508
1597
  });
1509
1598
 
@@ -2678,7 +2767,7 @@ async function updateWhiteUserStatus({ status = false, pipelineRunId = '', }) {
2678
2767
 
2679
2768
  const CRON_TIME = '0 */10 * * * *';
2680
2769
  function createUpdateWhiteUserCosCron() {
2681
- if (process.env.NODE_ENV === 'development') {
2770
+ if (process.env.NODE_ENV === 'development' || process.platform !== 'linux') {
2682
2771
  return;
2683
2772
  }
2684
2773
  try {
@@ -2944,9 +3033,19 @@ async function notifyRobot(entry, iwikiUrl, robotNotifyConfig) {
2944
3033
  console.warn('[EmailSync] 未配置机器人 webhookUrl,跳过通知');
2945
3034
  return;
2946
3035
  }
2947
- const contentPreview = entry.content.length > 200
2948
- ? `${entry.content.slice(0, 200)}...`
2949
- : entry.content;
3036
+ // 清理 HTML 标签,避免未闭合标签(如 <style、<table 等)破坏企微 Markdown 渲染
3037
+ const plainContent = entry.content
3038
+ .replace(/<style[\s\S]*?<\/style>/gi, '') // 移除完整的 <style> 块
3039
+ .replace(/<script[\s\S]*?<\/script>/gi, '') // 移除完整的 <script> 块
3040
+ .replace(/<[^>]*>/g, '') // 移除所有 HTML 标签
3041
+ .replace(/&nbsp;/g, ' ') // 替换常见 HTML 实体
3042
+ .replace(/&lt;/g, '<')
3043
+ .replace(/&gt;/g, '>')
3044
+ .replace(/&amp;/g, '&')
3045
+ .trim();
3046
+ const contentPreview = plainContent.length > 200
3047
+ ? `${plainContent.slice(0, 200)}...`
3048
+ : plainContent;
2950
3049
  const message = [
2951
3050
  '📬 **邮件知识已同步到 iwiki**',
2952
3051
  '',
package/lib/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import express from 'express';
2
- import { timeStampFormat, batchSendWxRobotMarkdown, uploadCOSStreamFile, purgeUrlCache, uploadCOSStreamFileV2, uploadCOSFile, createIwikiDoc, saveJsonToLog } from 't-comm';
2
+ import { timeStampFormat, batchSendWxRobotMarkdown, uploadCOSStreamFile, purgeUrlCache, uploadCOSStreamFileV2, uploadCOSFile, getAuditor, fetchRainbowConfig, createIwikiDoc, saveJsonToLog } from 't-comm';
3
3
  import { ObjectId } from 'mongodb';
4
- import { getUploadCosConfig, createFontProjectOrUpdate, cosSyncToGit, FONT_PROJECT_WEBHOOK_URL, getOneCdnUrl, getPushUrlCacheArea, createIconProjectOrUpdate, ICON_PROJECT_PIPELINE_CONFIG, ICON_PROJECT_WEBHOOK_URL, parseImage, getUploadImageFilePath, uploadFilesCore, compressFileUseTinypng, startMpCIPipeline, startNPMPublishPipelineCore, getComponentByRepo, getWhiteRainbowConfig, WHITE_USER_PIPELINE_ID, WHITE_USER_STATUS_MAP, getWhiteTypeDesc, updateWhiteUserCosByDb, watchEmails, toCdnUrl } from '@plugin-light/shared';
4
+ import { getUploadCosConfig, createFontProjectOrUpdate, cosSyncToGit, FONT_PROJECT_WEBHOOK_URL, getOneCdnUrl, getPushUrlCacheArea, createIconProjectOrUpdate, ICON_PROJECT_PIPELINE_CONFIG, ICON_PROJECT_WEBHOOK_URL, parseImage, getUploadImageFilePath, uploadFilesCore, compressFileUseTinypng, startMpCIPipeline, getRainbowNodeSdk, extractRepoPath, startNPMPublishPipelineCore, getComponentByRepo, getWhiteRainbowConfig, WHITE_USER_PIPELINE_ID, WHITE_USER_STATUS_MAP, getWhiteTypeDesc, updateWhiteUserCosByDb, watchEmails, toCdnUrl } from '@plugin-light/shared';
5
5
  import Fontmin from 'fontmin';
6
6
  import multer from 'multer';
7
+ import minimatch from 'minimatch';
7
8
  import { decrypt } from '@wecom/crypto';
8
9
  import { query } from '@tencent-ai/agent-sdk';
9
10
  import { Cron } from 'croner';
@@ -22,7 +23,9 @@ const defaultModule = {
22
23
  aggregate: () => Promise.resolve([]),
23
24
  },
24
25
  landun: {
26
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
25
27
  startPipeline: () => Promise.resolve({}),
28
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
29
  startPipelineByRawApi: () => Promise.resolve({}),
27
30
  },
28
31
  auth: {
@@ -1308,6 +1311,7 @@ router$7.post('/mcp-upload', uploadWithSlice.single('file'), async (req, res) =>
1308
1311
  console.log('[mcp-upload] req.body', req.body);
1309
1312
  const parsedDir = getUploadDir(dir, cdn);
1310
1313
  const staffName = (req.header('rid') || 'developer');
1314
+ const toolName = (req.header('x-mcp-tool-name') || '');
1311
1315
  const newFileKey = `${parsedDir}/${qiniuKey}`;
1312
1316
  if (!cdn) {
1313
1317
  res.send({ r: -1, msg: '缺少 cdn 参数' });
@@ -1393,6 +1397,7 @@ router$7.post('/mcp-upload', uploadWithSlice.single('file'), async (req, res) =>
1393
1397
  mcpDB,
1394
1398
  mcpName,
1395
1399
  mcpVersion,
1400
+ toolName,
1396
1401
  imageDB,
1397
1402
  operationTool: coreModule.get().operation,
1398
1403
  });
@@ -1414,10 +1419,19 @@ router$6.post('/start-publish', async (req, res) => {
1414
1419
  }
1415
1420
  }
1416
1421
  const staffName = (req.header('rid') || 'developer');
1422
+ const toolName = (req.header('x-mcp-tool-name') || '');
1417
1423
  const { mcpName, mcpVersion, repo, branch, publishReason, subProjectName, } = req.body;
1424
+ if (!repo || !branch) {
1425
+ res.json({
1426
+ r: -1,
1427
+ code: -1,
1428
+ msg: '缺少必要参数: repo 和 branch 是必填项',
1429
+ });
1430
+ return;
1431
+ }
1418
1432
  const result = await startMpCIPipeline({
1419
1433
  repo,
1420
- subProject: subProjectName,
1434
+ subProject: subProjectName || '',
1421
1435
  branch,
1422
1436
  staffName,
1423
1437
  isWeixin: true,
@@ -1426,8 +1440,46 @@ router$6.post('/start-publish', async (req, res) => {
1426
1440
  mcpVersion,
1427
1441
  operationTool: coreModule.get().operation,
1428
1442
  startPipeline: coreModule.get().landun.startPipeline,
1443
+ mcpDB: coreModule.get().mcpDB,
1444
+ toolName,
1429
1445
  });
1430
- res.send(result);
1446
+ // 获取审批人信息
1447
+ let auditorInfo = { auditor: '', shouldAudit: false };
1448
+ try {
1449
+ auditorInfo = await getAuditor({
1450
+ type: 'rainbow',
1451
+ configSource: async () => {
1452
+ const res = await fetchRainbowConfig('h5_publish_auditor', {
1453
+ appId: process.env.RAINBOW_APP_ID,
1454
+ userId: process.env.RAINBOW_USER_ID,
1455
+ secretKey: process.env.RAINBOW_SECRET_KEY,
1456
+ envName: 'Default',
1457
+ groupName: 'devops_open',
1458
+ }, {
1459
+ sdk: getRainbowNodeSdk(),
1460
+ tryJsonParse: true,
1461
+ });
1462
+ console.log('auditor', res);
1463
+ return res;
1464
+ },
1465
+ rainbowOptions: {
1466
+ projectName: extractRepoPath(repo),
1467
+ subProjectName: subProjectName || '',
1468
+ // @ts-ignore
1469
+ minimatch,
1470
+ },
1471
+ skipAudit: branch !== 'release',
1472
+ });
1473
+ }
1474
+ catch (e) {
1475
+ console.error('[MP Publish MCP] 获取审批人失败:', e);
1476
+ }
1477
+ // 在返回结果中追加审批人信息
1478
+ if (result.result && typeof result.result === 'object') {
1479
+ result.result.auditor = auditorInfo.auditor;
1480
+ result.result.shouldAudit = auditorInfo.shouldAudit;
1481
+ }
1482
+ res.json(result);
1431
1483
  });
1432
1484
 
1433
1485
  const router$5 = express.Router();
@@ -1459,6 +1511,7 @@ router$4.post('/mcp-start', async (req, res) => {
1459
1511
  }
1460
1512
  }
1461
1513
  const staffName = (req.header('rid') || 'developer');
1514
+ const toolName = (req.header('x-mcp-tool-name') || '');
1462
1515
  const { mcpName, mcpVersion, repo, branch, publishReason, versionType, publishExternalNPM, publishPackage, } = req.body;
1463
1516
  console.log('[mcp-start]', {
1464
1517
  mcpName,
@@ -1492,7 +1545,42 @@ router$4.post('/mcp-start', async (req, res) => {
1492
1545
  mcpName,
1493
1546
  mcpVersion,
1494
1547
  operationTool: coreModule.get().operation,
1548
+ toolName,
1495
1549
  });
1550
+ // 获取审批人信息
1551
+ let auditorInfo = { auditor: '', shouldAudit: false };
1552
+ try {
1553
+ auditorInfo = await getAuditor({
1554
+ type: 'json',
1555
+ configSource: async () => {
1556
+ const res = await fetchRainbowConfig('library_publish_auditor', {
1557
+ appId: process.env.RAINBOW_APP_ID,
1558
+ userId: process.env.RAINBOW_USER_ID,
1559
+ secretKey: process.env.RAINBOW_SECRET_KEY,
1560
+ envName: 'Default',
1561
+ groupName: 'devops_open',
1562
+ }, {
1563
+ sdk: getRainbowNodeSdk(),
1564
+ tryJsonParse: true,
1565
+ });
1566
+ console.log('auditor', res);
1567
+ return res;
1568
+ },
1569
+ jsonOptions: {
1570
+ projectName: extractRepoPath(component.git),
1571
+ key: versionType,
1572
+ },
1573
+ });
1574
+ }
1575
+ catch (e) {
1576
+ console.error('[Pipeline Open] 获取审批人失败:', e);
1577
+ }
1578
+ console.log('[auditorInfo]', auditorInfo, component, versionType);
1579
+ // 在返回结果中追加审批人信息
1580
+ if (result?.result?.data && typeof result?.result?.data === 'object') {
1581
+ (result?.result?.data).auditor = auditorInfo.auditor;
1582
+ (result?.result?.data).shouldAudit = auditorInfo.shouldAudit;
1583
+ }
1496
1584
  res.send(result);
1497
1585
  });
1498
1586
 
@@ -2667,7 +2755,7 @@ async function updateWhiteUserStatus({ status = false, pipelineRunId = '', }) {
2667
2755
 
2668
2756
  const CRON_TIME = '0 */10 * * * *';
2669
2757
  function createUpdateWhiteUserCosCron() {
2670
- if (process.env.NODE_ENV === 'development') {
2758
+ if (process.env.NODE_ENV === 'development' || process.platform !== 'linux') {
2671
2759
  return;
2672
2760
  }
2673
2761
  try {
@@ -2933,9 +3021,19 @@ async function notifyRobot(entry, iwikiUrl, robotNotifyConfig) {
2933
3021
  console.warn('[EmailSync] 未配置机器人 webhookUrl,跳过通知');
2934
3022
  return;
2935
3023
  }
2936
- const contentPreview = entry.content.length > 200
2937
- ? `${entry.content.slice(0, 200)}...`
2938
- : entry.content;
3024
+ // 清理 HTML 标签,避免未闭合标签(如 <style、<table 等)破坏企微 Markdown 渲染
3025
+ const plainContent = entry.content
3026
+ .replace(/<style[\s\S]*?<\/style>/gi, '') // 移除完整的 <style> 块
3027
+ .replace(/<script[\s\S]*?<\/script>/gi, '') // 移除完整的 <script> 块
3028
+ .replace(/<[^>]*>/g, '') // 移除所有 HTML 标签
3029
+ .replace(/&nbsp;/g, ' ') // 替换常见 HTML 实体
3030
+ .replace(/&lt;/g, '<')
3031
+ .replace(/&gt;/g, '>')
3032
+ .replace(/&amp;/g, '&')
3033
+ .trim();
3034
+ const contentPreview = plainContent.length > 200
3035
+ ? `${plainContent.slice(0, 200)}...`
3036
+ : plainContent;
2939
3037
  const message = [
2940
3038
  '📬 **邮件知识已同步到 iwiki**',
2941
3039
  '',
@@ -1,3 +1,4 @@
1
+ import { type StartPipelineResult } from '@plugin-light/shared';
1
2
  import { Request, Response } from 'express';
2
3
  interface MongoDb {
3
4
  connect(): Promise<any>;
@@ -32,12 +33,12 @@ interface OperationTool {
32
33
  updateRecord(where: any, record: any): Promise<void>;
33
34
  }
34
35
  interface Landun {
35
- startPipeline(pipelineId: string, data: any): Promise<any>;
36
+ startPipeline(pipelineId: string, data: any): Promise<StartPipelineResult>;
36
37
  startPipelineByRawApi(options: {
37
38
  data: any;
38
39
  pipelineId: string;
39
40
  userName: string;
40
- }): Promise<any>;
41
+ }): Promise<StartPipelineResult>;
41
42
  }
42
43
  interface CoreModuleData {
43
44
  mongodb: MongoDb;
@@ -46,7 +47,7 @@ interface CoreModuleData {
46
47
  operation: OperationTool;
47
48
  mcpValidate: (req: Request, res: Response) => Promise<boolean>;
48
49
  mcpDB?: {
49
- add: (...params: any[]) => Promise<void>;
50
+ add: (mcpName: string, staffName: string, content: string, version?: string, toolName?: string) => Promise<void>;
50
51
  };
51
52
  }
52
53
  interface CoreModule {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-admin-svr",
3
- "version": "0.1.49",
3
+ "version": "1.0.2",
4
4
  "description": "Next Admin 服务端",
5
5
  "keywords": [
6
6
  "vue3",
@@ -26,18 +26,21 @@
26
26
  "lib"
27
27
  ],
28
28
  "dependencies": {
29
+ "@plugin-light/shared": "latest",
30
+ "@tdesign/uniapp": "^0.7.3",
31
+ "@tdesign/uniapp-chat": "^0.2.1",
29
32
  "@tencent-ai/agent-sdk": "latest",
30
33
  "@types/express": "^5.0.6",
31
34
  "@wecom/crypto": "latest",
32
35
  "croner": "^9.1.0",
33
36
  "express": "^5.2.1",
34
37
  "fontmin": "latest",
38
+ "minimatch": "^10.0.1",
35
39
  "mongodb": "^7.0.0",
36
40
  "multer": "^2.0.2",
37
41
  "t-comm": "latest",
38
42
  "tinify": "^1.8.2",
39
- "tslib": "^2.8.1",
40
- "@plugin-light/shared": "^1.0.15"
43
+ "tslib": "^2.8.1"
41
44
  },
42
45
  "devDependencies": {
43
46
  "axios": "latest"