24
24
</h3 >
25
25
</DefineLabel >
26
26
27
- <!-- TODO 小屏幕的时候是定位在左边的,大屏是分开的 -->
27
+ <!-- TODO @hhhero 小屏幕的时候是定位在左边的,大屏是分开的 -->
28
28
<div class =" relative" v-bind =" $attrs" >
29
29
<!-- tab -->
30
30
<div
31
31
class =" absolute left-1/2 top-2 -translate-x-1/2 w-[303px] rounded-full bg-[#DDDFE3] p-1 z-10"
32
32
>
33
33
<div
34
34
class =" flex items-center relative after:content-[''] after:block after:bg-white after:h-[30px] after:w-1/2 after:absolute after:top-0 after:left-0 after:transition-transform after:rounded-full"
35
- :class =" selectedTab === 2 && 'after:transform after:translate-x-[100%]'"
35
+ :class =" selectedTab === AiWriteTypeEnum.REPLY && 'after:transform after:translate-x-[100%]'"
36
36
>
37
37
<ReuseTab
38
38
v-for =" tab in tabs"
53
53
type =" textarea"
54
54
:rows =" 5"
55
55
:maxlength =" 500"
56
- v-model =" writeForm .prompt"
56
+ v-model =" formData .prompt"
57
57
placeholder =" 请输入写作内容"
58
58
showWordLimit
59
59
/>
65
65
type =" textarea"
66
66
:rows =" 5"
67
67
:maxlength =" 500"
68
- v-model =" writeForm .originalContent"
68
+ v-model =" formData .originalContent"
69
69
placeholder =" 请输入原文"
70
70
showWordLimit
71
71
/>
75
75
type =" textarea"
76
76
:rows =" 5"
77
77
:maxlength =" 500"
78
- v-model =" writeForm .prompt"
78
+ v-model =" formData .prompt"
79
79
placeholder =" 请输入回复内容"
80
80
showWordLimit
81
81
/>
82
82
</template >
83
83
84
84
<ReuseLabel label =" 长度" />
85
- <Tag v-model =" writeForm .length" :tags =" writeTags.lenTags " />
85
+ <Tag v-model =" formData .length" :tags =" getIntDictOptions('ai_write_length') " />
86
86
<ReuseLabel label =" 格式" />
87
- <Tag v-model =" writeForm .format" :tags =" writeTags.formatTags " />
87
+ <Tag v-model =" formData .format" :tags =" getIntDictOptions('ai_write_format') " />
88
88
<ReuseLabel label =" 语气" />
89
- <Tag v-model =" writeForm .tone" :tags =" writeTags.toneTags " />
89
+ <Tag v-model =" formData .tone" :tags =" getIntDictOptions('ai_write_tone') " />
90
90
<ReuseLabel label =" 语言" />
91
- <Tag v-model =" writeForm .language" :tags =" writeTags.langTags " />
91
+ <Tag v-model =" formData .language" :tags =" getIntDictOptions('ai_write_language') " />
92
92
93
93
<div class =" flex items-center justify-center mt-3" >
94
94
<el-button :disabled =" isWriting" >重置</el-button >
103
103
import { createReusableTemplate } from ' @vueuse/core'
104
104
import { ref } from ' vue'
105
105
import Tag from ' ./Tag.vue'
106
- import { WriteParams } from ' @/api/ai/writer'
106
+ import { WriteVO } from ' @/api/ai/writer'
107
107
import { omit } from ' lodash-es'
108
108
import { getIntDictOptions } from ' @/utils/dict'
109
- import dataJson from ' ../data.json'
109
+ import { WriteExampleDataJson } from ' @/views/ai/utils/utils'
110
+ import { AiWriteTypeEnum } from " @/views/ai/utils/constants" ;
110
111
111
- type TabType = WriteParams [' type' ]
112
+ type TabType = WriteVO [' type' ]
112
113
113
114
const message = useMessage ()
114
115
@@ -117,33 +118,47 @@ defineProps<{
117
118
}>()
118
119
119
120
const emits = defineEmits <{
120
- (e : ' submit' , params : Partial <WriteParams >)
121
+ (e : ' submit' , params : Partial <WriteVO >)
121
122
(e : ' example' , param : ' write' | ' reply' )
122
123
}>()
123
124
124
125
const example = (type : ' write' | ' reply' ) => {
125
- writeForm .value = {
126
+ formData .value = {
126
127
... initData ,
127
- ... omit (dataJson [type ], [' data' ])
128
+ ... omit (WriteExampleDataJson [type ], [' data' ])
128
129
}
129
130
emits (' example' , type )
130
131
}
131
132
132
- const selectedTab = ref <TabType >(1 )
133
+ const selectedTab = ref <TabType >(AiWriteTypeEnum . WRITING )
133
134
const tabs: {
134
135
text: string
135
136
value: TabType
136
137
}[] = [
137
- { text: ' 撰写' , value: 1 }, // TODO @hhhero:1、2 这个枚举到 constants 里。方便后续万一要调整
138
- { text: ' 回复' , value: 2 }
138
+ { text: ' 撰写' , value: AiWriteTypeEnum . WRITING },
139
+ { text: ' 回复' , value: AiWriteTypeEnum . REPLY }
139
140
]
140
141
const [DefineTab, ReuseTab] = createReusableTemplate <{
141
142
active? : boolean
142
143
text: string
143
144
itemClick: () => void
144
145
}>()
145
146
146
- const initData: WriteParams = {
147
+ /**
148
+ * 可以在template里边定义可复用的组件,DefineLabel,ReuseLabel是采用的解构赋值,都是Vue组件
149
+ * 直接通过组件的形式使用,<DefineLabel v-slot="{ label, hint, hintClick }">中间是需要复用的组件代码</DefineLabel>,通过<ReuseLabel />来使用定义的组件
150
+ * DefineLabel里边的v-slot="{ label, hint, hintClick }“相当于是解构了组件的prop,需要注意的是boolean类型,需要显式的赋值比如 <ReuseLabel :flag="true" />
151
+ * 事件也得以prop形式传入,不能是@event 的形式,比如下面的hintClick需要<ReuseLabel :hintClick="() => { doSomething }"/>
152
+ * @see https://vueuse.org/createReusableTemplate
153
+ */
154
+ const [DefineLabel, ReuseLabel] = createReusableTemplate <{
155
+ label: string
156
+ class? : string
157
+ hint? : string
158
+ hintClick? : () => void
159
+ }>()
160
+
161
+ const initData: WriteVO = {
147
162
type: 1 ,
148
163
prompt: ' ' ,
149
164
originalContent: ' ' ,
@@ -152,49 +167,26 @@ const initData: WriteParams = {
152
167
length: 1 ,
153
168
format: 1
154
169
}
155
- // TODO @hhhero:这个字段,要不叫 formData,和其他模块保持一致。然后 initData 和它也更好对应上
156
- const writeForm = ref <WriteParams >({ ... initData })
157
-
158
- // TODO @hhhero:这种一次性的变量,要不直接 vue template 直接调用。目的是:让 ts 这块,更专注逻辑哈。
159
- const writeTags = {
160
- // 长度 TODO @hhhero:注释放在和面哈;
161
- // TODO @hhhero:一般 length 不用缩写哈。更完整会更容易阅读;
162
- lenTags: getIntDictOptions (' ai_write_length' ),
163
- // 格式
164
-
165
- formatTags: getIntDictOptions (' ai_write_format' ),
166
- // 语气
167
-
168
- toneTags: getIntDictOptions (' ai_write_tone' ),
169
- // 语言
170
- langTags: getIntDictOptions (' ai_write_language' )
171
- //
172
- }
173
-
174
- // TODO @hhhero:这个写法不错。要不写个简单的注释,我怕很多人不懂哈。
175
- const [DefineLabel, ReuseLabel] = createReusableTemplate <{
176
- label: string
177
- class? : string
178
- hint? : string
179
- hintClick? : () => void
180
- }>()
181
-
170
+ const formData = ref <WriteVO >({ ... initData })
171
+ /** 切换tab **/
182
172
const switchTab = (value : TabType ) => {
183
173
selectedTab .value = value
184
- writeForm .value = { ... initData }
174
+ formData .value = { ... initData }
185
175
}
186
176
187
177
const submit = () => {
188
- if (selectedTab .value === 2 && ! writeForm .value .originalContent ) {
178
+ if (selectedTab .value === 2 && ! formData .value .originalContent ) {
189
179
message .warning (' 请输入原文' )
190
180
return
191
181
}
192
- if (! writeForm .value .prompt ) {
182
+ if (! formData .value .prompt ) {
193
183
message .warning (` 请输入${selectedTab .value === 1 ? ' 写作' : ' 回复' }内容 ` )
194
184
return
195
185
}
196
186
emits (' submit' , {
197
- ... (selectedTab .value === 1 ? omit (writeForm .value , [' originalContent' ]) : writeForm .value ),
187
+ /** 撰写的时候没有 originalContent 字段**/
188
+ ... (selectedTab .value === 1 ? omit (formData .value , [' originalContent' ]) : formData .value ),
189
+ /** 使用选中tab值覆盖当前的type类型 **/
198
190
type: selectedTab .value
199
191
})
200
192
}
0 commit comments