museav-cli 2.7.0 → 2.8.0
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/CHANGELOG.md +14 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.js +35 -0
- package/dist/commands/poster-templates.d.ts +11 -0
- package/dist/commands/poster-templates.js +23 -0
- package/dist/commands/stickers.d.ts +10 -0
- package/dist/commands/stickers.js +22 -0
- package/dist/index.js +21 -0
- package/package.json +1 -1
- package/src/client.ts +41 -0
- package/src/commands/poster-templates.ts +33 -0
- package/src/commands/stickers.ts +29 -0
- package/src/index.ts +25 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.8.0 (2026-08-27)
|
|
4
|
+
|
|
5
|
+
### 新增:贴图素材 + 版式模板命令(租户级资产,给封面/海报工具用)
|
|
6
|
+
|
|
7
|
+
两个新命令,底层调中台 `/api/stickers` 和 `/api/poster-templates`,账户 Key / 租户 Key 均可(落到本租户)。
|
|
8
|
+
|
|
9
|
+
- `museav stickers`:列出本租户贴图素材(PNG 透明装饰图)
|
|
10
|
+
- `museav stickers add <file> --name <名称>`:上传贴图(不压缩,保留透明通道)
|
|
11
|
+
- `museav poster-templates`:列出版式模板(封面底图 + 固定描述)
|
|
12
|
+
- `museav poster-templates add <file> --name <名称> --prompt <描述>`:保存版式(`{城市}` `{明星}` 占位符会被替换)
|
|
13
|
+
|
|
14
|
+
背景:好易美(hym)的闲鱼封面工具此前版式存学员本机桌面、贴图只在后台本地,无法共享。
|
|
15
|
+
现在贴图素材 + 版式模板收归中台,CLI 一条命令加载/保存,学员间共享。
|
|
16
|
+
|
|
3
17
|
## 2.7.0 (2026-08-27)
|
|
4
18
|
|
|
5
19
|
### 修复:`remove-bg` 抠不出主体(三个静默 bug)
|
package/dist/client.d.ts
CHANGED
|
@@ -337,6 +337,18 @@ export declare class StudioClient {
|
|
|
337
337
|
createTemplate(input: CreateTemplateInput): Promise<TemplateOption>;
|
|
338
338
|
/** 新建视频模板。归属同图片模板:租户 apiKey 自动归租户,平台管理员归平台共享 */
|
|
339
339
|
createVideoTemplate(input: CreateVideoTemplateInput): Promise<TemplateOption>;
|
|
340
|
+
/** 贴图素材清单(租户级资产,服务端已按调用者权限过滤)。PNG 装饰图,叠加在海报/封面上 */
|
|
341
|
+
stickers(): Promise<any[]>;
|
|
342
|
+
/** 上传贴图素材(不压缩——透明 PNG 压缩会破坏透明通道) */
|
|
343
|
+
createSticker(filePath: string, name: string): Promise<any>;
|
|
344
|
+
/** 删除贴图素材 */
|
|
345
|
+
deleteSticker(id: string): Promise<void>;
|
|
346
|
+
/** 版式模板清单(租户级资产):封面底图 + 固定描述({城市}{明星} 占位符) */
|
|
347
|
+
posterTemplates(): Promise<any[]>;
|
|
348
|
+
/** 上传版式模板(不压缩,保留封面底图原样) */
|
|
349
|
+
createPosterTemplate(filePath: string, name: string, prompt: string): Promise<any>;
|
|
350
|
+
/** 删除版式模板 */
|
|
351
|
+
deletePosterTemplate(id: string): Promise<void>;
|
|
340
352
|
/** 提交出图任务,立即返回 jobId */
|
|
341
353
|
generate(opts: GenerateOptions): Promise<{
|
|
342
354
|
jobId: string;
|
package/dist/client.js
CHANGED
|
@@ -125,6 +125,41 @@ export class StudioClient {
|
|
|
125
125
|
});
|
|
126
126
|
return r.row;
|
|
127
127
|
}
|
|
128
|
+
/** 贴图素材清单(租户级资产,服务端已按调用者权限过滤)。PNG 装饰图,叠加在海报/封面上 */
|
|
129
|
+
async stickers() {
|
|
130
|
+
const r = await this.request('stickers');
|
|
131
|
+
return Array.isArray(r) ? r : [];
|
|
132
|
+
}
|
|
133
|
+
/** 上传贴图素材(不压缩——透明 PNG 压缩会破坏透明通道) */
|
|
134
|
+
async createSticker(filePath, name) {
|
|
135
|
+
const blob = new Blob([new Uint8Array(readFileSync(filePath))]);
|
|
136
|
+
const fd = new FormData();
|
|
137
|
+
fd.append('file', blob, basename(filePath));
|
|
138
|
+
fd.append('name', name);
|
|
139
|
+
return this.request('stickers', { method: 'POST', body: fd });
|
|
140
|
+
}
|
|
141
|
+
/** 删除贴图素材 */
|
|
142
|
+
async deleteSticker(id) {
|
|
143
|
+
await this.request(`stickers?id=${encodeURIComponent(id)}`, { method: 'DELETE' });
|
|
144
|
+
}
|
|
145
|
+
/** 版式模板清单(租户级资产):封面底图 + 固定描述({城市}{明星} 占位符) */
|
|
146
|
+
async posterTemplates() {
|
|
147
|
+
const r = await this.request('poster-templates');
|
|
148
|
+
return Array.isArray(r) ? r : [];
|
|
149
|
+
}
|
|
150
|
+
/** 上传版式模板(不压缩,保留封面底图原样) */
|
|
151
|
+
async createPosterTemplate(filePath, name, prompt) {
|
|
152
|
+
const blob = new Blob([new Uint8Array(readFileSync(filePath))]);
|
|
153
|
+
const fd = new FormData();
|
|
154
|
+
fd.append('file', blob, basename(filePath));
|
|
155
|
+
fd.append('name', name);
|
|
156
|
+
fd.append('prompt', prompt);
|
|
157
|
+
return this.request('poster-templates', { method: 'POST', body: fd });
|
|
158
|
+
}
|
|
159
|
+
/** 删除版式模板 */
|
|
160
|
+
async deletePosterTemplate(id) {
|
|
161
|
+
await this.request(`poster-templates?id=${encodeURIComponent(id)}`, { method: 'DELETE' });
|
|
162
|
+
}
|
|
128
163
|
/** 提交出图任务,立即返回 jobId */
|
|
129
164
|
async generate(opts) {
|
|
130
165
|
// prompt / skill_slug / template_id 三选一:都传时服务端按 prompt > template_id > skill_slug
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* museav poster-templates —— 版式模板库(租户级资产)。
|
|
3
|
+
* 封面底图 + 固定描述({城市} {明星} 占位符),选版式时把城市/明星名填进底图。
|
|
4
|
+
* 学员做的封面版式保存后全租户共享。
|
|
5
|
+
*/
|
|
6
|
+
import type { StudioClient } from '../client.js';
|
|
7
|
+
export declare function posterTemplates(client: StudioClient): Promise<void>;
|
|
8
|
+
export declare function createPosterTemplate(client: StudioClient, filePath: string, opts: {
|
|
9
|
+
name: string;
|
|
10
|
+
prompt: string;
|
|
11
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export async function posterTemplates(client) {
|
|
2
|
+
const list = await client.posterTemplates();
|
|
3
|
+
if (!list.length) {
|
|
4
|
+
process.stderr.write('没有版式模板(可用 museav poster-templates add <底图> --name <名称> --prompt <描述> 保存)\n');
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
process.stderr.write(`版式模板(${list.length} 个):\n`);
|
|
8
|
+
for (const t of list) {
|
|
9
|
+
process.stderr.write(` ${t.id.padEnd(38)} ${String(t.name || '').padEnd(18)} ${String(t.prompt || '').slice(0, 40)}\n`);
|
|
10
|
+
}
|
|
11
|
+
process.stderr.write(`\n保存: museav poster-templates add <底图路径> --name <名称> --prompt <描述>\n`);
|
|
12
|
+
console.log(list.map((t) => t.id).join('\n'));
|
|
13
|
+
}
|
|
14
|
+
export async function createPosterTemplate(client, filePath, opts) {
|
|
15
|
+
if (!opts.name?.trim())
|
|
16
|
+
throw new Error('--name 必填');
|
|
17
|
+
if (!opts.prompt?.trim())
|
|
18
|
+
throw new Error('--prompt 必填,{城市} {明星} 占位符会被替换');
|
|
19
|
+
const row = await client.createPosterTemplate(filePath, opts.name, opts.prompt);
|
|
20
|
+
const id = row?.template?.id || row?.id || '';
|
|
21
|
+
process.stderr.write(`✅ 版式模板已保存:${id}\n`);
|
|
22
|
+
console.log(id);
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* museav stickers —— 贴图素材库(租户级资产)。
|
|
3
|
+
* PNG 透明装饰图(logo/花纹/边框),叠加在海报/封面上。
|
|
4
|
+
* 列出的都是自己租户的贴图;上传用账户 Key 或租户 Key 均可(落到本租户)。
|
|
5
|
+
*/
|
|
6
|
+
import type { StudioClient } from '../client.js';
|
|
7
|
+
export declare function stickers(client: StudioClient): Promise<void>;
|
|
8
|
+
export declare function createSticker(client: StudioClient, filePath: string, opts: {
|
|
9
|
+
name: string;
|
|
10
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export async function stickers(client) {
|
|
2
|
+
const list = await client.stickers();
|
|
3
|
+
if (!list.length) {
|
|
4
|
+
process.stderr.write('没有贴图素材(可用 museav stickers add <图片> --name <名称> 上传)\n');
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
process.stderr.write(`贴图素材(${list.length} 个):\n`);
|
|
8
|
+
for (const s of list) {
|
|
9
|
+
process.stderr.write(` ${s.id.padEnd(38)} ${String(s.name || '').padEnd(20)} ${s.url || ''}\n`);
|
|
10
|
+
}
|
|
11
|
+
process.stderr.write(`\n上传: museav stickers add <图片路径> --name <名称>\n`);
|
|
12
|
+
// stdout 只出 id,便于脚本与 agent 解析
|
|
13
|
+
console.log(list.map((s) => s.id).join('\n'));
|
|
14
|
+
}
|
|
15
|
+
export async function createSticker(client, filePath, opts) {
|
|
16
|
+
if (!opts.name?.trim())
|
|
17
|
+
throw new Error('--name 必填');
|
|
18
|
+
const row = await client.createSticker(filePath, opts.name);
|
|
19
|
+
const id = row?.sticker?.id || row?.id || '';
|
|
20
|
+
process.stderr.write(`✅ 贴图素材已上传:${id}\n`);
|
|
21
|
+
console.log(id);
|
|
22
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ import { jobs } from './commands/jobs.js';
|
|
|
28
28
|
import { whoami } from './commands/whoami.js';
|
|
29
29
|
import { products } from './commands/products.js';
|
|
30
30
|
import { assets } from './commands/assets.js';
|
|
31
|
+
import { stickers, createSticker } from './commands/stickers.js';
|
|
32
|
+
import { posterTemplates, createPosterTemplate } from './commands/poster-templates.js';
|
|
31
33
|
import { speak, transcribeCmd } from './commands/speak.js';
|
|
32
34
|
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
33
35
|
// 每 12 小时最多查一次 npm registry,过期才提示,不拖慢日常调用
|
|
@@ -315,6 +317,25 @@ templatesCmd
|
|
|
315
317
|
.option('--fields <json>', '占位符字段说明,JSON 数组,如 \'[{"key":"artist","label":"艺人名"}]\';不传则自动从 --prompt 里的 {key} 提取')
|
|
316
318
|
.option('--type <type>', '模板类型:image(图片,默认) / article(文字)')
|
|
317
319
|
.action(withClient((client, opts) => createTemplate(client, opts)));
|
|
320
|
+
const stickersCmd = program
|
|
321
|
+
.command('stickers')
|
|
322
|
+
.description('查贴图素材库(租户级资产:PNG 装饰图,叠加在海报/封面上)')
|
|
323
|
+
.action(withClient((client) => stickers(client)));
|
|
324
|
+
stickersCmd
|
|
325
|
+
.command('add <file>')
|
|
326
|
+
.description('上传贴图素材(PNG 透明装饰图,不压缩保留透明通道)')
|
|
327
|
+
.requiredOption('--name <名称>', '贴图名称')
|
|
328
|
+
.action(withClient((client, file, opts) => createSticker(client, file, opts)));
|
|
329
|
+
const posterTemplatesCmd = program
|
|
330
|
+
.command('poster-templates')
|
|
331
|
+
.description('查版式模板库(租户级资产:封面底图 + 固定描述,选版式把城市/明星名填进底图)')
|
|
332
|
+
.action(withClient((client) => posterTemplates(client)));
|
|
333
|
+
posterTemplatesCmd
|
|
334
|
+
.command('add <file>')
|
|
335
|
+
.description('保存版式模板(封面底图 + 描述,描述里用 {城市} {明星} 占位)')
|
|
336
|
+
.requiredOption('--name <名称>', '版式名称')
|
|
337
|
+
.requiredOption('--prompt <描述>', '版式固定描述,{城市} {明星} 会自动替换')
|
|
338
|
+
.action(withClient((client, file, opts) => createPosterTemplate(client, file, opts)));
|
|
318
339
|
program
|
|
319
340
|
.command('products')
|
|
320
341
|
.description('查所属租户自己的产品目录(数据在租户自己的后台,不在 Studio 中台;只支持已开通该接口的租户,仅租户 apiKey 身份可用)')
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -432,6 +432,47 @@ export class StudioClient {
|
|
|
432
432
|
return r.row
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
+
/** 贴图素材清单(租户级资产,服务端已按调用者权限过滤)。PNG 装饰图,叠加在海报/封面上 */
|
|
436
|
+
async stickers(): Promise<any[]> {
|
|
437
|
+
const r = await this.request('stickers')
|
|
438
|
+
return Array.isArray(r) ? r : []
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/** 上传贴图素材(不压缩——透明 PNG 压缩会破坏透明通道) */
|
|
442
|
+
async createSticker(filePath: string, name: string): Promise<any> {
|
|
443
|
+
const blob = new Blob([new Uint8Array(readFileSync(filePath))])
|
|
444
|
+
const fd = new FormData()
|
|
445
|
+
fd.append('file', blob, basename(filePath))
|
|
446
|
+
fd.append('name', name)
|
|
447
|
+
return this.request('stickers', { method: 'POST', body: fd })
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** 删除贴图素材 */
|
|
451
|
+
async deleteSticker(id: string): Promise<void> {
|
|
452
|
+
await this.request(`stickers?id=${encodeURIComponent(id)}`, { method: 'DELETE' })
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/** 版式模板清单(租户级资产):封面底图 + 固定描述({城市}{明星} 占位符) */
|
|
456
|
+
async posterTemplates(): Promise<any[]> {
|
|
457
|
+
const r = await this.request('poster-templates')
|
|
458
|
+
return Array.isArray(r) ? r : []
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** 上传版式模板(不压缩,保留封面底图原样) */
|
|
462
|
+
async createPosterTemplate(filePath: string, name: string, prompt: string): Promise<any> {
|
|
463
|
+
const blob = new Blob([new Uint8Array(readFileSync(filePath))])
|
|
464
|
+
const fd = new FormData()
|
|
465
|
+
fd.append('file', blob, basename(filePath))
|
|
466
|
+
fd.append('name', name)
|
|
467
|
+
fd.append('prompt', prompt)
|
|
468
|
+
return this.request('poster-templates', { method: 'POST', body: fd })
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** 删除版式模板 */
|
|
472
|
+
async deletePosterTemplate(id: string): Promise<void> {
|
|
473
|
+
await this.request(`poster-templates?id=${encodeURIComponent(id)}`, { method: 'DELETE' })
|
|
474
|
+
}
|
|
475
|
+
|
|
435
476
|
/** 提交出图任务,立即返回 jobId */
|
|
436
477
|
async generate(opts: GenerateOptions): Promise<{ jobId: string; trace_id?: string }> {
|
|
437
478
|
// prompt / skill_slug / template_id 三选一:都传时服务端按 prompt > template_id > skill_slug
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* museav poster-templates —— 版式模板库(租户级资产)。
|
|
3
|
+
* 封面底图 + 固定描述({城市} {明星} 占位符),选版式时把城市/明星名填进底图。
|
|
4
|
+
* 学员做的封面版式保存后全租户共享。
|
|
5
|
+
*/
|
|
6
|
+
import type { StudioClient } from '../client.js'
|
|
7
|
+
|
|
8
|
+
export async function posterTemplates(client: StudioClient): Promise<void> {
|
|
9
|
+
const list = await client.posterTemplates()
|
|
10
|
+
if (!list.length) {
|
|
11
|
+
process.stderr.write('没有版式模板(可用 museav poster-templates add <底图> --name <名称> --prompt <描述> 保存)\n')
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
process.stderr.write(`版式模板(${list.length} 个):\n`)
|
|
15
|
+
for (const t of list) {
|
|
16
|
+
process.stderr.write(` ${t.id.padEnd(38)} ${String(t.name || '').padEnd(18)} ${String(t.prompt || '').slice(0, 40)}\n`)
|
|
17
|
+
}
|
|
18
|
+
process.stderr.write(`\n保存: museav poster-templates add <底图路径> --name <名称> --prompt <描述>\n`)
|
|
19
|
+
console.log(list.map((t) => t.id).join('\n'))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function createPosterTemplate(
|
|
23
|
+
client: StudioClient,
|
|
24
|
+
filePath: string,
|
|
25
|
+
opts: { name: string; prompt: string },
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
if (!opts.name?.trim()) throw new Error('--name 必填')
|
|
28
|
+
if (!opts.prompt?.trim()) throw new Error('--prompt 必填,{城市} {明星} 占位符会被替换')
|
|
29
|
+
const row = await client.createPosterTemplate(filePath, opts.name, opts.prompt)
|
|
30
|
+
const id = row?.template?.id || row?.id || ''
|
|
31
|
+
process.stderr.write(`✅ 版式模板已保存:${id}\n`)
|
|
32
|
+
console.log(id)
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* museav stickers —— 贴图素材库(租户级资产)。
|
|
3
|
+
* PNG 透明装饰图(logo/花纹/边框),叠加在海报/封面上。
|
|
4
|
+
* 列出的都是自己租户的贴图;上传用账户 Key 或租户 Key 均可(落到本租户)。
|
|
5
|
+
*/
|
|
6
|
+
import type { StudioClient } from '../client.js'
|
|
7
|
+
|
|
8
|
+
export async function stickers(client: StudioClient): Promise<void> {
|
|
9
|
+
const list = await client.stickers()
|
|
10
|
+
if (!list.length) {
|
|
11
|
+
process.stderr.write('没有贴图素材(可用 museav stickers add <图片> --name <名称> 上传)\n')
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
process.stderr.write(`贴图素材(${list.length} 个):\n`)
|
|
15
|
+
for (const s of list) {
|
|
16
|
+
process.stderr.write(` ${s.id.padEnd(38)} ${String(s.name || '').padEnd(20)} ${s.url || ''}\n`)
|
|
17
|
+
}
|
|
18
|
+
process.stderr.write(`\n上传: museav stickers add <图片路径> --name <名称>\n`)
|
|
19
|
+
// stdout 只出 id,便于脚本与 agent 解析
|
|
20
|
+
console.log(list.map((s) => s.id).join('\n'))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function createSticker(client: StudioClient, filePath: string, opts: { name: string }): Promise<void> {
|
|
24
|
+
if (!opts.name?.trim()) throw new Error('--name 必填')
|
|
25
|
+
const row = await client.createSticker(filePath, opts.name)
|
|
26
|
+
const id = row?.sticker?.id || row?.id || ''
|
|
27
|
+
process.stderr.write(`✅ 贴图素材已上传:${id}\n`)
|
|
28
|
+
console.log(id)
|
|
29
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,8 @@ import { jobs } from './commands/jobs.js'
|
|
|
28
28
|
import { whoami } from './commands/whoami.js'
|
|
29
29
|
import { products } from './commands/products.js'
|
|
30
30
|
import { assets } from './commands/assets.js'
|
|
31
|
+
import { stickers, createSticker } from './commands/stickers.js'
|
|
32
|
+
import { posterTemplates, createPosterTemplate } from './commands/poster-templates.js'
|
|
31
33
|
import { speak, transcribeCmd } from './commands/speak.js'
|
|
32
34
|
|
|
33
35
|
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8')) as { name: string; version: string }
|
|
@@ -345,6 +347,29 @@ templatesCmd
|
|
|
345
347
|
.option('--type <type>', '模板类型:image(图片,默认) / article(文字)')
|
|
346
348
|
.action(withClient((client: StudioClient, opts: any) => createTemplate(client, opts)))
|
|
347
349
|
|
|
350
|
+
const stickersCmd = program
|
|
351
|
+
.command('stickers')
|
|
352
|
+
.description('查贴图素材库(租户级资产:PNG 装饰图,叠加在海报/封面上)')
|
|
353
|
+
.action(withClient((client: StudioClient) => stickers(client)))
|
|
354
|
+
|
|
355
|
+
stickersCmd
|
|
356
|
+
.command('add <file>')
|
|
357
|
+
.description('上传贴图素材(PNG 透明装饰图,不压缩保留透明通道)')
|
|
358
|
+
.requiredOption('--name <名称>', '贴图名称')
|
|
359
|
+
.action(withClient((client: StudioClient, file: string, opts: any) => createSticker(client, file, opts)))
|
|
360
|
+
|
|
361
|
+
const posterTemplatesCmd = program
|
|
362
|
+
.command('poster-templates')
|
|
363
|
+
.description('查版式模板库(租户级资产:封面底图 + 固定描述,选版式把城市/明星名填进底图)')
|
|
364
|
+
.action(withClient((client: StudioClient) => posterTemplates(client)))
|
|
365
|
+
|
|
366
|
+
posterTemplatesCmd
|
|
367
|
+
.command('add <file>')
|
|
368
|
+
.description('保存版式模板(封面底图 + 描述,描述里用 {城市} {明星} 占位)')
|
|
369
|
+
.requiredOption('--name <名称>', '版式名称')
|
|
370
|
+
.requiredOption('--prompt <描述>', '版式固定描述,{城市} {明星} 会自动替换')
|
|
371
|
+
.action(withClient((client: StudioClient, file: string, opts: any) => createPosterTemplate(client, file, opts)))
|
|
372
|
+
|
|
348
373
|
program
|
|
349
374
|
.command('products')
|
|
350
375
|
.description('查所属租户自己的产品目录(数据在租户自己的后台,不在 Studio 中台;只支持已开通该接口的租户,仅租户 apiKey 身份可用)')
|