feat: 玩家黑名单 - 记录外部平台坑玩家
- 新增 player_blacklist collection 迁移 - 添加 PlayerTag/PlayerBlacklistEntry 类型定义和 API - 创建 PlayerBlacklistMain + CreatePlayerBlacklistDialog 组件 - BlacklistView 支持 Tab 切换游戏/玩家黑名单 - 支持搜索、标签筛选、严重程度筛选、实时订阅 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { createPlayerBlacklistEntry } from '@/api/playerBlacklist'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { PlayerTagMap, BlacklistSeverityMap } from '@/types'
|
||||
import type { PlayerTag, BlacklistSeverity } from '@/types'
|
||||
|
||||
const visible = defineModel<boolean>({ default: false })
|
||||
|
||||
const emit = defineEmits<{
|
||||
created: []
|
||||
}>()
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
|
||||
const form = ref({
|
||||
playerId: '',
|
||||
platform: '',
|
||||
tags: [] as PlayerTag[],
|
||||
customTag: '',
|
||||
severity: '' as BlacklistSeverity | '',
|
||||
description: '',
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
function resetForm() {
|
||||
form.value = {
|
||||
playerId: '',
|
||||
platform: '',
|
||||
tags: [],
|
||||
customTag: '',
|
||||
severity: '',
|
||||
description: '',
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!form.value.playerId.trim()) {
|
||||
ElMessage.warning('请输入玩家ID')
|
||||
return
|
||||
}
|
||||
if (!form.value.platform.trim()) {
|
||||
ElMessage.warning('请输入游戏/平台')
|
||||
return
|
||||
}
|
||||
if (form.value.tags.length === 0) {
|
||||
ElMessage.warning('请至少选择一个标签')
|
||||
return
|
||||
}
|
||||
if (!form.value.severity) {
|
||||
ElMessage.warning('请选择严重程度')
|
||||
return
|
||||
}
|
||||
if (!form.value.description.trim()) {
|
||||
ElMessage.warning('请填写描述')
|
||||
return
|
||||
}
|
||||
|
||||
const groupId = groupStore.currentGroupId
|
||||
if (!groupId) {
|
||||
ElMessage.error('请先选择群组')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
await createPlayerBlacklistEntry({
|
||||
group: groupId,
|
||||
playerId: form.value.playerId.trim(),
|
||||
platform: form.value.platform.trim(),
|
||||
tags: form.value.tags,
|
||||
customTag: form.value.customTag.trim() || undefined,
|
||||
description: form.value.description.trim(),
|
||||
severity: form.value.severity,
|
||||
})
|
||||
|
||||
visible.value = false
|
||||
resetForm()
|
||||
ElMessage.success('标记成功')
|
||||
emit('created')
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.message || '标记失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpen() {
|
||||
resetForm()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="标记坑玩家"
|
||||
width="460px"
|
||||
@open="handleOpen"
|
||||
>
|
||||
<div class="create-form">
|
||||
<div class="form-field">
|
||||
<label>玩家ID <span class="required">*</span></label>
|
||||
<el-input
|
||||
v-model="form.playerId"
|
||||
placeholder="输入玩家的游戏内ID或昵称"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>游戏/平台 <span class="required">*</span></label>
|
||||
<el-input
|
||||
v-model="form.platform"
|
||||
placeholder="如:英雄联盟、Steam、绝地求生"
|
||||
maxlength="100"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>标签 <span class="required">*</span></label>
|
||||
<el-checkbox-group v-model="form.tags">
|
||||
<el-checkbox
|
||||
v-for="(label, key) in PlayerTagMap"
|
||||
:key="key"
|
||||
:value="key"
|
||||
:label="label"
|
||||
/>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>自定义标签</label>
|
||||
<el-input
|
||||
v-model="form.customTag"
|
||||
placeholder="补充标签(选填)"
|
||||
maxlength="50"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>严重程度 <span class="required">*</span></label>
|
||||
<el-select v-model="form.severity" placeholder="选择严重程度" style="width: 100%">
|
||||
<el-option
|
||||
v-for="(label, key) in BlacklistSeverityMap"
|
||||
:key="key"
|
||||
:label="label"
|
||||
:value="key"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label>描述 <span class="required">*</span></label>
|
||||
<el-input
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
placeholder="描述一下遇到的情况"
|
||||
:rows="3"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<button class="submit-btn" :disabled="loading" @click="handleSubmit">
|
||||
{{ loading ? '提交中...' : '提交' }}
|
||||
</button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.create-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.form-field label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--gg-text);
|
||||
}
|
||||
|
||||
.required {
|
||||
color: var(--gg-danger);
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
padding: 8px 20px;
|
||||
border: none;
|
||||
border-radius: var(--gg-radius-sm);
|
||||
background: var(--gg-primary);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.submit-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user