@xqyz/xq-cli 0.3.3 → 0.3.5

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +1 -1
  3. package/src/cli.mjs +136 -25
package/CHANGELOG.md CHANGED
@@ -8,6 +8,44 @@
8
8
 
9
9
  发布日期以 npm 官方仓库记录为准。发布前必须先更新本文件,再执行版本发布。
10
10
 
11
+ ## [Unreleased]
12
+
13
+ ## [0.3.5 / WorkBuddy Plugin 0.10.11] - 2026-08-20(待发布)
14
+
15
+ ### 文件解析与多标包统一配置
16
+
17
+ - 修复 `xq-cli init --wait` 未识别 Web 端 `success=2`(解析完成、进入标书设置)的错误,避免 WorkBuddy 在文件已经解析完成后仍反复查询并最终超时。
18
+ - WorkBuddy 新任务改为先调用一次 `xique_prepare_source`,解析完成后在同一配置页展示后台真实返回的多标包 / EPC 选项和全部普通配置。
19
+ - 用户提交配置后复用原 `runId`、`cid` 和 `uuid` 启动大纲,不再重复上传文件、重复创建任务或二次选择标包。
20
+ - 普通文件不显示多标包 / EPC 占位字段;提交的标包和 EPC 值必须来自本次解析结果,禁止手工构造 ID。
21
+
22
+ ### 暗标生成方式
23
+
24
+ - xq-cli 新增 `--blind-generation-mode normal|blind`,并保留 `--anonymous-bid` 兼容别名。
25
+ - WorkBuddy 配置页新增“按通用方式生成 / 按暗标生成”,默认通用方式;选择会真实写入大纲请求的 `blindBidConfirm`,不再只停留在界面字段。
26
+ - 新增回归测试覆盖 `success=2`、真实多标包统一配置、同一任务复用、重复提交拦截和暗标请求体。
27
+
28
+ ### 导出格式二次设置
29
+
30
+ - xq-cli 导出新增 `imageSizeConfig`,支持横向/纵向图片宽度和最大高度四项厘米参数,并与页边距一起写入 `/c/downWithStyle`。
31
+ - WorkBuddy 新增 `xique_export_configuration` 二次导出设置卡:正文完成后可视化设置标题/正文编号、字体、对齐、起始编号、页边距和图片尺寸,再经确认重新下载,不会重新生成任务。
32
+ - 模板5不再在 WorkBuddy 中禁用;编号设置由卡片生成结构化 `customNumbering`,不要求用户填写高级样式 JSON。
33
+
34
+ ## [0.3.4 / WorkBuddy Plugin 0.10.10] - 2026-08-19
35
+
36
+ ### 快速模式新任务生成链路修复
37
+
38
+ - 对齐喜鹊 Web:新任务先调用 `/task/preSet` 保存用户配置,其中 `requirement`、`rating`、`plan` 允许为空;随后调用 `/proxy/multiBiddingChoice` 触发后台解析流程。
39
+ - 禁止新任务由 xq-cli 直接调用 `/task/generateByRequirement`,避免抢在 `autoGenerateDirectoryJobHandler` 补齐解析结果之前提交空字段,造成任务停留在大纲解析阶段。
40
+ - 保留历史任务兼容逻辑:仅 `task_status=0` 继续直接调用 `/task/generateByRequirement`。
41
+ - 新增新任务与历史任务两条回归测试。
42
+
43
+ ### WorkBuddy 响应依据完整预览
44
+
45
+ - “选择大纲依据”卡片改为三个页签:融合响应、仅格式要求、仅评分要求。
46
+ - 页签切换只读取后端返回的完整候选目录树,不会提交 `referenceType` 或改变任务状态。
47
+ - 用户只有点击“按当前思路生成大纲”才会调用既有单次提交链路;仍保留重复提交拦截。
48
+
11
49
  ## [0.3.3 / WorkBuddy Plugin 0.10.9] - 2026-08-19
12
50
 
