diff --git a/code/fms/.playwright-cli/console-2026-08-12T11-38-27-038Z.log b/code/fms/.playwright-cli/console-2026-08-12T11-38-27-038Z.log new file mode 100644 index 00000000..7f9a4907 --- /dev/null +++ b/code/fms/.playwright-cli/console-2026-08-12T11-38-27-038Z.log @@ -0,0 +1,27 @@ +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/0c89a48fa5027cee-s.p.1ii7211jqpzi_.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/f141b5b7abe57afc-s.p.3bm7l-ln3bnu5.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/8c2eb9ceedecfc8e-s.p.1c4v1kyduoipm.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/f06bf9da926bae75-s.p.3uuun_-7zsf1g.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/e41d5df559864f9e-s.p.2rlzm4mj5kw8e.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/e4505858a30c79c2-s.p.1simdcn5ouyn0.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/47df9ba1c7236d3b-s.p.0dnkekw3juhe5.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/fa0520225c6f3d07-s.p.3tasb8qs95n_v.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/03fc1b4a8d284b5e-s.p.45487z7p3r8wm.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/ce62453a442c7f35-s.p.3l4zvto3p0stf.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/83afe278b6a6bb3c-s.p.45535valc9rzk.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/b4e85636e2ca4056-s.p.41ski4tjpa2j-.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/1b99372b3eaef0c8-s.p.1ay-qk1u8nydy.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/797e433ab948586e-s.p.1v5bejj26fx9h.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/dc6d2a64e9dbf3bc-s.p.3yrvj83qsyboh.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/e8f2fbee2754df70-s.p.1gavkj72q9u43.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/70bc3e132a0a741e-s.p.269kn9uafm0ti.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/2a65768255d6b625-s.p.2r-cuu_7locvx.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/5fe5f57ee794eff4-s.p.3k6uam93e9kow.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/a343f882a40d2cc9-s.p.3259ncl47-hqj.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/5cf8828ea9d4dda3-s.p.2sut7fgnosohl.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/chunks/3olen860-_jty.css was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/f7aa21714c1c53f8-s.p.0jgzmitmnoe6_.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/5c285b27cdda1fe8-s.p.0lsanbtneewqp.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/248e1dc0efc99276-s.p.0dq1pb0w2temw.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/_next/static/immutable/media/c825fd02acae0153-s.p.2nh923zyv9e2o.woff2 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 +[ 5145ms] [WARNING] The resource https://ui.shadcn.com/placeholder.svg was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally. @ https://ui.shadcn.com/blocks:0 diff --git a/code/fms/.playwright-cli/page-2026-08-12T11-06-48-378Z.yml b/code/fms/.playwright-cli/page-2026-08-12T11-06-48-378Z.yml new file mode 100644 index 00000000..e69de29b diff --git a/code/fms/.playwright-cli/page-2026-08-12T11-27-27-744Z.yml b/code/fms/.playwright-cli/page-2026-08-12T11-27-27-744Z.yml new file mode 100644 index 00000000..e69de29b diff --git a/code/fms/.playwright-cli/page-2026-08-12T11-38-58-438Z.yml b/code/fms/.playwright-cli/page-2026-08-12T11-38-58-438Z.yml new file mode 100644 index 00000000..a00fb308 --- /dev/null +++ b/code/fms/.playwright-cli/page-2026-08-12T11-38-58-438Z.yml @@ -0,0 +1,739 @@ +- generic [active] [ref=e1]: + - generic [ref=e2]: + - banner [ref=e3]: + - generic [ref=e5]: + - navigation [ref=e6]: + - link "Home" [ref=e7] [cursor=pointer]: + - /url: / + - link "Docs" [ref=e8] [cursor=pointer]: + - /url: /docs/installation + - link "Components" [ref=e9] [cursor=pointer]: + - /url: /docs/components + - link "Blocks" [ref=e10] [cursor=pointer]: + - /url: /blocks + - link "Charts" [ref=e11] [cursor=pointer]: + - /url: /charts/area + - link "Directory" [ref=e12] [cursor=pointer]: + - /url: /docs/directory + - link "Typeset" [ref=e13] [cursor=pointer]: + - /url: /typeset + - link "Create" [ref=e14] [cursor=pointer]: + - /url: /create + - generic [ref=e15]: + - button "Search documentation..." [ref=e17] + - link "121k" [ref=e19] [cursor=pointer]: + - /url: https://github.com/shadcn-ui/ui + - button "Toggle theme" [ref=e21] + - link "New" [ref=e24] [cursor=pointer]: + - /url: /create + - main [ref=e25]: + - generic [ref=e28]: + - link "New Questionnaire component" [ref=e29] [cursor=pointer]: + - /url: /docs/changelog + - heading "Building Blocks for the Web" [level=1] [ref=e30] + - paragraph [ref=e31]: Clean, modern building blocks. Copy and paste into your apps. Works with all React frameworks. Open Source. Free forever. + - generic [ref=e32]: + - link "Browse Blocks" [ref=e33] [cursor=pointer]: + - /url: "#blocks" + - link "View Components" [ref=e34] [cursor=pointer]: + - /url: /docs/components + - generic [ref=e36]: + - generic [ref=e41]: + - link "Featured" [ref=e42] [cursor=pointer]: + - /url: /blocks + - link "Sidebar" [ref=e43] [cursor=pointer]: + - /url: /blocks/sidebar + - link "Login" [ref=e44] [cursor=pointer]: + - /url: /blocks/login + - link "Signup" [ref=e45] [cursor=pointer]: + - /url: /blocks/signup + - link "Browse all blocks" [ref=e46] [cursor=pointer]: + - /url: /blocks/sidebar + - generic [ref=e49]: + - generic [ref=e50]: + - generic [ref=e51]: + - tablist [ref=e53]: + - tab "Preview" [selected] [ref=e54] + - tab "Code" [ref=e55] + - link "A dashboard with sidebar, charts and data table" [ref=e56] [cursor=pointer]: + - /url: "#dashboard-01" + - generic [ref=e57]: + - group [ref=e59]: + - radio "Desktop" [checked] [ref=e60] + - radio "Tablet" [ref=e61] + - radio "Mobile" [ref=e62] + - link "Open in New Tab" [ref=e63] [cursor=pointer]: + - /url: /view/new-york-v4/dashboard-01 + - button "Refresh Preview" [ref=e65] + - button "npx shadcn add dashboard-01" [ref=e67] + - link "Open in" [ref=e69] [cursor=pointer]: + - /url: https://v0.dev/chat/api/open?url=https://ui.shadcn.com/r/styles/new-york-v4/dashboard-01.json + - generic [ref=e73]: + - iframe [ref=e76]: + - generic [ref=f1e1]: + - generic [ref=f1e3]: + - generic [ref=f1e6]: + - list [ref=f1e8]: + - listitem [ref=f1e9]: + - link "Acme Inc." [ref=f1e10] [cursor=pointer]: + - /url: "#" + - generic [ref=f1e15]: + - generic [ref=f1e17]: + - list [ref=f1e18]: + - listitem [ref=f1e19]: + - button "Quick Create" [ref=f1e20] + - button "Inbox" [ref=f1e24] + - list [ref=f1e26]: + - listitem [ref=f1e27]: + - button "Dashboard" [ref=f1e28] + - listitem [ref=f1e34]: + - button "Lifecycle" [ref=f1e35] + - listitem [ref=f1e40]: + - button "Analytics" [ref=f1e41] + - listitem [ref=f1e47]: + - button "Projects" [ref=f1e48] + - listitem [ref=f1e52]: + - button "Team" [ref=f1e53] + - generic [ref=f1e60]: + - generic [ref=f1e61]: Documents + - list [ref=f1e62]: + - listitem [ref=f1e63]: + - link "Data Library" [ref=f1e64] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f1e70] + - listitem [ref=f1e76]: + - link "Reports" [ref=f1e77] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f1e85] + - listitem [ref=f1e91]: + - link "Word Assistant" [ref=f1e92] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f1e98] + - listitem [ref=f1e104]: + - button "More" [ref=f1e105] + - list [ref=f1e113]: + - listitem [ref=f1e114]: + - link "Settings" [ref=f1e115] [cursor=pointer]: + - /url: "#" + - listitem [ref=f1e120]: + - link "Get Help" [ref=f1e121] [cursor=pointer]: + - /url: "#" + - listitem [ref=f1e126]: + - link "Search" [ref=f1e127] [cursor=pointer]: + - /url: "#" + - list [ref=f1e133]: + - listitem [ref=f1e134]: + - button "CN shadcn m@example.com" [ref=f1e135]: + - generic [ref=f1e136]: CN + - generic [ref=f1e138]: + - generic [ref=f1e139]: shadcn + - generic [ref=f1e140]: m@example.com + - main [ref=f1e145]: + - generic [ref=f1e147]: + - button "Toggle Sidebar" [ref=f1e148] + - heading "Documents" [level=1] [ref=f1e150] + - link "GitHub" [ref=f1e152] [cursor=pointer]: + - /url: https://github.com/shadcn-ui/ui/tree/main/apps/v4/app/(examples)/dashboard + - generic [ref=f1e155]: + - generic [ref=f1e156]: + - generic [ref=f1e157]: + - generic [ref=f1e158]: + - generic [ref=f1e159]: Total Revenue + - generic [ref=f1e160]: $1,250.00 + - generic [ref=f1e161]: +12.5% + - generic [ref=f1e163]: + - generic [ref=f1e164]: Trending up this month + - generic [ref=f1e168]: Visitors for the last 6 months + - generic [ref=f1e169]: + - generic [ref=f1e170]: + - generic [ref=f1e171]: New Customers + - generic [ref=f1e172]: 1,234 + - generic [ref=f1e173]: "-20%" + - generic [ref=f1e175]: + - generic [ref=f1e176]: Down 20% this period + - generic [ref=f1e180]: Acquisition needs attention + - generic [ref=f1e181]: + - generic [ref=f1e182]: + - generic [ref=f1e183]: Active Accounts + - generic [ref=f1e184]: 45,678 + - generic [ref=f1e185]: +12.5% + - generic [ref=f1e187]: + - generic [ref=f1e188]: Strong user retention + - generic [ref=f1e192]: Engagement exceed targets + - generic [ref=f1e193]: + - generic [ref=f1e194]: + - generic [ref=f1e195]: Growth Rate + - generic [ref=f1e196]: 4.5% + - generic [ref=f1e197]: +4.5% + - generic [ref=f1e199]: + - generic [ref=f1e200]: Steady performance increase + - generic [ref=f1e204]: Meets growth projections + - generic [ref=f1e206]: + - generic [ref=f1e207]: + - generic [ref=f1e208]: Total Visitors + - generic [ref=f1e209]: Total for the last 3 months + - group [ref=f1e212]: + - radio "Last 3 months" [checked] [ref=f1e213] + - radio "Last 30 days" [ref=f1e214] + - radio "Last 7 days" [ref=f1e215] + - application [ref=f1e220]: + - generic [ref=f1e238]: + - generic [ref=f1e239]: Apr 7 + - generic [ref=f1e241]: Apr 15 + - generic [ref=f1e243]: Apr 23 + - generic [ref=f1e245]: May 1 + - generic [ref=f1e247]: May 9 + - generic [ref=f1e249]: May 17 + - generic [ref=f1e251]: May 26 + - generic [ref=f1e253]: Jun 3 + - generic [ref=f1e255]: Jun 11 + - generic [ref=f1e257]: Jun 20 + - generic [ref=f1e259]: Jun 30 + - generic [ref=f1e261]: + - generic [ref=f1e262]: + - generic [ref=f1e263]: View + - combobox "View" [ref=f1e264]: + - generic: Outline + - generic [ref=f1e265]: + - button "Customize Columns" [ref=f1e266] + - button "Add Section" [ref=f1e268] + - tabpanel "Outline" [ref=f1e270]: + - generic [ref=f1e271]: + - table [ref=f1e273]: + - rowgroup [ref=f1e274]: + - row [ref=f1e275]: + - columnheader [ref=f1e276] + - columnheader [ref=f1e277]: + - checkbox "Select all" [ref=f1e279] + - columnheader "Header" [ref=f1e280] + - columnheader "Section Type" [ref=f1e281] + - columnheader "Status" [ref=f1e282] + - columnheader "Target" [ref=f1e283] + - columnheader "Limit" [ref=f1e285] + - columnheader "Reviewer" [ref=f1e287] + - columnheader [ref=f1e288] + - rowgroup [ref=f1e289]: + - row [ref=f1e290]: + - cell [ref=f1e291]: + - button "Drag to reorder" [ref=f1e292] + - cell [ref=f1e294]: + - checkbox "Select row" [ref=f1e296] + - cell [ref=f1e297]: + - button "Cover page" [ref=f1e298] + - cell "Cover page" [ref=f1e299] + - cell [ref=f1e302] + - cell [ref=f1e304]: + - generic [ref=f1e305]: + - generic [ref=f1e306]: Target + - textbox "Target" [ref=f1e307]: "18" + - cell [ref=f1e308]: + - generic [ref=f1e309]: + - generic [ref=f1e310]: Limit + - textbox "Limit" [ref=f1e311]: "5" + - cell "Eddie Lake" [ref=f1e312] + - cell [ref=f1e313]: + - button "Open menu" [ref=f1e314] + - row [ref=f1e316]: + - cell [ref=f1e317]: + - button "Drag to reorder" [ref=f1e318] + - cell [ref=f1e320]: + - checkbox "Select row" [ref=f1e322] + - cell [ref=f1e323]: + - button "Table of contents" [ref=f1e324] + - cell "Table of contents" [ref=f1e325] + - cell [ref=f1e328] + - cell [ref=f1e330]: + - generic [ref=f1e331]: + - generic [ref=f1e332]: Target + - textbox "Target" [ref=f1e333]: "29" + - cell [ref=f1e334]: + - generic [ref=f1e335]: + - generic [ref=f1e336]: Limit + - textbox "Limit" [ref=f1e337]: "24" + - cell "Eddie Lake" [ref=f1e338] + - cell [ref=f1e339]: + - button "Open menu" [ref=f1e340] + - row [ref=f1e342]: + - cell [ref=f1e343]: + - button "Drag to reorder" [ref=f1e344] + - cell [ref=f1e346]: + - checkbox "Select row" [ref=f1e348] + - cell [ref=f1e349]: + - button "Executive summary" [ref=f1e350] + - cell "Narrative" [ref=f1e351] + - cell [ref=f1e354] + - cell [ref=f1e356]: + - generic [ref=f1e357]: + - generic [ref=f1e358]: Target + - textbox "Target" [ref=f1e359]: "10" + - cell [ref=f1e360]: + - generic [ref=f1e361]: + - generic [ref=f1e362]: Limit + - textbox "Limit" [ref=f1e363]: "13" + - cell "Eddie Lake" [ref=f1e364] + - cell [ref=f1e365]: + - button "Open menu" [ref=f1e366] + - row [ref=f1e368]: + - cell [ref=f1e369]: + - button "Drag to reorder" [ref=f1e370] + - cell [ref=f1e372]: + - checkbox "Select row" [ref=f1e374] + - cell [ref=f1e375]: + - button "Technical approach" [ref=f1e376] + - cell "Narrative" [ref=f1e377] + - cell [ref=f1e380] + - cell [ref=f1e382]: + - generic [ref=f1e383]: + - generic [ref=f1e384]: Target + - textbox "Target" [ref=f1e385]: "27" + - cell [ref=f1e386]: + - generic [ref=f1e387]: + - generic [ref=f1e388]: Limit + - textbox "Limit" [ref=f1e389]: "23" + - cell "Jamik Tashpulatov" [ref=f1e390] + - cell [ref=f1e391]: + - button "Open menu" [ref=f1e392] + - row [ref=f1e394]: + - cell [ref=f1e395]: + - button "Drag to reorder" [ref=f1e396] + - cell [ref=f1e398]: + - checkbox "Select row" [ref=f1e400] + - cell [ref=f1e401]: + - button "Design" [ref=f1e402] + - cell "Narrative" [ref=f1e403] + - cell [ref=f1e406] + - cell [ref=f1e408]: + - generic [ref=f1e409]: + - generic [ref=f1e410]: Target + - textbox "Target" [ref=f1e411]: "2" + - cell [ref=f1e412]: + - generic [ref=f1e413]: + - generic [ref=f1e414]: Limit + - textbox "Limit" [ref=f1e415]: "16" + - cell "Jamik Tashpulatov" [ref=f1e416] + - cell [ref=f1e417]: + - button "Open menu" [ref=f1e418] + - row [ref=f1e420]: + - cell [ref=f1e421]: + - button "Drag to reorder" [ref=f1e422] + - cell [ref=f1e424]: + - checkbox "Select row" [ref=f1e426] + - cell [ref=f1e427]: + - button "Capabilities" [ref=f1e428] + - cell "Narrative" [ref=f1e429] + - cell [ref=f1e432] + - cell [ref=f1e434]: + - generic [ref=f1e435]: + - generic [ref=f1e436]: Target + - textbox "Target" [ref=f1e437]: "20" + - cell [ref=f1e438]: + - generic [ref=f1e439]: + - generic [ref=f1e440]: Limit + - textbox "Limit" [ref=f1e441]: "8" + - cell "Jamik Tashpulatov" [ref=f1e442] + - cell [ref=f1e443]: + - button "Open menu" [ref=f1e444] + - row [ref=f1e446]: + - cell [ref=f1e447]: + - button "Drag to reorder" [ref=f1e448] + - cell [ref=f1e450]: + - checkbox "Select row" [ref=f1e452] + - cell [ref=f1e453]: + - button "Integration with existing systems" [ref=f1e454] + - cell "Narrative" [ref=f1e455] + - cell [ref=f1e458] + - cell [ref=f1e460]: + - generic [ref=f1e461]: + - generic [ref=f1e462]: Target + - textbox "Target" [ref=f1e463]: "19" + - cell [ref=f1e464]: + - generic [ref=f1e465]: + - generic [ref=f1e466]: Limit + - textbox "Limit" [ref=f1e467]: "21" + - cell "Jamik Tashpulatov" [ref=f1e468] + - cell [ref=f1e469]: + - button "Open menu" [ref=f1e470] + - row [ref=f1e472]: + - cell [ref=f1e473]: + - button "Drag to reorder" [ref=f1e474] + - cell [ref=f1e476]: + - checkbox "Select row" [ref=f1e478] + - cell [ref=f1e479]: + - button "Innovation and Advantages" [ref=f1e480] + - cell "Narrative" [ref=f1e481] + - cell [ref=f1e484] + - cell [ref=f1e486]: + - generic [ref=f1e487]: + - generic [ref=f1e488]: Target + - textbox "Target" [ref=f1e489]: "25" + - cell [ref=f1e490]: + - generic [ref=f1e491]: + - generic [ref=f1e492]: Limit + - textbox "Limit" [ref=f1e493]: "26" + - cell [ref=f1e494]: + - combobox "Reviewer" [ref=f1e496]: + - generic: Assign reviewer + - cell [ref=f1e497]: + - button "Open menu" [ref=f1e498] + - row [ref=f1e500]: + - cell [ref=f1e501]: + - button "Drag to reorder" [ref=f1e502] + - cell [ref=f1e504]: + - checkbox "Select row" [ref=f1e506] + - cell [ref=f1e507]: + - button "Overview of EMR's Innovative Solutions" [ref=f1e508] + - cell "Technical content" [ref=f1e509] + - cell [ref=f1e512] + - cell [ref=f1e514]: + - generic [ref=f1e515]: + - generic [ref=f1e516]: Target + - textbox "Target" [ref=f1e517]: "7" + - cell [ref=f1e518]: + - generic [ref=f1e519]: + - generic [ref=f1e520]: Limit + - textbox "Limit" [ref=f1e521]: "23" + - cell [ref=f1e522]: + - combobox "Reviewer" [ref=f1e524]: + - generic: Assign reviewer + - cell [ref=f1e525]: + - button "Open menu" [ref=f1e526] + - row [ref=f1e528]: + - cell [ref=f1e529]: + - button "Drag to reorder" [ref=f1e530] + - cell [ref=f1e532]: + - checkbox "Select row" [ref=f1e534] + - cell [ref=f1e535]: + - button "Advanced Algorithms and Machine Learning" [ref=f1e536] + - cell "Narrative" [ref=f1e537] + - cell [ref=f1e540] + - cell [ref=f1e542]: + - generic [ref=f1e543]: + - generic [ref=f1e544]: Target + - textbox "Target" [ref=f1e545]: "30" + - cell [ref=f1e546]: + - generic [ref=f1e547]: + - generic [ref=f1e548]: Limit + - textbox "Limit" [ref=f1e549]: "28" + - cell [ref=f1e550]: + - combobox "Reviewer" [ref=f1e552]: + - generic: Assign reviewer + - cell [ref=f1e553]: + - button "Open menu" [ref=f1e554] + - status [ref=f1e556] + - generic [ref=f1e557]: + - generic [ref=f1e558]: 0 of 68 row(s) selected. + - generic [ref=f1e559]: + - generic [ref=f1e560]: + - generic [ref=f1e561]: Rows per page + - combobox "Rows per page" [ref=f1e562]: + - generic: "10" + - generic [ref=f1e563]: Page 1 of 7 + - generic [ref=f1e564]: + - button "Go to first page" [disabled] + - button "Go to previous page" [disabled] + - button "Go to next page" [ref=f1e565] + - button "Go to last page" [ref=f1e567] + - region "Notifications alt+T" + - alert [ref=f1e569] + - generic [ref=f1e570]: "20" + - generic: + - region "Notifications" + - separator [ref=e77] + - generic [ref=e78]: + - generic [ref=e79]: + - tablist [ref=e81]: + - tab "Preview" [selected] [ref=e82] + - tab "Code" [ref=e83] + - link "A sidebar that collapses to icons" [ref=e84] [cursor=pointer]: + - /url: "#sidebar-07" + - generic [ref=e85]: + - group [ref=e87]: + - radio "Desktop" [checked] [ref=e88] + - radio "Tablet" [ref=e89] + - radio "Mobile" [ref=e90] + - link "Open in New Tab" [ref=e91] [cursor=pointer]: + - /url: /view/new-york-v4/sidebar-07 + - button "Refresh Preview" [ref=e93] + - button "npx shadcn add sidebar-07" [ref=e95] + - link "Open in" [ref=e97] [cursor=pointer]: + - /url: https://v0.dev/chat/api/open?url=https://ui.shadcn.com/r/styles/new-york-v4/sidebar-07.json + - generic [ref=e101]: + - iframe [ref=e104]: + - generic [ref=f2e1]: + - generic [ref=f2e3]: + - generic [ref=f2e6]: + - list [ref=f2e8]: + - listitem [ref=f2e9]: + - button "Acme Inc Enterprise" [ref=f2e10]: + - generic [ref=f2e14]: + - generic [ref=f2e15]: Acme Inc + - generic [ref=f2e16]: Enterprise + - generic [ref=f2e20]: + - generic [ref=f2e21]: + - generic [ref=f2e22]: Platform + - list [ref=f2e23]: + - listitem [ref=f2e24]: + - button "Playground" [expanded] [ref=f2e25] + - list [ref=f2e33]: + - listitem [ref=f2e34]: + - link "History" [ref=f2e35] [cursor=pointer]: + - /url: "#" + - listitem [ref=f2e37]: + - link "Starred" [ref=f2e38] [cursor=pointer]: + - /url: "#" + - listitem [ref=f2e40]: + - link "Settings" [ref=f2e41] [cursor=pointer]: + - /url: "#" + - listitem [ref=f2e43]: + - button "Models" [ref=f2e44] + - listitem [ref=f2e51]: + - button "Documentation" [ref=f2e52] + - listitem [ref=f2e58]: + - button "Settings" [ref=f2e59] + - generic [ref=f2e66]: + - generic [ref=f2e67]: Projects + - list [ref=f2e68]: + - listitem [ref=f2e69]: + - link "Design Engineering" [ref=f2e70] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f2e73] + - listitem [ref=f2e79]: + - link "Sales & Marketing" [ref=f2e80] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f2e85] + - listitem [ref=f2e91]: + - link "Travel" [ref=f2e92] [cursor=pointer]: + - /url: "#" + - button "More" [ref=f2e96] + - listitem [ref=f2e102]: + - button "More" [ref=f2e103] + - list [ref=f2e110]: + - listitem [ref=f2e111]: + - button "shadcn shadcn m@example.com" [ref=f2e112]: + - img "shadcn" [ref=f2e114] + - generic [ref=f2e115]: + - generic [ref=f2e116]: shadcn + - generic [ref=f2e117]: m@example.com + - button "Toggle Sidebar" [ref=f2e121] + - main [ref=f2e122]: + - generic [ref=f2e124]: + - button "Toggle Sidebar" [ref=f2e125] + - navigation "breadcrumb" [ref=f2e127]: + - list [ref=f2e128]: + - listitem [ref=f2e129]: + - link "Build Your Application" [ref=f2e130] [cursor=pointer]: + - /url: "#" + - listitem [ref=f2e131] + - listitem [ref=f2e134]: + - link "Data Fetching" [disabled] [ref=f2e135] + - region "Notifications alt+T" + - alert [ref=f2e142] + - generic: + - region "Notifications" + - separator [ref=e105] + - generic [ref=e106]: + - generic [ref=e107]: + - tablist [ref=e109]: + - tab "Preview" [selected] [ref=e110] + - tab "Code" [ref=e111] + - link "A sidebar with submenus" [ref=e112] [cursor=pointer]: + - /url: "#sidebar-03" + - generic [ref=e113]: + - group [ref=e115]: + - radio "Desktop" [checked] [ref=e116] + - radio "Tablet" [ref=e117] + - radio "Mobile" [ref=e118] + - link "Open in New Tab" [ref=e119] [cursor=pointer]: + - /url: /view/new-york-v4/sidebar-03 + - button "Refresh Preview" [ref=e121] + - button "npx shadcn add sidebar-03" [ref=e123] + - link "Open in" [ref=e125] [cursor=pointer]: + - /url: https://v0.dev/chat/api/open?url=https://ui.shadcn.com/r/styles/new-york-v4/sidebar-03.json + - generic [ref=e129]: + - iframe [ref=e132]: + - generic [ref=f3e1]: + - generic [ref=f3e3]: + - generic [ref=f3e6]: + - list [ref=f3e8]: + - listitem [ref=f3e9]: + - link "Documentation v1.0.0" [ref=f3e10] [cursor=pointer]: + - /url: "#" + - generic [ref=f3e14]: + - generic [ref=f3e15]: Documentation + - generic [ref=f3e16]: v1.0.0 + - list [ref=f3e19]: + - listitem [ref=f3e20]: + - link "Getting Started" [ref=f3e21] [cursor=pointer]: + - /url: "#" + - list [ref=f3e22]: + - listitem [ref=f3e23]: + - link "Installation" [ref=f3e24] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e25]: + - link "Project Structure" [ref=f3e26] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e27]: + - link "Build Your Application" [ref=f3e28] [cursor=pointer]: + - /url: "#" + - list [ref=f3e29]: + - listitem [ref=f3e30]: + - link "Routing" [ref=f3e31] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e32]: + - link "Data Fetching" [ref=f3e33] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e34]: + - link "Rendering" [ref=f3e35] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e36]: + - link "Caching" [ref=f3e37] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e38]: + - link "Styling" [ref=f3e39] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e40]: + - link "Optimizing" [ref=f3e41] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e42]: + - link "Configuring" [ref=f3e43] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e44]: + - link "Testing" [ref=f3e45] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e46]: + - link "Authentication" [ref=f3e47] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e48]: + - link "Deploying" [ref=f3e49] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e50]: + - link "Upgrading" [ref=f3e51] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e52]: + - link "Examples" [ref=f3e53] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e54]: + - link "API Reference" [ref=f3e55] [cursor=pointer]: + - /url: "#" + - list [ref=f3e56]: + - listitem [ref=f3e57]: + - link "Components" [ref=f3e58] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e59]: + - link "File Conventions" [ref=f3e60] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e61]: + - link "Functions" [ref=f3e62] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e63]: + - link "next.config.js Options" [ref=f3e64] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e65]: + - link "CLI" [ref=f3e66] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e67]: + - link "Edge Runtime" [ref=f3e68] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e69]: + - link "Architecture" [ref=f3e70] [cursor=pointer]: + - /url: "#" + - list [ref=f3e71]: + - listitem [ref=f3e72]: + - link "Accessibility" [ref=f3e73] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e74]: + - link "Fast Refresh" [ref=f3e75] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e76]: + - link "Next.js Compiler" [ref=f3e77] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e78]: + - link "Supported Browsers" [ref=f3e79] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e80]: + - link "Turbopack" [ref=f3e81] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e82]: + - link "Community" [ref=f3e83] [cursor=pointer]: + - /url: "#" + - list [ref=f3e84]: + - listitem [ref=f3e85]: + - link "Contribution Guide" [ref=f3e86] [cursor=pointer]: + - /url: "#" + - button "Toggle Sidebar" [ref=f3e87] + - main [ref=f3e88]: + - generic [ref=f3e90]: + - button "Toggle Sidebar" [ref=f3e91] + - navigation "breadcrumb" [ref=f3e93]: + - list [ref=f3e94]: + - listitem [ref=f3e95]: + - link "Build Your Application" [ref=f3e96] [cursor=pointer]: + - /url: "#" + - listitem [ref=f3e97] + - listitem [ref=f3e100]: + - link "Data Fetching" [disabled] [ref=f3e101] + - region "Notifications alt+T" + - alert [ref=f3e108] + - generic: + - region "Notifications" + - separator [ref=e133] + - generic [ref=e134]: + - generic [ref=e135]: + - tablist [ref=e137]: + - tab "Preview" [selected] [ref=e138] + - tab "Code" [ref=e139] + - link "A login page with a muted background color" [ref=e140] [cursor=pointer]: + - /url: "#login-03" + - generic [ref=e141]: + - group [ref=e143]: + - radio "Desktop" [checked] [ref=e144] + - radio "Tablet" [ref=e145] + - radio "Mobile" [ref=e146] + - link "Open in New Tab" [ref=e147] [cursor=pointer]: + - /url: /view/new-york-v4/login-03 + - button "Refresh Preview" [ref=e149] + - button "npx shadcn add login-03" [ref=e151] + - link "Open in" [ref=e153] [cursor=pointer]: + - /url: https://v0.dev/chat/api/open?url=https://ui.shadcn.com/r/styles/new-york-v4/login-03.json + - generic [ref=e157]: + - iframe [ref=e160] + - separator [ref=e161] + - generic [ref=e162]: + - generic [ref=e163]: + - tablist [ref=e165]: + - tab "Preview" [selected] [ref=e166] + - tab "Code" [ref=e167] + - link "A login page with form and image" [ref=e168] [cursor=pointer]: + - /url: "#login-04" + - generic [ref=e169]: + - group [ref=e171]: + - radio "Desktop" [checked] [ref=e172] + - radio "Tablet" [ref=e173] + - radio "Mobile" [ref=e174] + - link "Open in New Tab" [ref=e175] [cursor=pointer]: + - /url: /view/new-york-v4/login-04 + - button "Refresh Preview" [ref=e177] + - button "npx shadcn add login-04" [ref=e179] + - link "Open in" [ref=e181] [cursor=pointer]: + - /url: https://v0.dev/chat/api/open?url=https://ui.shadcn.com/r/styles/new-york-v4/login-04.json + - generic [ref=e185]: + - iframe [ref=e188] + - separator [ref=e189] + - link "Browse more blocks" [ref=e192] [cursor=pointer]: + - /url: /blocks/sidebar + - contentinfo [ref=e193]: + - generic [ref=e196]: + - text: Built by + - link "shadcn" [ref=e197] [cursor=pointer]: + - /url: https://twitter.com/shadcn + - text: at + - link "Vercel" [ref=e198] [cursor=pointer]: + - /url: https://vercel.com/new?utm_source=shadcn_site&utm_medium=web&utm_campaign=docs_cta_deploy_now_callout + - text: . The source code is available on + - link "GitHub" [ref=e199] [cursor=pointer]: + - /url: https://github.com/shadcn-ui/ui + - text: . + - region "Notifications alt+T" + - alert [ref=e200] + - generic: + - region "Notifications" \ No newline at end of file diff --git a/code/fms/.playwright-cli/page-2026-08-12T11-39-05-825Z.yml b/code/fms/.playwright-cli/page-2026-08-12T11-39-05-825Z.yml new file mode 100644 index 00000000..e69de29b diff --git a/code/fms/erp-layout-patterns-demo.html b/code/fms/erp-layout-patterns-demo.html deleted file mode 100644 index 365f4c35..00000000 --- a/code/fms/erp-layout-patterns-demo.html +++ /dev/null @@ -1,1091 +0,0 @@ - - - - - -国外 ERP 布局模式 Demo — 分类树 + 内容区 - - - - - -
- - - 模块管理 -
- - - -
-
- - -
- - - -
- - -
- - - - - -
- -
- - - -
-
-

