@microi.net/cli 5.9.2 → 5.9.3

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 (199) hide show
  1. package/.codebuddy-plugin/marketplace.json +2 -2
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.workbuddy-plugin/marketplace.json +2 -2
  5. package/.workbuddy-plugin/plugin.json +1 -1
  6. package/LICENSE +21 -21
  7. package/README.md +71 -71
  8. package/assets/build-meta.json +5 -5
  9. package/assets/feature-matrix.json +138 -138
  10. package/assets/logo.svg +4 -4
  11. package/cordis.patch.yml +1 -1
  12. package/package.json +1 -1
  13. package/scripts/microi-codex-broker.js +466 -450
  14. package/scripts/microi-codex-router.js +634 -618
  15. package/scripts/microi-skills.meta.json +384 -378
  16. package/skills/.microi-skills-version.json +2 -2
  17. package/skills/.progressive-disclosure-manifest.json +122 -115
  18. package/skills/README.md +287 -287
  19. package/skills/ai-engine/SKILL.md +269 -269
  20. package/skills/ai-engine/agents/openai.yaml +4 -4
  21. package/skills/ai-engine/references/ai-employees.md +48 -48
  22. package/skills/ai-engine/references/self-hosted-digital-human.md +59 -59
  23. package/skills/ai-platform-governance/SKILL.md +177 -177
  24. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
  25. package/skills/app-store/SKILL.md +525 -525
  26. package/skills/app-store/agents/openai.yaml +4 -4
  27. package/skills/business-blueprint/SKILL.md +193 -193
  28. package/skills/datasource-engine/SKILL.md +93 -93
  29. package/skills/datasource-engine/agents/openai.yaml +4 -4
  30. package/skills/dos-orm/SKILL.md +101 -95
  31. package/skills/dos-orm/references/api-reference.md +229 -229
  32. package/skills/email-engine/SKILL.md +81 -81
  33. package/skills/email-engine/references/v8-email.md +34 -34
  34. package/skills/job-engine/SKILL.md +176 -176
  35. package/skills/job-engine/agents/openai.yaml +4 -4
  36. package/skills/message-notification/SKILL.md +156 -156
  37. package/skills/message-notification/agents/openai.yaml +5 -5
  38. package/skills/message-notification/references/contracts.md +102 -102
  39. package/skills/microi/SKILL.md +14 -14
  40. package/skills/microi-ai-app-auth.js +652 -652
  41. package/skills/microi-ai-application/SKILL.md +115 -115
  42. package/skills/microi-ai-application/agents/openai.yaml +4 -4
  43. package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
  44. package/skills/microi-client-frontend/SKILL.md +242 -242
  45. package/skills/microi-client-frontend/references/progressive-01-3-/345/212/250/346/200/201/346/214/211/351/222/256/347/263/273/347/273/237.md +144 -144
  46. package/skills/microi-client-frontend/references/progressive-02-8-/350/277/220/350/241/214/346/227/266/351/253/230/351/242/221/345/235/221/345/244/215/347/233/230.md +196 -196
  47. package/skills/microi-client-frontend/references/progressive-03-vue3-/345/211/215/347/253/257/345/276/256/346/234/215/345/212/241/345/256/277/344/270/273/350/247/204/345/210/231.md +167 -167
  48. package/skills/microi-codex-installer/SKILL.md +231 -231
  49. package/skills/microi-codex-installer/agents/openai.yaml +7 -7
  50. package/skills/microi-datasource-mapping/SKILL.md +122 -122
  51. package/skills/microi-db-schema/SKILL.md +175 -175
  52. package/skills/microi-db-schema/agents/openai.yaml +4 -4
  53. package/skills/microi-db-schema/references/core-tables.md +695 -695
  54. package/skills/microi-db-schema/references/form-component-options.md +256 -256
  55. package/skills/microi-db-schema/references/schema-overview.md +202 -202
  56. package/skills/microi-db-schema/references/schema.md +646 -646
  57. package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
  58. package/skills/microi-deployment/SKILL.md +239 -220
  59. package/skills/microi-deployment/references/deployment-matrix.md +109 -109
  60. package/skills/microi-docs-coverage/SKILL.md +133 -133
  61. package/skills/microi-docs-coverage/references/capability-map.md +90 -90
  62. package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
  63. package/skills/microi-form-engine/SKILL.md +338 -333
  64. package/skills/microi-form-engine/references/component-catalog.md +218 -218
  65. package/skills/microi-form-engine/references/data-source-events.md +124 -124
  66. package/skills/microi-frontend-sdk/SKILL.md +194 -194
  67. package/skills/microi-frontend-sdk/references/progressive-01-token-/345/275/223/345/211/215/347/231/273/345/275/225/347/224/250/346/210/267/344/270/216/345/275/223/345/211/215/347/273/210/347/253/257/347/231/273/345/275/225/345/215/217/350/256/256.md +176 -176
  68. package/skills/microi-left-right-layout/SKILL.md +141 -141
  69. package/skills/microi-microservice/SKILL.md +330 -328
  70. package/skills/microi-microservice/references/runtime-delivery.md +278 -278
  71. package/skills/microi-mobile-app-quality/SKILL.md +203 -203
  72. package/skills/microi-mobile-app-quality/references/progressive-01-4-/351/207/215/350/246/201/346/214/211/351/222/256/345/277/205/351/241/273/345/270/246/345/233/276/346/240/207.md +227 -227
  73. package/skills/microi-mobile-app-quality/references/progressive-02-9-/344/270/273/351/242/230/345/210/207/346/215/242/345/277/205/351/241/273/347/234/237/345/256/236/344/270/224/345/205/250/345/261/200/347/224/237/346/225/210.md +129 -129
  74. package/skills/microi-solution-quotation/SKILL.md +78 -78
  75. package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
  76. package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
  77. package/skills/microi-sso/SKILL.md +95 -91
  78. package/skills/microi-sso/references/acceptance.md +51 -49
  79. package/skills/microi-sso/references/configuration-and-security.md +53 -53
  80. package/skills/microi-sso/references/inbound.md +53 -53
  81. package/skills/microi-sso/references/outbound.md +43 -39
  82. package/skills/microi-ui/SKILL.md +192 -192
  83. package/skills/microi-ui/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/234/272/346/231/257/350/223/235/345/233/276.md +183 -183
  84. package/skills/microi-uniapp-frontend/SKILL.md +206 -204
  85. package/skills/microi-uniapp-frontend/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/210/206/347/261/273-/345/217/214/346/240/217/345/210/227/350/241/250/347/213/254/347/253/213/346/273/232/345/212/250.md +261 -261
  86. package/skills/microi-uniapp-frontend/references/progressive-02-/345/205/263/351/224/256/344/270/232/345/212/241/350/265/204/344/272/247/344/270/215/345/276/227/351/273/230/350/256/244/351/200/211/344/270/255.md +154 -154
  87. package/skills/microi.v8.js +1921 -1921
  88. package/skills/module-engine/SKILL.md +255 -255
  89. package/skills/module-engine/references/module-config.md +204 -204
  90. package/skills/ocr-engine/SKILL.md +113 -113
  91. package/skills/ocr-engine/agents/openai.yaml +4 -4
  92. package/skills/page-engine/SKILL.md +206 -206
  93. package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
  94. package/skills/page-engine/references/progressive-01-/346/211/200/346/234/211/347/273/204/344/273/266/347/261/273/345/236/213.md +234 -234
  95. package/skills/page-engine/references/progressive-02-/347/211/210/346/234/254/345/216/206/345/217/262-/345/271/266/345/217/221/344/277/235/345/255/230/344/270/216/345/233/236/346/273/232.md +60 -60
  96. package/skills/performance-testing/SKILL.md +227 -221
  97. package/skills/playwright-e2e/SKILL.md +197 -196
  98. package/skills/playwright-e2e/references/progressive-01-/345/205/250/350/207/252/345/212/250/347/231/273/345/275/225-/345/205/215/351/252/214/350/257/201/347/240/201-/344/275/206/344/270/215/345/205/215/345/257/206/347/240/201-/345/277/205/350/257/273.md +173 -173
  99. package/skills/playwright-e2e/references/progressive-02-/346/226/207/345/255/227/345/257/271/346/257/224/345/272/246/344/270/216/345/217/257/350/257/273/346/200/247/350/207/252/345/212/250/345/214/226/346/243/200/346/237/245-/345/277/205/345/201/232.md +183 -183
  100. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
  101. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
  102. package/skills/print-engine/SKILL.md +259 -259
  103. package/skills/production-readonly-audit/SKILL.md +41 -41
  104. package/skills/report-engine/SKILL.md +71 -71
  105. package/skills/report-engine/agents/openai.yaml +4 -4
  106. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
  107. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
  108. package/skills/scripts/sync-embedded-skills.mjs +46 -46
  109. package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
  110. package/skills/search-engine/SKILL.md +75 -75
  111. package/skills/search-engine/agents/openai.yaml +4 -4
  112. package/skills/spider-engine/SKILL.md +190 -190
  113. package/skills/system-observability/SKILL.md +259 -246
  114. package/skills/system-observability/references/memory-incident-triage.md +77 -77
  115. package/skills/translate-engine/SKILL.md +140 -140
  116. package/skills/translate-engine/agents/openai.yaml +4 -4
  117. package/skills/ui-design/SKILL.md +223 -223
  118. package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
  119. package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
  120. package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
  121. package/skills/ui-design/assets/templates/MCI-DESIGN.md +206 -206
  122. package/skills/ui-design/references/design-pattern-library.md +184 -184
  123. package/skills/ui-design/references/mci-design-contract.md +163 -163
  124. package/skills/ui-design/references/motion-and-media.md +78 -78
  125. package/skills/ui-design/references/product-flow-recipes.md +94 -94
  126. package/skills/ui-design/references/progressive-01-/351/242/234/350/211/262/344/275/223/347/263/273-css-variables-/346/224/257/346/214/201/344/270/273/351/242/230/345/210/207/346/215/242.md +218 -218
  127. package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +164 -164
  128. package/skills/ui-design/references/progressive-03-/345/212/250/346/225/210/350/247/204/350/214/203-/344/270/260/345/257/214/344/275/206/344/270/215/345/215/241.md +235 -235
  129. package/skills/ui-design/references/progressive-04-/347/273/204/344/273/266/351/243/216/346/240/274/351/200/237/346/237/245.md +152 -152
  130. package/skills/ui-design/references/progressive-05-/347/247/273/345/212/250/347/253/257/344/270/223/347/224/250/350/247/204/350/214/203.md +238 -238
  131. package/skills/ui-design/references/progressive-06-/344/270/273/351/242/230/345/210/207/346/215/242/345/256/236/347/216/260.md +194 -194
  132. package/skills/ui-design/references/progressive-07-/351/200/237/346/237/245-/344/273/216/345/244/264/346/220/255/345/273/272/344/270/200/344/270/252/347/247/273/345/212/250/347/253/257/351/241/265/351/235/242.md +207 -207
  133. package/skills/ui-design/references/progressive-08-/350/241/250/345/215/225/345/210/206/347/273/204/350/247/204/350/214/203-tabs-vs-collapsegroup-/345/274/272/345/210/266.md +142 -142
  134. package/skills/uniapp-mall-assets/SKILL.md +176 -176
  135. package/skills/unity-integration/SKILL.md +178 -171
  136. package/skills/unity-integration/agents/openai.yaml +4 -4
  137. package/skills/unity-integration/references/ai-app-delivery.md +119 -119
  138. package/skills/unity-integration/references/sdk-api.md +82 -82
  139. package/skills/unity-integration/references/toolbox-migration.md +66 -66
  140. package/skills/unity-integration/references/webgl-hosting.md +57 -57
  141. package/skills/v8-api-config/SKILL.md +388 -388
  142. package/skills/v8-cache-pattern/SKILL.md +312 -312
  143. package/skills/v8-crud-api/SKILL.md +179 -178
  144. package/skills/v8-crud-api/references/progressive-01-/346/237/245/350/257/242/345/210/227/350/241/250-/345/210/206/351/241/265.md +226 -226
  145. package/skills/v8-crud-api/references/progressive-02-where-/346/235/241/344/273/266/350/257/255/346/263/225/351/200/237/346/237/245.md +49 -49
  146. package/skills/v8-debugging/SKILL.md +284 -284
  147. package/skills/v8-explorer-tree/SKILL.md +228 -228
  148. package/skills/v8-export-import/SKILL.md +219 -219
  149. package/skills/v8-export-import/references/progressive-01-excellayout-/351/253/230/347/272/247/350/207/252/347/224/261/345/270/203/345/261/200.md +211 -211
  150. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
  151. package/skills/v8-export-import/references/progressive-03-/345/256/211/345/205/250-/346/200/247/350/203/275/346/263/250/346/204/217.md +42 -42
  152. package/skills/v8-file-upload/SKILL.md +255 -284
  153. package/skills/v8-file-upload/references/cdn-alias-repair.md +13 -0
  154. package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +263 -263
  155. package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +161 -161
  156. package/skills/v8-file-upload/references/progressive-03-/347/251/272/347/233/256/345/275/225/346/240/207/350/256/260/344/270/216/350/277/234/347/250/213/344/270/213/350/275/275.md +36 -0
  157. package/skills/v8-formengine-http/SKILL.md +238 -238
  158. package/skills/v8-frontend-events/SKILL.md +180 -180
  159. package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
  160. package/skills/v8-frontend-events/references/bluetooth-print.md +258 -258
  161. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
  162. package/skills/v8-http-integration/SKILL.md +182 -182
  163. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
  164. package/skills/v8-http-integration/references/progressive-02-/351/224/231/350/257/257/345/244/204/347/220/206/346/250/241/345/274/217.md +44 -44
  165. package/skills/v8-image-processing/SKILL.md +190 -190
  166. package/skills/v8-image-processing/agents/openai.yaml +4 -4
  167. package/skills/v8-image-processing/references/api-reference.md +623 -623
  168. package/skills/v8-menu-buttons/SKILL.md +186 -186
  169. package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +222 -222
  170. package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +228 -228
  171. package/skills/v8-menu-buttons/references/progressive-03-10-/345/217/215/346/250/241/345/274/217-/351/201/277/345/205/215.md +104 -104
  172. package/skills/v8-mongodb/SKILL.md +200 -200
  173. package/skills/v8-mq-mqtt/SKILL.md +178 -176
  174. package/skills/v8-mq-mqtt/references/mqtt-production.md +352 -342
  175. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
  176. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
  177. package/skills/v8-saas-multi-tenant/SKILL.md +305 -305
  178. package/skills/v8-security/SKILL.md +227 -210
  179. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +200 -200
  180. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +160 -160
  181. package/skills/v8-sql-query/SKILL.md +302 -302
  182. package/skills/v8-table-event/SKILL.md +176 -176
  183. package/skills/v8-table-event/references/progressive-01-informv8-js-/350/241/250/345/215/225/346/211/223/345/274/200/344/272/213/344/273/266.md +216 -216
  184. package/skills/v8-table-event/references/progressive-02-/345/211/215/347/253/257/344/272/213/344/273/266/345/220/215-v8-eventname-/345/217/257/350/203/275/347/232/204/345/200/274.md +46 -46
  185. package/skills/v8-tcp-integration/SKILL.md +158 -147
  186. package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
  187. package/skills/v8-template-engine/SKILL.md +167 -167
  188. package/skills/v8-utilities/SKILL.md +104 -104
  189. package/skills/v8-utilities/references/client-api-index.md +143 -143
  190. package/skills/v8-utilities/references/platform-http-routes.md +83 -83
  191. package/skills/v8-utilities/references/server-api-index.md +188 -188
  192. package/skills/v8-workflow/SKILL.md +252 -252
  193. package/skills/v8-workflow/references/progressive-01-/350/212/202/347/202/271/345/274/200/345/247/213-v8-/344/272/213/344/273/266.md +180 -180
  194. package/skills/v8-workflow/references/workflow-configuration.md +49 -49
  195. package/skills/vision-engine/SKILL.md +160 -160
  196. package/skills/vision-engine/agents/openai.yaml +4 -4
  197. package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
  198. package/skills/workspace-conventions/SKILL.md +13 -13
  199. package/skills/workspace-conventions/references/progressive-03-cli-/344/270/216-ide-/346/217/222/344/273/266/351/224/231/347/211/210/345/205/261/345/255/230/347/272/246/345/256/232.md +2 -2
