Skip to content

Commit e47f792

Browse files
author
Taois
committed
feat: 支持单行输入框的完整动作
1 parent de8124a commit e47f792

File tree

17 files changed

+1083
-208
lines changed

17 files changed

+1083
-208
lines changed

dashboard/src/App.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
<!-- 使用 slot 渲染页面内容 -->
44
<router-view />
55
</Layout>
6+
<!-- 全局Toast组件 -->
7+
<GlobalToast />
68
</template>
79

810
<script>
911
import { onMounted } from 'vue';
1012
import Layout from './components/Layout.vue';
13+
import GlobalToast from './components/GlobalToast.vue';
1114
import { useVisitedStore } from './stores/visitedStore';
1215
1316
export default {
1417
name: 'App',
1518
components: {
1619
Layout,
20+
GlobalToast,
1721
},
1822
setup() {
1923
const visitedStore = useVisitedStore();

dashboard/src/api/services/video.js

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33
* 封装视频播放、详情、搜索等功能
44
*/
55

6-
import {
7-
getHomeData,
8-
getCategoryData,
9-
getVideoDetail,
10-
getPlayData,
6+
import {
7+
getHomeData,
8+
getCategoryData,
9+
getVideoDetail,
10+
getPlayData,
1111
searchVideos,
12-
refreshModule
12+
refreshModule,
13+
executeAction
1314
} from '../modules/module'
1415
import { parseVideo } from '../modules/parse'
1516
import { encodeFilters, validateModule, validateVideoId } from '../utils'
16-
import {
17-
createVideoInfo,
18-
createSearchParams,
17+
import {
18+
createVideoInfo,
19+
createSearchParams,
1920
createPaginationInfo,
2021
VIDEO_TYPES,
21-
SORT_TYPES
22+
SORT_TYPES
2223
} from '../types'
2324

2425
/**
@@ -55,7 +56,7 @@ class VideoService {
5556
requestOptions.apiUrl = apiUrl
5657
}
5758
const response = await getHomeData(module, requestOptions)
58-
59+
5960
// 格式化返回数据
6061
const result = {
6162
categories: response.class || [],
@@ -87,7 +88,7 @@ class VideoService {
8788
}
8889

8990
const { typeId, page = 1, filters = {}, apiUrl, extend } = params
90-
91+
9192
if (!typeId) {
9293
throw new Error('分类ID不能为空')
9394
}
@@ -120,7 +121,7 @@ class VideoService {
120121
}
121122

122123
const response = await getCategoryData(module, requestParams)
123-
124+
124125
// 格式化返回数据
125126
const result = {
126127
videos: (response.list || []).map(this.formatVideoInfo),
@@ -156,7 +157,7 @@ class VideoService {
156157
}
157158

158159
const cacheKey = `detail_${module}_${videoId}`
159-
160+
160161
// 如果不跳过缓存,则检查缓存
161162
if (!skipCache) {
162163
const cached = this.getFromCache(cacheKey)
@@ -177,13 +178,13 @@ class VideoService {
177178
params.extend = extend
178179
}
179180
const response = await getVideoDetail(module, params)
180-
181+
181182
if (!response.list || response.list.length === 0) {
182183
throw new Error('视频不存在')
183184
}
184185

185186
const videoInfo = this.formatVideoInfo(response.list[0])
186-
187+
187188
// 解析播放地址
188189
if (videoInfo.vod_play_url) {
189190
videoInfo.playList = this.parsePlayUrls(videoInfo.vod_play_url, videoInfo.vod_play_from)
@@ -213,7 +214,7 @@ class VideoService {
213214
}
214215

215216
const { keyword, page = 1, extend, apiUrl } = params
216-
217+
217218
if (!keyword || keyword.trim().length === 0) {
218219
throw new Error('搜索关键词不能为空')
219220
}
@@ -223,19 +224,19 @@ class VideoService {
223224
wd: keyword.trim(),
224225
pg: page
225226
}
226-
227+
227228
// 添加extend参数
228229
if (extend) {
229230
requestParams.extend = extend
230231
}
231-
232+
232233
// 添加apiUrl参数
233234
if (apiUrl) {
234235
requestParams.apiUrl = apiUrl
235236
}
236-
237+
237238
const response = await searchVideos(module, requestParams)
238-
239+
239240
// 格式化返回数据
240241
const result = {
241242
videos: (response.list || []).map(this.formatVideoInfo),
@@ -278,7 +279,7 @@ class VideoService {
278279
params.extend = extend
279280
}
280281
const response = await getPlayData(module, params)
281-
282+
282283
return {
283284
url: response.url || playUrl,
284285
headers: response.headers || {},
@@ -309,7 +310,7 @@ class VideoService {
309310

310311
try {
311312
const response = await parseVideo(jx, { url, ...options })
312-
313+
313314
return {
314315
url: response.url || url,
315316
type: response.type || 'mp4',
@@ -322,6 +323,44 @@ class VideoService {
322323
}
323324
}
324325

326+
/**
327+
* 执行T4 Action动作
328+
* @param {string} module - 模块名称
329+
* @param {string} actionName - 动作名称
330+
* @param {object} options - 选项参数
331+
* @param {string} options.apiUrl - API地址
332+
* @param {string} options.extend - 扩展参数
333+
* @returns {Promise} Action执行结果
334+
*/
335+
async executeT4Action(module, actionName, options = {}) {
336+
if (!validateModule(module)) {
337+
throw new Error('无效的模块名称')
338+
}
339+
340+
if (!actionName || actionName.trim().length === 0) {
341+
throw new Error('动作名称不能为空')
342+
}
343+
344+
try {
345+
const actionData = {
346+
action: actionName.trim(),
347+
value: options.value || '',
348+
extend: options.extend,
349+
apiUrl: options.apiUrl
350+
}
351+
352+
console.log('执行T4 action:', { module, actionData })
353+
354+
const result = await executeAction(module, actionData)
355+
console.log('T4 action执行结果:', result)
356+
357+
return result
358+
} catch (error) {
359+
console.error('T4 action执行失败:', error)
360+
throw error
361+
}
362+
}
363+
325364
/**
326365
* 刷新模块数据
327366
* @param {string} module - 模块名称
@@ -337,9 +376,9 @@ class VideoService {
337376
try {
338377
// 清除相关缓存
339378
this.clearModuleCache(module)
340-
379+
341380
const response = await refreshModule(module, extend, apiUrl)
342-
381+
343382
return {
344383
success: true,
345384
message: response.msg || '刷新成功',
@@ -358,7 +397,7 @@ class VideoService {
358397
*/
359398
formatVideoInfo(rawVideo) {
360399
const video = createVideoInfo()
361-
400+
362401
Object.keys(video).forEach(key => {
363402
if (rawVideo[key] !== undefined) {
364403
video[key] = rawVideo[key]
@@ -422,18 +461,18 @@ class VideoService {
422461
*/
423462
createPagination(response, currentPage = 1) {
424463
const pagination = createPaginationInfo()
425-
464+
426465
pagination.page = currentPage
427-
466+
428467
// 处理不同的API响应格式
429468
const total = response.total || response.recordcount || 0
430469
const pageCount = response.pagecount || response.totalPages || 0
431470
const pageSize = response.limit || response.pagesize || 20
432471
const currentList = response.list || []
433-
472+
434473
pagination.total = total
435474
pagination.pageSize = pageSize
436-
475+
437476
// 如果API返回了总页数,直接使用
438477
if (pageCount > 0) {
439478
pagination.totalPages = pageCount
@@ -445,12 +484,12 @@ class VideoService {
445484
} else {
446485
// 如果没有总数信息,根据当前返回的数据判断
447486
// 检查是否有"no_data"标识
448-
const hasNoDataFlag = currentList.some(item =>
449-
item.vod_id === 'no_data' ||
487+
const hasNoDataFlag = currentList.some(item =>
488+
item.vod_id === 'no_data' ||
450489
item.vod_name === 'no_data' ||
451490
(typeof item === 'string' && item.includes('no_data'))
452491
)
453-
492+
454493
if (hasNoDataFlag || currentList.length === 0) {
455494
// 如果有no_data标识或列表为空,表示没有更多数据
456495
pagination.hasNext = false
@@ -461,7 +500,7 @@ class VideoService {
461500
pagination.totalPages = currentPage + 1
462501
}
463502
}
464-
503+
465504
pagination.hasPrev = currentPage > 1
466505

467506
return pagination
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<template>
2+
<!-- Toast提示 - 直接使用ActionRenderer中验证可用的样式 -->
3+
<Teleport to="body">
4+
<Transition name="action-toast">
5+
<div v-if="toastState.show" class="action-toast" :class="toastState.type">
6+
{{ toastState.message }}
7+
</div>
8+
</Transition>
9+
</Teleport>
10+
</template>
11+
12+
<script setup>
13+
import { toastState } from '@/stores/toast'
14+
</script>
15+
16+
<style scoped>
17+
/* Toast样式 - 直接复制ActionRenderer中的样式 */
18+
.action-toast {
19+
position: fixed !important;
20+
top: 20px !important;
21+
left: 50% !important;
22+
transform: translateX(-50%) !important;
23+
padding: 12px 24px;
24+
border-radius: 6px;
25+
color: white;
26+
font-size: 14px;
27+
z-index: 99999 !important;
28+
max-width: 400px;
29+
text-align: center;
30+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
31+
pointer-events: none;
32+
}
33+
34+
.action-toast.success {
35+
background: #52c41a;
36+
}
37+
38+
.action-toast.error {
39+
background: #f5222d;
40+
}
41+
42+
.action-toast.warning {
43+
background: #faad14;
44+
}
45+
46+
.action-toast.info {
47+
background: #1890ff;
48+
}
49+
50+
/* Toast动画 */
51+
.action-toast-enter-active,
52+
.action-toast-leave-active {
53+
transition: all 0.3s ease;
54+
}
55+
56+
.action-toast-enter-from {
57+
opacity: 0;
58+
transform: translateX(-50%) translateY(-20px);
59+
}
60+
61+
.action-toast-leave-to {
62+
opacity: 0;
63+
transform: translateX(-50%) translateY(-20px);
64+
}
65+
</style>

dashboard/src/components/SearchResults.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
:extend="props.extend"
104104
:api-url="props.apiUrl"
105105
@close="handleActionClose"
106-
@submit="handleActionSubmit"
106+
107107
@special-action="handleSpecialAction"
108108
/>
109109
</div>

0 commit comments

Comments
 (0)