完善 web 执行中任务页面
This commit is contained in:
parent
bcd6f63bb3
commit
54ba342153
|
|
@ -13,7 +13,7 @@
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"launchUrl": "/swagger/index.html",
|
"launchUrl": "swagger/index.html",
|
||||||
"applicationUrl": "http://*:5238",
|
"applicationUrl": "http://*:5238",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,4 @@ VITE_CDN = false
|
||||||
VITE_COMPRESSION = "none"
|
VITE_COMPRESSION = "none"
|
||||||
|
|
||||||
|
|
||||||
# 接口地址
|
VITE_API_BASEURL = "https://videoanalysis.w.23544.com:8843/"
|
||||||
VITE_API_BASEURL = "https://learn-archives-admin.23544.com/api"
|
|
||||||
#数据中心后台地址
|
|
||||||
VITE_API_USERCENTER_URL = "https://dcb.23544.com/api"
|
|
||||||
|
|
@ -56,3 +56,12 @@ export const ShowTaskInfo = (id: any) => {
|
||||||
params: { id }
|
params: { id }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** 展示数据 */
|
||||||
|
export const RunningTaskList = (data: any) => {
|
||||||
|
return http.request<any>("post", "/api/VideoTask/RunningTaskList", {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { promises } from "node:dns";
|
||||||
import { Ref } from "vue";
|
import { Ref } from "vue";
|
||||||
import { array } from "vue-types";
|
import { array } from "vue-types";
|
||||||
|
|
||||||
|
|
@ -326,8 +327,11 @@ export class SearchConditions {
|
||||||
|
|
||||||
/** 表格配置 */
|
/** 表格配置 */
|
||||||
export interface TableConfig {
|
export interface TableConfig {
|
||||||
/** 搜索回调函数 */
|
/** 搜索回调函数 [返回值为true则不调用基础PageAPI]*/
|
||||||
searchCallback?: (s: SearchConditions) => void;
|
searchCallback?: (
|
||||||
|
s: SearchConditions,
|
||||||
|
tv: TableConfig
|
||||||
|
) => Promise<boolean> | Promise<void> | boolean | void;
|
||||||
/** 新增/修改回调函数 */
|
/** 新增/修改回调函数 */
|
||||||
editCallback?: (from: any) => void;
|
editCallback?: (from: any) => void;
|
||||||
/** 编辑表单初始化回调函数 */
|
/** 编辑表单初始化回调函数 */
|
||||||
|
|
|
||||||
|
|
@ -103,10 +103,11 @@ const appB_S = ref<HTMLElement>(null);
|
||||||
function appStyle() {
|
function appStyle() {
|
||||||
if (tableHeight.value !== 0) return;
|
if (tableHeight.value !== 0) return;
|
||||||
tableHeight.value =
|
tableHeight.value =
|
||||||
appB.value.parentElement.parentElement.offsetHeight -
|
appB.value.parentElement.parentElement.parentElement.offsetHeight -
|
||||||
145 -
|
145 -
|
||||||
appB_S.value.offsetHeight +
|
appB_S.value.offsetHeight +
|
||||||
0;
|
0;
|
||||||
|
console.log("tableHeight.value", tableHeight.value);
|
||||||
return tableHeight;
|
return tableHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +289,7 @@ function searchReload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 查询
|
// 查询
|
||||||
function handleReloadPaged(reload = true) {
|
async function handleReloadPaged(reload = true) {
|
||||||
if (defaultOrderBy == null) {
|
if (defaultOrderBy == null) {
|
||||||
defaultOrderBy = {
|
defaultOrderBy = {
|
||||||
OrderBy: table.value.search.OrderBy,
|
OrderBy: table.value.search.OrderBy,
|
||||||
|
|
@ -332,12 +333,9 @@ function handleReloadPaged(reload = true) {
|
||||||
if (!reload && table.value.search.Conditions.length > 0) {
|
if (!reload && table.value.search.Conditions.length > 0) {
|
||||||
table.value.search.PageIndex = 0;
|
table.value.search.PageIndex = 0;
|
||||||
}
|
}
|
||||||
if (table.value.searchCallback) {
|
|
||||||
table.value.searchCallback(table.value.search);
|
|
||||||
}
|
|
||||||
//如果有展开行 则全部收回
|
//如果有展开行 则全部收回
|
||||||
if (table.value.expandColumn) expands.value = [];
|
if (table.value.expandColumn) expands.value = [];
|
||||||
fetchPagedData();
|
return fetchPagedData();
|
||||||
}
|
}
|
||||||
// 加载前置数据(如查询条件的下拉选择数据)
|
// 加载前置数据(如查询条件的下拉选择数据)
|
||||||
async function fetchInitData() {
|
async function fetchInitData() {
|
||||||
|
|
@ -360,7 +358,10 @@ function getByteLen(str) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
// 加载分页数据
|
// 加载分页数据
|
||||||
function fetchPagedData() {
|
async function fetchPagedData() {
|
||||||
|
if (table.value.searchCallback) {
|
||||||
|
if (await table.value.searchCallback(table.value.search, table.value)) return;
|
||||||
|
}
|
||||||
for (const iterator of table.value.search.defaultConditions) {
|
for (const iterator of table.value.search.defaultConditions) {
|
||||||
if (!iterator) continue;
|
if (!iterator) continue;
|
||||||
if (!table.value.search.Conditions.find((s) => s == iterator)) {
|
if (!table.value.search.Conditions.find((s) => s == iterator)) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
ComboModel,
|
ComboModel,
|
||||||
ConditionalType,
|
ConditionalType,
|
||||||
intTableData,
|
intTableData,
|
||||||
|
SearchConditions,
|
||||||
TableColumnSearch,
|
TableColumnSearch,
|
||||||
TableConfig,
|
TableConfig,
|
||||||
} from "@/components/hTable/hTable";
|
} from "@/components/hTable/hTable";
|
||||||
|
|
@ -17,6 +18,7 @@ import { ReStart, RowRload } from "@/api/videoTask";
|
||||||
import { Refresh } from "@element-plus/icons-vue";
|
import { Refresh } from "@element-plus/icons-vue";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { json } from "stream/consumers";
|
import { json } from "stream/consumers";
|
||||||
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
|
@ -26,15 +28,20 @@ defineOptions({
|
||||||
name: ControllerName,
|
name: ControllerName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
searchCallback?: (
|
||||||
|
s: SearchConditions,
|
||||||
|
tv: TableConfig
|
||||||
|
) => boolean | Promise<boolean> | void;
|
||||||
|
}>();
|
||||||
const route = useRouter();
|
const route = useRouter();
|
||||||
function searchCallback(data) {}
|
|
||||||
const table = ref<{ initTable: (config: TableConfig) => void }>();
|
const table = ref<{ initTable: (config: TableConfig) => void }>();
|
||||||
const tableData: TableConfig = intTableData({
|
const tableData: TableConfig = intTableData({
|
||||||
apiUrl: ControllerName,
|
apiUrl: ControllerName,
|
||||||
expandColumn: true,
|
expandColumn: true,
|
||||||
selectColumn: false, // 列表选择
|
selectColumn: false, // 列表选择
|
||||||
border: false, // 是否显示表格边框
|
border: false, // 是否显示表格边框
|
||||||
searchCallback: searchCallback,
|
searchCallback: props.searchCallback,
|
||||||
expandChange: expandChange,
|
expandChange: expandChange,
|
||||||
search: {
|
search: {
|
||||||
// 查询条件
|
// 查询条件
|
||||||
|
|
@ -122,6 +129,25 @@ async function submitRowRload() {
|
||||||
async function expandChange(row: any, expandedRows: any[]) {
|
async function expandChange(row: any, expandedRows: any[]) {
|
||||||
if (expandedRows.find((s) => s == row)) RloadTaskInfo(row);
|
if (expandedRows.find((s) => s == row)) RloadTaskInfo(row);
|
||||||
}
|
}
|
||||||
|
function previewTask(row: any) {
|
||||||
|
let pageName = "showTask";
|
||||||
|
let queryData = { id: row.id.toString() };
|
||||||
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
|
path: `/welcome/showTask_` + row.id,
|
||||||
|
name: pageName,
|
||||||
|
query: queryData,
|
||||||
|
meta: {
|
||||||
|
title: `任务预览` + row.id.toString().slice(-4),
|
||||||
|
dynamicLevel: 3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// 路由跳转
|
||||||
|
route.push({ name: pageName, query: queryData });
|
||||||
|
}
|
||||||
|
function firstLetterToLower(str) {
|
||||||
|
if (typeof str !== "string" || !str) return str;
|
||||||
|
return str[0].toLowerCase() + str.slice(1);
|
||||||
|
}
|
||||||
async function RloadTaskInfo(row: any) {
|
async function RloadTaskInfo(row: any) {
|
||||||
let res = await RowRload(row.id);
|
let res = await RowRload(row.id);
|
||||||
row.TaskInfo = res;
|
row.TaskInfo = res;
|
||||||
|
|
@ -132,7 +158,7 @@ async function RloadTaskInfo(row: any) {
|
||||||
if (row.TaskInfo.startTime != null) {
|
if (row.TaskInfo.startTime != null) {
|
||||||
for (const element of row.TaskInfo.stepData) {
|
for (const element of row.TaskInfo.stepData) {
|
||||||
element.time = formatDateToChinese(
|
element.time = formatDateToChinese(
|
||||||
row.TaskInfo.startTime[element.title.toLowerCase()]
|
row.TaskInfo.startTime[firstLetterToLower(element.title)]
|
||||||
);
|
);
|
||||||
let i = row.TaskInfo.stepData.indexOf(element);
|
let i = row.TaskInfo.stepData.indexOf(element);
|
||||||
if (i < row.TaskInfo.active) {
|
if (i < row.TaskInfo.active) {
|
||||||
|
|
@ -184,10 +210,12 @@ const stepData = ref<StepData[]>([
|
||||||
<!-- 拓展内容 -->
|
<!-- 拓展内容 -->
|
||||||
<div class="expanded-content expandSlot">
|
<div class="expanded-content expandSlot">
|
||||||
<h3>任务详情</h3>
|
<h3>任务详情</h3>
|
||||||
<div class="InfoEx">
|
<div class="InfoEx" v-if="props.row.TaskInfo != null">
|
||||||
<div>
|
<div>
|
||||||
<span>进度</span>
|
<span>进度</span>
|
||||||
<div class="content">{{ props.row.lastEnum }} {{ props.row.progress }}</div>
|
<div class="content">
|
||||||
|
{{ props.row.TaskInfo.lastEnum }} {{ props.row.TaskInfo.progress }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>操作</span>
|
<span>操作</span>
|
||||||
|
|
@ -198,19 +226,8 @@ const stepData = ref<StepData[]>([
|
||||||
@click="RloadTaskInfo(props.row)"
|
@click="RloadTaskInfo(props.row)"
|
||||||
circle
|
circle
|
||||||
/>
|
/>
|
||||||
<el-button type="danger" @click="showDialog(props.row.id)"
|
<el-button type="danger" @click="showDialog(props.row)">重试</el-button>
|
||||||
>重试</el-button
|
<el-button type="primary" @click="previewTask(props.row)">预览</el-button>
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
@click="
|
|
||||||
route.push({
|
|
||||||
path: '/welcome/showTask',
|
|
||||||
query: { id: props.row.id.toString() },
|
|
||||||
})
|
|
||||||
"
|
|
||||||
>预览</el-button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,233 +1,41 @@
|
||||||
<template>
|
|
||||||
<div id="video-container">
|
|
||||||
<div v-if="videoKnows.length > 0">
|
|
||||||
<div id="segmentsContainer" class="sc" :class="{ locked: isLocked }">
|
|
||||||
<h2>
|
|
||||||
<button class="gudingBtn" @click="toggleLock">
|
|
||||||
{{ isLocked ? "🔓" : "🔒" }}
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div v-for="(item, index) in videoKnows" :key="index" class="knowDiv">
|
|
||||||
<div class="knowTtile">
|
|
||||||
<div style="cursor: pointer" @click="spClick(index, $event)">
|
|
||||||
<div class="knowTtileTheme">{{ getTimeRange(item) }} {{ item.Theme }}</div>
|
|
||||||
<span class="kSpan">#{{ item.KnowPointId }} {{ item.KnowPoint }}</span>
|
|
||||||
</div>
|
|
||||||
<div>概览: {{ item.Content }}</div>
|
|
||||||
<br />
|
|
||||||
<div v-if="item.QuestionArr && item.QuestionArr.length > 0">
|
|
||||||
<div
|
|
||||||
v-for="(q, qIndex) in item.QuestionArr"
|
|
||||||
:key="qIndex"
|
|
||||||
class="knowQuestion"
|
|
||||||
@click="spClickTime(q.startTime)"
|
|
||||||
>
|
|
||||||
<h3>
|
|
||||||
问题: <span class="kSpan">{{ q.startTime }} 秒</span>
|
|
||||||
</h3>
|
|
||||||
<div class="kSpan">{{ q.topicStem }}</div>
|
|
||||||
<div>{{ q.question }}</div>
|
|
||||||
<img
|
|
||||||
style="text-align: center"
|
|
||||||
:src="q.pPTImageUrl"
|
|
||||||
width="320"
|
|
||||||
height="180"
|
|
||||||
:alt="'问题图片' + qIndex"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<button class="kBtn" @click="spClick(index, $event)">
|
|
||||||
<span>{{ getFirstChar(item.Theme) }} {{ item.Theme }}</span>
|
|
||||||
<br />
|
|
||||||
<span class="kSpan textEllipsis"
|
|
||||||
>#{{ item.KnowPointId }} {{ item.KnowPoint }}</span
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<video ref="videoPlayerEL" controls autoplay>
|
|
||||||
<source :src="videoSrc" type="video/mp4" />
|
|
||||||
</video>
|
|
||||||
<div ref="subtitleAreaEL" class="subtitles">{{ currentSubtitle }}</div>
|
|
||||||
<div ref="subtitleArea1EL" class="subtitles" :style="subtitleStyle">
|
|
||||||
{{ currentSubtitle1 }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SenseVoiceRes, ShowTaskInfo, VideoKnowRes } from "@/api/videoTask";
|
import ahTable from "@/components/hTable/index.vue";
|
||||||
|
import {
|
||||||
|
ComboModel,
|
||||||
|
ConditionalType,
|
||||||
|
intTableData,
|
||||||
|
SearchConditions,
|
||||||
|
TableColumnSearch,
|
||||||
|
TableConfig,
|
||||||
|
} from "@/components/hTable/hTable";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import { getenum } from "@/api/enum";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { ReStart, RowRload, RunningTaskList } from "@/api/videoTask";
|
||||||
|
import { Refresh } from "@element-plus/icons-vue";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { isEmpty } from "@pureadmin/utils";
|
import videoTask from "./index.vue";
|
||||||
import { ref, onMounted, nextTick } from "vue";
|
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "runningTask",
|
name: `runningTask`,
|
||||||
});
|
});
|
||||||
|
async function searchCallback(s: SearchConditions, tv: TableConfig): Promise<boolean> {
|
||||||
const subtitleAreaEL = ref<HTMLElement | null>(null);
|
//自定义搜索回调函数
|
||||||
const subtitleArea1EL = ref<HTMLElement | null>(null);
|
let res = await RunningTaskList(s);
|
||||||
const videoPlayerEL = ref<HTMLVideoElement | null>(null);
|
tv.data = res.data.map((s, i) => {
|
||||||
|
return { ...s, customId: i };
|
||||||
// 响应式数据
|
|
||||||
const videoKnows = ref<VideoKnowRes[]>([]);
|
|
||||||
const currentSubtitle = ref("");
|
|
||||||
const currentSubtitle1 = ref("");
|
|
||||||
const isLocked = ref(false);
|
|
||||||
const displayButton = ref<any[]>([]);
|
|
||||||
const lastSegments = ref<any>(null);
|
|
||||||
const videoSrc = ref("");
|
|
||||||
const subtitles = ref<SenseVoiceRes[]>([]);
|
|
||||||
const b1 = ref([]);
|
|
||||||
const subtitles1 = ref<SenseVoiceRes[]>([]);
|
|
||||||
|
|
||||||
// 计算样式
|
|
||||||
const subtitleStyle = {
|
|
||||||
bottom: "101px",
|
|
||||||
backgroundColor: "rgb(99 129 103 / 50%)",
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取首字符
|
|
||||||
const getFirstChar = (str: string): string => {
|
|
||||||
return str ? str.charAt(0) : "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换锁定状态
|
|
||||||
const toggleLock = () => {
|
|
||||||
isLocked.value = !isLocked.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击知识点
|
|
||||||
const spClick = (index: number, event: Event) => {
|
|
||||||
if (videoPlayerEL && displayButton.value[index]) {
|
|
||||||
videoPlayerEL.value.currentTime = displayButton.value[index].startTime;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击时间跳转
|
|
||||||
const spClickTime = (startTime: number) => {
|
|
||||||
if (videoPlayerEL) {
|
|
||||||
videoPlayerEL.value.currentTime = startTime;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化知识点按钮
|
|
||||||
const initKD = () => {
|
|
||||||
const btns = document.getElementsByClassName("kBtn");
|
|
||||||
if (btns.length === 0) return;
|
|
||||||
|
|
||||||
displayButton.value = b1.value.map((s: any, i: number) => {
|
|
||||||
return { ...s, button: btns[i] };
|
|
||||||
});
|
});
|
||||||
};
|
tv.pageData = res;
|
||||||
|
return true;
|
||||||
// 设置数据(模拟从后端获取)
|
//返回true则不调用基础搜索API
|
||||||
const setDB = (
|
|
||||||
a: SenseVoiceRes[],
|
|
||||||
a1: SenseVoiceRes[],
|
|
||||||
videoKnows: VideoKnowRes[],
|
|
||||||
c: string
|
|
||||||
) => {
|
|
||||||
subtitles.value = a;
|
|
||||||
subtitles1.value = a1;
|
|
||||||
b1.value = videoKnows;
|
|
||||||
videoSrc.value = c;
|
|
||||||
|
|
||||||
// 初始化视频数据
|
|
||||||
init();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
const init = () => {
|
|
||||||
if (!videoPlayerEL) return;
|
|
||||||
|
|
||||||
// 视频时间变化监听
|
|
||||||
videoPlayerEL.value.addEventListener("timeupdate", function () {
|
|
||||||
if (displayButton.value.length === 0) initKD();
|
|
||||||
|
|
||||||
const currentTime = videoPlayerEL.value.currentTime;
|
|
||||||
if (subtitleAreaEL) subtitleAreaEL.value.textContent = "";
|
|
||||||
if (subtitleArea1EL) subtitleArea1EL.value.textContent = "";
|
|
||||||
|
|
||||||
// 更新字幕
|
|
||||||
subtitles.value.forEach((subtitle, index) => {
|
|
||||||
if (
|
|
||||||
currentTime >= subtitle.start &&
|
|
||||||
currentTime <= subtitle.end &&
|
|
||||||
subtitleAreaEL &&
|
|
||||||
subtitleAreaEL.value.textContent !== subtitle.text
|
|
||||||
) {
|
|
||||||
currentSubtitle.value = subtitle.text;
|
|
||||||
currentSubtitle1.value = subtitles1.value[index]?.text || "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 更新当前时间段
|
|
||||||
const segment = displayButton.value.findLast((s: any) => currentTime >= s.startTime);
|
|
||||||
if (segment) {
|
|
||||||
segment.button.style.backgroundColor = "rgb(238, 200, 118)";
|
|
||||||
if (lastSegments.value && lastSegments.value !== segment) {
|
|
||||||
lastSegments.value.button.style.backgroundColor = "rgb(240, 249, 235)";
|
|
||||||
}
|
|
||||||
lastSegments.value = segment;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 扩展功能:格式化开始和结束时间范围
|
|
||||||
* @param segment 包含 StartTime 和 EndTime 的对象
|
|
||||||
* @returns 格式化的时间范围字符串 (MM:SS - MM:SS)
|
|
||||||
*/
|
|
||||||
function getTimeRange(segment: VideoKnowRes): string {
|
|
||||||
const startTime = segment.startTime ?? 0;
|
|
||||||
|
|
||||||
const startMinutes = Math.floor(startTime / 60);
|
|
||||||
const startSeconds = Math.floor(startTime % 60);
|
|
||||||
|
|
||||||
const sf = startMinutes.toString().padStart(2, "0");
|
|
||||||
const sm = startSeconds.toString().padStart(2, "0");
|
|
||||||
|
|
||||||
return `${sf}:${sm}`;
|
|
||||||
}
|
}
|
||||||
// 组件挂载后
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 初始化MathJax
|
//初始化数据
|
||||||
if (window.MathJax) {
|
|
||||||
window.MathJax = {
|
|
||||||
tex: {
|
|
||||||
inlineMath: [
|
|
||||||
["$", "$"],
|
|
||||||
["\\(", "\\)"],
|
|
||||||
],
|
|
||||||
displayMath: [
|
|
||||||
["$$", "$$"],
|
|
||||||
["\\[", "\\]"],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// 获取当前路由对象
|
|
||||||
const route = useRoute();
|
|
||||||
const data = isEmpty(route.params) ? route.query : route.params;
|
|
||||||
if (isEmpty(data.id) || data.id == null) {
|
|
||||||
message("无效的任务", { type: "warning" });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let info = await ShowTaskInfo(data.id);
|
|
||||||
debugger;
|
|
||||||
setDB(info.captions, info.captions1, info.VideoKnows, info.MediaUrl);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 扩展Window接口以包含全局变量
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
MathJax: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<videoTask :searchCallback="searchCallback"></videoTask>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
<div id="video-container">
|
<div id="video-container">
|
||||||
<div v-if="videoKnows.length > 0">
|
<div v-if="videoKnows.length > 0">
|
||||||
<div id="segmentsContainer" class="sc" :class="{ locked: isLocked }">
|
<div id="segmentsContainer" class="sc" :class="{ locked: isLocked }">
|
||||||
|
<div>
|
||||||
<h2>
|
<h2>
|
||||||
<button class="gudingBtn" @click="toggleLock">
|
<button class="gudingBtn" @click="toggleLock">
|
||||||
{{ isLocked ? "🔓" : "🔒" }}
|
{{ isLocked ? "🔓" : "🔒" }}</button
|
||||||
</button>
|
>视频分段
|
||||||
</h2>
|
</h2>
|
||||||
|
</div>
|
||||||
<div v-for="(item, index) in videoKnows" :key="index" class="knowDiv">
|
<div v-for="(item, index) in videoKnows" :key="index" class="knowDiv">
|
||||||
<div class="knowTtile">
|
<div class="knowTtile">
|
||||||
<div style="cursor: pointer" @click="spClick(index, $event)">
|
<div style="cursor: pointer" @click="spClick(index, $event)">
|
||||||
|
|
@ -137,7 +139,13 @@ const setDB = (
|
||||||
videoKnows.value = vKnows;
|
videoKnows.value = vKnows;
|
||||||
videoSrc.value = c;
|
videoSrc.value = c;
|
||||||
videoPlayerEL.value?.load();
|
videoPlayerEL.value?.load();
|
||||||
videoPlayerEL.value?.play();
|
try {
|
||||||
|
nextTick(() => {
|
||||||
|
initKD();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("视频自动播放失败:", error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
function timeupdateVideo() {
|
function timeupdateVideo() {
|
||||||
if (displayButton.value.length === 0) initKD();
|
if (displayButton.value.length === 0) initKD();
|
||||||
|
|
@ -254,7 +262,6 @@ video {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
/* border-radius: 16px; */
|
/* border-radius: 16px; */
|
||||||
line-height: 27px;
|
line-height: 27px;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitles {
|
.subtitles {
|
||||||
|
|
@ -289,7 +296,7 @@ video {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kBtn {
|
.kBtn {
|
||||||
|
|
@ -312,6 +319,7 @@ video {
|
||||||
.kBtn:hover {
|
.kBtn:hover {
|
||||||
background-color: rgb(248, 230, 191) !important;
|
background-color: rgb(248, 230, 191) !important;
|
||||||
border: 1px solid rgb(206, 187, 81);
|
border: 1px solid rgb(206, 187, 81);
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.knowDiv {
|
.knowDiv {
|
||||||
|
|
@ -323,7 +331,9 @@ video {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: #cddc393d;
|
background-color: #cddc393d;
|
||||||
}
|
}
|
||||||
|
.knowDiv:hover .kBtn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.knowDiv:hover .knowTtile {
|
.knowDiv:hover .knowTtile {
|
||||||
width: 340px;
|
width: 340px;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -332,7 +342,7 @@ video {
|
||||||
}
|
}
|
||||||
|
|
||||||
.knowTtile {
|
.knowTtile {
|
||||||
position: absolute;
|
/* position: absolute; */
|
||||||
text-align: left;
|
text-align: left;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
await baseService.UpdateAsync(task);
|
await baseService.UpdateAsync(task);
|
||||||
}
|
}
|
||||||
//todo重新开始执行GPT分析
|
//todo重新开始执行GPT分析
|
||||||
return BadRequest("任务为实现");
|
return BadRequest("任务未实现");
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,7 +270,7 @@ namespace VideoAnalysisCore.Controllers
|
||||||
public async Task ReStart(long id, RedisChannelEnum selectEnum)
|
public async Task ReStart(long id, RedisChannelEnum selectEnum)
|
||||||
{
|
{
|
||||||
await redisManager.ClearTaskError(id);
|
await redisManager.ClearTaskError(id);
|
||||||
await Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
await redisManager.InsertChannel(selectEnum, id)
|
await redisManager.InsertChannel(selectEnum, id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -356,8 +356,32 @@ namespace VideoAnalysisCore.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 预览任务结果
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="model">查询模型</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<object> RunningTaskList([FromBody] QueryRequestBase model)
|
||||||
|
{
|
||||||
|
var oldTaskArr = redisManager.Redis.LRange<long>(RedisExpandKey.IDTask, 0, 999);
|
||||||
|
var sqlquery = base.BaseQuery(model)
|
||||||
|
.Where(s => oldTaskArr.Contains(s.Id))
|
||||||
|
.Select(s => new VideoTask
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
TagId = s.TagId,
|
||||||
|
VideoType = s.VideoType,
|
||||||
|
LastEnum = s.LastEnum,
|
||||||
|
Subject = s.Subject,
|
||||||
|
ComeFrom = s.ComeFrom,
|
||||||
|
MediaUrl = s.MediaUrl,
|
||||||
|
CreateTime = s.CreateTime,
|
||||||
|
});
|
||||||
|
RefAsync<int> total = 0;
|
||||||
|
var data = await sqlquery.ToPageListAsync(model.PageIndex + 1, model.PageSize, total);
|
||||||
|
return new PageResult<VideoTask>() { Data = data, Total = total };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue