Skip to content

Commit 1f22e0b

Browse files
committed
[新增]AI: 写作管理
1 parent d266b99 commit 1f22e0b

File tree

5 files changed

+279
-29
lines changed

5 files changed

+279
-29
lines changed

src/api/ai/writer/index.ts

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fetchEventSource } from '@microsoft/fetch-event-source'
33
import { getAccessToken } from '@/utils/auth'
44
import { config } from '@/config/axios/config'
55
import { AiWriteTypeEnum } from '@/views/ai/utils/constants'
6+
import request from '@/config/axios'
67

78
export interface WriteVO {
89
type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复
@@ -14,32 +15,67 @@ export interface WriteVO {
1415
language: number // 语言
1516
}
1617

17-
// TODO @hhero:搞成 WriteApi,类似 ConversationApi 一样。这样更有类的概念,后续引入某个 Api,然后调用它的方法就可以了。
18-
export const writeStream = ({
19-
data,
20-
onClose,
21-
onMessage,
22-
onError,
23-
ctrl
24-
}: {
25-
data: WriteVO
26-
onMessage?: (res: any) => void
27-
onError?: (...args: any[]) => void
28-
onClose?: (...args: any[]) => void
29-
ctrl: AbortController
30-
}) => {
31-
const token = getAccessToken()
32-
return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, {
33-
method: 'post',
34-
headers: {
35-
'Content-Type': 'application/json',
36-
Authorization: `Bearer ${token}`
37-
},
38-
openWhenHidden: true,
39-
body: JSON.stringify(data),
40-
onmessage: onMessage,
41-
onerror: onError,
42-
onclose: onClose,
43-
signal: ctrl.signal
44-
})
18+
export interface AiWritePageReqVO extends PageParam {
19+
userId?: number // 用户编号
20+
type?: AiWriteTypeEnum // 写作类型
21+
platform?: string // 平台
22+
createTime?: [string, string] // 创建时间
4523
}
24+
25+
export interface AiWriteRespVo {
26+
id: number
27+
userId: number
28+
type: number
29+
platform: string
30+
model: string
31+
prompt: string
32+
generatedContent: string
33+
originalContent: string
34+
length: number
35+
format: number
36+
tone: number
37+
language: number
38+
errorMessage: string
39+
createTime: string
40+
}
41+
42+
const WriteApi = {
43+
writeStream: ({
44+
data,
45+
onClose,
46+
onMessage,
47+
onError,
48+
ctrl
49+
}: {
50+
data: WriteVO
51+
onMessage?: (res: any) => void
52+
onError?: (...args: any[]) => void
53+
onClose?: (...args: any[]) => void
54+
ctrl: AbortController
55+
}) => {
56+
const token = getAccessToken()
57+
return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, {
58+
method: 'post',
59+
headers: {
60+
'Content-Type': 'application/json',
61+
Authorization: `Bearer ${token}`
62+
},
63+
openWhenHidden: true,
64+
body: JSON.stringify(data),
65+
onmessage: onMessage,
66+
onerror: onError,
67+
onclose: onClose,
68+
signal: ctrl.signal
69+
})
70+
},
71+
// 获取写作列表
72+
getWritePage: (params: AiWritePageReqVO) => {
73+
return request.get<PageResult<AiWriteRespVo[]>>({ url: `/ai/write/page`, params })
74+
},
75+
// 删除写作
76+
deleteWrite(id: number) {
77+
return request.delete({ url: `/ai/write/delete`, params: { id } })
78+
}
79+
}
80+
81+
export default WriteApi

src/views/ai/utils/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ export enum AiWriteTypeEnum {
6161
REPLY // 回复
6262
}
6363