合作伙伴

-
- 数据模块 - · - v_b_othercompany - 已启用 -
-
-
- - -
-
- - -
- - -
- - -
- - -
- - -
-
-
-

身份信息

- 定义模块在系统中的基本身份标识 -
-
-
-
-
-
-
- -
-
-
- -
-
-
-
-
- - -
-
-
-

数据源配置 数据模块从查询视图读取

-
- -
-
-
-
-
-
-
-
-
-
-
-
- - -
-

功能开关

-
-
-
- - 启用模块 -
-
- - 在菜单中显示 -
-
- - 允许导出 -
-
- - 启用审计日志 -
-
-
-
- - - -
-
- - -
-
-
-
-

字段定义

从视图同步字段,调整显示属性
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
序字段名显示名称类型宽度状态
⋮⋮b_id编号数字120启用
⋮⋮b_name名称文本200启用
⋮⋮b_shortname简称文本140启用
⋮⋮b_type类型选择150启用
⋮⋮b_tel电话文本130停用
-
-
-
-
-
- - -
-
-
- ⓘ -
权限控制目前仅在前端生效。后端拦截尚未实现,建议在后续版本中增加 API 层面的权限校验。
-
-
-
-

操作权限

控制用户可执行的操作
- -
-
-
- - - - - - - -
操作名称操作编码类型状态
新增add数据操作启用
编辑edit数据操作启用
删除delete数据操作受限
导出export批量操作停用
-
-
-
-
- - -
-
-
-

