直播场次
This commit is contained in:
@@ -1,103 +1,55 @@
|
|||||||
<!-- LiveRecordDialog.vue -->
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="visible" title="直播记录" width="86vw" top="6vh" :close-on-click-modal="false" destroy-on-close>
|
<el-dialog v-model="visible" title="直播记录" width="80vw" top="6vh" :close-on-click-modal="false" destroy-on-close>
|
||||||
<!-- 顶部工具栏 -->
|
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<el-input v-model="kw" placeholder="搜索:hostsId / userId / tenantId / id" clearable
|
|
||||||
style="width: 320px" />
|
|
||||||
<el-select v-model="sortKey" style="width: 170px" placeholder="排序字段">
|
|
||||||
<el-option label="开始时间" value="startTimeFormatted" />
|
|
||||||
<el-option label="结束时间" value="endTimeFormatted" />
|
|
||||||
<el-option label="点赞数" value="likeCount" />
|
|
||||||
<el-option label="粉丝团" value="fansClubCount" />
|
|
||||||
</el-select>
|
|
||||||
<el-select v-model="sortOrder" style="width: 140px" placeholder="排序方式">
|
|
||||||
<el-option label="降序" value="desc" />
|
|
||||||
<el-option label="升序" value="asc" />
|
|
||||||
</el-select>
|
|
||||||
|
|
||||||
<el-checkbox v-model="onlyAbnormal">只看异常</el-checkbox>
|
<el-checkbox v-model="onlyAbnormal">只看异常</el-checkbox>
|
||||||
|
|
||||||
<el-button @click="reset">重置</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<el-tag type="info">总条数:{{ filteredRows.length }}</el-tag>
|
<el-tag type="info">总条数:{{ filteredRows.length }}</el-tag>
|
||||||
<el-tag type="success">点赞合计:{{ totalLikes }}</el-tag>
|
<el-tag type="success">点赞合计:{{ totalLikes }}</el-tag>
|
||||||
<el-tag type="warning">like=0:{{ zeroLikeCount }}</el-tag>
|
<el-tag type="warning">无点赞:{{ zeroLikeCount }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="pagedRows" border height="62vh" style="width: 100%"
|
<el-table :data="filteredRows" border height="62vh" style="width: 100%"
|
||||||
:default-sort="{ prop: 'startTimeFormatted', order: 'descending' }">
|
:default-sort="{ prop: 'startTimeFormatted', order: 'descending' }" table-layout="auto">
|
||||||
<el-table-column prop="id" label="ID" width="90" />
|
<el-table-column prop="hostsId" label="主播id" />
|
||||||
<el-table-column prop="userId" label="userId" width="90" />
|
<el-table-column prop="startTimeFormatted" label="开始时间" />
|
||||||
<el-table-column prop="hostsId" label="hostsId" width="130" />
|
<el-table-column prop="endTimeFormatted" label="结束时间" />
|
||||||
<el-table-column prop="tenantId" label="tenantId" width="100" />
|
<el-table-column prop="durationFormatted" label="时长" />
|
||||||
|
|
||||||
<el-table-column prop="fansClubCount" label="粉丝团" width="90" />
|
<el-table-column prop="likeCount" label="点赞" sortable>
|
||||||
<el-table-column prop="lightedVsTotalGifts" label="点亮/礼物" width="110" />
|
|
||||||
|
|
||||||
<el-table-column prop="startTimeFormatted" label="开始时间" width="170" />
|
|
||||||
<el-table-column prop="endTimeFormatted" label="结束时间" width="170" />
|
|
||||||
<el-table-column prop="durationFormatted" label="时长" width="120" />
|
|
||||||
|
|
||||||
<el-table-column prop="likeCount" label="点赞" width="110" sortable>
|
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag v-if="row.likeCount === 0" type="danger">0</el-tag>
|
<el-tag v-if="row.likeCount === 0" type="danger">0</el-tag>
|
||||||
<span v-else>{{ row.likeCount }}</span>
|
<span v-else>{{ row.likeCount }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="createTime" label="入库时间" width="170" />
|
<el-table-column prop="createTime" label="入库时间" />
|
||||||
|
|
||||||
<el-table-column label="操作" fixed="right" width="160">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-button size="small" @click="copyRow(row)">复制</el-button>
|
|
||||||
<el-button size="small" type="primary" @click="emitSelect(row)">选中</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<div class="footer">
|
|
||||||
<el-pagination v-model:current-page="page" v-model:page-size="pageSize" :page-sizes="[10, 20, 50, 100]"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper" :total="filteredRows.length" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="visible = false">关闭</el-button>
|
<el-button @click="visible = false">关闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="js">
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
type Row = {
|
const props = defineProps({
|
||||||
id: number;
|
modelValue: {
|
||||||
userId: number;
|
type: Boolean,
|
||||||
hostsId: string;
|
default: false,
|
||||||
tenantId: number;
|
},
|
||||||
fansClubCount: number;
|
rows: {
|
||||||
lightedVsTotalGifts: string;
|
type: Array,
|
||||||
startTimeFormatted: string;
|
default: () => [],
|
||||||
endTimeFormatted: string;
|
},
|
||||||
likeCount: number;
|
});
|
||||||
durationFormatted: string;
|
|
||||||
createTime: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const emit = defineEmits(["update:modelValue", "select"]);
|
||||||
modelValue: boolean;
|
|
||||||
rows: Row[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "update:modelValue", v: boolean): void;
|
|
||||||
(e: "select", row: Row): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const visible = computed({
|
const visible = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
@@ -105,25 +57,16 @@ const visible = computed({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const kw = ref("");
|
const kw = ref("");
|
||||||
const sortKey = ref<keyof Row>("startTimeFormatted");
|
const sortKey = ref("startTimeFormatted");
|
||||||
const sortOrder = ref<"asc" | "desc">("desc");
|
const sortOrder = ref("desc");
|
||||||
const onlyAbnormal = ref(false);
|
const onlyAbnormal = ref(false);
|
||||||
|
|
||||||
const page = ref(1);
|
function parseTime(s) {
|
||||||
const pageSize = ref(20);
|
|
||||||
|
|
||||||
watch([kw, sortKey, sortOrder, onlyAbnormal], () => {
|
|
||||||
page.value = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
function parseTime(s?: string) {
|
|
||||||
// "2025-12-18 13:12:11" -> Date
|
|
||||||
if (!s) return 0;
|
if (!s) return 0;
|
||||||
return new Date(s.replace(" ", "T")).getTime() || 0;
|
return new Date(s.replace(" ", "T")).getTime() || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function durationSeconds(durationFormatted?: string) {
|
function durationSeconds(durationFormatted) {
|
||||||
// 例:"2小时49分钟55秒" / "18分钟31秒" / "25秒"
|
|
||||||
if (!durationFormatted) return 0;
|
if (!durationFormatted) return 0;
|
||||||
const h = Number((durationFormatted.match(/(\d+)\s*小时/) || [])[1] || 0);
|
const h = Number((durationFormatted.match(/(\d+)\s*小时/) || [])[1] || 0);
|
||||||
const m = Number((durationFormatted.match(/(\d+)\s*分钟/) || [])[1] || 0);
|
const m = Number((durationFormatted.match(/(\d+)\s*分钟/) || [])[1] || 0);
|
||||||
@@ -144,27 +87,23 @@ const filteredRows = computed(() => {
|
|||||||
arr = arr.filter((r) => r.likeCount === 0 || durationSeconds(r.durationFormatted) < 60);
|
arr = arr.filter((r) => r.likeCount === 0 || durationSeconds(r.durationFormatted) < 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排序
|
|
||||||
const key = sortKey.value;
|
const key = sortKey.value;
|
||||||
const order = sortOrder.value;
|
const order = sortOrder.value;
|
||||||
|
|
||||||
arr = [...arr].sort((a, b) => {
|
arr = [...arr].sort((a, b) => {
|
||||||
const av = a[key] as any;
|
const av = a[key];
|
||||||
const bv = b[key] as any;
|
const bv = b[key];
|
||||||
|
|
||||||
// 时间字段特殊处理
|
|
||||||
if (key === "startTimeFormatted" || key === "endTimeFormatted" || key === "createTime") {
|
if (key === "startTimeFormatted" || key === "endTimeFormatted" || key === "createTime") {
|
||||||
const aa = parseTime(String(av));
|
const aa = parseTime(String(av));
|
||||||
const bb = parseTime(String(bv));
|
const bb = parseTime(String(bv));
|
||||||
return order === "desc" ? bb - aa : aa - bb;
|
return order === "desc" ? bb - aa : aa - bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数字
|
|
||||||
if (typeof av === "number" && typeof bv === "number") {
|
if (typeof av === "number" && typeof bv === "number") {
|
||||||
return order === "desc" ? bv - av : av - bv;
|
return order === "desc" ? bv - av : av - bv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字符串
|
|
||||||
return order === "desc"
|
return order === "desc"
|
||||||
? String(bv).localeCompare(String(av))
|
? String(bv).localeCompare(String(av))
|
||||||
: String(av).localeCompare(String(bv));
|
: String(av).localeCompare(String(bv));
|
||||||
@@ -173,11 +112,6 @@ const filteredRows = computed(() => {
|
|||||||
return arr;
|
return arr;
|
||||||
});
|
});
|
||||||
|
|
||||||
const pagedRows = computed(() => {
|
|
||||||
const start = (page.value - 1) * pageSize.value;
|
|
||||||
return filteredRows.value.slice(start, start + pageSize.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
const totalLikes = computed(() =>
|
const totalLikes = computed(() =>
|
||||||
filteredRows.value.reduce((sum, r) => sum + (Number(r.likeCount) || 0), 0)
|
filteredRows.value.reduce((sum, r) => sum + (Number(r.likeCount) || 0), 0)
|
||||||
);
|
);
|
||||||
@@ -189,11 +123,9 @@ function reset() {
|
|||||||
sortKey.value = "startTimeFormatted";
|
sortKey.value = "startTimeFormatted";
|
||||||
sortOrder.value = "desc";
|
sortOrder.value = "desc";
|
||||||
onlyAbnormal.value = false;
|
onlyAbnormal.value = false;
|
||||||
page.value = 1;
|
|
||||||
pageSize.value = 20;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyRow(row: Row) {
|
async function copyRow(row) {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(JSON.stringify(row, null, 2));
|
await navigator.clipboard.writeText(JSON.stringify(row, null, 2));
|
||||||
ElMessage.success("已复制该行 JSON");
|
ElMessage.success("已复制该行 JSON");
|
||||||
@@ -202,7 +134,7 @@ async function copyRow(row: Row) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitSelect(row: Row) {
|
function emitSelect(row) {
|
||||||
emit("select", row);
|
emit("select", row);
|
||||||
ElMessage.success(`已选中:ID ${row.id}`);
|
ElMessage.success(`已选中:ID ${row.id}`);
|
||||||
}
|
}
|
||||||
@@ -231,10 +163,4 @@ function emitSelect(row: Row) {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -17,8 +17,8 @@ let baseURL = ''
|
|||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
// 生产环境
|
// 生产环境
|
||||||
// baseURL = "https://api.tkpage.yolozs.com"
|
// baseURL = "https://api.tkpage.yolozs.com"
|
||||||
baseURL = "http://192.168.2.21:8101"
|
// baseURL = "http://192.168.2.21:8101"
|
||||||
// baseURL = "https://crawlclient.api.yolozs.com"
|
baseURL = "https://crawlclient.api.yolozs.com"
|
||||||
} else {
|
} else {
|
||||||
// 测试环境
|
// 测试环境
|
||||||
// baseURL = "http://120.26.251.180:8085/"
|
// baseURL = "http://120.26.251.180:8085/"
|
||||||
|
|||||||
@@ -1,121 +1,134 @@
|
|||||||
// pythonBridge.js
|
// pythonBridge.js
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
|
|
||||||
const bridge = ref(null);
|
const bridge = ref(null);
|
||||||
|
|
||||||
|
// 统一安全调用,确保 Qt 响应有回调可执行
|
||||||
|
const callBridge = (method, ...args) => {
|
||||||
|
if (!bridge.value || typeof bridge.value[method] !== 'function') return;
|
||||||
|
const last = args[args.length - 1];
|
||||||
|
const hasCallback = typeof last === 'function';
|
||||||
|
const callback = hasCallback ? args.pop() : () => { };
|
||||||
|
bridge.value[method](...args, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 防御:若 Qt 返回了未知 id,忽略以免 execCallbacks 报错
|
||||||
|
const patchQWebChannel = () => {
|
||||||
|
if (!window.QWebChannel || QWebChannel.__patchedIgnoreMissing) return;
|
||||||
|
const originalHandleResponse = QWebChannel.prototype.handleResponse;
|
||||||
|
QWebChannel.__patchedIgnoreMissing = true;
|
||||||
|
QWebChannel.prototype.handleResponse = function (message) {
|
||||||
|
const cb = this.execCallbacks && this.execCallbacks[message.id];
|
||||||
|
if (message.id && typeof cb !== 'function') {
|
||||||
|
console.warn('忽略未知的 WebChannel 响应', message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return originalHandleResponse.call(this, message);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化 QWebChannel
|
// 初始化 QWebChannel
|
||||||
const initBridge = () => {
|
const initBridge = () => {
|
||||||
if (/localhost/.test(window.location.href)) return
|
if (/localhost/.test(window.location.href)) return;
|
||||||
|
patchQWebChannel();
|
||||||
new QWebChannel(qt.webChannelTransport, (channel) => {
|
new QWebChannel(qt.webChannelTransport, (channel) => {
|
||||||
|
// 兜底:任何缺失的回调都返回空函数,避免 execCallbacks 报错
|
||||||
|
channel.execCallbacks = new Proxy(channel.execCallbacks || {}, {
|
||||||
|
get(target, prop) {
|
||||||
|
const val = target[prop];
|
||||||
|
if (typeof val === 'function') return val;
|
||||||
|
// 返回空函数,确保 handleResponse 可调用
|
||||||
|
return () => {};
|
||||||
|
},
|
||||||
|
set(target, prop, value) {
|
||||||
|
target[prop] = value;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
bridge.value = channel.objects.bridge;
|
bridge.value = channel.objects.bridge;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export function usePythonBridge() {
|
export function usePythonBridge() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 调用 Python 方法
|
// 调用 Python 方法
|
||||||
const fetchDataConfig = (data) => {
|
const fetchDataConfig = (data) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
if (bridge.value) {
|
if (!bridge.value) return resolve(null);
|
||||||
bridge.value.fetchDataConfig(data, function (result) {
|
callBridge('fetchDataConfig', data, (result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查询获取主播的数据
|
// 查询获取主播的数据
|
||||||
const fetchDataCount = () => {
|
const fetchDataCount = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
if (bridge.value) {
|
if (!bridge.value) return resolve(null);
|
||||||
bridge.value.fetchDataCount(function (result) {
|
callBridge('fetchDataCount', (result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开 tk 后台
|
// 打开 tk 后台
|
||||||
const loginTikTok = () => {
|
const loginTikTok = () => {
|
||||||
if (bridge.value) {
|
callBridge('loginTikTok');
|
||||||
bridge.value.loginTikTok(function (result) {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 登录 tk 后台
|
// 登录 tk 后台
|
||||||
const loginBackStage = (data) => {
|
const loginBackStage = (data) => {
|
||||||
if (bridge.value) {
|
|
||||||
if (data.index == 0) {
|
if (data.index == 0) {
|
||||||
bridge.value.loginBackStage(JSON.stringify(data));
|
callBridge('loginBackStage', JSON.stringify(data));
|
||||||
} else if (data.index == 1) {
|
} else if (data.index == 1) {
|
||||||
bridge.value.loginBackStageCopy(JSON.stringify(data));
|
callBridge('loginBackStageCopy', JSON.stringify(data));
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到主播页面
|
// 跳转到主播页面
|
||||||
const givePyAnchorId = (id) => {
|
const givePyAnchorId = (id) => {
|
||||||
|
callBridge('givePyAnchorId', id);
|
||||||
if (bridge.value) {
|
|
||||||
bridge.value.givePyAnchorId(id, function (result) {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查询登录状态
|
// 查询登录状态
|
||||||
const backStageloginStatus = () => {
|
const backStageloginStatus = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
if (bridge.value) {
|
if (!bridge.value) return resolve(null);
|
||||||
bridge.value.backStageloginStatus(function (result) {
|
callBridge('backStageloginStatus', (result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
//查询登录状态
|
|
||||||
|
// 查询登录状态(副账号)
|
||||||
const backStageloginStatusCopy = () => {
|
const backStageloginStatusCopy = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
if (bridge.value) {
|
if (!bridge.value) return resolve(null);
|
||||||
bridge.value.backStageloginStatusCopy(function (result) {
|
callBridge('backStageloginStatusCopy', (result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导出表格
|
// 导出表格
|
||||||
const exportToExcel = (data) => {
|
const exportToExcel = (data) => {
|
||||||
if (bridge.value) {
|
callBridge('exportToExcel', JSON.stringify(data));
|
||||||
bridge.value.exportToExcel(JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
const stopScript = () => {
|
|
||||||
if (bridge.value) {
|
|
||||||
bridge.value.stopScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const stopScript = () => {
|
||||||
|
callBridge('stopScript');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取版本号
|
// 获取版本号
|
||||||
const getVersion = () => {
|
const getVersion = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
if (bridge.value) {
|
if (!bridge.value) return resolve(null);
|
||||||
bridge.value.currentVersion(function (result) {
|
callBridge('currentVersion', (result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 在组件挂载时初始化桥接
|
// 在组件挂载时初始化桥接
|
||||||
onMounted(initBridge);
|
onMounted(initBridge);
|
||||||
|
|
||||||
@@ -129,6 +142,6 @@ export function usePythonBridge() {
|
|||||||
backStageloginStatusCopy,
|
backStageloginStatusCopy,
|
||||||
exportToExcel,
|
exportToExcel,
|
||||||
stopScript,
|
stopScript,
|
||||||
getVersion
|
getVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -46,12 +46,20 @@
|
|||||||
<el-table-column prop="invitationType" :label="$t('hostList.invitationType')" width="80">
|
<el-table-column prop="invitationType" :label="$t('hostList.invitationType')" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|
||||||
<el-tag :type="scope.row.invitationType == 1 ? 'success' : 'warning'" @click="getliveHost">
|
<el-tag :type="scope.row.invitationType == 1 ? 'success' : 'warning'">
|
||||||
{{ scope.row.invitationType == 1 ? $t('hostList.invitationType1') : $t('hostList.invitationType2') }}
|
{{ scope.row.invitationType == 1 ? $t('hostList.invitationType1') : $t('hostList.invitationType2') }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="直播场次" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button class="live-btn" size="small" @click="getliveHost(scope.row.hostId)">
|
||||||
|
查看场次
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column v-for="label in labelList" :key="label.paramCode" :prop="label.paramCode"
|
<el-table-column v-for="label in labelList" :key="label.paramCode" :prop="label.paramCode"
|
||||||
:label="label.paramCodeMeaning" width="120">
|
:label="label.paramCodeMeaning" width="120">
|
||||||
<template v-if="label.paramCode != 'createDt'" #default="scope">
|
<template v-if="label.paramCode != 'createDt'" #default="scope">
|
||||||
@@ -139,6 +147,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<LiveRecordDialog v-model:modelValue="liveDetailDialogVisible" :rows="liveDetailRecords"
|
||||||
|
@select="handleLiveSelect" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -154,6 +165,7 @@ import { ref, reactive, onMounted } from 'vue';
|
|||||||
// import { ElMessage, ElMessageBox } from 'element-plus'
|
// import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
// import { color } from 'echarts';
|
// import { color } from 'echarts';
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import LiveRecordDialog from '@/components/LiveRecordDialog.vue'
|
||||||
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
@@ -224,6 +236,9 @@ let staffId = ref({})
|
|||||||
let commentInfo = ref('')
|
let commentInfo = ref('')
|
||||||
//备注信息主播
|
//备注信息主播
|
||||||
let commentHost = ref('')
|
let commentHost = ref('')
|
||||||
|
let liveDetailDialogVisible = ref(false)
|
||||||
|
let liveDetailRecords = ref([])
|
||||||
|
let liveDetailLoading = ref(false)
|
||||||
//分页
|
//分页
|
||||||
let pageSize = ref(10)
|
let pageSize = ref(10)
|
||||||
let page = ref(1)
|
let page = ref(1)
|
||||||
@@ -359,17 +374,29 @@ function handleClose(done) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getliveHost() {
|
function getliveHost(hostId) {
|
||||||
|
liveDetailLoading.value = true
|
||||||
liveHostDetail(
|
liveHostDetail(
|
||||||
{
|
{
|
||||||
"hostsId": "1296peahh",
|
"hostsId": hostId,
|
||||||
"tenantId": userInfo.value.tenantId
|
"tenantId": userInfo.value.tenantId
|
||||||
}
|
}
|
||||||
).then(res => {
|
).then(res => {
|
||||||
console.log("直播间信息列表", JSON.stringify(res))
|
const detailList = Array.isArray(res) ? res : (res?.records || [])
|
||||||
|
liveDetailRecords.value = detailList
|
||||||
|
liveDetailDialogVisible.value = true
|
||||||
|
}).catch(err => {
|
||||||
|
console.log('liveHostDetail error', err)
|
||||||
|
}).finally(() => {
|
||||||
|
liveDetailLoading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleLiveSelect(row) {
|
||||||
|
console.log('selected live row', row)
|
||||||
|
liveDetailDialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
//修改主播维护状态
|
//修改主播维护状态
|
||||||
// function handleSelectChange(event, data) {
|
// function handleSelectChange(event, data) {
|
||||||
|
|
||||||
@@ -518,6 +545,8 @@ function openHTML(id) {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
// height: 100vh;
|
// height: 100vh;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
|
background: linear-gradient(135deg, #f7fbff 0%, #f2f9f8 100%);
|
||||||
|
border-radius: 16px;
|
||||||
|
|
||||||
/* 页面无法选中 */
|
/* 页面无法选中 */
|
||||||
// -webkit-user-select: none;
|
// -webkit-user-select: none;
|
||||||
@@ -527,12 +556,38 @@ function openHTML(id) {
|
|||||||
|
|
||||||
.hostTable {
|
.hostTable {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 40px 0;
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 16px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04);
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
.hostIdText {
|
.hostIdText {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.live-btn {
|
||||||
|
background: linear-gradient(90deg, #45a1ff, #5ad9ff);
|
||||||
|
border: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-btn:hover {
|
||||||
|
filter: brightness(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table) {
|
||||||
|
width: 100% !important;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table__header-wrapper),
|
||||||
|
:deep(.el-table__body-wrapper) {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.serch-button {
|
.serch-button {
|
||||||
|
|||||||
Reference in New Issue
Block a user