@@ -1,296 +1,296 @@
1
- import argparse
2
- import json
3
- from datetime import date
4
- from pathlib import Path
5
-
6
- from docx import Document
7
- from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT, WD_TABLE_ALIGNMENT
8
- from docx.enum.text import WD_ALIGN_PARAGRAPH
9
- from docx.oxml import OxmlElement
10
- from docx.oxml.ns import qn
11
- from docx.shared import Inches, Pt, RGBColor
12
-
13
-
14
- NAVY = "17365D"
15
- BLUE = "2F75B5"
16
- PALE_BLUE = "EAF3F9"
17
- PALE_GRAY = "F4F6F8"
18
- PALE_GOLD = "FFF3D6"
19
- GOLD = "B45309"
20
- INK = "1F2937"
21
- MUTED = "64748B"
22
- WHITE = "FFFFFF"
23
- BORDER = "CBD5E1"
24
- FONT = "Microsoft YaHei"
25
- PAGE_WIDTH_DXA = 11909
26
- MARGIN_DXA = 720
27
- TABLE_INDENT_DXA = 120
28
- TABLE_WIDTH_DXA = PAGE_WIDTH_DXA - MARGIN_DXA * 2 - TABLE_INDENT_DXA
29
-
30
-
31
- def set_run_font(run, size=9.2, bold=False, color=INK):
32
- run.font.name = FONT
33
- rfonts = run._element.get_or_add_rPr().get_or_add_rFonts()
34
- for key in ("w:eastAsia", "w:ascii", "w:hAnsi"):
35
- rfonts.set(qn(key), FONT)
36
- run.font.size = Pt(size)
37
- run.font.bold = bold
38
- run.font.color.rgb = RGBColor.from_string(color)
39
-
40
-
41
- def format_paragraph(paragraph, before=0, after=0, line=1.05, align=None):
42
- fmt = paragraph.paragraph_format
43
- fmt.space_before = Pt(before)
44
- fmt.space_after = Pt(after)
45
- fmt.line_spacing = line
46
- if align is not None:
47
- paragraph.alignment = align
48
-
49
-
50
- def add_paragraph(doc, text, size=9.2, bold=False, color=INK, before=0, after=2, line=1.05, align=None):
51
- paragraph = doc.add_paragraph()
52
- format_paragraph(paragraph, before, after, line, align)
53
- set_run_font(paragraph.add_run(text), size, bold, color)
54
- return paragraph
55
-
56
-
57
- def set_cell_shading(cell, fill):
58
- tc_pr = cell._tc.get_or_add_tcPr()
59
- shd = tc_pr.find(qn("w:shd"))
60
- if shd is None:
61
- shd = OxmlElement("w:shd")
62
- tc_pr.append(shd)
63
- shd.set(qn("w:fill"), fill)
64
-
65
-
66
- def set_cell_margins(cell, top=70, start=110, bottom=70, end=110):
67
- tc_pr = cell._tc.get_or_add_tcPr()
68
- tc_mar = tc_pr.first_child_found_in("w:tcMar")
69
- if tc_mar is None:
70
- tc_mar = OxmlElement("w:tcMar")
71
- tc_pr.append(tc_mar)
72
- for name, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
73
- element = tc_mar.find(qn(f"w:{name}"))
74
- if element is None:
75
- element = OxmlElement(f"w:{name}")
76
- tc_mar.append(element)
77
- element.set(qn("w:w"), str(value))
78
- element.set(qn("w:type"), "dxa")
79
-
80
-
81
- def set_cell_width(cell, width):
82
- tc_pr = cell._tc.get_or_add_tcPr()
83
- tc_w = tc_pr.find(qn("w:tcW"))
84
- if tc_w is None:
85
- tc_w = OxmlElement("w:tcW")
86
- tc_pr.append(tc_w)
87
- tc_w.set(qn("w:w"), str(width))
88
- tc_w.set(qn("w:type"), "dxa")
89
-
90
-
91
- def set_table_geometry(table, widths, indent=TABLE_INDENT_DXA):
92
- total = sum(widths)
93
- table.autofit = False
94
- table.alignment = WD_TABLE_ALIGNMENT.LEFT
95
- tbl_pr = table._tbl.tblPr
96
- tbl_w = tbl_pr.find(qn("w:tblW"))
97
- if tbl_w is None:
98
- tbl_w = OxmlElement("w:tblW")
99
- tbl_pr.append(tbl_w)
100
- tbl_w.set(qn("w:w"), str(total))
101
- tbl_w.set(qn("w:type"), "dxa")
102
- tbl_ind = tbl_pr.find(qn("w:tblInd"))
103
- if tbl_ind is None:
104
- tbl_ind = OxmlElement("w:tblInd")
105
- tbl_pr.append(tbl_ind)
106
- tbl_ind.set(qn("w:w"), str(indent))
107
- tbl_ind.set(qn("w:type"), "dxa")
108
- grid = table._tbl.tblGrid
109
- for child in list(grid):
110
- grid.remove(child)
111
- for width in widths:
112
- col = OxmlElement("w:gridCol")
113
- col.set(qn("w:w"), str(width))
114
- grid.append(col)
115
- for row in table.rows:
116
- for index, cell in enumerate(row.cells):
117
- set_cell_width(cell, widths[index])
118
- set_cell_margins(cell)
119
- cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
120
-
121
-
122
- def set_table_borders(table, color=BORDER, size="6"):
123
- tbl_pr = table._tbl.tblPr
124
- borders = tbl_pr.first_child_found_in("w:tblBorders")
125
- if borders is None:
126
- borders = OxmlElement("w:tblBorders")
127
- tbl_pr.append(borders)
128
- for edge in ("top", "left", "bottom", "right", "insideH", "insideV"):
129
- tag = f"w:{edge}"
130
- element = borders.find(qn(tag))
131
- if element is None:
132
- element = OxmlElement(tag)
133
- borders.append(element)
134
- element.set(qn("w:val"), "single")
135
- element.set(qn("w:sz"), size)
136
- element.set(qn("w:space"), "0")
137
- element.set(qn("w:color"), color)
138
-
139
-
140
- def add_section_heading(doc, text):
141
- return add_paragraph(doc, text, size=10.8, bold=True, color=BLUE, before=4, after=1, line=1.0)
142
-
143
-
144
- def add_bullet(doc, label, detail):
145
- paragraph = doc.add_paragraph(style="List Bullet")
146
- format_paragraph(paragraph, before=0, after=1, line=1.03)
147
- set_run_font(paragraph.add_run(f"{label}:"), 8.8, True, NAVY)
148
- set_run_font(paragraph.add_run(detail), 8.8, False, INK)
149
-
150
-
151
- def add_metadata_table(doc, config):
152
- table = doc.add_table(rows=1, cols=4)
153
- widths = [TABLE_WIDTH_DXA // 4] * 4
154
- widths[-1] += TABLE_WIDTH_DXA - sum(widths)
155
- values = [
156
- ("版本", config["version"]),
157
- ("日期", config["date"]),
158
- ("开发周期", config["development_cycle"]),
159
- ("报价有效期", f'{config["validity_days"]} 天'),
160
- ]
161
- for index, (label, value) in enumerate(values):
162
- cell = table.cell(0, index)
163
- set_cell_shading(cell, PALE_GRAY)
164
- paragraph = cell.paragraphs[0]
165
- format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
166
- set_run_font(paragraph.add_run(f"{label}:"), 8.0, True, MUTED)
167
- set_run_font(paragraph.add_run(str(value)), 8.2, True, NAVY)
168
- set_table_geometry(table, widths)
169
- set_table_borders(table, "E2E8F0", "4")
170
-
171
-
172
- def add_callout(doc, label, detail, fill=PALE_BLUE):
173
- table = doc.add_table(rows=1, cols=1)
174
- set_table_geometry(table, [TABLE_WIDTH_DXA])
175
- set_table_borders(table, "9CC2E5", "7")
176
- cell = table.cell(0, 0)
177
- set_cell_shading(cell, fill)
178
- paragraph = cell.paragraphs[0]
179
- format_paragraph(paragraph, after=0, line=1.03)
180
- set_run_font(paragraph.add_run(f"{label}:"), 8.8, True, NAVY)
181
- set_run_font(paragraph.add_run(detail), 8.8, False, INK)
182
-
183
-
184
- def add_quote_table(doc, config):
185
- table = doc.add_table(rows=2, cols=3)
186
- widths = [TABLE_WIDTH_DXA // 3] * 3
187
- widths[-1] += TABLE_WIDTH_DXA - sum(widths)
188
- headers = ["市场预估价(总价)", "吾码优惠报价(总价)", "开发周期"]
189
- values = [config["market_price"], config["preferential_price"], config["development_cycle"]]
190
- for index, header in enumerate(headers):
191
- cell = table.cell(0, index)
192
- set_cell_shading(cell, NAVY)
193
- paragraph = cell.paragraphs[0]
194
- format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
195
- set_run_font(paragraph.add_run(header), 8.7, True, WHITE)
196
- for index, value in enumerate(values):
197
- cell = table.cell(1, index)
198
- set_cell_shading(cell, PALE_GOLD if index == 1 else PALE_GRAY)
199
- paragraph = cell.paragraphs[0]
200
- format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
201
- set_run_font(paragraph.add_run(str(value)), 12.0 if index == 1 else 10.5, True, GOLD if index == 1 else NAVY)
202
- set_table_geometry(table, widths)
203
- set_table_borders(table)
204
-
205
-
206
- def normalize_config(raw):
207
- required = [
208
- "system_name", "project_goal", "solution_items", "technical_route",
209
- "deliverables", "market_price", "preferential_price",
210
- "development_cycle", "boundary_note",
211
- ]
212
- missing = [name for name in required if not raw.get(name)]
213
- if missing:
214
- raise ValueError("Missing required fields: " + ", ".join(missing))
215
- if not isinstance(raw["solution_items"], list) or not raw["solution_items"]:
216
- raise ValueError("solution_items must be a non-empty list")
217
- raw.setdefault("version", "v1.0.0")
218
- raw.setdefault("date", date.today().isoformat())
219
- raw.setdefault("validity_days", 15)
220
- raw.setdefault("subtitle", "AI 深度融合 V8引擎 的低代码平台,官网:https://microi.net")
221
- raw.setdefault("project_scope", "")
222
- return raw
223
-
224
-
225
- def build_document(config, output):
226
- doc = Document()
227
- section = doc.sections[0]
228
- section.page_width = Inches(8.27)
229
- section.page_height = Inches(11.69)
230
- section.top_margin = Inches(0.5)
231
- section.bottom_margin = Inches(0.5)
232
- section.left_margin = Inches(0.5)
233
- section.right_margin = Inches(0.5)
234
- section.header_distance = Inches(0.2)
235
- section.footer_distance = Inches(0.2)
236
-
237
- normal = doc.styles["Normal"]
238
- normal.font.name = FONT
239
- normal._element.rPr.rFonts.set(qn("w:eastAsia"), FONT)
240
- normal.font.size = Pt(9.2)
241
- normal.font.color.rgb = RGBColor.from_string(INK)
242
-
243
- title = f'Microi吾码 {config["system_name"]} 解决方案与报价'
244
- add_paragraph(doc, title, size=20.0, bold=True, color=NAVY, after=1, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
245
- add_paragraph(doc, config["subtitle"], size=9.3, color=MUTED, after=4, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
246
- add_metadata_table(doc, config)
247
-
248
- add_section_heading(doc, "一、项目目标")
249
- add_callout(doc, "目标", config["project_goal"])
250
-
251
- add_section_heading(doc, "二、解决方案")
252
- for item in config["solution_items"]:
253
- if isinstance(item, str):
254
- add_bullet(doc, "方案", item)
255
- else:
256
- add_bullet(doc, item.get("label", "方案"), item.get("detail", ""))
257
-
258
- add_section_heading(doc, "三、核心技术路线")
259
- add_callout(doc, "链路", config["technical_route"], fill=PALE_GRAY)
260
-
261
- add_section_heading(doc, "四、交付范围")
262
- add_paragraph(doc, config["deliverables"], size=8.7, after=1, line=1.03)
263
- if config["project_scope"]:
264
- add_paragraph(doc, config["project_scope"], size=8.3, color=MUTED, after=1, line=1.0)
265
-
266
- add_section_heading(doc, "五、项目总价与周期")
267
- add_quote_table(doc, config)
268
-
269
- add_section_heading(doc, "六、说明与边界")
270
- add_paragraph(doc, config["boundary_note"], size=8.1, color=MUTED, after=0, line=1.0)
271
-
272
- footer = section.footer.paragraphs[0]
273
- format_paragraph(footer, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.RIGHT)
274
- set_run_font(footer.add_run(f'Microi吾码 | {config["version"]} | {config["date"]} | https://microi.net'), 7.2, False, MUTED)
275
-
276
- doc.core_properties.title = title
277
- doc.core_properties.subject = "Microi吾码系统解决方案与报价"
278
- doc.core_properties.author = "Microi吾码"
279
- output.parent.mkdir(parents=True, exist_ok=True)
280
- doc.save(output)
281
-
282
-
283
- def main():
284
- parser = argparse.ArgumentParser(description="Build a compact Microi solution quotation DOCX")
285
- parser.add_argument("--input", required=True, help="UTF-8 JSON configuration file")
286
- parser.add_argument("--output", required=True, help="Output DOCX path")
287
- args = parser.parse_args()
288
- with open(args.input, "r", encoding="utf-8") as handle:
289
- config = normalize_config(json.load(handle))
290
- output = Path(args.output).resolve()
291
- build_document(config, output)
292
- print(output)
293
-
294
-
295
- if __name__ == "__main__":
296
- main()
1
+ import argparse
2
+ import json
3
+ from datetime import date
4
+ from pathlib import Path
5
+
6
+ from docx import Document
7
+ from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT, WD_TABLE_ALIGNMENT
8
+ from docx.enum.text import WD_ALIGN_PARAGRAPH
9
+ from docx.oxml import OxmlElement
10
+ from docx.oxml.ns import qn
11
+ from docx.shared import Inches, Pt, RGBColor
12
+
13
+
14
+ NAVY = "17365D"
15
+ BLUE = "2F75B5"
16
+ PALE_BLUE = "EAF3F9"
17
+ PALE_GRAY = "F4F6F8"
18
+ PALE_GOLD = "FFF3D6"
19
+ GOLD = "B45309"
20
+ INK = "1F2937"
21
+ MUTED = "64748B"
22
+ WHITE = "FFFFFF"
23
+ BORDER = "CBD5E1"
24
+ FONT = "Microsoft YaHei"
25
+ PAGE_WIDTH_DXA = 11909
26
+ MARGIN_DXA = 720
27
+ TABLE_INDENT_DXA = 120
28
+ TABLE_WIDTH_DXA = PAGE_WIDTH_DXA - MARGIN_DXA * 2 - TABLE_INDENT_DXA
29
+
30
+
31
+ def set_run_font(run, size=9.2, bold=False, color=INK):
32
+ run.font.name = FONT
33
+ rfonts = run._element.get_or_add_rPr().get_or_add_rFonts()
34
+ for key in ("w:eastAsia", "w:ascii", "w:hAnsi"):
35
+ rfonts.set(qn(key), FONT)
36
+ run.font.size = Pt(size)
37
+ run.font.bold = bold
38
+ run.font.color.rgb = RGBColor.from_string(color)
39
+
40
+
41
+ def format_paragraph(paragraph, before=0, after=0, line=1.05, align=None):
42
+ fmt = paragraph.paragraph_format
43
+ fmt.space_before = Pt(before)
44
+ fmt.space_after = Pt(after)
45
+ fmt.line_spacing = line
46
+ if align is not None:
47
+ paragraph.alignment = align
48
+
49
+
50
+ def add_paragraph(doc, text, size=9.2, bold=False, color=INK, before=0, after=2, line=1.05, align=None):
51
+ paragraph = doc.add_paragraph()
52
+ format_paragraph(paragraph, before, after, line, align)
53
+ set_run_font(paragraph.add_run(text), size, bold, color)
54
+ return paragraph
55
+
56
+
57
+ def set_cell_shading(cell, fill):
58
+ tc_pr = cell._tc.get_or_add_tcPr()
59
+ shd = tc_pr.find(qn("w:shd"))
60
+ if shd is None:
61
+ shd = OxmlElement("w:shd")
62
+ tc_pr.append(shd)
63
+ shd.set(qn("w:fill"), fill)
64
+
65
+
66
+ def set_cell_margins(cell, top=70, start=110, bottom=70, end=110):
67
+ tc_pr = cell._tc.get_or_add_tcPr()
68
+ tc_mar = tc_pr.first_child_found_in("w:tcMar")
69
+ if tc_mar is None:
70
+ tc_mar = OxmlElement("w:tcMar")
71
+ tc_pr.append(tc_mar)
72
+ for name, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
73
+ element = tc_mar.find(qn(f"w:{name}"))
74
+ if element is None:
75
+ element = OxmlElement(f"w:{name}")
76
+ tc_mar.append(element)
77
+ element.set(qn("w:w"), str(value))
78
+ element.set(qn("w:type"), "dxa")
79
+
80
+
81
+ def set_cell_width(cell, width):
82
+ tc_pr = cell._tc.get_or_add_tcPr()
83
+ tc_w = tc_pr.find(qn("w:tcW"))
84
+ if tc_w is None:
85
+ tc_w = OxmlElement("w:tcW")
86
+ tc_pr.append(tc_w)
87
+ tc_w.set(qn("w:w"), str(width))
88
+ tc_w.set(qn("w:type"), "dxa")
89
+
90
+
91
+ def set_table_geometry(table, widths, indent=TABLE_INDENT_DXA):
92
+ total = sum(widths)
93
+ table.autofit = False
94
+ table.alignment = WD_TABLE_ALIGNMENT.LEFT
95
+ tbl_pr = table._tbl.tblPr
96
+ tbl_w = tbl_pr.find(qn("w:tblW"))
97
+ if tbl_w is None:
98
+ tbl_w = OxmlElement("w:tblW")
99
+ tbl_pr.append(tbl_w)
100
+ tbl_w.set(qn("w:w"), str(total))
101
+ tbl_w.set(qn("w:type"), "dxa")
102
+ tbl_ind = tbl_pr.find(qn("w:tblInd"))
103
+ if tbl_ind is None:
104
+ tbl_ind = OxmlElement("w:tblInd")
105
+ tbl_pr.append(tbl_ind)
106
+ tbl_ind.set(qn("w:w"), str(indent))
107
+ tbl_ind.set(qn("w:type"), "dxa")
108
+ grid = table._tbl.tblGrid
109
+ for child in list(grid):
110
+ grid.remove(child)
111
+ for width in widths:
112
+ col = OxmlElement("w:gridCol")
113
+ col.set(qn("w:w"), str(width))
114
+ grid.append(col)
115
+ for row in table.rows:
116
+ for index, cell in enumerate(row.cells):
117
+ set_cell_width(cell, widths[index])
118
+ set_cell_margins(cell)
119
+ cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
120
+
121
+
122
+ def set_table_borders(table, color=BORDER, size="6"):
123
+ tbl_pr = table._tbl.tblPr
124
+ borders = tbl_pr.first_child_found_in("w:tblBorders")
125
+ if borders is None:
126
+ borders = OxmlElement("w:tblBorders")
127
+ tbl_pr.append(borders)
128
+ for edge in ("top", "left", "bottom", "right", "insideH", "insideV"):
129
+ tag = f"w:{edge}"
130
+ element = borders.find(qn(tag))
131
+ if element is None:
132
+ element = OxmlElement(tag)
133
+ borders.append(element)
134
+ element.set(qn("w:val"), "single")
135
+ element.set(qn("w:sz"), size)
136
+ element.set(qn("w:space"), "0")
137
+ element.set(qn("w:color"), color)
138
+
139
+
140
+ def add_section_heading(doc, text):
141
+ return add_paragraph(doc, text, size=10.8, bold=True, color=BLUE, before=4, after=1, line=1.0)
142
+
143
+
144
+ def add_bullet(doc, label, detail):
145
+ paragraph = doc.add_paragraph(style="List Bullet")
146
+ format_paragraph(paragraph, before=0, after=1, line=1.03)
147
+ set_run_font(paragraph.add_run(f"{label}:"), 8.8, True, NAVY)
148
+ set_run_font(paragraph.add_run(detail), 8.8, False, INK)
149
+
150
+
151
+ def add_metadata_table(doc, config):
152
+ table = doc.add_table(rows=1, cols=4)
153
+ widths = [TABLE_WIDTH_DXA // 4] * 4
154
+ widths[-1] += TABLE_WIDTH_DXA - sum(widths)
155
+ values = [
156
+ ("版本", config["version"]),
157
+ ("日期", config["date"]),
158
+ ("开发周期", config["development_cycle"]),
159
+ ("报价有效期", f'{config["validity_days"]} 天'),
160
+ ]
161
+ for index, (label, value) in enumerate(values):
162
+ cell = table.cell(0, index)
163
+ set_cell_shading(cell, PALE_GRAY)
164
+ paragraph = cell.paragraphs[0]
165
+ format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
166
+ set_run_font(paragraph.add_run(f"{label}:"), 8.0, True, MUTED)
167
+ set_run_font(paragraph.add_run(str(value)), 8.2, True, NAVY)
168
+ set_table_geometry(table, widths)
169
+ set_table_borders(table, "E2E8F0", "4")
170
+
171
+
172
+ def add_callout(doc, label, detail, fill=PALE_BLUE):
173
+ table = doc.add_table(rows=1, cols=1)
174
+ set_table_geometry(table, [TABLE_WIDTH_DXA])
175
+ set_table_borders(table, "9CC2E5", "7")
176
+ cell = table.cell(0, 0)
177
+ set_cell_shading(cell, fill)
178
+ paragraph = cell.paragraphs[0]
179
+ format_paragraph(paragraph, after=0, line=1.03)
180
+ set_run_font(paragraph.add_run(f"{label}:"), 8.8, True, NAVY)
181
+ set_run_font(paragraph.add_run(detail), 8.8, False, INK)
182
+
183
+
184
+ def add_quote_table(doc, config):
185
+ table = doc.add_table(rows=2, cols=3)
186
+ widths = [TABLE_WIDTH_DXA // 3] * 3
187
+ widths[-1] += TABLE_WIDTH_DXA - sum(widths)
188
+ headers = ["市场预估价(总价)", "吾码优惠报价(总价)", "开发周期"]
189
+ values = [config["market_price"], config["preferential_price"], config["development_cycle"]]
190
+ for index, header in enumerate(headers):
191
+ cell = table.cell(0, index)
192
+ set_cell_shading(cell, NAVY)
193
+ paragraph = cell.paragraphs[0]
194
+ format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
195
+ set_run_font(paragraph.add_run(header), 8.7, True, WHITE)
196
+ for index, value in enumerate(values):
197
+ cell = table.cell(1, index)
198
+ set_cell_shading(cell, PALE_GOLD if index == 1 else PALE_GRAY)
199
+ paragraph = cell.paragraphs[0]
200
+ format_paragraph(paragraph, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
201
+ set_run_font(paragraph.add_run(str(value)), 12.0 if index == 1 else 10.5, True, GOLD if index == 1 else NAVY)
202
+ set_table_geometry(table, widths)
203
+ set_table_borders(table)
204
+
205
+
206
+ def normalize_config(raw):
207
+ required = [
208
+ "system_name", "project_goal", "solution_items", "technical_route",
209
+ "deliverables", "market_price", "preferential_price",
210
+ "development_cycle", "boundary_note",
211
+ ]
212
+ missing = [name for name in required if not raw.get(name)]
213
+ if missing:
214
+ raise ValueError("Missing required fields: " + ", ".join(missing))
215
+ if not isinstance(raw["solution_items"], list) or not raw["solution_items"]:
216
+ raise ValueError("solution_items must be a non-empty list")
217
+ raw.setdefault("version", "v1.0.0")
218
+ raw.setdefault("date", date.today().isoformat())
219
+ raw.setdefault("validity_days", 15)
220
+ raw.setdefault("subtitle", "AI 深度融合 V8引擎 的低代码平台,官网:https://microi.net")
221
+ raw.setdefault("project_scope", "")
222
+ return raw
223
+
224
+
225
+ def build_document(config, output):
226
+ doc = Document()
227
+ section = doc.sections[0]
228
+ section.page_width = Inches(8.27)
229
+ section.page_height = Inches(11.69)
230
+ section.top_margin = Inches(0.5)
231
+ section.bottom_margin = Inches(0.5)
232
+ section.left_margin = Inches(0.5)
233
+ section.right_margin = Inches(0.5)
234
+ section.header_distance = Inches(0.2)
235
+ section.footer_distance = Inches(0.2)
236
+
237
+ normal = doc.styles["Normal"]
238
+ normal.font.name = FONT
239
+ normal._element.rPr.rFonts.set(qn("w:eastAsia"), FONT)
240
+ normal.font.size = Pt(9.2)
241
+ normal.font.color.rgb = RGBColor.from_string(INK)
242
+
243
+ title = f'Microi吾码 {config["system_name"]} 解决方案与报价'
244
+ add_paragraph(doc, title, size=20.0, bold=True, color=NAVY, after=1, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
245
+ add_paragraph(doc, config["subtitle"], size=9.3, color=MUTED, after=4, line=1.0, align=WD_ALIGN_PARAGRAPH.CENTER)
246
+ add_metadata_table(doc, config)
247
+
248
+ add_section_heading(doc, "一、项目目标")
249
+ add_callout(doc, "目标", config["project_goal"])
250
+
251
+ add_section_heading(doc, "二、解决方案")
252
+ for item in config["solution_items"]:
253
+ if isinstance(item, str):
254
+ add_bullet(doc, "方案", item)
255
+ else:
256
+ add_bullet(doc, item.get("label", "方案"), item.get("detail", ""))
257
+
258
+ add_section_heading(doc, "三、核心技术路线")
259
+ add_callout(doc, "链路", config["technical_route"], fill=PALE_GRAY)
260
+
261
+ add_section_heading(doc, "四、交付范围")
262
+ add_paragraph(doc, config["deliverables"], size=8.7, after=1, line=1.03)
263
+ if config["project_scope"]:
264
+ add_paragraph(doc, config["project_scope"], size=8.3, color=MUTED, after=1, line=1.0)
265
+
266
+ add_section_heading(doc, "五、项目总价与周期")
267
+ add_quote_table(doc, config)
268
+
269
+ add_section_heading(doc, "六、说明与边界")
270
+ add_paragraph(doc, config["boundary_note"], size=8.1, color=MUTED, after=0, line=1.0)
271
+
272
+ footer = section.footer.paragraphs[0]
273
+ format_paragraph(footer, after=0, line=1.0, align=WD_ALIGN_PARAGRAPH.RIGHT)
274
+ set_run_font(footer.add_run(f'Microi吾码 | {config["version"]} | {config["date"]} | https://microi.net'), 7.2, False, MUTED)
275
+
276
+ doc.core_properties.title = title
277
+ doc.core_properties.subject = "Microi吾码系统解决方案与报价"
278
+ doc.core_properties.author = "Microi吾码"
279
+ output.parent.mkdir(parents=True, exist_ok=True)
280
+ doc.save(output)
281
+
282
+
283
+ def main():
284
+ parser = argparse.ArgumentParser(description="Build a compact Microi solution quotation DOCX")
285
+ parser.add_argument("--input", required=True, help="UTF-8 JSON configuration file")
286
+ parser.add_argument("--output", required=True, help="Output DOCX path")
287
+ args = parser.parse_args()
288
+ with open(args.input, "r", encoding="utf-8") as handle:
289
+ config = normalize_config(json.load(handle))
290
+ output = Path(args.output).resolve()
291
+ build_document(config, output)
292
+ print(output)
293
+
294
+
295
+ if __name__ == "__main__":
296
+ main()