frontend去ai化

This commit is contained in:
2026-04-20 16:02:50 +08:00
parent bba6de25ac
commit a039b957d0
15 changed files with 15 additions and 109 deletions
-1
View File
@@ -5,7 +5,6 @@
<link rel="icon" href="/favicon.svg"> <link rel="icon" href="/favicon.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聚势智见 - 基于语义聚类与大模型的热点资讯聚合平台</title> <title>聚势智见 - 基于语义聚类与大模型的热点资讯聚合平台</title>
<!-- Font Awesome 图标库 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head> </head>
<body> <body>
-6
View File
@@ -6,9 +6,6 @@ export function fetchDeliveryConfig(userId: number): Promise<DeliveryConfig> {
return apiGet<DeliveryConfig>(`/users/${userId}/delivery-config`) return apiGet<DeliveryConfig>(`/users/${userId}/delivery-config`)
} }
// ==========================================
// 推送时间表
// ==========================================
export function createDeliverySchedule( export function createDeliverySchedule(
userId: number, userId: number,
payload: { delivery_time: string; is_active?: boolean }, payload: { delivery_time: string; is_active?: boolean },
@@ -34,9 +31,6 @@ export function deleteDeliverySchedule(
return apiDelete(`/users/${userId}/delivery-schedules/${scheduleId}`) return apiDelete(`/users/${userId}/delivery-schedules/${scheduleId}`)
} }
// ==========================================
// 推送渠道
// ==========================================
export function createPushEndpoint( export function createPushEndpoint(
userId: number, userId: number,
payload: { payload: {
-3
View File
@@ -1,6 +1,3 @@
/**
* 认证 API:登录、注册、发送验证码(不走通用 client,无 Bearer
*/
import type { import type {
AuthTokenResponse, AuthTokenResponse,
LoginPayload, LoginPayload,
+2
View File
@@ -1,3 +1,5 @@
// AI辅助生成:deepseek-v3-22026年3月20日
export interface UserProfile { export interface UserProfile {
id: number id: number
email: string email: string
+1
View File
@@ -1,3 +1,4 @@
<!-- AI辅助生成deepseek-v3-22026年3月20日 -->
<!-- 仪表盘布局侧边栏导航主内容区移动端抽屉 --> <!-- 仪表盘布局侧边栏导航主内容区移动端抽屉 -->
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
+1 -3
View File
@@ -1,6 +1,4 @@
/** // AI辅助生成:deepseek-v3-22026年3月20日
* 应用入口:初始化 Vue、Pinia、路由、主题
*/
import './assets/main.css' import './assets/main.css'
import { createApp } from 'vue' import { createApp } from 'vue'
+2
View File
@@ -1,3 +1,5 @@
<!-- AI辅助生成deepseek-v3-22026年3月20日 -->
<!-- 关于页占位 --> <!-- 关于页占位 -->
<template> <template>
<div class="about"> <div class="about">
+2 -49
View File
@@ -1,4 +1,3 @@
<!-- 主仪表盘事件流为你推荐公关修改追踪系统状态 -->
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, computed, watch } from 'vue' import { onMounted, ref, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
@@ -13,9 +12,6 @@ import type { MatchedEvent, UserTopicPreference } from '@/types/preference'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
// ==========================================
// 聚光灯:从推荐页跳转过来时,按 ID 单独拉取目标事件
// ==========================================
const spotlightEvent = ref<UnifiedEvent | null>(null) const spotlightEvent = ref<UnifiedEvent | null>(null)
const loadingSpotlight = ref(false) const loadingSpotlight = ref(false)
@@ -41,9 +37,7 @@ function dismissSpotlight() {
const authStore = useAuthStore() const authStore = useAuthStore()
const userId = computed(() => authStore.user?.id ?? 0) const userId = computed(() => authStore.user?.id ?? 0)
// ==========================================
// 状态
// ==========================================
const events = ref<UnifiedEvent[]>([]) const events = ref<UnifiedEvent[]>([])
const revisions = ref<HeadlineRevision[]>([]) const revisions = ref<HeadlineRevision[]>([])
const stats = ref<SystemStats | null>(null) const stats = ref<SystemStats | null>(null)
@@ -101,9 +95,6 @@ const recSortOptions = [
{ label: '最新', value: 'created_at' }, { label: '最新', value: 'created_at' },
] ]
// ==========================================
// 平台视觉映射
// ==========================================
const platformIconMap: Record<string, string> = { const platformIconMap: Record<string, string> = {
微博热搜: 'fa-brands fa-weibo', 微博热搜: 'fa-brands fa-weibo',
微博: 'fa-brands fa-weibo', 微博: 'fa-brands fa-weibo',
@@ -171,9 +162,7 @@ function formatRelativeTime(dateStr: string): string {
return `${days} 天前` return `${days} 天前`
} }
// ==========================================
// 排名图表配置
// ==========================================
function getRankingChartOptions(history: number[], platformColor: string) { function getRankingChartOptions(history: number[], platformColor: string) {
return { return {
series: [{ name: '排名', data: history }], series: [{ name: '排名', data: history }],
@@ -249,9 +238,6 @@ function platformKey(eventId: number, index: number, prefix: string = ''): strin
return prefix ? `${prefix}-${eventId}-${index}` : `${eventId}-${index}` return prefix ? `${prefix}-${eventId}-${index}` : `${eventId}-${index}`
} }
// ==========================================
// 数据加载
// ==========================================
async function loadEvents(append = false) { async function loadEvents(append = false) {
if (!append) { if (!append) {
loading.value = true loading.value = true
@@ -681,9 +667,6 @@ watch(() => route.query.event, (newId) => {
</template> </template>
</div> </div>
<!-- ==========================================
右侧:小组件面板
========================================== -->
<div class="widgets-column"> <div class="widgets-column">
<!-- 为你推荐(基于用户关键词的匹配) --> <!-- 为你推荐(基于用户关键词的匹配) -->
@@ -897,9 +880,6 @@ watch(() => route.query.event, (newId) => {
margin-top: 6px; margin-top: 6px;
} }
/* ==========================================
网格布局
========================================== */
.content-grid { .content-grid {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -931,9 +911,6 @@ watch(() => route.query.event, (newId) => {
} }
} }
/* ==========================================
区域标题 + 热度阈值 (高级磨砂透明风)
========================================== */
.section-header { .section-header {
margin-bottom: 24px; margin-bottom: 24px;
} }
@@ -1023,9 +1000,6 @@ watch(() => route.query.event, (newId) => {
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
} }
/* ==========================================
事件卡片
========================================== */
/* 事件卡片,加入毛玻璃与高级阴影 */ /* 事件卡片,加入毛玻璃与高级阴影 */
.event-card { .event-card {
background: var(--bg-surface); background: var(--bg-surface);
@@ -1142,9 +1116,6 @@ watch(() => route.query.event, (newId) => {
color: transparent; color: transparent;
} }
/* ==========================================
平台列表 + 悬停排名图
========================================== */
.platforms-list { .platforms-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -1262,9 +1233,6 @@ watch(() => route.query.event, (newId) => {
max-height: 120px; max-height: 120px;
} }
/* ==========================================
加载更多
========================================== */
.load-more-wrapper { .load-more-wrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -1310,9 +1278,6 @@ watch(() => route.query.event, (newId) => {
color: var(--text-placeholder); color: var(--text-placeholder);
} }
/* ==========================================
小组件面板(通用)- 玻璃拟态高级质感
========================================== */
.widget-panel { .widget-panel {
background: var(--bg-surface); background: var(--bg-surface);
backdrop-filter: var(--backdrop-blur); backdrop-filter: var(--backdrop-blur);
@@ -1406,9 +1371,6 @@ watch(() => route.query.event, (newId) => {
font-size: 13px; font-size: 13px;
} }
/* ==========================================
为你推荐面板
========================================== */
.recommend-header { .recommend-header {
background: rgba(139, 92, 246, 0.06); background: rgba(139, 92, 246, 0.06);
border-bottom-color: rgba(139, 92, 246, 0.15); border-bottom-color: rgba(139, 92, 246, 0.15);
@@ -1584,9 +1546,6 @@ watch(() => route.query.event, (newId) => {
font-size: 9px; font-size: 9px;
} }
/* ==========================================
公关修改追踪
========================================== */
.revision-header { .revision-header {
background: rgba(239, 68, 68, 0.06); background: rgba(239, 68, 68, 0.06);
border-bottom-color: rgba(239, 68, 68, 0.15); border-bottom-color: rgba(239, 68, 68, 0.15);
@@ -1687,9 +1646,6 @@ watch(() => route.query.event, (newId) => {
margin: 0; margin: 0;
} }
/* ==========================================
系统状态
========================================== */
.stats-widget { .stats-widget {
padding: 16px; padding: 16px;
} }
@@ -1759,9 +1715,6 @@ watch(() => route.query.event, (newId) => {
color: var(--status-error); color: var(--status-error);
} }
/* ==========================================
聚光灯区块
========================================== */
.spotlight-wrap { .spotlight-wrap {
margin-bottom: 20px; margin-bottom: 20px;
} }
-28
View File
@@ -1,4 +1,3 @@
<!-- 推送设置页管理推送时间表与推送渠道邮箱等 -->
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, computed } from 'vue' import { onMounted, ref, computed } from 'vue'
@@ -62,9 +61,6 @@ async function loadConfig() {
} }
} }
// ==========================================
// 推送时间表操作
// ==========================================
async function handleAddSchedule() { async function handleAddSchedule() {
if (!userId.value || !newTime.value) return if (!userId.value || !newTime.value) return
submittingSchedule.value = true submittingSchedule.value = true
@@ -109,9 +105,6 @@ async function handleDeleteSchedule(schedule: DeliverySchedule) {
} }
} }
// ==========================================
// 推送渠道操作
// ==========================================
async function handleAddEndpoint() { async function handleAddEndpoint() {
if (!userId.value || !newChannelAccount.value.trim()) return if (!userId.value || !newChannelAccount.value.trim()) return
submittingEndpoint.value = true submittingEndpoint.value = true
@@ -186,9 +179,6 @@ onMounted(loadConfig)
</div> </div>
<div v-else class="config-sections"> <div v-else class="config-sections">
<!-- ==========================================
推送时间管理
========================================== -->
<section class="config-section"> <section class="config-section">
<div class="section-title"> <div class="section-title">
<h2><i class="fa-regular fa-clock"></i> 推送时间</h2> <h2><i class="fa-regular fa-clock"></i> 推送时间</h2>
@@ -229,9 +219,6 @@ onMounted(loadConfig)
</div> </div>
</section> </section>
<!-- ==========================================
推送渠道管理
========================================== -->
<section class="config-section"> <section class="config-section">
<div class="section-title"> <div class="section-title">
<h2><i class="fa-solid fa-envelope"></i> 接收邮箱</h2> <h2><i class="fa-solid fa-envelope"></i> 接收邮箱</h2>
@@ -374,9 +361,6 @@ onMounted(loadConfig)
color: var(--text-secondary); color: var(--text-secondary);
} }
/* ==========================================
通用区块样式
========================================== */
.config-sections { .config-sections {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -418,9 +402,6 @@ onMounted(loadConfig)
margin: 0; margin: 0;
} }
/* ==========================================
添加行
========================================== */
.add-row { .add-row {
display: flex; display: flex;
gap: 10px; gap: 10px;
@@ -497,9 +478,6 @@ onMounted(loadConfig)
font-size: 13px; font-size: 13px;
} }
/* ==========================================
时间表列表
========================================== */
.schedule-list { .schedule-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -573,9 +551,6 @@ onMounted(loadConfig)
background: rgba(239, 68, 68, 0.1); background: rgba(239, 68, 68, 0.1);
} }
/* ==========================================
渠道列表
========================================== */
.endpoint-add { .endpoint-add {
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -661,9 +636,6 @@ onMounted(loadConfig)
gap: 6px; gap: 6px;
} }
/* ==========================================
工作原理说明
========================================== */
.info-section { .info-section {
background: transparent; background: transparent;
border: 1px dashed var(--border-subtle); border: 1px dashed var(--border-subtle);
-1
View File
@@ -1,4 +1,3 @@
<!-- 概览页展示当前账户会话状态认证接入说明 -->
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
+3 -7
View File
@@ -1,4 +1,3 @@
<!-- 登录页支持密码登录与邮箱验证码登录 -->
<script setup lang="ts"> <script setup lang="ts">
import { computed, onUnmounted, reactive, ref, watch } from 'vue' import { computed, onUnmounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
@@ -156,7 +155,7 @@ onUnmounted(() => {
<p class="brand-desc"> <p class="brand-desc">
聚合多平台趋势自动完成热点归并与摘要你可以用密码登录也可以直接使用邮箱验证码快速登录 聚合多平台趋势自动完成热点归并与摘要你可以用密码登录也可以直接使用邮箱验证码快速登录
</p> </p>
<div class="feature-list"> <div class="feature-list">
<div class="feature-item"> <div class="feature-item">
<div class="feature-icon">🚀</div> <div class="feature-icon">🚀</div>
@@ -287,7 +286,7 @@ onUnmounted(() => {
<button class="btn-primary" :disabled="authStore.loading" type="submit"> <button class="btn-primary" :disabled="authStore.loading" type="submit">
{{ isSubmitting ? '登录中...' : (loginMode === 'password' ? '密码登录' : '邮箱验证码登录') }} {{ isSubmitting ? '登录中...' : (loginMode === 'password' ? '密码登录' : '邮箱验证码登录') }}
</button> </button>
<button type="button" class="btn-primary guest-btn" @click="router.push('/')" style="margin-top: 12px; background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-subtle);"> <button type="button" class="btn-primary guest-btn" @click="router.push('/')" style="margin-top: 12px; background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-subtle);">
以游客身份体验 以游客身份体验
</button> </button>
@@ -303,9 +302,6 @@ onUnmounted(() => {
</template> </template>
<style scoped> <style scoped>
/* ==========================================
全新高级分屏布局与背景
========================================== */
.split-layout { .split-layout {
display: flex; display: flex;
min-height: 100vh; min-height: 100vh;
@@ -330,7 +326,7 @@ onUnmounted(() => {
left: -50%; left: -50%;
right: -50%; right: -50%;
bottom: -50%; bottom: -50%;
background-image: background-image:
linear-gradient(rgba(128, 128, 128, 0.15) 1px, transparent 1px), linear-gradient(rgba(128, 128, 128, 0.15) 1px, transparent 1px),
linear-gradient(90deg, rgba(128, 128, 128, 0.15) 1px, transparent 1px); linear-gradient(90deg, rgba(128, 128, 128, 0.15) 1px, transparent 1px);
background-size: 32px 32px; background-size: 32px 32px;
+1 -5
View File
@@ -1,4 +1,3 @@
<!-- 注册页邮箱验证码 + 密码带密码强度提示 -->
<script setup lang="ts"> <script setup lang="ts">
import { computed, onUnmounted, reactive, ref } from 'vue' import { computed, onUnmounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@@ -280,9 +279,6 @@ onUnmounted(() => {
</template> </template>
<style scoped> <style scoped>
/* ==========================================
全新高级分屏布局与背景
========================================== */
.split-layout { .split-layout {
display: flex; display: flex;
min-height: 100vh; min-height: 100vh;
@@ -306,7 +302,7 @@ onUnmounted(() => {
content: ""; content: "";
position: absolute; position: absolute;
top: -50%; left: -50%; right: -50%; bottom: -50%; top: -50%; left: -50%; right: -50%; bottom: -50%;
background-image: background-image:
linear-gradient(rgba(128, 128, 128, 0.15) 1px, transparent 1px), linear-gradient(rgba(128, 128, 128, 0.15) 1px, transparent 1px),
linear-gradient(90deg, rgba(128, 128, 128, 0.15) 1px, transparent 1px); linear-gradient(90deg, rgba(128, 128, 128, 0.15) 1px, transparent 1px);
background-size: 32px 32px; background-size: 32px 32px;
-1
View File
@@ -1,4 +1,3 @@
<!-- 公关修改追踪页展示热搜标题被偷偷修改的历史记录 -->
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, reactive } from 'vue' import { computed, onMounted, ref, reactive } from 'vue'
+1 -2
View File
@@ -1,4 +1,3 @@
<!-- 事件追踪分析页关键词搜索时间热度图表关联事件列表 -->
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import VueApexCharts from 'vue3-apexcharts' import VueApexCharts from 'vue3-apexcharts'
@@ -621,7 +620,7 @@ async function handleSearch() {
.chart-container { .chart-container {
margin-top: 16px; margin-top: 16px;
margin-left: -10px; margin-left: -10px;
} }
.chart-container :deep(svg), .chart-container :deep(svg),
+2 -3
View File
@@ -1,4 +1,3 @@
<!-- 兴趣关键词页添加/删除关键词查看命中事件 -->
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, computed } from 'vue' import { onMounted, ref, computed } from 'vue'
@@ -64,10 +63,10 @@ async function loadMatchedEvents() {
loadingMatched.value = true loadingMatched.value = true
matchedError.value = '' matchedError.value = ''
try { try {
const result = await fetchRecommendedEvents(userId.value, { const result = await fetchRecommendedEvents(userId.value, {
limit: 30, limit: 30,
hours: hoursRange.value, hours: hoursRange.value,
sort_by: sortBy.value sort_by: sortBy.value
}) })
matchedEvents.value = result.data matchedEvents.value = result.data
} catch (e) { } catch (e) {