refactor: 清理废弃模块并重构管理端与全端代码

- 移除所有废弃的旧首页配置模块,包括destinationHero、demand相关、HomeExperience、vehicleService等表结构与代码,新增数据库迁移删除遗留表
- 重构管理端后台布局为标准RuoYi风格,新增Sidebar、Navbar、SettingsDrawer等组件,替换旧的过渡菜单实现
- 调整移动端响应断点为768px,更新布局相关测试用例,新增布局组件测试
- 删除OperationsTools发布/重置页面,移除/tools菜单入口,清理对应的API调用与测试代码
- 重构玩法模块编辑器:替换旧的图片手动输入框为图片上传组件,移除冗余的取消按钮
- 新增线索查询offset参数支持,完善查询参数处理逻辑
- 优化rbac菜单构建逻辑,新增可见性控制参数
- 修正管家编辑器提示文案,优化系统资源编辑器表单初始化逻辑
- 清理小程序端废弃的体验推荐组件与相关测试代码
- 更新文档与种子脚本,匹配新的API契约与使用说明
This commit is contained in:
duanshuwen committed 2026-08-26 23:24:28 +08:00
1 parent f6c5ad589f
commit fbf2c772a8
63 files changed
+2272 -1991

No files matched your search

@@ -1,35 +0,0 @@
<template>
<view
class="w-full bg-[#fffdf9] pt-[18px] tap-feedback min-[431px]:pt-[22px]"
:aria-label="`${item.title},${item.category}`"
@click="$emit('select', item)"
>
<view class="flex items-start justify-between gap-4 pr-[18px] min-[431px]:pr-[22px]">
<view class="min-w-0 flex-1">
<view class="flex min-h-5 items-center gap-[10px]">
<text class="inline-flex min-h-5 items-center rounded-[12px] border border-[#eadfce] bg-[#f8f1e8] px-[6px] text-[10px] leading-[18px] tracking-[0.06em] text-[#98744b]">{{ item.badge }}</text>
<text class="text-[13px] font-semibold leading-5 text-[#283b4d]">{{ item.category }}</text>
</view>
<text class="mt-[10px] block whitespace-pre-line font-serif text-[25px] font-medium leading-8 tracking-[0.04em] text-[#18212a]">{{ item.title }}</text>
<text class="mt-0.5 block font-sans text-[11px] font-medium leading-[18px] tracking-[0.22em] text-[#a7a0a0]">{{ item.englishTitle }}</text>
</view>
<view class="mt-8 flex h-10 w-6 shrink-0 items-center justify-center" aria-hidden="true">
<uni-icons type="right" :size="24" color="#c8c8c8" />
</view>
</view>
<image class="mt-[17px] block h-[174px] w-full rounded-[12px] bg-[#eae7e1] min-[431px]:h-[190px]" :src="item.image" mode="aspectFill" />
</view>
</template>
<script setup lang="ts">
import type { HomeExperience } from "./homeExperienceData";
defineProps<{
item: HomeExperience;
}>();
defineEmits<{
select: [item: HomeExperience];
}>();
</script>
@@ -1,23 +0,0 @@
<template>
<view class="bg-[#fffdf9] px-[8.5%] pb-[26px]">
<HomeExperienceCard
v-for="item in items"
:key="item.id"
:item="item"
@select="$emit('select', $event)"
/>
</view>
</template>
<script setup lang="ts">
import HomeExperienceCard from "./HomeExperienceCard.vue";
import type { HomeExperience } from "./homeExperienceData";
defineProps<{
items: HomeExperience[];
}>();
defineEmits<{
select: [item: HomeExperience];
}>();
</script>
@@ -1,78 +0,0 @@
export type HomeExperience = {
id: string;
badge: string;
category: string;
title: string;
englishTitle: string;
image: string;
demandKeyword: string;
};
export type HomeExperienceApiItem = {
id?: string | null;
badge?: string | null;
category?: string | null;
title?: string | null;
englishTitle?: string | null;
image?: string | null;
demandKeyword?: string | null;
isActive?: boolean | null;
sortOrder?: number | null;
};
export type HomeExperiences = HomeExperienceApiItem[];
export const homeExperienceMocks: HomeExperience[] = [
{
id: "waterfall-descent",
badge: "玩过推荐",
category: "瀑降体验",
title: "悬崖瀑降",
englishTitle: "WATERFALL DESCENT",
image: "https://genk.mediacdn.vn/139269124445442048/2024/4/27/10-23-sinkhole-1714189653945948438879.jpg",
demandKeyword: "悬崖瀑降",
},
{
id: "cave-exploration",
badge: "玩过推荐",
category: "地心探险",
title: "森林&探洞",
englishTitle: "CAVE EXPLORATION",
image: "https://www.zurnal24.si/media/img/5e/d5/9526a56dba168aa136f3.jpeg",
demandKeyword: "地心探险",
},
];
export const homeExperienceFallback = homeExperienceMocks;
export function normalizeHomeExperiences(
items: HomeExperiences | null | undefined,
): HomeExperience[] {
const fallback = homeExperienceFallback.map((item) => ({ ...item }));
const activeItems = (items ?? [])
.map((item, index) => ({ item, index }))
.filter(({ item }) => item.isActive !== false && Boolean(item.title?.trim()))
.sort(
(left, right) =>
(left.item.sortOrder ?? left.index) - (right.item.sortOrder ?? right.index),
);
if (activeItems.length === 0) {
return fallback;
}
return activeItems.map(({ item }, index) => {
const fallbackItem = homeExperienceFallback[index] ?? homeExperienceFallback[0];
const title = item.title?.trim() || fallbackItem.title;
return {
id: item.id?.trim() || fallbackItem.id,
badge: item.badge?.trim() || fallbackItem.badge,
category: item.category?.trim() || fallbackItem.category,
title,
englishTitle: item.englishTitle?.trim() || fallbackItem.englishTitle,
image: item.image?.trim() || fallbackItem.image,
demandKeyword: item.demandKeyword?.trim() || title,
};
});
}