Files
ai-dimension/admin/src/views/Trends.vue
T

102 lines
5.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="page">
<div class="toolbar">
<el-input v-model="q" placeholder="搜索标题" style="width: 220px" clearable @keyup.enter="search" />
<el-button type="primary" @click="search">搜索</el-button>
<el-button type="success" @click="openEdit(null)">新增资讯</el-button>
</div>
<el-table :data="list" stripe v-loading="loading">
<el-table-column label="标题" min-width="220" show-overflow-tooltip>
<template #default="{ row }">
{{ row.title }}
<el-tag v-if="row.hot" type="danger" size="small" style="margin-left:4px">热</el-tag>
<el-tag v-if="row.picked" type="warning" size="small" style="margin-left:4px">精</el-tag>
</template>
</el-table-column>
<el-table-column prop="category" label="分类" width="80" />
<el-table-column prop="source" label="来源" width="110" show-overflow-tooltip />
<el-table-column label="人话解读" min-width="170" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row.plainExplain">{{ row.plainExplain }}<template v-if="row.takeAway"> | {{ row.takeAway }}</template></span>
<el-tag v-else type="info" size="small">待补</el-tag>
</template>
</el-table-column>
<el-table-column label="日期" width="110">
<template #default="{ row }">{{ (row.newsDate || row.createdAt || '').slice(0, 10) }}</template>
</el-table-column>
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button size="small" @click="openEdit(row)">编辑</el-button>
<el-button size="small" type="danger" @click="del(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination background layout="total, prev, pager, next" :total="total" :page-size="pageSize" v-model:current-page="page" @current-change="load" style="margin-top: 12px" />
<el-dialog v-model="dlg" :title="form._id ? '编辑资讯' : '新增资讯'" width="min(560px, 94%)" style="max-width: 560px">
<el-form label-width="76px">
<el-form-item label="标题"><el-input v-model="form.title" /></el-form-item>
<el-form-item label="摘要"><el-input v-model="form.summary" type="textarea" :rows="2" /></el-form-item>
<el-form-item label="来源/链接">
<el-input v-model="form.source" style="width: 140px" />
<el-input v-model="form.sourceUrl" placeholder="原文链接(选填)" style="flex:1; margin-left:8px" />
</el-form-item>
<el-form-item label="人话解读"><el-input v-model="form.plainExplain" placeholder="一句大白话说清(30字内)" /></el-form-item>
<el-form-item label="对你"><el-input v-model="form.takeAway" placeholder="对普通人意味着什么(30字内)" /></el-form-item>
<el-form-item label="分类">
<el-select v-model="form.category" style="width: 130px"><el-option v-for="c in ['产品','论文','工具','公司','政策','其他']" :key="c" :label="c" :value="c" /></el-select>
<el-switch v-model="form.hot" active-text="热门" style="margin-left: 16px" />
<el-switch v-model="form.picked" active-text="精选" style="margin-left: 12px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dlg = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { apiGet, apiPost, apiPut, apiDelete } from '../api'
const list = ref([]), total = ref(0), page = ref(1), pageSize = 20, q = ref(''), loading = ref(false)
const dlg = ref(false)
const form = ref({})
function search() { page.value = 1; load() }
async function load() {
loading.value = true
try {
const r = await apiGet(`/api/admin/trends?page=${page.value}&limit=${pageSize}&keyword=${encodeURIComponent(q.value)}`)
list.value = r.items || []
total.value = r.pagination?.total || 0
} finally { loading.value = false }
}
function openEdit(row) {
form.value = row ? { ...row } : { title: '', summary: '', source: '', sourceUrl: '', category: '产品', hot: false, picked: false, plainExplain: '', takeAway: '' }
dlg.value = true
}
async function save() {
if (!form.value.title) return ElMessage.warning('标题必填')
try {
if (form.value._id) await apiPut(`/api/admin/trends/${form.value._id}`, form.value)
else await apiPost('/api/admin/trends', form.value)
ElMessage.success('已保存')
dlg.value = false
load()
} catch (e) { ElMessage.error(e.message || '保存失败') }
}
async function del(row) {
await ElMessageBox.confirm(`删除「${row.title}」?`, '确认', { type: 'warning' })
try { await apiDelete(`/api/admin/trends/${row._id}`); ElMessage.success('已删除'); load() }
catch (e) { ElMessage.error(e.message || '删除失败') }
}
onMounted(load)
</script>
<style scoped>
.page { background: #fff; border-radius: 12px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,.06); }
.toolbar { display: flex; gap: 8px; margin-bottom: 12px; }
</style>