dm-design/用户端APP/我的订单/order-refund.html

560 lines
16 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>退款申请</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
background-color: #f5f5f5;
padding-bottom: 80px;
}
.header {
background-color: #013820;
color: white;
padding: 15px 20px;
font-size: 18px;
font-weight: bold;
text-align: center;
}
.feed-all {
min-height: 100vh;
}
.group {
background-color: white;
margin: 10px;
border-radius: 8px;
overflow: hidden;
border: 1px solid #e5e5e5;
}
.form-item {
padding: 15px;
border-bottom: 1px solid #f0f0f0;
}
.form-item:last-child {
border-bottom: none;
}
.form-label {
display: block;
color: #333;
font-size: 15px;
margin-bottom: 10px;
font-weight: 500;
}
.form-label.required::before {
content: '*';
color: #ff0000;
margin-right: 4px;
}
.textarea-wrapper {
position: relative;
}
.textarea-field {
width: 100%;
min-height: 120px;
padding: 10px;
border: 1px solid #dcdcdc;
border-radius: 4px;
font-size: 14px;
resize: vertical;
font-family: inherit;
line-height: 1.5;
}
.textarea-field:focus {
outline: none;
border-color: #013820;
}
.textarea-field::placeholder {
color: #999;
}
.word-limit {
text-align: right;
color: #999;
font-size: 12px;
margin-top: 5px;
}
.upload-section {
margin-top: 10px;
}
.upload-wrapper {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.upload-item {
position: relative;
width: 80px;
height: 80px;
border: 1px dashed #dcdcdc;
border-radius: 4px;
overflow: hidden;
}
.upload-item img {
width: 100%;
height: 100%;
object-fit: cover;
background: linear-gradient(135deg, #e0e0e0 0%, #f5f5f5 100%);
}
.upload-preview {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 36px;
}
.upload-item .remove-btn {
position: absolute;
top: -8px;
right: -8px;
width: 20px;
height: 20px;
background-color: #ff0000;
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
line-height: 1;
}
.upload-btn {
width: 80px;
height: 80px;
border: 1px dashed #dcdcdc;
border-radius: 4px;
background-color: #fafafa;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #999;
font-size: 12px;
transition: all 0.3s;
}
.upload-btn:hover {
border-color: #013820;
color: #013820;
}
.upload-btn .icon {
font-size: 24px;
margin-bottom: 5px;
}
.upload-input {
display: none;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 15px 25px;
background-color: white;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
}
.submit-btn {
width: 100%;
padding: 15px;
background-color: #013820;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
}
.submit-btn:hover {
background-color: #025530;
}
.submit-btn:active {
transform: scale(0.98);
}
.error-message {
color: #ff0000;
font-size: 12px;
margin-top: 5px;
}
.toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 15px 25px;
border-radius: 4px;
z-index: 1000;
display: none;
}
.toast.show {
display: block;
animation: fadeIn 0.3s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: none;
align-items: center;
justify-content: center;
z-index: 1000;
}
.loading.show {
display: flex;
}
.loading-content {
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 20px 30px;
border-radius: 8px;
text-align: center;
}
.spinner {
border: 3px solid rgba(255, 255, 255, 0.3);
border-top: 3px solid white;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="header">退款申请</div>
<div class="feed-all">
<form id="refundForm">
<div class="group">
<div class="form-item">
<label class="form-label required">申请理由</label>
<div class="textarea-wrapper">
<textarea
id="reason"
class="textarea-field"
placeholder="请输入申请理由"
maxlength="300"
></textarea>
<div class="word-limit">
<span id="wordCount">0</span>/300
</div>
</div>
<div id="reasonError" class="error-message" style="display: none;">请输入申请理由</div>
</div>
<div class="form-item">
<label class="form-label required">上传凭证</label>
<div class="upload-section">
<div class="upload-wrapper" id="uploadWrapper">
<div class="upload-btn" id="uploadBtn">
<div class="icon">+</div>
<div>上传图片</div>
</div>
</div>
<input
type="file"
id="fileInput"
class="upload-input"
accept="image/*"
multiple
>
</div>
<div id="uploadError" class="error-message" style="display: none;">请上传凭证</div>
</div>
</div>
</form>
</div>
<div class="footer">
<button class="submit-btn" id="submitBtn">提交</button>
</div>
<div id="toast" class="toast"></div>
<div id="loading" class="loading">
<div class="loading-content">
<div class="spinner"></div>
<div>申请中...</div>
</div>
</div>
<script>
// 获取URL参数
function getQueryParam(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
// 订单编号从URL参数获取
const unitOrderNo = getQueryParam('unitOrderNo') || '';
// 文件列表
let fileList = [];
const MAX_FILES = 5;
// DOM元素
const reasonTextarea = document.getElementById('reason');
const wordCountSpan = document.getElementById('wordCount');
const uploadBtn = document.getElementById('uploadBtn');
const fileInput = document.getElementById('fileInput');
const uploadWrapper = document.getElementById('uploadWrapper');
const submitBtn = document.getElementById('submitBtn');
const reasonError = document.getElementById('reasonError');
const uploadError = document.getElementById('uploadError');
const toast = document.getElementById('toast');
const loading = document.getElementById('loading');
// 字数统计
reasonTextarea.addEventListener('input', function() {
const length = this.value.length;
wordCountSpan.textContent = length;
if (length > 0) {
reasonError.style.display = 'none';
}
});
// 点击上传按钮
uploadBtn.addEventListener('click', function() {
if (fileList.length < MAX_FILES) {
fileInput.click();
} else {
showToast('最多只能上传5张图片');
}
});
// 文件选择
fileInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
if (fileList.length + files.length > MAX_FILES) {
showToast(`最多只能上传${MAX_FILES}张图片`);
return;
}
files.forEach(file => {
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = function(event) {
fileList.push({
file: file,
url: event.target.result
});
renderFiles();
uploadError.style.display = 'none';
};
reader.readAsDataURL(file);
}
});
// 清空input以便可以重复选择同一文件
fileInput.value = '';
});
// 渲染文件列表
function renderFiles() {
// 清空现有内容
uploadWrapper.innerHTML = '';
// 渲染已上传的图片
fileList.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'upload-item';
// 使用表情符号作为占位符
const emojis = ['📷', '🖼️', '🎨', '📸', '🌅'];
const emoji = emojis[index % emojis.length];
div.innerHTML = `
<div class="upload-preview">${emoji}</div>
<button class="remove-btn" onclick="removeFile(${index})">×</button>
`;
uploadWrapper.appendChild(div);
});
// 如果未达到上限,显示上传按钮
if (fileList.length < MAX_FILES) {
const uploadBtnClone = document.createElement('div');
uploadBtnClone.className = 'upload-btn';
uploadBtnClone.id = 'uploadBtn';
uploadBtnClone.innerHTML = `
<div class="icon">+</div>
<div>上传图片</div>
`;
uploadBtnClone.addEventListener('click', function() {
fileInput.click();
});
uploadWrapper.appendChild(uploadBtnClone);
}
}
// 删除文件
window.removeFile = function(index) {
fileList.splice(index, 1);
renderFiles();
};
// 显示提示
function showToast(message, duration = 2000) {
toast.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, duration);
}
// 显示加载中
function showLoading() {
loading.classList.add('show');
}
// 隐藏加载中
function hideLoading() {
loading.classList.remove('show');
}
// 表单验证
function validateForm() {
let isValid = true;
// 验证申请理由
if (!reasonTextarea.value.trim()) {
reasonError.style.display = 'block';
isValid = false;
} else {
reasonError.style.display = 'none';
}
// 验证上传凭证
if (fileList.length === 0) {
uploadError.style.display = 'block';
showToast('请上传凭证');
isValid = false;
} else {
uploadError.style.display = 'none';
}
return isValid;
}
// 模拟文件上传到服务器
async function uploadFilesToServer(files) {
// 这里应该是实际的上传逻辑返回文件URL列表
// 现在使用模拟数据
const urls = files.map((item, index) => {
return `https://example.com/uploads/refund_${Date.now()}_${index}.jpg`;
});
return urls;
}
// 提交表单
submitBtn.addEventListener('click', async function() {
if (!validateForm()) {
return;
}
showLoading();
try {
// 模拟上传文件并获取URL
const imageUrls = await uploadFilesToServer(fileList);
// 准备提交数据
const submitData = {
unitOrderNo: unitOrderNo,
reason: reasonTextarea.value.trim(),
img: imageUrls.join(',')
};
console.log('提交数据:', submitData);
// 模拟API请求
// 实际项目中应该调用真实的API接口
await new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟成功
resolve();
// 模拟失败,取消下面的注释
// reject(new Error('提交失败'));
}, 1500);
});
hideLoading();
showToast('申请成功,等待审核中');
// 延迟后返回上一页
setTimeout(() => {
window.history.back();
console.log('返回上一页并刷新订单列表');
}, 1500);
} catch (error) {
hideLoading();
showToast('申请失败,请联系商家');
console.error('提交失败:', error);
}
});
// 页面加载完成
document.addEventListener('DOMContentLoaded', function() {
console.log('页面加载完成,订单编号:', unitOrderNo);
});
</script>
</body>
</html>