@lovrabet/rabetbase-cli 2.5.4 → 2.5.5-beta.2

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