feat:在个人展示页显示光栅卡
This commit is contained in:
parent
5f4a443a93
commit
3e6ff3c898
@ -616,6 +616,7 @@ func (ctrl *GalleryController) GetMyExhibitedAssets(c *gin.Context) {
|
|||||||
ExpireAt: item.ExpireAt,
|
ExpireAt: item.ExpireAt,
|
||||||
Earnings: item.Earnings,
|
Earnings: item.Earnings,
|
||||||
SlotIndex: item.SlotIndex,
|
SlotIndex: item.SlotIndex,
|
||||||
|
IsLenticular: item.IsLenticular,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,6 +806,7 @@ func (ctrl *GalleryController) GetUserExhibitedAssets(c *gin.Context) {
|
|||||||
ExpireAt: item.ExpireAt,
|
ExpireAt: item.ExpireAt,
|
||||||
Earnings: item.Earnings,
|
Earnings: item.Earnings,
|
||||||
SlotIndex: item.SlotIndex,
|
SlotIndex: item.SlotIndex,
|
||||||
|
IsLenticular: item.IsLenticular,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -81,6 +81,7 @@ type ExhibitedAssetItemDTO struct {
|
|||||||
ExpireAt int64 `json:"expire_at"` // 展出过期时间(毫秒时间戳)
|
ExpireAt int64 `json:"expire_at"` // 展出过期时间(毫秒时间戳)
|
||||||
Earnings int64 `json:"earnings"` // 当前可领取收益
|
Earnings int64 `json:"earnings"` // 当前可领取收益
|
||||||
SlotIndex int32 `json:"slot_index"` // 展位序号
|
SlotIndex int32 `json:"slot_index"` // 展位序号
|
||||||
|
IsLenticular bool `json:"is_lenticular"` // 是否为光栅卡
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMyExhibitedAssetsResponseDTO 获取我展出的作品列表响应
|
// GetMyExhibitedAssetsResponseDTO 获取我展出的作品列表响应
|
||||||
|
|||||||
@ -1223,6 +1223,7 @@ type ExhibitedAssetItem struct {
|
|||||||
ExpireAt int64 `protobuf:"varint,6,opt,name=expire_at,json=expireAt,proto3" json:"expire_at,omitempty"` // 展出过期时间(毫秒时间戳)
|
ExpireAt int64 `protobuf:"varint,6,opt,name=expire_at,json=expireAt,proto3" json:"expire_at,omitempty"` // 展出过期时间(毫秒时间戳)
|
||||||
Earnings int64 `protobuf:"varint,7,opt,name=earnings,proto3" json:"earnings,omitempty"` // 当前可领取收益
|
Earnings int64 `protobuf:"varint,7,opt,name=earnings,proto3" json:"earnings,omitempty"` // 当前可领取收益
|
||||||
SlotIndex int32 `protobuf:"varint,8,opt,name=slot_index,json=slotIndex,proto3" json:"slot_index,omitempty"` // 展位序号
|
SlotIndex int32 `protobuf:"varint,8,opt,name=slot_index,json=slotIndex,proto3" json:"slot_index,omitempty"` // 展位序号
|
||||||
|
IsLenticular bool `protobuf:"varint,9,opt,name=is_lenticular,json=isLenticular,proto3" json:"is_lenticular,omitempty"` // 是否为光栅卡(根据 tags 判断)
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@ -1313,6 +1314,13 @@ func (x *ExhibitedAssetItem) GetSlotIndex() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ExhibitedAssetItem) GetIsLenticular() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.IsLenticular
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 获取灵感瀑布藏品列表请求
|
// 获取灵感瀑布藏品列表请求
|
||||||
type GetInspirationFlowRequest struct {
|
type GetInspirationFlowRequest struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
@ -1809,7 +1817,7 @@ const file_gallery_proto_rawDesc = "" +
|
|||||||
"\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" +
|
"\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" +
|
||||||
"\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x14\n" +
|
"\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x14\n" +
|
||||||
"\x05total\x18\x04 \x01(\x03R\x05total\x12\x19\n" +
|
"\x05total\x18\x04 \x01(\x03R\x05total\x12\x19\n" +
|
||||||
"\bhas_more\x18\x05 \x01(\bR\ahasMore\"\xfa\x01\n" +
|
"\bhas_more\x18\x05 \x01(\bR\ahasMore\"\x9f\x02\n" +
|
||||||
"\x12ExhibitedAssetItem\x12\x19\n" +
|
"\x12ExhibitedAssetItem\x12\x19\n" +
|
||||||
"\basset_id\x18\x01 \x01(\x03R\aassetId\x12\x12\n" +
|
"\basset_id\x18\x01 \x01(\x03R\aassetId\x12\x12\n" +
|
||||||
"\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" +
|
"\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" +
|
||||||
@ -1820,7 +1828,8 @@ const file_gallery_proto_rawDesc = "" +
|
|||||||
"\texpire_at\x18\x06 \x01(\x03R\bexpireAt\x12\x1a\n" +
|
"\texpire_at\x18\x06 \x01(\x03R\bexpireAt\x12\x1a\n" +
|
||||||
"\bearnings\x18\a \x01(\x03R\bearnings\x12\x1d\n" +
|
"\bearnings\x18\a \x01(\x03R\bearnings\x12\x1d\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"slot_index\x18\b \x01(\x05R\tslotIndex\"\x9a\x01\n" +
|
"slot_index\x18\b \x01(\x05R\tslotIndex\x12#\n" +
|
||||||
|
"\ris_lenticular\x18\t \x01(\bR\fisLenticular\"\x9a\x01\n" +
|
||||||
"\x19GetInspirationFlowRequest\x12\x16\n" +
|
"\x19GetInspirationFlowRequest\x12\x16\n" +
|
||||||
"\x06cursor\x18\x01 \x01(\tR\x06cursor\x12\x1c\n" +
|
"\x06cursor\x18\x01 \x01(\tR\x06cursor\x12\x1c\n" +
|
||||||
"\tdirection\x18\x02 \x01(\tR\tdirection\x12\x14\n" +
|
"\tdirection\x18\x02 \x01(\tR\tdirection\x12\x14\n" +
|
||||||
|
|||||||
@ -208,6 +208,7 @@ message ExhibitedAssetItem {
|
|||||||
int64 expire_at = 6; // 展出过期时间(毫秒时间戳)
|
int64 expire_at = 6; // 展出过期时间(毫秒时间戳)
|
||||||
int64 earnings = 7; // 当前可领取收益
|
int64 earnings = 7; // 当前可领取收益
|
||||||
int32 slot_index = 8; // 展位序号
|
int32 slot_index = 8; // 展位序号
|
||||||
|
bool is_lenticular = 9; // 是否为光栅卡(根据 tags 判断)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 灵感瀑布相关消息 ====================
|
// ==================== 灵感瀑布相关消息 ====================
|
||||||
|
|||||||
@ -100,6 +100,7 @@ type ExhibitedAssetInfo struct {
|
|||||||
ExpireAt int64
|
ExpireAt int64
|
||||||
Earnings int64
|
Earnings int64
|
||||||
SlotIndex int32
|
SlotIndex int32
|
||||||
|
IsLenticular bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// galleryRepository Repository实现
|
// galleryRepository Repository实现
|
||||||
@ -418,7 +419,8 @@ func (r *galleryRepository) GetMyExhibitedAssets(userID, starID int64, page, pag
|
|||||||
err = r.db.Model(&models.Exhibition{}).
|
err = r.db.Model(&models.Exhibition{}).
|
||||||
Raw(`
|
Raw(`
|
||||||
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
||||||
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index
|
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index,
|
||||||
|
(a.tags @> '["craft:lenticular"]') as is_lenticular
|
||||||
FROM exhibitions
|
FROM exhibitions
|
||||||
JOIN assets a ON a.id = exhibitions.asset_id
|
JOIN assets a ON a.id = exhibitions.asset_id
|
||||||
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
||||||
@ -462,7 +464,8 @@ func (r *galleryRepository) GetUserExhibitedAssets(userID, starID int64, page, p
|
|||||||
err = r.db.Model(&models.Exhibition{}).
|
err = r.db.Model(&models.Exhibition{}).
|
||||||
Raw(`
|
Raw(`
|
||||||
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
SELECT exhibitions.asset_id, a.name, a.cover_url, a.like_count,
|
||||||
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index
|
exhibitions.start_time as exhibited_at, exhibitions.expire_at, bs.slot_index,
|
||||||
|
(a.tags @> '["craft:lenticular"]') as is_lenticular
|
||||||
FROM exhibitions
|
FROM exhibitions
|
||||||
JOIN assets a ON a.id = exhibitions.asset_id
|
JOIN assets a ON a.id = exhibitions.asset_id
|
||||||
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
JOIN booth_slots bs ON bs.slot_id = exhibitions.slot_id
|
||||||
|
|||||||
@ -217,6 +217,7 @@ func (s *exhibitionService) GetMyExhibitedAssets(ctx context.Context, userID, st
|
|||||||
ExpireAt: item.ExpireAt,
|
ExpireAt: item.ExpireAt,
|
||||||
Earnings: item.Earnings,
|
Earnings: item.Earnings,
|
||||||
SlotIndex: item.SlotIndex,
|
SlotIndex: item.SlotIndex,
|
||||||
|
IsLenticular: item.IsLenticular,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,11 +39,11 @@
|
|||||||
<view class="vignette" />
|
<view class="vignette" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="showHint && tiltHintText" class="tilt-hint">
|
<!-- <view v-if="showHint && tiltHintText" class="tilt-hint">
|
||||||
<text class="tilt-hint-icon">↻</text>
|
<text class="tilt-hint-icon">↻</text>
|
||||||
<text class="tilt-hint-text">{{ tiltHintText }}</text>
|
<text class="tilt-hint-text">{{ tiltHintText }}</text>
|
||||||
<text v-if="approximatePreview" class="tilt-hint-sub">叠化近似预览(倾斜或拖动体验光栅效果)</text>
|
<text v-if="approximatePreview" class="tilt-hint-sub">叠化近似预览(倾斜或拖动体验光栅效果)</text>
|
||||||
</view>
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -28,7 +28,17 @@
|
|||||||
<view v-for="(item, index) in exhibitionWorks" :key="item.id" class="exhibition-card"
|
<view v-for="(item, index) in exhibitionWorks" :key="item.id" class="exhibition-card"
|
||||||
:class="index % 2 === 0 ? 'card-tilt-left' : 'card-tilt-right'"
|
:class="index % 2 === 0 ? 'card-tilt-left' : 'card-tilt-right'"
|
||||||
@tap="handleExhibitionCardTap(item, index)">
|
@tap="handleExhibitionCardTap(item, index)">
|
||||||
<image class="card-image" :src="item.cover_url || '/static/nft/placeholder.png'"
|
<LenticularCard
|
||||||
|
v-if="item.is_lenticular"
|
||||||
|
class="card-lenticular"
|
||||||
|
:layers="getLenticularLayers(item.id)"
|
||||||
|
:transforms="getLenticularTransforms(item.id)"
|
||||||
|
:gyro-source="gyroSourceLabel"
|
||||||
|
:skip-built-in-touch="false"
|
||||||
|
:shimmer-mid-opacity="0.16"
|
||||||
|
@simulate="(x, y) => onLenticularSimulate(item.id, x, y)"
|
||||||
|
/>
|
||||||
|
<image v-else class="card-image" :src="item.cover_url || '/static/nft/placeholder.png'"
|
||||||
mode="aspectFill"></image>
|
mode="aspectFill"></image>
|
||||||
<!-- 领取收益按钮 -->
|
<!-- 领取收益按钮 -->
|
||||||
<view class="claim-reward-btn" v-if="isRewardClaimable(item.id)">
|
<view class="claim-reward-btn" v-if="isRewardClaimable(item.id)">
|
||||||
@ -167,12 +177,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted } from 'vue';
|
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||||
import { getMyExhibitedAssetsApi, getMyLikedAssetsApi, getMyTodayLikedAssetsApi, getMyWeekLikedAssetsApi, getMyGalleriesApi, placeAssetToGalleryApi } from '@/utils/api.js';
|
import { getMyExhibitedAssetsApi, getMyLikedAssetsApi, getMyTodayLikedAssetsApi, getMyWeekLikedAssetsApi, getMyGalleriesApi, placeAssetToGalleryApi, getAssetMaterialsApi } from '@/utils/api.js';
|
||||||
import { getExhibitionRevenue, claimExhibitionRevenue } from '@/utils/task-api.js';
|
import { getExhibitionRevenue, claimExhibitionRevenue } from '@/utils/task-api.js';
|
||||||
import AssetSelector from '../components/AssetSelector.vue';
|
import AssetSelector from '../components/AssetSelector.vue';
|
||||||
import { onShow } from '@dcloudio/uni-app';
|
import { onShow } from '@dcloudio/uni-app';
|
||||||
import { doubleTapLike } from '@/utils/likeHelper.js';
|
import { doubleTapLike } from '@/utils/likeHelper.js';
|
||||||
|
import LenticularCard from '@/components/lenticular/LenticularCard.vue';
|
||||||
|
import { useLenticularCraftTiltPreview } from '@/composables/useLenticularCraftTiltPreview.js';
|
||||||
|
import { buildLenticularLayers } from '@/utils/castloveMintForm.js';
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
// 获取页面栈
|
// 获取页面栈
|
||||||
@ -496,6 +509,157 @@ const likedWorks = ref([]);
|
|||||||
// 点赞标签状态: current-当前, today-今日, week-本周
|
// 点赞标签状态: current-当前, today-今日, week-本周
|
||||||
const likedTab = ref('current');
|
const likedTab = ref('current');
|
||||||
|
|
||||||
|
// 光栅卡预览相关
|
||||||
|
// 每张光栅卡独立的 transforms,通过 asset id 索引
|
||||||
|
const lenticularTransformsMap = ref({});
|
||||||
|
const lenticularLayersByAsset = ref({});
|
||||||
|
const activeLenticularId = ref(null);
|
||||||
|
const gyroSourceLabel = ref('device');
|
||||||
|
|
||||||
|
// 创建单一引擎供模拟倾斜使用
|
||||||
|
const lenticularPhysics = ref(null);
|
||||||
|
const lenticularEngine = ref(null);
|
||||||
|
let lenticularRafId = null;
|
||||||
|
|
||||||
|
// 使用 useLenticularPreview 来管理光栅效果
|
||||||
|
const lenticularLayersRef = ref([]);
|
||||||
|
|
||||||
|
function getLenticularLayers(assetId) {
|
||||||
|
return lenticularLayersByAsset.value[assetId] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLenticularTransforms(assetId) {
|
||||||
|
return lenticularTransformsMap.value[assetId] || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadLenticularLayersForAsset(assetId) {
|
||||||
|
// 需要获取 bg + subject 素材构建 layers
|
||||||
|
// 目前使用 buildLenticularLayers(coverUrl) 作为占位
|
||||||
|
const item = exhibitionWorks.value.find(w => w.id === assetId);
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
// 异步获取素材列表,参考 asset-detail.vue 的实现
|
||||||
|
try {
|
||||||
|
const materialsRes = await getAssetMaterialsApi(assetId);
|
||||||
|
if (materialsRes.code === 200 && materialsRes.data) {
|
||||||
|
const materialsList = Array.isArray(materialsRes.data) ? materialsRes.data : materialsRes.data.materials || [];
|
||||||
|
let subjectUrl = item.cover_url;
|
||||||
|
let bgUrl = '';
|
||||||
|
for (const mat of materialsList) {
|
||||||
|
if (mat.material_type === 'main' && mat.material_url_signed) {
|
||||||
|
subjectUrl = mat.material_url_signed;
|
||||||
|
}
|
||||||
|
if (mat.material_type === 'bg' && mat.material_url_signed) {
|
||||||
|
bgUrl = mat.material_url_signed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 使用 buildLenticularLayersTwo 或 buildLenticularLayers
|
||||||
|
if (bgUrl) {
|
||||||
|
const { buildLenticularLayersTwo } = await import('@/utils/castloveMintForm.js');
|
||||||
|
lenticularLayersByAsset.value[assetId] = buildLenticularLayersTwo(bgUrl, subjectUrl);
|
||||||
|
} else {
|
||||||
|
lenticularLayersByAsset.value[assetId] = buildLenticularLayers(subjectUrl);
|
||||||
|
}
|
||||||
|
// 初始化 transforms
|
||||||
|
initTransformsForAsset(assetId);
|
||||||
|
} else {
|
||||||
|
lenticularLayersByAsset.value[assetId] = buildLenticularLayers(item.cover_url);
|
||||||
|
initTransformsForAsset(assetId);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[myWorks] 获取素材列表失败:', e);
|
||||||
|
lenticularLayersByAsset.value[assetId] = buildLenticularLayers(item.cover_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理光栅卡触摸模拟
|
||||||
|
function onLenticularSimulate(assetId, x, y) {
|
||||||
|
simulateLenticularTilt(assetId, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理光栅卡触摸模拟
|
||||||
|
function simulateLenticularTilt(assetId, x, y) {
|
||||||
|
if (!lenticularEngine.value) return;
|
||||||
|
const layers = lenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) return;
|
||||||
|
|
||||||
|
// 更新引擎的层
|
||||||
|
lenticularEngine.value.setLayers(layers);
|
||||||
|
|
||||||
|
// 计算渲染状态
|
||||||
|
const renderState = lenticularEngine.value.feedSimulatedTilt(x, y ? y : 0);
|
||||||
|
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
const rs = renderState.layerOffsets.get(l.id);
|
||||||
|
const op = renderState.layerOpacities.get(l.id);
|
||||||
|
transforms[l.id] = {
|
||||||
|
x: rs ? rs.x : 0,
|
||||||
|
y: rs ? rs.y : 0,
|
||||||
|
opacity: op != null ? op : l.opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 创建新对象以触发 Vue 响应式更新
|
||||||
|
lenticularTransformsMap.value = { ...lenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化光栅引擎
|
||||||
|
function initLenticularEngine() {
|
||||||
|
if (lenticularEngine.value) return;
|
||||||
|
import('@/utils/lenticular-engine.js').then(({ LenticularEngine, DEFAULT_PHYSICS }) => {
|
||||||
|
const physics = { ...DEFAULT_PHYSICS, parallaxDepth: 18 };
|
||||||
|
physics.gyroSimEnabled = false;
|
||||||
|
lenticularPhysics.value = physics;
|
||||||
|
lenticularEngine.value = new LenticularEngine(physics);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为每个资产初始化 transforms 为空(居中状态)
|
||||||
|
function initTransformsForAsset(assetId) {
|
||||||
|
const layers = lenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) return;
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
transforms[l.id] = { x: 0, y: 0, opacity: l.opacity || 1 };
|
||||||
|
}
|
||||||
|
lenticularTransformsMap.value = { ...lenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始光栅渲染循环(为所有卡片更新 transforms)
|
||||||
|
function startLenticularRenderLoop() {
|
||||||
|
if (lenticularRafId !== null) return;
|
||||||
|
const tick = () => {
|
||||||
|
// 遍历所有有层数据的卡片,更新 transforms
|
||||||
|
for (const assetId of Object.keys(lenticularLayersByAsset.value)) {
|
||||||
|
const layers = lenticularLayersByAsset.value[assetId];
|
||||||
|
if (!layers || layers.length === 0) continue;
|
||||||
|
// 使用当前的 sensorData 或默认的 gamma=0 来渲染
|
||||||
|
lenticularEngine.value.setLayers(layers);
|
||||||
|
const renderState = lenticularEngine.value.feedSimulatedTilt(0, 0);
|
||||||
|
const transforms = {};
|
||||||
|
for (const l of layers) {
|
||||||
|
const rs = renderState.layerOffsets.get(l.id);
|
||||||
|
const op = renderState.layerOpacities.get(l.id);
|
||||||
|
transforms[l.id] = {
|
||||||
|
x: rs ? rs.x : 0,
|
||||||
|
y: rs ? rs.y : 0,
|
||||||
|
opacity: op != null ? op : l.opacity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
lenticularTransformsMap.value = { ...lenticularTransformsMap.value, [assetId]: transforms };
|
||||||
|
}
|
||||||
|
lenticularRafId = requestAnimationFrame(tick);
|
||||||
|
};
|
||||||
|
lenticularRafId = requestAnimationFrame(tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopLenticularRenderLoop() {
|
||||||
|
if (lenticularRafId !== null) {
|
||||||
|
cancelAnimationFrame(lenticularRafId);
|
||||||
|
lenticularRafId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 切换点赞标签
|
// 切换点赞标签
|
||||||
const switchLikedTab = async (tab) => {
|
const switchLikedTab = async (tab) => {
|
||||||
if (likedTab.value === tab) return;
|
if (likedTab.value === tab) return;
|
||||||
@ -519,8 +683,17 @@ const loadExhibitedAssets = async () => {
|
|||||||
expire_at: item.expire_at,
|
expire_at: item.expire_at,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
slot_index: item.slot_index ?? 0,
|
slot_index: item.slot_index ?? 0,
|
||||||
|
is_lenticular: item.is_lenticular ?? false,
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => (a.slot_index ?? 0) - (b.slot_index ?? 0));
|
.sort((a, b) => (a.slot_index ?? 0) - (b.slot_index ?? 0));
|
||||||
|
|
||||||
|
// 为每个光栅卡加载层级数据
|
||||||
|
for (const item of exhibitionWorks.value) {
|
||||||
|
if (item.is_lenticular) {
|
||||||
|
loadLenticularLayersForAsset(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('展出作品:', exhibitionWorks.value);
|
console.log('展出作品:', exhibitionWorks.value);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -562,6 +735,8 @@ const loadLikedAssets = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
initLenticularEngine();
|
||||||
|
startLenticularRenderLoop();
|
||||||
loadExhibitedAssets();
|
loadExhibitedAssets();
|
||||||
loadLikedAssets();
|
loadLikedAssets();
|
||||||
|
|
||||||
@ -583,6 +758,7 @@ onUnmounted(() => {
|
|||||||
if (countdownTimer) {
|
if (countdownTimer) {
|
||||||
clearInterval(countdownTimer);
|
clearInterval(countdownTimer);
|
||||||
}
|
}
|
||||||
|
stopLenticularRenderLoop();
|
||||||
uni.$off('userInfoUpdated');
|
uni.$off('userInfoUpdated');
|
||||||
uni.$off('assetLiked');
|
uni.$off('assetLiked');
|
||||||
});
|
});
|
||||||
@ -792,6 +968,18 @@ onShow(() => {
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-lenticular {
|
||||||
|
width: 88%;
|
||||||
|
height: 93%;
|
||||||
|
left: 5%;
|
||||||
|
top: 4%;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
transform-origin: center center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* 领取收益按钮 */
|
/* 领取收益按钮 */
|
||||||
.claim-reward-btn {
|
.claim-reward-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
// 不需要手动注释!
|
// 不需要手动注释!
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
const baseURL = 'http://192.168.110.60:8080' // H5 开发用本机
|
// const baseURL = 'http://192.168.110.60:8080' // H5 开发用本机
|
||||||
// const baseURL = 'http://101.132.250.62:8080' // H5 开发用本机
|
const baseURL = 'http://101.132.250.62:8080' // H5 开发用本机
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user