1
0
forked from dyf/APP
# Conflicts:
#	pages.json
#	unpackage/dist/dev/app-plus/app-config-service.js
#	unpackage/dist/dev/app-plus/app-service.js
#	unpackage/dist/dev/app-plus/app-view.js
#	unpackage/dist/dev/app-plus/manifest.json
#	utils/request.js
This commit is contained in:
liub
2025-08-11 15:21:37 +08:00
126 changed files with 3977 additions and 727 deletions

View File

@ -1,182 +1,292 @@
<template>
<view class="agreement-mask" v-if="show" @click="closePopup">
<view class="agreement-popup" @click.stop>
<view class="popup-content">
<!-- 动态图标 -->
<image v-if="showIcon && icon" :src="icon" mode="aspectFit" class="svg"></image>
<view class="text-content">
<!-- 动态标题 -->
<view class="popup-Title" v-if="title">{{ title }}</view>
<!-- 动态消息内容 -->
<view class="popup-Message" v-if="message">{{ message }}</view>
</view>
</view>
<!-- 按钮组 -->
<view class="popup-buttons">
<button v-if="showCancel" class="btn cancelBtn" @click="handleCancel">{{ cancelText }}</button>
<button class="btn agreeBtn" @click="handleConfirm">{{ confirmText }}</button>
</view>
</view>
</view>
<view class="agreement-mask" v-if="show" @click.stop="closePopup">
<!-- 弹窗主体支持自定义边框背景 -->
<view class="agreement-popup" @click.stop :style="{
border: popupBorder,
backgroundColor: popupBg,
borderRadius: popupRadius
}" :class="popupClass">
<view class="text-content">
<!-- 动态标题支持自定义颜色字体大小 -->
<view class="popup-Title" v-if="title" :style="{
color: titleColor,
fontSize: titleSize,
padding: titlePadding
}">
{{ title }}
</view>
<view class="popup-content">
<!-- 动态图标支持自定义大小边距 -->
<image v-if="showIcon && icon" :src="icon" mode="aspectFit" class="svg" :style="iconStyle"></image>
<!-- 动态消息内容支持自定义颜色换行字体大小 -->
<view class="popup-Message" v-if="message" :style="{
color: messageColor,
fontSize: messageSize,
whiteSpace: messageWrap ? 'normal' : 'nowrap',
padding: messagePadding
}">
{{ message }}
</view>
<!-- 倒计时显示 -->
<!-- <view v-if="showCountdown" class="countdown" :style="countdownStyle">
{{ countdownFormat.replace('{time}', currentCountdown) }}
</view> -->
</view>
</view>
<!-- 按钮组支持自定义按钮样式 -->
<view class="popup-buttons" :style="{ marginTop: buttonGroupMargin }">
<button v-if="showCancel" class="btn cancelBtn" @click="handleCancel" :style="{
border: cancelBtnBorder,
color: cancelBtnColor,
backgroundColor: cancelBtnBg,
fontSize: cancelBtnSize,
borderRadius: buttonRadius,
margin: buttonMargin
}" :class="cancelBtnClass">
{{ cancelText }}
</button>
<button class="btn agreeBtn" @click="handleConfirm" :style="{
backgroundColor: confirmBtnBg,
color: confirmBtnColor,
fontSize: confirmBtnSize,
borderRadius: buttonRadius,
margin: buttonMargin
}" :class="confirmBtnClass">
{{ confirmText }}
</button>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// 控制显示
show: {
type: Boolean,
default: false
},
// 标题内容(可选)
title: {
type: String,
default: ''
},
// 消息内容
message: {
type: String,
default: ''
},
// 确认按钮文本
confirmText: {
type: String,
default: '确定'
},
// 取消按钮文本
cancelText: {
type: String,
default: '取消'
},
// 是否显示取消按钮
showCancel: {
type: Boolean,
default: false
},
// 是否显示图标
showIcon: {
type: Boolean,
default: true
},
// 图标路径(支持网络和本地路径)
icon: {
type: String,
default: ''
},
// 图标样式
iconStyle: {
type: Object,
default: () => ({
width: '58rpx',
height: '62rpx',
marginBottom: '20rpx'
})
}
},
methods: {
handleConfirm() {
this.$emit('confirm')
this.$emit('update:show', false)
},
handleCancel() {
this.$emit('cancel')
this.$emit('update:show', false)
},
closePopup() {
this.$emit('close')
this.$emit('update:show', false)
}
}
}
export default {
name: 'CustomPopup',
props: {
// 基础控制
show: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
message: {
type: String,
default: ''
},
showCountdown: {
type: Boolean,
default: false
},
confirmText: {
type: String,
default: '确定'
},
cancelText: {
type: String,
default: '取消'
},
showCancel: {
type: Boolean,
default: false
},
showIcon: {
type: Boolean,
default: true
},
icon: {
type: String,
default: ''
},
// 文本换行控制
messageWrap: {
type: Boolean,
default: false // 默认不换行true则自动换行
},
// 弹窗样式自定义
popupBorder: {
type: String,
default: '1px solid rgba(187, 230, 0, 0.3)'
},
popupBg: {
type: String,
default: 'rgb(42, 42, 42, 0.9)'
},
popupRadius: {
type: String,
default: '40rpx'
},
popupClass: {
type: String,
default: ''
},
// 标题样式自定义
titleColor: {
type: String,
default: 'rgba(255, 255, 255, 0.86)'
},
titleSize: {
type: String,
default: '32rpx'
},
titlePadding: {
type: String,
default: '10rpx 0 10rpx'
},
// 消息样式自定义
messageColor: {
type: String,
default: 'rgba(255, 255, 255, 0.7)'
},
messageSize: {
type: String,
default: '28rpx'
},
messagePadding: {
type: String,
default: '10rpx 20rpx 30rpx'
},
// 图标样式自定义
iconStyle: {
type: Object,
default: () => ({
width: '72rpx',
height: '60rpx',
marginBottom: '20rpx'
})
},
// 按钮组样式
buttonGroupMargin: {
type: String,
default: '20rpx'
},
buttonRadius: {
type: String,
default: '40rpx'
},
buttonMargin: {
type: String,
default: '0 10rpx'
},
// 确认按钮样式
confirmBtnBg: {
type: String,
default: 'rgba(187, 230, 0, 1)'
},
confirmBtnColor: {
type: String,
default: '#232323'
},
confirmBtnSize: {
type: String,
default: '24rpx'
},
confirmBtnClass: {
type: String,
default: ''
},
// 取消按钮样式
cancelBtnBorder: {
type: String,
default: '1px solid rgba(255, 255, 255, 0.3)'
},
cancelBtnColor: {
type: String,
default: 'rgba(255, 255, 255, 0.7)'
},
cancelBtnBg: {
type: String,
default: 'transparent'
},
cancelBtnSize: {
type: String,
default: '24rpx'
},
cancelBtnClass: {
type: String,
default: ''
}
},
methods: {
handleConfirm() {
this.$emit('confirm')
this.$emit('update:show', false)
},
handleCancel() {
this.$emit('cancel')
this.$emit('update:show', false)
},
closePopup() {
this.$emit('close')
this.$emit('update:show', false)
}
}
}
</script>
<style scoped>
/* 遮罩层 */
.agreement-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
/* 遮罩层:全屏覆盖 */
.agreement-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
/* 弹窗主体 */
.agreement-popup {
width: 60%;
background-color: rgb(42, 42, 42);
border-radius: 40rpx;
padding: 30rpx;
text-align: center;
border: 1px solid rgba(255, 200, 78, 0.3);
}
/* 弹窗主体:基础样式 */
.agreement-popup {
width: 66%;
padding: 30rpx;
text-align: center;
}
.popup-content {
display: flex;
flex-direction: column;
align-items: center;
}
/* 内容区域布局 */
.popup-content {
display: flex;
flex-direction: column;
align-items: center;
}
.text-content {
width: 100%;
}
.text-content {
width: 100%;
}
.popup-Title {
color: rgba(255, 255, 255, 0.86);
text-align: center;
padding: 30rpx 0 10rpx;
font-size: 32rpx;
font-weight: bold;
}
/* 按钮基础样式(不包含可变样式) */
.popup-buttons {
display: flex;
justify-content: center;
}
.popup-Message {
color: rgba(255, 255, 255, 0.7);
text-align: center;
padding: 10rpx 20rpx 30rpx;
font-size: 28rpx;
line-height: 1.5;
}
.btn {
height: 60rpx;
line-height: 60rpx;
padding: 0 30rpx;
min-width: 170rpx;
border: none;
}
/* 图标样式 */
.svg {
width: 72rpx;
height: 60rpx;
margin-bottom: v-bind('iconStyle.marginBottom');
}
/* 按钮组 */
.popup-buttons {
display: flex;
justify-content: center;
margin-top: 20rpx;
}
/* 按钮基础样式 */
.btn {
height: 60rpx;
line-height: 60rpx;
border-radius: 40rpx;
font-size: 24rpx;
margin: 0 10rpx;
padding: 0 30rpx;
min-width: 170rpx;
}
/* 确认按钮 */
.agreeBtn {
background: rgba(187, 230, 0, 1);
color: #232323;
border: none;
}
/* 取消按钮 */
.cancelBtn {
background: transparent;
color: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(255, 255, 255, 0.3);
}
/* 解决按钮默认样式冲突 */
.btn::after {
border: none;
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<picker-view
class="picker-body"
:value="timeIndex"
@change="handleTimeChange"
>
<!-- 分钟列 -->
<picker-view-column>
<view
v-for="min in minutes"
:key="min"
class="item"
:class="{ active: timeIndex[0] === minutes.indexOf(min) }"
>{{ min }}</view>
</picker-view-column>
<!-- 秒数列 -->
<picker-view-column>
<view
v-for="sec in seconds"
:key="sec"
class="item"
:class="{ active: timeIndex[1] === seconds.indexOf(sec) }"
>{{ sec }}</view>
</picker-view-column>
</picker-view>
</template>
<script>
export default {
name: "TimePicker",
props: {
// 初始时间(格式:{ minutes: '02', seconds: '30' }
defaultTime: {
type: Object,
default: () => ({ minutes: '00', seconds: '00' })
}
},
data() {
return {
minutes: Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0')), // 00-59
seconds: Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0')), // 00-59
timeIndex: [0, 0], // 当前选中索引
selectedTime: { minutes: '00', seconds: '00' } // 当前选择的时间
};
},
created() {
// 初始化默认时间
const minIndex = this.minutes.indexOf(this.defaultTime.minutes);
const secIndex = this.seconds.indexOf(this.defaultTime.seconds);
this.timeIndex = [minIndex, secIndex];
this.selectedTime = { ...this.defaultTime };
},
methods: {
// 时间变化时更新选中值
handleTimeChange(e) {
this.timeIndex = e.detail.value;
const [minIdx, secIdx] = this.timeIndex;
this.selectedTime = {
minutes: this.minutes[minIdx],
seconds: this.seconds[secIdx]
};
this.$emit("change", this.selectedTime); // 实时通知父组件
},
// 提供给父组件的方法:获取当前时间
getCurrentTime() {
return this.selectedTime;
}
}
};
</script>
<style scoped>
.picker-body {
height: 180px;
background: #3A3A3A;
border-radius: 10px;
}
.item {
color: rgba(255, 255, 255, 0.7);
text-align: center;
padding: 10px 0;
}
.item.active {
color: #A3FF00; /* 选中项高亮 */
}
</style>

View File

@ -22,9 +22,17 @@
<text v-if="rightText" :style="{ color: rightColor }" @click="handleRightClick">
{{ rightText }}
</text>
<!-- 显示多个图标 -->
<template v-if="rightIcons && rightIcons.length > 0">
<image v-for="(icon, index) in rightIcons" :key="index" :src="icon.src"
@click="handleIconClick(index)" class="pathIMG" :style="{
width: icon.size || '40rpx',
height: icon.size || '40rpx',
marginLeft: index > 0 ? '20rpx' : '0'
}" />
</template>
<!-- 或显示图标 -->
<image v-if="rightIcon" :src="rightIcon" @click="handleRightClick" mode=""
class="pathIMG">
<image v-if="rightIcon" :src="rightIcon" @click="handleRightClick" class="pathIMG">
</image>
</slot>
</view>
@ -60,6 +68,11 @@
rightIconSize: { // 图标大小
type: Number,
default: 24
},
rightIcons: {
type: Array,
default: () => []
// 格式: [{src: '/path/icon1.png'}, {src: '/path/icon2.png'}]
}
},
data() {
@ -76,6 +89,10 @@
},
handleRightClick() {
this.$emit('right-click'); // 触发右侧点击事件
},
// 新增图标点击方法
handleIconClick(index) {
this.$emit('icon-click', index)
}
}
}