@lovrabet/rabetbase-cli 2.5.4-beta.5 → 2.5.5-beta.1

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 (379) hide show
  1. package/lib/api/api-doc.js +1 -1
  2. package/lib/api/api-group.js +1 -1
  3. package/lib/api/fetch-model-list.js +1 -1
  4. package/lib/api/generate-api-file.js +1 -1
  5. package/lib/api/generate-sdk-config-file.js +1 -1
  6. package/lib/api/legacy-api-file.js +1 -1
  7. package/lib/api/model-registry-file.js +1 -1
  8. package/lib/api/model-registry-scaffold.js +1 -1
  9. package/lib/api/model-source.js +1 -1
  10. package/lib/auth/auth-server-ui.js +1 -1
  11. package/lib/auth/auth-server.js +1 -1
  12. package/lib/auth/constant.js +1 -1
  13. package/lib/auth/get-cookie.js +1 -1
  14. package/lib/auth/get-session-user.js +1 -1
  15. package/lib/auth/is-session-valid.js +1 -1
  16. package/lib/auth/login-success-html.js +1 -1
  17. package/lib/auth/logout.js +1 -1
  18. package/lib/cli-flags.js +1 -1
  19. package/lib/cli.js +1 -1
  20. package/lib/commands/api/generate.js +1 -1
  21. package/lib/commands/api/index.js +1 -1
  22. package/lib/commands/api/list.js +1 -1
  23. package/lib/commands/api/pull.js +1 -1
  24. package/lib/commands/api/shared.js +1 -1
  25. package/lib/commands/app/detail.js +1 -1
  26. package/lib/commands/app/index.js +1 -1
  27. package/lib/commands/app/list.js +1 -1
  28. package/lib/commands/app/members-list.js +1 -1
  29. package/lib/commands/app/remote-directory.js +1 -1
  30. package/lib/commands/app/shared.js +1 -1
  31. package/lib/commands/app-config/delete.js +1 -1
  32. package/lib/commands/app-config/get.js +1 -1
  33. package/lib/commands/app-config/index.js +1 -1
  34. package/lib/commands/app-config/list.js +1 -1
  35. package/lib/commands/app-config/set.js +1 -1
  36. package/lib/commands/app-config/shared.js +1 -1
  37. package/lib/commands/auth/index.js +1 -1
  38. package/lib/commands/bff/create.js +1 -1
  39. package/lib/commands/bff/delete.js +1 -1
  40. package/lib/commands/bff/detail.js +1 -1
  41. package/lib/commands/bff/index.js +1 -1
  42. package/lib/commands/bff/list.js +1 -1
  43. package/lib/commands/bff/logs.js +1 -1
  44. package/lib/commands/bff/pull.js +1 -1
  45. package/lib/commands/bff/push.js +1 -1
  46. package/lib/commands/bff/status.js +1 -1
  47. package/lib/commands/cli-skill/index.js +1 -1
  48. package/lib/commands/cli-update.js +1 -1
  49. package/lib/commands/codegen/index.js +1 -1
  50. package/lib/commands/codegen/sdk.js +1 -1
  51. package/lib/commands/codegen/sql.js +1 -1
  52. package/lib/commands/common/app-registry.js +1 -1
  53. package/lib/commands/common/app-selector.js +1 -1
  54. package/lib/commands/common/async-task.js +1 -1
  55. package/lib/commands/common/dry-run.js +1 -1
  56. package/lib/commands/common/flags.js +1 -1
  57. package/lib/commands/common/local-file.js +1 -1
  58. package/lib/commands/common/validate.js +1 -1
  59. package/lib/commands/config/delete.js +1 -1
  60. package/lib/commands/config/get.js +1 -1
  61. package/lib/commands/config/index.js +1 -1
  62. package/lib/commands/config/init.js +1 -1
  63. package/lib/commands/config/list.js +1 -1
  64. package/lib/commands/config/set.js +1 -1
  65. package/lib/commands/config/shared.js +1 -1
  66. package/lib/commands/dataset/batch-design.js +1 -1
  67. package/lib/commands/dataset/business-group-update.js +1 -1
  68. package/lib/commands/dataset/business-groups.js +1 -1
  69. package/lib/commands/dataset/capability.js +1 -1
  70. package/lib/commands/dataset/cross-relation-create.js +1 -1
  71. package/lib/commands/dataset/cross-relation-delete.js +1 -1
  72. package/lib/commands/dataset/cross-relation-list.js +1 -1
  73. package/lib/commands/dataset/cross-relation-shared.js +1 -1
  74. package/lib/commands/dataset/cross-relation-update.js +1 -1
  75. package/lib/commands/dataset/delete.js +1 -1
  76. package/lib/commands/dataset/detail.js +1 -1
  77. package/lib/commands/dataset/extend-update.js +1 -1
  78. package/lib/commands/dataset/field-restore.js +1 -1
  79. package/lib/commands/dataset/field-update.js +1 -1
  80. package/lib/commands/dataset/generate.js +1 -1
  81. package/lib/commands/dataset/index.js +1 -1
  82. package/lib/commands/dataset/list.js +1 -1
  83. package/lib/commands/dataset/operations.js +1 -1
  84. package/lib/commands/dataset/relation-audit.js +1 -1
  85. package/lib/commands/dataset/relation-create.js +1 -1
  86. package/lib/commands/dataset/relation-delete.js +1 -1
  87. package/lib/commands/dataset/relation-shared.js +1 -1
  88. package/lib/commands/dataset/relation-update.js +1 -1
  89. package/lib/commands/dataset/relations.js +1 -1
  90. package/lib/commands/dataset/rename.js +1 -1
  91. package/lib/commands/dataset/restore.js +1 -1
  92. package/lib/commands/dataset/user-deleted-field-list.js +1 -1
  93. package/lib/commands/db/analysis-batching.js +1 -1
  94. package/lib/commands/db/analyze-batch-plan.js +1 -1
  95. package/lib/commands/db/analyze-cancel.js +1 -1
  96. package/lib/commands/db/analyze-start.js +1 -1
  97. package/lib/commands/db/analyze-status.js +1 -1
  98. package/lib/commands/db/create.js +1 -1
  99. package/lib/commands/db/delete.js +1 -1
  100. package/lib/commands/db/detail.js +1 -1
  101. package/lib/commands/db/diff-refresh-start.js +1 -1
  102. package/lib/commands/db/diff-refresh-status.js +1 -1
  103. package/lib/commands/db/diff.js +1 -1
  104. package/lib/commands/db/index.js +1 -1
  105. package/lib/commands/db/list.js +1 -1
  106. package/lib/commands/db/shared.js +1 -1
  107. package/lib/commands/db/table-diff-shared.js +1 -1
  108. package/lib/commands/db/tables.js +1 -1
  109. package/lib/commands/db/test.js +1 -1
  110. package/lib/commands/db/update.js +1 -1
  111. package/lib/commands/deployment/index.js +1 -1
  112. package/lib/commands/deployment/sync-all.js +1 -1
  113. package/lib/commands/deployment/sync-jobs.js +1 -1
  114. package/lib/commands/deployment/sync-status.js +1 -1
  115. package/lib/commands/doctor.js +1 -1
  116. package/lib/commands/file/index.js +1 -1
  117. package/lib/commands/flow/create.js +1 -1
  118. package/lib/commands/flow/detail.js +1 -1
  119. package/lib/commands/flow/index.js +1 -1
  120. package/lib/commands/flow/list.js +1 -1
  121. package/lib/commands/flow/publish.js +1 -1
  122. package/lib/commands/flow/runtime-resources-shared.js +1 -1
  123. package/lib/commands/flow/runtime-role-list.js +1 -1
  124. package/lib/commands/flow/runtime-role-user-list.js +1 -1
  125. package/lib/commands/flow/runtime-user-search.js +1 -1
  126. package/lib/commands/flow/shared.js +1 -1
  127. package/lib/commands/flow/update.js +1 -1
  128. package/lib/commands/flow/validate.js +1 -1
  129. package/lib/commands/instant-api-policy/current.js +1 -1
  130. package/lib/commands/instant-api-policy/index.js +1 -1
  131. package/lib/commands/instant-api-policy/init.js +1 -1
  132. package/lib/commands/instant-api-policy/publish.js +1 -1
  133. package/lib/commands/instant-api-policy/pull.js +1 -1
  134. package/lib/commands/instant-api-policy/revision.js +1 -1
  135. package/lib/commands/instant-api-policy/revisions.js +1 -1
  136. package/lib/commands/instant-api-policy/rollback.js +1 -1
  137. package/lib/commands/instant-api-policy/shared.js +1 -1
  138. package/lib/commands/instant-api-policy/validate.js +1 -1
  139. package/lib/commands/issue/index.js +1 -1
  140. package/lib/commands/issue/nudge.js +1 -1
  141. package/lib/commands/issue/report.js +1 -1
  142. package/lib/commands/issue/shared.js +1 -1
  143. package/lib/commands/kb/create.js +1 -1
  144. package/lib/commands/kb/delete.js +1 -1
  145. package/lib/commands/kb/detail.js +1 -1
  146. package/lib/commands/kb/index.js +1 -1
  147. package/lib/commands/kb/list.js +1 -1
  148. package/lib/commands/kb/search.js +1 -1
  149. package/lib/commands/kb/shared.js +1 -1
  150. package/lib/commands/kb/update.js +1 -1
  151. package/lib/commands/logs/index.js +1 -1
  152. package/lib/commands/menu/asset-update.js +1 -1
  153. package/lib/commands/menu/delete.js +1 -1
  154. package/lib/commands/menu/external-link-create.js +1 -1
  155. package/lib/commands/menu/external-link-update.js +1 -1
  156. package/lib/commands/menu/group-create.js +1 -1
  157. package/lib/commands/menu/group-update.js +1 -1
  158. package/lib/commands/menu/index.js +1 -1
  159. package/lib/commands/menu/list.js +1 -1
  160. package/lib/commands/menu/move.js +1 -1
  161. package/lib/commands/menu/regroup-start.js +1 -1
  162. package/lib/commands/menu/rename.js +1 -1
  163. package/lib/commands/menu/shared/compare-table.js +1 -1
  164. package/lib/commands/menu/shared/delete-plan.js +1 -1
  165. package/lib/commands/menu/shared/facts.js +1 -1
  166. package/lib/commands/menu/shared/index.js +1 -1
  167. package/lib/commands/menu/shared/inquirer.js +1 -1
  168. package/lib/commands/menu/shared/local-pages.js +1 -1
  169. package/lib/commands/menu/shared/logic.js +1 -1
  170. package/lib/commands/menu/shared/mutations.js +1 -1
  171. package/lib/commands/menu/shared/path.js +1 -1
  172. package/lib/commands/menu/shared/service.js +1 -1
  173. package/lib/commands/menu/shared/subapp-assets.js +1 -1
  174. package/lib/commands/menu/shared/sync-core.js +1 -1
  175. package/lib/commands/menu/shared/update-core.js +1 -1
  176. package/lib/commands/menu/shared/valid-url.js +1 -1
  177. package/lib/commands/menu/subapp-assets-status.js +1 -1
  178. package/lib/commands/menu/subapp-assets-update.js +1 -1
  179. package/lib/commands/menu/sync.js +1 -1
  180. package/lib/commands/menu/visibility-update.js +1 -1
  181. package/lib/commands/notification/config-create.js +1 -1
  182. package/lib/commands/notification/config-delete.js +1 -1
  183. package/lib/commands/notification/config-list.js +1 -1
  184. package/lib/commands/notification/config-update.js +1 -1
  185. package/lib/commands/notification/index.js +1 -1
  186. package/lib/commands/notification/shared.js +1 -1
  187. package/lib/commands/ocr/index.js +1 -1
  188. package/lib/commands/page/create.js +1 -1
  189. package/lib/commands/page/custom/detail.js +1 -1
  190. package/lib/commands/page/custom/list.js +1 -1
  191. package/lib/commands/page/custom/publish.js +1 -1
  192. package/lib/commands/page/custom/shared.js +1 -1
  193. package/lib/commands/page/custom/syntax.js +1 -1
  194. package/lib/commands/page/custom/update.js +1 -1
  195. package/lib/commands/page/data-list-status.js +1 -1
  196. package/lib/commands/page/generate-start.js +1 -1
  197. package/lib/commands/page/generate-status.js +1 -1
  198. package/lib/commands/page/index.js +1 -1
  199. package/lib/commands/page/pull.js +1 -1
  200. package/lib/commands/page/push.js +1 -1
  201. package/lib/commands/page/relation-audit.js +1 -1
  202. package/lib/commands/page/restore.js +1 -1
  203. package/lib/commands/page/shared.js +1 -1
  204. package/lib/commands/page/sync.js +1 -1
  205. package/lib/commands/project/api-architecture-upgrade.js +1 -1
  206. package/lib/commands/project/create/enhanced-guided-create.js +1 -1
  207. package/lib/commands/project/create/format-elapsed.js +1 -1
  208. package/lib/commands/project/create/main.js +1 -1
  209. package/lib/commands/project/create/materialize-project-template.js +1 -1
  210. package/lib/commands/project/create/project-name.js +1 -1
  211. package/lib/commands/project/create/project-template-archive.js +1 -1
  212. package/lib/commands/project/create/project-template-path.js +1 -1
  213. package/lib/commands/project/create/use-copy-project-template.js +1 -1
  214. package/lib/commands/project/create/use-format-code.js +1 -1
  215. package/lib/commands/project/create/use-install-dependencies.js +1 -1
  216. package/lib/commands/project/domain-routing-sync.js +1 -1
  217. package/lib/commands/project/index.js +1 -1
  218. package/lib/commands/project/upgrade.js +1 -1
  219. package/lib/commands/registry.js +1 -1
  220. package/lib/commands/role/delete.js +1 -1
  221. package/lib/commands/role/detail.js +1 -1
  222. package/lib/commands/role/index.js +1 -1
  223. package/lib/commands/role/list.js +1 -1
  224. package/lib/commands/role/shared.js +1 -1
  225. package/lib/commands/role/update.js +1 -1
  226. package/lib/commands/role/user-add.js +1 -1
  227. package/lib/commands/role/user-remove.js +1 -1
  228. package/lib/commands/role/user-resolve.js +1 -1
  229. package/lib/commands/rule/get.js +1 -1
  230. package/lib/commands/rule/index.js +1 -1
  231. package/lib/commands/rule/list.js +1 -1
  232. package/lib/commands/rule/set.js +1 -1
  233. package/lib/commands/rule/shared.js +1 -1
  234. package/lib/commands/run/index.js +1 -1
  235. package/lib/commands/schema.js +1 -1
  236. package/lib/commands/sql/create.js +1 -1
  237. package/lib/commands/sql/delete.js +1 -1
  238. package/lib/commands/sql/detail.js +1 -1
  239. package/lib/commands/sql/exec.js +1 -1
  240. package/lib/commands/sql/index.js +1 -1
  241. package/lib/commands/sql/list.js +1 -1
  242. package/lib/commands/sql/pull.js +1 -1
  243. package/lib/commands/sql/push.js +1 -1
  244. package/lib/commands/sql/shared.js +1 -1
  245. package/lib/commands/sql/status.js +1 -1
  246. package/lib/commands/sql/validate.js +1 -1
  247. package/lib/commands/task/index.js +1 -1
  248. package/lib/commands/task/status.js +1 -1
  249. package/lib/commands/tenant/index.js +1 -1
  250. package/lib/commands/tenant/members-list.js +1 -1
  251. package/lib/commands/tenant/shared.js +1 -1
  252. package/lib/commands/user-account/dingding-sandbox-bind.js +1 -1
  253. package/lib/commands/user-account/feishu-bind.js +1 -1
  254. package/lib/commands/user-account/index.js +1 -1
  255. package/lib/commands/workspace/add.js +1 -1
  256. package/lib/commands/workspace/index.js +1 -1
  257. package/lib/commands/workspace/remove.js +1 -1
  258. package/lib/config/domain-config.js +1 -1
  259. package/lib/config/project-domain-routing.js +1 -1
  260. package/lib/config/region-config.js +1 -1
  261. package/lib/config/schema.js +1 -1
  262. package/lib/constant/cdn.js +1 -1
  263. package/lib/constant/cli.js +1 -1
  264. package/lib/constant/defaults.js +1 -1
  265. package/lib/constant/domain.js +1 -1
  266. package/lib/constant/env.js +1 -1
  267. package/lib/constant/output.js +1 -1
  268. package/lib/constant/paths.js +1 -1
  269. package/lib/constant/region.js +1 -1
  270. package/lib/constant/risk.js +1 -1
  271. package/lib/constant/routing-profile.js +1 -1
  272. package/lib/context/app-resolver.js +1 -1
  273. package/lib/context/auth-resolver.js +1 -1
  274. package/lib/context/config-loader.js +1 -1
  275. package/lib/context.js +1 -1
  276. package/lib/core/alias-resolver.js +1 -1
  277. package/lib/core/api-client.js +1 -1
  278. package/lib/core/bff/config.js +1 -1
  279. package/lib/core/bff/file-system.js +1 -1
  280. package/lib/core/bff/hash.js +1 -1
  281. package/lib/core/bff/hook-directory.js +1 -1
  282. package/lib/core/bff/lock.js +1 -1
  283. package/lib/core/bff/utils.js +1 -1
  284. package/lib/core/cross-db-relation.js +1 -1
  285. package/lib/core/db-resolver.js +1 -1
  286. package/lib/core/flow-config.js +1 -1
  287. package/lib/core/instant-api-policy/config.js +1 -1
  288. package/lib/core/kb-search-client.js +1 -1
  289. package/lib/core/page/file-system.js +1 -1
  290. package/lib/core/page/hash.js +1 -1
  291. package/lib/core/page/lock.js +1 -1
  292. package/lib/core/page/lr-smart-jsx.js +1 -1
  293. package/lib/core/sql-index-auditor.js +1 -1
  294. package/lib/core/sql-sync/config.js +1 -1
  295. package/lib/core/sql-sync/file-system.js +1 -1
  296. package/lib/core/sql-sync/hash.js +1 -1
  297. package/lib/core/sql-sync/lock.js +1 -1
  298. package/lib/core/sql-sync/utils.js +1 -1
  299. package/lib/core/sql-validator.js +1 -1
  300. package/lib/errors.js +1 -1
  301. package/lib/framework/build-all-flags.js +1 -1
  302. package/lib/framework/error-output.js +1 -1
  303. package/lib/framework/explicit-yes.js +1 -1
  304. package/lib/framework/flags.js +1 -1
  305. package/lib/framework/help.js +1 -1
  306. package/lib/framework/index.js +1 -1
  307. package/lib/framework/output.js +1 -1
  308. package/lib/framework/response.js +1 -1
  309. package/lib/framework/runner-alias.js +1 -1
  310. package/lib/framework/runner.js +1 -1
  311. package/lib/framework/schema-export.js +1 -1
  312. package/lib/framework/supported-flags.js +1 -1
  313. package/lib/framework/types.js +1 -1
  314. package/lib/generated/build-info.d.ts +4 -4
  315. package/lib/generated/build-info.js +1 -1
  316. package/lib/generated/official-routing.js +1 -1
  317. package/lib/generated/routing-contract.js +1 -1
  318. package/lib/help.js +1 -1
  319. package/lib/postinstall.js +1 -1
  320. package/lib/runtime/confirmation.js +1 -1
  321. package/lib/runtime/event.js +1 -1
  322. package/lib/runtime/index.js +1 -1
  323. package/lib/runtime/queue.js +1 -1
  324. package/lib/runtime/resolve.js +1 -1
  325. package/lib/skills/builtin-skill.js +1 -1
  326. package/lib/skills/main.js +1 -1
  327. package/lib/skills/npx-skills-add.js +1 -1
  328. package/lib/skills/skill-presence.js +1 -1
  329. package/lib/telemetry/cli-command-trace.js +1 -1
  330. package/lib/telemetry/cli-help-trace.js +1 -1
  331. package/lib/telemetry/ensure-cli-otel-config.js +1 -1
  332. package/lib/telemetry/register-otel-exit-shutdown.js +1 -1
  333. package/lib/telemetry/send-cli-trace-log.js +1 -1
  334. package/lib/telemetry/send-platform-issue-collect-log.js +1 -1
  335. package/lib/utils/ai_config.js +1 -1
  336. package/lib/utils/apply-jq-filter.js +1 -1
  337. package/lib/utils/cdn-config.js +1 -1
  338. package/lib/utils/check-sdk-version.js +1 -1
  339. package/lib/utils/cli-version-check.js +1 -1
  340. package/lib/utils/cli-version-policy.js +1 -1
  341. package/lib/utils/config.js +1 -1
  342. package/lib/utils/entity-with-id.js +1 -1
  343. package/lib/utils/file-utils.js +1 -1
  344. package/lib/utils/guides-cdn.js +1 -1
  345. package/lib/utils/http-client.js +1 -1
  346. package/lib/utils/is-non-interactive.js +1 -1
  347. package/lib/utils/logger.js +1 -1
  348. package/lib/utils/params.js +1 -1
  349. package/lib/utils/platform.js +1 -1
  350. package/lib/utils/sleep.js +1 -1
  351. package/lib/utils/template-replacer.js +1 -1
  352. package/lib/utils/update-notice.js +1 -1
  353. package/lib/utils/version.js +1 -1
  354. package/lib/utils/with-active-cookie.js +1 -1
  355. package/lib/utils/write-cli-side-channel.js +1 -1
  356. package/package.json +2 -1
  357. package/skills/rabetbase/SKILL.md +1 -1
  358. package/skills/rabetbase-page-generation/SKILL.md +35 -0
  359. package/skills/rabetbase-page-generation/references/component-baseline.md +18 -0
  360. package/skills/rabetbase-page-generation/references/generation.md +77 -0
  361. package/skills/rabetbase-page-generation/templates/onepage/build.mjs +63 -0
  362. package/skills/rabetbase-page-generation/templates/onepage/create/README.md +20 -0
  363. package/skills/rabetbase-page-generation/templates/onepage/create/index.jsx +4 -0
  364. package/skills/rabetbase-page-generation/templates/onepage/create/preview.png +0 -0
  365. package/skills/rabetbase-page-generation/templates/onepage/detail/README.md +20 -0
  366. package/skills/rabetbase-page-generation/templates/onepage/detail/index.jsx +194 -0
  367. package/skills/rabetbase-page-generation/templates/onepage/detail/preview.png +0 -0
  368. package/skills/rabetbase-page-generation/templates/onepage/list/README.md +20 -0
  369. package/skills/rabetbase-page-generation/templates/onepage/list/index.jsx +717 -0
  370. package/skills/rabetbase-page-generation/templates/onepage/list/preview.png +0 -0
  371. package/skills/rabetbase-page-generation/templates/onepage/shared/editor.jsx +395 -0
  372. package/skills/rabetbase-page-generation/templates/onepage/shared/model.js +141 -0
  373. package/skills/rabetbase-page-generation/templates/onepage/shared/page.css +377 -0
  374. package/skills/rabetbase-page-generation/templates/onepage/shared/record-layout.jsx +90 -0
  375. package/skills/rabetbase-page-generation/templates/onepage/shared/responsive.jsx +70 -0
  376. package/skills/rabetbase-page-generation/templates/onepage/update/README.md +21 -0
  377. package/skills/rabetbase-page-generation/templates/onepage/update/index.jsx +4 -0
  378. package/skills/rabetbase-page-generation/templates/onepage/update/preview.png +0 -0
  379. package/skills/rabetbase.manifest.json +3 -3