64+
// 表格展示对照map
65+
export const AiWriteTypeTableRender = {
66+
[AiWriteTypeEnum.WRITING]: '撰写',
67+
[AiWriteTypeEnum.REPLY]: '回复',
68+
}
69+
6470
// ========== 【图片 UI】相关的枚举 ==========
6571
export const ImageHotWords = [
6672
'中国旗袍',

src/views/ai/writer/index/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<script setup lang="ts">
2121
import Left from './components/Left.vue'
2222
import Right from './components/Right.vue'
23-
import * as WriteApi from '@/api/ai/writer'
23+
import WriteApi from '@/api/ai/writer'
2424
import { WriteExample } from '@/views/ai/utils/constants'
2525
2626
const message = useMessage()

src/views/ai/writer/manager/index.vue

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<template>
2+
<ContentWrap>
3+
<!-- 搜索工作栏 -->
4+
<el-form
5+
class="-mb-15px"
6+
:model="queryParams"
7+
ref="queryFormRef"
8+
:inline="true"
9+
label-width="68px"
10+
>
11+
<el-form-item label="用户编号" prop="userId">
12+
<el-select
13+
v-model="queryParams.userId"
14+
clearable
15+
placeholder="请输入用户编号"
16+
class="!w-240px"
17+
>
18+
<el-option
19+
v-for="item in userList"
20+
:key="item.id"
21+
:label="item.nickname"
22+
:value="item.id"
23+
/>
24+
</el-select>
25+
</el-form-item>
26+
<el-form-item label="平台" prop="platform">
27+
<el-select
28+
v-model="queryParams.platform"
29+
placeholder="请选择平台"
30+
clearable
31+
class="!w-240px"
32+
>
33+
<el-option
34+
v-for="dict in getStrDictOptions(DICT_TYPE.AI_PLATFORM)"
35+
:key="dict.value"
36+
:label="dict.label"
37+
:value="dict.value"
38+
/>
39+
</el-select>
40+
</el-form-item>
41+
<el-form-item label="是否发布" prop="publicStatus">
42+
<el-select
43+
v-model="queryParams.type"
44+
placeholder="请选择写作方式"
45+
clearable
46+
class="!w-240px"
47+
>
48+
<el-option label="撰写" :value="AiWriteTypeEnum.WRITING" />
49+
<el-option label="回复" :value="AiWriteTypeEnum.REPLY" />
50+
</el-select>
51+
</el-form-item>
52+
<el-form-item label="创建时间" prop="createTime">
53+
<el-date-picker
54+
v-model="queryParams.createTime"
55+
value-format="YYYY-MM-DD HH:mm:ss"
56+
type="daterange"
57+
start-placeholder="开始日期"
58+
end-placeholder="结束日期"
59+
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
60+
class="!w-220px"
61+
/>
62+
</el-form-item>
63+
<el-form-item>
64+
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
65+
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
66+
</el-form-item>
67+
</el-form>
68+
</ContentWrap>
69+
70+
<!-- 列表 -->
71+
<ContentWrap>
72+
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
73+
<el-table-column label="编号" align="center" prop="id" width="180" fixed="left" />
74+
<el-table-column label="用户" align="center" prop="userId" width="180">
75+
<template #default="scope">
76+
<span>{{ userList.find((item) => item.id === scope.row.userId)?.nickname }}</span>
77+
</template>
78+
</el-table-column>
79+
<el-table-column label="写作类型" align="center" prop="platform" width="120">
80+
<template #default="scope">
81+
{{ AiWriteTypeTableRender[scope.row.type] }}
82+
</template>
83+
</el-table-column>
84+
<el-table-column label="平台" align="center" prop="platform" width="120">
85+
<template #default="scope">
86+
<dict-tag :type="DICT_TYPE.AI_PLATFORM" :value="scope.row.platform" />
87+
</template>
88+
</el-table-column>
89+
<el-table-column label="模型" align="center" prop="model" width="180" />
90+
<el-table-column
91+
label="预览内容"
92+
align="center"
93+
prop="generatedContent"
94+
width="200"
95+
show-overflow-tooltip
96+
/>
97+
<el-table-column label="提示词" align="center" prop="prompt" width="180" />
98+
<el-table-column label="原文" align="center" prop="originalContent" width="180" />
99+
<el-table-column label="长度" align="center" prop="length" width="180" />
100+
<el-table-column label="格式" align="center" prop="format" width="180" />
101+
<el-table-column label="语气" align="center" prop="tone" width="180" />
102+
<el-table-column label="语言" align="center" prop="language" width="180" />
103+
<el-table-column
104+
label="创建时间"
105+
align="center"
106+
prop="createTime"
107+
:formatter="dateFormatter"
108+
width="180px"
109+
/>
110+
<el-table-column label="错误信息" align="center" prop="errorMessage" />
111+
<el-table-column label="操作" align="center" width="100" fixed="right">
112+
<template #default="scope">
113+
<el-button
114+
link
115+
type="danger"
116+
@click="handleDelete(scope.row.id)"
117+
v-hasPermi="['ai:write:delete']"
118+
>
119+
删除
120+
</el-button>
121+
</template>
122+
</el-table-column>
123+
</el-table>
124+
<!-- 分页 -->
125+
<Pagination
126+
:total="total"
127+
v-model:page="queryParams.pageNo"
128+
v-model:limit="queryParams.pageSize"
129+
@pagination="getList"
130+
/>
131+
</ContentWrap>
132+
</template>
133+
134+
<script setup lang="ts">
135+
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
136+
import { dateFormatter } from '@/utils/formatTime'
137+
import WriteApi, { AiWritePageReqVO, AiWriteRespVo } from '@/api/ai/writer'
138+
import * as UserApi from '@/api/system/user'
139+
import { AiWriteTypeEnum, AiWriteTypeTableRender } from '@/views/ai/utils/constants'
140+
141+
/** AI 写作 列表 */
142+
defineOptions({ name: 'AiWriteManage' })
143+
144+
const message = useMessage() // 消息弹窗
145+
const { t } = useI18n() // 国际化
146+
147+
const loading = ref(true) // 列表的加载中
148+
const list = ref<AiWriteRespVo[]>([]) // 列表的数据
149+
const total = ref(0) // 列表的总页数
150+
const queryParams = reactive<AiWritePageReqVO>({
151+
pageNo: 1,
152+
pageSize: 10,
153+
userId: undefined,
154+
platform: undefined,
155+
createTime: undefined
156+
})
157+
const queryFormRef = ref() // 搜索的表单
158+
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
159+
160+
/** 查询列表 */
161+
const getList = async () => {
162+
loading.value = true
163+
try {
164+
const data = await WriteApi.getWritePage(queryParams)
165+
list.value = data.list
166+
total.value = data.total
167+
} finally {
168+
loading.value = false
169+
}
170+
}
171+
172+
/** 搜索按钮操作 */
173+
const handleQuery = () => {
174+
queryParams.pageNo = 1
175+
getList()
176+
}
177+
178+
/** 重置按钮操作 */
179+
const resetQuery = () => {
180+
queryFormRef.value.resetFields()
181+
handleQuery()
182+
}
183+
184+
/** 删除按钮操作 */
185+
const handleDelete = async (id: number) => {
186+
try {
187+
// 删除的二次确认
188+
await message.delConfirm()
189+
// 发起删除
190+
await WriteApi.deleteWrite(id)
191+
message.success(t('common.delSuccess'))
192+
// 刷新列表
193+
await getList()
194+
} catch {}
195+
}
196+
197+
/** 初始化 **/
198+
onMounted(async () => {
199+
getList()
200+
// 获得用户列表
201+
userList.value = await UserApi.getSimpleUserList()
202+
})
203+
</script>

types/global.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,9 @@ declare global {
5050
name: string
5151
children?: Tree[] | any[]
5252
}
53+
// 分页数据公共返回
54+
interface PageResult<T> {
55+
list: T // 数据
56+
total: number // 总量
57+
}
5358
}

0 commit comments

Comments
 (0)