Compare commits

..

No commits in common. "2eb5f2be92c5f2ca4177e52384c1c76ecb885e1a" and "c00cb2e1358c46c4630c383abb8274bbd6d96c85" have entirely different histories.

33 changed files with 119 additions and 2508 deletions

View File

@ -12,7 +12,7 @@
</view> </view>
<view class="money alipay-font" <view class="money alipay-font"
:class="item.isAdd ? (isBalance ? 'add-color' : 'red-add-color') : 'minus-color', { 'line-height-51rpx': isBalance }"> :class="item.isAdd ? (isBalance ? 'add-color' : 'red-add-color') : 'minus-color', { 'line-height-51rpx': isBalance }">
{{ item.isAdd ? '+' : '-' }}{{ numberUtil.formatMoneyWithThousand(item.money) }} {{ item.isAdd ? '+' : '-' }}{{ Number(item.money).toFixed(2) }}
</view> </view>
</view> </view>
@ -39,7 +39,7 @@
<view v-if="item.isRefund" class="refund" :class="{ 'item-box': !isBalance }">已全额退款</view> <view v-if="item.isRefund" class="refund" :class="{ 'item-box': !isBalance }">已全额退款</view>
<view v-if="isBalance" class="balance secondary" :class="{ 'item-box': !isBalance }">余额 <view v-if="isBalance" class="balance secondary" :class="{ 'item-box': !isBalance }">余额
<text class="balance-text wx-font-regular">{{ <text class="balance-text wx-font-regular">{{
numberUtil.formatMoneyWithThousand(item.balance) Number(item.balance).toFixed(2)
}}</text> }}</text>
</view> </view>
</view> </view>
@ -58,10 +58,6 @@ import {
reactive reactive
} from 'vue' } from 'vue'
import {
numberUtil
} from '@/utils/common.js'
// //
const props = defineProps({ const props = defineProps({
list: { list: {

View File

@ -1,5 +1,5 @@
<template> <template>
<view class="shopping-card" @longpress="onLongPress"> <view class="shopping-card">
<!-- Header --> <!-- Header -->
<view class="card-header"> <view class="card-header">
<view class="shop-info"> <view class="shop-info">
@ -98,7 +98,8 @@
<!-- Promo --> <!-- Promo -->
<view class="promo-box" <view class="promo-box"
:class="{ 'plus-promo': item.promoType === 'plus', 'cashback-promo': item.shopType == 'waimai' && (item.status == '骑手到店取餐中' || item.status == '商家备餐中'), 'coupon-promo': item.promoType === 'coupon' }"> :class="{ 'plus-promo': item.promoType === 'plus', 'cashback-promo': item.promoType === 'cashback', 'coupon-promo': item.promoType === 'coupon' }"
v-if="item.promoType || item.promoText || item.promoHighlight">
<template v-if="item.promoType === 'plus'"> <template v-if="item.promoType === 'plus'">
<view class="plus-row"> <view class="plus-row">
<image class="plus-tag" src="/static/image/shopping/jingdong/plus.png"></image> <image class="plus-tag" src="/static/image/shopping/jingdong/plus.png"></image>
@ -106,9 +107,11 @@
</view> </view>
<text class="promo-action">解锁权益 <uni-icons type="right" size="10" color="#654629"></uni-icons> </text> <text class="promo-action">解锁权益 <uni-icons type="right" size="10" color="#654629"></uni-icons> </text>
</template> </template>
<template v-else-if="item.shopType == 'waimai' && (item.status == '骑手到店取餐中' || item.status == '商家备餐中')"> <template v-else-if="item.promoType === 'cashback'">
<text class="promo-text text-basic">当笔订单返现成功到账<text style="color: #E31700;">点击领取</text></text> <text class="promo-text">{{ item.promoText }} <text class="highlight" v-if="item.promoHighlight">{{
<uni-icons type="right" size="10" color="#1A1A1A"></uni-icons> item.promoHighlight }}</text></text>
<text class="promo-action red">{{ item.promoAction || '点击领取' }} <uni-icons type="right" size="10"
color="#ED1C04"></uni-icons></text>
</template> </template>
<template v-else-if="item.promoType === 'coupon'"> <template v-else-if="item.promoType === 'coupon'">
<view class="coupon-row"> <view class="coupon-row">
@ -146,7 +149,7 @@
</template> </template>
<script setup> <script setup>
import { defineProps, computed, defineEmits } from 'vue'; import { defineProps, computed } from 'vue';
const props = defineProps({ const props = defineProps({
item: { item: {
@ -156,12 +159,6 @@ const props = defineProps({
} }
}); });
const emit = defineEmits(['btnClick', 'longpress']);
const onLongPress = (e) => {
emit('longpress', { event: e, item: props.item });
};
const getButtons = (shopType, status, item) => { const getButtons = (shopType, status, item) => {
const buttons = []; const buttons = [];
if (status == '等待付款') { if (status == '等待付款') {

View File

@ -27,7 +27,7 @@ export function createApp() {
const systemInfo = uni.getStorageSync('systemInfo') || {} const systemInfo = uni.getStorageSync('systemInfo') || {}
app.config.globalProperties.$system = systemInfo.platform == 'ios' ? 'iOS' : 'Android' app.config.globalProperties.$system = systemInfo.platform == 'ios' ? 'iOS' : 'Android'
app.config.globalProperties.$systemInfo = systemInfo app.config.globalProperties.$systemInfo = systemInfo
uni.setStorageSync('version', '1.0.3.sp17') uni.setStorageSync('version', '1.0.3.sp16')
app.config.globalProperties.$version = uni.getStorageSync('version') app.config.globalProperties.$version = uni.getStorageSync('version')
app.use(globalMethods); app.use(globalMethods);
return { return {

View File

@ -9,19 +9,23 @@
} }
} }
], ],
"subPackages": [{ "subPackages": [
{
"root": "pages/call-log", "root": "pages/call-log",
"pages": [{ "pages": [
{
"path": "call", "path": "call",
"style": { "style": {
"navigationBarTitleText": "通话记录页面", "navigationBarTitleText": "通话记录页面",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}] }
]
}, },
{ {
"root": "pages/message", "root": "pages/message",
"pages": [{ "pages": [
{
"path": "list-index", "path": "list-index",
"style": { "style": {
"navigationBarTitleText": "短信列表首页", "navigationBarTitleText": "短信列表首页",
@ -39,7 +43,8 @@
}, },
{ {
"root": "pages/shopping", "root": "pages/shopping",
"pages": [{ "pages": [
{
"path": "index", "path": "index",
"style": { "style": {
"navigationBarTitleText": "购物app首页", "navigationBarTitleText": "购物app首页",
@ -52,19 +57,13 @@
"navigationBarTitleText": "京东列表首页", "navigationBarTitleText": "京东列表首页",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},
{
"path": "jingdong/order-detail/order-detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
} }
] ]
}, },
{ {
"root": "pages/balance", "root": "pages/balance",
"pages": [{ "pages": [
{
"path": "index", "path": "index",
"style": { "style": {
"navigationBarTitleText": "余额页面", "navigationBarTitleText": "余额页面",
@ -90,7 +89,8 @@
}, },
{ {
"root": "pages/bill", "root": "pages/bill",
"pages": [{ "pages": [
{
"path": "bill-list/bill-list", "path": "bill-list/bill-list",
"style": { "style": {
"navigationBarTitleText": "账单列表页面", "navigationBarTitleText": "账单列表页面",
@ -115,7 +115,8 @@
}, },
{ {
"root": "pages/ant-credit-pay", "root": "pages/ant-credit-pay",
"pages": [{ "pages": [
{
"path": "index", "path": "index",
"style": { "style": {
"navigationBarTitleText": "花呗首页", "navigationBarTitleText": "花呗首页",
@ -133,7 +134,8 @@
}, },
{ {
"root": "pages/finance-management", "root": "pages/finance-management",
"pages": [{ "pages": [
{
"path": "index", "path": "index",
"style": { "style": {
"navigationBarTitleText": "理财首页", "navigationBarTitleText": "理财首页",
@ -158,7 +160,8 @@
}, },
{ {
"root": "pages/other", "root": "pages/other",
"pages": [{ "pages": [
{
"path": "/video-group-chat/video-group-chat", "path": "/video-group-chat/video-group-chat",
"style": { "style": {
"navigationBarTitleText": "视频群聊", "navigationBarTitleText": "视频群聊",
@ -259,20 +262,13 @@
"navigationBarTitleText": "飞猪火车票", "navigationBarTitleText": "飞猪火车票",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},
{
"path" : "ranking/ranking",
"style" :
{
"navigationBarTitleText" : "从夯倒拉排名",
"navigationStyle": "custom"
}
} }
] ]
}, },
{ {
"root": "pages/common", "root": "pages/common",
"pages": [{ "pages": [
{
"path": "hot-icon/hot-icon", "path": "hot-icon/hot-icon",
"style": { "style": {
"navigationBarTitleText": "热门图标", "navigationBarTitleText": "热门图标",

View File

@ -29,8 +29,7 @@
<!-- 金额 --> <!-- 金额 -->
<view class=" money info-item-input alipay-font" style="height: 77rpx;"> <view class=" money info-item-input alipay-font" style="height: 77rpx;">
<!-- 隐藏的text用于测量宽度 --> <!-- 隐藏的text用于测量宽度 -->
<text class="text-measure font-w500" style="font-size: 64rpx;">{{ <text class="text-measure font-w500" style="font-size: 64rpx;">{{ billData.money }}</text>
numberUtil.formatMoneyWithThousand(billData.money) }}</text>
</view> </view>
</view> </view>
@ -254,8 +253,7 @@ const {
} = addBillJson } = addBillJson
import { import {
util, util,
randomUtil, randomUtil
numberUtil
} from '@/utils/common.js' } from '@/utils/common.js'
import { import {

View File

@ -49,9 +49,9 @@
<view class="income-ande-outCome flex-between"> <view class="income-ande-outCome flex-between">
<view class="flex"> <view class="flex">
<view class="item"><text>支出</text><text class="money wx-font-regular">{{ <view class="item"><text>支出</text><text class="money wx-font-regular">{{
numberUtil.formatMoneyWithThousand(currentMonthData.outCome) }}</text></view> Number(currentMonthData.outCome).toFixed(2) }}</text></view>
<view class="item"><text>收入</text><text class="money wx-font-regular">{{ <view class="item"><text>收入</text><text class="money wx-font-regular">{{
numberUtil.formatMoneyWithThousand(currentMonthData.inCome) }}</text></view> Number(currentMonthData.inCome).toFixed(2) }}</text></view>
</view> </view>
<view class=""> <view class="">
@ -83,13 +83,13 @@
<view class="outCome item"> <view class="outCome item">
<text class="title">支出</text> <text class="title">支出</text>
<text class="amount alipay-font"><text class="font-11 wx-font-regular"></text>{{ <text class="amount alipay-font"><text class="font-11 wx-font-regular"></text>{{
numberUtil.formatMoneyWithThousand(item.outCome) Number(item.outCome).toFixed(2)
}}</text> }}</text>
</view> </view>
<view class="income item"> <view class="income item">
<text class="title">收入</text> <text class="title">收入</text>
<text class="amount alipay-font"><text class="font-11 wx-font-regular"></text>{{ <text class="amount alipay-font"><text class="font-11 wx-font-regular"></text>{{
numberUtil.formatMoneyWithThousand(item.inCome) Number(item.inCome).toFixed(2)
}}</text> }}</text>
</view> </view>
</view> </view>
@ -129,8 +129,7 @@
<script setup> <script setup>
import { import {
dateUtil, dateUtil,
util, util
numberUtil
} from '@/utils/common.js' } from '@/utils/common.js'
import navBar from '@/components/nav-bar/nav-bar.vue' import navBar from '@/components/nav-bar/nav-bar.vue'
import BalanceList from '@/components/balance-list/balance-list.vue' import BalanceList from '@/components/balance-list/balance-list.vue'

View File

@ -275,16 +275,11 @@ const otherList = [{
name: "通话", name: "通话",
path: "/pages/common/call-and-message-entry/call-and-message-entry?type=call" path: "/pages/common/call-and-message-entry/call-and-message-entry?type=call"
}, },
// { // {
// icon: "/static/image/index/qita/gouwu.png", // icon: "/static/image/index/qita/gouwu.png",
// name: "购物", // name: "购物",
// path: "/pages/shopping/index" // path: "/pages/shopping/index"
// }, // },
{
icon: "/static/image/index/qita/ranking.png",
name: "从夯倒拉排名",
path: "/pages/other/ranking/ranking"
},
] ]
const data = reactive({ const data = reactive({

View File

@ -1,697 +0,0 @@
<template>
<view class="ranking-page">
<nav-bar title="从夯到拉" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
@right-click="onRightClick">
</nav-bar>
<view class="content-container">
<view :class="{ 'skin-box': type == 'skin', 'table-box': type != 'skin' }"
:style="type == 'skin' ? { backgroundColor: skinBgColor } : {}">
<template v-if="type == 'skin'">
<view v-if="!isEdit" class="title">{{ title }}</view>
<input v-else class="title title-input" v-model="title" placeholder="请输入排名标题" />
<image class="img happy" src="/static/image/other/ranking/happy.png"></image>
<image class="img sad" src="/static/image/other/ranking/sad.png"></image>
</template>
<image class="watermark" :class="{}" src="/static/image/other/card/shuiyin2.png" mode="heightFix">
</image>
<view class="ranking-table">
<view v-for="(item, index) in tierList" :key="index" class="ranking-row">
<view class="label-box" :style="{ backgroundColor: item.bgColor }"
@click="changeRowBgColor(index)">
<text class="label-text" :class="{ 'with-stroke': item.hasStroke }"
:style="{ color: item.textColor }">
{{ item.label }}
</text>
</view>
<view class="items-box ranking-item-list" :id="'row-' + index">
<view v-for="(img, imgIdx) in item.images" :key="imgIdx" class="item-wrapper"
:class="{ 'is-dragging': drag.tierIndex === index && drag.imgIdx === imgIdx }"
:style="getDragStyle(index, imgIdx)" @touchstart="onTouchStart($event, index, imgIdx)"
@touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd">
<image :src="img" mode="aspectFill" class="item-img"></image>
<view v-if="isEdit" class="del-btn" @click.stop="deleteImage(index, imgIdx)">×</view>
</view>
<view v-if="isEdit && item.images.length < 4" class="add-btn" @click="chooseImage(index)">
<image class="add-icon" src="/static/image/common/add.png"></image>
</view>
</view>
</view>
</view>
</view>
<view class="save-action">
<button v-if="!isEdit" class="save-btn" @click="handleSave">保存图片</button>
<!-- 编辑模式下的全局颜色控制器 -->
<view v-else-if="type == 'skin'" class="bottom-edit-actions">
<view class="color-picker-wrapper">
<view class="color-picker">
<view v-for="color in ['#FFDFDF', '#DFF0FF', '#E0FFDF', '#FDF5C8', '#F3DFFF']" :key="color"
class="color-dot" :style="{ backgroundColor: color }" @click="skinBgColor = color">
</view>
</view>
<input v-if="false" class="hex-input" v-model="skinBgColor" placeholder="#HEX" maxlength="7" />
</view>
<view class="spectrum-picker" @touchstart="handleHueTouch" @touchmove.stop.prevent="handleHueTouch">
<view class="spectrum-bar"></view>
<view class="slider-thumb" :style="{ left: (skinHue / 360 * 100) + '%' }"></view>
</view>
<text class="edit-tip">点击左侧分类标签可切换背景色</text>
</view>
</view>
</view>
<view class="bottom-tabs">
<view class="tab-item" :class="{ active: type == 'base' }" @click="switchType('base')">基础</view>
<view class="tab-item" :class="{ active: type == 'skin' }" @click="switchType('skin')">皮肤</view>
</view>
<view class="painter-container" v-if="isSnapshot">
<l-painter isCanvasToTempFilePath @success="onPainterSuccess"
:css="`width:750rpx; padding: 40rpx; background-color:${type == 'skin' ? skinBgColor : '#F8F8F8'};`">
<l-painter-view
:css="`width: 100%; display: flex; flex-direction: column; position: relative; ${type == 'skin' ? 'padding-top: 120rpx;padding-bottom: 120rpx;' : ''}`">
<template v-if="type == 'skin'">
<l-painter-text :text="title"
css="position: absolute; top: 26rpx; left: 50%; transform: translateX(-50%); font-size: 36rpx; font-weight: bold; color: #333;" />
<l-painter-image src="/static/image/other/ranking/happy.png"
css="position: absolute;top: 58rpx;right: 24rpx; width: 96rpx; height: 96rpx;" />
</template>
<l-painter-view css="border: 3rpx solid #333; background-color: #fff; width: 100%;">
<l-painter-view v-for="(item, index) in tierList" :key="index"
:css="`display: flex; min-height: 148rpx; border-bottom: ${index === tierList.length - 1 ? 'none' : '3rpx solid #333'};`">
<l-painter-view
:css="`width: 176rpx; min-height: 148rpx; background-color: ${item.bgColor}; display: flex; align-items: center; justify-content: center; border-right: 3rpx solid #333;`">
<l-painter-text :text="item.label"
:css="`font-size: 52rpx; font-weight: bold; color: ${item.textColor}; ${item.hasStroke ? 'text-shadow: 2rpx 2rpx 0 #000, -2rpx -2rpx 0 #000, 2rpx -2rpx 0 #000, -2rpx 2rpx 0 #000, 0 2rpx 0 #000, 0 -2rpx 0 #000, 2rpx 0 0 #000, -2rpx 0 0 #000;' : ''}`" />
</l-painter-view>
<l-painter-view :css="`flex: 1; padding: 14rpx 16rpx; display: flex; align-items: center;`">
<l-painter-image v-for="(img, imgIdx) in item.images" :key="imgIdx" :src="img"
css="width: 110rpx; height: 110rpx; margin: 0 6rpx; object-fit: cover;"
mode="aspectFill" />
</l-painter-view>
</l-painter-view>
</l-painter-view>
<l-painter-view
:css="type == 'skin' ? `position: absolute;bottom: 32rpx;right: 14rpx;` : `position: absolute;top: 50%;right: 50%;transform: translate(50%, -50%);`">
<l-painter-image src="/static/image/other/card/shuiyin2.png"
css="width: 194rpx;height: 56rpx;" />
</l-painter-view>
<l-painter-image v-if="type == 'skin'" src="/static/image/other/ranking/sad.png"
css="position: absolute;bottom: 76rpx;left: 116rpx; width: 96rpx; height: 96rpx;" />
</l-painter-view>
</l-painter>
</view>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const type = ref("base");
const title = ref("xx排名");
const skinBgColor = ref("#FFDFDF");
const skinHue = ref(0); //
const isSnapshot = ref(false);
const isEdit = ref(false);
const rightButtonText = ref("编辑");
const tierList = ref([
{ label: '夯', bgColor: '#D5171C', textColor: '#FFFFFF', hasStroke: true, images: [] },
{ label: '顶级', bgColor: '#FF6A0B', textColor: '#FFFFFF', hasStroke: true, images: [] },
{ label: '人上人', bgColor: '#FFF06A', textColor: '#FFFFFF', hasStroke: true, images: [] },
{ label: 'NPC', bgColor: '#FDF5C8', textColor: '#FFFFFF', hasStroke: true, images: [] },
{ label: '拉完了', bgColor: '#FFFFFF', textColor: '#FFFFFF', hasStroke: true, images: [] }
]);
// --- ---
onLoad(() => {
const cache = uni.getStorageSync('ranking_config_data');
if (cache) {
title.value = cache.title || title.value;
type.value = cache.type || type.value;
skinBgColor.value = cache.skinBgColor || skinBgColor.value;
skinHue.value = cache.skinHue ?? skinHue.value;
if (cache.tierList) tierList.value = cache.tierList;
console.log(tierList.value);
}
});
// --- ---
const drag = reactive({
tierIndex: -1,
imgIdx: -1,
startX: 0,
startY: 0,
moveX: 0,
moveY: 0
});
//
const getDragStyle = (tIdx, iIdx) => {
if (drag.tierIndex === tIdx && drag.imgIdx === iIdx) {
return {
transform: `translate(${drag.moveX}px, ${drag.moveY}px)`,
zIndex: 99,
transition: 'none'
};
}
return { transition: 'transform 0.3s ease' };
};
const onTouchStart = (e, tIdx, iIdx) => {
if (!isEdit.value) return;
const touch = e.touches[0];
drag.tierIndex = tIdx;
drag.imgIdx = iIdx;
drag.startX = touch.clientX;
drag.startY = touch.clientY;
drag.moveX = 0;
drag.moveY = 0;
};
const onTouchMove = (e) => {
if (drag.tierIndex === -1) return;
const touch = e.touches[0];
drag.moveX = touch.clientX - drag.startX;
drag.moveY = touch.clientY - drag.startY;
};
const onTouchEnd = () => {
if (drag.tierIndex === -1) return;
const { tierIndex, imgIdx, moveX } = drag;
const rowData = tierList.value[tierIndex].images;
// item (100rpx + 12rpx 56px)
const itemWidth = 56;
const offset = Math.round(moveX / itemWidth);
let newIndex = imgIdx + offset;
//
newIndex = Math.max(0, Math.min(newIndex, rowData.length - 1));
if (newIndex !== imgIdx) {
const temp = rowData.splice(imgIdx, 1)[0];
rowData.splice(newIndex, 0, temp);
}
//
drag.tierIndex = -1;
drag.imgIdx = -1;
};
// --- ---
const chooseImage = (index) => {
const currentCount = tierList.value[index].images.length;
uni.chooseImage({
count: 4 - currentCount,
sizeType: ['compressed'],
success: (res) => {
tierList.value[index].images.push(...res.tempFilePaths);
}
});
};
const deleteImage = (tIdx, iIdx) => {
const path = tierList.value[tIdx].images[iIdx];
removeLocalFile(path); //
tierList.value[tIdx].images.splice(iIdx, 1);
};
const onRightClick = async () => {
if (isEdit.value) {
uni.showLoading({ title: '正在持久化图片...', mask: true });
// 1.
for (let tierIdx = 0; tierIdx < tierList.value.length; tierIdx++) {
const tier = tierList.value[tierIdx];
for (let i = 0; i < tier.images.length; i++) {
const path = tier.images[i];
// static _doc/usr
const isStatic = path.startsWith('/static/') || path.startsWith('static/');
const isPersistent = path.indexOf('_doc/') !== -1 || path.indexOf('usr/') !== -1;
if (!isStatic && !isPersistent) {
console.log('检测到待持久化图片:', path);
const newPath = await saveImageToLocal(path);
if (newPath) {
tier.images[i] = newPath;
console.log('持久化成功,新路径:', newPath);
}
}
}
}
// 2.
uni.setStorageSync('ranking_config_data', {
title: title.value,
type: type.value,
skinBgColor: skinBgColor.value,
skinHue: skinHue.value,
tierList: tierList.value
});
uni.hideLoading();
uni.showToast({ title: '已保存', icon: 'none' });
}
isEdit.value = !isEdit.value;
rightButtonText.value = isEdit.value ? "确定" : "编辑";
};
/**
* 将临时图片保存到本地永久目录
*/
const saveImageToLocal = (tempFilePath) => {
return new Promise((resolve) => {
//
if (tempFilePath.indexOf('_doc/') !== -1 || tempFilePath.indexOf('usr/') !== -1) {
return resolve(tempFilePath);
}
uni.saveFile({
tempFilePath: tempFilePath,
success: (res) => {
resolve(res.savedFilePath);
},
fail: (err) => {
console.error('本地持久化保存失败:', err);
// H5 saveFile App/
resolve(null);
}
});
});
};
/**
* 物理删除本地已保存的文件
*/
const removeLocalFile = (path) => {
if (!path) return;
//
if (path.indexOf('_doc/') !== -1 || path.indexOf('usr/') !== -1) {
uni.removeSavedFile({
filePath: path,
success: () => console.log('文件物理删除成功:', path),
fail: (err) => console.log('文件删除失败:', err)
});
}
};
const handleSave = () => {
uni.showLoading({ title: '生成中...', mask: true });
isSnapshot.value = true;
};
const onPainterSuccess = (path) => {
const done = () => {
isSnapshot.value = false;
uni.hideLoading();
};
if (!path) return done();
uni.saveImageToPhotosAlbum({
filePath: path,
success: () => uni.showToast({ title: '保存成功' }),
fail: () => uni.showToast({ title: '保存失败', icon: 'none' }),
complete: done
});
};
const switchType = (val) => {
type.value = val;
if (val == 'skin') {
tierList.value[0].bgColor = '#F3575B'
tierList.value[1].bgColor = '#FF9B5B'
tierList.value[2].bgColor = '#FFF59E'
tierList.value[3].bgColor = '#FFFBE1'
tierList.value[4].bgColor = '#FFFFFF'
} else {
tierList.value[0].bgColor = '#D5171C'
tierList.value[1].bgColor = '#FF6A0B'
tierList.value[2].bgColor = '#FFF06A'
tierList.value[3].bgColor = '#FDF5C8'
tierList.value[4].bgColor = '#FFFFFF'
}
// type便
const cache = uni.getStorageSync('ranking_config_data') || {};
cache.type = val;
uni.setStorageSync('ranking_config_data', cache);
}
/**
* 循环切换行背景色 (编辑模式下)
*/
const changeRowBgColor = (index) => {
if (!isEdit.value) return;
const colors = ['#D5171C', '#FF6A0B', '#FFF06A', '#FDF5C8', '#FFFFFF', '#1777FF', '#333333'];
const curr = tierList.value[index].bgColor;
let nextIdx = (colors.indexOf(curr.toUpperCase()) + 1) % colors.length;
if (nextIdx === -1) nextIdx = 0;
tierList.value[index].bgColor = colors[nextIdx];
// ()
const darkColors = ['#D5171C', '#1777FF', '#333333'];
tierList.value[index].textColor = darkColors.includes(colors[nextIdx]) ? '#FFFFFF' : '#333333';
};
/**
* 处理色域滑动
*/
const handleHueTouch = (e) => {
const touch = e.touches[0];
uni.createSelectorQuery().select('.spectrum-picker').boundingClientRect(rect => {
if (rect) {
const x = Math.max(0, Math.min(touch.clientX - rect.left, rect.width));
skinHue.value = Math.round((x / rect.width) * 360);
// 1. HSL
const h = skinHue.value;
const s = 70;
const l = 90;
// 2. 16
skinBgColor.value = hslToHex(h, s, l);
}
}).exec();
};
/**
* HSL Hex 工具函数
*/
function hslToHex(h, s, l) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0');
};
return `#${f(0)}${f(8)}${f(4)}`.toUpperCase();
}
</script>
<style lang="less" scoped>
.ranking-page {
min-height: 100vh;
background-color: #F8F8F8;
padding-bottom: 200rpx;
}
.content-container {
position: relative;
padding: 12rpx 24rpx;
}
.table-box {
position: relative;
.watermark {
position: absolute;
height: 56rpx;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 99;
}
}
.ranking-table {
border: 3rpx solid #333;
background-color: #fff;
}
.ranking-row {
display: flex;
min-height: 148rpx;
border-bottom: 3rpx solid #333;
&:last-child {
border-bottom: none;
}
}
.label-box {
width: 176rpx;
display: flex;
align-items: center;
justify-content: center;
border-right: 3rpx solid #333;
}
.label-text {
font-size: 48rpx;
font-weight: bold;
&.with-stroke {
text-shadow: 2rpx 2rpx 0 #000, -2rpx -2rpx 0 #000, 2rpx -2rpx 0 #000, -2rpx 2rpx 0 #000;
}
}
.items-box {
flex: 1;
display: flex;
align-items: center;
padding: 14rpx 8rpx;
flex-wrap: wrap;
}
.item-wrapper {
width: 100rpx;
height: 100rpx;
position: relative;
margin: 0 6rpx;
touch-action: none;
/* 关键:禁止浏览器默认触摸行为 */
&.is-dragging {
opacity: 0.7;
scale: 1.1;
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.2);
}
}
.item-img {
width: 100%;
height: 100%;
border-radius: 4rpx;
}
.del-btn {
position: absolute;
top: -12rpx;
right: -12rpx;
width: 36rpx;
height: 36rpx;
background: #ff4d4f;
color: #fff;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
z-index: 10;
}
.add-btn {
width: 100rpx;
height: 100rpx;
background: #eee;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4rpx;
.add-icon {
width: 40rpx;
height: 40rpx;
}
}
.save-btn {
margin-top: 60rpx;
width: 400rpx;
background: #1777FF;
color: #fff;
border-radius: 50rpx;
}
.bottom-tabs {
position: fixed;
bottom: 40rpx;
width: 100%;
display: flex;
justify-content: center;
.tab-item {
width: 180rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background: #fff;
margin: 0 20rpx;
border-radius: 10rpx;
&.active {
border: 4rpx solid #1777FF;
color: #1777FF;
}
}
}
.skin-box {
position: relative;
padding: 120rpx 12rpx;
background-color: #FFDFDF;
.watermark {
height: 56rpx !important;
position: absolute;
right: 14rpx !important;
bottom: 32rpx !important;
}
.title {
position: absolute;
top: 30rpx;
left: 50%;
transform: translateX(-50%);
font-weight: bold;
text-align: center;
font-size: 36rpx;
color: #333;
}
.title-input {
background: rgba(255, 255, 255, 0.5);
border-radius: 8rpx;
padding: 4rpx 12rpx;
width: 300rpx;
border: 1rpx dashed #1777FF;
}
.title-input {
background: rgba(255, 255, 255, 0.5);
border-radius: 8rpx;
padding: 4rpx 12rpx;
width: 300rpx;
border: 1rpx dashed #1777FF;
}
.img {
position: absolute;
width: 90rpx;
height: 90rpx;
}
.happy {
top: 40rpx;
right: 30rpx;
}
.sad {
bottom: 60rpx;
left: 100rpx;
}
}
.save-action {
margin-top: 60rpx;
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 60rpx;
}
.bottom-edit-actions {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.edit-tip {
font-size: 22rpx;
color: #999;
margin-top: 10rpx;
}
.color-picker {
display: flex;
gap: 16rpx;
background: #fff;
padding: 12rpx 20rpx;
border-radius: 40rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.color-picker-wrapper {
display: flex;
align-items: center;
margin: 12rpx 0;
}
.hex-input {
width: 150rpx;
height: 56rpx;
background: #fff;
border-radius: 28rpx;
font-size: 24rpx;
text-align: center;
color: #333;
border: 1rpx solid #eee;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.spectrum-picker {
width: 600rpx;
height: 32rpx;
background: #fff;
border-radius: 16rpx;
padding: 4rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
position: relative;
margin: 12rpx 0;
}
.slider-thumb {
position: absolute;
top: 50%;
width: 38rpx;
height: 38rpx;
background: #fff;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.3);
border: 2rpx solid #fff;
pointer-events: none;
}
.spectrum-bar {
width: 100%;
height: 100%;
border-radius: 12rpx;
background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
.color-dot {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid #fff;
box-shadow: 0 0 4rpx rgba(0, 0, 0, 0.2);
margin: 0 10rpx;
}
.painter-container {
position: fixed;
left: -9999rpx;
}
</style>

View File

@ -1,136 +0,0 @@
<script setup>
import { ref } from 'vue';
const list = ref([
{ label: '澶?, bgColor: '#BE0012', textColor: '#FFFFFF', hasShadow: true },
{ label: '椤剁骇', bgColor: '#F17415', textColor: '#FFFFFF', hasShadow: true },
{ label: '浜轰笂浜?, bgColor: '#F9E962', textColor: '#FFFFFF', hasShadow: true },
{ label: 'NPC', bgColor: '#FDF5C0', textColor: '#555555', hasShadow: false },
{ label: '鎷夊畬浜?, bgColor: '#FFFFFF', textColor: '#555555', hasShadow: false }
]);
const handleAdd = (index) => {
console.log('娣诲姞椤?, index);
};
</script>
<template>
<view class="ranking-container">
<view class="ranking-table">
<view v-for="(item, index) in list" :key="index" class="ranking-row">
<!-- 鏍囩鍒?-->
<view class="label-col" :style="{ backgroundColor: item.bgColor }">
<text class="label-text" :class="{ 'with-shadow': item.hasShadow }" :style="{ color: item.textColor }">
{{ item.label }}
</text>
</view>
<!-- 鍐呭鍒?-->
<view class="content-col">
<!-- 浠呭湪绗竴琛屽睍绀烘紨绀哄浘鐗?-->
<template v-if="index === 0">
<view class="item-box">
<image src="/static/images/food.jpg" mode="aspectFill" class="item-img" />
</view>
</template>
<!-- 娣诲姞鎸夐挳 -->
<view class="add-btn" @tap="handleAdd(index)">
<text class="plus-icon">+</text>
</view>
</view>
</view>
</view>
</view>
</template>
<style lang="less">
.ranking-container {
padding: 30rpx 20rpx;
background-color: #F8F8F8;
min-height: 100vh;
}
.ranking-table {
border: 2rpx solid #333;
background-color: #fff;
display: flex;
flex-direction: column;
}
.ranking-row {
display: flex;
min-height: 180rpx;
border-bottom: 2rpx solid #333;
&:last-child {
border-bottom: none;
}
}
.label-col {
width: 200rpx;
display: flex;
align-items: center;
justify-content: center;
border-right: 2rpx solid #333;
padding: 0 10rpx;
box-sizing: border-box;
}
.label-text {
font-size: 52rpx;
font-weight: bold;
text-align: center;
line-height: 1.2;
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
&.with-shadow {
/* 寮哄姏榛戣壊鎻忚竟锛屾ā鎷?:1鏁堟灉 */
text-shadow:
2rpx 2rpx 0 #000,
-2rpx -2rpx 0 #000,
2rpx -2rpx 0 #000,
-2rpx 2rpx 0 #000,
0 2rpx 0 #000,
0 -2rpx 0 #000,
2rpx 0 0 #000,
-2rpx 0 0 #000;
}
}
.content-col {
flex: 1;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
padding: 20rpx;
gap: 20rpx;
}
.item-box {
width: 140rpx;
height: 140rpx;
background-color: #eee;
border: 1rpx solid #ddd;
}
.item-img {
width: 100%;
height: 100%;
}
.add-btn {
width: 140rpx;
height: 140rpx;
background-color: #F2F2F2;
display: flex;
align-items: center;
justify-content: center;
.plus-icon {
font-size: 70rpx;
color: #DBDBDB;
font-weight: 200;
}
}
</style>

View File

@ -43,14 +43,9 @@
</view> </view>
</view> </view>
<view class="content" :style="{ paddingTop: contentPaddingTop }"> <view class="content" :style="{ paddingTop: contentPaddingTop }">
<shopping-card v-for="(item, index) in filteredOrderList" :key="index" :item="item" @longpress="handleLongPress" <shopping-card v-for="(item, index) in filteredOrderList" :key="index" :item="item"></shopping-card>
@click="handleCardClick(item)"></shopping-card>
<view class="empty-state" v-if="filteredOrderList.length === 0">
<image class="empty-icon" src="/static/image/shopping/jingdong/null.png" mode="heightFix"></image>
<text class="empty-text">您还没有相关订单</text>
</view> </view>
</view> <view class="bottom-fixed">
<view class="bottom-fixed" :style="{ height: bottomBoxHeight }">
<view class="bottom-item"> <view class="bottom-item">
<image class="like-icon" src="/static/image/shopping/jingdong/weinituijian.png" mode="aspectFit"></image> <image class="like-icon" src="/static/image/shopping/jingdong/weinituijian.png" mode="aspectFit"></image>
<text>为你推荐</text> <text>为你推荐</text>
@ -63,76 +58,15 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 长按操作气泡菜单 -->
<view v-if="showActionMenu" class="action-menu-mask" @click="showActionMenu = false">
<view class="action-menu-bubble" :style="{ left: actionMenuState.x + 'px', top: actionMenuState.y + 'px' }"
@click.stop>
<view class="menu-item" @click.stop="editOrder">修改</view>
<view class="bubble-arrow"></view>
<view class="menu-item" @click.stop="handleDeleteOrder">删除</view>
<view class="bubble-arrow"></view>
</view>
</view>
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, getCurrentInstance } from 'vue'; import { ref, computed, onMounted, getCurrentInstance } from 'vue';
import ShoppingCard from '@/components/shopping/jingdong/shopping-card.vue'; import ShoppingCard from '@/components/shopping/jingdong/shopping-card.vue';
const showActionMenu = ref(false);
const actionMenuState = ref({ x: 0, y: 0, item: null });
const handleLongPress = (data) => {
let touch = data.event.touches[0];
if (!touch && data.event.changedTouches) touch = data.event.changedTouches[0];
if (touch) {
actionMenuState.value = {
x: touch.clientX,
y: touch.clientY,
item: data.item
};
showActionMenu.value = true;
}
};
const handleCardClick = (item) => {
if (item.shopType !== "waimai") {
uni.navigateTo({
url: '/pages/shopping/jingdong/order-detail/order-detail?id=' + item.id
});
}
};
/**
* 删除订单
*/
const handleDeleteOrder = () => {
const itemToDel = actionMenuState.value.item;
const realIndex = mockOrderList.value.findIndex(item => item === itemToDel);
if (realIndex > -1) {
mockOrderList.value.splice(realIndex, 1);
}
showActionMenu.value = false;
uni.showToast({ title: '已删除', icon: 'none' });
};
const contentPaddingTop = ref('0px'); const contentPaddingTop = ref('0px');
const instance = getCurrentInstance(); const instance = getCurrentInstance();
/**
* 底部盒子高度
*/
const bottomBoxHeight = computed(() => {
const { windowHeight } = uni.getSystemInfoSync();
return `calc(${windowHeight}px - ${contentPaddingTop.value} - 324rpx)`;
});
/**
* 初始化
*/
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
const query = uni.createSelectorQuery().in(instance.proxy); const query = uni.createSelectorQuery().in(instance.proxy);
@ -152,11 +86,6 @@ const tabList = ref([
{ name: '服务', icon: '/static/image/shopping/jingdong/jiazheng.png', disabled: true } { name: '服务', icon: '/static/image/shopping/jingdong/jiazheng.png', disabled: true }
]); ]);
/**
* 切换tab
* @param index
*/
const switchTab = (index) => { const switchTab = (index) => {
if (tabList.value[index].disabled) return; if (tabList.value[index].disabled) return;
currentTab.value = index; currentTab.value = index;
@ -166,16 +95,12 @@ const currentFilter = ref(-1);
const filterList = ref([ const filterList = ref([
{ name: '待付款' }, { name: '待付款' },
{ name: '待收货' }, { name: '待收货' },
{ name: '待使用', disabled: false }, { name: '待使用', disabled: true },
{ name: '已完成' }, { name: '已完成' },
{ name: '待评价' }, { name: '待评价' },
{ name: '已取消' } { name: '已取消' }
]); ]);
/**
* 切换筛选
* @param index 索引
*/
const switchFilter = (index) => { const switchFilter = (index) => {
if (filterList.value[index].disabled) return; if (filterList.value[index].disabled) return;
if (currentFilter.value === index) { if (currentFilter.value === index) {
@ -185,9 +110,6 @@ const switchFilter = (index) => {
} }
}; };
/**
* 筛选订单列表
*/
const filteredOrderList = computed(() => { const filteredOrderList = computed(() => {
const tabName = tabList.value[currentTab.value].name; const tabName = tabList.value[currentTab.value].name;
let baseList = mockOrderList.value; let baseList = mockOrderList.value;
@ -214,12 +136,8 @@ const filteredOrderList = computed(() => {
}); });
}); });
/**
* 模拟订单列表
*/
const mockOrderList = ref([ const mockOrderList = ref([
{ {
id: 123211111,
shopType: 'waimai', shopType: 'waimai',
shopName: '安野屋 (AARYE) 京...', shopName: '安野屋 (AARYE) 京...',
status: '等待付款', status: '等待付款',
@ -236,9 +154,14 @@ const mockOrderList = ref([
], ],
promoType: 'text', promoType: 'text',
promoHighlight: '近90天600+人回购', promoHighlight: '近90天600+人回购',
buttons: [
{ text: '取消订单', type: 'default' },
{ text: '查看发票', type: 'default' },
{ text: '修改订单', type: 'default' },
{ text: '去支付', type: 'primary' }
]
}, },
{ {
id: 9632554,
shopType: 'waimai', shopType: 'waimai',
shopName: '安野屋 (AARYE) 京...', shopName: '安野屋 (AARYE) 京...',
status: '骑手到店取餐中', status: '骑手到店取餐中',
@ -254,10 +177,16 @@ const mockOrderList = ref([
price: '69.00', price: '69.00',
count: 1, count: 1,
} }
],
promoType: 'cashback',
promoText: '当笔订单返现成功到账,',
promoAction: '点击领取',
buttons: [
{ text: '申请退款', type: 'default' },
{ text: '查看发票', type: 'default' }
] ]
}, },
{ {
id: 63254112,
shopType: 'waimai', shopType: 'waimai',
shopName: '安野屋 (AARYE) 京...', shopName: '安野屋 (AARYE) 京...',
status: '商家备餐中', status: '商家备餐中',
@ -273,10 +202,16 @@ const mockOrderList = ref([
price: '69.00', price: '69.00',
count: 1, count: 1,
} }
],
promoType: 'cashback',
promoText: '当笔订单返现成功到账,',
promoAction: '点击领取',
buttons: [
{ text: '申请退款', type: 'default' },
{ text: '查看发票', type: 'default' }
] ]
}, },
{ {
id: 78456211,
shopType: 'waimai', shopType: 'waimai',
shopName: '瑞幸咖啡', shopName: '瑞幸咖啡',
status: '完成', status: '完成',
@ -293,10 +228,15 @@ const mockOrderList = ref([
], ],
promoType: 'coupon', promoType: 'coupon',
promoText: '恭喜您获得3元京东购物券', promoText: '恭喜您获得3元京东购物券',
promoAction: '去领券' promoAction: '去领券',
buttons: [
{ text: '删除订单', type: 'default' },
{ text: '查看发票', type: 'default' },
{ text: '退换/售后', type: 'default' },
{ text: '再次购买', type: 'primary' }
]
}, },
{ {
id: 56322115,
shopType: 'waimai', shopType: 'waimai',
shopName: '瑞幸咖啡', shopName: '瑞幸咖啡',
status: '完成', status: '完成',
@ -314,9 +254,14 @@ const mockOrderList = ref([
], ],
price: '17.00', price: '17.00',
count: 2, count: 2,
buttons: [
{ text: '删除订单', type: 'default' },
{ text: '查看发票', type: 'default' },
{ text: '退换/售后', type: 'default' },
{ text: '再次购买', type: 'primary' }
]
}, },
{ {
id: 52322221,
shopType: 'waimai', shopType: 'waimai',
shopName: '瑞幸咖啡', shopName: '瑞幸咖啡',
status: '已取消', status: '已取消',
@ -330,10 +275,14 @@ const mockOrderList = ref([
price: '69.00', price: '69.00',
count: 1, count: 1,
} }
],
buttons: [
{ text: '删除订单', type: 'default' },
{ text: '钱款去向', type: 'default' },
{ text: '再次购买', type: 'primary' }
] ]
}, },
{ {
id: 8562245551,
shopType: 'self', shopType: 'self',
shopName: '安野屋 (AARYE) 京联名哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈好梦', shopName: '安野屋 (AARYE) 京联名哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈好梦',
status: '等待付款', status: '等待付款',
@ -350,9 +299,14 @@ const mockOrderList = ref([
], ],
promoType: 'text', promoType: 'text',
promoHighlight: '白条支付券0.5元优惠券', promoHighlight: '白条支付券0.5元优惠券',
buttons: [
{ text: '取消订单', type: 'default' },
{ text: '查看发票', type: 'default' },
{ text: '修改订单', type: 'default' },
{ text: '去支付', type: 'primary', badge: '减0.5元' }
]
}, },
{ {
id: 5504455,
shopType: 'none', shopType: 'none',
shopName: '甜小南旗舰店', shopName: '甜小南旗舰店',
status: '正在出库', status: '正在出库',
@ -371,9 +325,14 @@ const mockOrderList = ref([
], ],
promoType: 'plus', promoType: 'plus',
promoText: '告别凑单, 享免运优惠', promoText: '告别凑单, 享免运优惠',
buttons: [
{ text: '查看发票', type: 'default' },
{ text: '再次购买', type: 'default' },
{ text: '申请退款', type: 'default' },
{ text: '修改订单', type: 'default' }
]
}, },
{ {
id: 585552,
shopType: 'self', shopType: 'self',
shopName: '甜小南旗舰店', shopName: '甜小南旗舰店',
status: '完成', status: '完成',
@ -394,9 +353,13 @@ const mockOrderList = ref([
promoType: 'plus', promoType: 'plus',
promoText: '告别凑单, 享免运优惠', promoText: '告别凑单, 享免运优惠',
hasMore: true, hasMore: true,
buttons: [
{ text: '卖了换钱', type: 'default' },
{ text: '退还/售后', type: 'default' },
{ text: '再次购买', type: 'primary' }
]
}, },
{ {
id: 4545451,
shopType: 'jd', shopType: 'jd',
shopName: '甜小南旗舰店', shopName: '甜小南旗舰店',
status: '完成', status: '完成',
@ -412,9 +375,13 @@ const mockOrderList = ref([
} }
], ],
hasMore: true, hasMore: true,
buttons: [
{ text: '再次购买', type: 'default' },
{ text: '申请退款', type: 'default' },
{ text: '修改订单', type: 'default' }
]
}, },
{ {
id: 1236524,
shopType: 'self', shopType: 'self',
shopName: '甜小南旗舰店', shopName: '甜小南旗舰店',
status: '已取消', status: '已取消',
@ -428,6 +395,11 @@ const mockOrderList = ref([
price: '1669.00', price: '1669.00',
count: 1, count: 1,
} }
],
buttons: [
{ text: '再次购买', type: 'default' },
{ text: '申请退款', type: 'default' },
{ text: '修改订单', type: 'primary' }
] ]
} }
]); ]);
@ -631,12 +603,6 @@ const mockOrderList = ref([
padding: 0 20rpx; padding: 0 20rpx;
} }
.bottom-fixed {
display: flex;
flex-direction: column;
}
.bottom-item { .bottom-item {
display: flex; display: flex;
align-items: center; align-items: center;
@ -656,8 +622,7 @@ const mockOrderList = ref([
.upload-screenshot-box { .upload-screenshot-box {
width: 100%; width: 100%;
flex: 1; height: 540rpx;
min-height: 540rpx;
background-color: #FFFFFF; background-color: #FFFFFF;
display: flex; display: flex;
align-items: center; align-items: center;
@ -682,69 +647,4 @@ const mockOrderList = ref([
} }
} }
} }
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx 0 64rpx;
.empty-icon {
height: 220rpx;
margin-bottom: 12rpx;
}
.empty-text {
font-size: 22rpx;
color: #999A9E;
line-height: 24rpx;
}
}
.action-menu-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
}
.action-menu-bubble {
position: fixed;
background-color: #3B3C3E;
border-radius: 12rpx;
width: 200rpx;
transform: translate(-50%, calc(-100% - 15px));
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
.menu-item {
color: #FFFFFF;
font-size: 26rpx;
text-align: center;
padding: 24rpx 0;
line-height: 26rpx;
}
.menu-line {
height: 1rpx;
background-color: rgba(255, 255, 255, 0.1);
margin: 0 24rpx;
}
.bubble-arrow {
position: absolute;
bottom: -12rpx;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
border-top: 14rpx solid #3B3C3E;
}
}
</style> </style>

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB