1078 lines
26 KiB
Vue
1078 lines
26 KiB
Vue
<template>
|
||
<view class="page-container flex-column">
|
||
<view class="top-fixed">
|
||
<nav-bar v-if="!selectedImage" title="淘宝" bgColor="#ffffff" :buttonGroup="buttonGroup"
|
||
@button-click="util.clickTitlePopupButton" tipLayerType="jingdong-shopping-list" isTipLayer
|
||
tipLayerText="添加订单信息">
|
||
<template v-slot:left>
|
||
<image class="back-icon" src="/static/image/shopping/taobao/back.png" mode="aspectFit"></image>
|
||
</template>
|
||
<template v-slot:center>
|
||
<view class="search-box flex-align-center">
|
||
<image class="search-icon" src="/static/image/shopping/jingdong/search-icon.png"
|
||
mode="aspectFit">
|
||
</image>
|
||
<input class="input" type="text" placeholder="搜索我的订单" />
|
||
</view>
|
||
</template>
|
||
<template v-slot:right>
|
||
<view class="right-box flex-align-center">
|
||
<view class="item flex-column flex-align-center">
|
||
<image class="icon" src="/static/image/shopping/taobao/shaixuan.png"></image>
|
||
<text class="text">筛选</text>
|
||
</view>
|
||
<view class="item flex-column flex-align-center">
|
||
<image class="icon" src="/static/image/shopping/taobao/guanli.png"></image>
|
||
<text class="text">管理</text>
|
||
</view>
|
||
<view class="item flex-column flex-align-center">
|
||
<image class="icon" src="/static/image/shopping/taobao/xiaoxi.png"></image>
|
||
<text class="text" style="opacity: 0;">消息</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</nav-bar>
|
||
<nav-bar v-else title="拼图" bgColor="#EFEFEF" noBack @back="closeImage" isRightButton
|
||
@right-click="confirmImage">
|
||
</nav-bar>
|
||
<view class="tab-list">
|
||
<view class="tab-item" v-for="(item, index) in tabList" :key="index"
|
||
:class="{ active: currentTab === index }" @click="switchTab(index)">
|
||
<view class="title">
|
||
<text>{{ item.name }}</text>
|
||
<view class="line" v-if="currentTab === index"></view>
|
||
</view>
|
||
<!-- <view class="line" v-if="currentTab === index"></view> -->
|
||
<image v-if="item.icon" class="badge-icon" :class="{ 'android-m-top': $system == 'Android' }"
|
||
:src="item.icon" mode="heightFix"></image>
|
||
</view>
|
||
</view>
|
||
<view class="filter-wrapper">
|
||
<view class="position-l">
|
||
<view class="filter-item" :class="{ active: currentFilter === 0 }" @click="switchFilter(0)">
|
||
<text class="text">全部</text>
|
||
</view>
|
||
</view>
|
||
<scroll-view class="filter-scroll" scroll-x="true" :show-scrollbar="false">
|
||
<view class="filter-list">
|
||
<view class="filter-item " v-for="(item, index) in filterList" :key="index"
|
||
:class="{ active: currentFilter === index, disabled: item.disabled }"
|
||
@click="switchFilter(index)">
|
||
<text class="text">{{ item.name }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
</view>
|
||
<scroll-view class="flex-1" style="height: 100px;" scroll-y="true">
|
||
<view v-if="currentTab === 0 && currentFilter === 0"
|
||
class="shangou-tips flex-align-center flex-justify-between">
|
||
<view class="left flex-align-center">
|
||
<image style="width: 64rpx;height: 28rpx;margin-right: 8rpx;"
|
||
src="/static/image/shopping/taobao/shangou-logo.png"></image>
|
||
<text>暂无进行中订单</text>
|
||
</view>
|
||
<view class="right">
|
||
<text>查看全部</text>
|
||
<uni-icons type="right" size="14" color="#5E6367"></uni-icons>
|
||
</view>
|
||
</view>
|
||
<listCard v-if="displayList.length > 0" :list="displayList" @click-item="goDetail"
|
||
@longpress="onItemLongPress" />
|
||
<view v-else class="null-data-box flex-center flex-column">
|
||
<image style="width: 254rpx;height: 200rpx;" src="/static/image/shopping/taobao/null.png"></image>
|
||
<text
|
||
style="font-size: 28rpx;color: #7C8495;line-height: 28rpx;margin-top: 16rpx;font-weight: 500;">您还没有相关的订单</text>
|
||
</view>
|
||
<view class="bottom-fixed" style="height: 1000rpx;">
|
||
<view v-if="!selectedImage" class="upload-screenshot-box" @touchstart="handleTouchStart"
|
||
@touchend="handleTouchEnd">
|
||
<view v-if="!screenshotImage" class="upload-screenshot-content">
|
||
<image class="upload-screenshot" src="/static/image/common/upload-screenshot.png"
|
||
mode="aspectFit">
|
||
</image>
|
||
<view class="upload-screenshot-text">长按替换截图</view>
|
||
</view>
|
||
<view v-else class="screenshot-preview-box">
|
||
<image class="screenshot-preview" :src="screenshotImage" mode="widthFix"></image>
|
||
</view>
|
||
<!-- <image v-else class="w100 h100" :src="screenshotImage" mode="widthFix"></image> -->
|
||
</view>
|
||
<view v-else class="upload-screenshot-box scroll-image-box">
|
||
<scroll-view class="image-box" style="width: 100%;height: 100%;" scroll-y :show-scrollbar="false"
|
||
@scroll="onImageScroll">
|
||
<image class="crop-image-target" style="width:100%;" :src="selectedImage" mode="widthFix">
|
||
</image>
|
||
</scroll-view>
|
||
<view class="dashed-line-box">
|
||
<view class="dashed-line-text">我是分割线</view>
|
||
</view>
|
||
</view>
|
||
<canvas canvas-id="crop-canvas"
|
||
style="position: fixed; left: -9999px; width: 750rpx; height: 100vh; pointer-events: none;"></canvas>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
</view>
|
||
|
||
<!-- 自定义长按上下文菜单 -->
|
||
<view v-if="menuState.show" class="menu-mask" @click="menuState.show = false" @touchmove.stop.prevent>
|
||
<view class="menu-content" :style="{ top: menuState.y + 'px', left: menuState.x + 'px' }">
|
||
<view class="menu-item" @click.stop="handleMenuAction('edit')">
|
||
<uni-icons type="compose" size="18" color="#1A1A1A"></uni-icons>
|
||
<text>编辑</text>
|
||
</view>
|
||
<view class="menu-line"></view>
|
||
<view class="menu-item" @click.stop="handleMenuAction('delete')">
|
||
<uni-icons type="trash" size="18" color="#FF4D4F"></uni-icons>
|
||
<text style="color: #FF4D4F;">删除</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 切换底部图片弹窗 -->
|
||
<uni-popup ref="bottomImgPopup" type="center">
|
||
<view class="bottom-img-popup-card">
|
||
<view class="p-header">选择底部商品图</view>
|
||
<view class="p-content">
|
||
<view class="option-item" @click="selectBottomImg(1)">
|
||
<image class="preview-img" src="/static/image/shopping/taobao/bottom-bg-1.png" mode="aspectFill">
|
||
</image>
|
||
<view class="info">
|
||
<text class="name">商品图片 1</text>
|
||
<text class="desc">默认背景布局</text>
|
||
</view>
|
||
<uni-icons type="right" size="16" color="#C7C7CC"></uni-icons>
|
||
</view>
|
||
<view class="option-item" @click="selectBottomImg(2)">
|
||
<image class="preview-img" src="/static/image/shopping/taobao/bottom-bg-2.png" mode="aspectFill">
|
||
</image>
|
||
<view class="info">
|
||
<text class="name">商品图片 2</text>
|
||
<text class="desc">备选商品排列</text>
|
||
</view>
|
||
<uni-icons type="right" size="16" color="#C7C7CC"></uni-icons>
|
||
</view>
|
||
<text
|
||
style="color: #949494;font-size: 24rpx;text-align: center;display: block;">*长按底部商品图片区域可上传自定义图片*</text>
|
||
</view>
|
||
<view class="p-footer" @click="bottomImgPopup.close()">取消</view>
|
||
</view>
|
||
</uni-popup>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted, getCurrentInstance, reactive } from 'vue';
|
||
import { onShow } from '@dcloudio/uni-app';
|
||
import { util } from '@/utils/common.js';
|
||
import listCard from './components/list-card/list-card.vue';
|
||
import { defualtData } from './json/order.json'
|
||
|
||
const instance = getCurrentInstance();
|
||
const mockList = ref([]);
|
||
const menuState = reactive({
|
||
show: false,
|
||
x: 0,
|
||
y: 0,
|
||
target: null
|
||
});
|
||
|
||
const bottomImgPopup = ref(null);
|
||
|
||
const selectBottomImg = (type) => {
|
||
const path = `/static/image/shopping/taobao/bottom-bg-${type}.png`;
|
||
screenshotImage.value = path;
|
||
uni.setStorageSync('taobao_screenshot', path);
|
||
bottomImgPopup.value.close();
|
||
uni.showToast({
|
||
title: '切换成功',
|
||
icon: 'success'
|
||
});
|
||
};
|
||
|
||
onShow(() => {
|
||
// 加载缓存数据
|
||
let storageData = uni.getStorageSync('taobaoShopping');
|
||
|
||
// 如果缓存为空,则初始化默认数据
|
||
if (!storageData || (Array.isArray(storageData) && storageData.length === 0)) {
|
||
console.log('检测到淘宝订单缓存为空,注入初始默认数据');
|
||
storageData = JSON.parse(JSON.stringify(defualtData));
|
||
uni.setStorageSync('taobaoShopping', storageData);
|
||
}
|
||
|
||
mockList.value = storageData || [];
|
||
|
||
// 加载拼图截图缓存 (若不存在则初始化默认底图)
|
||
let savedScreenshot = uni.getStorageSync('taobao_screenshot');
|
||
if (!savedScreenshot) {
|
||
savedScreenshot = '/static/image/shopping/taobao/bottom-bg-1.png';
|
||
uni.setStorageSync('taobao_screenshot', savedScreenshot);
|
||
}
|
||
screenshotImage.value = savedScreenshot;
|
||
});
|
||
|
||
|
||
//导航栏菜单按钮
|
||
const buttonGroup = [
|
||
{
|
||
name: "新增购物订单",
|
||
click: () => {
|
||
uni.navigateTo({
|
||
url: '/pages/shopping/taobao/add-shopping-order/add-shopping-order'
|
||
});
|
||
}
|
||
}, {
|
||
name: "新增闪购订单",
|
||
click: () => {
|
||
uni.showToast({
|
||
title: '开发中,敬请期待',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}, {
|
||
name: "切换底部商品图片",
|
||
click: () => {
|
||
bottomImgPopup.value.open();
|
||
}
|
||
},
|
||
]
|
||
|
||
const displayList = computed(() => {
|
||
let list = JSON.parse(JSON.stringify(mockList.value));
|
||
|
||
// 1. 一级 Tab 过滤 (orderType)
|
||
if (currentTab.value === 1) { // 购物
|
||
list = list.filter(item => item.orderType === 'shopping');
|
||
} else if (currentTab.value === 2) { // 闪购
|
||
list = list.filter(item => item.orderType === 'waimai');
|
||
}
|
||
|
||
// 2. 二级分类过滤 (currentFilter)
|
||
if (currentFilter.value > 0) {
|
||
const filterName = filterList.value[currentFilter.value]?.name;
|
||
const statusMap = {
|
||
'待付款': ['wait_pay'],
|
||
'待发货': ['wait_send'],
|
||
'待收货': ['wait_recv'],
|
||
'退款/售后': ['refunding'],
|
||
'评价': ['success'],
|
||
'已关闭': ['closed']
|
||
|
||
};
|
||
|
||
const targetStatus = statusMap[filterName];
|
||
if (targetStatus) {
|
||
list = list.filter(item => targetStatus.includes(item.statusType));
|
||
}
|
||
}
|
||
|
||
// 3. 时间降序排列逻辑 (创建时间 || 申请时间)
|
||
list.sort((a, b) => {
|
||
const getTime = (order) => {
|
||
if (!order.orderInfo) return '';
|
||
const create = order.orderInfo.find(i => i.key === 'createTime')?.value;
|
||
const apply = order.orderInfo.find(i => i.key === 'applyTime')?.value;
|
||
return create || apply || '';
|
||
};
|
||
const timeA = getTime(a);
|
||
const timeB = getTime(b);
|
||
return timeB.localeCompare(timeA); // 降序
|
||
});
|
||
|
||
return list;
|
||
});
|
||
|
||
const currentFilter = ref(0);
|
||
const filterList = ref([
|
||
{ name: '全部' },
|
||
{ name: '待付款' },
|
||
{ name: '待发货' },
|
||
{ name: '待收货' },
|
||
{ name: '退款/售后' },
|
||
{ name: '评价' },
|
||
{ name: '已关闭' }
|
||
]);
|
||
|
||
const currentTab = ref(0);
|
||
const tabList = ref([
|
||
{ name: '全部订单' },
|
||
{ name: '购物' },
|
||
{ name: '闪购', icon: '/static/image/shopping/taobao/waimai.png' },
|
||
{ name: '飞猪', icon: '/static/image/shopping/taobao/lvxing.png', disabled: true }
|
||
]);
|
||
|
||
// 长按替换截图相关
|
||
const screenshotImage = ref('');
|
||
const selectedImage = ref('');
|
||
const scrollTop = ref(0);
|
||
let longPressTimer = null;
|
||
|
||
|
||
// 长按替换截图 - 选择图片
|
||
const chooseImage = () => {
|
||
if (selectedImage.value) return;
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sourceType: ['album'],
|
||
success: (res) => {
|
||
selectedImage.value = res.tempFilePaths[0];
|
||
}
|
||
});
|
||
};
|
||
|
||
// 长按事件
|
||
const handleTouchStart = (e) => {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
if (systemInfo.platform === 'ios' && systemInfo.safeAreaInsets?.bottom) {
|
||
const clientY = e.touches[0].clientY;
|
||
const windowHeight = systemInfo.windowHeight;
|
||
if (clientY > windowHeight - systemInfo.safeAreaInsets.bottom) {
|
||
return;
|
||
}
|
||
}
|
||
longPressTimer = setTimeout(() => {
|
||
uni.vibrateShort();
|
||
chooseImage();
|
||
}, 1200);
|
||
};
|
||
|
||
const handleTouchEnd = () => {
|
||
if (longPressTimer) {
|
||
clearTimeout(longPressTimer);
|
||
longPressTimer = null;
|
||
}
|
||
};
|
||
|
||
// 图片滚动
|
||
const onImageScroll = (e) => {
|
||
scrollTop.value = e.detail.scrollTop;
|
||
};
|
||
// 确认图片裁剪
|
||
const confirmImage = () => {
|
||
uni.showLoading({
|
||
title: '处理中...'
|
||
})
|
||
const query = uni.createSelectorQuery().in(instance)
|
||
|
||
// 获取容器和图片信息
|
||
query.select('.image-box').boundingClientRect()
|
||
query.select('.crop-image-target').boundingClientRect()
|
||
query.exec(res => {
|
||
if (!res[0] || !res[1]) {
|
||
uni.hideLoading()
|
||
return
|
||
}
|
||
|
||
console.log('rects', res)
|
||
const container = res[0] // 容器
|
||
const image = res[1] // 图片实际渲染尺寸
|
||
|
||
// 计算缩放比例 (渲染宽度 / 实际宽度 不准确,应该反过来用 图片原始宽/渲染宽?)
|
||
// 这里更简单的方法是:canvas设为容器大小,把图片画进去
|
||
// canvas drawImage 参数: img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight
|
||
|
||
// 获取图片原始尺寸
|
||
uni.getImageInfo({
|
||
src: selectedImage.value,
|
||
success: (imgInfo) => {
|
||
const scale = imgInfo.width / image.width // 图片 原始宽 / 渲染宽
|
||
const sTop = scrollTop.value * scale // 原始图上的裁切起始Y
|
||
const sHeight = container.height * scale // 原始图上的裁切高度
|
||
|
||
// 因为是 widthFix,宽度就是原始图宽度(或裁切全宽)
|
||
const sWidth = imgInfo.width
|
||
|
||
// 设置画布尺寸 (使用像素值)
|
||
// 注意:canvasContext绘制使用的是逻辑像素还是物理像素?通常需要考虑到 pixelRatio,
|
||
// 但 uni-app canvas-id 方式通常对应逻辑像素(px)
|
||
// 我们把 canvas 大小设为和容器显示一致
|
||
const canvasW = container.width
|
||
const canvasH = container.height
|
||
|
||
const ctx = uni.createCanvasContext('crop-canvas', instance)
|
||
|
||
// 清除画布
|
||
ctx.clearRect(0, 0, canvasW, canvasH)
|
||
|
||
// 绘制
|
||
// drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
||
ctx.drawImage(
|
||
imgInfo.path,
|
||
0, sTop, sWidth, sHeight, // 源图裁剪区域
|
||
0, 0, canvasW, canvasH // 画布绘制区域
|
||
)
|
||
ctx.draw(false, () => {
|
||
uni.canvasToTempFilePath({
|
||
canvasId: 'crop-canvas',
|
||
width: canvasW,
|
||
height: canvasH,
|
||
destWidth: sWidth, // 使用原图实际宽度,保持原图清晰度
|
||
destHeight: sHeight, // 使用原图实际高度,保持原图清晰度
|
||
success: (res) => {
|
||
console.log('crop success (temp)', res
|
||
.tempFilePath)
|
||
|
||
// 将临时路径保存为永久路径
|
||
uni.saveFile({
|
||
tempFilePath: res.tempFilePath,
|
||
success: (saveRes) => {
|
||
console.log('save success (saved)', saveRes.savedFilePath)
|
||
screenshotImage.value = saveRes.savedFilePath
|
||
selectedImage.value = '' // 隐藏编辑模式
|
||
setTimeout(() => {
|
||
plus.navigator.setStatusBarStyle("light");
|
||
}, 200)
|
||
// 保存到缓存
|
||
uni.setStorageSync('taobao_screenshot', screenshotImage.value)
|
||
uni.hideLoading()
|
||
},
|
||
fail: (err) => {
|
||
console.error('saveFile fail', err)
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error(err)
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '裁剪失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}, instance)
|
||
})
|
||
},
|
||
fail: () => {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '图片加载失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
|
||
})
|
||
}
|
||
|
||
// 关闭截图预览
|
||
const closeImage = () => {
|
||
selectedImage.value = '';
|
||
};
|
||
|
||
|
||
/**
|
||
* 切换tab
|
||
* @param index
|
||
*/
|
||
const switchTab = (index) => {
|
||
if (tabList.value[index].disabled) return;
|
||
currentTab.value = index;
|
||
// 重置筛选为“全部”
|
||
currentFilter.value = 0;
|
||
// 动态更新筛选项
|
||
updateFilterList();
|
||
};
|
||
|
||
/**
|
||
* 动态更新筛选项
|
||
*/
|
||
const updateFilterList = () => {
|
||
let sourceList = [];
|
||
// 根据tab切换不同的筛选项数据
|
||
switch (currentTab.value) {
|
||
case 0:
|
||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "评价", "已关闭"];
|
||
break;
|
||
case 1:
|
||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "评价", "已关闭"];
|
||
break;
|
||
case 2:
|
||
sourceList = ["全部", "待付款", "待发货", "待收货", "待评价", "已关闭"];
|
||
break;
|
||
case 3:
|
||
sourceList = ["全部", "全部行程", "已完成", "退款/售后"];
|
||
break;
|
||
}
|
||
filterList.value = sourceList.map((name, index) => ({
|
||
name,
|
||
disabled: index === 2 && currentTab.value === 1 // 示例:只有待发货可以被禁用
|
||
}));
|
||
};
|
||
|
||
/**
|
||
* 切换筛选
|
||
* @param index 索引
|
||
*/
|
||
const switchFilter = (index) => {
|
||
if (filterList.value[index].disabled) return;
|
||
if (currentFilter.value === index) {
|
||
currentFilter.value = 0;
|
||
} else {
|
||
currentFilter.value = index;
|
||
}
|
||
};
|
||
|
||
const goDetail = (item) => {
|
||
util.goPage(`/pages/shopping/taobao/shopping-order-detail/shopping-order-detail?id=${item.id}`)
|
||
}
|
||
|
||
/**
|
||
* 长按管理订单 - 记录坐标并显示自定义菜单
|
||
*/
|
||
const onItemLongPress = (data) => {
|
||
const { item, x, y } = data;
|
||
menuState.target = item;
|
||
|
||
// 计算菜单位置,避免手指遮挡(向上偏移 60px,向左偏移 40px)
|
||
// 并简单处理边界溢出(示例:不超出右边界)
|
||
const screenWidth = uni.getSystemInfoSync().windowWidth;
|
||
let posX = x - 40;
|
||
if (posX + 120 > screenWidth) {
|
||
posX = screenWidth - 130;
|
||
}
|
||
|
||
menuState.x = Math.max(10, posX);
|
||
menuState.y = y - 80;
|
||
menuState.show = true;
|
||
};
|
||
|
||
/**
|
||
* 处理菜单点击
|
||
*/
|
||
const handleMenuAction = (action) => {
|
||
const item = menuState.target;
|
||
menuState.show = false;
|
||
if (!item) return;
|
||
|
||
if (action === 'edit') {
|
||
uni.navigateTo({
|
||
url: `/pages/shopping/taobao/add-shopping-order/add-shopping-order?id=${item.id}&isEdit=true`
|
||
});
|
||
} else if (action === 'delete') {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要删除该订单吗?',
|
||
confirmColor: '#FF7824',
|
||
success: (modalRes) => {
|
||
if (modalRes.confirm) {
|
||
deleteOrder(item.id);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 从缓存执行删除
|
||
*/
|
||
const deleteOrder = (id) => {
|
||
let list = uni.getStorageSync('taobaoShopping') || [];
|
||
|
||
// 1. 物理删除关联图片
|
||
const target = list.find(item => String(item.id) === String(id));
|
||
if (target) {
|
||
const imagesToClear = [];
|
||
if (target.goodsList?.[0]?.image) imagesToClear.push(target.goodsList[0].image);
|
||
if (target.productImgUrl) imagesToClear.push(target.productImgUrl);
|
||
|
||
imagesToClear.forEach(path => {
|
||
if (path && (path.includes('_doc') || path.includes('store_'))) {
|
||
uni.removeSavedFile({
|
||
filePath: path,
|
||
success: () => console.log('删除订单关联图片成功:', path),
|
||
fail: (err) => console.log('图片文件不存在或已删除:', path)
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 2. 移除缓存记录
|
||
list = list.filter(item => String(item.id) !== String(id));
|
||
// 同步缓存
|
||
uni.setStorageSync('taobaoShopping', list);
|
||
// 同步 UI
|
||
mockList.value = list;
|
||
|
||
uni.showToast({
|
||
title: '已删除',
|
||
icon: 'success'
|
||
});
|
||
};
|
||
|
||
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.page-container {
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.top-fixed {
|
||
background-color: #ffffff;
|
||
|
||
::v-deep .uni-navbar__header-btns {
|
||
width: auto !important;
|
||
}
|
||
|
||
::v-deep .uni-navbar__header-container {
|
||
padding: 0 14rpx;
|
||
padding-left: 34rpx;
|
||
}
|
||
|
||
.back-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
|
||
.search-box {
|
||
background-color: #F1F5F8;
|
||
padding: 0 18rpx;
|
||
width: 100%;
|
||
border-radius: 16rpx;
|
||
|
||
.search-icon {
|
||
width: 26rpx;
|
||
height: 26rpx;
|
||
margin-right: 10rpx;
|
||
}
|
||
|
||
.input {
|
||
width: 100%;
|
||
height: 72rpx;
|
||
font-size: 26rpx;
|
||
|
||
::v-deep .input-placeholder {
|
||
color: #7E8C9D;
|
||
}
|
||
}
|
||
}
|
||
|
||
.right-box {
|
||
.item {
|
||
margin: 0 14rpx;
|
||
|
||
.icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
|
||
.text {
|
||
font-size: 20rpx;
|
||
color: #1A1A1A;
|
||
line-height: 20rpx;
|
||
margin-top: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.tab-list {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 16rpx 36rpx 10rpx;
|
||
|
||
.tab-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-right: 58rpx;
|
||
|
||
.title {
|
||
position: relative;
|
||
font-size: 30rpx;
|
||
color: #00032A;
|
||
font-weight: 500;
|
||
line-height: 16px !important;
|
||
}
|
||
|
||
&.active {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
|
||
.title {
|
||
color: #EF7518;
|
||
}
|
||
}
|
||
|
||
.line {
|
||
position: absolute;
|
||
bottom: -12rpx;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 22rpx;
|
||
height: 4rpx;
|
||
background-color: #EF7518;
|
||
border-radius: 4rpx;
|
||
}
|
||
|
||
.badge-icon {
|
||
margin-left: 6rpx;
|
||
width: 52rpx;
|
||
height: 14px;
|
||
|
||
&.android-m-top {
|
||
margin-top: -3rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.filter-wrapper {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 22rpx 0 30rpx;
|
||
margin-top: 28rpx;
|
||
padding-bottom: 16rpx;
|
||
|
||
.filter-scroll {
|
||
flex: 1;
|
||
width: 0;
|
||
white-space: nowrap;
|
||
|
||
.filter-list {
|
||
padding-right: 24rpx;
|
||
}
|
||
}
|
||
|
||
.position-l {
|
||
position: absolute;
|
||
left: 0;
|
||
padding-left: 30rpx;
|
||
background-color: #ffffff;
|
||
z-index: 1;
|
||
|
||
.filter-item {
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
|
||
.filter-item {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
vertical-align: middle;
|
||
height: 56rpx;
|
||
padding: 0 22rpx;
|
||
background-color: #F1F4F9;
|
||
border-radius: 12rpx;
|
||
margin-right: 16rpx;
|
||
border: 2rpx solid transparent;
|
||
box-sizing: border-box;
|
||
|
||
.text {
|
||
font-size: 26rpx;
|
||
line-height: 26rpx;
|
||
color: #00032A;
|
||
}
|
||
|
||
.close-icon {
|
||
font-size: 18px;
|
||
color: #E40C24;
|
||
margin-top: -4rpx;
|
||
line-height: 14px;
|
||
margin-left: 6rpx;
|
||
font-weight: 400;
|
||
}
|
||
|
||
&.active {
|
||
background-color: #FFEEE6;
|
||
|
||
.text {
|
||
color: #EF7518;
|
||
}
|
||
}
|
||
|
||
// &.disabled {
|
||
// background-color: #F8F8F8;
|
||
// border-color: transparent;
|
||
|
||
// .text {
|
||
// color: #CCCCCC;
|
||
// }
|
||
// }
|
||
}
|
||
}
|
||
}
|
||
|
||
.shangou-tips {
|
||
padding: 28rpx 22rpx 36rpx 32rpx;
|
||
background-color: #ffffff;
|
||
|
||
.left {
|
||
height: 28rpx;
|
||
|
||
text {
|
||
font-size: 26rpx;
|
||
line-height: 28rpx;
|
||
color: #00032A;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.right {
|
||
color: #5E6367;
|
||
font-size: 26rpx;
|
||
line-height: 28rpx;
|
||
|
||
text {
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.menu-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 9999;
|
||
background-color: transparent;
|
||
}
|
||
|
||
.menu-content {
|
||
position: absolute;
|
||
width: 240rpx;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
overflow: hidden;
|
||
animation: menu-show 0.15s ease-out;
|
||
}
|
||
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx 32rpx;
|
||
transition: background 0.2s;
|
||
|
||
&:active {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
color: #1A1A1A;
|
||
margin-left: 16rpx;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.menu-line {
|
||
height: 1px;
|
||
background-color: #EEEEEE;
|
||
margin: 0 20rpx;
|
||
}
|
||
|
||
@keyframes menu-show {
|
||
from {
|
||
opacity: 0;
|
||
transform: scale(0.9);
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
.null-data-box {
|
||
padding: 68rpx;
|
||
}
|
||
|
||
.bottom-fixed {
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.upload-screenshot-box {
|
||
width: 100%;
|
||
flex: 1;
|
||
min-height: 540rpx;
|
||
background-color: #FFFFFF;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
|
||
.upload-screenshot {
|
||
width: 92rpx;
|
||
height: 92rpx;
|
||
}
|
||
|
||
.upload-screenshot-content {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
|
||
.upload-screenshot-text {
|
||
font-size: 36rpx;
|
||
color: #1777FF;
|
||
line-height: 50rpx;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
.screenshot-preview-box {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
// flex-direction: column;
|
||
justify-content: center;
|
||
|
||
.screenshot-preview {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.scroll-image-box {
|
||
width: 100%;
|
||
min-height: 0; // 修复 flex一出问题
|
||
// overflow: hidden; // scroll-view 需要
|
||
position: relative;
|
||
}
|
||
|
||
.dashed-line-box {
|
||
width: 100%;
|
||
height: 100%;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
border: 4rpx dashed #ffffff;
|
||
pointer-events: none;
|
||
|
||
.dashed-line-text {
|
||
height: 44rpx;
|
||
line-height: 44rpx;
|
||
width: 180rpx;
|
||
padding: 0 20rpx;
|
||
border-radius: 8rpx;
|
||
color: #1777FF;
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
background-color: #fff;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
|
||
.mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.8);
|
||
z-index: 999;
|
||
|
||
.mask-icon {
|
||
position: absolute;
|
||
top: 50%;
|
||
right: 52rpx;
|
||
transform: translateY(-25%);
|
||
width: 360rpx;
|
||
height: 360rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.bottom-img-popup-card {
|
||
width: 600rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 32rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.15);
|
||
|
||
.p-header {
|
||
padding: 40rpx 0 20rpx;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #1A1A1A;
|
||
}
|
||
|
||
.p-content {
|
||
padding: 20rpx 30rpx;
|
||
|
||
.option-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx;
|
||
margin-bottom: 20rpx;
|
||
background-color: #F8F9FA;
|
||
border-radius: 20rpx;
|
||
transition: all 0.2s;
|
||
|
||
&:active {
|
||
background-color: #F0F2F5;
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.preview-img {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 12rpx;
|
||
background-color: #EEE;
|
||
}
|
||
|
||
.info {
|
||
flex: 1;
|
||
margin: 0 24rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.name {
|
||
font-size: 28rpx;
|
||
font-weight: 500;
|
||
color: #1A1A1A;
|
||
}
|
||
|
||
.desc {
|
||
font-size: 22rpx;
|
||
color: #8E8E93;
|
||
margin-top: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.p-footer {
|
||
height: 100rpx;
|
||
line-height: 100rpx;
|
||
text-align: center;
|
||
border-top: 1rpx solid #F0F2F5;
|
||
font-size: 30rpx;
|
||
color: #8E8E93;
|
||
|
||
&:active {
|
||
background-color: #F8F9FA;
|
||
}
|
||
}
|
||
}
|
||
</style>
|
||
<style>
|
||
@import '@/common/main.css';
|
||
|
||
page {
|
||
background-color: #F1F5F8;
|
||
}
|
||
</style> |