@@ -15,6 +15,7 @@ import {
1515 userCreationCmd ,
1616 udevReloadCmd ,
1717 uinputModprobeCmd ,
18+ type StepBlock ,
1819} from ' @/data/installer' ;
1920
2021const selectedDistro = ref (distros [0 ]?.name || ' ' );
@@ -36,23 +37,97 @@ const needsUinputModprobe = computed(() => {
3637 return selectedMethod .value === ' Source' ;
3738});
3839
39- const activateServerCode = computed (() => {
40- if (selectedDistro .value === ' NixOS' )
41- return ' # Bước này đã được cấu hình trong flake.nix ở trên.' ;
40+ const nixosServerBlocks: StepBlock [] = [
41+ {
42+ type: ' text' ,
43+ content:
44+ ' Thêm vào configuration.nix để bật server daemon (thay your_username bằng tên user của bạn):' ,
45+ },
46+ {
47+ type: ' code' ,
48+ content:
49+ ' {\n pkgs,\n ...\n }: {\n systemd.packages = [ pkgs.fcitx5-lotus ];\n systemd.services."fcitx5-lotus-server@your_username" = {\n wantedBy = [ "multi-user.target" ];\n overrideStrategy = "asDropin";\n };\n }' ,
50+ },
51+ ];
52+
53+ const nixosEnvBlocks: StepBlock [] = [
54+ {
55+ type: ' text' ,
56+ content:
57+ ' Nếu cài qua i18n.inputMethod (Cách 1), NixOS tự set các biến này.\n Nếu cần khai báo thủ công, thêm vào configuration.nix:' ,
58+ },
59+ {
60+ type: ' code' ,
61+ content:
62+ ' environment.sessionVariables = {\n GTK_IM_MODULE = "fcitx";\n QT_IM_MODULE = "fcitx";\n XMODIFIERS = "@im=fcitx";\n SDL_IM_MODULE = "fcitx";\n GLFW_IM_MODULE = "ibus";\n };' ,
63+ },
64+ ];
65+
66+ const toBlocks = (value : string | StepBlock []): StepBlock [] => {
67+ if (Array .isArray (value )) return value ;
68+ return [{ type: ' code' , content: value }];
69+ };
70+
71+ const installStepBlocks = computed <StepBlock []>(() => {
72+ const distroInfo =
73+ logic .steps .install [
74+ selectedDistro .value as keyof typeof logic .steps .install
75+ ];
76+ if (! distroInfo ) return [{ type: ' text' , content: ' Cấu hình chưa sẵn sàng.' }];
77+ const methodData = (distroInfo as any )[selectedMethod .value ];
78+ if (! methodData ) {
79+ return [{ type: ' text' , content: ' Phương thức chưa sẵn sàng.' }];
80+ }
81+ if (Array .isArray (methodData )) {
82+ return toBlocks (methodData );
83+ }
84+ if (methodData && typeof methodData === ' object' ) {
85+ return toBlocks (
86+ methodData [selectedShell .value ] ||
87+ methodData .Bash ||
88+ ' Cấu hình chưa sẵn sàng.' ,
89+ );
90+ }
91+ return toBlocks (methodData );
92+ });
93+
94+ const activateServerBlocks = computed <StepBlock []>(() => {
95+ if (selectedDistro .value === ' NixOS' ) {
96+ if (selectedMethod .value === ' Package Manager' ) return nixosServerBlocks ;
97+ return [
98+ {
99+ type: ' text' ,
100+ content: ' Bước này đã được cấu hình trong flake.nix ở trên.' ,
101+ },
102+ ];
103+ }
42104 if (
43105 isAutoHandled .value &&
44106 selectedInit .value !== ' OpenRC' &&
45107 selectedInit .value !== ' runit'
46108 ) {
47- return ' # Gói .deb sẽ tự động thực hiện bước này.\n ' + serverCmd .value ;
109+ return [
110+ {
111+ type: ' text' ,
112+ content: ' Gói .deb sẽ tự động thực hiện bước này. Có thể chạy thủ công:' ,
113+ },
114+ { type: ' code' , content: serverCmd .value },
115+ ];
48116 }
49- return serverCmd .value ;
117+ return toBlocks ( serverCmd .value ) ;
50118});
51119
52- const shellConfigCode = computed (() => {
53- if (selectedDistro .value === ' NixOS' )
54- return ' # Bước này đã được cấu hình trong flake.nix ở trên.' ;
55- return envCmd .value ;
120+ const shellConfigBlocks = computed <StepBlock []>(() => {
121+ if (selectedDistro .value === ' NixOS' ) {
122+ if (selectedMethod .value === ' Package Manager' ) return nixosEnvBlocks ;
123+ return [
124+ {
125+ type: ' text' ,
126+ content: ' Bước này đã được cấu hình trong flake.nix ở trên.' ,
127+ },
128+ ];
129+ }
130+ return toBlocks (envCmd .value );
56131});
57132
58133const serverCmd = computed (() => {
@@ -129,20 +204,6 @@ const copyToClipboard = async (text: string) => {
129204 }
130205};
131206
132- const installStepCode = computed (() => {
133- const distroInfo =
134- logic .steps .install [
135- selectedDistro .value as keyof typeof logic .steps .install
136- ];
137- if (! distroInfo ) return ' Cấu hình chưa sẵn sàng.' ;
138- const methodData = (distroInfo as any )[selectedMethod .value ];
139- if (! methodData ) return ' Phương thức chưa sẵn sàng.' ;
140- if (typeof methodData === ' object' && methodData !== null ) {
141- return methodData [selectedShell .value ] || methodData .Bash || ' Cấu hình chưa sẵn sàng.' ;
142- }
143- return methodData ;
144- });
145-
146207const autostartText = computed (
147208 () =>
148209 logic .steps .autostart [
@@ -268,14 +329,21 @@ const chromiumWaylandFlags = computed(() =>
268329 <div class =" step-badge" >1</div >
269330 <div class =" step-content" >
270331 <h4 >Cài đặt gói</h4 >
271- <div class =" code-container" >
272- <pre ><code >{{ installStepCode }}</code ></pre >
273- <el-button
274- class =" copy-float"
275- circle
276- :icon =" DocumentCopy"
277- @click =" copyToClipboard(installStepCode)"
278- />
332+ <div class =" step-blocks" >
333+ <template v-for =" (block , idx ) in installStepBlocks " :key =" idx " >
334+ <p v-if =" block.type === 'text'" class =" instruction" >
335+ {{ block.content }}
336+ </p >
337+ <div v-else class =" code-container" >
338+ <pre ><code >{{ block.content }}</code ></pre >
339+ <el-button
340+ class =" copy-float"
341+ circle
342+ :icon =" DocumentCopy"
343+ @click =" copyToClipboard(block.content)"
344+ />
345+ </div >
346+ </template >
279347 </div >
280348 </div >
281349 </div >
@@ -338,14 +406,21 @@ const chromiumWaylandFlags = computed(() =>
338406 :closable =" false"
339407 />
340408 </div >
341- <div class =" code-container" >
342- <pre ><code >{{ activateServerCode }}</code ></pre >
343- <el-button
344- class =" copy-float"
345- circle
346- :icon =" DocumentCopy"
347- @click =" copyToClipboard(activateServerCode)"
348- />
409+ <div class =" step-blocks" >
410+ <template v-for =" (block , idx ) in activateServerBlocks " :key =" idx " >
411+ <p v-if =" block.type === 'text'" class =" instruction" >
412+ {{ block.content }}
413+ </p >
414+ <div v-else class =" code-container" >
415+ <pre ><code >{{ block.content }}</code ></pre >
416+ <el-button
417+ class =" copy-float"
418+ circle
419+ :icon =" DocumentCopy"
420+ @click =" copyToClipboard(block.content)"
421+ />
422+ </div >
423+ </template >
349424 </div >
350425 </div >
351426 </div >
@@ -406,14 +481,21 @@ const chromiumWaylandFlags = computed(() =>
406481 <div class =" step-badge" >4</div >
407482 <div class =" step-content" >
408483 <h4 >Thiết lập biến môi trường (Shell)</h4 >
409- <div class =" code-container" >
410- <pre ><code >{{ shellConfigCode }}</code ></pre >
411- <el-button
412- class =" copy-float"
413- circle
414- :icon =" DocumentCopy"
415- @click =" copyToClipboard(shellConfigCode)"
416- />
484+ <div class =" step-blocks" >
485+ <template v-for =" (block , idx ) in shellConfigBlocks " :key =" idx " >
486+ <p v-if =" block.type === 'text'" class =" instruction" >
487+ {{ block.content }}
488+ </p >
489+ <div v-else class =" code-container" >
490+ <pre ><code >{{ block.content }}</code ></pre >
491+ <el-button
492+ class =" copy-float"
493+ circle
494+ :icon =" DocumentCopy"
495+ @click =" copyToClipboard(block.content)"
496+ />
497+ </div >
498+ </template >
417499 </div >
418500 <el-alert
419501 title =" Lưu ý: Bạn cần Đăng xuất và Đăng nhập lại sau bước này để cấu hình Shell có hiệu lực."
@@ -778,6 +860,22 @@ const chromiumWaylandFlags = computed(() =>
778860 overflow-x : auto ;
779861}
780862
863+ .step-blocks {
864+ display : flex ;
865+ flex-direction : column ;
866+ gap : 0.75rem ;
867+ width : 100% ;
868+ }
869+
870+ .step-blocks .code-container {
871+ margin-bottom : 0 ;
872+ }
873+
874+ .step-blocks .instruction {
875+ margin : 0 ;
876+ line-height : 1.6 ;
877+ }
878+
781879.code-container.mini {
782880 padding : 0.75rem 1rem ;
783881 margin-top : 0.5rem ;
0 commit comments