@@ -0,0 +1,717 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import {
3
+ Alert,
4
+ App,
5
+ Button,
6
+ Checkbox,
7
+ ConfigProvider,
8
+ Dropdown,
9
+ Empty,
10
+ Input,
11
+ Pagination,
12
+ Select,
13
+ Spin,
14
+ Popover,
15
+ Radio,
16
+ Space,
17
+ Table,
18
+ Tag,
19
+ Tooltip,
20
+ theme,
21
+ } from "antd";
22
+ import {
23
+ EllipsisOutlined,
24
+ HomeOutlined,
25
+ InfoCircleFilled,
26
+ ReloadOutlined,
27
+ SettingOutlined,
28
+ } from "@ant-design/icons";
29
+ import { useAppTheme, useNavigate, useSdkClient } from "@/context/app-context";
30
+ import { LrSmartFilter } from "@lovrabet/components/smart-filter";
31
+ import {
32
+ APP_CODE,
33
+ DATASET_CODE,
34
+ DEFAULT_ORDER,
35
+ LIST_PATH,
36
+ childPaths,
37
+ fields,
38
+ formatField,
39
+ levelOptions,
40
+ statusOptions,
41
+ typeOptions,
42
+ smartWhere,
43
+ traditionalWhere,
44
+ } from "../shared/model";
45
+ import { ResponsiveDateRange, useMobileLayout } from "../shared/responsive";
46
+ import "../shared/page.css";
47
+
48
+ const filterItems = [
49
+ {
50
+ name: "customer_name",
51
+ label: "客户名称",
52
+ control: <Input allowClear placeholder="请输入客户名称" />,
53
+ },
54
+ {
55
+ name: "status",
56
+ label: "状态",
57
+ control: <Radio.Group options={statusOptions} />,
58
+ },
59
+ {
60
+ name: "customer_type",
61
+ label: "客户类型",
62
+ control: <Radio.Group options={typeOptions} />,
63
+ },
64
+ {
65
+ name: "customer_level",
66
+ label: "客户等级",
67
+ control: <Radio.Group options={levelOptions} />,
68
+ },
69
+ {
70
+ name: "onboarding_date",
71
+ label: "入驻日期",
72
+ control: <ResponsiveDateRange />,
73
+ },
74
+ {
75
+ name: "region",
76
+ label: "区域",
77
+ control: <Input allowClear placeholder="请输入区域" />,
78
+ },
79
+ {
80
+ name: "contact_name",
81
+ label: "联系人",
82
+ control: <Input allowClear placeholder="请输入联系人" />,
83
+ },
84
+ ];
85
+ function CustomerList() {
86
+ const mobile = useMobileLayout();
87
+ const client = useSdkClient();
88
+ const navigate = useNavigate();
89
+ const { token } = theme.useToken();
90
+ const { message, modal } = App.useApp();
91
+ const [request, setRequest] = useState({
92
+ where: {},
93
+ currentPage: 1,
94
+ pageSize: mobile ? 10 : 30,
95
+ });
96
+ const [revision, setRevision] = useState(0);
97
+ const [filterKey, setFilterKey] = useState(0);
98
+ const [rows, setRows] = useState([]);
99
+ const [total, setTotal] = useState(0);
100
+ const [loading, setLoading] = useState(true);
101
+ const [error, setError] = useState("");
102
+ const [selected, setSelected] = useState([]);
103
+ const preferenceKey = `${APP_CODE}:${DATASET_CODE}:visible-fields`;
104
+ const [visibleFields, setVisibleFields] = useState(() => {
105
+ try {
106
+ const saved = JSON.parse(localStorage.getItem(preferenceKey));
107
+ if (Array.isArray(saved))
108
+ return fields.map((f) => f.key).filter((key) => saved.includes(key));
109
+ } catch {
110
+ /* 浏览器禁用存储时继续使用默认列。 */
111
+ }
112
+ return fields.map((field) => field.key);
113
+ });
114
+ useEffect(() => {
115
+ try {
116
+ localStorage.setItem(preferenceKey, JSON.stringify(visibleFields));
117
+ } catch {
118
+ /* 列偏好不影响业务操作。 */
119
+ }
120
+ }, [preferenceKey, visibleFields]);
121
+ function clearFilters() {
122
+ setFilterKey((value) => value + 1);
123
+ setSelected([]);
124
+ setRequest((previous) => ({ ...previous, where: {}, currentPage: 1 }));
125
+ }
126
+ const [exporting, setExporting] = useState(false);
127
+ const alive = useRef(true);
128
+ const model = client.models[`dataset_${DATASET_CODE}`];
129
+ useEffect(() => {
130
+ alive.current = true;
131
+ return () => {
132
+ alive.current = false;
133
+ };
134
+ }, []);
135
+ useEffect(() => {
136
+ const changed = (event) => {
137
+ if (event.detail === LIST_PATH) setRevision((value) => value + 1);
138
+ };
139
+ window.addEventListener("lovrabet:page-generation:changed", changed);
140
+ return () =>
141
+ window.removeEventListener("lovrabet:page-generation:changed", changed);
142
+ }, []);
143
+ useEffect(() => {
144
+ let active = true;
145
+ setLoading(true);
146
+ setError("");
147
+ model
148
+ .filter({ ...request, orderBy: DEFAULT_ORDER })
149
+ .then((result) => {
150
+ if (!active) return;
151
+ const count = Number(result?.paging?.totalCount);
152
+ if (
153
+ !Array.isArray(result?.tableData) ||
154
+ !Number.isSafeInteger(count) ||
155
+ count < 0
156
+ )
157
+ throw Error("列表响应无效,请重试");
158
+ const lastPage = Math.max(1, Math.ceil(count / request.pageSize));
159
+ if (request.currentPage > lastPage) {
160
+ setRequest((previous) => ({ ...previous, currentPage: lastPage }));
161
+ return;
162
+ }
163
+ setRows(result.tableData);
164
+ setTotal(count);
165
+ setSelected((previous) =>
166
+ previous.filter((id) =>
167
+ result.tableData.some((row) => row.id === id),
168
+ ),
169
+ );
170
+ })
171
+ .catch((cause) => {
172
+ if (active) {
173
+ setError(cause.message || "加载失败,请重试");
174
+ setRows([]);
175
+ setSelected([]);
176
+ }
177
+ })
178
+ .finally(() => {
179
+ if (active) setLoading(false);
180
+ });
181
+ return () => {
182
+ active = false;
183
+ };
184
+ }, [client, request, revision]);
185
+ function applySearch({ mode, values }) {
186
+ setSelected([]);
187
+ setRequest((previous) => ({
188
+ ...previous,
189
+ where: mode === "fields" ? traditionalWhere(values) : values,
190
+ currentPage: 1,
191
+ }));
192
+ }
193
+ function openChild(kind, id) {
194
+ const path = childPaths[kind];
195
+ if (!path) return;
196
+ const target =
197
+ id === undefined
198
+ ? path
199
+ : `${path}?${new URLSearchParams({ id: String(id), ...(kind === "detail" ? { ids: rows.map((row) => row.id).join(",") } : {}) })}`;
200
+ navigate(target, { onePage: true });
201
+ }
202
+ function remove(ids) {
203
+ modal.confirm({
204
+ title:
205
+ ids.length === 1
206
+ ? "删除这条记录?"
207
+ : `删除选中的 ${ids.length} 条记录?`,
208
+ content: "删除后列表将自动刷新。",
209
+ okText: "删除",
210
+ cancelText: "取消",
211
+ okButtonProps: { danger: true },
212
+ async onOk() {
213
+ try {
214
+ await model.delete({ id: ids });
215
+ setSelected([]);
216
+ setRevision((value) => value + 1);
217
+ message.success("删除成功");
218
+ } catch (cause) {
219
+ message.error(cause.message || "删除失败,请重试");
220
+ throw cause;
221
+ }
222
+ },
223
+ });
224
+ }
225
+ async function exportRows(onlySelected) {
226
+ setExporting(true);
227
+ try {
228
+ const where = onlySelected ? { id: { $in: selected } } : request.where;
229
+ const all = [];
230
+ // Export every matching server page, not only the visible rows.
231
+ for (let page = 1; ; page++) {
232
+ const result = await model.filter({
233
+ where,
234
+ currentPage: page,
235
+ pageSize: 200,
236
+ orderBy: DEFAULT_ORDER,
237
+ });
238
+ if (!alive.current) return;
239
+ if (
240
+ !Array.isArray(result.tableData) ||
241
+ !Number.isSafeInteger(Number(result.paging?.totalCount))
242
+ )
243
+ throw Error("导出响应无效");
244
+ all.push(...result.tableData);
245
+ if (all.length >= Number(result.paging.totalCount)) break;
246
+ if (!result.tableData.length) throw Error("导出数据不完整,请重试");
247
+ }
248
+ const csvCell = (value) =>
249
+ '"' +
250
+ String(value)
251
+ .replace(/^[=+@\-\t\r]/, "'$&")
252
+ .replaceAll('"', '""') +
253
+ '"';
254
+ const text =
255
+ "\ufeff" +
256
+ [
257
+ fields.map((f) => f.label),
258
+ ...all.map((row) => fields.map((f) => formatField(row[f.key], f))),
259
+ ]
260
+ .map((row) => row.map(csvCell).join(","))
261
+ .join("\r\n");
262
+ const url = URL.createObjectURL(
263
+ new Blob([text], { type: "text/csv;charset=utf-8" }),
264
+ );
265
+ const link = document.createElement("a");
266
+ link.href = url;
267
+ link.download = "客户列表.csv";
268
+ link.click();
269
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
270
+ message.success(`已导出 ${all.length} 条记录`);
271
+ } catch (cause) {
272
+ message.error(cause.message || "导出失败,请重试");
273
+ } finally {
274
+ if (alive.current) setExporting(false);
275
+ }
276
+ }
277
+ const columns = fields
278
+ .filter((field) => visibleFields.includes(field.key))
279
+ .map((field) => ({
280
+ title: field.label,
281
+ dataIndex: field.key,
282
+ key: field.key,
283
+ width: field.width,
284
+ align: field.align,
285
+ ellipsis: true,
286
+ render: (value, row) =>
287
+ field.key === "customer_name" ? (
288
+ <Button
289
+ className="customer-name-link"
290
+ type="link"
291
+ onClick={() => openChild("detail", row.id)}
292
+ >
293
+ {formatField(value, field)}
294
+ </Button>
295
+ ) : field.tag && value != null && value !== "" ? (
296
+ <Tag>{formatField(value, field)}</Tag>
297
+ ) : (
298
+ formatField(value, field)
299
+ ),
300
+ }));
301
+ columns.push({
302
+ title: "操作",
303
+ key: "actions",
304
+ width: 136,
305
+ fixed: "right",
306
+ render: (_, row) => (
307
+ <Space size={4}>
308
+ <Tooltip title={childPaths.update ? undefined : "更新页面尚未开放"}>
309
+ <Button
310
+ size="small"
311
+ type="link"
312
+ disabled={!childPaths.update}
313
+ onClick={() => openChild("update", row.id)}
314
+ >
315
+ 更新
316
+ </Button>
317
+ </Tooltip>
318
+ <Tooltip
319
+ title={childPaths.detail ? undefined : "详情页等待 ONEPAGE 路由接通"}
320
+ >
321
+ <Button
322
+ size="small"
323
+ type="link"
324
+ disabled={!childPaths.detail}
325
+ onClick={() => openChild("detail", row.id)}
326
+ >
327
+ 详情
328
+ </Button>
329
+ </Tooltip>
330
+ <Button
331
+ size="small"
332
+ type="link"
333
+ onClick={() => remove([row.id])}
334
+ disabled={loading || Boolean(error)}
335
+ >
336
+ 删除
337
+ </Button>
338
+ </Space>
339
+ ),
340
+ });
341
+ const menu = {
342
+ items: [
343
+ {
344
+ key: "exportSelected",
345
+ label: "导出选中项",
346
+ disabled: !selected.length || exporting,
347
+ },
348
+ {
349
+ key: "export",
350
+ label: "导出当前结果",
351
+ disabled: exporting || Boolean(error),
352
+ },
353
+ { type: "divider" },
354
+ {
355
+ key: "delete",
356
+ label: "删除选中项",
357
+ danger: true,
358
+ disabled: !selected.length || loading || Boolean(error),
359
+ },
360
+ ],
361
+ onClick: ({ key }) =>
362
+ key === "delete"
363
+ ? remove(selected)
364
+ : exportRows(key === "exportSelected"),
365
+ };
366
+ return (
367
+ <main
368
+ className="standard-jsx-list"
369
+ style={{ background: token.colorBgContainer, color: token.colorText }}
370
+ >
371
+ <div className="list-breadcrumb">
372
+ <HomeOutlined />
373
+ <span>/</span>
374
+ <span>客户列表</span>
375
+ </div>
376
+ <LrSmartFilter
377
+ key={filterKey}
378
+ items={filterItems}
379
+ onSmartSearch={(query, options) => smartWhere(client, query, options)}
380
+ onSearch={applySearch}
381
+ labels={{
382
+ filters: "筛选",
383
+ smartSearch: "智能搜索",
384
+ placeholder: "描述要查找的客户",
385
+ search: "查询",
386
+ reset: "重置",
387
+ expand: "更多条件",
388
+ collapse: "收起条件",
389
+ failed: "查询失败,请重试",
390
+ }}
391
+ />
392
+ {Object.keys(request.where).length > 0 && (
393
+ <div className="active-filter-summary" role="status">
394
+ <span>已应用筛选 · {error ? "—" : total} 条结果</span>
395
+ <Button type="link" onClick={clearFilters}>
396
+ 清除筛选
397
+ </Button>
398
+ </div>
399
+ )}
400
+ <div className="list-toolbar">
401
+ <div className="list-toolbar-left">
402
+ <div
403
+ className="selection-summary"
404
+ style={{
405
+ background: token.colorPrimaryBg,
406
+ borderColor: token.colorPrimaryBorder,
407
+ }}
408
+ >
409
+ <InfoCircleFilled style={{ color: token.colorPrimary }} />
410
+ <span>
411
+ {`已选 ${selected.length} / 共 ${error ? "—" : total} 条`}
412
+ </span>
413
+ {selected.length > 0 && (
414
+ <Button type="link" size="small" onClick={() => setSelected([])}>
415
+ 清空
416
+ </Button>
417
+ )}
418
+ </div>
419
+ <Space.Compact>
420
+ <Button
421
+ disabled={!selected.length || loading || Boolean(error)}
422
+ onClick={() => exportRows(true)}
423
+ loading={exporting}
424
+ >
425
+ 导出选中
426
+ </Button>
427
+ <Dropdown menu={menu} trigger={["click"]} disabled={loading}>
428
+ <Button icon={<EllipsisOutlined />} aria-label="更多操作" />
429
+ </Dropdown>
430
+ </Space.Compact>
431
+ </div>
432
+ <Space size={8} className="list-toolbar-actions">
433
+ <Tooltip title="刷新">
434
+ <Button
435
+ type="text"
436
+ icon={<ReloadOutlined spin={loading} />}
437
+ aria-label="刷新"
438
+ onClick={() => setRevision((value) => value + 1)}
439
+ />
440
+ </Tooltip>
441
+ <Popover
442
+ trigger="click"
443
+ placement="bottomRight"
444
+ title="列设置"
445
+ content={
446
+ <div className="column-options">
447
+ <Checkbox.Group
448
+ value={visibleFields}
449
+ onChange={setVisibleFields}
450
+ options={fields.map((f) => ({
451
+ label: f.label,
452
+ value: f.key,
453
+ }))}
454
+ />
455
+ <Button
456
+ type="link"
457
+ onClick={() => setVisibleFields(fields.map((f) => f.key))}
458
+ >
459
+ 恢复默认
460
+ </Button>
461
+ </div>
462
+ }
463
+ >
464
+ <Button
465
+ type="text"
466
+ icon={<SettingOutlined />}
467
+ aria-label="列设置"
468
+ />
469
+ </Popover>
470
+ <Tooltip title={childPaths.create ? undefined : "新增页面尚未开放"}>
471
+ <Button
472
+ type="primary"
473
+ disabled={!childPaths.create}
474
+ onClick={() => openChild("create")}
475
+ >
476
+ 新增
477
+ </Button>
478
+ </Tooltip>
479
+ </Space>
480
+ </div>
481
+ {error ? (
482
+ <Alert
483
+ type="error"
484
+ showIcon
485
+ message="列表加载失败"
486
+ description={error}
487
+ action={
488
+ <Button onClick={() => setRevision((value) => value + 1)}>
489
+ 重试
490
+ </Button>
491
+ }
492
+ />
493
+ ) : mobile ? (
494
+ <Spin spinning={loading}>
495
+ <div
496
+ className="mobile-record-list"
497
+ aria-label="客户列表"
498
+ aria-busy={loading}
499
+ >
500
+ {rows.length > 0 && (
501
+ <Checkbox
502
+ disabled={loading}
503
+ checked={selected.length === rows.length}
504
+ indeterminate={
505
+ selected.length > 0 && selected.length < rows.length
506
+ }
507
+ onChange={(event) =>
508
+ setSelected(
509
+ event.target.checked ? rows.map((row) => row.id) : [],
510
+ )
511
+ }
512
+ >
513
+ 选择本页
514
+ </Checkbox>
515
+ )}
516
+ {rows.map((row) => (
517
+ <article
518
+ className="mobile-record-card"
519
+ key={row.id}
520
+ aria-label={row.customer_name || `客户 ${row.id}`}
521
+ style={{
522
+ borderColor: token.colorBorderSecondary,
523
+ background: token.colorBgContainer,
524
+ }}
525
+ >
526
+ <header>
527
+ <Checkbox
528
+ aria-label={`选择客户 ${row.id}`}
529
+ disabled={loading}
530
+ checked={selected.includes(row.id)}
531
+ onChange={(event) =>
532
+ setSelected((previous) =>
533
+ event.target.checked
534
+ ? [...previous, row.id]
535
+ : previous.filter((id) => id !== row.id),
536
+ )
537
+ }
538
+ />
539
+ <Button
540
+ type="link"
541
+ className="mobile-record-title"
542
+ onClick={() => openChild("detail", row.id)}
543
+ >
544
+ {row.customer_name || "未命名客户"}
545
+ </Button>
546
+ </header>
547
+ <dl>
548
+ {fields
549
+ .filter(
550
+ (field) =>
551
+ field.key !== "customer_name" &&
552
+ visibleFields.includes(field.key) &&
553
+ ([
554
+ "id",
555
+ "status",
556
+ "customer_type",
557
+ "customer_level",
558
+ "region",
559
+ "annual_revenue",
560
+ ].includes(field.key) ||
561
+ (row[field.key] != null && row[field.key] !== "")),
562
+ )
563
+ .map((field) => (
564
+ <div key={field.key}>
565
+ <dt style={{ color: token.colorTextSecondary }}>
566
+ {field.label}
567
+ </dt>
568
+ <dd>
569
+ {field.tag && row[field.key] ? (
570
+ <Tag>{formatField(row[field.key], field)}</Tag>
571
+ ) : (
572
+ formatField(row[field.key], field)
573
+ )}
574
+ </dd>
575
+ </div>
576
+ ))}
577
+ </dl>
578
+ <footer>
579
+ <Button onClick={() => openChild("detail", row.id)}>
580
+ 详情
581
+ </Button>
582
+ <Button onClick={() => openChild("update", row.id)}>
583
+ 更新
584
+ </Button>
585
+ <Button
586
+ danger
587
+ disabled={loading}
588
+ onClick={() => remove([row.id])}
589
+ >
590
+ 删除
591
+ </Button>
592
+ </footer>
593
+ </article>
594
+ ))}
595
+ {!rows.length && !loading && (
596
+ <Empty
597
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
598
+ description={
599
+ Object.keys(request.where).length
600
+ ? "暂无匹配结果"
601
+ : "暂无数据"
602
+ }
603
+ />
604
+ )}
605
+ </div>
606
+ <div className="mobile-pagination">
607
+ <span>共 {total} 条</span>
608
+ <Select
609
+ aria-label="每页条数"
610
+ value={request.pageSize}
611
+ options={[10, 20, 30, 50, 100].map((value) => ({
612
+ value,
613
+ label: `${value} 条/页`,
614
+ }))}
615
+ onChange={(pageSize) => {
616
+ setSelected([]);
617
+ setRequest((previous) => ({
618
+ ...previous,
619
+ currentPage: 1,
620
+ pageSize,
621
+ }));
622
+ }}
623
+ />
624
+ {total > 0 && (
625
+ <Pagination
626
+ simple={{ readOnly: true }}
627
+ current={request.currentPage}
628
+ pageSize={request.pageSize}
629
+ total={total}
630
+ showSizeChanger={false}
631
+ onChange={(currentPage) => {
632
+ setSelected([]);
633
+ setRequest((previous) => ({ ...previous, currentPage }));
634
+ }}
635
+ />
636
+ )}
637
+ </div>
638
+ </Spin>
639
+ ) : (
640
+ <Table
641
+ size="small"
642
+ rowKey="id"
643
+ loading={loading}
644
+ columns={columns}
645
+ dataSource={rows}
646
+ rowSelection={{
647
+ selectedRowKeys: selected,
648
+ onChange: setSelected,
649
+ columnWidth: 48,
650
+ preserveSelectedRowKeys: false,
651
+ }}
652
+ scroll={{ x: columns.reduce((sum, col) => sum + col.width, 48) }}
653
+ pagination={{
654
+ current: request.currentPage,
655
+ pageSize: request.pageSize,
656
+ total,
657
+ showSizeChanger: true,
658
+ locale: {
659
+ items_per_page: "条/页",
660
+ prev_page: "上一页",
661
+ next_page: "下一页",
662
+ page_size: "每页条数",
663
+ },
664
+ pageSizeOptions: [10, 20, 30, 50, 100],
665
+ showTotal: (count) => `共 ${count} 条`,
666
+ onChange: (currentPage, pageSize) => {
667
+ setSelected([]);
668
+ setRequest((previous) => ({
669
+ ...previous,
670
+ currentPage: pageSize === previous.pageSize ? currentPage : 1,
671
+ pageSize,
672
+ }));
673
+ },
674
+ }}
675
+ locale={{
676
+ emptyText: (
677
+ <Empty
678
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
679
+ description={
680
+ Object.keys(request.where).length
681
+ ? "暂无匹配结果"
682
+ : "暂无数据"
683
+ }
684
+ />
685
+ ),
686
+ }}
687
+ />
688
+ )}
689
+ </main>
690
+ );
691
+ }
692
+ export default function ListPage() {
693
+ const hostTheme = useAppTheme();
694
+ return (
695
+ <ConfigProvider
696
+ theme={{
697
+ algorithm:
698
+ hostTheme?.mode === "dark"
699
+ ? theme.darkAlgorithm
700
+ : theme.defaultAlgorithm,
701
+ token: {
702
+ fontSize: 12,
703
+ colorPrimary: hostTheme?.skinColor || "#4548b9",
704
+ borderRadius: 6,
705
+ },
706
+ components: {
707
+ Table: { cellPaddingBlockSM: 8, cellPaddingInlineSM: 8 },
708
+ Tag: { fontSizeSM: 10 },
709
+ },
710
+ }}
711
+ >
712
+ <App>
713
+ <CustomerList />
714
+ </App>
715
+ </ConfigProvider>
716
+ );
717
+ }