优化组件类型声明,添加页面描述元信息,更新依赖项,添加新图片,重构多个组件,改进画廊功能
This commit is contained in:
2
components.d.ts
vendored
2
components.d.ts
vendored
@ -29,9 +29,7 @@ declare module 'vue' {
|
||||
DSelect: typeof import('vue-devui/select/index.es.js')['Select']
|
||||
DTab: typeof import('vue-devui/tabs/index.es.js')['Tab']
|
||||
DTabs: typeof import('vue-devui/tabs/index.es.js')['Tabs']
|
||||
DUpload: typeof import('vue-devui/upload/index.es.js')['Upload']
|
||||
HomeSide: typeof import('./src/components/homeSide.vue')['default']
|
||||
Menu: typeof import('./src/components/menuH.vue')['default']
|
||||
MenuH: typeof import('./src/components/menuH.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="这是柚子的网站,做一些分享类的功能"/>
|
||||
<title>柚子の网站</title>
|
||||
</head>
|
||||
|
||||
|
||||
@ -15,9 +15,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@devui-design/icons": "^1.4.0",
|
||||
"@meting/core": "^1.5.13",
|
||||
"@unocss/reset": "^66.3.3",
|
||||
"aplayer": "^1.10.1",
|
||||
"axios": "^1.11.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"devui-theme": "^0.0.7",
|
||||
"es-toolkit": "^1.39.8",
|
||||
"less": "^4.4.0",
|
||||
@ -28,6 +30,7 @@
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-vue-components": "^28.8.0",
|
||||
"unplugin-vue-router": "^0.15.0",
|
||||
"vditor": "^3.11.2",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
"vue": "^3.6.0-alpha.2",
|
||||
"vue-devui": "^1.6.33",
|
||||
|
||||
BIN
src/assets/images/offwork.png
Normal file
BIN
src/assets/images/offwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 586 KiB |
BIN
src/assets/images/onwork.png
Normal file
BIN
src/assets/images/onwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 741 KiB |
@ -30,14 +30,20 @@ const data: any = reactive({
|
||||
|
||||
onMounted(async () => {
|
||||
// 8834041785
|
||||
const res = await fetch("https://met.hxyouzi.com/meting-api/?server=tencent&type=playlist&id=7567066822")
|
||||
// const res = await fetch("https://met.hxyouzi.com/meting-api/?server=tencent&type=playlist&id=7567066822")
|
||||
// const res = await fetch("https://api.moeyao.cn/meting/?server=tencent&type=playlist&id=8834041785")
|
||||
const mlist = await res.json()
|
||||
// const mlist = await res.json()
|
||||
const metto = 'youzi'
|
||||
const server = 'tencent'
|
||||
const gdid = '7567066822'
|
||||
let ck = 'RK=beuVmBI+x3; ptcz=08924c0c66c35b66361f002fb0b3005ff0f2144404f548f8728b167ffb3dc25d; pgv_pvid=2605897556; fqm_pvqid=c38eee7f-1f49-4867-8fb4-8dbb764cb93b; ts_uid=4584087650; pac_uid=0_xXEQBtbyPnKSj; omgid=0_SK8mZi6ZyjtN4; _qimei_q32=d611a6803057686110470945b0c17a21; _qimei_q36=fcef018f916225c22be032db30001e219617; _qimei_h38=e8d664cf2171af215382857302000000719801; eas_sid=I1j7m5e9o2O188P6Y4P7D745Z4; fqm_sessionid=f2c44c43-4d85-4dcb-99c0-cef6d6e2b0cb; pgv_info=ssid=s1311374400; ts_last=y.qq.com/; ts_refer=cn.bing.com/; _qpsvr_localtk=0.1390152059728047; login_type=1; psrf_access_token_expiresAt=1765271149; psrf_qqopenid=DE4C1520CB81DEEF7C0BE8E9B0FD2783; wxrefresh_token=; music_ignore_pskey=202306271436Hn@vBj; wxunionid=; euin=owv5oeCioiEAoz**; wxopenid=; tmeLoginType=2; psrf_qqrefresh_token=A9707E145813679F3654C6E051AA3E2F; psrf_qqaccess_token=C0591D34DF4A719D28815DBA71122DC5; psrf_musickey_createtime=1760087149; psrf_qqunionid=AD81CE40E407AFA9A2F984D05F7F5CD6; uin=2410633923; qm_keyst=Q_H_L_63k3NMFc5RtmTBDyGhskoc5AjaymIKYUZThRS2bJfh0AHztt8D10MRy1XN-MEAUtIkdF_oauym2Y51IbgjNvw1Wu8hZECDA; qqmusic_key=Q_H_L_63k3NMFc5RtmTBDyGhskoc5AjaymIKYUZThRS2bJfh0AHztt8D10MRy1XN-MEAUtIkdF_oauym2Y51IbgjNvw1Wu8hZECDA'
|
||||
const res = await fetch(`https://met.hxyouzi.com/api?server=${server}&type=playlist&id=${gdid}`)
|
||||
let mlist: any = await res.json()
|
||||
data.audio = []
|
||||
mlist.forEach((i: any) => {
|
||||
data.audio.push({
|
||||
title: i.name,
|
||||
author: i.artist,
|
||||
title: i.title,
|
||||
author: i.author,
|
||||
url: i.url,
|
||||
pic: i.pic,
|
||||
lrc: i.lrc,
|
||||
|
||||
@ -1,37 +1,27 @@
|
||||
<template>
|
||||
<div class="pr-8">
|
||||
<!-- <d-card shadow="never" class="mt-10 bg-white"> -->
|
||||
<div class="dt-card mt-10 bg-white">
|
||||
<!-- <template #title> -->
|
||||
<d-card shadow="never" class="mt-4 bg-white">
|
||||
<!-- <div class="dt-card mt-10 bg-white"> -->
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<icon-time class="w-5 mr-2"></icon-time>
|
||||
时间日期
|
||||
</div>
|
||||
<!-- </template> -->
|
||||
<!-- <template #content> -->
|
||||
<div class="w-full text-center text-[#ec66ab] font-500 text-4xl font-[yj]">{{ t }}</div>
|
||||
<div class="mt-3 text-right">{{ d }}</div>
|
||||
<!-- </template> -->
|
||||
</div>
|
||||
<!-- </d-card> -->
|
||||
|
||||
<d-card shadow="never" class="mt-10 bg-white">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<icon-date class="w-5 mr-2"></icon-date>
|
||||
农历节气
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="w-full text-center text-[#ec66ab] font-500">{{ jq.yearTips }}年 {{ jq.lunarCalendar }}</div>
|
||||
<div class="w-full flex justify-center">
|
||||
<img class="mt-2 w-[90%] rounded" :src="jqImg" alt=""></img>
|
||||
<div class="w-full pr-20 text-center text-[#ec66ab] font-500 text-4xl font-[yj]">{{ t }}</div>
|
||||
<div class="mt-3 flex justify-between">
|
||||
<span>今年已过了{{ jq.dayOfYear }}天</span>
|
||||
{{ d }}
|
||||
</div>
|
||||
<div class="mt-2 text-center">{{ jq.solarTerms }}</div>
|
||||
<img v-if="jq.type != 0" class="absolute top-0 right-4" width="120" src="@/assets/images/offwork.png" alt="">
|
||||
<img v-else class="absolute top-0 right-4" width="120" src="@/assets/images/onwork.png" alt="">
|
||||
</template>
|
||||
<!-- </div> -->
|
||||
</d-card>
|
||||
|
||||
<d-card shadow="never" class="mt-10 bg-white">
|
||||
|
||||
<d-card shadow="never" class="mt-4 bg-white">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<icon-news class="w-5 mr-2"></icon-news>
|
||||
@ -59,6 +49,30 @@
|
||||
</div>
|
||||
</template>
|
||||
</d-card>
|
||||
|
||||
|
||||
<d-card shadow="never" class="mt-4 bg-white">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<icon-date class="w-5 mr-2"></icon-date>
|
||||
农历节气
|
||||
<div class="ml-12 text-[#ec66ab] font-500">{{ jq.yearTips }}年 {{ jq.lunarCalendar }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="truncate text-sm mx-[5%]">
|
||||
宜:{{ jq.suit }}
|
||||
</div>
|
||||
<div class="truncate text-sm mx-[5%]">
|
||||
忌:{{ jq.avoid }}
|
||||
</div>
|
||||
<div class="w-full flex justify-center">
|
||||
<img class="mt-2 w-[90%] rounded" :src="jqImg" alt=""></img>
|
||||
</div>
|
||||
<div class="mt-2 text-center">{{ jq.solarTerms }}</div>
|
||||
</template>
|
||||
</d-card>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -119,9 +133,8 @@ onUnmounted(() => {
|
||||
src: url('@/assets/font/LCDML.woff2');
|
||||
}
|
||||
|
||||
.dt-card {
|
||||
background-image: url('@/assets/images/中秋节中国风边框34.png');
|
||||
background-size: 100% 100%;
|
||||
padding: 20px 40px;
|
||||
}
|
||||
</style>
|
||||
// .dt-card {
|
||||
// background-image: url('@/assets/images/中秋节中国风边框34.png');
|
||||
// background-size: 100% 100%;
|
||||
// padding: 20px 40px;
|
||||
// }</style>
|
||||
@ -32,8 +32,8 @@
|
||||
</d-menu-item>
|
||||
</d-menu>
|
||||
<!-- 用户区域 -->
|
||||
<div class="!text-[#ec66ab] user-area flex items-center px-3">
|
||||
<span class="flex items-center location-info ">
|
||||
<div class="!text-[#ec66ab] flex items-center" @click="gotoHf">
|
||||
<span class="flex items-center location-info truncate">
|
||||
<d-icon color="#ec66ab" class="mr-1" name="location-new"></d-icon>
|
||||
{{ locationInfo }}
|
||||
</span>
|
||||
@ -41,8 +41,11 @@
|
||||
<span class="weather-info mr-2">{{ wea }}</span>
|
||||
<i :class="'qiIcon qi-' + weaIcon + '-fill'"></i>
|
||||
<span class="weather-info ml-4">{{ temp }}°C</span>
|
||||
<d-avatar v-if="userinfo" :img-src="userinfo.ava_url" class="ml-20 cursor-pointer" alt="用户的头" />
|
||||
<d-avatar v-else class="ml-20 cursor-pointer" @click="toLogin"></d-avatar>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center ">
|
||||
<d-avatar v-if="userinfo" :img-src="userinfo.ava_url" class="ml-10 mr-4 cursor-pointer" alt="用户的头" />
|
||||
<d-avatar v-else class="ml-10 mr-4 cursor-pointer" @click="toLogin"></d-avatar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -69,6 +72,7 @@ const key = ref("home");
|
||||
const locationInfo = ref("获取位置中...");
|
||||
const latitude = ref<number | null>(null);
|
||||
const longitude = ref<number | null>(null);
|
||||
const fxlink = ref<string>("#")
|
||||
const wea = ref("")
|
||||
const weaIcon = ref<string>("")
|
||||
const temp = ref<number>(0);
|
||||
@ -96,13 +100,13 @@ const getLocation = () => {
|
||||
async (error) => {
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
locationInfo.value = "用户拒绝了位置请求";
|
||||
locationInfo.value = "正在定位...";
|
||||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
locationInfo.value = "位置信息不可用";
|
||||
locationInfo.value = "正在定位...";
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
locationInfo.value = "获取位置超时";
|
||||
locationInfo.value = "正在定位...";
|
||||
break;
|
||||
}
|
||||
const res = await $http.mix.getIp();
|
||||
@ -125,11 +129,12 @@ async function handdleJw(jw: string) {
|
||||
const zxs = ['北京', '重庆', '天津', '上海']
|
||||
// 根据经纬度获取物理位置
|
||||
const loc = await $http.mix.getLocation({ location: jw });
|
||||
console.log(loc);
|
||||
console.log('>>> --> handdleJw --> loc:', loc)
|
||||
fxlink.value = loc.data.fxLink
|
||||
if (loc.code == 200) {
|
||||
const data = loc.data;
|
||||
if (zxs.includes(data.adm2)) {
|
||||
locationInfo.value = `${data.country}${data.adm1}${data.name}`;
|
||||
locationInfo.value = `${data.adm1}${data.name}`;
|
||||
} else {
|
||||
locationInfo.value = `${data.adm1}${data.adm2}${data.name}`;
|
||||
}
|
||||
@ -138,7 +143,7 @@ async function handdleJw(jw: string) {
|
||||
return
|
||||
}
|
||||
const res = await $http.mix.getWeather({ location: jw });
|
||||
console.log(res);
|
||||
console.log('>>> --> handdleJw --> res:', res)
|
||||
if (res.code == 200) {
|
||||
wea.value = res.data.text;
|
||||
weaIcon.value = res.data.icon;
|
||||
@ -158,11 +163,17 @@ function goHome() {
|
||||
}
|
||||
|
||||
function toLogin() {
|
||||
console.log('>>> --> toLogin --> toLogin:', 'toLogin')
|
||||
|
||||
if ($cookies.get('token')) return
|
||||
router.push('/login');
|
||||
}
|
||||
|
||||
function gotoHf(){
|
||||
console.log('>>> --> gotoHf --> fxlink:', fxlink)
|
||||
window.open(fxlink.value,"_BLACK")
|
||||
|
||||
}
|
||||
onMounted(() => {
|
||||
|
||||
userinfo.value = $cookies.get('userinfo');
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div class="article-page">
|
||||
<h1>文章页</h1>
|
||||
<!-- 文章内容 -->
|
||||
<div id="vditor"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Vditor from 'vditor';
|
||||
import 'vditor/dist/index.css';
|
||||
import { onMounted, ref } from 'vue';
|
||||
definePage({
|
||||
name: 'article',
|
||||
meta: {
|
||||
@ -13,6 +15,14 @@ definePage({
|
||||
}
|
||||
})
|
||||
// 文章页逻辑
|
||||
const vditor:any = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
vditor.value = new Vditor('vditor', {
|
||||
height: '100vh',
|
||||
width: '100vw'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
<template>
|
||||
<PerfectScrollbar ref="scrollbar" @ps-scroll-y="handleScroll">
|
||||
<div ref="myCon" class="gallery-page py-5 px-[10%]">
|
||||
<d-tabs v-model="tid" type="options" :before-change="beforeChange" @active-tab-change.native="activeTabChange">
|
||||
<d-tab id="share" title="画廊">
|
||||
<d-search class="mt-0 mb-8 w-2/3 mx-auto rounded-full" v-model="kw" is-keyup-search :delay="1000"
|
||||
@search="onSearch"></d-search>
|
||||
<div class="gallery-container w-full box-border">
|
||||
@ -31,86 +29,14 @@
|
||||
<div v-if="loading" class="loading-indicator text-center p-5 text-gray-600">加载中...</div>
|
||||
<div v-else class="loading-indicator text-center p-5 text-gray-600">已全部加载完成</div>
|
||||
</div>
|
||||
</d-tab>
|
||||
<d-tab id="my" title="我的">
|
||||
<div>
|
||||
<d-upload class="py-8 upload-demo border-2 border-dashed border-gray-300 rounded-md p-4"
|
||||
:on-success="handleSuccess" :upload-options="uploadOptions" droppable="true">
|
||||
<div class="w-full h-full flex flex-col items-center justify-center">
|
||||
<div><d-icon name="upload" size="32px"></d-icon></div>
|
||||
<div class="my-2">
|
||||
将文件拖到此处,或
|
||||
<span class="devui-link text-[#ec66ab]">点击上传</span>
|
||||
</div>
|
||||
<div class="text-sm text-gray-500">注意图片大小不要大于5MB哟~</div>
|
||||
</div>
|
||||
</d-upload>
|
||||
</div>
|
||||
<div class="gallery-container w-full box-border">
|
||||
<!-- 瀑布流容器 -->
|
||||
<div ref="waterfallContainer" v-image-preview
|
||||
class="waterfall-container flex justify-between flex-nowrap w-full overflow-hidden">
|
||||
<!-- 动态生成的列 -->
|
||||
<div v-for="(column, index) in columns" :key="index" class="waterfall-column flex flex-col w-[240px]">
|
||||
<div v-for="item in column" :key="item.id"
|
||||
class="gallery-item group relative my-[10px] rounded-lg overflow-hidden transition-transform duration-300 box-border hover:-translate-y-1.5">
|
||||
<div
|
||||
class="px-2 truncate absolute hidden group-hover:block top-0 text-center w-full bg-[#00000070] text-white">
|
||||
{{ item.filename }}
|
||||
</div>
|
||||
<img :src="item.filepath" alt="" class="gallery-image block w-full h-auto object-cover rounded-md">
|
||||
<div class="pr-2 absolute bottom-0 flex justify-between items-center w-full bg-[#00000060]">
|
||||
<div class="text-white ">
|
||||
<span class="px-2 py-1 bg-primary rounded-full" v-if="item.share">已共享</span>
|
||||
<span class="px-2 py-1 bg-[#ffa500] rounded-full" v-else>未共享</span>
|
||||
</div>
|
||||
<div class="icon flex items-center">
|
||||
<d-popover content="下载" trigger="hover" class="!bg-primary" style="color: #fff">
|
||||
<icon-download @click="downloadFile(item.filepath)"
|
||||
class="w-5 h-5 mr-2 text-white hover-text-primary"></icon-download>
|
||||
</d-popover>
|
||||
<d-popover v-if="item.share" content="取消共享" trigger="hover" class="!bg-primary"
|
||||
style="color: #fff">
|
||||
<icon-lock @click="handdleShare(item.pid, item.share)"
|
||||
class="w-5 h-5 text-white hover-text-primary"></icon-lock>
|
||||
</d-popover>
|
||||
<d-popover v-else content="共享" trigger="hover" class="!bg-primary" style="color: #fff">
|
||||
<icon-unlock @click="handdleShare(item.pid, item.share)"
|
||||
class="w-5 h-5 text-white hover-text-primary"></icon-unlock>
|
||||
</d-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 加载中指示器 -->
|
||||
<div v-if="loading" class="loading-indicator text-center p-5 text-gray-600">加载中...</div>
|
||||
<div v-else class="loading-indicator text-center p-5 text-gray-600">已全部加载完成</div>
|
||||
</div>
|
||||
</d-tab>
|
||||
</d-tabs>
|
||||
</div>
|
||||
<Teleport to="body">
|
||||
<div>
|
||||
<img class="fixed top-10 -left-2" :src="tao" alt="">
|
||||
<img class="fixed bottom-10 left-0 w-44" :src="sword" alt="">
|
||||
<img class="fixed bottom-0 right-5 w-25" :src="psword" alt="">
|
||||
<img class="fixed top-[56px] right-0" :src="denglong" alt="">
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
|
||||
</PerfectScrollbar>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import psword from "@/assets/images/剑-粉.png";
|
||||
import sword from "@/assets/images/剑.png";
|
||||
import tao from "@/assets/images/树枝桃.png";
|
||||
import denglong from "@/assets/images/灯笼.png";
|
||||
import { throttle } from 'es-toolkit';
|
||||
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
definePage({
|
||||
name: 'gallery',
|
||||
@ -121,7 +47,6 @@ definePage({
|
||||
|
||||
|
||||
// 画廊页逻辑
|
||||
const tid = ref('share');
|
||||
const fileList = ref<any[]>([]);
|
||||
const pn = ref(1);
|
||||
const ps = ref(40);
|
||||
@ -130,23 +55,17 @@ const waterfallContainer = ref<HTMLDivElement | null>(null);
|
||||
const columns = ref<Array<Array<any>>>([]);
|
||||
const columnHeights = ref<number[]>([]);
|
||||
const columnCount = ref(4); // 默认列数
|
||||
const imageHeights = ref<Record<string, number>>({}); // 存储每张图片的实际高度
|
||||
const imagesLoaded = ref(0);
|
||||
const itemWidth = ref(240); // 图片宽度固定为220px
|
||||
const scrollbar = ref<any>(null);
|
||||
const itemWidth = ref(240); // 图片宽度固定为240px
|
||||
const kw = ref<string>('');
|
||||
const myCon = ref<HTMLDivElement | null>(null);
|
||||
|
||||
const uploadOptions = ref({
|
||||
uri: 'https://www.hxyouzi.com/api/files/upload',
|
||||
method: 'POST',
|
||||
maximumSize: 5 * 1024 * 1024,
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + $cookies.get('token'),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// const uploadOptions = ref({
|
||||
// uri: 'https://www.hxyouzi.com/api/files/upload',
|
||||
// method: 'POST',
|
||||
// maximumSize: 5 * 1024 * 1024,
|
||||
// headers: {
|
||||
// 'Authorization': 'Bearer ' + $cookies.get('token'),
|
||||
// },
|
||||
// });
|
||||
|
||||
// 计算列数 based on 屏幕宽度
|
||||
function calculateColumnCount() {
|
||||
@ -164,7 +83,8 @@ function resetWaterfall() {
|
||||
columns.value = Array(columnCount.value).fill(0).map(() => []);
|
||||
columnHeights.value = Array(columnCount.value).fill(0);
|
||||
// 重新分配图片
|
||||
fileList.value.forEach(item => addToWaterfall(item));
|
||||
fileList.value.forEach(async item =>await addToWaterfall(item));
|
||||
console.log('>>> --> resetWaterfall --> fileList:', fileList.value)
|
||||
}
|
||||
|
||||
// 添加图片到瀑布流
|
||||
@ -175,53 +95,34 @@ async function addToWaterfall(item: any) {
|
||||
// 找到高度最小的列
|
||||
let minHeight = Math.min(...columnHeights.value);
|
||||
let minIndex = columnHeights.value.indexOf(minHeight);
|
||||
console.log('>>> --> addToWaterfall --> item:', item)
|
||||
console.log('>>> --> addToWaterfall --> minIndex:', minIndex)
|
||||
// 添加到该列
|
||||
columns.value[minIndex].push(item);
|
||||
// 估算列高 - 实际高度会在图片加载后更新
|
||||
|
||||
const estimatedHeight = itemWidth.value * height / width // 假设1:1比例
|
||||
const estimatedHeight = itemWidth.value * height / width
|
||||
columnHeights.value[minIndex] += estimatedHeight + 20; // 加上padding和margin
|
||||
}
|
||||
|
||||
// 图片加载完成后更新瀑布流
|
||||
function onImageLoad(id: string) {
|
||||
// 等待DOM更新
|
||||
nextTick(() => {
|
||||
if (!waterfallContainer.value) return;
|
||||
const imgElements = waterfallContainer.value.querySelectorAll(`.gallery-image[src*="${id}"]`);
|
||||
if (imgElements.length > 0) {
|
||||
const img = imgElements[0] as HTMLImageElement;
|
||||
imageHeights.value[id] = img.height;
|
||||
updateColumnHeights();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getImageSizeByCheck(url: string): any {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
let image = new Image();
|
||||
image.src = url;
|
||||
let height = 0
|
||||
let width = 0
|
||||
let timer = setTimeout(() => {
|
||||
// let timer = setTimeout(() => {
|
||||
image.onload = () => {
|
||||
if (image.width > 0 && image.height > 0) {
|
||||
height = image.height
|
||||
width = image.width
|
||||
resolve({ height, width })
|
||||
clearTimeout(timer)
|
||||
// clearTimeout(timer)
|
||||
}
|
||||
}, 40)
|
||||
}
|
||||
// }, 100)
|
||||
});
|
||||
}
|
||||
|
||||
// 更新所有列的高度
|
||||
function updateColumnHeights() {
|
||||
if (!waterfallContainer.value) return;
|
||||
const columnElements = waterfallContainer.value.querySelectorAll('.waterfall-column');
|
||||
columnHeights.value = Array.from(columnElements).map(el => el.clientHeight);
|
||||
}
|
||||
|
||||
// 获取文件列表
|
||||
async function getFileList() {
|
||||
if (loading.value) return;
|
||||
@ -251,33 +152,33 @@ async function getFileList() {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取我的文件列表
|
||||
async function getMyList() {
|
||||
if (loading.value) return;
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await $http.file.getMyList({
|
||||
page_num: pn.value,
|
||||
page_size: ps.value,
|
||||
});
|
||||
// console.log('>>> --> getFileList --> res:', res);
|
||||
// // 获取我的文件列表
|
||||
// async function getMyList() {
|
||||
// if (loading.value) return;
|
||||
// loading.value = true;
|
||||
// try {
|
||||
// const res = await $http.file.getMyList({
|
||||
// page_num: pn.value,
|
||||
// page_size: ps.value,
|
||||
// });
|
||||
// // console.log('>>> --> getFileList --> res:', res);
|
||||
|
||||
if (pn.value === 1) {
|
||||
fileList.value = res.data;
|
||||
resetWaterfall();
|
||||
} else {
|
||||
// 追加新数据
|
||||
res.data.forEach((item: any) => {
|
||||
fileList.value.push(item);
|
||||
addToWaterfall(item);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取文件列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
// if (pn.value === 1) {
|
||||
// fileList.value = res.data;
|
||||
// resetWaterfall();
|
||||
// } else {
|
||||
// // 追加新数据
|
||||
// res.data.forEach((item: any) => {
|
||||
// fileList.value.push(item);
|
||||
// addToWaterfall(item);
|
||||
// });
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error('获取文件列表失败:', error);
|
||||
// } finally {
|
||||
// loading.value = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 监听滚动事件
|
||||
const handleScroll: any = throttle((e: any) => {
|
||||
@ -302,42 +203,6 @@ function onSearch() {
|
||||
getFileList();
|
||||
}
|
||||
|
||||
function beforeChange(tabId: string) {
|
||||
myCon.value?.scrollIntoView(true)
|
||||
if (tabId === 'my') {
|
||||
// 我的画廊,不加载更多
|
||||
if (!$cookies.get('token')) {
|
||||
$msg.error('请先登录');
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
function activeTabChange(tabId: string) {
|
||||
pn.value = 1;
|
||||
kw.value = '';
|
||||
fileList.value = [];
|
||||
resetWaterfall();
|
||||
if (tabId === 'my') {
|
||||
// console.log('>>> --> activeTabChange --> tabId:', tabId)
|
||||
getMyList()
|
||||
} else if (tabId === 'share') {
|
||||
getFileList();
|
||||
}
|
||||
|
||||
}
|
||||
function handleSuccess(res: any) {
|
||||
console.log('>>> --> handleSuccess --> res:', res)
|
||||
const code = JSON.parse(res[0].response).code
|
||||
if (code === 200) {
|
||||
$msg.success('上传成功');
|
||||
getMyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function downloadFile(url: string) {
|
||||
console.log('>>> --> downloadFile --> url:', url)
|
||||
// 创建临时a标签
|
||||
@ -358,35 +223,6 @@ function downloadFile(url: string) {
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
async function handdleShare(id: string, share: boolean | number) {
|
||||
console.log('>>> --> handdleShare --> id:', id)
|
||||
console.log('>>> --> handdleShare --> share:', share)
|
||||
try {
|
||||
const res = await $http.file.putShare({
|
||||
pid: id,
|
||||
share: Number(!share),
|
||||
|
||||
})
|
||||
console.log('>>> --> handdleShare --> res:', res)
|
||||
if (res.code === 200) {
|
||||
$msg.success('共享成功');
|
||||
pn.value = 1;
|
||||
fileList.value = [];
|
||||
resetWaterfall();
|
||||
getMyList();
|
||||
console.log('>>> --> handdleShare --> myCon.value:', myCon.value?.scrollTop)
|
||||
if (myCon.value) {
|
||||
myCon.value.scrollIntoView(true)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('共享文件失败:', error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
getFileList();
|
||||
// 计算初始列数
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
</div>
|
||||
<!-- 图片网格展示区域 -->
|
||||
<PerfectScrollbar class="" :style="navStyle">
|
||||
<div class="navcard grid-cols-5 gap-6 p-12">
|
||||
<div class="navcard grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 gap-6 p-12">
|
||||
<d-card class="bg-[#ffffff80] h-25" v-for="(item, index) in navlist" :key="index"
|
||||
@click="goExtra(item.menu_link)">
|
||||
<template #content>
|
||||
@ -22,8 +22,8 @@
|
||||
<div :style="{ background: item.color }"
|
||||
class="w-8 h-8 rounded-full text-white flex items-center justify-center" v-if="item.icon_error">
|
||||
{{ item.first }}</div>
|
||||
<img v-else width="32" :src="item.menu_icon" @error="imgErr(index)" class="grid-image" />
|
||||
<div class="mt-2 w-full text-center text-lg">{{ item.menu_name || "" }}</div>
|
||||
<img class="grid-image w-8 h-8 rounded-full" v-else :src="item.menu_icon" @error="imgErr(index)" />
|
||||
<div class="mt-2 w-full text-center text-lg truncate">{{ item.menu_name || "" }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</d-card>
|
||||
@ -132,8 +132,7 @@ const navlist: any = ref([])
|
||||
|
||||
async function getNavList() {
|
||||
const res = await $http.nav.getNavList()
|
||||
|
||||
res.data.forEach((i: any) => {
|
||||
res.data?.forEach((i: any) => {
|
||||
i.icon_error = false
|
||||
i.first = i.menu_name.at(0)
|
||||
i.color = getRandomDarkColor()
|
||||
@ -239,13 +238,14 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
/* 首页样式 */
|
||||
/* 首页样式
|
||||
.main-content {
|
||||
background-image: url('@/assets/images/小鹿.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: 111% center;
|
||||
background-size: auto 100%;
|
||||
}
|
||||
*/
|
||||
.navcard {
|
||||
display: grid;
|
||||
|
||||
|
||||
22
yarn.lock
22
yarn.lock
@ -518,6 +518,11 @@
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@meting/core@^1.5.13":
|
||||
version "1.5.13"
|
||||
resolved "https://registry.npmmirror.com/@meting/core/-/core-1.5.13.tgz#d5178b99124e5ba8e5cef36ca70d6e63d7426339"
|
||||
integrity sha512-9jVXr6IWNn+4undmM+NDIxa1p7ROcHHLh4x1vCcZGh45fsV4Xh93sEwGNE6YpNMoK2aEfhBvregqGcE2l8bVCw==
|
||||
|
||||
"@polka/url@^1.0.0-next.24":
|
||||
version "1.0.0-next.29"
|
||||
resolved "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1"
|
||||
@ -1560,6 +1565,11 @@ cross-spawn@^7.0.6:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
|
||||
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
|
||||
|
||||
css-select@^5.1.0:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e"
|
||||
@ -2214,6 +2224,11 @@ devui-theme@^0.0.7:
|
||||
resolved "https://registry.npmmirror.com/devui-theme/-/devui-theme-0.0.7.tgz#978a8a32aa7c097430350c586f0ba819e63e6a9f"
|
||||
integrity sha512-sJWnkqOvqqVyvqaqyXn3/F+SIlNuoPUGdxG6TyDXuzZSAigWMuQsz8v8JJYTKL2Ash1q8kAKfRT01SqZmvlByA==
|
||||
|
||||
diff-match-patch@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmmirror.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
|
||||
integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==
|
||||
|
||||
diff2html@^3.4.35:
|
||||
version "3.4.52"
|
||||
resolved "https://registry.npmmirror.com/diff2html/-/diff2html-3.4.52.tgz#5bb6d169a0d7cb20710596600cbd851499da2d92"
|
||||
@ -3626,6 +3641,13 @@ uuid@^9.0.1:
|
||||
resolved "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
|
||||
vditor@^3.11.2:
|
||||
version "3.11.2"
|
||||
resolved "https://registry.npmmirror.com/vditor/-/vditor-3.11.2.tgz#612a405c74b71278a4eea188db3c7d93c0884c11"
|
||||
integrity sha512-8QguQQUPWbBFocnfQmWjz4jiykQnvsmCuhOomGIVVK7vc+dQq2h8w9qQQuEjUTZpnZT5fEdYbj4aLr1NGdAZaA==
|
||||
dependencies:
|
||||
diff-match-patch "^1.0.5"
|
||||
|
||||
vite-dev-rpc@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmmirror.com/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz#a54be63cc4dbb127bce1360e4b12d9038087c204"
|
||||
|
||||
Reference in New Issue
Block a user