1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-09-13 00:50:40 +08:00

chore: 批量新增项目依赖、工具函数、页面与组件资源

1. 新增mp-html、qs等生产依赖,补全项目基础库
2. 新增平台判断、缓存、工具函数等通用工具集
3. 新增标签页、网站浏览页、关于页等业务页面
4. 新增分类卡片、通知弹窗等业务组件
5. 新增uts-progressNotification、liu-poster、uhalo-upgrade等uni模块
6. 补充audio/video组件样式补件,修复uni-components路径缺失问题
7. 新增环境变量Halo个人令牌配置项
8. 重构store导出结构,新增appConfig/halo/setting三个状态模块
9. 新增tsconfig编译目标配置,适配更高版本ES语法
This commit is contained in:
小莫唐尼
2026-08-31 19:56:16 +08:00
parent ba5b77568b
commit 067f3ed98a
147 changed files with 20866 additions and 325 deletions
+283
View File
@@ -0,0 +1,283 @@
<script lang="ts" setup>
/**
* 数据看板页(源自旧项目 pagesA/data-visual,新建复刻)
* 标签统计/分类统计(环形图)、文章发布趋势(热度图)、评论活跃用户(柱状图)、热门文章 Top10(柱状图)
*/
import { ref } from 'vue'
import { onPullDownRefresh } from '@dcloudio/uni-app'
import { getChartData } from '@/api/uni-halo'
import { usePluginAvailable } from '@/utils/plugin'
import type { IDataStatistics } from '@/api/uni-halo'
definePage({
style: {
navigationBarTitleText: '数据看板',
enablePullDownRefresh: true,
},
})
/** 依赖插件(plugin-data-statistics) */
const uniHaloPluginId = 'plugin-data-statistics'
const uniHaloPluginAvailable = ref(true)
/* ---------------- 状态 ---------------- */
const loading = ref<'loading' | 'success' | 'error'>('loading')
const statistics = ref<IDataStatistics>({
tags: [],
categories: [],
articles: [],
comments: [],
top10Articles: [],
})
/* ---------------- 图表配置 ---------------- */
const chartColors = ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#EC4899', '#14B8A6', '#F97316', '#ea7ccc', '#0EA5E9']
/** 标签统计(环形图) */
const tagChart = ref({
isExpand: true,
type: 'ring',
data: { series: [{ data: [] as { name: string, value: number }[] }] },
})
/** 分类统计(柱状图) */
const categoryChart = ref({
isExpand: true,
type: 'column',
data: { categories: [] as string[], series: [{ name: '分类', data: [] as number[] }] },
})
/** 文章发布趋势(热度图) */
const trandArticleChart = ref({
isExpand: true,
type: 'hotmap',
data: [] as { date: string, count: number }[],
})
/** 评论活跃用户(柱状图) */
const userCommentsChart = ref({
isExpand: true,
type: 'column',
data: { categories: [] as string[], series: [{ name: '评论', data: [] as number[] }] },
})
/** 热门文章 Top10(柱状图) */
const top10ArticlesChart = ref({
isExpand: true,
type: 'column',
data: { categories: [] as string[], series: [{ name: '访问量', data: [] as number[] }] },
})
/* ---------------- 数据处理 ---------------- */
function handleTagChart() {
const data = [...statistics.value.tags].sort((a, b) => b.count - a.count)
tagChart.value.data = {
series: [
{
data: data.map(item => ({ name: item.name, value: item.count })),
},
],
}
}
function handleCategoriesChart() {
const data = [...statistics.value.categories].sort((a, b) => b.total - a.total)
categoryChart.value.data = {
categories: data.map(item => item.name),
series: [{ name: '分类', data: data.map(item => item.total) }],
}
}
function handleTrendArticlesChart() {
trandArticleChart.value.data = statistics.value.articles.map(item => ({
date: item.date,
count: item.count,
}))
}
function handleUserCommentsChart() {
const data = [...statistics.value.comments].sort((a, b) => b.count - a.count).slice(0, 10)
userCommentsChart.value.data = {
categories: data.map(item => item.username),
series: [{ name: '评论', data: data.map(item => item.count) }],
}
}
function handleTop10ArticlesChart() {
const data = [...statistics.value.top10Articles].sort((a, b) => b.views - a.views).slice(0, 10)
top10ArticlesChart.value.data = {
categories: data.map(item => item.name),
series: [{ name: '访问量', data: data.map(item => item.views) }],
}
}
/* ---------------- 数据加载 ---------------- */
async function handleGetData() {
uni.showLoading({ mask: true, title: '加载中...' })
loading.value = 'loading'
try {
const res = await getChartData()
statistics.value = res.data
handleTagChart()
handleCategoriesChart()
handleTrendArticlesChart()
handleUserCommentsChart()
handleTop10ArticlesChart()
loading.value = 'success'
}
catch (err) {
console.error(err)
loading.value = 'error'
}
finally {
setTimeout(() => {
uni.hideLoading()
uni.stopPullDownRefresh()
}, 100)
}
}
/* ---------------- 生命周期 ---------------- */
async function init() {
uniHaloPluginAvailable.value = await usePluginAvailable(uniHaloPluginId)
if (!uniHaloPluginAvailable.value) {
uni.stopPullDownRefresh()
return
}
handleGetData()
}
onPullDownRefresh(() => {
if (!uniHaloPluginAvailable.value) {
uni.stopPullDownRefresh()
return
}
handleGetData()
})
init()
</script>
<template>
<view class="app-page box-border min-h-screen w-screen p-6 text-[#353437]" style="background-color: #fafafd;">
<uh-plugin-unavailable
v-if="!uniHaloPluginAvailable"
:plugin-id="uniHaloPluginId"
error-text="阿偶检测到当前插件没有安装或者启用无法使用功能哦请联系管理员"
@on-refresh="handleGetData"
/>
<template v-else>
<!-- 加载/错误 -->
<view v-if="loading === 'loading'" class="loading-wrap p-3">
<wd-skeleton :row="4" :animated="true" />
</view>
<view v-else-if="loading === 'error'" class="h-[60vh] flex items-center justify-center content-empty">
<wd-empty description="加载异常" />
</view>
<!-- 内容区域 -->
<view v-else class="content flex flex-col gap-6">
<!-- 标签统计 -->
<view class="card box-border rounded-xl bg-white/95 p-6" style="box-shadow: 0 0 12rpx rgb(226 232 240 / 35%);">
<view class="card-head flex items-center justify-between" @click="tagChart.isExpand = !tagChart.isExpand">
<view class="card-head-title flex items-baseline gap-2">
<text class="card-head-text relative box-border pl-6 text-[30rpx] font-bold">标签统计</text>
<text class="card-head-subtext text-[26rpx] text-[#6b7280] font-normal">全部标签的文章数量占比</text>
</view>
<wd-icon :name="tagChart.isExpand ? 'arrow-up' : 'arrow-down'" size="16px" color="#909399" />
</view>
<view v-show="tagChart.isExpand" class="card-body mt-6 box-border w-full overflow-hidden border-2 border-[#e9eef3] rounded-xl bg-[#fcfdfe] p-3">
<qiun-data-charts
type="ring"
:chart-data="tagChart.data"
:opts="{ color: chartColors, padding: [5, 5, 5, 5], dataLabel: false, legend: { show: false }, extra: { ring: { ringWidth: 36, offsetAngle: -90, border: true, borderWidth: 1, borderColor: '#FFFFFF' } } }"
/>
</view>
</view>
<!-- 分类统计 -->
<view class="card box-border rounded-xl bg-white/95 p-6" style="box-shadow: 0 0 12rpx rgb(226 232 240 / 35%);">
<view class="card-head flex items-center justify-between" @click="categoryChart.isExpand = !categoryChart.isExpand">
<view class="card-head-title flex items-baseline gap-2">
<text class="card-head-text relative box-border pl-6 text-[30rpx] font-bold">分类统计</text>
<text class="card-head-subtext text-[26rpx] text-[#6b7280] font-normal">全部分类的文章数量占比</text>
</view>
<wd-icon :name="categoryChart.isExpand ? 'arrow-up' : 'arrow-down'" size="16px" color="#909399" />
</view>
<view v-show="categoryChart.isExpand" class="card-body mt-6 box-border w-full overflow-hidden border-2 border-[#e9eef3] rounded-xl bg-[#fcfdfe] p-3">
<qiun-data-charts
type="column"
:chart-data="categoryChart.data"
:opts="{ color: chartColors, padding: [20, 15, 10, 15], legend: { show: false }, xAxis: { disableGrid: true, fontSize: 10, itemCount: 6 }, yAxis: { gridType: 'dash', dashLength: 4 }, extra: { column: { type: 'group', width: 22, linearType: 'custom', seriesGap: 5, barBorderCircle: true, customColor: ['#F59E0B'] } } }"
/>
</view>
</view>
<!-- 文章发布趋势 -->
<view class="card box-border rounded-xl bg-white/95 p-6" style="box-shadow: 0 0 12rpx rgb(226 232 240 / 35%);">
<view class="card-head flex items-center justify-between" @click="trandArticleChart.isExpand = !trandArticleChart.isExpand">
<view class="card-head-title flex items-baseline gap-2">
<text class="card-head-text relative box-border pl-6 text-[30rpx] font-bold">文章发布趋势</text>
<text class="card-head-subtext text-[26rpx] text-[#6b7280] font-normal">按日期统计文章发布数量</text>
</view>
<wd-icon :name="trandArticleChart.isExpand ? 'arrow-up' : 'arrow-down'" size="16px" color="#909399" />
</view>
<view v-show="trandArticleChart.isExpand" class="card-body mt-6 box-border w-full overflow-hidden border-2 border-[#e9eef3] rounded-xl bg-[#fcfdfe] p-3">
<uh-heatmap :chart-data="trandArticleChart.data" />
</view>
</view>
<!-- 评论活跃用户 -->
<view class="card box-border rounded-xl bg-white/95 p-6" style="box-shadow: 0 0 12rpx rgb(226 232 240 / 35%);">
<view class="card-head flex items-center justify-between" @click="userCommentsChart.isExpand = !userCommentsChart.isExpand">
<view class="card-head-title flex items-baseline gap-2">
<text class="card-head-text relative box-border pl-6 text-[30rpx] font-bold">评论活跃用户</text>
<text class="card-head-subtext text-[26rpx] text-[#6b7280] font-normal">按评论作者统计评论数量</text>
</view>
<wd-icon :name="userCommentsChart.isExpand ? 'arrow-up' : 'arrow-down'" size="16px" color="#909399" />
</view>
<view v-show="userCommentsChart.isExpand" class="card-body mt-6 box-border w-full overflow-hidden border-2 border-[#e9eef3] rounded-xl bg-[#fcfdfe] p-3">
<qiun-data-charts
type="column"
:chart-data="userCommentsChart.data"
:opts="{ color: chartColors, padding: [20, 15, 10, 10], legend: { show: false }, xAxis: { disableGrid: true, fontSize: 10, itemCount: 5 }, yAxis: { gridType: 'dash', dashLength: 4 }, extra: { column: { type: 'group', width: 22, linearType: 'custom', seriesGap: 5, barBorderCircle: true, customColor: ['#F59E0B'] } } }"
/>
</view>
</view>
<!-- 热门文章 Top10 -->
<view class="card box-border rounded-xl bg-white/95 p-6" style="box-shadow: 0 0 12rpx rgb(226 232 240 / 35%);">
<view class="card-head">
<view class="card-head-title flex items-baseline gap-2">
<text class="card-head-text relative box-border pl-6 text-[30rpx] font-bold">热门文章前10</text>
<text class="card-head-subtext text-[26rpx] text-[#6b7280] font-normal">按访问量排序的热门文章</text>
</view>
</view>
<view class="card-body mt-6 box-border w-full overflow-hidden border-2 border-[#e9eef3] rounded-xl bg-[#fcfdfe] p-3">
<qiun-data-charts
type="column"
:chart-data="top10ArticlesChart.data"
:opts="{ color: chartColors, padding: [20, 15, 10, 10], legend: { show: false }, xAxis: { disableGrid: true, fontSize: 10, itemCount: 5 }, yAxis: { gridType: 'dash', dashLength: 4 }, extra: { column: { type: 'group', width: 22, linearType: 'custom', seriesGap: 5, barBorderCircle: true, customColor: ['#F59E0B'] } } }"
/>
</view>
</view>
</view>
</template>
</view>
</template>
<style scoped lang="scss">
.card-head-text {
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 70%;
background-color: #03a9f4;
border-radius: 12rpx;
}
}
</style>