anon-ui/src/pages/sending/index.vue
2025-03-10 13:49:32 +08:00

924 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 顶部通知栏 -->
<view class='tui-notice-board' v-if="showNotice">
<view class="tui-icon-bg">
<tui-icon name="news-fill" :size='24' color='#f54f46'></tui-icon>
</view>
<view class="tui-scorll-view" @tap='detail'>
<view class="tui-notice" :class="[animation ? 'tui-animation' : '']">B站10分日本动漫已消失9.9分仅剩12部这一部动漫包揽三席</view>
</view>
</view>
<!-- 主要内容 -->
<view class="main-content">
<!-- 填写信息部分 -->
<view class="info-section">
<view class="page-header">
<text class="page-title">填写信息</text>
</view>
<view class="form-container">
<!-- 手机号输入 -->
<view class="form-item">
<view class="input-container">
<input
class="form-input"
type="number"
v-model="phoneNumber"
placeholder="请输入对方手机号"
placeholder-class="placeholder-style"
/>
</view>
</view>
<!-- 日期时间选择 -->
<view class="form-item">
<view class="input-container date-container" @tap="showDatePicker">
<view class="date-icon">
<image src="../../assets/time-32.svg" mode="aspectFit" class="icon-calendar"></image>
</view>
<text class="date-text">{{ selectedDate || '选择日期时间' }}</text>
</view>
</view>
<!-- 日期提示信息 -->
<view class="tip-container">
<view class="tip-icon">
<image src="../../assets/waring-32.svg" mode="aspectFit" class="icon-info"></image>
</view>
<view class="tip-text-wrapper">
<text class="tip-text">如果选择时间我们将在指定时间为您送达(节假日高峰可能存在延迟)不选择时间将立即发送</text>
</view>
</view>
</view>
</view>
<!-- 编辑短信部分 -->
<view class="edit-section">
<view class="page-header">
<view class="title-price-section">
<view class="title-section">
<text class="page-title">编辑短信</text>
<text class="price-info">(短信发送价格: 3.99/)</text>
</view>
<!-- 模板按钮 -->
<view class="template-button-container">
<button class="template-button" hover-class="button-hover" @tap="useTemplate">使用内置文案</button>
</view>
</view>
</view>
<view class="form-container">
<!-- 文本输入区 -->
<view class="textarea-container">
<!-- 添加图标 -->
<view class="textarea-icon">
<image src="../../assets/staples.svg" mode="aspectFit" class="icon-message"></image>
</view>
<!-- 文本区域 -->
<textarea
class="message-textarea"
v-model="messageContent"
placeholder="点击输入要传达的内容(表白、早晚安、祝福等~"
placeholder-class="textarea-placeholder"
maxlength="500"
auto-height
></textarea>
<!-- 字数统计和预览按钮 - 更改为非绝对定位 -->
<view class="actions-row">
<view class="character-count">
<text class="count-text">{{ messageContent.length }}/</text>
<text class="count-limit">按照20个字一条计算{{ calculateMessageCost() }}</text>
</view>
<view class="preview-button-container">
<button class="preview-button" @tap="previewMessage">预览短信</button>
</view>
</view>
</view>
</view>
</view>
<!-- 发送按钮 -->
<view class="send-button-container">
<button class="send-button" @tap="sendMessage">
<text class="send-icon"></text>
<text class="send-text">发送</text>
</button>
</view>
</view>
<!-- 日期选择器弹窗 -->
<view class="date-picker-popup" v-if="showDatePickerPopup">
<view class="date-picker-mask" @tap="hideDatePicker"></view>
<view class="date-picker-content">
<view class="date-picker-header">
<text class="picker-title">选择发送时间</text>
<text class="picker-close" @tap="hideDatePicker">×</text>
</view>
<picker-view
class="date-picker"
:value="dateTimeValue"
@change="onDateTimeChange"
>
<picker-view-column>
<view class="picker-item" v-for="(date, index) in dateOptions" :key="'date-'+index">{{ date }}</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(hour, index) in hourOptions" :key="'hour-'+index">{{ hour }}</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(minute, index) in minuteOptions" :key="'minute-'+index">{{ minute }}</view>
</picker-view-column>
</picker-view>
<view class="date-picker-footer">
<button class="picker-confirm" @tap="confirmDatePicker">确认</button>
</view>
</view>
</view>
<!-- 预览短信弹窗 -->
<view class="preview-popup" v-if="showPreviewPopup">
<view class="preview-mask" @tap="hidePreview"></view>
<view class="preview-content">
<view class="preview-header">
<text class="preview-title">短信预览</text>
<text class="preview-close" @tap="hidePreview">×</text>
</view>
<view class="preview-message">
<view class="message-bubble">
<text class="message-text">{{ messageContent || '暂无内容' }}</text>
</view>
<text class="receiver-info">发送至: {{ formatPhone(phoneNumber) }}</text>
<text class="time-info" v-if="selectedDate">发送时间: {{ selectedDate }}</text>
</view>
<view class="preview-footer">
<button class="preview-confirm" @tap="hidePreview">确认</button>
</view>
</view>
</view>
<!-- 模板选择弹窗 -->
<view class="template-popup" v-if="showTemplatePopup">
<view class="template-mask" @tap="hideTemplate"></view>
<view class="template-content">
<view class="template-header">
<text class="template-title">选择模板</text>
<text class="template-close" @tap="hideTemplate">×</text>
</view>
<scroll-view class="template-list" scroll-y>
<view
class="template-item"
v-for="(template, index) in messageTemplates"
:key="index"
@tap="selectTemplate(template)"
>
<text class="template-preview">{{ template.content }}</text>
<text class="template-type">{{ template.type }}</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
// 动画控制
const animation = ref<boolean>(false);
const showNotice = ref<boolean>(true);
// 表单数据
const phoneNumber = ref<string>('');
const messageContent = ref<string>('');
const selectedDate = ref<string>('');
// 日期选择器
const showDatePickerPopup = ref<boolean>(false);
const dateTimeValue = ref<number[]>([0, 0, 0]); // 默认选中第一项
const dateOptions = ref<string[]>([]);
const hourOptions = ref<string[]>([]);
const minuteOptions = ref<string[]>([]);
// 预览弹窗
const showPreviewPopup = ref<boolean>(false);
// 模板选择弹窗
const showTemplatePopup = ref<boolean>(false);
const messageTemplates = ref([
{ type: '表白', content: '我很喜欢你,可以和你交往吗?' },
{ type: '道歉', content: '对不起,是我考虑不周,希望你能原谅我。' },
{ type: '祝福', content: '祝你生日快乐,愿所有的幸福都围绕在你身边!' },
{ type: '问候', content: '早安,愿你今天心情愉快,万事顺利!' },
{ type: '思念', content: '不知不觉已经很久没见了,很想念你。' }
]);
// 初始化日期数据
const initDateOptions = () => {
// 生成未来7天的日期选项
const today = new Date();
dateOptions.value = Array.from({ length: 7 }, (_, i) => {
const date = new Date(today);
date.setDate(today.getDate() + i);
return `${date.getMonth() + 1}${date.getDate()}`;
});
// 生成小时选项
hourOptions.value = Array.from({ length: 24 }, (_, i) => {
return `${String(i).padStart(2, '0')}`;
});
// 生成分钟选项
minuteOptions.value = Array.from({ length: 60 }, (_, i) => {
return `${String(i).padStart(2, '0')}`;
});
};
// 显示日期选择器
const showDatePicker = () => {
showDatePickerPopup.value = true;
};
// 隐藏日期选择器
const hideDatePicker = () => {
showDatePickerPopup.value = false;
};
// 日期时间选择变化
const onDateTimeChange = (e:any) => {
dateTimeValue.value = e.detail.value;
};
// 确认日期选择
const confirmDatePicker = () => {
const [dateIndex, hourIndex, minuteIndex] = dateTimeValue.value;
selectedDate.value = `${dateOptions.value[dateIndex]} ${hourOptions.value[hourIndex]}${minuteOptions.value[minuteIndex]}`;
hideDatePicker();
};
// 计算短信费用
const calculateMessageCost = () => {
const messageLength = messageContent.value.length;
if (messageLength === 0) return 0;
const messageCount = Math.ceil(messageLength / 20);
return (messageCount * 3.99).toFixed(2);
};
// 格式化手机号显示
const formatPhone = (phone:string) => {
if (!phone || phone.length !== 11) return phone;
return `${phone.substring(0, 3)}****${phone.substring(7)}`;
};
// 预览短信
const previewMessage = () => {
if (!messageContent.value.trim()) {
// 提示用户输入内容
uni.showToast({
title: '请先输入短信内容',
icon: 'none'
});
return;
}
showPreviewPopup.value = true;
};
// 隐藏预览
const hidePreview = () => {
showPreviewPopup.value = false;
};
// 显示模板选择
const useTemplate = () => {
showTemplatePopup.value = true;
};
// 隐藏模板选择
const hideTemplate = () => {
showTemplatePopup.value = false;
};
// 选择模板
const selectTemplate = (template:any) => {
messageContent.value = template.content;
hideTemplate();
};
// 发送短信
const sendMessage = () => {
if (!phoneNumber.value) {
uni.showToast({
title: '请输入对方手机号',
icon: 'none'
});
return;
}
if (!messageContent.value.trim()) {
uni.showToast({
title: '请输入短信内容',
icon: 'none'
});
return;
}
// 这里是发送操作实际项目中应调用API
uni.showLoading({
title: '发送中...'
});
// 模拟发送过程
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: '发送成功',
icon: 'success'
});
// 重置表单
phoneNumber.value = '';
messageContent.value = '';
selectedDate.value = '';
}, 1500);
};
// 详情页跳转
const detail = () => {
uni.navigateTo({
url: '/pages/news/detail'
});
};
// 生命周期
onMounted(() => {
initDateOptions();
// 启动滚动动画
setTimeout(() => {
animation.value = true;
}, 600);
});
</script>
<style>
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
background-color: #f7f7f7;
position: relative;
}
/* 通知栏样式 */
.tui-notice-board {
width: 100%;
padding-right: 30rpx;
box-sizing: border-box;
font-size: 28rpx;
height: 60rpx;
background: #fff8d5;
display: flex;
align-items: center;
position: relative;
z-index: 10;
}
.tui-icon-bg {
background: #fff8d5;
padding-left: 30rpx;
position: relative;
z-index: 10;
}
.tui-scorll-view {
flex: 1;
line-height: 1;
white-space: nowrap;
overflow: hidden;
color: #f54f46;
}
.tui-notice {
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
transform: translate3d(100%, 0, 0);
}
.tui-animation {
-webkit-animation: tui-rolling 12s linear infinite;
animation: tui-rolling 12s linear infinite;
}
@keyframes tui-rolling {
0% {
transform: translate3d(100%, 0, 0);
}
100% {
transform: translate3d(-170%, 0, 0);
}
}
/* 主内容区域 */
.main-content {
flex: 1;
padding: 20rpx 30rpx;
}
/* 信息和编辑部分 */
.info-section, .edit-section {
margin-bottom: 30rpx;
}
/* 页面标题 */
.page-header {
padding: 20rpx 0 30rpx;
}
/* 模板按钮 */
.title-price-section {
display: flex;
justify-content: space-between;
align-items: center;
}
.title-section {
flex: 1;
}
.page-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx; /* 添加底部间距 */
}
.price-info {
font-size: 24rpx;
color: #999;
display: block; /* 使其成为块级元素 */
}
/* 表单样式 */
.form-container {
background-color: #fff;
border-radius: 20rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
margin-bottom: 20rpx;
}
.form-item {
margin-bottom: 20rpx;
}
.input-container {
border: 1px solid #e0e0e0;
border-radius: 35rpx;
padding: 18rpx 30rpx;
background-color: #fff;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
}
.form-input {
height: 46rpx;
width: 100%;
font-size: 30rpx;
color: #333;
}
.placeholder-style {
color: #bdbdbd;
font-size: 30rpx;
}
/* 日期选择器 */
.date-container {
display: flex;
align-items: center;
min-height: 46rpx; /* 与输入框高度一致 */
height: 100%;
}
.date-icon {
margin-right: 10rpx;
display: flex;
align-items: center;
height: 100%;
}
.icon-calendar {
width: 32rpx;
height: 32rpx;
}
.date-text {
flex: 1;
font-size: 30rpx;
color: #bdbdbd;
}
/* 提示信息 */
.tip-container {
display: flex;
align-items: flex-start;
margin: 36rpx 15rpx 10rpx;
}
.tip-icon {
margin-right: 5rpx;
}
.icon-info {
width: 32rpx;
height: 32rpx;
}
.tip-text {
font-size: 22rpx;
color: #999;
line-height: 1.5;
}
.tip-text-wrapper {
flex: 1;
display: flex;
align-items: center;
min-height: 16rpx; /* 与图标高度一致 */
}
/* 短信编辑区 */
.message-edit-section {
margin-top: 20rpx;
}
/* 模板按钮 */
.template-button-container {
display: flex;
justify-content: flex-end;
align-items: center;
}
.template-button {
background-color: rgba(7, 193, 96, 0.1); /* 微信绿色的浅色背景 */
color: #07c160; /* 微信绿色文字 */
border: none;
border-radius: 10px;
font-size: 14px;
font-weight: 450;
padding: 0;
height: 38px;
width: 120px; /* 减小按钮宽度 */
display: flex;
align-items: center;
justify-content: center;
box-shadow: none; /* 移除阴影 */
}
.template-button::after {
border: none; /* 移除按钮默认边框 */
}
/* 按钮悬停效果 */
.button-hover {
opacity: 0.8;
}
/* 文本输入区 */
.textarea-container {
border: 1px solid #e0e0e0;
border-radius: 20rpx;
padding: 20rpx;
background-color: #fff;
margin-bottom: 10rpx;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
}
.textarea-icon {
position: absolute;
left: 20rpx;
top: 20rpx;
z-index: 10
}
.icon-message {
width: 32rpx;
height: 32rpx;
}
.message-textarea {
width: 100%;
min-height: 200rpx;
font-size: 30rpx;
line-height: 44rpx; /* 设置行高与背景线条匹配 */
}
.textarea-placeholder {
color: #bdbdbd;
font-size: 30rpx;
}
.actions-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
}
/* 字数统计 */
.character-count {
font-size: 26rpx;
color: #999;
}
.count-text {
font-size: 26rpx;
color: #333;
}
.count-limit {
font-size: 26rpx;
color: #999;
}
/* 预览按钮 */
.preview-button-container {
padding-right: 10rpx;
}
.preview-button {
background-color: #f2f2f2;
color: #666;
font-size: 26rpx;
padding: 10rpx 30rpx;
border-radius: 30rpx;
border: none;
line-height: 1;
}
/* 发送按钮 */
.send-button-container {
margin-top: 50rpx;
padding: 0 30rpx;
}
.send-button {
background-color: #7ed321;
color: #fff;
font-size: 32rpx;
border-radius: 40rpx;
border: none;
padding: 20rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
.send-icon {
margin-right: 10rpx;
}
/* 日期选择器弹窗 */
.date-picker-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
}
.date-picker-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.date-picker-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
overflow: hidden;
}
.date-picker-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.picker-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.picker-close {
font-size: 40rpx;
color: #999;
}
.date-picker {
height: 400rpx;
width: 100%;
}
.picker-item {
line-height: 80rpx;
text-align: center;
font-size: 32rpx;
}
.date-picker-footer {
padding: 20rpx 30rpx;
border-top: 1px solid #f0f0f0;
}
.picker-confirm {
background-color: #7ed321;
color: #fff;
font-size: 32rpx;
border-radius: 40rpx;
border: none;
padding: 10rpx 0;
}
/* 预览短信弹窗 */
.preview-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
}
.preview-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.preview-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.preview-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.preview-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.preview-close {
font-size: 40rpx;
color: #999;
}
.preview-message {
padding: 30rpx;
}
.message-bubble {
background-color: #95ec69;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 20rpx;
}
.message-text {
font-size: 30rpx;
color: #333;
line-height: 1.5;
}
.receiver-info, .time-info {
font-size: 26rpx;
color: #999;
margin-top: 10rpx;
}
.preview-footer {
padding: 20rpx 30rpx;
border-top: 1px solid #f0f0f0;
}
.preview-confirm {
background-color: #7ed321;
color: #fff;
font-size: 32rpx;
border-radius: 40rpx;
border: none;
padding: 10rpx 0;
}
/* 模板选择弹窗 */
.template-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
}
.template-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.template-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
overflow: hidden;
height: 60%;
display: flex;
flex-direction: column;
}
.template-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.template-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.template-close {
font-size: 40rpx;
color: #999;
}
.template-list {
flex: 1;
padding: 10rpx 20rpx;
}
.template-item {
padding: 20rpx;
border-bottom: 1px solid #f0f0f0;
}
.template-preview {
font-size: 28rpx;
color: #333;
line-height: 1.5;
margin-bottom: 10rpx;
display: block;
}
.template-type {
font-size: 24rpx;
color: #999;
display: block;
}
</style>