This commit is contained in:
Your Name
2026-04-16 21:35:47 +08:00
parent ff32aa50bf
commit ebf632e651
86 changed files with 14097 additions and 585 deletions

View File

@@ -0,0 +1,114 @@
<template>
<PageCard title="敏感词配置" description="对齐旧桌面版主功能,支持加载、编辑、导入、导出和整库保存。">
<el-alert
:title="`当前共 ${total} 个敏感词`"
type="info"
:closable="false"
show-icon
style="margin-bottom: 16px"
/>
<el-input
v-model="text"
type="textarea"
:rows="22"
placeholder="请输入敏感词,一行一个"
style="margin-bottom: 16px"
/>
<div class="actions">
<el-button @click="triggerImport">导入</el-button>
<el-button @click="exportWords">导出</el-button>
<el-button @click="loadWords">加载</el-button>
<el-button type="primary" :loading="saving" @click="saveWords">保存</el-button>
<input ref="fileInput" type="file" accept=".txt,text/plain" class="hidden-input" @change="handleImport" />
</div>
</PageCard>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { ElMessage } from "element-plus";
import PageCard from "@/components/PageCard.vue";
import { sensitiveWordsApi } from "@/api/modules";
const text = ref("");
const total = ref(0);
const saving = ref(false);
const fileInput = ref<HTMLInputElement | null>(null);
const normalizeText = (value: string) =>
value
.split(/\r?\n/)
.map((item) => item.trim())
.filter(Boolean)
.join("\n");
const loadWords = async () => {
try {
const response = await sensitiveWordsApi.get();
text.value = response.data?.text || "";
total.value = Number(response.data?.total || 0);
} catch (error: any) {
ElMessage.error(error?.message || "加载敏感词失败");
}
};
const saveWords = async () => {
saving.value = true;
try {
const response = await sensitiveWordsApi.save({ text: normalizeText(text.value) });
text.value = response.data?.text || normalizeText(text.value);
total.value = Number(response.data?.total || 0);
ElMessage.success(response.message || "敏感词已保存");
} catch (error: any) {
ElMessage.error(error?.message || "保存敏感词失败");
} finally {
saving.value = false;
}
};
const triggerImport = () => {
fileInput.value?.click();
};
const handleImport = async (event: Event) => {
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
if (!file) return;
text.value = normalizeText(await file.text());
total.value = text.value ? text.value.split("\n").length : 0;
ElMessage.success(`已导入 ${total.value} 个敏感词`);
input.value = "";
};
const exportWords = () => {
const content = normalizeText(text.value);
if (!content) {
ElMessage.warning("没有敏感词可导出");
return;
}
const blob = new Blob([`${content}\n`], { type: "text/plain;charset=utf-8" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "sensitive_words.txt";
link.click();
window.URL.revokeObjectURL(url);
ElMessage.success("敏感词已导出");
};
onMounted(loadWords);
</script>
<style scoped>
.actions {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.hidden-input {
display: none;
}
</style>