mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-07-27 04:20:43 +08:00
refactor: 项目重构适配uni-halo,拆分首页组件
1. 统一环境变量前缀为VITE_UNI_HALO_BASEURL,替换原有VITE_SERVER_BASEURL 2. 新增首页home页面,将原index页面作为启动页跳转首页 3. 新增多个业务组件:模板组件、个人资料卡片、分类推荐卡片、文章卡片 4. 新增图片处理工具、数字格式化工具、URL验证工具 5. 重构tabbar配置,修正首页跳转路径 6. 更新站点统计API方法命名,优化请求逻辑
This commit is contained in:
@@ -19,14 +19,14 @@ VITE_APP_PUBLIC_BASE=/
|
|||||||
# 默认后台请求地址
|
# 默认后台请求地址
|
||||||
# 不同命令会按 mode 叠加读取 .env.development / .env.test / .env.production。
|
# 不同命令会按 mode 叠加读取 .env.development / .env.test / .env.production。
|
||||||
# 微信小程序如果没有配置下面的专用地址,也会回退使用这个值。
|
# 微信小程序如果没有配置下面的专用地址,也会回退使用这个值。
|
||||||
VITE_SERVER_BASEURL=''
|
VITE_UNI_HALO_BASEURL=''
|
||||||
# 备注:如果后台带统一前缀,则也要加到后面,eg: https://blog.xiaoxiaomo.cn/api
|
# 备注:如果后台带统一前缀,则也要加到后面,eg: https://blog.xiaoxiaomo.cn/api
|
||||||
|
|
||||||
# 微信小程序专用后台请求地址,按微信开发者工具 envVersion 区分。
|
# 微信小程序专用后台请求地址,按微信开发者工具 envVersion 区分。
|
||||||
# 不配置时会回退使用 VITE_SERVER_BASEURL。
|
# 不配置时会回退使用 VITE_UNI_HALO_BASEURL。
|
||||||
# VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://dev.xxx.com'
|
# VITE_UNI_HALO_BASEURL__WEIXIN_DEVELOP = 'https://dev.xxx.com'
|
||||||
# VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://trial.xxx.com'
|
# VITE_UNI_HALO_BASEURL__WEIXIN_TRIAL = 'https://trial.xxx.com'
|
||||||
# VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://prod.xxx.com'
|
# VITE_UNI_HALO_BASEURL__WEIXIN_RELEASE = 'https://prod.xxx.com'
|
||||||
|
|
||||||
# h5是否需要配置代理
|
# h5是否需要配置代理
|
||||||
VITE_APP_PROXY_ENABLE=false
|
VITE_APP_PROXY_ENABLE=false
|
||||||
@@ -34,7 +34,7 @@ VITE_APP_PROXY_ENABLE=false
|
|||||||
VITE_APP_PROXY_PREFIX='/dev-api'
|
VITE_APP_PROXY_PREFIX='/dev-api'
|
||||||
|
|
||||||
# 第二个请求地址 (目前alova中可以使用)
|
# 第二个请求地址 (目前alova中可以使用)
|
||||||
VITE_SERVER_BASEURL_SECONDARY='https://blog.xiaoxiaomo.cn'
|
VITE_UNI_HALO_BASEURL_SECONDARY='https://blog.xiaoxiaomo.cn'
|
||||||
|
|
||||||
# 认证模式,'single' | 'double' ==> 单token | 双token
|
# 认证模式,'single' | 'double' ==> 单token | 双token
|
||||||
VITE_AUTH_MODE='single'
|
VITE_AUTH_MODE='single'
|
||||||
|
|||||||
Vendored
+1
-1
@@ -6,4 +6,4 @@ VITE_DELETE_CONSOLE=false
|
|||||||
VITE_SHOW_SOURCEMAP=false
|
VITE_SHOW_SOURCEMAP=false
|
||||||
|
|
||||||
# development mode 后台请求地址
|
# development mode 后台请求地址
|
||||||
VITE_SERVER_BASEURL='https://www.yijunzhao.cn'
|
VITE_UNI_HALO_BASEURL='https://www.yijunzhao.cn'
|
||||||
|
|||||||
Vendored
+1
-1
@@ -6,4 +6,4 @@ VITE_DELETE_CONSOLE=true
|
|||||||
VITE_SHOW_SOURCEMAP=false
|
VITE_SHOW_SOURCEMAP=false
|
||||||
|
|
||||||
# production mode 后台请求地址
|
# production mode 后台请求地址
|
||||||
# VITE_SERVER_BASEURL = 'https://prod.xxx.com'
|
# VITE_UNI_HALO_BASEURL = 'https://prod.xxx.com'
|
||||||
|
|||||||
Vendored
+1
-1
@@ -6,4 +6,4 @@ VITE_DELETE_CONSOLE=false
|
|||||||
VITE_SHOW_SOURCEMAP=false
|
VITE_SHOW_SOURCEMAP=false
|
||||||
|
|
||||||
# test mode 后台请求地址
|
# test mode 后台请求地址
|
||||||
# VITE_SERVER_BASEURL = 'https://test.xxx.com'
|
# VITE_UNI_HALO_BASEURL = 'https://test.xxx.com'
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export interface SiteStatsVo {
|
|||||||
* 获取站点统计信息
|
* 获取站点统计信息
|
||||||
* @returns 站点统计信息
|
* @returns 站点统计信息
|
||||||
*/
|
*/
|
||||||
export function getSiteStats() {
|
export function querySiteStats() {
|
||||||
return http.Get<SiteStatsVo>(`/apis/api.halo.run/v1alpha1/stats/-`, {
|
return http.Get<SiteStatsVo>(`/apis/api.halo.run/v1alpha1/stats/-`, {
|
||||||
meta: { isHalo: true },
|
meta: { isHalo: true },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
内容
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { querySiteStats } from '@/api/halo-base/stats'
|
||||||
|
import { formatNumberUnit } from '@/utils/base/digital'
|
||||||
|
import type { SiteStatsVo } from '@halo-dev/api-client'
|
||||||
|
|
||||||
|
const { loading, error, data, run } = useRequest<SiteStatsVo>(querySiteStats, { loadingToast: false, loadingToastContent: '加载中...', loadingToastMask: true })
|
||||||
|
|
||||||
|
const stats = computed(() => {
|
||||||
|
return {
|
||||||
|
post: formatNumberUnit(data.value?.post || 0),
|
||||||
|
comment: formatNumberUnit(data.value?.comment || 0),
|
||||||
|
upvote: formatNumberUnit(data.value?.upvote || 0),
|
||||||
|
visit: formatNumberUnit(data.value?.visit || 0),
|
||||||
|
category: formatNumberUnit(data.value?.category || 0),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="uh-shadow-xs box-border flex flex-col items-center gap-y-2 rounded-2xl bg-white p-4">
|
||||||
|
<view class="w-full flex items-center justify-between gap-x-2">
|
||||||
|
<image
|
||||||
|
class="uh-shadow-xs h-11 w-11 shrink-0 border-2 border-white rounded-full border-solid"
|
||||||
|
src="https://www.xiaoxiaomo.cn/logo.jpg" mode="scaleToFill"
|
||||||
|
/>
|
||||||
|
<view class="h-full flex flex-1 flex-col justify-between gap-y-1">
|
||||||
|
<view class="text-sm text-gray-900 font-bold">
|
||||||
|
小莫唐尼
|
||||||
|
</view>
|
||||||
|
<view class="line-clamp-1 text-xs text-gray-500">
|
||||||
|
一个爱凑热闹,喜欢捣鼓前端的码农。
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="h-full shrink-0 rounded-3xl bg-[#1A1A1A] px-4 py-2 text-xs text-white">
|
||||||
|
联系我
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="my-1 h-1px w-full bg-gray-50" />
|
||||||
|
<view class="grid grid-cols-5 w-full gap-x-4">
|
||||||
|
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">{{ stats.post }}</text>
|
||||||
|
<text class="text-xs text-gray-600">笔记</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">{{ stats.visit }}</text>
|
||||||
|
<text class="text-xs text-gray-600">访客</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">{{ stats.category }}</text>
|
||||||
|
<text class="text-xs text-gray-600">分类</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">{{ stats.comment }}</text>
|
||||||
|
<text class="text-xs text-gray-600">评论</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">{{ stats.upvote }}</text>
|
||||||
|
<text class="text-xs text-gray-600">点赞</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.uh-shadow-xs {
|
||||||
|
box-shadow: 0 0 24rpx rgba(0, 0, 0, 0.035);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { cover } from '@/utils/imageHelper'
|
||||||
|
import { queryCategories } from '@/api/halo-base/category'
|
||||||
|
import type { CategoryV1alpha1PublicApiQueryCategoriesRequest, CategoryVoList } from '@halo-dev/api-client'
|
||||||
|
|
||||||
|
const { loading, error, data, run } = useRequest<CategoryVoList, CategoryV1alpha1PublicApiQueryCategoriesRequest>(queryCategories, { loadingToast: false, loadingToastContent: '加载中...', loadingToastMask: true })
|
||||||
|
|
||||||
|
const isVisible = computed(() => {
|
||||||
|
return !loading.value && !error.value && data.value?.items.length > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const firstCateItem = computed(() => {
|
||||||
|
const item = data.value?.items[0]
|
||||||
|
return {
|
||||||
|
name: item.spec.displayName,
|
||||||
|
count: item.status.postCount,
|
||||||
|
cover: cover(item.spec.cover),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const otherCateItems = computed(() => {
|
||||||
|
const items = data.value?.items.slice(1) || []
|
||||||
|
return items.map(item => ({
|
||||||
|
name: item.spec.displayName,
|
||||||
|
count: item.status.postCount,
|
||||||
|
cover: cover(item.spec.cover),
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('分类推荐 onMounted')
|
||||||
|
run({
|
||||||
|
page: 1,
|
||||||
|
size: 3,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view v-if="isVisible" class="mt-6 box-border px-4">
|
||||||
|
<view class="mb-4 box-border flex items-center justify-between">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">热门分类</text>
|
||||||
|
</view>
|
||||||
|
<view class="box-border h-36 flex items-center gap-2 overflow-hidden">
|
||||||
|
<view
|
||||||
|
class="relative box-border h-full flex-1 overflow-hidden border-2 border-white rounded-xl border-solid bg-white"
|
||||||
|
>
|
||||||
|
<image :src="firstCateItem.cover" mode="heightFix" class="h-full w-full rounded-xl" />
|
||||||
|
<view
|
||||||
|
class="absolute bottom-0 left-0 right-0 z-10 box-border box-border w-full flex flex-col gap-y-1 from-black/0 via-black/50 to-black/90 bg-gradient-to-b p-2"
|
||||||
|
>
|
||||||
|
<text class="line-clamp-1 text-xs text-white font-bold">{{ firstCateItem.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="absolute right-2 top-2 z-10 box-border rounded-md bg-black/20 px-1.5 py-0.5">
|
||||||
|
<text class="text-[12px] text-white">{{ firstCateItem.count }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="h-full flex flex-1 flex-col gap-2">
|
||||||
|
<view
|
||||||
|
v-for="cate in otherCateItems" :key="cate.name"
|
||||||
|
class="relative box-border flex-1 overflow-hidden border-2 border-white rounded-xl border-solid bg-white"
|
||||||
|
>
|
||||||
|
<image :src="cate.cover" mode="aspectFill" class="w-full rounded-xl" />
|
||||||
|
<view
|
||||||
|
class="absolute bottom-0 left-0 right-0 z-10 box-border box-border w-full flex flex-col gap-y-1 from-black/0 via-black/50 to-black/90 bg-gradient-to-b p-2"
|
||||||
|
>
|
||||||
|
<text class="line-clamp-1 text-xs text-white font-bold">{{ cate.name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="absolute right-2 top-2 z-10 box-border rounded-md bg-black/20 px-1.5 py-0.5">
|
||||||
|
<text class="text-[12px] text-white">{{ cate.count }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
Vendored
+7
-7
@@ -14,13 +14,13 @@ interface ImportMetaEnv {
|
|||||||
/** 服务端口号 */
|
/** 服务端口号 */
|
||||||
readonly VITE_SERVER_PORT: string
|
readonly VITE_SERVER_PORT: string
|
||||||
/** 后台接口地址 */
|
/** 后台接口地址 */
|
||||||
readonly VITE_SERVER_BASEURL: string
|
readonly VITE_UNI_HALO_BASEURL: string
|
||||||
/** 微信小程序开发版后台接口地址,不配置则使用 VITE_SERVER_BASEURL */
|
/** 微信小程序开发版后台接口地址,不配置则使用 VITE_UNI_HALO_BASEURL */
|
||||||
readonly VITE_SERVER_BASEURL__WEIXIN_DEVELOP?: string
|
readonly VITE_UNI_HALO_BASEURL__WEIXIN_DEVELOP?: string
|
||||||
/** 微信小程序体验版后台接口地址,不配置则使用 VITE_SERVER_BASEURL */
|
/** 微信小程序体验版后台接口地址,不配置则使用 VITE_UNI_HALO_BASEURL */
|
||||||
readonly VITE_SERVER_BASEURL__WEIXIN_TRIAL?: string
|
readonly VITE_UNI_HALO_BASEURL__WEIXIN_TRIAL?: string
|
||||||
/** 微信小程序正式版后台接口地址,不配置则使用 VITE_SERVER_BASEURL */
|
/** 微信小程序正式版后台接口地址,不配置则使用 VITE_UNI_HALO_BASEURL */
|
||||||
readonly VITE_SERVER_BASEURL__WEIXIN_RELEASE?: string
|
readonly VITE_UNI_HALO_BASEURL__WEIXIN_RELEASE?: string
|
||||||
/** H5是否需要代理 */
|
/** H5是否需要代理 */
|
||||||
readonly VITE_APP_PROXY_ENABLE: 'true' | 'false'
|
readonly VITE_APP_PROXY_ENABLE: 'true' | 'false'
|
||||||
/** H5是否需要代理,需要的话有个前缀 */
|
/** H5是否需要代理,需要的话有个前缀 */
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@ import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum'
|
|||||||
|
|
||||||
// 配置动态Tag
|
// 配置动态Tag
|
||||||
export const API_DOMAINS = {
|
export const API_DOMAINS = {
|
||||||
DEFAULT: import.meta.env.VITE_SERVER_BASEURL,
|
DEFAULT: import.meta.env.VITE_UNI_HALO_BASEURL,
|
||||||
SECONDARY: import.meta.env.VITE_SERVER_BASEURL_SECONDARY,
|
SECONDARY: import.meta.env.VITE_UNI_HALO_BASEURL_SECONDARY,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import useRequest from '@/hooks/useRequest'
|
||||||
|
import { queryPostByName, queryPosts } from '@/api/halo-base/post'
|
||||||
|
import { cover } from '@/utils/imageHelper'
|
||||||
|
import { timeFrom } from '@/utils/base/timeFrom'
|
||||||
|
import { useListData } from '@/hooks/useListData'
|
||||||
|
import { randomImageUrl } from '@/utils/randomResources'
|
||||||
|
import type { ListedPostVo, ListedPostVoList, PostV1alpha1PublicApiQueryPostByNameRequest, PostV1alpha1PublicApiQueryPostsRequest, PostVo } from '@halo-dev/api-client'
|
||||||
|
|
||||||
|
import ProfileCard from '@/components/home/uh-profile-card.vue'
|
||||||
|
import RecommendCategory from '@/components/home/uh-recommend-category.vue'
|
||||||
|
import PostCard from '@/components/uh-post-card/uh-post-card.vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'Home',
|
||||||
|
})
|
||||||
|
|
||||||
|
definePage({
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
navigationBarTitleText: '首页',
|
||||||
|
enablePullDownRefresh: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const exampleImageUrls = reactive({
|
||||||
|
banner: 'https://fastly.picsum.photos/id/353/800/800.jpg?hmac=RaDuQ92sSXj4q5vOYna9G00J7KrBUC3eBS0slCWYZXA',
|
||||||
|
avatar: 'https://www.xiaoxiaomo.cn/logo.jpg',
|
||||||
|
postCover1: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDg-QKAXOU1_Lv726MyeTiY2R1MAJWKzjiUy__RYoUw78YL5PctVg2sfMUCRMBybAzw_E0V0fEhir4IW2RHF7YRcxm89JFDKVMlfU_yQTijnr4o-praEXX_buxFWWxsSayLdA64X9pOmjYT5FDp9kfpW4tqZBWLfiyqhiYZnyHTCFeKZruH2auHZt4OlsOdzamOOkoib4CMGmUwTj112emdzlshRDLxGOSbThTWUOw61YirCl-RUrx1WFg2kZimP9Byq4pV7tv9YhtS',
|
||||||
|
postCover: 'https://www.yijunzhao.cn/upload/HermesWebUIHermesStudio%E8%83%8C%E5%90%8E%E7%9A%84%E5%93%81%E7%89%8C%E5%8D%87%E7%BA%A7%E4%B8%8E%E4%BA%A7%E5%93%81%E8%BF%9B%E5%8C%96-02.png',
|
||||||
|
})
|
||||||
|
|
||||||
|
const banner = reactive({
|
||||||
|
current: 0,
|
||||||
|
items: [
|
||||||
|
exampleImageUrls.banner,
|
||||||
|
exampleImageUrls.postCover1,
|
||||||
|
],
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
value: exampleImageUrls.banner,
|
||||||
|
title: 'UNI HALO v3.0',
|
||||||
|
desc: '新全新探索简约的艺术风格',
|
||||||
|
time: timeFrom(new Date()),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: randomImageUrl.pc,
|
||||||
|
title: 'UNI HALO v3.0 使用手册',
|
||||||
|
desc: 'uni-halo 使用手册,包含安装、配置、使用等信息666666666aaaa啊啊啊啊啊啊啊啊啊啊啊',
|
||||||
|
time: timeFrom(new Date()),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const quickList = reactive([
|
||||||
|
{
|
||||||
|
pagePath: 'pages/moments/moments',
|
||||||
|
text: '动态',
|
||||||
|
iconType: 'uiLib',
|
||||||
|
icon: 'gift',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages-blog/about/about',
|
||||||
|
text: '关于',
|
||||||
|
iconType: 'uiLib',
|
||||||
|
icon: 'image',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/me/me',
|
||||||
|
text: '我的',
|
||||||
|
iconType: 'uiLib',
|
||||||
|
icon: 'user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/category/category',
|
||||||
|
text: '分类',
|
||||||
|
iconType: 'uiLib',
|
||||||
|
icon: 'image',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: 'pages/category/category',
|
||||||
|
text: '其他',
|
||||||
|
iconType: 'uiLib',
|
||||||
|
icon: 'image',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const { loading, error, data, run } = useRequest<ListedPostVoList, PostV1alpha1PublicApiQueryPostsRequest>(queryPosts, { loadingToast: true, loadingToastContent: '加载中...', loadingToastMask: true })
|
||||||
|
const { loading: loadingSingle, error: errorSingle, data: dataSingle, run: runSingle } = useRequest<PostVo, PostV1alpha1PublicApiQueryPostByNameRequest>(queryPostByName)
|
||||||
|
|
||||||
|
const { list: postList, refresh } = useListData<ListedPostVo>({
|
||||||
|
params: {
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
},
|
||||||
|
loading: toRef(loading),
|
||||||
|
onPullDownRefresh: async (params, updateData) => {
|
||||||
|
await run({ ...params })
|
||||||
|
updateData({
|
||||||
|
error: error.value,
|
||||||
|
hasNext: data.value?.hasNext,
|
||||||
|
items: data.value?.items ?? [],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onReachBottom: async (params, updateData) => {
|
||||||
|
await run({ ...params })
|
||||||
|
updateData({
|
||||||
|
error: error.value,
|
||||||
|
hasNext: data.value?.hasNext,
|
||||||
|
items: data.value?.items ?? [],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
console.log('home onLoad')
|
||||||
|
refresh()
|
||||||
|
runSingle({ name: '019eb1ca-e37c-7729-97af-e0b658aeef0f' })
|
||||||
|
})
|
||||||
|
|
||||||
|
onPageScroll(() => { })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="min-h-screen bg-page pb-safe">
|
||||||
|
<!-- 顶部banner -->
|
||||||
|
<view v-if="false" class="relative h-72 w-full">
|
||||||
|
<image class="h-72 w-full object-cover" :src="exampleImageUrls.banner" />
|
||||||
|
<view class="absolute bottom-4 left-4 flex flex-col gap-y-2">
|
||||||
|
<text class="text-xs text-white">welcome to new world</text>
|
||||||
|
<text class="text-2xl text-white font-bold">UNI HALO V3.0 </text>
|
||||||
|
<text class="text-xs text-white">新全新探索简约的艺术风格</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<wd-swiper
|
||||||
|
v-model:current="banner.current" :list="banner.items" indicator-position="right" autoplay
|
||||||
|
:height="340"
|
||||||
|
>
|
||||||
|
<template #default="{ index }">
|
||||||
|
<view class="relative h-full w-full">
|
||||||
|
<image class="h-full w-full" mode="aspectFill" :src="banner.list[index].value" />
|
||||||
|
<!-- 渐变遮罩 from-black/0 via-black/50 to-black/90 bg-gradient-to-b -->
|
||||||
|
<view class="absolute bottom-0 left-0 right-0 p-4 pb-16">
|
||||||
|
<view class="relative z-20 w-5/6 flex flex-col gap-y-2">
|
||||||
|
<text class="text-xs text-white/90">{{ banner.list[index].time }}</text>
|
||||||
|
<text class="line-clamp-1 text-xl text-white font-bold">{{ banner.list[index].title }}</text>
|
||||||
|
<text class="line-clamp-1 text-xs text-white/95">{{ banner.list[index].desc }}</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="absolute bottom-0 left-0 right-0 z-10 h-3/5 from-black/0 via-page/50 to-page bg-gradient-to-b"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template #indicator="{ current, total }">
|
||||||
|
<view class="absolute bottom-16 right-4 text-xs text-white">
|
||||||
|
{{ current + 1 }}/{{ total }}
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</wd-swiper>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 作者卡片 -->
|
||||||
|
<view class="relative z-10 box-border px-4 -mt-12">
|
||||||
|
<profile-card />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 金刚区 -->
|
||||||
|
<view class="mt-6 px-4">
|
||||||
|
<view class="flex items-center justify-around gap-x-4">
|
||||||
|
<view
|
||||||
|
v-for="item in quickList" :key="item.pagePath"
|
||||||
|
class="w-1/5 flex flex-col items-center justify-center gap-y-1"
|
||||||
|
>
|
||||||
|
<view class="uh-shadow-xs flex items-center justify-center rounded-2xl bg-white p-3.5">
|
||||||
|
<wd-icon :name="item.icon" :size="24" />
|
||||||
|
</view>
|
||||||
|
<text class="text-xs text-gray-800">{{ item.text }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 分类推荐 -->
|
||||||
|
<recommend-category />
|
||||||
|
|
||||||
|
<!-- 瞬间推荐 -->
|
||||||
|
|
||||||
|
<!-- 置顶文章 -->
|
||||||
|
<view v-if="dataSingle && false" class="mt-4 box-border px-4">
|
||||||
|
<view class="mb-2 box-border flex items-center justify-between">
|
||||||
|
<text class="text-lg text-gray-900 font-bold">置顶文章</text>
|
||||||
|
</view>
|
||||||
|
<view class="box-border rounded-xl bg-white p-4">
|
||||||
|
<image :src="cover(dataSingle.spec.cover)" mode="aspectFill" class="h-36 w-full rounded-xl" />
|
||||||
|
<view class="box-border w-full flex flex-col gap-y-1 pt-2">
|
||||||
|
<text class="line-clamp-1 text-sm text-gray-900 font-bold">{{ dataSingle.spec.title }}</text>
|
||||||
|
<text class="line-clamp-2 text-xs text-gray-500">{{ dataSingle.status.excerpt }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 最新笔记 -->
|
||||||
|
<view class="mt-4 mt-4 box-border px-4">
|
||||||
|
<view class="mb-4 box-border flex items-center justify-between">
|
||||||
|
<text class="text-sm text-gray-900 font-bold">最新笔记</text>
|
||||||
|
</view>
|
||||||
|
<view class="box-border w-full flex flex-col items-center justify-center gap-y-4 overflow-hidden">
|
||||||
|
<view v-if="error && postList.length > 0" class="un-shadow-xs w-full rounded-2xl bg-white py-12">
|
||||||
|
<wd-empty :icon-size="60" icon="no-result" tip="暂无数据" />
|
||||||
|
</view>
|
||||||
|
<template v-else>
|
||||||
|
<post-card v-for="post in postList" :key="post.metadata.name" :post="post" type="topCover" />
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部导航占位 -->
|
||||||
|
<view class="h-60px w-full" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.uh-shadow-xs {
|
||||||
|
box-shadow: 0 0 24rpx rgba(0, 0, 0, 0.035);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+6
-295
@@ -1,314 +1,25 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import useRequest from '@/hooks/useRequest'
|
|
||||||
import { queryPostByName, queryPosts } from '@/api/halo-base/post'
|
|
||||||
import { completeUrl } from '@/utils/url'
|
|
||||||
import { timeFrom } from '@/utils/base/timeFrom'
|
|
||||||
import { useListData } from '@/hooks/useListData'
|
|
||||||
import { getRandomUrl, randomImageUrl } from '@/utils/randomResources'
|
|
||||||
import type { ListedPostVo, ListedPostVoList, PostV1alpha1PublicApiQueryPostByNameRequest, PostV1alpha1PublicApiQueryPostsRequest, PostVo } from '@halo-dev/api-client'
|
|
||||||
|
|
||||||
import PostCard from '@/components/post-card/post-card.vue'
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'Home',
|
name: 'Index',
|
||||||
})
|
})
|
||||||
|
|
||||||
definePage({
|
definePage({
|
||||||
type: 'home',
|
type: 'home',
|
||||||
style: {
|
style: {
|
||||||
navigationStyle: 'custom',
|
navigationStyle: 'custom',
|
||||||
navigationBarTitleText: '首页',
|
navigationBarTitleText: '启动页',
|
||||||
enablePullDownRefresh: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const exampleImageUrls = reactive({
|
|
||||||
banner: 'https://fastly.picsum.photos/id/353/800/800.jpg?hmac=RaDuQ92sSXj4q5vOYna9G00J7KrBUC3eBS0slCWYZXA',
|
|
||||||
avatar: 'https://www.xiaoxiaomo.cn/logo.jpg',
|
|
||||||
postCover1: 'https://lh3.googleusercontent.com/aida-public/AB6AXuDg-QKAXOU1_Lv726MyeTiY2R1MAJWKzjiUy__RYoUw78YL5PctVg2sfMUCRMBybAzw_E0V0fEhir4IW2RHF7YRcxm89JFDKVMlfU_yQTijnr4o-praEXX_buxFWWxsSayLdA64X9pOmjYT5FDp9kfpW4tqZBWLfiyqhiYZnyHTCFeKZruH2auHZt4OlsOdzamOOkoib4CMGmUwTj112emdzlshRDLxGOSbThTWUOw61YirCl-RUrx1WFg2kZimP9Byq4pV7tv9YhtS',
|
|
||||||
postCover: 'https://www.yijunzhao.cn/upload/HermesWebUIHermesStudio%E8%83%8C%E5%90%8E%E7%9A%84%E5%93%81%E7%89%8C%E5%8D%87%E7%BA%A7%E4%B8%8E%E4%BA%A7%E5%93%81%E8%BF%9B%E5%8C%96-02.png',
|
|
||||||
})
|
|
||||||
|
|
||||||
const banner = reactive({
|
|
||||||
current: 0,
|
|
||||||
items: [
|
|
||||||
exampleImageUrls.banner,
|
|
||||||
exampleImageUrls.postCover1,
|
|
||||||
],
|
|
||||||
list: [
|
|
||||||
{
|
|
||||||
value: exampleImageUrls.banner,
|
|
||||||
title: 'UNI HALO v3.0',
|
|
||||||
desc: '新全新探索简约的艺术风格',
|
|
||||||
time: timeFrom(new Date()),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: randomImageUrl.pc,
|
|
||||||
title: 'UNI HALO v3.0 使用手册',
|
|
||||||
desc: 'uni-halo 使用手册,包含安装、配置、使用等信息666666666aaaa啊啊啊啊啊啊啊啊啊啊啊',
|
|
||||||
time: timeFrom(new Date()),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const categories = reactive([
|
|
||||||
{
|
|
||||||
name: '全栈开发',
|
|
||||||
count: 120,
|
|
||||||
cover: getRandomUrl(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Docker',
|
|
||||||
count: 0,
|
|
||||||
cover: getRandomUrl(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Vue技术',
|
|
||||||
count: 99,
|
|
||||||
cover: getRandomUrl(),
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const quickList = reactive([
|
|
||||||
{
|
|
||||||
pagePath: 'pages/moments/moments',
|
|
||||||
text: '动态',
|
|
||||||
iconType: 'uiLib',
|
|
||||||
icon: 'gift',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pagePath: 'pages-blog/about/about',
|
|
||||||
text: '关于',
|
|
||||||
iconType: 'uiLib',
|
|
||||||
icon: 'image',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pagePath: 'pages/me/me',
|
|
||||||
text: '我的',
|
|
||||||
iconType: 'uiLib',
|
|
||||||
icon: 'user',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pagePath: 'pages/category/category',
|
|
||||||
text: '分类',
|
|
||||||
iconType: 'uiLib',
|
|
||||||
icon: 'image',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pagePath: 'pages/category/category',
|
|
||||||
text: '其他',
|
|
||||||
iconType: 'uiLib',
|
|
||||||
icon: 'image',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const { loading, error, data, run } = useRequest<ListedPostVoList, PostV1alpha1PublicApiQueryPostsRequest>(queryPosts, { loadingToast: true, loadingToastContent: '加载中...', loadingToastMask: true })
|
|
||||||
const { loading: loadingSingle, error: errorSingle, data: dataSingle, run: runSingle } = useRequest<PostVo, PostV1alpha1PublicApiQueryPostByNameRequest>(queryPostByName)
|
|
||||||
|
|
||||||
const { list: postList, refresh } = useListData<ListedPostVo>({
|
|
||||||
params: {
|
|
||||||
page: 1,
|
|
||||||
size: 10,
|
|
||||||
},
|
|
||||||
loading: toRef(loading),
|
|
||||||
onPullDownRefresh: async (params, updateData) => {
|
|
||||||
await run({ ...params })
|
|
||||||
updateData({
|
|
||||||
error: error.value,
|
|
||||||
hasNext: data.value?.hasNext,
|
|
||||||
items: data.value?.items ?? [],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onReachBottom: async (params, updateData) => {
|
|
||||||
await run({ ...params })
|
|
||||||
updateData({
|
|
||||||
error: error.value,
|
|
||||||
hasNext: data.value?.hasNext,
|
|
||||||
items: data.value?.items ?? [],
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
console.log('home onLoad')
|
console.log('index onLoad')
|
||||||
refresh()
|
// 默认跳转首页
|
||||||
runSingle({ name: '019eb1ca-e37c-7729-97af-e0b658aeef0f' })
|
uni.switchTab({ url: '/pages/home/home' })
|
||||||
})
|
|
||||||
|
|
||||||
onPageScroll(({ scrollTop }) => {
|
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="min-h-screen bg-page pb-safe">
|
<view class="min-h-screen bg-page pb-safe">
|
||||||
<!-- 顶部banner -->
|
启动页
|
||||||
<view v-if="false" class="relative h-72 w-full">
|
|
||||||
<image class="h-72 w-full object-cover" :src="exampleImageUrls.banner" />
|
|
||||||
<view class="absolute bottom-4 left-4 flex flex-col gap-y-2">
|
|
||||||
<text class="text-xs text-white">welcome to new world</text>
|
|
||||||
<text class="text-2xl text-white font-bold">UNI HALO V3.0 </text>
|
|
||||||
<text class="text-xs text-white">新全新探索简约的艺术风格</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<wd-swiper
|
|
||||||
v-model:current="banner.current" :list="banner.items" indicator-position="right" autoplay
|
|
||||||
:height="340"
|
|
||||||
>
|
|
||||||
<template #default="{ index }">
|
|
||||||
<view class="relative h-full w-full">
|
|
||||||
<image class="h-full w-full" mode="aspectFill" :src="banner.list[index].value" />
|
|
||||||
<!-- 渐变遮罩 from-black/0 via-black/50 to-black/90 bg-gradient-to-b -->
|
|
||||||
<view class="absolute bottom-0 left-0 right-0 p-4 pb-16">
|
|
||||||
<view class="relative z-20 w-5/6 flex flex-col gap-y-2">
|
|
||||||
<text class="text-xs text-white/90">{{ banner.list[index].time }}</text>
|
|
||||||
<text class="line-clamp-1 text-xl text-white font-bold">{{ banner.list[index].title }}</text>
|
|
||||||
<text class="line-clamp-1 text-xs text-white/95">{{ banner.list[index].desc }}</text>
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
class="absolute bottom-0 left-0 right-0 z-10 h-3/5 from-black/0 via-page/50 to-page bg-gradient-to-b"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template #indicator="{ current, total }">
|
|
||||||
<view class="absolute bottom-16 right-4 text-xs text-white">
|
|
||||||
{{ current + 1 }}/{{ total }}
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</wd-swiper>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 作者卡片 -->
|
|
||||||
<view class="relative z-10 box-border px-4 -mt-12">
|
|
||||||
<view class="uh-shadow-xs box-border flex flex-col items-center gap-y-2 rounded-2xl bg-white p-4">
|
|
||||||
<view class="w-full flex items-center justify-between gap-x-2">
|
|
||||||
<image
|
|
||||||
class="uh-shadow-xs h-11 w-11 shrink-0 border-2 border-white rounded-full border-solid"
|
|
||||||
src="https://www.xiaoxiaomo.cn/logo.jpg" mode="scaleToFill"
|
|
||||||
/>
|
|
||||||
<view class="h-full flex flex-1 flex-col justify-between gap-y-1">
|
|
||||||
<view class="text-sm text-gray-900 font-bold">
|
|
||||||
小莫唐尼
|
|
||||||
</view>
|
|
||||||
<view class="line-clamp-1 text-xs text-gray-500">
|
|
||||||
一个爱凑热闹,喜欢捣鼓前端的码农。
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="h-full shrink-0 rounded-3xl bg-[#1A1A1A] px-4 py-2 text-xs text-white">
|
|
||||||
联系我
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="my-1 h-1px w-full bg-gray-50" />
|
|
||||||
<view class="grid grid-cols-5 w-full gap-x-4">
|
|
||||||
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">128</text>
|
|
||||||
<text class="text-xs text-gray-600">内容</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">999</text>
|
|
||||||
<text class="text-xs text-gray-600">访客</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">1.2k</text>
|
|
||||||
<text class="text-xs text-gray-600">分类</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">128k</text>
|
|
||||||
<text class="text-xs text-gray-600">评论</text>
|
|
||||||
</view>
|
|
||||||
<view class="flex flex-col items-center justify-center gap-y-0.5">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">10.5k</text>
|
|
||||||
<text class="text-xs text-gray-600">点赞</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 金刚区 -->
|
|
||||||
<view class="mt-6 px-4">
|
|
||||||
<view class="flex items-center justify-around gap-x-4">
|
|
||||||
<view
|
|
||||||
v-for="item in quickList" :key="item.pagePath"
|
|
||||||
class="w-1/5 flex flex-col items-center justify-center gap-y-1"
|
|
||||||
>
|
|
||||||
<view class="uh-shadow-xs flex items-center justify-center rounded-2xl bg-white p-3.5">
|
|
||||||
<wd-icon :name="item.icon" :size="24" />
|
|
||||||
</view>
|
|
||||||
<text class="text-xs text-gray-800">{{ item.text }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 分类推荐(磁贴) -->
|
|
||||||
<view class="mt-6 box-border px-4">
|
|
||||||
<view class="mb-4 box-border flex items-center justify-between">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">热门分类</text>
|
|
||||||
</view>
|
|
||||||
<view class="box-border h-36 flex items-center gap-2 overflow-hidden">
|
|
||||||
<view class="relative box-border h-full flex-1 overflow-hidden border-2 border-white rounded-xl border-solid bg-white">
|
|
||||||
<image :src="completeUrl(categories[0].cover)" mode="heightFix" class="h-full w-full rounded-xl" />
|
|
||||||
<view class="absolute bottom-0 left-0 right-0 z-10 box-border box-border w-full flex flex-col gap-y-1 from-black/0 via-black/50 to-black/90 bg-gradient-to-b p-2">
|
|
||||||
<text class="line-clamp-1 text-xs text-white font-bold">{{ categories[0].name }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="absolute right-2 top-2 z-10 box-border rounded-md bg-black/20 px-1.5 py-0.5">
|
|
||||||
<text class="line-clamp-1 text-[12px] text-white">{{ categories[0].count }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="h-full flex flex-1 flex-col gap-2">
|
|
||||||
<view v-for="cate in categories.slice(1)" :key="cate.name" class="relative box-border flex-1 overflow-hidden border-2 border-white rounded-xl border-solid bg-white">
|
|
||||||
<image :src="completeUrl(cate.cover)" mode="aspectFill" class="w-full rounded-xl" />
|
|
||||||
<view class="absolute bottom-0 left-0 right-0 z-10 box-border box-border w-full flex flex-col gap-y-1 from-black/0 via-black/50 to-black/90 bg-gradient-to-b p-2">
|
|
||||||
<text class="line-clamp-1 text-xs text-white font-bold">{{ cate.name }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="absolute right-2 top-2 z-10 box-border rounded-md bg-black/20 px-1.5 py-0.5">
|
|
||||||
<text class="line-clamp-1 text-[12px] text-white">{{ cate.count }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 瞬间推荐 -->
|
|
||||||
|
|
||||||
<!-- 置顶文章 -->
|
|
||||||
<view v-if="dataSingle && false" class="mt-4 box-border px-4">
|
|
||||||
<view class="mb-2 box-border flex items-center justify-between">
|
|
||||||
<text class="text-lg text-gray-900 font-bold">置顶文章</text>
|
|
||||||
</view>
|
|
||||||
<view class="box-border rounded-xl bg-white p-4">
|
|
||||||
<image :src="completeUrl(dataSingle.spec.cover)" mode="aspectFill" class="h-36 w-full rounded-xl" />
|
|
||||||
<view class="box-border w-full flex flex-col gap-y-1 pt-2">
|
|
||||||
<text class="line-clamp-1 text-sm text-gray-900 font-bold">{{ dataSingle.spec.title }}</text>
|
|
||||||
<text class="line-clamp-2 text-xs text-gray-500">{{ dataSingle.status.excerpt }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 最新文章 -->
|
|
||||||
<view class="mt-4 mt-4 box-border px-4">
|
|
||||||
<view class="mb-4 box-border flex items-center justify-between">
|
|
||||||
<text class="text-sm text-gray-900 font-bold">最新文章</text>
|
|
||||||
</view>
|
|
||||||
<view class="box-border w-full flex flex-col items-center justify-center gap-y-4 overflow-hidden">
|
|
||||||
<view v-if="error && postList.length > 0" class="un-shadow-xs w-full rounded-2xl bg-white py-12">
|
|
||||||
<wd-empty :icon-size="60" icon="no-result" tip="暂无数据" />
|
|
||||||
</view>
|
|
||||||
<template v-else>
|
|
||||||
<post-card v-for="post in postList" :key="post.metadata.name" :post="post" type="topCover" />
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 底部导航占位 -->
|
|
||||||
<view class="h-60px w-full" />
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.uh-shadow-xs {
|
|
||||||
box-shadow: 0 0 24rpx rgba(0, 0, 0, 0.035);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import type { IUniHaloConfig } from '@/api/halo-plugin/uni-halo'
|
|||||||
import { deepMerge } from '@/utils/base/deepMerge'
|
import { deepMerge } from '@/utils/base/deepMerge'
|
||||||
|
|
||||||
const defaultConfig: IUniHaloConfig = {
|
const defaultConfig: IUniHaloConfig = {
|
||||||
baseURL: import.meta.env.VITE_SERVER_BASEURL,
|
baseURL: import.meta.env.VITE_UNI_HALO_BASEURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigsStoreKey = 'UNI_HALO_CONFIG'
|
const ConfigsStoreKey = 'UNI_HALO_CONFIG'
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const nativeTabbarList: NativeTabBarItem[] = [
|
|||||||
export const customTabbarList: CustomTabBarItem[] = [
|
export const customTabbarList: CustomTabBarItem[] = [
|
||||||
{
|
{
|
||||||
text: '%tabbar.home%',
|
text: '%tabbar.home%',
|
||||||
pagePath: 'pages/index/index',
|
pagePath: 'pages/home/home',
|
||||||
iconType: 'uiLib',
|
iconType: 'uiLib',
|
||||||
icon: 'home',
|
icon: 'home',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 数字单位格式化 k / w / m / b
|
||||||
|
* @param num 数字/数字字符串
|
||||||
|
* @param decimal 保留小数位数,默认 1
|
||||||
|
* @returns 格式化结果
|
||||||
|
*/
|
||||||
|
export function formatNumberUnit(num: number | string, decimal = 1): string {
|
||||||
|
const n = Number(num)
|
||||||
|
if (Number.isNaN(n))
|
||||||
|
return '0'
|
||||||
|
|
||||||
|
// 单位映射:阈值 / 除数 / 单位
|
||||||
|
const units = [
|
||||||
|
{ threshold: 1e9, divisor: 1e9, unit: 'b' },
|
||||||
|
{ threshold: 1e6, divisor: 1e6, unit: 'm' },
|
||||||
|
{ threshold: 1e4, divisor: 1e4, unit: 'w' },
|
||||||
|
{ threshold: 1e3, divisor: 1e3, unit: 'k' },
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const item of units) {
|
||||||
|
if (n >= item.threshold) {
|
||||||
|
const val = n / item.divisor
|
||||||
|
const fixedVal = val.toFixed(decimal)
|
||||||
|
// 去掉末尾 .0
|
||||||
|
return fixedVal.replace(/\.0$/, '') + item.unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 小于 1000 直接返回
|
||||||
|
return String(n)
|
||||||
|
}
|
||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 验证URL格式
|
||||||
|
*/
|
||||||
|
function url(value: string): boolean {
|
||||||
|
const urlRegex = /^(?:https?:)?\/\/(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(?::\d+)?(?:\/\S*)?$/
|
||||||
|
return urlRegex.test(value.trim())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证电子邮箱格式
|
* 验证电子邮箱格式
|
||||||
*/
|
*/
|
||||||
@@ -223,6 +231,7 @@ function string(value: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
url,
|
||||||
email,
|
email,
|
||||||
mobile,
|
mobile,
|
||||||
date,
|
date,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { completeUrl } from '@/utils/url'
|
||||||
|
import { getRandomUrl } from '@/utils/randomResources'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片封面处理
|
||||||
|
* @param cover 图片封面
|
||||||
|
* @returns 处理后的图片封面
|
||||||
|
*/
|
||||||
|
export function cover(cover: string) {
|
||||||
|
if (cover.trim()) {
|
||||||
|
return completeUrl(cover)
|
||||||
|
}
|
||||||
|
return getRandomUrl()
|
||||||
|
}
|
||||||
+7
-7
@@ -138,12 +138,12 @@ export function isCurrentPageTabbar() {
|
|||||||
*/
|
*/
|
||||||
export function getEnvBaseUrl() {
|
export function getEnvBaseUrl() {
|
||||||
// 请求基准地址
|
// 请求基准地址
|
||||||
let baseUrl = import.meta.env.VITE_SERVER_BASEURL
|
let baseUrl = import.meta.env.VITE_UNI_HALO_BASEURL
|
||||||
|
|
||||||
// # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
|
// # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
|
||||||
const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run'
|
const VITE_UNI_HALO_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run'
|
||||||
const VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run'
|
const VITE_UNI_HALO_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run'
|
||||||
const VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run'
|
const VITE_UNI_HALO_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run'
|
||||||
|
|
||||||
// 微信小程序端环境区分
|
// 微信小程序端环境区分
|
||||||
if (isMpWeixin) {
|
if (isMpWeixin) {
|
||||||
@@ -153,13 +153,13 @@ export function getEnvBaseUrl() {
|
|||||||
|
|
||||||
switch (envVersion) {
|
switch (envVersion) {
|
||||||
case 'develop':
|
case 'develop':
|
||||||
baseUrl = VITE_SERVER_BASEURL__WEIXIN_DEVELOP || baseUrl
|
baseUrl = VITE_UNI_HALO_BASEURL__WEIXIN_DEVELOP || baseUrl
|
||||||
break
|
break
|
||||||
case 'trial':
|
case 'trial':
|
||||||
baseUrl = VITE_SERVER_BASEURL__WEIXIN_TRIAL || baseUrl
|
baseUrl = VITE_UNI_HALO_BASEURL__WEIXIN_TRIAL || baseUrl
|
||||||
break
|
break
|
||||||
case 'release':
|
case 'release':
|
||||||
baseUrl = VITE_SERVER_BASEURL__WEIXIN_RELEASE || baseUrl
|
baseUrl = VITE_UNI_HALO_BASEURL__WEIXIN_RELEASE || baseUrl
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function getPicsum(width: number = 800, height?: number) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取随机图片URL
|
* 获取随机图片URL
|
||||||
* @param type 图片类型
|
* @param type 图片类型 默认pc
|
||||||
* @returns 随机图片URL
|
* @returns 随机图片URL
|
||||||
*/
|
*/
|
||||||
export function getRandomUrl(type?: randomUrlKeys) {
|
export function getRandomUrl(type?: randomUrlKeys) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
export const uploadFileUrl = {
|
export const uploadFileUrl = {
|
||||||
/** 用户头像上传地址 */
|
/** 用户头像上传地址 */
|
||||||
USER_AVATAR: `${import.meta.env.VITE_SERVER_BASEURL}/user/avatar`,
|
USER_AVATAR: `${import.meta.env.VITE_UNI_HALO_BASEURL}/user/avatar`,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+11
-8
@@ -1,13 +1,16 @@
|
|||||||
const HALO_BASEURL = import.meta.env.VITE_SERVER_BASEURL
|
import test from '@/utils/base/test'
|
||||||
|
|
||||||
|
const UNI_HALO_BASEURL = import.meta.env.VITE_UNI_HALO_BASEURL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete the URL with the base URL
|
* 补全URL
|
||||||
* @param url The URL to be completed
|
* @description 如果URL以http://或https://开头,则直接返回URL;否则,在URL前添加HALO_BASEURL
|
||||||
* @returns The completed URL
|
* @param url URL字符串
|
||||||
*/
|
* @returns 补全后的URL字符串
|
||||||
export function completeUrl (url: string): string {
|
*/
|
||||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
export function completeUrl(url: string): string {
|
||||||
|
if (test.url(url)) {
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
return HALO_BASEURL + url
|
return UNI_HALO_BASEURL + url
|
||||||
}
|
}
|
||||||
+2
-2
@@ -57,7 +57,7 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
const localEnv = loadEnv(mode, envDir, '')
|
const localEnv = loadEnv(mode, envDir, '')
|
||||||
const {
|
const {
|
||||||
VITE_APP_PORT,
|
VITE_APP_PORT,
|
||||||
VITE_SERVER_BASEURL,
|
VITE_UNI_HALO_BASEURL,
|
||||||
VITE_APP_TITLE,
|
VITE_APP_TITLE,
|
||||||
VITE_DELETE_CONSOLE,
|
VITE_DELETE_CONSOLE,
|
||||||
VITE_APP_PUBLIC_BASE,
|
VITE_APP_PUBLIC_BASE,
|
||||||
@@ -191,7 +191,7 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
proxy: JSON.parse(VITE_APP_PROXY_ENABLE)
|
proxy: JSON.parse(VITE_APP_PROXY_ENABLE)
|
||||||
? {
|
? {
|
||||||
[VITE_APP_PROXY_PREFIX]: {
|
[VITE_APP_PROXY_PREFIX]: {
|
||||||
target: VITE_SERVER_BASEURL,
|
target: VITE_UNI_HALO_BASEURL,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
// 后端有/api前缀则不做处理,没有则需要去掉
|
// 后端有/api前缀则不做处理,没有则需要去掉
|
||||||
rewrite: path =>
|
rewrite: path =>
|
||||||
|
|||||||
Reference in New Issue
Block a user