678 lines
22 KiB
Vue
678 lines
22 KiB
Vue
<!-- Author: fruit.com.cn -->
|
||
|
||
<script setup>
|
||
import { onMounted, reactive, ref } from 'vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import PageHeading from '@/views/components/PageHeading.vue'
|
||
import { useRbac } from '@/stores/rbac'
|
||
import { dateCell } from '@/utils/format'
|
||
import {
|
||
auditCommentApi,
|
||
createSensitiveWordApi,
|
||
deleteCommentApi,
|
||
deleteSensitiveWordApi,
|
||
handleReportApi,
|
||
pageCommentsApi,
|
||
pageReportsApi,
|
||
pageSensitiveWordsApi,
|
||
updateSensitiveWordApi
|
||
} from '@/api/admin/governance'
|
||
|
||
const { can } = useRbac()
|
||
const canCommentAudit = can('comment:audit')
|
||
const canReportHandle = can('report:handle')
|
||
const canWordUpdate = can('sensitive-word:update')
|
||
|
||
const activeTab = ref('comments')
|
||
|
||
const COMMENT_STATUS = [
|
||
{ value: '', label: '全部状态', tag: 'info' },
|
||
{ value: 'pending', label: '待审核', tag: 'warning' },
|
||
{ value: 'published', label: '已发布', tag: 'success' },
|
||
{ value: 'rejected', label: '已驳回', tag: 'danger' },
|
||
{ value: 'deleted', label: '已删除', tag: 'info' }
|
||
]
|
||
const REPORT_STATUS = [
|
||
{ value: '', label: '全部状态', tag: 'info' },
|
||
{ value: 'pending', label: '待处理', tag: 'warning' },
|
||
{ value: 'handled', label: '已处理', tag: 'success' },
|
||
{ value: 'rejected', label: '已驳回', tag: 'info' }
|
||
]
|
||
const REPORT_TARGET_TYPES = {
|
||
COMMENT: { label: '评论', tag: 'warning' },
|
||
USER: { label: '用户', tag: 'success' },
|
||
DRAMA: { label: '短剧', tag: 'info' }
|
||
}
|
||
const WORD_LEVELS = [
|
||
{ value: 'BLOCK', label: '禁止发布' },
|
||
{ value: 'REVIEW', label: '转人工审核' },
|
||
{ value: 'REPLACE', label: '替换后放行' }
|
||
]
|
||
|
||
function meta(list, value) {
|
||
return list.find((item) => item.value === value) || { label: value || '-', tag: 'info' }
|
||
}
|
||
function levelText(level) {
|
||
return WORD_LEVELS.find((item) => item.value === level)?.label || level
|
||
}
|
||
function commentEpisodeText(row) {
|
||
if (row.episodeNo) return `第 ${row.episodeNo} 集`
|
||
return row.episodeId ? `分集 #${row.episodeId}` : '未关联分集'
|
||
}
|
||
function commentContentTooltip(row) {
|
||
return `短剧 ID:${row.dramaId} / 分集 ID:${row.episodeId || '未关联'}`
|
||
}
|
||
function reportTargetMeta(type) {
|
||
return REPORT_TARGET_TYPES[type] || { label: type || '-', tag: 'info' }
|
||
}
|
||
function reportTargetSummary(row) {
|
||
return row.targetSummary || `${reportTargetMeta(row.targetType).label} #${row.targetId}`
|
||
}
|
||
function reporterText(row) {
|
||
return row.reporterNickname || row.reporterUid || `#${row.reporterId}`
|
||
}
|
||
|
||
const comments = reactive({
|
||
rows: [],
|
||
total: 0,
|
||
loading: false,
|
||
page: 1,
|
||
size: 10,
|
||
status: '',
|
||
keyword: ''
|
||
})
|
||
async function loadComments() {
|
||
comments.loading = true
|
||
try {
|
||
const res = await pageCommentsApi({
|
||
pageIndex: comments.page,
|
||
pageSize: comments.size,
|
||
status: comments.status || undefined,
|
||
keyword: comments.keyword.trim() || undefined
|
||
})
|
||
comments.rows = res.data?.list || []
|
||
comments.total = res.data?.total || 0
|
||
} finally {
|
||
comments.loading = false
|
||
}
|
||
}
|
||
function queryComments() {
|
||
comments.page = 1
|
||
loadComments()
|
||
}
|
||
async function auditComment(row, result) {
|
||
if (result === 'REJECT') {
|
||
let reason = ''
|
||
try {
|
||
const { value } = await ElMessageBox.prompt('请填写驳回原因(会进入审核留证)', '驳回评论', {
|
||
confirmButtonText: '确认驳回',
|
||
cancelButtonText: '取消',
|
||
inputValidator: (val) => (val && val.trim() ? true : '驳回原因不能为空')
|
||
})
|
||
reason = value
|
||
} catch {
|
||
return
|
||
}
|
||
await auditCommentApi(row.id, {
|
||
result: 'REJECT',
|
||
reasonText: reason.trim(),
|
||
reasonCode: 'VIOLATION'
|
||
})
|
||
} else {
|
||
await auditCommentApi(row.id, { result: 'PASS' })
|
||
}
|
||
ElMessage.success(result === 'PASS' ? '评论已通过' : '评论已驳回')
|
||
await loadComments()
|
||
}
|
||
async function removeComment(row) {
|
||
try {
|
||
await ElMessageBox.confirm('删除后该评论对用户不可见,确认删除?', '删除评论', {
|
||
confirmButtonText: '确认删除',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
confirmButtonClass: 'el-button--danger'
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
await deleteCommentApi(row.id)
|
||
ElMessage.success('评论已删除')
|
||
await loadComments()
|
||
}
|
||
|
||
const reports = reactive({
|
||
rows: [],
|
||
total: 0,
|
||
loading: false,
|
||
page: 1,
|
||
size: 10,
|
||
status: ''
|
||
})
|
||
async function loadReports() {
|
||
reports.loading = true
|
||
try {
|
||
const res = await pageReportsApi({
|
||
pageIndex: reports.page,
|
||
pageSize: reports.size,
|
||
status: reports.status || undefined
|
||
})
|
||
reports.rows = res.data?.list || []
|
||
reports.total = res.data?.total || 0
|
||
} finally {
|
||
reports.loading = false
|
||
}
|
||
}
|
||
function queryReports() {
|
||
reports.page = 1
|
||
loadReports()
|
||
}
|
||
const handleVisible = ref(false)
|
||
const handleSaving = ref(false)
|
||
const handleTarget = ref(null)
|
||
const handleForm = reactive({ status: 'handled', note: '', banTarget: false })
|
||
function openHandle(row) {
|
||
handleTarget.value = row
|
||
handleForm.status = 'handled'
|
||
handleForm.note = ''
|
||
handleForm.banTarget = false
|
||
handleVisible.value = true
|
||
}
|
||
async function confirmHandle() {
|
||
const row = handleTarget.value
|
||
if (!row) return
|
||
if (handleForm.status === 'handled' && !handleForm.note.trim()) {
|
||
return ElMessage.warning('结论成立时请填写处理说明')
|
||
}
|
||
handleSaving.value = true
|
||
try {
|
||
await handleReportApi(row.id, {
|
||
status: handleForm.status,
|
||
note: handleForm.note.trim(),
|
||
banTarget: handleForm.banTarget,
|
||
banReason: handleForm.note.trim()
|
||
})
|
||
ElMessage.success(handleForm.status === 'handled' ? '工单已处理' : '工单已驳回')
|
||
handleVisible.value = false
|
||
await loadReports()
|
||
} finally {
|
||
handleSaving.value = false
|
||
}
|
||
}
|
||
|
||
const words = reactive({
|
||
rows: [],
|
||
total: 0,
|
||
loading: false,
|
||
page: 1,
|
||
size: 10,
|
||
keyword: '',
|
||
level: undefined
|
||
})
|
||
async function loadWords() {
|
||
words.loading = true
|
||
try {
|
||
const res = await pageSensitiveWordsApi({
|
||
pageIndex: words.page,
|
||
pageSize: words.size,
|
||
keyword: words.keyword.trim() || undefined,
|
||
level: words.level || undefined
|
||
})
|
||
words.rows = res.data?.list || []
|
||
words.total = res.data?.total || 0
|
||
} finally {
|
||
words.loading = false
|
||
}
|
||
}
|
||
function queryWords() {
|
||
words.page = 1
|
||
loadWords()
|
||
}
|
||
const wordVisible = ref(false)
|
||
const wordSaving = ref(false)
|
||
const wordEditingId = ref(null)
|
||
const wordForm = reactive({
|
||
word: '',
|
||
category: '',
|
||
level: 'REVIEW',
|
||
replaceText: '*',
|
||
language: 'id-ID',
|
||
status: 1
|
||
})
|
||
function openWord(row) {
|
||
wordEditingId.value = row?.id ?? null
|
||
Object.assign(wordForm, {
|
||
word: row?.word ?? '',
|
||
category: row?.category ?? '',
|
||
level: row?.level ?? 'REVIEW',
|
||
replaceText: row?.replaceText ?? '*',
|
||
language: row?.language ?? 'id-ID',
|
||
status: row?.status ?? 1
|
||
})
|
||
wordVisible.value = true
|
||
}
|
||
async function saveWord() {
|
||
if (!wordForm.word.trim()) return ElMessage.warning('请输入敏感词')
|
||
wordSaving.value = true
|
||
try {
|
||
const payload = { ...wordForm, word: wordForm.word.trim() }
|
||
if (wordEditingId.value) {
|
||
await updateSensitiveWordApi(wordEditingId.value, payload)
|
||
} else {
|
||
await createSensitiveWordApi(payload)
|
||
}
|
||
ElMessage.success('已保存,词库即时生效')
|
||
wordVisible.value = false
|
||
await loadWords()
|
||
} finally {
|
||
wordSaving.value = false
|
||
}
|
||
}
|
||
async function removeWord(row) {
|
||
try {
|
||
await ElMessageBox.confirm(`确认从词库删除「${row.word}」?`, '删除敏感词', {
|
||
confirmButtonText: '确认删除',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
confirmButtonClass: 'el-button--danger'
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
await deleteSensitiveWordApi(row.id)
|
||
ElMessage.success('已删除')
|
||
await loadWords()
|
||
}
|
||
|
||
const tabLoaded = {}
|
||
onMounted(() => {
|
||
loadComments()
|
||
tabLoaded.comments = true
|
||
})
|
||
function onTabChange(name) {
|
||
if (tabLoaded[name]) return
|
||
tabLoaded[name] = true
|
||
if (name === 'reports') loadReports()
|
||
if (name === 'words') loadWords()
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<PageHeading
|
||
eyebrow="内容治理"
|
||
title="评论与举报"
|
||
description="审核评论、处理举报工单、维护敏感词库。"
|
||
/>
|
||
|
||
<section class="panel">
|
||
<el-tabs v-model="activeTab" @tab-change="onTabChange">
|
||
<el-tab-pane label="评论审核" name="comments">
|
||
<div class="console-toolbar">
|
||
<el-input
|
||
v-model="comments.keyword"
|
||
class="console-keyword"
|
||
clearable
|
||
placeholder="搜索评论内容"
|
||
@keyup.enter="queryComments"
|
||
@clear="queryComments"
|
||
/>
|
||
<el-select
|
||
v-model="comments.status"
|
||
class="console-select"
|
||
clearable
|
||
placeholder="全部状态"
|
||
@change="queryComments"
|
||
>
|
||
<el-option
|
||
v-for="item in COMMENT_STATUS"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
<el-button type="primary" @click="queryComments">查询</el-button>
|
||
<span class="console-count">共 {{ comments.total }} 条</span>
|
||
</div>
|
||
<el-table
|
||
v-loading="comments.loading"
|
||
:data="comments.rows"
|
||
row-key="id"
|
||
border
|
||
class="drama-el-table"
|
||
empty-text="没有符合条件的评论"
|
||
>
|
||
<el-table-column prop="id" label="ID" width="80" />
|
||
<el-table-column prop="nickname" label="用户" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="content" label="内容" min-width="220" show-overflow-tooltip />
|
||
<el-table-column label="短剧 / 分集" min-width="190">
|
||
<template #default="{ row }">
|
||
<el-tooltip :content="commentContentTooltip(row)" placement="top">
|
||
<div class="episode-table-title">
|
||
<b>{{ row.dramaTitle || `短剧 #${row.dramaId}` }}</b>
|
||
<small>{{ commentEpisodeText(row) }}</small>
|
||
<small v-if="row.episodeTitle">{{ row.episodeTitle }}</small>
|
||
</div>
|
||
</el-tooltip>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" width="100">
|
||
<template #default="{ row }">
|
||
<el-tag :type="meta(COMMENT_STATUS, row.status).tag" effect="light">{{
|
||
meta(COMMENT_STATUS, row.status).label
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="likeCount" label="点赞" width="80" />
|
||
<el-table-column prop="replyCount" label="回复" width="80" />
|
||
<el-table-column prop="reportCount" label="举报" width="80" />
|
||
<el-table-column
|
||
prop="createdAt"
|
||
label="时间"
|
||
min-width="165"
|
||
show-overflow-tooltip
|
||
:formatter="dateCell"
|
||
/>
|
||
<el-table-column label="操作" width="230" fixed="right">
|
||
<template #default="{ row }">
|
||
<div class="table-actions">
|
||
<el-button
|
||
v-if="canCommentAudit"
|
||
type="primary"
|
||
size="small"
|
||
@click="auditComment(row, 'PASS')"
|
||
>通过</el-button
|
||
>
|
||
<el-button v-if="canCommentAudit" size="small" @click="auditComment(row, 'REJECT')"
|
||
>驳回</el-button
|
||
>
|
||
<el-button
|
||
v-if="canCommentAudit"
|
||
type="danger"
|
||
size="small"
|
||
@click="removeComment(row)"
|
||
>删除</el-button
|
||
>
|
||
<el-button v-if="!canCommentAudit" size="small" disabled>只读</el-button>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="comments.page"
|
||
v-model:page-size="comments.size"
|
||
:page-sizes="[10, 20, 50]"
|
||
:total="comments.total"
|
||
layout="total, prev, pager, next, sizes"
|
||
background
|
||
@current-change="loadComments"
|
||
@size-change="queryComments"
|
||
/>
|
||
</div>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="举报工单" name="reports">
|
||
<div class="console-toolbar">
|
||
<el-select
|
||
v-model="reports.status"
|
||
class="console-select"
|
||
clearable
|
||
placeholder="全部状态"
|
||
@change="queryReports"
|
||
>
|
||
<el-option
|
||
v-for="item in REPORT_STATUS"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
<el-button type="primary" @click="queryReports">查询</el-button>
|
||
<span class="console-count">共 {{ reports.total }} 条</span>
|
||
</div>
|
||
<el-table
|
||
v-loading="reports.loading"
|
||
:data="reports.rows"
|
||
row-key="id"
|
||
border
|
||
class="drama-el-table"
|
||
empty-text="没有符合条件的工单"
|
||
>
|
||
<el-table-column prop="id" label="工单ID" width="90" />
|
||
<el-table-column label="对象" min-width="240">
|
||
<template #default="{ row }">
|
||
<el-tooltip placement="top">
|
||
<template #content>
|
||
<div>原始对象:#{{ row.targetId }}</div>
|
||
<div v-if="row.commentContent">评论内容:{{ row.commentContent }}</div>
|
||
</template>
|
||
<div class="episode-table-title">
|
||
<el-tag :type="reportTargetMeta(row.targetType).tag" size="small" effect="light">
|
||
{{ reportTargetMeta(row.targetType).label }}
|
||
</el-tag>
|
||
<b>{{ reportTargetSummary(row) }}</b>
|
||
</div>
|
||
</el-tooltip>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="reasonCode" label="原因码" width="120" />
|
||
<el-table-column
|
||
prop="description"
|
||
label="补充说明"
|
||
min-width="180"
|
||
show-overflow-tooltip
|
||
/>
|
||
<el-table-column label="举报人" min-width="140" show-overflow-tooltip>
|
||
<template #default="{ row }">{{ reporterText(row) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="状态" width="100">
|
||
<template #default="{ row }">
|
||
<el-tag :type="meta(REPORT_STATUS, row.status).tag" effect="light">{{
|
||
meta(REPORT_STATUS, row.status).label
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="createdAt"
|
||
label="时间"
|
||
min-width="165"
|
||
show-overflow-tooltip
|
||
:formatter="dateCell"
|
||
/>
|
||
<el-table-column label="操作" width="130" fixed="right">
|
||
<template #default="{ row }">
|
||
<div class="table-actions">
|
||
<el-button
|
||
v-if="canReportHandle && row.status === 'pending'"
|
||
type="primary"
|
||
size="small"
|
||
@click="openHandle(row)"
|
||
>处理</el-button
|
||
>
|
||
<span v-else class="console-muted">{{
|
||
row.status === 'pending' ? '只读' : '已处理'
|
||
}}</span>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="reports.page"
|
||
v-model:page-size="reports.size"
|
||
:page-sizes="[10, 20, 50]"
|
||
:total="reports.total"
|
||
layout="total, prev, pager, next, sizes"
|
||
background
|
||
@current-change="loadReports"
|
||
@size-change="queryReports"
|
||
/>
|
||
</div>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="敏感词库" name="words">
|
||
<div class="console-toolbar">
|
||
<el-input
|
||
v-model="words.keyword"
|
||
class="console-keyword"
|
||
clearable
|
||
placeholder="搜索敏感词"
|
||
@keyup.enter="queryWords"
|
||
@clear="queryWords"
|
||
/>
|
||
<el-select
|
||
v-model="words.level"
|
||
class="console-select"
|
||
clearable
|
||
placeholder="全部级别"
|
||
@change="queryWords"
|
||
>
|
||
<el-option
|
||
v-for="item in WORD_LEVELS"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
<el-button type="primary" @click="queryWords">查询</el-button>
|
||
<el-button v-if="canWordUpdate" type="primary" @click="openWord(null)"
|
||
>新增敏感词</el-button
|
||
>
|
||
<span class="console-count">共 {{ words.total }} 个词</span>
|
||
</div>
|
||
<el-table
|
||
v-loading="words.loading"
|
||
:data="words.rows"
|
||
row-key="id"
|
||
border
|
||
class="drama-el-table"
|
||
empty-text="词库为空"
|
||
>
|
||
<el-table-column prop="word" label="敏感词" min-width="160" show-overflow-tooltip />
|
||
<el-table-column prop="category" label="分类" width="120" />
|
||
<el-table-column label="处置级别" width="140">
|
||
<template #default="{ row }">{{ levelText(row.level) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="replaceText" label="替换为" width="100" />
|
||
<el-table-column prop="language" label="语言" width="100" />
|
||
<el-table-column label="启用" width="90">
|
||
<template #default="{ row }">
|
||
<el-tag :type="row.status === 1 ? 'success' : 'info'" effect="light">{{
|
||
row.status === 1 ? '启用' : '停用'
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="150" fixed="right">
|
||
<template #default="{ row }">
|
||
<div class="table-actions">
|
||
<el-button v-if="canWordUpdate" type="primary" size="small" @click="openWord(row)"
|
||
>编辑</el-button
|
||
>
|
||
<el-button v-if="canWordUpdate" type="danger" size="small" @click="removeWord(row)"
|
||
>删除</el-button
|
||
>
|
||
<span v-if="!canWordUpdate" class="console-muted">只读</span>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="words.page"
|
||
v-model:page-size="words.size"
|
||
:page-sizes="[10, 20, 50]"
|
||
:total="words.total"
|
||
layout="total, prev, pager, next, sizes"
|
||
background
|
||
@current-change="loadWords"
|
||
@size-change="queryWords"
|
||
/>
|
||
</div>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</section>
|
||
|
||
<el-dialog v-model="handleVisible" title="处理举报工单" width="480px">
|
||
<el-form label-position="top">
|
||
<el-form-item label="工单对象">
|
||
<div v-if="handleTarget" class="episode-table-title">
|
||
<el-tag :type="reportTargetMeta(handleTarget.targetType).tag" size="small" effect="light">
|
||
{{ reportTargetMeta(handleTarget.targetType).label }}
|
||
</el-tag>
|
||
<b>{{ reportTargetSummary(handleTarget) }}</b>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="处理结论">
|
||
<el-radio-group v-model="handleForm.status">
|
||
<el-radio label="handled">举报成立</el-radio>
|
||
<el-radio label="rejected">举报不成立</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="处理说明">
|
||
<el-input
|
||
v-model="handleForm.note"
|
||
type="textarea"
|
||
:rows="3"
|
||
maxlength="200"
|
||
show-word-limit
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item v-if="handleForm.status === 'handled'">
|
||
<el-checkbox v-model="handleForm.banTarget">同时封禁被举报用户</el-checkbox>
|
||
</el-form-item>
|
||
<el-alert
|
||
v-if="handleForm.status === 'handled'"
|
||
type="warning"
|
||
:closable="false"
|
||
show-icon
|
||
title="结论成立会联动驳回被举报评论;勾选封禁会立即使该用户所有会话失效"
|
||
/>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="handleVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="handleSaving" @click="confirmHandle">提交</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<el-dialog
|
||
v-model="wordVisible"
|
||
:title="wordEditingId ? '编辑敏感词' : '新增敏感词'"
|
||
width="460px"
|
||
>
|
||
<el-form label-position="top">
|
||
<el-form-item label="敏感词" required>
|
||
<el-input v-model="wordForm.word" maxlength="64" placeholder="例如:赌博" />
|
||
</el-form-item>
|
||
<el-form-item label="分类">
|
||
<el-input
|
||
v-model="wordForm.category"
|
||
maxlength="32"
|
||
placeholder="例如:AD / PORN / ABUSE"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="处置级别">
|
||
<el-select v-model="wordForm.level" class="console-full">
|
||
<el-option
|
||
v-for="item in WORD_LEVELS"
|
||
:key="item.value"
|
||
:label="item.label"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item v-if="wordForm.level === 'REPLACE'" label="替换为">
|
||
<el-input v-model="wordForm.replaceText" maxlength="16" />
|
||
</el-form-item>
|
||
<el-form-item label="语言">
|
||
<el-input v-model="wordForm.language" maxlength="16" placeholder="id-ID" />
|
||
</el-form-item>
|
||
<el-form-item label="启用">
|
||
<el-switch v-model="wordForm.status" :active-value="1" :inactive-value="0" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="wordVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="wordSaving" @click="saveWord">保存</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|