13
51
  ### WorkBuddy 响应依据阶段化选择
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xqyz/xq-cli",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "CLI for xique bid-book task workflows",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/cli.mjs CHANGED
@@ -127,6 +127,12 @@ const DEFAULT_PAGE_MARGIN_SETTING = {
127
127
  leftMargin: 3.18,
128
128
  rightMargin: 3.18,
129
129
  };
130
+ const DEFAULT_IMAGE_SIZE_CONFIG = {
131
+ landscapeWidth: 10.58,
132
+ landscapeMaxHeight: 8,
133
+ portraitWidth: 5.5,
134
+ portraitMaxHeight: 8,
135
+ };
130
136
  const OUTLINE_REFERENCE_OPTIONS = [
131
137
  {
132
138
  value: 0,
@@ -205,6 +211,10 @@ const PLAN_MODE_OPTIONS = [
205
211
  { value: 0, label: 'quick', description: 'quick mode', aliases: ['0', 'quick'] },
206
212
  { value: 1, label: 'planning', description: 'planning mode', aliases: ['1', 'planning', 'plan'] },
207
213
  ];
214
+ const BLIND_GENERATION_MODE_OPTIONS = [
215
+ { value: 'normal', label: 'normal', description: 'general bid generation', aliases: ['normal', 'general', '0', 'open'] },
216
+ { value: 'blind', label: 'blind', description: 'blind-bid protected generation', aliases: ['blind', 'anonymous', '1'] },
217
+ ];
208
218
  const PLAN_MODE_PHASE_LABELS = {
209
219
  0: 'analysis',
210
220
  1: 'outline',
@@ -238,6 +248,12 @@ const PAGE_MARGIN_FIELDS = [
238
248
  { key: 'leftMargin', optionKeys: ['leftMargin', 'marginLeft'] },
239
249
  { key: 'rightMargin', optionKeys: ['rightMargin', 'marginRight'] },
240
250
  ];
251
+ const IMAGE_SIZE_FIELDS = [
252
+ { key: 'landscapeWidth', optionKeys: ['landscapeWidth', 'imageLandscapeWidth'] },
253
+ { key: 'landscapeMaxHeight', optionKeys: ['landscapeMaxHeight', 'imageLandscapeMaxHeight'] },
254
+ { key: 'portraitWidth', optionKeys: ['portraitWidth', 'imagePortraitWidth'] },
255
+ { key: 'portraitMaxHeight', optionKeys: ['portraitMaxHeight', 'imagePortraitMaxHeight'] },
256
+ ];
241
257
  const EXPORT_TEMPLATE_OPTIONS = templateData.map((template, index) => ({
242
258
  value: index + 1,
243
259
  label: `template-${index + 1}`,
@@ -514,13 +530,16 @@ Outline config
514
530
  --knowledge-img <0|1> knowledge-base image toggle
515
531
  --mermaid-style <1|2|3|4|5|6|gray|purple|blue|green|orange|red>
516
532
  --plan-mode <0|1|quick|planning>
533
+ --blind-generation-mode <normal|blind> Bid body generation mode; default normal
534
+ --anonymous-bid <0|1> Deprecated alias of --blind-generation-mode
517
535
  --multi-bid-id <id> override the selected bid package when needed
518
536
  --multi-bid-type <text> persist the selected bid package type
519
537
  --epc-engineer-type <text> accepts raw backend value or aliases: all, construction, design, not-epc
520
538
 
521
539
  Export style
522
540
  --template <1-${templateData.length}> Same template order as the frontend download drawer
523
- --style-json <file> Advanced export style JSON with startIndex/directorySettings/contentSettings
541
+ --style-json <file> Export style JSON file (CLI/automation compatibility)
542
+ --style-json-data <json> Structured export style payload (automation; no user file required)
524
543
  --start-index <n> Override the template heading numbering start index
525
544
  --auto-number <0|1> Toggle Word auto numbering
526
545
  --add-mark <0|1> Add suggest-modify marks
@@ -529,6 +548,10 @@ Export style
529
548
  --bottom-margin <cm> Page bottom margin
530
549
  --left-margin <cm> Page left margin
531
550
  --right-margin <cm> Page right margin
551
+ --landscape-width <cm> Landscape image fixed width
552
+ --landscape-max-height <cm> Landscape image maximum height
553
+ --portrait-width <cm> Portrait image fixed width
554
+ --portrait-max-height <cm> Portrait image maximum height
532
555
  --skeleton-color <hex> Alias of --table-bolder-color-of-skeleton
533
556
  --img-title-color <hex>
534
557
  --heading4-color <hex>
@@ -1816,6 +1839,7 @@ async function handleExport(args, state) {
1816
1839
  const tableStyle = enumOption(effectiveArgs, 'tableStyle', TABLE_STYLE_OPTIONS, snapshot.tableStyle ?? DEFAULT_TABLE_STYLE);
1817
1840
  const themeStyleSetting = buildThemeStyleSetting(snapshot, effectiveArgs);
1818
1841
  const pageMarginSetting = buildPageMarginSetting(snapshot, effectiveArgs);
1842
+ const imageSizeConfig = buildImageSizeConfig(snapshot, effectiveArgs);
1819
1843
  const templatePostData = buildTemplatePostData(template, effectiveArgs);
1820
1844
  const requestData = {
1821
1845
  cid,
@@ -1829,6 +1853,7 @@ async function handleExport(args, state) {
1829
1853
  },
1830
1854
  themeStyleSetting,
1831
1855
  pageMarginSetting,
1856
+ imageSizeConfig,
1832
1857
  t: Date.now(),
1833
1858
  ...templatePostData,
1834
1859
  };
@@ -1840,6 +1865,7 @@ async function handleExport(args, state) {
1840
1865
  tableStyle,
1841
1866
  themeStyleSetting,
1842
1867
  pageMarginSetting,
1868
+ imageSizeConfig,
1843
1869
  });
1844
1870
  const exportConfig = pickExportConfig(requestData, templateIndex);
1845
1871
 
@@ -1887,6 +1913,12 @@ function buildOutlineParams(snapshot, args) {
1887
1913
  const plan = stringOption(args, 'plan', snapshot.plan || '');
1888
1914
  const requirement = stringOption(args, 'requirement', snapshot.requirement || '');
1889
1915
  const rating = stringOption(args, 'rating', snapshot.rating || '');
1916
+ const blindGenerationMode = enumOption(
1917
+ args,
1918
+ ['blindGenerationMode', 'anonymousBid'],
1919
+ BLIND_GENERATION_MODE_OPTIONS,
1920
+ snapshot.blindGenerationMode ?? snapshot.blindBidConfirm?.blindGenerationMode ?? 'normal',
1921
+ );
1890
1922
 
1891
1923
  if (!uuid) {
1892
1924
  throw new Error('Missing uuid for outline generation. Run init first or make sure the task snapshot contains uuid.');
@@ -1924,32 +1956,39 @@ function buildOutlineParams(snapshot, args) {
1924
1956
  multiBidType: stringOption(args, 'multiBidType', snapshot.multiBidType),
1925
1957
  planMode: enumOption(args, 'planMode', PLAN_MODE_OPTIONS, snapshot.planMode ?? 0),
1926
1958
  epcEngineerType: normalizeEpcEngineerType(stringOption(args, 'epcEngineerType', snapshot.epcEngineerType)),
1959
+ blindBidConfirm: {
1960
+ blindGenerationMode,
1961
+ reviewMode: blindGenerationMode === 'blind' ? 'blind_review' : 'open_review',
1962
+ rules: [],
1963
+ },
1927
1964
  });
1928
1965
  }
1929
1966
 
1930
1967
  async function triggerOutlineGeneration(client, snapshot, params) {
1931
- await postJson(client, '/task/preSet', params);
1932
-
1933
- // task_status=6 means "file parsing" in the Xique backend. It is not a
1934
- // signal that this is a multi-bid/EPC task. Only route through the
1935
- // special-selection endpoint when the caller actually supplied a
1936
- // multi-bid or EPC selection; ordinary tasks must use the normal
1937
- // generation endpoint even while the task is transitioning from parse.
1938
- const hasSpecialSelection = Boolean(
1939
- String(params.multiBidId ?? snapshot.multiBidId ?? '').trim()
1940
- || String(params.epcEngineerType ?? snapshot.epcEngineerType ?? '').trim()
1941
- );
1942
- if (hasSpecialSelection) {
1943
- await getJson(client, '/proxy/multiBiddingChoice', compactObject({
1944
- uuid: snapshot.uuid,
1945
- multiBidId: params.multiBidId ?? snapshot.multiBidId,
1946
- epcEngineerType: normalizeEpcEngineerTypeForProxy(params.epcEngineerType ?? snapshot.epcEngineerType),
1947
- }));
1948
- return 'multiBiddingChoice';
1968
+ // The web flow has two deliberately different paths:
1969
+ //
1970
+ // * legacy tasks (task_status === 0) already contain the parsed
1971
+ // requirement/rating/plan fields, so they go straight to
1972
+ // generateByRequirement;
1973
+ // * newly parsed tasks must only persist the user's configuration with
1974
+ // preSet, then call multiBiddingChoice. That endpoint wakes the async
1975
+ // parser, and autoGenerateDirectoryJobHandler later fills the three
1976
+ // parsed fields before it invokes generateByRequirement.
1977
+ //
1978
+ // Calling generateByRequirement here for a new task races that job and
1979
+ // sends empty parsed fields, which leaves the web task stuck in parsing.
1980
+ if (Number(snapshot.task_status) === 0) {
1981
+ await postJson(client, '/task/generateByRequirement', params);
1982
+ return 'generateByRequirement';
1949
1983
  }
1950
1984
 
1951
- await postJson(client, '/task/generateByRequirement', params);
1952
- return 'generateByRequirement';
1985
+ await postJson(client, '/task/preSet', params);
1986
+ await getJson(client, '/proxy/multiBiddingChoice', compactObject({
1987
+ uuid: snapshot.uuid,
1988
+ multiBidId: params.multiBidId ?? snapshot.multiBidId,
1989
+ epcEngineerType: normalizeEpcEngineerTypeForProxy(params.epcEngineerType ?? snapshot.epcEngineerType),
1990
+ }));
1991
+ return 'multiBiddingChoice';
1953
1992
  }
1954
1993
 
1955
1994
  async function preparePlanningAnalysis(client, params) {
@@ -2280,7 +2319,10 @@ async function ensurePeriodReady(client, state, cid, args) {
2280
2319
 
2281
2320
  function isParseReadyForNextStep(success) {
2282
2321
  const parsed = Number(success);
2283
- return parsed === 1 || parsed === 4;
2322
+ // The web client treats 2 as the completed parse state that opens the
2323
+ // bid-settings page. Waiting past it keeps WorkBuddy polling forever even
2324
+ // though multi-bid/EPC results are already available.
2325
+ return parsed === 1 || parsed === 2 || parsed === 4;
2284
2326
  }
2285
2327
 
2286
2328
  async function pollTaskUntil(client, state, cid, args, isDone, formatProgress) {
@@ -3058,6 +3100,7 @@ function buildChoicesPayload(scope) {
3058
3100
  imageToggles: ['infoImg', 'sceneImg', 'onlineImg', 'mermaidImg', 'knowledgeImg'],
3059
3101
  mermaidStyle: MERMAID_STYLE_OPTIONS,
3060
3102
  planMode: PLAN_MODE_OPTIONS,
3103
+ blindGenerationMode: BLIND_GENERATION_MODE_OPTIONS,
3061
3104
  multiBid: ['--multi-bid-id', '--multi-bid-type'],
3062
3105
  epcEngineerType: {
3063
3106
  option: '--epc-engineer-type',
@@ -3075,9 +3118,11 @@ function buildChoicesPayload(scope) {
3075
3118
  tableStyle: TABLE_STYLE_OPTIONS,
3076
3119
  advancedStyle: {
3077
3120
  option: '--style-json',
3121
+ automationOption: '--style-json-data',
3078
3122
  fields: ['startIndex', 'directorySettings', 'contentSettings'],
3079
3123
  },
3080
3124
  pageMargins: PAGE_MARGIN_FIELDS.map(field => `--${toKebabCase(field.optionKeys[0])}`),
3125
+ imageSize: IMAGE_SIZE_FIELDS.map(field => `--${toKebabCase(field.optionKeys[0])}`),
3081
3126
  themeColors: THEME_STYLE_SETTING_FIELDS.map(field => field.optionKeys.map(key => `--${toKebabCase(key)}`).join('/')),
3082
3127
  };
3083
3128
  }
@@ -3098,6 +3143,7 @@ function renderChoicesLines(payload) {
3098
3143
  lines.push(` table-style: ${formatChoiceOptions(TABLE_STYLE_OPTIONS)}`);
3099
3144
  lines.push(` mermaid-style: ${formatChoiceOptions(MERMAID_STYLE_OPTIONS)}`);
3100
3145
  lines.push(` plan-mode: ${formatChoiceOptions(PLAN_MODE_OPTIONS)}`);
3146
+ lines.push(` blind-generation-mode: ${formatChoiceOptions(BLIND_GENERATION_MODE_OPTIONS)}`);
3101
3147
  lines.push(' image toggles: --info-img, --scene-img, --online-img, --mermaid-img, --knowledge-img (0|1)');
3102
3148
  lines.push(' multi-bid override: --multi-bid-id <id>, --multi-bid-type <text>');
3103
3149
  lines.push(` epc-engineer-type: --epc-engineer-type <text>; aliases=${Object.keys(EPC_ENGINEER_TYPE_ALIAS_MAP).join(', ')}`);
@@ -3109,8 +3155,9 @@ function renderChoicesLines(payload) {
3109
3155
  lines.push(` table-color: ${formatChoiceOptions(TABLE_COLOR_OPTIONS)}`);
3110
3156
  lines.push(` table-style: ${formatChoiceOptions(TABLE_STYLE_OPTIONS)}`);
3111
3157
  lines.push(' binary toggles: --auto-number, --add-mark (0|1)');
3112
- lines.push(' advanced style: --style-json <file> with startIndex, directorySettings, contentSettings');
3158
+ lines.push(' custom numbering: --style-json-data <json> (automation) or --style-json <file> (compatibility) with startIndex, directorySettings, contentSettings');
3113
3159
  lines.push(` margins: ${PAGE_MARGIN_FIELDS.map(field => `--${toKebabCase(field.optionKeys[0])}`).join(', ')}`);
3160
+ lines.push(` image sizes (cm): ${IMAGE_SIZE_FIELDS.map(field => `--${toKebabCase(field.optionKeys[0])}`).join(', ')}`);
3114
3161
  lines.push(` theme colors: ${THEME_STYLE_SETTING_FIELDS.map(field => field.optionKeys.map(key => `--${toKebabCase(key)}`).join('/')).join(', ')}`);
3115
3162
  }
3116
3163
  return lines;
@@ -3391,6 +3438,22 @@ async function collectExportInteractiveArgs(args, snapshot, context = null, opti
3391
3438
  }
3392
3439
  }
3393
3440
 
3441
+ const customizeImageSize = await promptYesNo(
3442
+ promptContext,
3443
+ '是否要自定义图片尺寸',
3444
+ hasAnyOption(args, IMAGE_SIZE_FIELDS.flatMap(field => field.optionKeys)),
3445
+ );
3446
+ if (customizeImageSize) {
3447
+ for (const field of IMAGE_SIZE_FIELDS) {
3448
+ nextArgs[field.optionKeys[0]] = await promptNumber(promptContext, {
3449
+ title: `图片尺寸: ${field.key}`,
3450
+ question: `请输入 ${field.key} (单位 cm)`,
3451
+ defaultValue: numberOptionAny(args, field.optionKeys, defaults.imageSizeConfig?.[field.key] ?? DEFAULT_IMAGE_SIZE_CONFIG[field.key]),
3452
+ min: 0.1,
3453
+ });
3454
+ }
3455
+ }
3456
+
3394
3457
  const useStyleJson = await promptYesNo(
3395
3458
  promptContext,
3396
3459
  '\u662F\u5426\u8981\u6302\u8F7D\u9AD8\u7EA7\u6837\u5F0F JSON',
@@ -3440,6 +3503,7 @@ function buildInteractiveSnapshotDefaults(source = {}) {
3440
3503
  multiBidType: source.multiBidType ?? '',
3441
3504
  epcEngineerType: source.epcEngineerType ?? '',
3442
3505
  pageMarginSetting: source.pageMarginSetting ?? DEFAULT_PAGE_MARGIN_SETTING,
3506
+ imageSizeConfig: source.imageSizeConfig ?? DEFAULT_IMAGE_SIZE_CONFIG,
3443
3507
  themeStyleSetting: source.themeStyleSetting ?? DEFAULT_THEME_STYLE_SETTING,
3444
3508
  };
3445
3509
  }
@@ -4411,19 +4475,48 @@ function buildPageMarginSetting(snapshot, args) {
4411
4475
  return pageMarginSetting;
4412
4476
  }
4413
4477
 
4478
+ function buildImageSizeConfig(snapshot, args) {
4479
+ const imageSizeConfig = {
4480
+ ...DEFAULT_IMAGE_SIZE_CONFIG,
4481
+ ...(snapshot.imageSizeConfig || {}),
4482
+ };
4483
+ for (const field of IMAGE_SIZE_FIELDS) {
4484
+ const value = numberOptionAny(args, field.optionKeys);
4485
+ if (value === undefined) {
4486
+ continue;
4487
+ }
4488
+ if (!Number.isFinite(value) || value <= 0 || value > 50) {
4489
+ throw new Error(`Option --${toKebabCase(field.optionKeys[0])} expects a number greater than 0 and no greater than 50 cm.`);
4490
+ }
4491
+ imageSizeConfig[field.key] = value;
4492
+ }
4493
+ return imageSizeConfig;
4494
+ }
4495
+
4414
4496
  function buildTemplatePostData(template, args) {
4415
4497
  const styleJsonPath = stringOption(args, 'styleJson');
4416
4498
  let styleJson = {};
4499
+ const styleJsonData = stringOption(args, 'styleJsonData');
4500
+ if (styleJsonData) {
4501
+ try {
4502
+ styleJson = JSON.parse(styleJsonData);
4503
+ } catch {
4504
+ throw new Error('Option --style-json-data expects a valid JSON object.');
4505
+ }
4506
+ }
4417
4507
  if (styleJsonPath) {
4418
4508
  const resolvedPath = path.resolve(styleJsonPath);
4419
4509
  ensureFileExists(resolvedPath);
4420
4510
  try {
4421
- styleJson = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
4511
+ styleJson = {
4512
+ ...styleJson,
4513
+ ...JSON.parse(fs.readFileSync(resolvedPath, 'utf8')),
4514
+ };
4422
4515
  } catch (error) {
4423
4516
  throw new Error(`Failed to parse style JSON: ${resolvedPath}`);
4424
4517
  }
4425
4518
  if (!styleJson || Array.isArray(styleJson) || typeof styleJson !== 'object') {
4426
- throw new Error('Option --style-json expects a JSON object.');
4519
+ throw new Error('Export style expects a JSON object.');
4427
4520
  }
4428
4521
  if (styleJson.directorySettings !== undefined && !Array.isArray(styleJson.directorySettings)) {
4429
4522
  throw new Error('Option --style-json expects directorySettings to be an array.');
@@ -4432,6 +4525,15 @@ function buildTemplatePostData(template, args) {
4432
4525
  throw new Error('Option --style-json expects contentSettings to be an object.');
4433
4526
  }
4434
4527
  }
4528
+ if (!styleJson || Array.isArray(styleJson) || typeof styleJson !== 'object') {
4529
+ throw new Error('Export style expects a JSON object.');
4530
+ }
4531
+ if (styleJson.directorySettings !== undefined && !Array.isArray(styleJson.directorySettings)) {
4532
+ throw new Error('Export style expects directorySettings to be an array.');
4533
+ }
4534
+ if (styleJson.contentSettings !== undefined && (Array.isArray(styleJson.contentSettings) || typeof styleJson.contentSettings !== 'object' || styleJson.contentSettings === null)) {
4535
+ throw new Error('Export style expects contentSettings to be an object.');
4536
+ }
4435
4537
  const startIndex = numberOption(args, 'startIndex', styleJson.startIndex ?? template.postData.startIndex ?? 1);
4436
4538
  if (!Number.isInteger(startIndex) || startIndex < 1) {
4437
4539
  throw new Error('Option --start-index expects an integer greater than or equal to 1.');
@@ -4482,6 +4584,7 @@ function pickOutlineConfig(params) {
4482
4584
  knowledgeImg: params.knowledgeImg,
4483
4585
  mermaidStyle: params.mermaidStyle,
4484
4586
  planMode: params.planMode,
4587
+ blindBidConfirm: params.blindBidConfirm,
4485
4588
  multiBidId: params.multiBidId,
4486
4589
  multiBidType: params.multiBidType,
4487
4590
  epcEngineerType: params.epcEngineerType,
@@ -4497,6 +4600,9 @@ function buildOutlineConfigSummary(params) {
4497
4600
  params.tableColor !== undefined ? `tableColor=${describeEnumValue(TABLE_COLOR_OPTIONS, params.tableColor)}` : null,
4498
4601
  params.tableStyle !== undefined ? `tableStyle=${describeEnumValue(TABLE_STYLE_OPTIONS, params.tableStyle)}` : null,
4499
4602
  `planMode=${describeEnumValue(PLAN_MODE_OPTIONS, params.planMode)}`,
4603
+ params.blindBidConfirm?.blindGenerationMode
4604
+ ? `blindGenerationMode=${params.blindBidConfirm.blindGenerationMode}`
4605
+ : null,
4500
4606
  ].filter(Boolean).join(', ');
4501
4607
  }
4502
4608
 
@@ -4512,6 +4618,7 @@ function pickExportConfig(requestData, templateIndex) {
4512
4618
  directorySettings: requestData.directorySettings,
4513
4619
  contentSettings: requestData.contentSettings,
4514
4620
  pageMarginSetting: requestData.pageMarginSetting,
4621
+ imageSizeConfig: requestData.imageSizeConfig,
4515
4622
  themeStyleSetting: requestData.themeStyleSetting,
4516
4623
  };
4517
4624
  }
@@ -4527,6 +4634,7 @@ function buildExportConfigSummary(config) {
4527
4634
  `autoNumber=${config.autoNumber}`,
4528
4635
  `addMark=${config.addMark}`,
4529
4636
  `margins=${margins.topMargin}/${margins.bottomMargin}/${margins.leftMargin}/${margins.rightMargin}`,
4637
+ `images=${config.imageSizeConfig.landscapeWidth}/${config.imageSizeConfig.landscapeMaxHeight}/${config.imageSizeConfig.portraitWidth}/${config.imageSizeConfig.portraitMaxHeight}`,
4530
4638
  ].join(', ');
4531
4639
  }
4532
4640
 
@@ -4650,6 +4758,8 @@ function pickTaskSnapshot(source) {
4650
4758
  tableStyle: source.tableStyle,
4651
4759
  tableQuantity: source.tableQuantity,
4652
4760
  planMode: source.planMode,
4761
+ blindBidConfirm: source.blindBidConfirm,
4762
+ blindGenerationMode: source.blindGenerationMode || source.blindBidConfirm?.blindGenerationMode,
4653
4763
  multiBidId: source.multiBidId,
4654
4764
  multiBidType: source.multiBidType,
4655
4765
  epcEngineerType: source.epcEngineerType,
@@ -4657,6 +4767,7 @@ function pickTaskSnapshot(source) {
4657
4767
  referenceStatus: source.referenceStatus,
4658
4768
  themeStyleSetting: source.themeStyleSetting,
4659
4769
  pageMarginSetting: source.pageMarginSetting,
4770
+ imageSizeConfig: source.imageSizeConfig,
4660
4771
  outlineTriggeredAt: source.outlineTriggeredAt,
4661
4772
  triggerMode: source.triggerMode,
4662
4773
  writeTriggeredAt: source.writeTriggeredAt,