操作日志

-
-
- - - - - - - -
时间操作操作人详情
2026-08-08 15:32修改管理员更新了字段「简称」的显示名称
2026-08-07 09:15新增张三新增了操作权限「导出」
2026-08-05 17:48同步系统从视图同步了 12 个字段
2026-08-01 10:00创建管理员创建模块「合作伙伴」
-
-
-
-
-
-
-
- - - - - - - - diff --git a/code/fms/fms-vue/src/views/system/module-management/components/FieldGroupManager.vue b/code/fms/fms-vue/src/views/system/module-management/components/FieldGroupManager.vue index a2958e89..96d39a28 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/FieldGroupManager.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/FieldGroupManager.vue @@ -6,10 +6,7 @@ import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; import { Label } from "@/components/ui/label"; import FmsTree from "@/components/FmsTree.vue"; -import { - loadDataApi, - saveObjectApi, -} from "@/services/api"; +import { loadDataApi, saveObjectApi } from "@/services/api"; import { diffRows, tableChange, @@ -57,15 +54,18 @@ function rebuildTree() { groupTree.value = buildGroupTree(props.groups); } -watch(() => props.open, (v) => { - if (v) { - rebuildTree(); - const all = props.groups.map((g) => String(g.b_id)); - expandedKeys.value = all; - dirty.value = false; - selectedGroupId.value = null; - } -}); +watch( + () => props.open, + (v) => { + if (v) { + rebuildTree(); + const all = props.groups.map((g) => String(g.b_id)); + expandedKeys.value = all; + dirty.value = false; + selectedGroupId.value = null; + } + }, +); const selectedGroup = ref | null>(null); @@ -74,8 +74,7 @@ watch(selectedGroupId, (id) => { selectedGroup.value = null; return; } - selectedGroup.value = - props.groups.find((g) => String(g.b_id) === id) || null; + selectedGroup.value = props.groups.find((g) => String(g.b_id) === id) || null; }); function findNode(key: string): Record | null { @@ -160,7 +159,12 @@ async function deleteGroup(groupId: string) { toast.error("该分组已被列表配置或编辑配置引用,请先取消引用。"); return; } - const ok = await confirm({ title: "删除分组", description: "确定删除该分组?", confirmText: "删除", danger: true }); + const ok = await confirm({ + title: "删除分组", + description: "确定删除该分组?", + confirmText: "删除", + danger: true, + }); if (!ok) return; const walk = (nodes: Record[]): boolean => { @@ -223,14 +227,13 @@ async function close() { -
+
请从左侧选择分组
@@ -308,13 +322,13 @@ async function close() {
-
- - +
diff --git a/code/fms/fms-vue/src/views/system/module-management/components/I18nQuickSetModal.vue b/code/fms/fms-vue/src/views/system/module-management/components/I18nQuickSetModal.vue index 73b8ef21..3b8400b9 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/I18nQuickSetModal.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/I18nQuickSetModal.vue @@ -21,45 +21,46 @@ const locales = ref([]); const loading = ref(false); const saving = ref(false); +watch( + () => props.open, + async (v) => { + if (!v) return; + loading.value = true; + try { + const key = props.i18nKey; + if (!key) { + translations.value = {}; + return; + } + // Load language types + const langRes = await loadDataApi( + "b_i18n_type", + "b_canuse = 1", + "b_default DESC, b_xh ASC, b_id ASC", + ); + const langs = (langRes.data || []) as { b_code: string; b_default: number }[]; + locales.value = langs.map((l) => l.b_code); + // Load existing translations + const i18nRes = await loadDataApi("b_i18n", `b_key = '${key}'`); + const existing = (i18nRes.data || []) as { b_locale: string; b_value: string }[]; -watch(() => props.open, async (v) => { - if (!v) return; - loading.value = true; - try { - const key = props.i18nKey; - if (!key) { - translations.value = {}; - return; + const values: Record = {}; + for (const lang of locales.value) { + const found = existing.find((e) => e.b_locale === lang); + values[lang] = found?.b_value ?? ""; + } + // Set default value for primary locale + const primary = langs.find((l) => Number(l.b_default) === 1); + if (primary && !values[primary.b_code]) { + values[primary.b_code] = props.defaultValue; + } + translations.value = values; + } finally { + loading.value = false; } - // Load language types - const langRes = await loadDataApi( - "b_i18n_type", - "b_canuse = 1", - "b_default DESC, b_xh ASC, b_id ASC", - ); - const langs = (langRes.data || []) as { b_code: string; b_default: number }[]; - locales.value = langs.map((l) => l.b_code); - - // Load existing translations - const i18nRes = await loadDataApi("b_i18n", `b_key = '${key}'`); - const existing = (i18nRes.data || []) as { b_locale: string; b_value: string }[]; - - const values: Record = {}; - for (const lang of locales.value) { - const found = existing.find((e) => e.b_locale === lang); - values[lang] = found?.b_value ?? ""; - } - // Set default value for primary locale - const primary = langs.find((l) => Number(l.b_default) === 1); - if (primary && !values[primary.b_code]) { - values[primary.b_code] = props.defaultValue; - } - translations.value = values; - } finally { - loading.value = false; - } -}); + }, +); async function save() { saving.value = true; @@ -77,9 +78,7 @@ async function save() { }); } if (inserts.length) { - await saveObjectApi([ - { table: "b_i18n", key_field: "b_key", inserts }, - ]); + await saveObjectApi([{ table: "b_i18n", key_field: "b_key", inserts }]); } emit("saved", key); emit("update:open", false); @@ -97,7 +96,9 @@ function close() {
-
+
多语言快速设置 @@ -113,22 +121,17 @@ function close() {
- -
-
- 加载中… +
+
加载中…
- +
- - +
diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleAutoCodePanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleAutoCodePanel.vue index abbbed7b..20113ba2 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleAutoCodePanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleAutoCodePanel.vue @@ -3,42 +3,178 @@ import { computed } from "vue"; import { Switch } from "@/components/ui/switch"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import { createAutoCodeDraft } from "../common"; -const props = defineProps<{ moduleId: string; autoCode: Record[]; fields: Record[]; loading?: boolean }>(); +const props = defineProps<{ + moduleId: string; + autoCode: Record[]; + fields: Record[]; + loading?: boolean; +}>(); const emit = defineEmits<{ (e: "update", rows: Record[]): void }>(); -const rule = computed(() => props.autoCode?.length ? props.autoCode[0] : null); +const rule = computed(() => (props.autoCode?.length ? props.autoCode[0] : null)); const enabled = computed(() => Number(rule.value?.b_canuse) === 1); -const FMT = ["yyyy","yy","yyyyMM","yyyy-MM","yyyyMMdd","yyyy-MM-dd","yyyy/MM/dd","yyyyMMddHHmm","yyyy-MM-dd HH:mm","yyyy/MM/dd HH:mm"]; -const AVF = computed(() => (props.fields || []).filter((f) => Number(f.b_canuse) === 1 && f.b_field !== "b_id" && (f.b_type === "input" || f.b_type === "textarea"))); -const RST = [{ value: "none", label: "不重置" },{ value: "year", label: "按年" },{ value: "month", label: "按月" },{ value: "day", label: "按日" }]; -const preview = computed(() => { if (!rule.value || !enabled.value) return ""; const p = String(rule.value.b_prefix || ""), sep = String(rule.value.b_separator || ""), fmt = String(rule.value.b_date_format || ""), w = Number(rule.value.b_sequence_width || 5), sv = Number(rule.value.b_start_value || 1); const d = new Date(), Y = String(d.getFullYear()), y = Y.slice(2), M = String(d.getMonth()+1).padStart(2,"0"), D = String(d.getDate()).padStart(2,"0"); const ds = fmt.replace("yyyy",Y).replace("yy",y).replace("MM",M).replace("dd",D); return `${p}${ds}${sep}${String(sv).padStart(w,"0")}`; }); -function setEn(v: boolean) { if (v && !rule.value) { emit("update", [createAutoCodeDraft(props.moduleId, props.fields as any, true)]); } else if (rule.value) { emit("update", [{ ...rule.value, b_canuse: v ? 1 : 0 }]); } } -function up(key: string, value: unknown) { if (!rule.value) return; emit("update", [{ ...rule.value, [key]: value }]); } +const FMT = [ + "yyyy", + "yy", + "yyyyMM", + "yyyy-MM", + "yyyyMMdd", + "yyyy-MM-dd", + "yyyy/MM/dd", + "yyyyMMddHHmm", + "yyyy-MM-dd HH:mm", + "yyyy/MM/dd HH:mm", +]; +const AVF = computed(() => + (props.fields || []).filter( + (f) => + Number(f.b_canuse) === 1 && + f.b_field !== "b_id" && + (f.b_type === "input" || f.b_type === "textarea"), + ), +); +const RST = [ + { value: "none", label: "不重置" }, + { value: "year", label: "按年" }, + { value: "month", label: "按月" }, + { value: "day", label: "按日" }, +]; +const preview = computed(() => { + if (!rule.value || !enabled.value) return ""; + const p = String(rule.value.b_prefix || ""), + sep = String(rule.value.b_separator || ""), + fmt = String(rule.value.b_date_format || ""), + w = Number(rule.value.b_sequence_width || 5), + sv = Number(rule.value.b_start_value || 1); + const d = new Date(), + Y = String(d.getFullYear()), + y = Y.slice(2), + M = String(d.getMonth() + 1).padStart(2, "0"), + D = String(d.getDate()).padStart(2, "0"); + const ds = fmt.replace("yyyy", Y).replace("yy", y).replace("MM", M).replace("dd", D); + return `${p}${ds}${sep}${String(sv).padStart(w, "0")}`; +}); +function setEn(v: boolean) { + if (v && !rule.value) { + emit("update", [createAutoCodeDraft(props.moduleId, props.fields as any, true)]); + } else if (rule.value) { + emit("update", [{ ...rule.value, b_canuse: v ? 1 : 0 }]); + } +} +function up(key: string, value: unknown) { + if (!rule.value) return; + emit("update", [{ ...rule.value, [key]: value }]); +} + + - diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleBasicPanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleBasicPanel.vue index 7e3a1395..d16f0496 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleBasicPanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleBasicPanel.vue @@ -3,19 +3,66 @@ import { Globe } from "@lucide/vue"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import I18nQuickSetModal from "./I18nQuickSetModal.vue"; import { MODULE_TYPE_LABELS } from "@/types/module"; import { buildModuleI18nKey } from "@/utils/i18n"; -const props = defineProps<{ moduleId: string; data: Record | null; parentName?: string; loading?: boolean }>(); +const props = defineProps<{ + moduleId: string; + data: Record | null; + parentName?: string; + loading?: boolean; +}>(); const emit = defineEmits<{ (e: "update", data: Record): void }>(); -const moduleTypeOptions = Object.entries(MODULE_TYPE_LABELS).map(([v, l]) => ({ value: v, label: l })); -const iconList = ["Folder","FileText","Database","Settings","Users","Globe","Home","Layout","Package","Shield","BarChart","PieChart","List","Grid","Calendar","Clock","Map","Mail","MessageSquare","Search","Code","Terminal","Book","Zap","Star","Heart","Award","Trophy","Briefcase","ShoppingCart"]; +const moduleTypeOptions = Object.entries(MODULE_TYPE_LABELS).map(([v, l]) => ({ + value: v, + label: l, +})); +const iconList = [ + "Folder", + "FileText", + "Database", + "Settings", + "Users", + "Globe", + "Home", + "Layout", + "Package", + "Shield", + "BarChart", + "PieChart", + "List", + "Grid", + "Calendar", + "Clock", + "Map", + "Mail", + "MessageSquare", + "Search", + "Code", + "Terminal", + "Book", + "Zap", + "Star", + "Heart", + "Award", + "Trophy", + "Briefcase", + "ShoppingCart", +]; const i18nModalOpen = ref(false); -function openI18nModal() { i18nModalOpen.value = true; } +function openI18nModal() { + i18nModalOpen.value = true; +} function updateField(key: string, value: unknown) { if (!props.data) return; const u: Record = { ...props.data, [key]: value }; @@ -23,37 +70,140 @@ function updateField(key: string, value: unknown) { emit("update", u); } - + diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleCard.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleCard.vue index 94470079..c4a756b3 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleCard.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleCard.vue @@ -46,10 +46,7 @@ function toggle() {
-
+
diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleEditConfigPanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleEditConfigPanel.vue index 9b75d626..3bc1204c 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleEditConfigPanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleEditConfigPanel.vue @@ -1,67 +1,230 @@ - + diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue index fbe67030..9d450122 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleFieldsPanel.vue @@ -1,19 +1,61 @@ - + diff --git a/code/fms/fms-vue/src/views/system/module-management/components/ModuleI18nPanel.vue b/code/fms/fms-vue/src/views/system/module-management/components/ModuleI18nPanel.vue index b47423b9..4e4b3472 100644 --- a/code/fms/fms-vue/src/views/system/module-management/components/ModuleI18nPanel.vue +++ b/code/fms/fms-vue/src/views/system/module-management/components/ModuleI18nPanel.vue @@ -3,6 +3,13 @@ import { ref, watch, computed, h } from "vue"; import { Plus, Trash2, Search } from "@lucide/vue"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import FmsTable from "@/components/fms-table/FmsTable.vue"; import { loadDataApi } from "@/services/api"; import { cloneData } from "@/utils/dataChanges"; @@ -13,13 +20,31 @@ const locales = ref([]); const dirty = ref(false); const savedSnapshot = ref([]); const pivotRows = ref([]); + +const searchFields = [ + { value: "b_key", label: "翻译键" }, + { value: "_type", label: "类型" }, + { value: "_value", label: "翻译内容" }, +]; +const searchField = ref(searchFields[0].value); const search = ref(""); const selectedRowKeys = ref([]); const filteredRows = computed(() => { const kw = search.value.trim().toLowerCase(); if (!kw) return pivotRows.value; - return pivotRows.value.filter((r) => String(r.b_key).toLowerCase().includes(kw)); + return pivotRows.value.filter((r) => { + if (searchField.value === "b_key") return String(r.b_key).toLowerCase().includes(kw); + if (searchField.value === "_type") { + const t = isCtrl(r) ? "系统" : "自定义"; + return t.includes(kw); + } + return Object.values(r).some((v) => + String(v ?? "") + .toLowerCase() + .includes(kw), + ); + }); }); function isCtrl(row: I18nRow) { @@ -138,11 +163,13 @@ async function buildSaveRequest() { const k = `${fl.b_key}:${fl.b_locale}`; const ex = exMap.get(k); if (!ex) inserts.push(fl); - else if (String(ex.b_value) !== String(fl.b_value)) updates.push({ ...ex, b_value: fl.b_value }); + else if (String(ex.b_value) !== String(fl.b_value)) + updates.push({ ...ex, b_value: fl.b_value }); } const curKL = new Set(flat.map((r) => `${r.b_key}:${r.b_locale}`)); for (const ex of existing) { - if (!curKL.has(`${ex.b_key}:${ex.b_locale}`)) deletes.push({ b_key: ex.b_key, b_locale: ex.b_locale }); + if (!curKL.has(`${ex.b_key}:${ex.b_locale}`)) + deletes.push({ b_key: ex.b_key, b_locale: ex.b_locale }); } if (!inserts.length && !updates.length && !deletes.length) return null; const req: Record = { table: "b_i18n", key_field: "b_key" }; @@ -156,9 +183,16 @@ function markSaved() { savedSnapshot.value = cloneData(pivotRows.value); dirty.value = false; } -function mergeDefaults(entries: { key: string; locale: string; value: unknown; managedId?: string }[]) { +function mergeDefaults( + entries: { key: string; locale: string; value: unknown; managedId?: string }[], +) { const byKey = new Map(pivotRows.value.map((r) => [String(r.b_key), r])); - const existM = new Set(pivotRows.value.map((r) => r._managedId).filter(Boolean).map(String)); + const existM = new Set( + pivotRows.value + .map((r) => r._managedId) + .filter(Boolean) + .map(String), + ); for (const e of entries) { if (!e.key) continue; const ex = byKey.get(e.key); @@ -200,10 +234,21 @@ function removeByManagedIds(managedIds: Set) { pivotRows.value = pivotRows.value.filter((r) => !r._managedId || !managedIds.has(r._managedId)); dirty.value = true; } -defineExpose({ reconcileManagedRows, buildSaveRequest, markSaved, mergeDefaults, refreshKey, removeByManagedIds }); +defineExpose({ + reconcileManagedRows, + buildSaveRequest, + markSaved, + mergeDefaults, + refreshKey, + removeByManagedIds, +}); function addNewRow() { - pivotRows.value.push({ _id: "i18n_" + Math.random().toString(36).slice(2, 10), b_key: "", _localeIds: {} }); + pivotRows.value.push({ + _id: "i18n_" + Math.random().toString(36).slice(2, 10), + b_key: "", + _localeIds: {}, + }); dirty.value = true; } function delSel() { @@ -215,7 +260,11 @@ function delSel() { async function loadLocales() { try { - const r = await loadDataApi("b_i18n_type", "b_canuse = 1", "b_default DESC, b_xh ASC, b_id ASC"); + const r = await loadDataApi( + "b_i18n_type", + "b_canuse = 1", + "b_default DESC, b_xh ASC, b_id ASC", + ); locales.value = ((r.data || []) as { b_code: string }[]).map((l) => l.b_code); } catch { locales.value = []; @@ -234,29 +283,35 @@ export default { name: "ModuleI18nPanel" };