1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-09-12 16:40: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
@@ -0,0 +1,166 @@
<script lang="ts" setup>
/**
* 相册图片查看弹窗(源自旧项目 components/album-photo-viewer,新建复刻)
* 双列瀑布流展示相册照片,支持大图预览
*/
import { computed, ref, watch } from 'vue'
import { checkImageUrl } from '@/utils/url'
const props = withDefaults(defineProps<{
show: boolean
albumName?: string
photos?: IAlbumPhoto[]
loading?: boolean
}>(), {
albumName: '',
photos: () => [],
loading: false,
})
const emit = defineEmits<{
(e: 'update:show', show: boolean): void
}>()
export interface IAlbumPhoto {
name?: string
url?: string
title?: string
takenDate?: string
location?: string
description?: string
[key: string]: unknown
}
const isShow = ref(false)
watch(() => props.show, (val) => {
isShow.value = val
})
/** 预处理图片路径(相对路径拼接 BASE_API) */
const photoList = computed<IAlbumPhoto[]>(() =>
(props.photos || []).map(photo => ({
...photo,
url: checkImageUrl(photo.url || ''),
})),
)
/** 左列(偶数位照片,瀑布流错落) */
const leftPhotos = computed(() => photoList.value.filter((_, index) => index % 2 === 0))
/** 右列(奇数位照片) */
const rightPhotos = computed(() => photoList.value.filter((_, index) => index % 2 === 1))
function handleClose() {
isShow.value = false
emit('update:show', false)
}
/** 预览大图 */
function handlePreview(url?: string) {
const urls = photoList.value.map(photo => photo.url || '')
if (urls.length === 0) {
uni.showToast({ title: '相册暂无照片', icon: 'none' })
return
}
uni.previewImage({
current: url || urls[0],
urls,
})
}
</script>
<template>
<wd-popup v-model="isShow" position="center" custom-style="width:94vw;height:82vh;border-radius:12rpx;" @close="handleClose">
<view class="album-photo-viewer h-full w-full flex flex-col overflow-hidden rounded-xl bg-white">
<!-- 头部 -->
<view class="viewer-header box-border flex shrink-0 items-center justify-between border-b border-black/5 px-7 py-6">
<text class="viewer-title flex-1 overflow-hidden text-ellipsis whitespace-nowrap text-[32rpx] text-[#333] font-bold">{{ albumName }}</text>
<view class="viewer-close h-14 w-14 flex shrink-0 items-center justify-center rounded-full bg-black/5" @click="handleClose">
<wd-icon name="close" size="16px" color="#666" />
</view>
</view>
<!-- 照片列表 -->
<scroll-view class="viewer-body box-border min-h-0 flex-1" scroll-y :show-scrollbar="false">
<view v-if="loading" class="viewer-empty box-border h-full flex items-center justify-center p-10">
<view class="viewer-loading flex flex-col items-center">
<view class="loading-text mt-7 text-[28rpx] text-[#56bbf9]">
照片正在努力加载中啦~
</view>
</view>
</view>
<view v-else-if="photoList.length === 0" class="viewer-empty box-border h-full flex items-center justify-center p-10">
<wd-empty description="这个相册暂时还没有照片~" />
</view>
<view v-else class="photo-list box-border flex items-start p-5">
<!-- 左列 -->
<view class="photo-column box-border min-w-0 flex-1">
<view v-for="photo in leftPhotos" :key="photo.name" class="photo-card mb-6 box-border overflow-hidden rounded-xl bg-white shadow-sm">
<image
class="photo-image w-full"
:src="photo.url"
mode="widthFix"
lazy-load
@click="handlePreview(photo.url)"
/>
<view class="photo-info box-border px-6 py-5">
<view v-if="photo.title" class="photo-title mb-3 text-[30rpx] text-[#333] font-bold">
{{ photo.title }}
</view>
<view v-if="photo.takenDate || photo.location" class="photo-meta mb-3 flex flex-wrap items-center">
<text v-if="photo.takenDate" class="meta-item mr-8 text-[24rpx] text-[#999]">{{ photo.takenDate }}</text>
<text v-if="photo.location" class="meta-item mr-8 text-[24rpx] text-[#999]">{{ photo.location }}</text>
</view>
<view v-if="photo.description" class="photo-desc text-[26rpx] text-[#666] leading-[1.6]">
{{ photo.description }}
</view>
</view>
</view>
</view>
<!-- 右列 -->
<view class="photo-column box-border min-w-0 flex-1">
<view v-for="photo in rightPhotos" :key="photo.name" class="photo-card mb-6 box-border overflow-hidden rounded-xl bg-white shadow-sm">
<image
class="photo-image w-full"
:src="photo.url"
mode="widthFix"
lazy-load
@click="handlePreview(photo.url)"
/>
<view class="photo-info box-border px-6 py-5">
<view v-if="photo.title" class="photo-title mb-3 text-[30rpx] text-[#333] font-bold">
{{ photo.title }}
</view>
<view v-if="photo.takenDate || photo.location" class="photo-meta mb-3 flex flex-wrap items-center">
<text v-if="photo.takenDate" class="meta-item mr-8 text-[24rpx] text-[#999]">{{ photo.takenDate }}</text>
<text v-if="photo.location" class="meta-item mr-8 text-[24rpx] text-[#999]">{{ photo.location }}</text>
</view>
<view v-if="photo.description" class="photo-desc text-[26rpx] text-[#666] leading-[1.6]">
{{ photo.description }}
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<!-- 底部关闭 -->
<view class="viewer-footer box-border shrink-0 border-t border-black/5 px-7 py-5">
<view class="viewer-footer-btn h-20 flex items-center justify-center rounded-[40rpx]" style="background: linear-gradient(135deg, #f88ca2, #ff6b9d); box-shadow: 0 4rpx 24rpx rgb(248 140 162 / 35%);" @click="handleClose">
<text class="footer-text text-[30rpx] text-white font-bold"> </text>
</view>
</view>
</view>
</wd-popup>
</template>
<style scoped>
.album-photo-viewer {
/* 布局全部由 UnoCSS 原子类实现 */
.photo-column:first-child {
margin-right: 20rpx;
}
}
</style>