neo-cmp-cli 1.8.21 → 1.8.23

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/README.md CHANGED
@@ -393,7 +393,7 @@ const result = await customApi.run({
393
393
  | lodash | ^4.17.21 |
394
394
  | neo-ui-component-web | ^1.0.0 |
395
395
  | neo-ui-common | ^1.0.0 |
396
- | neo-open-api | ^1.1.6 |
396
+ | neo-open-api | ^1.1.9 |
397
397
  | amis | ^1.1.5 |
398
398
 
399
399
  > **注意**:自定义组件中请使用依赖包支持的版本,如版本不匹配运行时可能出现异常。
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),n=require("node:fs"),t=require("node:path"),o=require("ora"),s=require("node:http"),r=require("node:url"),i=require("open"),c=require("node:net");require("portfinder");const a=require("../utils/common.js"),l=require("../config/auth.config.js");var p,h;exports.__require=function(){if(h)return p;h=1;const d=e,g=n,u=t,y=o,k=s,_=r,m=i,w=c,{errorLog:x,successLog:f}=a.__require(),T=l.__require();return p=class{constructor(e={}){const{loginURL:n,tokenAPI:t}=e;if(!n||!t)throw new Error("auth.config.js 配置不完整,需要包含 loginURL、tokenAPI");this.loginURL=n,this.tokenAPI=t,this.response_type=T.response_type||"code",this.client_id=T.client_id,this.client_secret=T.client_secret,this.scope=T.scope||"all",this.oauthType=T.oauthType||"standard",this.access_type=T.access_type||"offline",this.grant_type=T.grant_type||"authorization_code",this.tokenDir=u.join(process.cwd(),".neo-cli"),this.tokenFile=u.join(this.tokenDir,"token.json")}ensureTokenDir(){g.existsSync(this.tokenDir)||g.mkdirSync(this.tokenDir,{recursive:!0})}saveToken(e){this.ensureTokenDir();const n={...e,savedAt:Date.now(),expiresAt:Date.now()+1e3*(e.expires_in||7200)};g.writeFileSync(this.tokenFile,JSON.stringify(n,null,2),"utf-8")}readToken(){if(!g.existsSync(this.tokenFile))return null;try{return JSON.parse(g.readFileSync(this.tokenFile,"utf-8"))}catch(e){return x(`读取 token 文件失败: ${e.message}`),null}}isTokenExpired(e){return!e||!e.expiresAt||Date.now()>=e.expiresAt-3e5}clearToken(){g.existsSync(this.tokenFile)&&g.unlinkSync(this.tokenFile)}getRedirectURI(e){return`http://localhost:${e}`}buildAuthUrl(e){const n=new URLSearchParams({response_type:this.response_type,client_id:this.client_id,redirect_uri:e,scope:this.scope,oauthType:this.oauthType,access_type:this.access_type});return`${this.loginURL}?${n.toString()}`}async openBrowser(e){try{await m(e)}catch(n){x(`无法自动打开浏览器: ${n.message}`),console.log(`\n请手动访问以下 URL 进行授权:\n${e}\n`)}}async isPortInUse(e){return new Promise(n=>{const t=w.createServer();t.once("error",e=>{"EADDRINUSE"===e.code?n(!0):n(!1)}),t.once("listening",()=>{t.once("close",()=>{n(!1)}),t.close()}),t.listen(e)})}async startCallbackServer(){let e=T.redirectUri,n=new URL(e),t=parseInt(n.port,10);await this.isPortInUse(t)&&(consoleError(`\n警告: 端口 ${t} 已被占用,请调整 redirectUri 配置项,使其指向一个未被占用的端口。`),process.exit(1));const o=new Promise((o,s)=>{const r=k.createServer((e,t)=>{const i=_.parse(e.url,!0);if(i.pathname===n.pathname||"/"===i.pathname){const e=i.query.code,n=i.query.error;if(n)return t.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),t.end(`\n <html>\n <head>\n <title>授权失败</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .error-title {\n color: red;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="error-title">授权失败</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权失败" />\n <p>错误信息: ${n}</p>\n </div>\n </body>\n </html>\n `),r.close(),void s(new Error(`授权失败: ${n}`));if(e)return t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end('\n <html>\n <head>\n <title>授权成功</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .success-title {\n color: green;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="success-title">授权成功!</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权成功" />\n <p>您已成功授权开发账户,请关闭此页面。</p>\n </div>\n </body>\n </html>\n '),r.close(),void o(e);t.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),t.end('\n <html>\n <head>\n <title>授权失败</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .error-title {\n color: red;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="error-title">授权失败</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权失败" />\n <p>未获取到授权码。</p>\n </div>\n </body>\n </html>\n '),r.close(),s(new Error("未获取到授权码"))}else t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Not Found")});r.on("error",e=>{"EADDRINUSE"===e.code?s(new Error(`端口 ${t} 已被占用,无法启动回调服务器`)):s(e)}),r.listen(t,()=>{console.log(`\n本地回调服务器已启动,监听端口: ${t}`),console.log(`回调地址: ${e}`)}),setTimeout(()=>{r.close(),s(new Error("授权超时,请重试"))},3e5)});return{redirectUri:e,codePromise:o}}async getTokenByCode(e,n){const t=y("正在获取 access token...").start();try{const o=new URLSearchParams;o.append("grant_type",this.grant_type),o.append("client_id",this.client_id),o.append("client_secret",this.client_secret),o.append("code",e),o.append("redirect_uri",n);const s=(await d.post(this.tokenAPI,o.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return s&&s.access_token||(x("获取 token 失败:响应中未包含 access_token",t),x(`响应数据: ${JSON.stringify(s)}`),process.exit(1)),f("成功获取 access token",t),s}catch(e){x("获取 token 失败",t),x(`\n获取 token 失败: ${e.message}`),e.response&&x(`响应数据: ${JSON.stringify(e.response.data)}`),process.exit(1)}}async refreshToken(e){const n=y("正在刷新授权信息(token)...").start();try{const t=new URLSearchParams;t.append("grant_type","refresh_token"),t.append("client_id",this.client_id),t.append("client_secret",this.client_secret),t.append("refresh_token",e);const o=(await d.post(this.tokenAPI,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return o&&o.access_token?(f("刷新授权信息成功(token)。",n),o):(x("刷新授权信息失败:响应中未包含 access_token",n),x(`响应数据: ${JSON.stringify(o)}`),null)}catch(e){return x("刷新授权信息失败",n),x(`\n刷新授权信息失败: ${e.message}`),e.response&&x(`响应数据: ${JSON.stringify(e.response.data)}`),null}}async login(){console.log("\n========== NeoCRM 登录授权 ==========\n");try{const{redirectUri:e,codePromise:n}=await this.startCallbackServer(),t=this.buildAuthUrl(e);console.log("授权 URL:",t),console.log("\n正在打开浏览器进行授权..."),await this.openBrowser(t);const o=await n;f("\n✓ 已获取授权码");const s=await this.getTokenByCode(o,e);return this.saveToken(s),console.log("\n========== 登录成功 ==========\n"),console.log(`已缓存授权信息到: ${this.tokenFile}`),console.log(`实例地址: ${s.instance_uri||"未返回"}`),console.log(`租户 ID: ${s.tenant_id||"未返回"}`),console.log(`授权信息有效期(access_token): ${s.expires_in||7200} 秒`),console.log(`自动刷新授权信息有效期(refresh_token): ${s.refresh_token_expires_in||2592e3} 秒`),s}catch(e){x(`\n登录失败: ${e.message}`),process.exit(1)}}async logout(){if(console.log("\n========== NeoCRM 登出 ==========\n"),g.existsSync(this.tokenFile))try{this.clearToken(),f("已清除授权信息,下次登录需要重新授权。"),console.log("\n登出成功!\n")}catch(e){x(`登出失败: ${e.message}`),process.exit(1)}else console.log("当前未登录,无需登出。")}async getValidToken(){const e=this.readToken();if(e||(x("未找到授权信息,请先执行 neo login 进行登录。"),process.exit(1)),this.isTokenExpired(e)){console.log("授权信息已过期,正在尝试刷新..."),e.refresh_token||(x("自动刷新授权信息失败,请重新登录(neo login)。"),process.exit(1));const n=await this.refreshToken(e.refresh_token);return n||(x("刷新授权信息失败,请重新登录 (neo login)"),process.exit(1)),this.saveToken(n),n}return e}async getAccessToken(){return(await this.getValidToken()).access_token}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),n=require("node:fs"),t=require("node:path"),o=require("ora"),r=require("node:http"),s=require("node:url"),i=require("open"),c=require("node:net");require("portfinder");const a=require("../utils/common.js"),l=require("../config/auth.config.js");var p,h;exports.__require=function(){if(h)return p;h=1;const d=e,g=n,u=t,y=o,k=r,_=s,m=i,w=c,{errorLog:x,successLog:f}=a.__require(),T=l.__require();return p=class{constructor(e={}){const{loginURL:n,tokenAPI:t}=e;if(!n||!t)throw new Error("auth.config.js 配置不完整,需要包含 loginURL、tokenAPI");this.loginURL=n,this.tokenAPI=t,this.response_type=T.response_type||"code",this.client_id=T.client_id,this.client_secret=T.client_secret,this.scope=T.scope||"all",this.oauthType=T.oauthType||"standard",this.access_type=T.access_type||"offline",this.grant_type=T.grant_type||"authorization_code",this.tokenDir=u.join(process.cwd(),".neo-cli"),this.tokenFile=u.join(this.tokenDir,"token.json")}ensureTokenDir(){g.existsSync(this.tokenDir)||g.mkdirSync(this.tokenDir,{recursive:!0})}saveToken(e){this.ensureTokenDir();const n={...e,savedAt:Date.now(),expiresAt:Date.now()+1e3*(e.expires_in||7200)};g.writeFileSync(this.tokenFile,JSON.stringify(n,null,2),"utf-8")}readToken(){if(!g.existsSync(this.tokenFile))return null;try{return JSON.parse(g.readFileSync(this.tokenFile,"utf-8"))}catch(e){return x(`读取 token 文件失败: ${e.message}`),null}}isTokenExpired(e){return!e||!e.expiresAt||Date.now()>=e.expiresAt-3e5}clearToken(){g.existsSync(this.tokenFile)&&g.unlinkSync(this.tokenFile)}getRedirectURI(e){return`http://localhost:${e}`}buildAuthUrl(e){const n=new URLSearchParams({response_type:this.response_type,client_id:this.client_id,redirect_uri:e,scope:this.scope,oauthType:this.oauthType,access_type:this.access_type});return`${this.loginURL}?${n.toString()}`}async openBrowser(e){try{await m(e)}catch(n){x(`无法自动打开浏览器: ${n.message}`),console.log(`\n请手动访问以下 URL 进行授权:\n${e}\n`)}}async isPortInUse(e){return new Promise(n=>{const t=w.createServer();t.once("error",e=>{"EADDRINUSE"===e.code?n(!0):n(!1)}),t.once("listening",()=>{t.once("close",()=>{n(!1)}),t.close()}),t.listen(e)})}async startCallbackServer(){let e=T.redirectUri,n=new URL(e),t=parseInt(n.port,10);await this.isPortInUse(t)&&(consoleError(`\n警告: 端口 ${t} 已被占用,请调整 redirectUri 配置项,使其指向一个未被占用的端口。`),process.exit(1));const o=new Promise((o,r)=>{const s=k.createServer((e,t)=>{const i=_.parse(e.url,!0);if(i.pathname===n.pathname||"/"===i.pathname){const e=i.query.code,n=i.query.error;if(n)return t.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),t.end(`\n <html>\n <head>\n <title>授权失败</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .error-title {\n color: red;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="error-title">授权失败</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权失败" />\n <p>错误信息: ${n}</p>\n </div>\n </body>\n </html>\n `),s.close(),void r(new Error(`授权失败: ${n}`));if(e){const n=this.readToken()||{},r=n.tenant_id,i=n.instance_uri;return t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(`\n <html>\n <head>\n <title>授权成功</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .success-title {\n color: green;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="success-title">授权成功!</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权成功" />\n <p>您已成功授权开发账户,请关闭此页面。<br />租户 ID: ${r},所在租户的 API 域名: ${i}。</p>\n </div>\n </body>\n </html>\n `),s.close(),void o(e)}t.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),t.end('\n <html>\n <head>\n <title>授权失败</title>\n <style>\n .container {\n margin: 0 auto;\n padding-top: 30px;\n text-align: center;\n\n .error-title {\n color: red;\n }\n\n h1, p {\n text-align: center;\n margin-top: 30px;\n }\n }\n </style>\n </head>\n <body>\n <div class="container">\n <h1 class="error-title">授权失败</h1>\n <img src="https://custom-widgets.bj.bcebos.com/neocrmlogin.png" alt="授权失败" />\n <p>未获取到授权码。</p>\n </div>\n </body>\n </html>\n '),s.close(),r(new Error("未获取到授权码"))}else t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Not Found")});s.on("error",e=>{"EADDRINUSE"===e.code?r(new Error(`端口 ${t} 已被占用,无法启动回调服务器`)):r(e)}),s.listen(t,()=>{console.log(`\n本地回调服务器已启动,监听端口: ${t}`),console.log(`回调地址: ${e}`)}),setTimeout(()=>{s.close(),r(new Error("授权超时,请重试"))},3e5)});return{redirectUri:e,codePromise:o}}async getTokenByCode(e,n){const t=y("正在获取 access token...").start();try{const o=new URLSearchParams;o.append("grant_type",this.grant_type),o.append("client_id",this.client_id),o.append("client_secret",this.client_secret),o.append("code",e),o.append("redirect_uri",n);const r=(await d.post(this.tokenAPI,o.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return r&&r.access_token||(x("获取 token 失败:响应中未包含 access_token",t),x(`响应数据: ${JSON.stringify(r)}`),process.exit(1)),f("成功获取 access token",t),r}catch(e){x("获取 token 失败",t),x(`\n获取 token 失败: ${e.message}`),e.response&&x(`响应数据: ${JSON.stringify(e.response.data)}`),process.exit(1)}}async refreshToken(e){const n=y("正在刷新授权信息(token)...").start();try{const t=new URLSearchParams;t.append("grant_type","refresh_token"),t.append("client_id",this.client_id),t.append("client_secret",this.client_secret),t.append("refresh_token",e);const o=(await d.post(this.tokenAPI,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return o&&o.access_token?(f("刷新授权信息成功(token)。",n),o):(x("刷新授权信息失败:响应中未包含 access_token",n),x(`响应数据: ${JSON.stringify(o)}`),null)}catch(e){return x("刷新授权信息失败",n),x(`\n刷新授权信息失败: ${e.message}`),e.response&&x(`响应数据: ${JSON.stringify(e.response.data)}`),null}}async login(){console.log("\n========== NeoCRM 登录授权 ==========\n");try{const{redirectUri:e,codePromise:n}=await this.startCallbackServer(),t=this.buildAuthUrl(e);console.log("授权 URL:",t),console.log("\n正在打开浏览器进行授权..."),await this.openBrowser(t);const o=await n;f("\n✓ 已获取授权码");const r=await this.getTokenByCode(o,e);return this.saveToken(r),console.log("\n========== 登录成功 ==========\n"),console.log(`已缓存授权信息到: ${this.tokenFile}`),console.log(`实例地址: ${r.instance_uri||"未返回"}`),console.log(`租户 ID: ${r.tenant_id||"未返回"}`),console.log(`授权信息有效期(access_token): ${r.expires_in||7200} 秒`),console.log(`自动刷新授权信息有效期(refresh_token): ${r.refresh_token_expires_in||2592e3} 秒`),r}catch(e){x(`\n登录失败: ${e.message}`),process.exit(1)}}async logout(){if(console.log("\n========== NeoCRM 登出 ==========\n"),g.existsSync(this.tokenFile))try{this.clearToken(),f("已清除授权信息,下次登录需要重新授权。"),console.log("\n登出成功!\n")}catch(e){x(`登出失败: ${e.message}`),process.exit(1)}else console.log("当前未登录,无需登出。")}async getValidToken(){const e=this.readToken();if(e||(x("未找到授权信息,请先执行 neo login 进行登录。"),process.exit(1)),this.isTokenExpired(e)){console.log("授权信息已过期,正在尝试刷新..."),e.refresh_token||(x("自动刷新授权信息失败,请重新登录(neo login)。"),process.exit(1));const n=await this.refreshToken(e.refresh_token);return n||(x("刷新授权信息失败,请重新登录 (neo login)"),process.exit(1)),this.saveToken(n),n}return e}async getAccessToken(){return await this.getValidToken()}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("lodash");var e,n;exports.__require=function(){if(n)return e;n=1;const s=o,d={react:"^16.13.1","react-dom":"^16.13.1",mobx:"^6.3.0","mobx-react":"^7.0.0","mobx-state-tree":"^5.4.0",echarts:"5.4.2",antd:"4.9.4","antd-mobile":"2.3.4","@ant-design/icons":"^4.8.0","video-react":"0.14.1",axios:"^0.27.2",classnames:"^2.3.2",qs:"^6.11.0",lodash:"^4.17.21","neo-ui-component-web":"^1.0.0","neo-ui-common":"^1.0.0","neo-open-api":"^1.1.6",amis:"^1.1.5"};return e={initNeoRequire:()=>{window.neoRequire||(window.neoRequire=o=>window.__NeoCommonModules[o]||window[o])},addNeoCommonModules:o=>{if(window.__NeoCommonModules||(window.__NeoCommonModules={}),isPlainObject(o)){Object.keys(o).forEach(e=>{const n=o[e],s=window.__NeoCommonModules[e];s&&Object.keys(s).length<3?(window.__NeoCommonModules[e]=Object.assign(window.__NeoCommonModules[e],n),void 0!==n.__esModule&&(window.__NeoCommonModules[e].__esModule=n.__esModule),void 0!==n.default&&(window.__NeoCommonModules[e].default=n.default)):window.__NeoCommonModules[e]=n})}},addNeoRemoteDeps:o=>{window.__NeoCommonModules||(window.__NeoCommonModules={}),window.__NeoCommonModules.__neoRemoteDeps||(window.__NeoCommonModules.__neoRemoteDeps={}),s.isPlainObject(o)&&(window.__NeoCommonModules.__neoRemoteDeps=Object.assign(window.__NeoCommonModules.__neoRemoteDeps,o))},getExternalsByNeoCommonModules:o=>{const e={};return Object.keys(d).forEach(o=>{e[o]=`commonjs ${o}`}),o&&o.length>0&&o.forEach(o=>{e[o]=`commonjs ${o}`}),e}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("lodash");var e,n;exports.__require=function(){if(n)return e;n=1;const s=o,d={react:"^16.13.1","react-dom":"^16.13.1",mobx:"^6.3.0","mobx-react":"^7.0.0","mobx-state-tree":"^5.4.0",echarts:"5.4.2",antd:"4.9.4","antd-mobile":"2.3.4","@ant-design/icons":"^4.8.0","video-react":"0.14.1",axios:"^0.27.2",classnames:"^2.3.2",qs:"^6.11.0",lodash:"^4.17.21","neo-ui-component-web":"^1.0.0","neo-ui-common":"^1.0.0","neo-open-api":"^1.1.9",amis:"^1.1.5"};return e={initNeoRequire:()=>{window.neoRequire||(window.neoRequire=o=>window.__NeoCommonModules[o]||window[o])},addNeoCommonModules:o=>{if(window.__NeoCommonModules||(window.__NeoCommonModules={}),isPlainObject(o)){Object.keys(o).forEach(e=>{const n=o[e],s=window.__NeoCommonModules[e];s&&Object.keys(s).length<3?(window.__NeoCommonModules[e]=Object.assign(window.__NeoCommonModules[e],n),void 0!==n.__esModule&&(window.__NeoCommonModules[e].__esModule=n.__esModule),void 0!==n.default&&(window.__NeoCommonModules[e].default=n.default)):window.__NeoCommonModules[e]=n})}},addNeoRemoteDeps:o=>{window.__NeoCommonModules||(window.__NeoCommonModules={}),window.__NeoCommonModules.__neoRemoteDeps||(window.__NeoCommonModules.__neoRemoteDeps={}),s.isPlainObject(o)&&(window.__NeoCommonModules.__neoRemoteDeps=Object.assign(window.__NeoCommonModules.__neoRemoteDeps,o))},getExternalsByNeoCommonModules:o=>{const e={};return Object.keys(d).forEach(o=>{e[o]=`commonjs ${o}`}),o&&o.length>0&&o.forEach(o=>{e[o]=`commonjs ${o}`}),e}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("form-data"),s=require("node:fs"),o=require("node:path"),i=require("ora"),n=require("lodash"),r=require("akfun"),a=require("./neoLogin.js"),c=require("../utils/projectUtils/updatePublishLog.js"),u=require("../utils/common.js");var h,p;exports.__require=function(){if(p)return h;p=1;const l=e,d=t,m=s,f=o,y=i,w=n,{resolve:g}=r,k=a.__require(),$=c.__require(),{getFramework:x,errorLog:A,successLog:C}=u.__require(),T="https://crm.xiaoshouyi.com",F="https://login-cd.xiaoshouyi.com/auc/oauth2/auth",L="https://login.xiaoshouyi.com/auc/oauth2/token",b="/rest/metadata/v3.0/ui/customComponents",S="/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent",P="/rest/metadata/v3.0/ui/components/filter?custom=true",U=e=>`/rest/metadata/v3.0/ui/customComponents/${e}/codeLib`,B="/rest/metadata/v3.0/ui/customComponents/actions/upload",E=["cmpType","label","componentCategory","description","framework","icon","iconUrl","orderNo","version","propsSchema","defaultProps","previewProps","events","functions","asset","modelAsset","cssAsset","codeLib"];return h=class{constructor(e={}){const{assetsRoot:t,neoBaseURL:s,tokenAPI:o,loginURL:i,auth:n,authType:r}=e||{};this.authType=r||"oauth2","password"!==this.authType||n||(A("密码授权模式时,neo.config.js / neoConfig / auth 配置不能为空"),process.exit(1)),"password"===this.authType?n.client_id&&n.client_secret&&n.username&&n.password||(A("neo.config.js / neoConfig / auth 配置不完整(password 模式),需要包含 client_id、client_secret、username、password"),process.exit(1)):"oauth2"===this.authType?i&&o||(A("neo.config.js / neoConfig 配置不完整(oauth2 模式),需要包含 loginURL、tokenAPI 配置。"),process.exit(1)):(A(`不支持的授权类型: ${this.authType},可选值:oauth2、password`),process.exit(1)),this.assetsRoot=t||g("dist"),this.neoBaseURL=s||T,this.tokenAPI=o||L,this.loginURL=i||F,this.auth=n,this.cmpList=[],this.cmpInfoMap={},this.tokenCache={token:null,expiresAt:null}}buildFullUrl(e){return e.startsWith("http://")||e.startsWith("https://")?e:`${this.neoBaseURL}${e}`}uploadAPI(){return this.buildFullUrl(B)}saveAPI(){return this.buildFullUrl(S)}isTokenExpired(){return!this.tokenCache.token||!this.tokenCache.expiresAt||Date.now()>=this.tokenCache.expiresAt}async getToken(){return this.isTokenExpired()?"oauth2"===this.authType?await this.getTokenByOAuth2():await this.getTokenByPassword():this.tokenCache.token}async getTokenByPassword(){const e=y("获取 token(密码模式)...").start();if(!this.isTokenExpired())return C("使用缓存的 token。",e),this.tokenCache.token;const t=new URLSearchParams;t.append("grant_type","password"),t.append("client_id",this.auth.client_id),t.append("client_secret",this.auth.client_secret),t.append("username",this.auth.username),t.append("password",this.auth.password);const s=this.buildFullUrl(this.tokenAPI);try{const o=await l.post(s,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),{access_token:i,expires_in:n}=o.data||{};i||(A("获取 token 失败(授权配置错误):响应中未包含 access_token,"+JSON.stringify(o.data),e),process.exit(1));const r=parseInt(n)||3600;return this.tokenCache={token:i,expiresAt:Date.now()+1e3*(r-60)},e.clear(),e.stop(),i}catch(o){A("获取 token 失败",e),A(`\n获取 token 失败: ${o.message}`),A(`\ntoken 授权地址: ${s}`),A(`\ntoken 请求参数: ${t}`),o.response&&A(`响应数据: ${JSON.stringify(o.response.data)}`),process.exit(1)}}async getTokenByOAuth2(){const e=y("获取 token(OAuth2 模式)...").start();try{const t={loginURL:this.loginURL,tokenAPI:this.tokenAPI},s=new k(t),o=await s.getAccessToken();return this.tokenCache={token:o,expiresAt:Date.now()+72e5},e.clear(),e.stop(),o}catch(t){A("获取 token 失败(OAuth2 模式)",e),A(`\n获取 token 失败: ${t.message}`),t.response&&A(`响应数据: ${JSON.stringify(t.response.data)}`),process.exit(1)}}async refreshToken(){return this.tokenCache={token:null,expiresAt:null},await this.getToken()}async ensureValidToken(){if(!this.tokenCache.token)return await this.getToken();if(this.isTokenExpired()){const e=y("token 已过期,正在刷新...").start();try{const t=await this.refreshToken();return C("token 刷新成功。",e),t}catch(t){throw A("token 刷新失败。",e),t}}return this.tokenCache.token}async uploadFile(e,t={}){const s=await this.ensureValidToken();if(!e||"string"!=typeof e)throw new Error(`文件路径无效: ${e}`);if(!m.existsSync(e))throw new Error(`文件不存在: ${e}`);const o=m.statSync(e);if(!o.isFile())throw new Error(`路径不是文件: ${e}`);const i=t.maxSize||5242880;if(o.size>i){const e=(o.size/1024/1024).toFixed(2),t=(i/1024/1024).toFixed(2);throw new Error(`文件大小超过限制: ${e}MB > ${t}MB`)}if(0===o.size)throw new Error(`文件为空: ${e}`);const n=f.basename(e),r=(o.size/1024).toFixed(2),a=y(`正在上传文件: ${n} (${r}KB)...`).start();try{const o=new d,i=t.fieldName||"customComponentCode",r=m.createReadStream(e);o.append(i,r,n);const c=this.uploadAPI(),u=t.timeout||6e4,h={headers:{Authorization:`Bearer ${s}`,"xsy-inner-source":"bff",...o.getHeaders()},timeout:u,maxContentLength:1/0,maxBodyLength:1/0},p=await l.post(c,o,h);let f;const y=p.data;if(200!==p.status&&201!==p.status)throw new Error(`上传失败: HTTP ${p.status}`);if("string"==typeof y)f=y.trim();else{if(!y||"object"!=typeof y)throw new Error("响应数据格式不正确: "+typeof y);if(void 0!==y.code&&200!==y.code&&0!==y.code){const e=y.message||y.msg||"未知错误";throw new Error(`上传失败: ${e} (code: ${y.code})`)}f=void 0!==y.data?y.data:void 0!==y.url?y.url:void 0!==y.fileUrl?y.fileUrl:y}if(!f)throw new Error("返回的文件地址为空");let w;return"string"==typeof f?w=f:f&&"object"==typeof f&&f.url&&(w=f.url),C(`文件上传成功: ${n} -> ${w}`,a),w}catch(t){if(A(`上传文件失败: ${t.message}, 文件路径: ${e}`,a),t.response){const e=t.response.status,s=t.response.statusText,o=t.response.data,i=t.config?.url||this.uploadAPI();if(A("\n========== 上传请求详情 =========="),A(`请求 URL: ${i}`),A(`HTTP 状态码: ${e} ${s}`),A(`响应数据: ${JSON.stringify(o)}`),A("==================================\n"),404===e)throw new Error(`上传 API 不存在 (404): ${i}\n请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n当前配置的 API 路径: ${B}`)}else t.request&&A("请求已发送但未收到响应,请检查网络连接或代理配置。");throw t}}async publish2oss(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e},o=m.readdirSync(this.assetsRoot).map(async o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;try{const e=await this.uploadFile(i);o.indexOf("Model")>-1?s.modelAsset=e:o.endsWith(".css")?s.cssAsset=e:o.endsWith(".zip")?s.codeLib=e:s.asset=e}catch(e){A(`文件上传失败(${o}):\n`),process.exit(1)}}});return await Promise.all(o),s&&s.cmpType&&(console.info("上传至 OSS 的文件信息:\n",s),$(s)),s}async getCmpAssets(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e};return m.readdirSync(this.assetsRoot).forEach(o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;const r=5242880;if(n.size>r){const e=(n.size/1024/1024).toFixed(2),t=(r/1024/1024).toFixed(2);throw new Error(`${o} 文件大小超过限制: ${e}MB > ${t}MB`)}const a={fileContent:m.createReadStream(i),fileName:o,fileSize:n.size};o.indexOf("Model")>-1?s.modelAssetFile=a:o.endsWith(".css")?s.cssAssetFile=a:o.endsWith(".zip")?s.codeLibFile=a:s.assetFile=a}}),s}async updateCustomComponent(e){const t=await this.ensureValidToken();if(!e)throw new Error("componentData 不能为空");const s=y("正在保存自定义组件信息...").start();try{const o=this.saveAPI(),i=new d;e.assetFile&&i.append("assetFile",e.assetFile.fileContent,e.assetFile.fileName),e.modelAssetFile&&i.append("modelAssetFile",e.modelAssetFile.fileContent,e.modelAssetFile.fileName),e.cssAssetFile&&i.append("cssAssetFile",e.cssAssetFile.fileContent,e.cssAssetFile.fileName),e.codeLibFile&&i.append("codeLibFile",e.codeLibFile.fileContent,e.codeLibFile.fileName),i.append("component",JSON.stringify(w.omit(e,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])));const n=await l.post(o,i,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff",...i.getHeaders()},timeout:12e4,maxContentLength:1/0,maxBodyLength:1/0}),{code:r,message:a}=n.data||{};r&&200!==r&&(A(`保存自定义组件信息失败: ${n.data.message||"未知错误"}`),process.exit(1)),s.clear(),s.stop()}catch(e){e.message?A(`保存自定义组件信息失败: ${e.message}`,s):A(`保存自定义组件信息失败: ${JSON.stringify(e)}`,s),process.exit(1)}}async getCustomCmpList(){const e=await this.ensureValidToken();try{let t=this.buildFullUrl(P);t+=`&fields=${E.join(",")}`;const s=await l.get(t,{headers:{Authorization:`Bearer ${e}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:o,message:i}=s.data||{};o&&200!==o&&(A(`获取自定义组件列表失败: ${i||"未知错误"}`),process.exit(1)),this.updateCustomCmpList(s.data.data||[])}catch(e){e.message?A(`获取自定义组件列表失败: ${e.message}`):A(`响应数据: ${JSON.stringify(e)}`),process.exit(1)}return this.cmpList||[]}getCodeLibByCmpType(e){return e?this.buildFullUrl(U(e)):null}async deleteCmp(e){const t=await this.ensureValidToken();e||(A("自定义组件名称不能为空。"),process.exit(1));let s=this.buildFullUrl(b);s+=`/${e}`;const o=await l.delete(s,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:i,message:n}=o.data||{};return i&&200!==i&&(A(`删除自定义组件失败: ${n||"未知错误"}`),process.exit(1)),o.data}getCmpListByFramework(e){if(!e)return this.cmpList;const t=x(e);return this.cmpList.filter(e=>e.framework===t)}getCmpInfoByCmpType(e){return e&&this.cmpInfoMap[e]||null}updateCustomCmpList(e){e&&Array.isArray(e)&&(this.cmpList=e,e.forEach(e=>{this.cmpInfoMap[e.cmpType]=e}))}async request(e,t,s={}){const o=await this.ensureValidToken(),{data:i,headers:n={},params:r}=s,a=this.buildFullUrl(t);try{const t=await l({method:e,url:a,data:i,params:r,headers:{Authorization:`Bearer ${o}`,"xsy-inner-source":"bff",...n}});if(t.data&&t.data.code&&200!==t.data.code)throw new Error(`请求失败: ${t.data.message||"未知错误"}`);return t.data}catch(s){throw A(`请求失败 [${e} ${t}]: ${s.message}`),s.response&&A(`响应数据: ${JSON.stringify(s.response.data)}`),s}}async get(e,t={}){return await this.request("GET",e,t)}async post(e,t={}){return await this.request("POST",e,t)}async put(e,t={}){return await this.request("PUT",e,t)}async delete(e,t={}){return await this.request("DELETE",e,t)}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("form-data"),s=require("node:fs"),o=require("node:path"),i=require("ora"),n=require("lodash"),r=require("akfun"),a=require("./neoLogin.js"),c=require("../utils/projectUtils/updatePublishLog.js"),u=require("../utils/common.js");var h,p;exports.__require=function(){if(p)return h;p=1;const l=e,d=t,m=s,f=o,y=i,w=n,{resolve:g}=r,k=a.__require(),$=c.__require(),{getFramework:x,errorLog:A,successLog:C}=u.__require(),T="https://crm.xiaoshouyi.com",F="https://login-cd.xiaoshouyi.com/auc/oauth2/auth",L="https://login.xiaoshouyi.com/auc/oauth2/token",b="/rest/metadata/v3.0/ui/customComponents",S="/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent",P="/rest/metadata/v3.0/ui/components/filter?custom=true",U=e=>`/rest/metadata/v3.0/ui/customComponents/${e}/codeLib`,B="/rest/metadata/v3.0/ui/customComponents/actions/upload",E=["cmpType","label","componentCategory","description","framework","icon","iconUrl","orderNo","version","propsSchema","defaultProps","previewProps","events","functions","asset","modelAsset","cssAsset","codeLib"];return h=class{constructor(e={}){const{assetsRoot:t,neoBaseURL:s,tokenAPI:o,loginURL:i,auth:n,authType:r}=e||{};this.authType=r||"oauth2","password"!==this.authType||n||(A("密码授权模式时,neo.config.js / neoConfig / auth 配置不能为空"),process.exit(1)),"password"===this.authType?n.client_id&&n.client_secret&&n.username&&n.password||(A("neo.config.js / neoConfig / auth 配置不完整(password 模式),需要包含 client_id、client_secret、username、password"),process.exit(1)):"oauth2"===this.authType?i&&o||(A("neo.config.js / neoConfig 配置不完整(oauth2 模式),需要包含 loginURL、tokenAPI 配置。"),process.exit(1)):(A(`不支持的授权类型: ${this.authType},可选值:oauth2、password`),process.exit(1)),this.assetsRoot=t||g("dist"),this.neoBaseURL=s||T,this.tokenAPI=o||L,this.loginURL=i||F,this.auth=n,this.cmpList=[],this.cmpInfoMap={},this.tokenCache={token:null,expiresAt:null}}buildFullUrl(e){return e.startsWith("http://")||e.startsWith("https://")?e:`${this.neoBaseURL}${e}`}uploadAPI(){return this.buildFullUrl(B)}saveAPI(){return this.buildFullUrl(S)}isTokenExpired(){return!this.tokenCache.token||!this.tokenCache.expiresAt||Date.now()>=this.tokenCache.expiresAt}async getToken(){return this.isTokenExpired()?"oauth2"===this.authType?await this.getTokenByOAuth2():await this.getTokenByPassword():this.tokenCache.token}async getTokenByPassword(){const e=y("获取 token(密码模式)...").start();if(!this.isTokenExpired())return C("使用缓存的 token。",e),this.tokenCache.token;const t=new URLSearchParams;t.append("grant_type","password"),t.append("client_id",this.auth.client_id),t.append("client_secret",this.auth.client_secret),t.append("username",this.auth.username),t.append("password",this.auth.password);const s=this.buildFullUrl(this.tokenAPI);try{const o=await l.post(s,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),i=o.data||{},{access_token:n,expires_in:r}=i;n||(A("获取 token 失败(授权配置错误):响应中未包含 access_token,"+JSON.stringify(o.data),e),process.exit(1));const a=parseInt(r)||3600;return this.tokenCache={...i,token:n,expiresAt:Date.now()+1e3*(a-60)},e.clear(),e.stop(),n}catch(o){A("获取 token 失败",e),A(`\n获取 token 失败: ${o.message}`),A(`\ntoken 授权地址: ${s}`),A(`\ntoken 请求参数: ${t}`),o.response&&A(`响应数据: ${JSON.stringify(o.response.data)}`),process.exit(1)}}async getTokenByOAuth2(){const e=y("获取 token(OAuth2 模式)...").start();try{const t={loginURL:this.loginURL,tokenAPI:this.tokenAPI},s=new k(t),o=await s.getAccessToken(),i=o.access_token;return this.tokenCache={...o,token:i,expiresAt:Date.now()+72e5},e.clear(),e.stop(),i}catch(t){A("获取 token 失败(OAuth2 模式)",e),A(`\n获取 token 失败: ${t.message}`),t.response&&A(`响应数据: ${JSON.stringify(t.response.data)}`),process.exit(1)}}async refreshToken(){return this.tokenCache={token:null,expiresAt:null},await this.getToken()}async ensureValidToken(){if(!this.tokenCache.token)return await this.getToken();if(this.isTokenExpired()){const e=y("token 已过期,正在刷新...").start();try{const t=await this.refreshToken();return C("token 刷新成功。",e),t}catch(t){throw A("token 刷新失败。",e),t}}return this.tokenCache.token}async uploadFile(e,t={}){const s=await this.ensureValidToken();if(!e||"string"!=typeof e)throw new Error(`文件路径无效: ${e}`);if(!m.existsSync(e))throw new Error(`文件不存在: ${e}`);const o=m.statSync(e);if(!o.isFile())throw new Error(`路径不是文件: ${e}`);const i=t.maxSize||5242880;if(o.size>i){const e=(o.size/1024/1024).toFixed(2),t=(i/1024/1024).toFixed(2);throw new Error(`文件大小超过限制: ${e}MB > ${t}MB`)}if(0===o.size)throw new Error(`文件为空: ${e}`);const n=f.basename(e),r=(o.size/1024).toFixed(2),a=y(`正在上传文件: ${n} (${r}KB)...`).start();try{const o=new d,i=t.fieldName||"customComponentCode",r=m.createReadStream(e);o.append(i,r,n);const c=this.uploadAPI(),u=t.timeout||6e4,h={headers:{Authorization:`Bearer ${s}`,"xsy-inner-source":"bff",...o.getHeaders()},timeout:u,maxContentLength:1/0,maxBodyLength:1/0},p=await l.post(c,o,h);let f;const y=p.data;if(200!==p.status&&201!==p.status)throw new Error(`上传失败: HTTP ${p.status}`);if("string"==typeof y)f=y.trim();else{if(!y||"object"!=typeof y)throw new Error("响应数据格式不正确: "+typeof y);if(void 0!==y.code&&200!==y.code&&0!==y.code){const e=y.message||y.msg||"未知错误";throw new Error(`上传失败: ${e} (code: ${y.code})`)}f=void 0!==y.data?y.data:void 0!==y.url?y.url:void 0!==y.fileUrl?y.fileUrl:y}if(!f)throw new Error("返回的文件地址为空");let w;return"string"==typeof f?w=f:f&&"object"==typeof f&&f.url&&(w=f.url),C(`文件上传成功: ${n} -> ${w}`,a),w}catch(t){if(A(`上传文件失败: ${t.message}, 文件路径: ${e}`,a),t.response){const e=t.response.status,s=t.response.statusText,o=t.response.data,i=t.config?.url||this.uploadAPI();if(A("\n========== 上传请求详情 =========="),A(`请求 URL: ${i}`),A(`HTTP 状态码: ${e} ${s}`),A(`响应数据: ${JSON.stringify(o)}`),A("==================================\n"),404===e)throw new Error(`上传 API 不存在 (404): ${i}\n请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n当前配置的 API 路径: ${B}`)}else t.request&&A("请求已发送但未收到响应,请检查网络连接或代理配置。");throw t}}async publish2oss(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e},o=m.readdirSync(this.assetsRoot).map(async o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;try{const e=await this.uploadFile(i);o.indexOf("Model")>-1?s.modelAsset=e:o.endsWith(".css")?s.cssAsset=e:o.endsWith(".zip")?s.codeLib=e:s.asset=e}catch(e){A(`文件上传失败(${o}):\n`),process.exit(1)}}});return await Promise.all(o),s&&s.cmpType&&(console.info("上传至 OSS 的文件信息:\n",s),$(s)),s}async getCmpAssets(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e};return m.readdirSync(this.assetsRoot).forEach(o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;const r=5242880;if(n.size>r){const e=(n.size/1024/1024).toFixed(2),t=(r/1024/1024).toFixed(2);throw new Error(`${o} 文件大小超过限制: ${e}MB > ${t}MB`)}const a={fileContent:m.createReadStream(i),fileName:o,fileSize:n.size};o.indexOf("Model")>-1?s.modelAssetFile=a:o.endsWith(".css")?s.cssAssetFile=a:o.endsWith(".zip")?s.codeLibFile=a:s.assetFile=a}}),s}async updateCustomComponent(e){const t=await this.ensureValidToken();if(!e)throw new Error("componentData 不能为空");const s=y("正在保存自定义组件信息...").start();try{const o=this.saveAPI(),i=new d;e.assetFile&&i.append("assetFile",e.assetFile.fileContent,e.assetFile.fileName),e.modelAssetFile&&i.append("modelAssetFile",e.modelAssetFile.fileContent,e.modelAssetFile.fileName),e.cssAssetFile&&i.append("cssAssetFile",e.cssAssetFile.fileContent,e.cssAssetFile.fileName),e.codeLibFile&&i.append("codeLibFile",e.codeLibFile.fileContent,e.codeLibFile.fileName),i.append("component",JSON.stringify(w.omit(e,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])));const n=await l.post(o,i,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff",...i.getHeaders()},timeout:12e4,maxContentLength:1/0,maxBodyLength:1/0}),{code:r,message:a}=n.data||{};r&&200!==r&&(A(`保存自定义组件信息失败: ${n.data.message||"未知错误"}`),process.exit(1)),s.clear(),s.stop()}catch(e){e.message?A(`保存自定义组件信息失败: ${e.message}`,s):A(`保存自定义组件信息失败: ${JSON.stringify(e)}`,s),process.exit(1)}}async getCustomCmpList(){const e=await this.ensureValidToken();try{let t=this.buildFullUrl(P);t+=`&fields=${E.join(",")}`;const s=await l.get(t,{headers:{Authorization:`Bearer ${e}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:o,message:i}=s.data||{};o&&200!==o&&(A(`获取自定义组件列表失败: ${i||"未知错误"}`),process.exit(1)),this.updateCustomCmpList(s.data.data||[])}catch(e){e.message?A(`获取自定义组件列表失败: ${e.message}`):A(`响应数据: ${JSON.stringify(e)}`),process.exit(1)}return this.cmpList||[]}getCodeLibByCmpType(e){return e?this.buildFullUrl(U(e)):null}async deleteCmp(e){const t=await this.ensureValidToken();e||(A("自定义组件名称不能为空。"),process.exit(1));let s=this.buildFullUrl(b);s+=`/${e}`;const o=await l.delete(s,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:i,message:n}=o.data||{};return i&&200!==i&&(A(`删除自定义组件失败: ${n||"未知错误"}`),process.exit(1)),o.data}getCmpListByFramework(e){if(!e)return this.cmpList;const t=x(e);return this.cmpList.filter(e=>e.framework===t)}getCmpInfoByCmpType(e){return e&&this.cmpInfoMap[e]||null}updateCustomCmpList(e){e&&Array.isArray(e)&&(this.cmpList=e,e.forEach(e=>{this.cmpInfoMap[e.cmpType]=e}))}async request(e,t,s={}){const o=await this.ensureValidToken(),{data:i,headers:n={},params:r}=s,a=this.buildFullUrl(t);try{const t=await l({method:e,url:a,data:i,params:r,headers:{Authorization:`Bearer ${o}`,"xsy-inner-source":"bff",...n}});if(t.data&&t.data.code&&200!==t.data.code)throw new Error(`请求失败: ${t.data.message||"未知错误"}`);return t.data}catch(s){throw A(`请求失败 [${e} ${t}]: ${s.message}`),s.response&&A(`响应数据: ${JSON.stringify(s.response.data)}`),s}}async get(e,t={}){return await this.request("GET",e,t)}async post(e,t={}){return await this.request("POST",e,t)}async put(e,t={}){return await this.request("PUT",e,t)}async delete(e,t={}){return await this.request("DELETE",e,t)}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var e="1.8.21";const o={version:e};exports.default=o,exports.version=e;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var e="1.8.23";const o={version:e};exports.default=o,exports.version=e;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:fs"),t=require("node:path"),s=require("lodash"),o=require("akfun"),r=require("../pathUtils.js"),i=require("ora"),a=require("../../neo/neoService.js"),n=require("../common.js"),c=require("../projectUtils/createCmpProjectZip.js");var l,p;exports.__require=function(){if(p)return l;p=1;const u=e,g=t,d=s,{getConfigObj:m}=o,{catchCurPackageJson:w}=r.__require(),b=i,h=a.__require(),{getFramework:f,errorLog:y,successLog:C}=n.__require(),q=c.__require(),$=m(w()),T=(e=[])=>e.map(e=>({label:e.label,description:e.description,propSchema:JSON.stringify(e)}));return l=async(e,t)=>{const s=b("正在发布组件...").start();try{let o,r=new h(e);await r.ensureValidToken(),s.start("[1/4] 打包源码文件(含单个自定义组件源码)...");try{o=q(t,process.cwd(),e.assetsRoot),o?C(`[1/4] 源码文件打包完成: ${g.basename(o)}。`,s):y("[1/4] 源码文件打包失败,未返回 zip 文件路径。",s)}catch(e){y("[1/4] 源码文件打包失败。",s)}s.start("[2/4] 获取自定义组件构建产物...");const i=await r.getCmpAssets(t);let a;s.start("[3/4] 构建组件数据...");try{a=await(async(e,t)=>{if(!t||!t.cmpType)return y("自定义组件信息或组件名称不能为空"),null;const{cmpType:s}=t;if(!e||!u.existsSync(e))return y(`未找到自定义组件目录: ${e}`),null;const o=d.camelCase(s),r=g.join(e,`${o}Model.js`),i=globalThis.window;globalThis.window||(globalThis.window={console:console,neoRequire:()=>{},postMessage:()=>{}});try{u.existsSync(r)?require(r):(y(`未找到自定义组件模型文件,请检查以下路径是否存在:${r}`),process.exit(1)),globalThis.window&&globalThis.window.NEOEditorCustomModels||(y(`模型文件未导出有效模型方法(CatchCustomCmpModelClass),模型文件地址: ${r} `),process.exit(1));const e=globalThis.window.NEOEditorCustomModels[s];e||(y(`未找到自定义组件模型类(${s}),模型文件地址: ${r} `),process.exit(1));const o=new e;o||(y(`未找到自定义组件模型信息(${s}),模型文件地址: ${r} `),process.exit(1));const i={...t,version:$.version||"1.0.0",framework:$.framework?f($.framework):0,label:o.label||s,description:o.description||"",componentCategory:(o.tags||["自定义组件"]).join(","),targetPage:o.targetPage||["customPage"],targetObject:o.targetObject||["all"],targetApplication:o.targetApplication||["all"],targetDevice:o.targetDevice||"all",iconUrl:o.iconUrl||o.iconUrl,defaultProps:JSON.stringify(o.defaultComProps||{}),previewProps:JSON.stringify(o.previewComProps||{}),props:T(o.propsSchema||[]),events:o.events||[],functions:o.functions||o.actions||[],exposedToDesigner:void 0===o.exposedToDesigner||o.exposedToDesigner,namespace:o.namespace||"neo-cmp-cli",enableDuplicate:void 0===o.enableDuplicate||o.enableDuplicate};return console.log(`自定义组件模型信息(${s}):`,d.omit(i,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])),i}catch(e){return y(`自定义组件模型文件解析失败 (${r||"未知路径"}): ${e.message}`),y(e.stack),null}finally{void 0===i?delete globalThis.window:globalThis.window=i}})(e.assetsRoot,i),a?C("[3/4] 组件数据构建完成。",s):y(`[3/4] 未获取到自定义组件模型信息(${t})。`,s)}catch(e){y(`[3/4] 组件数据构建失败: ${e.message}`,s)}s.start("[4/4] 保存组件信息到 NeoCRM 平台...");try{await r.updateCustomComponent(a),C("[4/4] 组件信息保存成功",s)}catch(e){y("[4/4] 组件信息保存失败",s)}console.log("\n✅ 自定义组件发布成功!")}catch(e){try{s&&s.isSpinning&&y(`❌ 自定义组件发布失败: ${e.message}`,s)}catch{y(`\n❌ 自定义组件发布失败: ${e.message}`)}throw e}},l};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:fs"),t=require("node:path"),s=require("lodash"),o=require("akfun"),r=require("../pathUtils.js"),i=require("ora"),a=require("../../neo/neoService.js"),n=require("../common.js"),c=require("../projectUtils/createCmpProjectZip.js");var l,p;exports.__require=function(){if(p)return l;p=1;const u=e,g=t,d=s,{getConfigObj:m}=o,{catchCurPackageJson:w}=r.__require(),h=i,b=a.__require(),{getFramework:f,errorLog:y,successLog:C}=n.__require(),$=c.__require(),q=m(w()),T=(e=[])=>e.map(e=>({label:e.label,description:e.description,propSchema:JSON.stringify(e)}));return l=async(e,t)=>{const s=h("正在发布组件...").start();try{let o,r=new b(e);await r.ensureValidToken(),s.start("[1/4] 打包源码文件(含单个自定义组件源码)...");try{o=$(t,process.cwd(),e.assetsRoot),o?C(`[1/4] 源码文件打包完成: ${g.basename(o)}。`,s):y("[1/4] 源码文件打包失败,未返回 zip 文件路径。",s)}catch(e){y("[1/4] 源码文件打包失败。",s)}s.start("[2/4] 获取自定义组件构建产物...");const i=await r.getCmpAssets(t);let a;s.start("[3/4] 构建组件数据...");try{a=await(async(e,t)=>{if(!t||!t.cmpType)return y("自定义组件信息或组件名称不能为空"),null;const{cmpType:s}=t;if(!e||!u.existsSync(e))return y(`未找到自定义组件目录: ${e}`),null;const o=d.camelCase(s),r=g.join(e,`${o}Model.js`),i=globalThis.window;globalThis.window||(globalThis.window={console:console,neoRequire:()=>{},postMessage:()=>{}});try{u.existsSync(r)?require(r):(y(`未找到自定义组件模型文件,请检查以下路径是否存在:${r}`),process.exit(1)),globalThis.window&&globalThis.window.NEOEditorCustomModels||(y(`模型文件未导出有效模型方法(CatchCustomCmpModelClass),模型文件地址: ${r} `),process.exit(1));const e=globalThis.window.NEOEditorCustomModels[s];e||(y(`未找到自定义组件模型类(${s}),模型文件地址: ${r} `),process.exit(1));const o=new e;o||(y(`未找到自定义组件模型信息(${s}),模型文件地址: ${r} `),process.exit(1));const i={...t,version:q.version||"1.0.0",framework:q.framework?f(q.framework):0,label:o.label||s,description:o.description||"",componentCategory:(o.tags||["自定义组件"]).join(","),targetPage:o.targetPage||["customPage"],targetObject:o.targetObject||["all"],targetApplication:o.targetApplication||["all"],targetDevice:o.targetDevice||"all",iconUrl:o.iconUrl||o.iconUrl,defaultProps:JSON.stringify(o.defaultComProps||{}),previewProps:JSON.stringify(o.previewComProps||{}),props:T(o.propsSchema||[]),events:o.events||[],functions:o.functions||o.actions||[],exposedToDesigner:void 0===o.exposedToDesigner||o.exposedToDesigner,namespace:o.namespace||"neo-cmp-cli",enableDuplicate:void 0===o.enableDuplicate||o.enableDuplicate};return console.log(`自定义组件模型信息(${s}):`,d.omit(i,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])),i}catch(e){return y(`自定义组件模型文件解析失败 (${r||"未知路径"}): ${e.message}`),y(e.stack),null}finally{void 0===i?delete globalThis.window:globalThis.window=i}})(e.assetsRoot,i),a?C("[3/4] 组件数据构建完成。",s):y(`[3/4] 未获取到自定义组件模型信息(${t})。`,s)}catch(e){y(`[3/4] 组件数据构建失败: ${e.message}`,s)}s.start("[4/4] 保存组件信息到 NeoCRM 平台...");try{await r.updateCustomComponent(a),C("[4/4] 组件信息保存成功",s)}catch(e){y("[4/4] 组件信息保存失败",s)}const{tenant_id:n,instance_uri:c}=r.tokenCache||{};console.log(`\n✅ 自定义组件发布成功!\n(当前租户 ID: ${n},所在租户的 API 域名: ${c}。)`)}catch(e){try{s&&s.isSpinning&&y(`❌ 自定义组件发布失败: ${e.message}`,s)}catch{y(`\n❌ 自定义组件发布失败: ${e.message}`)}throw e}},l};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-cmp-cli",
3
- "version": "1.8.21",
3
+ "version": "1.8.23",
4
4
  "description": "Neo 自定义组件开发工具,支持react 和 vue2.0技术栈。",
5
5
  "keywords": [
6
6
  "neo-cli",
@@ -48,7 +48,7 @@
48
48
  "@commitlint/config-conventional": "^9.1.1",
49
49
  "@types/react": "^16.9.11",
50
50
  "@types/react-dom": "^16.9.15",
51
- "neo-cmp-cli": "^1.8.20",
51
+ "neo-cmp-cli": "^1.8.23",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5"
@@ -48,7 +48,7 @@
48
48
  "@commitlint/config-conventional": "^9.1.1",
49
49
  "@types/react": "^16.9.11",
50
50
  "@types/react-dom": "^16.9.15",
51
- "neo-cmp-cli": "^1.8.20",
51
+ "neo-cmp-cli": "^1.8.23",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5",
@@ -46,7 +46,7 @@
46
46
  "@commitlint/config-conventional": "^9.1.1",
47
47
  "@types/react": "^16.9.11",
48
48
  "@types/react-dom": "^16.9.15",
49
- "neo-cmp-cli": "^1.8.20",
49
+ "neo-cmp-cli": "^1.8.23",
50
50
  "husky": "^4.2.5",
51
51
  "lint-staged": "^10.2.9",
52
52
  "prettier": "^2.0.5"
@@ -54,7 +54,7 @@
54
54
  "@types/react": "^16.9.11",
55
55
  "@types/react-dom": "^16.9.15",
56
56
  "@types/axios": "^0.14.0",
57
- "neo-cmp-cli": "^1.8.20",
57
+ "neo-cmp-cli": "^1.8.23",
58
58
  "husky": "^4.2.5",
59
59
  "lint-staged": "^10.2.9",
60
60
  "prettier": "^2.0.5"
@@ -23,11 +23,13 @@ import {
23
23
  ReloadOutlined,
24
24
  CheckCircleOutlined,
25
25
  } from '@ant-design/icons';
26
- import moment from 'moment';
27
26
  // @ts-ignore
28
27
  import { xObject } from 'neo-open-api'; // Neo Open API
29
28
  // @ts-ignore
30
29
  import isEqual from 'lodash/isEqual';
30
+ // 引入 neo-ui-common / aop
31
+ // @ts-ignore
32
+ import { aop } from 'neo-ui-common';
31
33
  import './style.scss';
32
34
 
33
35
  const { Option } = Select;
@@ -131,7 +133,7 @@ export default class EntityForm extends React.PureComponent<
131
133
  componentDidMount() {
132
134
  const { xObjectDataApi } = this.props;
133
135
  const { xObjectApiKey } = xObjectDataApi || {};
134
-
136
+
135
137
  if (xObjectApiKey) {
136
138
  // 初始化字段列表和业务类型列表
137
139
  this.getEntityTypeList(xObjectApiKey);
@@ -228,6 +230,14 @@ export default class EntityForm extends React.PureComponent<
228
230
  }
229
231
  }
230
232
 
233
+ /**
234
+ * 表单提交事件
235
+ */
236
+ @aop
237
+ submit() {
238
+ console.log('触发了表单提交事件:', this.props);
239
+ }
240
+
231
241
  /**
232
242
  * 处理表单提交
233
243
  * 执行新增操作
@@ -295,6 +305,9 @@ export default class EntityForm extends React.PureComponent<
295
305
  message.error('创建失败');
296
306
  this.setState({ submitting: false });
297
307
  }
308
+
309
+ // 触发表单提交事件
310
+ this.submit();
298
311
  });
299
312
  }
300
313
 
@@ -33,7 +33,9 @@ export class EntityFormModel {
33
33
  * customPage: 6 自定义页面
34
34
  * bizPage: 7 业务页面
35
35
  */
36
- // targetPage: string[] = ['customPage'];
36
+ targetPage: string[] = ['all'];
37
+
38
+ enableDuplicate: boolean = true;
37
39
 
38
40
  /** 组件图标,用于设置在编辑器左侧组件面板中展示的图标 */
39
41
  iconUrl: string = 'https://custom-widgets.bj.bcebos.com/custom-form.svg';
@@ -49,6 +51,25 @@ export class EntityFormModel {
49
51
  },
50
52
  };
51
53
 
54
+ /**
55
+ * 声明当前组件会触发的所有事件
56
+ */
57
+ events = [
58
+ {
59
+ helpText: '点击页签后触发该事件',
60
+ apiKey: 'onChange',
61
+ description: '点击页签触发该事件',
62
+ label: '页签切换后',
63
+ // cmpKeyIdentifier: '',
64
+ // helpTextKey: '',
65
+ // eventCategory: 2,
66
+ // pageType: 1,
67
+ // targetDevice: 1,
68
+ // eventParams: '[{"apiKey":"eventParam","children":[{"apiKey":"target","label":"组件名称","type":"string"},{"apiKey":"cmp","label":"组件实例","type":"Object"},{"apiKey":"data","children":[{"apiKey":"tabKey","label":"页签key","type":"string"}],"label":"数据","type":"Object"}],"label":"事件入参","type":"Object"}]',
69
+ // labelKey: 'XdMDNeoEvent.NeoTabContainer.onChange'
70
+ },
71
+ ];
72
+
52
73
  /**
53
74
  * 组件属性配置模式
54
75
  * 支持静态配置:propsSchema,优先级比 propsSchemaCreator 低
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@commitlint/cli": "^8.3.5",
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
- "neo-cmp-cli": "^1.8.20",
48
+ "neo-cmp-cli": "^1.8.23",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5"
@@ -47,7 +47,7 @@
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
48
  "@types/react": "^16.9.11",
49
49
  "@types/react-dom": "^16.9.15",
50
- "neo-cmp-cli": "^1.8.20",
50
+ "neo-cmp-cli": "^1.8.23",
51
51
  "husky": "^4.2.5",
52
52
  "lint-staged": "^10.2.9",
53
53
  "prettier": "^2.0.5"
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@commitlint/cli": "^8.3.5",
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
- "neo-cmp-cli": "^1.8.20",
48
+ "neo-cmp-cli": "^1.8.23",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5",
@@ -1,7 +1,7 @@
1
1
  const { execSync } = require('child_process');
2
2
 
3
3
  // 所有需要废弃的版本
4
- const versionsToDeprecate = ["1.8.15", "1.8.17", "1.8.18"];
4
+ const versionsToDeprecate = ["1.8.15", "1.8.17", "1.8.18", "1.8.19", "1.8.20", "1.8.21"];
5
5
 
6
6
  const packageName = 'neo-cmp-cli';
7
7
  const deprecateMessage = '此版本为开发中版本(存在 bug),请升级到最新版本。';