优化达人工作台
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<div class="mx-4 flex max-h-[84vh] w-full max-w-6xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl">
|
<div class="mx-4 flex max-h-[84vh] w-full max-w-6xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl">
|
||||||
<div class="flex items-center justify-between border-b border-gray-200 px-5 py-4">
|
<div class="flex items-center justify-between border-b border-gray-200 px-5 py-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-lg font-semibold text-gray-900">大哥池</h3>
|
<h3 class="text-lg font-semibold text-gray-900">{{ featureLabels.poolName }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button @click="handleDeleteAll" :disabled="loading || total === 0"
|
<button @click="handleDeleteAll" :disabled="loading || total === 0"
|
||||||
@@ -63,31 +63,31 @@
|
|||||||
<table class="min-w-full border-collapse text-left text-sm">
|
<table class="min-w-full border-collapse text-left text-sm">
|
||||||
<thead class="sticky top-0 bg-slate-900 text-slate-100">
|
<thead class="sticky top-0 bg-slate-900 text-slate-100">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-3 font-medium">ID</th>
|
|
||||||
<th class="px-4 py-3 font-medium">displayId</th>
|
<th class="px-4 py-3 font-medium">displayId</th>
|
||||||
<th class="px-4 py-3 font-medium">昵称</th>
|
|
||||||
<th class="px-4 py-3 font-medium">地区</th>
|
<th class="px-4 py-3 font-medium">地区</th>
|
||||||
<th class="px-4 py-3 font-medium">等级</th>
|
|
||||||
<th class="px-4 py-3 font-medium">打赏金币</th>
|
|
||||||
<th class="px-4 py-3 font-medium">粉丝数</th>
|
<th class="px-4 py-3 font-medium">粉丝数</th>
|
||||||
<th class="px-4 py-3 font-medium">主播ID</th>
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">ID</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">昵称</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">等级</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">打赏金币</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">主播ID</th>
|
||||||
<th class="px-4 py-3 font-medium">创建时间</th>
|
<th class="px-4 py-3 font-medium">创建时间</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="row in rows" :key="row.id" class="border-b border-gray-100 hover:bg-blue-50/50">
|
<tr v-for="row in rows" :key="row.id" class="border-b border-gray-100 hover:bg-blue-50/50">
|
||||||
<td class="px-4 py-3 text-gray-700">{{ row.id ?? '-' }}</td>
|
|
||||||
<td class="px-4 py-3 font-medium text-gray-900">{{ row.displayId || '-' }}</td>
|
<td class="px-4 py-3 font-medium text-gray-900">{{ row.displayId || '-' }}</td>
|
||||||
<td class="px-4 py-3 text-gray-700">{{ row.nickname || '-' }}</td>
|
|
||||||
<td class="px-4 py-3 text-gray-700">{{ row.region || '-' }}</td>
|
<td class="px-4 py-3 text-gray-700">{{ row.region || '-' }}</td>
|
||||||
<td class="px-4 py-3 text-gray-700">{{ row.level ?? '-' }}</td>
|
|
||||||
<td class="px-4 py-3 text-gray-700">{{ formatNumber(row.hostcoins) }}</td>
|
|
||||||
<td class="px-4 py-3 text-gray-700">{{ formatNumber(row.followerCount) }}</td>
|
<td class="px-4 py-3 text-gray-700">{{ formatNumber(row.followerCount) }}</td>
|
||||||
<td class="px-4 py-3 text-gray-700">{{ row.hostDisplayId || '-' }}</td>
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.id ?? '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.nickname || '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.level ?? '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ formatNumber(row.hostcoins) }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.hostDisplayId || '-' }}</td>
|
||||||
<td class="px-4 py-3 text-gray-700">{{ formatTime(row.createTime) }}</td>
|
<td class="px-4 py-3 text-gray-700">{{ formatTime(row.createTime) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="!loading && rows.length === 0">
|
<tr v-if="!loading && rows.length === 0">
|
||||||
<td colspan="9" class="px-4 py-12 text-center text-gray-400">暂无大哥池数据</td>
|
<td :colspan="featureLabels.expertTenant ? 4 : 9" class="px-4 py-12 text-center text-gray-400">暂无{{ featureLabels.poolName }}数据</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -131,6 +131,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { getCurrentBrotherFeatureLabels } from '@/utils/tenantFeature'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@@ -140,6 +141,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close'])
|
||||||
|
const featureLabels = getCurrentBrotherFeatureLabels()
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const rows = ref([])
|
const rows = ref([])
|
||||||
@@ -182,7 +184,7 @@ async function loadData() {
|
|||||||
rows.value = []
|
rows.value = []
|
||||||
total.value = 0
|
total.value = 0
|
||||||
totalPages.value = 0
|
totalPages.value = 0
|
||||||
ElMessage.error('当前客户端未加载大哥池查询桥接,请重启客户端后再试')
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}查询桥接,请重启客户端后再试`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ async function loadData() {
|
|||||||
const raw = await tkBridge.queryBrotherInfo(JSON.stringify(buildPayload()))
|
const raw = await tkBridge.queryBrotherInfo(JSON.stringify(buildPayload()))
|
||||||
const result = typeof raw === 'string' ? JSON.parse(raw) : raw
|
const result = typeof raw === 'string' ? JSON.parse(raw) : raw
|
||||||
if (result?.status !== 'success') {
|
if (result?.status !== 'success') {
|
||||||
throw new Error(result?.message || '查询大哥池失败')
|
throw new Error(result?.message || `查询${featureLabels.poolName}失败`)
|
||||||
}
|
}
|
||||||
rows.value = Array.isArray(result?.list) ? result.list : []
|
rows.value = Array.isArray(result?.list) ? result.list : []
|
||||||
total.value = Number(result?.total || 0)
|
total.value = Number(result?.total || 0)
|
||||||
@@ -210,7 +212,7 @@ async function loadData() {
|
|||||||
async function handleDeleteAll() {
|
async function handleDeleteAll() {
|
||||||
const tkBridge = getTkBridge()
|
const tkBridge = getTkBridge()
|
||||||
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
||||||
ElMessage.error('当前客户端未加载大哥池删除桥接,请重启客户端后再试')
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}删除桥接,请重启客户端后再试`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +223,7 @@ async function confirmDeleteAll() {
|
|||||||
const tkBridge = getTkBridge()
|
const tkBridge = getTkBridge()
|
||||||
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
||||||
showDeleteConfirm.value = false
|
showDeleteConfirm.value = false
|
||||||
ElMessage.error('当前客户端未加载大哥池删除桥接,请重启客户端后再试')
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}删除桥接,请重启客户端后再试`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +232,7 @@ async function confirmDeleteAll() {
|
|||||||
const rawList = await tkBridge.getAllBrotherInfo()
|
const rawList = await tkBridge.getAllBrotherInfo()
|
||||||
const listResult = typeof rawList === 'string' ? JSON.parse(rawList) : rawList
|
const listResult = typeof rawList === 'string' ? JSON.parse(rawList) : rawList
|
||||||
if (listResult?.status !== 'success') {
|
if (listResult?.status !== 'success') {
|
||||||
throw new Error(listResult?.message || '读取大哥池失败')
|
throw new Error(listResult?.message || `读取${featureLabels.poolName}失败`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ids = (Array.isArray(listResult?.list) ? listResult.list : [])
|
const ids = (Array.isArray(listResult?.list) ? listResult.list : [])
|
||||||
@@ -239,7 +241,7 @@ async function confirmDeleteAll() {
|
|||||||
|
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
showDeleteConfirm.value = false
|
showDeleteConfirm.value = false
|
||||||
ElMessage.success('大哥池已经是空的')
|
ElMessage.success(`${featureLabels.poolName}已经是空的`)
|
||||||
rows.value = []
|
rows.value = []
|
||||||
total.value = 0
|
total.value = 0
|
||||||
totalPages.value = 1
|
totalPages.value = 1
|
||||||
@@ -250,10 +252,10 @@ async function confirmDeleteAll() {
|
|||||||
const rawDelete = await tkBridge.deleteBrotherInfo(JSON.stringify({ ids }))
|
const rawDelete = await tkBridge.deleteBrotherInfo(JSON.stringify({ ids }))
|
||||||
const deleteResult = typeof rawDelete === 'string' ? JSON.parse(rawDelete) : rawDelete
|
const deleteResult = typeof rawDelete === 'string' ? JSON.parse(rawDelete) : rawDelete
|
||||||
if (deleteResult?.status !== 'success') {
|
if (deleteResult?.status !== 'success') {
|
||||||
throw new Error(deleteResult?.message || '删除大哥池失败')
|
throw new Error(deleteResult?.message || `删除${featureLabels.poolName}失败`)
|
||||||
}
|
}
|
||||||
|
|
||||||
ElMessage.success(`已删除 ${ids.length} 条大哥池数据`)
|
ElMessage.success(`已删除 ${ids.length} 条${featureLabels.poolName}数据`)
|
||||||
showDeleteConfirm.value = false
|
showDeleteConfirm.value = false
|
||||||
page.value = 1
|
page.value = 1
|
||||||
await loadData()
|
await loadData()
|
||||||
|
|||||||
440
src/components/TenantBrotherInfoDialog.vue
Normal file
440
src/components/TenantBrotherInfoDialog.vue
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
<template>
|
||||||
|
<Teleport to="body">
|
||||||
|
<div v-if="visible" class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/50">
|
||||||
|
<div class="mx-4 flex max-h-[84vh] w-full max-w-6xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl">
|
||||||
|
<div class="flex items-center justify-between border-b border-gray-200 px-5 py-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900">{{ featureLabels.poolName }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
@click="handleDeleteAll"
|
||||||
|
:disabled="loading || total === 0"
|
||||||
|
class="rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600 transition-colors hover:bg-red-100 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
全部删除
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="handleClose"
|
||||||
|
class="rounded-lg px-3 py-2 text-sm text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700"
|
||||||
|
>
|
||||||
|
关闭
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border-b border-gray-100 bg-gray-50 px-5 py-4">
|
||||||
|
<div class="grid grid-cols-1 gap-3 md:grid-cols-4">
|
||||||
|
<input
|
||||||
|
v-model.trim="filters.keyword"
|
||||||
|
type="text"
|
||||||
|
placeholder="关键词:displayId / 昵称 / userIdStr"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
@keyup.enter="handleSearch"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.trim="filters.region"
|
||||||
|
type="text"
|
||||||
|
placeholder="地区"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
@keyup.enter="handleSearch"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.trim="filters.hostDisplayId"
|
||||||
|
type="text"
|
||||||
|
placeholder="主播 displayId"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
@keyup.enter="handleSearch"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.trim="filters.displayId"
|
||||||
|
type="text"
|
||||||
|
:placeholder="`${featureLabels.roleName} displayId`"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
@keyup.enter="handleSearch"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 grid grid-cols-2 gap-3 md:grid-cols-6">
|
||||||
|
<input
|
||||||
|
v-model.number="filters.minLevel"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
placeholder="最低等级"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.number="filters.maxLevel"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
placeholder="最高等级"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.number="filters.minCoins"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
placeholder="最低金币"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-model.number="filters.maxCoins"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
placeholder="最高金币"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
/>
|
||||||
|
<select
|
||||||
|
v-model.number="pageSize"
|
||||||
|
class="h-10 rounded-lg border border-gray-300 bg-white px-3 text-sm outline-none focus:border-blue-500"
|
||||||
|
>
|
||||||
|
<option :value="10">10 / 页</option>
|
||||||
|
<option :value="20">20 / 页</option>
|
||||||
|
<option :value="50">50 / 页</option>
|
||||||
|
<option :value="100">100 / 页</option>
|
||||||
|
</select>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<button
|
||||||
|
@click="handleSearch"
|
||||||
|
:disabled="loading"
|
||||||
|
class="flex-1 rounded-lg bg-blue-600 px-3 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60"
|
||||||
|
>
|
||||||
|
查询
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="handleReset"
|
||||||
|
:disabled="loading"
|
||||||
|
class="flex-1 rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-60"
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between border-b border-gray-100 px-5 py-3 text-sm text-gray-500">
|
||||||
|
<div>共 {{ total }} 条,本页 {{ rows.length }} 条</div>
|
||||||
|
<div v-if="loading" class="text-blue-600">加载中...</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="min-h-0 flex-1 overflow-auto">
|
||||||
|
<table class="min-w-full border-collapse text-left text-sm">
|
||||||
|
<thead class="sticky top-0 bg-slate-900 text-slate-100">
|
||||||
|
<tr>
|
||||||
|
<th class="px-4 py-3 font-medium">displayId</th>
|
||||||
|
<th class="px-4 py-3 font-medium">地区</th>
|
||||||
|
<th class="px-4 py-3 font-medium">粉丝数</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">ID</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">昵称</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">等级</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">打赏金币</th>
|
||||||
|
<th v-if="!featureLabels.expertTenant" class="px-4 py-3 font-medium">主播ID</th>
|
||||||
|
<th class="px-4 py-3 font-medium">创建时间</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="row in rows" :key="row.id" class="border-b border-gray-100 hover:bg-blue-50/50">
|
||||||
|
<td class="px-4 py-3 font-medium text-gray-900">{{ row.displayId || '-' }}</td>
|
||||||
|
<td class="px-4 py-3 text-gray-700">{{ row.region || '-' }}</td>
|
||||||
|
<td class="px-4 py-3 text-gray-700">{{ formatNumber(row.followerCount) }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.id ?? '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.nickname || '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.level ?? '-' }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ formatNumber(row.hostcoins) }}</td>
|
||||||
|
<td v-if="!featureLabels.expertTenant" class="px-4 py-3 text-gray-700">{{ row.hostDisplayId || '-' }}</td>
|
||||||
|
<td class="px-4 py-3 text-gray-700">{{ formatTime(row.createTime) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="!loading && rows.length === 0">
|
||||||
|
<td :colspan="featureLabels.expertTenant ? 4 : 9" class="px-4 py-12 text-center text-gray-400">暂无{{ featureLabels.poolName }}数据</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between border-t border-gray-200 px-5 py-4">
|
||||||
|
<div class="text-sm text-gray-500">第 {{ page }} / {{ totalPages || 1 }} 页</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
@click="goPrev"
|
||||||
|
:disabled="loading || page <= 1"
|
||||||
|
class="rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
上一页
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="goNext"
|
||||||
|
:disabled="loading || page >= totalPages"
|
||||||
|
class="rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
下一页
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="showDeleteConfirm" class="absolute inset-0 z-[10001] flex items-center justify-center bg-black/45 px-4">
|
||||||
|
<div class="w-full max-w-md rounded-2xl bg-white p-6 shadow-2xl">
|
||||||
|
<div class="text-lg font-semibold text-gray-900">确认全部删除</div>
|
||||||
|
<p class="mt-3 text-sm leading-6 text-gray-600">
|
||||||
|
将删除本地 sqlite 中
|
||||||
|
<code class="rounded bg-gray-100 px-1.5 py-0.5 text-xs text-gray-700">brother_info</code>
|
||||||
|
的全部数据,删除后不可恢复。
|
||||||
|
</p>
|
||||||
|
<div class="mt-6 flex justify-end gap-3">
|
||||||
|
<button
|
||||||
|
@click="showDeleteConfirm = false"
|
||||||
|
:disabled="loading"
|
||||||
|
class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm text-gray-700 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="confirmDeleteAll"
|
||||||
|
:disabled="loading"
|
||||||
|
class="rounded-lg bg-red-600 px-4 py-2 text-sm text-white transition-colors hover:bg-red-700 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{{ loading ? '删除中...' : '确认删除' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { getCurrentBrotherFeatureLabels } from '@/utils/tenantFeature'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
|
||||||
|
const featureLabels = getCurrentBrotherFeatureLabels()
|
||||||
|
const loading = ref(false)
|
||||||
|
const rows = ref([])
|
||||||
|
const total = ref(0)
|
||||||
|
const page = ref(1)
|
||||||
|
const pageSize = ref(20)
|
||||||
|
const totalPages = ref(0)
|
||||||
|
const showDeleteConfirm = ref(false)
|
||||||
|
const filters = reactive({
|
||||||
|
keyword: '',
|
||||||
|
region: '',
|
||||||
|
hostDisplayId: '',
|
||||||
|
displayId: '',
|
||||||
|
minLevel: undefined,
|
||||||
|
maxLevel: undefined,
|
||||||
|
minCoins: undefined,
|
||||||
|
maxCoins: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
function getTkBridge() {
|
||||||
|
return window?.electronAPI?.tk || null
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPayload() {
|
||||||
|
const nextFilters = {}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(filters)) {
|
||||||
|
if (value === '' || value === null || value === undefined) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFilters[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
page: page.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
filters: nextFilters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadData() {
|
||||||
|
const tkBridge = getTkBridge()
|
||||||
|
if (!tkBridge?.queryBrotherInfo) {
|
||||||
|
rows.value = []
|
||||||
|
total.value = 0
|
||||||
|
totalPages.value = 0
|
||||||
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}查询桥接,请重启客户端后再试`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const raw = await tkBridge.queryBrotherInfo(JSON.stringify(buildPayload()))
|
||||||
|
const result = typeof raw === 'string' ? JSON.parse(raw) : raw
|
||||||
|
|
||||||
|
if (result?.status !== 'success') {
|
||||||
|
throw new Error(result?.message || `查询${featureLabels.poolName}失败`)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.value = Array.isArray(result?.list) ? result.list : []
|
||||||
|
total.value = Number(result?.total || 0)
|
||||||
|
totalPages.value = Math.max(1, Number(result?.totalPages || 0))
|
||||||
|
page.value = Number(result?.page || page.value || 1)
|
||||||
|
} catch (error) {
|
||||||
|
rows.value = []
|
||||||
|
total.value = 0
|
||||||
|
totalPages.value = 0
|
||||||
|
ElMessage.error(error instanceof Error ? error.message : String(error))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDeleteAll() {
|
||||||
|
const tkBridge = getTkBridge()
|
||||||
|
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
||||||
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}删除桥接,请重启客户端后再试`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showDeleteConfirm.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function confirmDeleteAll() {
|
||||||
|
const tkBridge = getTkBridge()
|
||||||
|
if (!tkBridge?.getAllBrotherInfo || !tkBridge?.deleteBrotherInfo) {
|
||||||
|
showDeleteConfirm.value = false
|
||||||
|
ElMessage.error(`当前客户端未加载${featureLabels.poolName}删除桥接,请重启客户端后再试`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const rawList = await tkBridge.getAllBrotherInfo()
|
||||||
|
const listResult = typeof rawList === 'string' ? JSON.parse(rawList) : rawList
|
||||||
|
|
||||||
|
if (listResult?.status !== 'success') {
|
||||||
|
throw new Error(listResult?.message || `读取${featureLabels.poolName}失败`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ids = (Array.isArray(listResult?.list) ? listResult.list : [])
|
||||||
|
.map(item => Number(item?.id))
|
||||||
|
.filter(id => Number.isFinite(id))
|
||||||
|
|
||||||
|
if (ids.length === 0) {
|
||||||
|
showDeleteConfirm.value = false
|
||||||
|
ElMessage.success(`${featureLabels.poolName}已经是空的`)
|
||||||
|
rows.value = []
|
||||||
|
total.value = 0
|
||||||
|
totalPages.value = 1
|
||||||
|
page.value = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawDelete = await tkBridge.deleteBrotherInfo(JSON.stringify({ ids }))
|
||||||
|
const deleteResult = typeof rawDelete === 'string' ? JSON.parse(rawDelete) : rawDelete
|
||||||
|
|
||||||
|
if (deleteResult?.status !== 'success') {
|
||||||
|
throw new Error(deleteResult?.message || `删除${featureLabels.poolName}失败`)
|
||||||
|
}
|
||||||
|
|
||||||
|
ElMessage.success(`已删除 ${ids.length} 条${featureLabels.poolName}数据`)
|
||||||
|
showDeleteConfirm.value = false
|
||||||
|
page.value = 1
|
||||||
|
await loadData()
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error(error instanceof Error ? error.message : String(error))
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
page.value = 1
|
||||||
|
void loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleReset() {
|
||||||
|
filters.keyword = ''
|
||||||
|
filters.region = ''
|
||||||
|
filters.hostDisplayId = ''
|
||||||
|
filters.displayId = ''
|
||||||
|
filters.minLevel = undefined
|
||||||
|
filters.maxLevel = undefined
|
||||||
|
filters.minCoins = undefined
|
||||||
|
filters.maxCoins = undefined
|
||||||
|
page.value = 1
|
||||||
|
pageSize.value = 20
|
||||||
|
void loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
function goPrev() {
|
||||||
|
if (page.value <= 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
page.value -= 1
|
||||||
|
void loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function goNext() {
|
||||||
|
if (page.value >= totalPages.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
page.value += 1
|
||||||
|
void loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatNumber(value) {
|
||||||
|
if (value === null || value === undefined || value === '') {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const numericValue = Number(value)
|
||||||
|
return Number.isFinite(numericValue) ? numericValue.toLocaleString() : String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(value) {
|
||||||
|
const timestamp = Number(value)
|
||||||
|
if (!Number.isFinite(timestamp) || timestamp <= 0) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
if (Number.isNaN(date.getTime())) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hour = String(date.getHours()).padStart(2, '0')
|
||||||
|
const minute = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hour}:${minute}`
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (!visible) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadData()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(pageSize, () => {
|
||||||
|
if (!props.visible) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
page.value = 1
|
||||||
|
void loadData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -44,17 +44,17 @@
|
|||||||
<button @click="currentView = 'FanWorkbench'"
|
<button @click="currentView = 'FanWorkbench'"
|
||||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
||||||
:class="currentView === 'FanWorkbench' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'"
|
:class="currentView === 'FanWorkbench' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'"
|
||||||
title="大哥工作台">
|
:title="brotherFeatureLabels.workbenchName">
|
||||||
<img :src="currentView === 'FanWorkbench' ? nav44 : nav4" class="w-9 h-9 object-contain flex-shrink-0" />
|
<img :src="currentView === 'FanWorkbench' ? nav44 : nav4" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||||
<span class="menu-label">大哥工作台</span>
|
<span class="menu-label">大哥工作台</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button v-if="tenantId === '12384'" @click="currentView = 'expert_workbench'"
|
<button v-if="showExpertWorkbench" @click="currentView = 'expert_workbench'"
|
||||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200" style="height: 6vh;"
|
||||||
:class="currentView === 'expert_workbench' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'"
|
:class="currentView === 'expert_workbench' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'"
|
||||||
title="达人工作台">
|
:title="brotherFeatureLabels.workbenchName">
|
||||||
<img :src="currentView === 'expert_workbench' ? nav44 : nav4" class="w-9 h-9 object-contain flex-shrink-0" />
|
<img :src="currentView === 'expert_workbench' ? nav44 : nav4" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||||
<span class="menu-label">达人工作台</span>
|
<span class="menu-label">{{ brotherFeatureLabels.workbenchName }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button @click="currentView = 'pk_mini'"
|
<button @click="currentView = 'pk_mini'"
|
||||||
@@ -134,8 +134,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="currentView === 'expert_workbench'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden">
|
<div v-show="currentView === 'expert_workbench'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden">
|
||||||
<PermissionMask permission-key="crawl" title="达人工作台未开通" description="您当前没有使用达人工作台功能的权限"
|
<PermissionMask permission-key="crawl" :title="`${brotherFeatureLabels.workbenchName}未开通`"
|
||||||
:placeholder-image="placeholderHosts" :contacts="serviceContacts">
|
:description="`您当前没有使用${brotherFeatureLabels.workbenchName}功能的权限`" :placeholder-image="placeholderHosts"
|
||||||
|
:contacts="serviceContacts">
|
||||||
<ExpertWorkbench />
|
<ExpertWorkbench />
|
||||||
</PermissionMask>
|
</PermissionMask>
|
||||||
</div>
|
</div>
|
||||||
@@ -193,6 +194,7 @@ import placeholderWebAi from '@/assets/placeholder-webai.png'
|
|||||||
import placeholderBigBrother from '@/assets/placeholder-bigbrother.png'
|
import placeholderBigBrother from '@/assets/placeholder-bigbrother.png'
|
||||||
|
|
||||||
import { getUser } from '@/utils/storage';
|
import { getUser } from '@/utils/storage';
|
||||||
|
import { getBrotherFeatureLabels, isExpertPoolTenant } from '@/utils/tenantFeature'
|
||||||
const tenantId = ref('');
|
const tenantId = ref('');
|
||||||
|
|
||||||
const emit = defineEmits(['logout', 'go-back', 'stop-all'])
|
const emit = defineEmits(['logout', 'go-back', 'stop-all'])
|
||||||
@@ -205,6 +207,8 @@ const shopUrl = ENV.SHOP_URL
|
|||||||
const sidebarRef = useTemplateRef('sidebarRef')
|
const sidebarRef = useTemplateRef('sidebarRef')
|
||||||
const navSidebarWidth = ref(200)
|
const navSidebarWidth = ref(200)
|
||||||
const tkWorkbenchKey = ref(0)
|
const tkWorkbenchKey = ref(0)
|
||||||
|
const showExpertWorkbench = ref(false)
|
||||||
|
const brotherFeatureLabels = ref(getBrotherFeatureLabels(''))
|
||||||
|
|
||||||
const reloadTkWorkbench = () => {
|
const reloadTkWorkbench = () => {
|
||||||
tkWorkbenchKey.value++
|
tkWorkbenchKey.value++
|
||||||
@@ -243,6 +247,8 @@ onMounted(() => {
|
|||||||
loadServiceContacts()
|
loadServiceContacts()
|
||||||
|
|
||||||
tenantId.value = String(getUser()?.tenantId || '');
|
tenantId.value = String(getUser()?.tenantId || '');
|
||||||
|
showExpertWorkbench.value = isExpertPoolTenant(tenantId.value)
|
||||||
|
brotherFeatureLabels.value = getBrotherFeatureLabels(tenantId.value)
|
||||||
|
|
||||||
if (!isElectron()) return
|
if (!isElectron()) return
|
||||||
resizeObserver = new ResizeObserver((entries) => {
|
resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
|||||||
27
src/utils/tenantFeature.js
Normal file
27
src/utils/tenantFeature.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { getUser } from '@/utils/storage'
|
||||||
|
|
||||||
|
const EXPERT_POOL_TENANT_IDS = new Set(['12384'])
|
||||||
|
|
||||||
|
export function getCurrentTenantId() {
|
||||||
|
return String(getUser()?.tenantId || '')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isExpertPoolTenant(tenantId) {
|
||||||
|
return EXPERT_POOL_TENANT_IDS.has(String(tenantId || ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBrotherFeatureLabels(tenantId) {
|
||||||
|
const expertTenant = isExpertPoolTenant(tenantId)
|
||||||
|
|
||||||
|
return {
|
||||||
|
expertTenant,
|
||||||
|
poolName: expertTenant ? '达人池' : '大哥池',
|
||||||
|
workbenchName: expertTenant ? '达人工作台' : '大哥工作台',
|
||||||
|
roleName: expertTenant ? '达人' : '大哥',
|
||||||
|
roleIdLabel: expertTenant ? '达人ID' : '大哥ID',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentBrotherFeatureLabels() {
|
||||||
|
return getBrotherFeatureLabels(getCurrentTenantId())
|
||||||
|
}
|
||||||
@@ -140,7 +140,7 @@
|
|||||||
:class="configForm.dataPoolSource === 'brother_info' ? 'border-purple-500 bg-purple-50 text-purple-700' : 'border-gray-200 bg-gray-50 text-gray-700'">
|
:class="configForm.dataPoolSource === 'brother_info' ? 'border-purple-500 bg-purple-50 text-purple-700' : 'border-gray-200 bg-gray-50 text-gray-700'">
|
||||||
<input v-model="configForm.dataPoolSource" :disabled="isConfigControlDisabled" type="radio"
|
<input v-model="configForm.dataPoolSource" :disabled="isConfigControlDisabled" type="radio"
|
||||||
value="brother_info" class="h-4 w-4 border-gray-300 text-purple-600 focus:ring-purple-500" />
|
value="brother_info" class="h-4 w-4 border-gray-300 text-purple-600 focus:ring-purple-500" />
|
||||||
<span>大哥池</span>
|
<span>{{ brotherFeatureLabels.poolName }}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-if="isBrotherInfoMode" class="mt-4">
|
<!-- <div v-if="isBrotherInfoMode" class="mt-4">
|
||||||
@@ -218,14 +218,14 @@
|
|||||||
<section class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
|
<section class="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
|
||||||
<div class="flex items-start justify-between gap-3">
|
<div class="flex items-start justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="text-sm font-medium text-gray-900">大哥池</div>
|
<div class="text-sm font-medium text-gray-900">{{ brotherFeatureLabels.poolName }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
:class="['rounded-full px-3 py-1 text-xs font-medium', isBrotherInfoMode ? 'bg-fuchsia-100 text-fuchsia-700' : 'bg-gray-100 text-gray-600']">{{
|
:class="['rounded-full px-3 py-1 text-xs font-medium', isBrotherInfoMode ? 'bg-fuchsia-100 text-fuchsia-700' : 'bg-gray-100 text-gray-600']">{{
|
||||||
isBrotherInfoMode ? '当前使用中' : '可切换' }}</span>
|
isBrotherInfoMode ? '当前使用中' : '可切换' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button @click="showBrotherInfoDialog = true"
|
<button @click="showBrotherInfoDialog = true"
|
||||||
class="mt-4 w-full rounded-lg border border-fuchsia-200 bg-fuchsia-50 px-4 py-3 text-sm font-medium text-fuchsia-600 transition-colors hover:bg-fuchsia-100">打开大哥池</button>
|
class="mt-4 w-full rounded-lg border border-fuchsia-200 bg-fuchsia-50 px-4 py-3 text-sm font-medium text-fuchsia-600 transition-colors hover:bg-fuchsia-100">打开{{ brotherFeatureLabels.poolName }}</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- <section class="rounded-xl bg-slate-950 p-5 shadow-sm">
|
<!-- <section class="rounded-xl bg-slate-950 p-5 shadow-sm">
|
||||||
@@ -317,7 +317,7 @@
|
|||||||
<AIConfigDialog :visible="showAIDialog" :config="aiConfig" @close="showAIDialog = false" @save="handleSaveAIConfig"
|
<AIConfigDialog :visible="showAIDialog" :config="aiConfig" @close="showAIDialog = false" @save="handleSaveAIConfig"
|
||||||
@change="(key, value) => aiConfig[key] = value" />
|
@change="(key, value) => aiConfig[key] = value" />
|
||||||
<HostListDialog :visible="showHostDialog" @close="showHostDialog = false" @save="() => { }" />
|
<HostListDialog :visible="showHostDialog" @close="showHostDialog = false" @save="() => { }" />
|
||||||
<BrotherInfoDialog :visible="showBrotherInfoDialog" @close="showBrotherInfoDialog = false" />
|
<TenantBrotherInfoDialog :visible="showBrotherInfoDialog" @close="showBrotherInfoDialog = false" />
|
||||||
<GreetingDialog :visible="showGreetingDialog" @close="showGreetingDialog = false"
|
<GreetingDialog :visible="showGreetingDialog" @close="showGreetingDialog = false"
|
||||||
@confirm="handleGreetingConfirm" />
|
@confirm="handleGreetingConfirm" />
|
||||||
</div>
|
</div>
|
||||||
@@ -327,11 +327,12 @@
|
|||||||
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { isElectron } from '@/utils/electronBridge'
|
import { isElectron } from '@/utils/electronBridge'
|
||||||
|
import { getCurrentBrotherFeatureLabels } from '@/utils/tenantFeature'
|
||||||
import ViewPlaceholder from '@/components/ViewPlaceholder.vue'
|
import ViewPlaceholder from '@/components/ViewPlaceholder.vue'
|
||||||
import HostListDialog from '@/components/HostListDialog.vue'
|
import HostListDialog from '@/components/HostListDialog.vue'
|
||||||
import AIConfigDialog from '@/components/AIConfigDialog.vue'
|
import AIConfigDialog from '@/components/AIConfigDialog.vue'
|
||||||
import GreetingDialog from '@/components/GreetingDialog.vue'
|
import GreetingDialog from '@/components/GreetingDialog.vue'
|
||||||
import BrotherInfoDialog from '@/components/BrotherInfoDialog.vue'
|
import TenantBrotherInfoDialog from '@/components/TenantBrotherInfoDialog.vue'
|
||||||
|
|
||||||
const props = defineProps({ navSidebarWidth: { type: Number, default: 144 } })
|
const props = defineProps({ navSidebarWidth: { type: Number, default: 144 } })
|
||||||
const TIKTOK_VIEW_IDS = Array.from({ length: 9 }, (_, index) => index + 10)
|
const TIKTOK_VIEW_IDS = Array.from({ length: 9 }, (_, index) => index + 10)
|
||||||
@@ -366,7 +367,8 @@ const replyMessageCount = computed(() => replyMessages.value.length)
|
|||||||
const languageCount = computed(() => Object.keys(configForm.prologueList || {}).length)
|
const languageCount = computed(() => Object.keys(configForm.prologueList || {}).length)
|
||||||
const isBrotherInfoMode = computed(() => configForm.dataPoolSource === 'brother_info')
|
const isBrotherInfoMode = computed(() => configForm.dataPoolSource === 'brother_info')
|
||||||
const effectiveReplyUnreadMessages = computed(() => !isBrotherInfoMode.value && Boolean(configForm.replyUnreadMessages))
|
const effectiveReplyUnreadMessages = computed(() => !isBrotherInfoMode.value && Boolean(configForm.replyUnreadMessages))
|
||||||
const dataPoolLabel = computed(() => (isBrotherInfoMode.value ? '大哥池' : '主播池'))
|
const brotherFeatureLabels = getCurrentBrotherFeatureLabels()
|
||||||
|
const dataPoolLabel = computed(() => (isBrotherInfoMode.value ? brotherFeatureLabels.poolName : '主播池'))
|
||||||
const normalizedGroupSwitchMinutes = computed(() => clampMinutes(configForm.groupSwitchMinutes))
|
const normalizedGroupSwitchMinutes = computed(() => clampMinutes(configForm.groupSwitchMinutes))
|
||||||
const normalizedGroupViewCounts = computed(() => normalizeGroupViewCounts(configForm.groupViewCounts))
|
const normalizedGroupViewCounts = computed(() => normalizeGroupViewCounts(configForm.groupViewCounts))
|
||||||
const effectiveInitialFullGroupNumber = computed(() => resolveInitialFullGroupNumber(configForm.initialFullGroupNumber, normalizedGroupViewCounts.value))
|
const effectiveInitialFullGroupNumber = computed(() => resolveInitialFullGroupNumber(configForm.initialFullGroupNumber, normalizedGroupViewCounts.value))
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ import { getCountryName } from "@/utils/countryUtil";
|
|||||||
import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
|
import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useCountryInfo } from '@/composables/useCountryInfo';
|
import { useCountryInfo } from '@/composables/useCountryInfo';
|
||||||
|
import { isExpertPoolTenant } from '@/utils/tenantFeature';
|
||||||
|
|
||||||
// Mock API calls if not present
|
// Mock API calls if not present
|
||||||
// Ideally we should import these from api file, but for simplicity I will mock them or use empty callbacks
|
// Ideally we should import these from api file, but for simplicity I will mock them or use empty callbacks
|
||||||
@@ -488,7 +489,7 @@ function stopTimerfun() {
|
|||||||
// Specify Room Logic
|
// Specify Room Logic
|
||||||
// 动态计算最大行数限制:tenantId=12741 为 5000 条,其他为 50 条
|
// 动态计算最大行数限制:tenantId=12741 为 5000 条,其他为 50 条
|
||||||
const maxSpecifyLines = computed(() => {
|
const maxSpecifyLines = computed(() => {
|
||||||
return userInfo.value.tenantId == 12384 || userInfo.value.tenantId == 12741 ? 5000 : 50;
|
return isExpertPoolTenant(userInfo.value.tenantId) || userInfo.value.tenantId == 12741 ? 5000 : 50;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 当前行数
|
// 当前行数
|
||||||
|
|||||||
Reference in New Issue
Block a user