好友
阅读权限20
听众
最后登录1970-1-1
|
最近公司接到客户投诉,说在我们公司停车场停车后缴纳了停车费,可没有提供发票。
根据公司要求要实现扫码开票功能,可停车系统要实现扫码开票,必须缴纳对接服务费一年几百上千元。为了节省下来对接服务费,我结合AI编写UI界面,实现扫码后填写开票信息发送至后端制定邮箱来开票。
采用的PHP+PHPmailer+QQ邮箱发送接收来实现扫码开票
功能介绍:
扫码后进入停车开票助手
填写开票信息及上传缴费截图凭证
提交发送至后端指定财务邮箱
财务邮箱收到邮件后开票发送至缴费者
扫码开票系统.rar
(147.62 KB, 下载次数: 63)
修改send_email.php文件中的*****星号区域
// ================================================================
// 📧 邮件配置 (请修改为您的真实信息)
// ================================================================
$SMTP_CONFIG = [
// QQ 邮箱 SMTP 服务器
'host' => 'smtp.qq.com',
// SMTP 端口 (SSL)
'port' => 465,
// 是否使用 SSL
'secure' => 'ssl',
// 您的 QQ 邮箱账号 (完整地址)
'username' => '***********',
// QQ 邮箱授权码 (不是登录密码!)
'password' => '**********',
// 接收邮件的邮箱 (可以跟发件人相同)
'to_email' => '**********',
// 发件人名称 (显示用)
'from_name' => '************'
];
// ================================================================
[PHP] 纯文本查看 复制代码 <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<title>停车开票助手</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
}
body {
background: #f5f7fc;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24px 16px;
}
.container {
width: 100%;
max-width: 480px;
background: white;
border-radius: 32px;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.06);
padding: 28px 24px 32px;
transition: all 0.2s;
}
h1 {
font-size: 26px;
font-weight: 700;
color: #0b1b33;
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 6px;
}
.subhead {
font-size: 14px;
color: #6b7a8f;
border-left: 3px solid #2a7de1;
padding-left: 14px;
margin-bottom: 28px;
line-height: 1.5;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
font-size: 14px;
font-weight: 600;
color: #1e2b3f;
margin-bottom: 6px;
}
label i {
margin-right: 8px;
color: #2a7de1;
width: 20px;
}
input,
textarea,
select {
width: 100%;
padding: 14px 16px;
border: 1.5px solid #e2e8f0;
border-radius: 16px;
font-size: 15px;
background: #fafcff;
transition: 0.15s;
outline: none;
color: #0b1b33;
}
input:focus,
textarea:focus,
select:focus {
border-color: #2a7de1;
background: white;
box-shadow: 0 0 0 4px rgba(42, 125, 225, 0.12);
}
textarea {
min-height: 80px;
resize: vertical;
}
.file-upload-wrapper {
position: relative;
border: 1.5px dashed #cbd5e1;
border-radius: 16px;
padding: 20px 12px;
text-align: center;
background: #f8fafd;
transition: 0.15s;
cursor: pointer;
}
.file-upload-wrapper:hover {
border-color: #2a7de1;
background: #f0f6ff;
}
.file-upload-wrapper input[type="file"] {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
}
.file-upload-text {
pointer-events: none;
color: #4b5e77;
}
.file-upload-text i {
font-size: 28px;
color: #2a7de1;
display: block;
margin-bottom: 6px;
}
.file-name {
margin-top: 8px;
font-size: 14px;
color: #1f3a6b;
font-weight: 500;
}
.btn-submit {
width: 100%;
background: #1a5bbf;
color: white;
border: none;
border-radius: 40px;
padding: 16px;
font-size: 18px;
font-weight: 700;
margin-top: 10px;
transition: 0.2s;
cursor: pointer;
box-shadow: 0 8px 20px rgba(26, 91, 191, 0.25);
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.btn-submit:active {
transform: scale(0.97);
background: #124a9e;
}
.btn-submit:disabled {
opacity: 0.7;
transform: scale(0.98);
cursor: not-allowed;
}
.hint {
font-size: 13px;
color: #6b7a8f;
margin-top: 18px;
display: flex;
align-items: center;
gap: 6px;
background: #f0f5fe;
padding: 12px 16px;
border-radius: 40px;
}
.toast-message {
background: #0b1b33;
color: white;
padding: 12px 24px;
border-radius: 40px;
font-weight: 500;
font-size: 15px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
max-width: 90%;
width: auto;
text-align: center;
z-index: 999;
transition: 0.3s;
opacity: 0;
pointer-events: none;
}
.toast-message.show {
opacity: 1;
pointer-events: auto;
}
[url=home.php?mod=space&uid=945662]@media[/url] (max-width: 420px) {
.container {
padding: 20px 16px;
}
}
</style>
</head>
<body>
<div class="container">
<h1><i class="fas fa-receipt" style="color:#2a7de1;"></i> 停车开票助手</h1>
<div class="subhead">填写开票信息 · 上传凭证 · 选择接收方式</div>
<form id="invoiceForm" autocomplete="off">
<div class="form-group">
<label><i class="fas fa-building"></i> 单位名称</label>
<input type="text" id="companyName" placeholder="请输入开票单位全称" required>
</div>
<div class="form-group">
<label><i class="fas fa-id-card"></i> 税号 / 统一社会信用代码</label>
<input type="text" id="taxId" placeholder="如 91330100MA27X..." required>
</div>
<div class="form-group">
<label><i class="fas fa-map-pin"></i> 注册地址 & 电话</label>
<input type="text" id="addressPhone" placeholder="地址, 电话 (选填)">
</div>
<div class="form-group">
<label><i class="fas fa-university"></i> 开户行 & 账号</label>
<input type="text" id="bankAccount" placeholder="开户行, 银行账号 (选填)">
</div>
<div class="form-group">
<label><i class="fas fa-paperclip"></i> 上传支付凭证截图</label>
<div class="file-upload-wrapper">
<div class="file-upload-text">
<i class="fas fa-cloud-upload-alt"></i>
<span>点击上传 或 拍照</span>
<div style="font-size: 12px; color: #6b7a8f; margin-top: 4px;">支持 jpg, png, pdf</div>
</div>
<input type="file" id="paymentFile" accept=".jpg,.jpeg,.png,.pdf">
<div id="fileNameDisplay" class="file-name" style="display:none;"></div>
</div>
</div>
<div class="form-group">
<label><i class="fas fa-share-alt"></i> 发票接收方式</label>
<select id="deliveryMethod">
<option value="email">📧 邮箱</option>
<option value="wechat">💬 微信</option>
<option value="qq">🐧 QQ</option>
</select>
</div>
<div class="form-group">
<label><i class="fas fa-at"></i> 接收账号</label>
<input type="text" id="deliveryAccount" placeholder="邮箱 / 微信号 / QQ号" required>
</div>
<button type="submit" class="btn-submit"><i class="fas fa-paper-plane"></i> 提交 · 发送到开票邮箱</button>
</form>
<div class="hint">
<i class="fas fa-info-circle" style="color:#2a7de1;"></i>
提交后信息将自动发送到开票邮箱
</div>
</div>
<div id="toast" class="toast-message">✔️ 已提交</div>
<script>
(function() {
"use strict";
// ================================================================
// 📧 后端 API 地址 (请修改为您的实际地址)
// ================================================================
const API_URL = 'send_email.php';
// ================================================================
const form = document.getElementById('invoiceForm');
const fileInput = document.getElementById('paymentFile');
const fileNameDisplay = document.getElementById('fileNameDisplay');
const toast = document.getElementById('toast');
let toastTimer = null;
function showToast(msg, isError = false) {
toast.textContent = msg;
toast.classList.add('show');
toast.style.background = isError ? '#b91c1c' : '#0b1b33';
clearTimeout(toastTimer);
toastTimer = setTimeout(() => {
toast.classList.remove('show');
toast.style.background = '#0b1b33';
}, 3200);
}
fileInput.addEventListener('change', function() {
if (this.files && this.files.length > 0) {
const name = this.files[0].name;
fileNameDisplay.textContent = '📎 ' + name;
fileNameDisplay.style.display = 'block';
} else {
fileNameDisplay.style.display = 'none';
}
});
// ---------- 发送到后端 API ----------
function sendToBackend(data) {
return new Promise((resolve, reject) => {
// 使用 FormData 支持文件上传
const formData = new FormData();
formData.append('company', data.company);
formData.append('taxId', data.taxId);
formData.append('addressPhone', data.addressPhone || '');
formData.append('bankAccount', data.bankAccount || '');
formData.append('fileInfo', data.fileInfo);
formData.append('deliveryMethod', data.deliveryMethod);
formData.append('deliveryAccount', data.deliveryAccount);
// 如果有文件,添加到 FormData
if (data.file) {
formData.append('paymentFile', data.file);
}
fetch(API_URL, {
method: 'POST',
body: formData,
// 不要设置 Content-Type,让浏览器自动设置
})
.then(response => response.json())
.then(result => {
if (result.success) {
resolve(result);
} else {
reject(new Error(result.message || '发送失败'));
}
})
.catch(error => {
reject(new Error('网络请求失败: ' + error.message));
});
});
}
// ---------- 表单提交 ----------
form.addEventListener('submit', function(e) {
e.preventDefault();
const company = document.getElementById('companyName').value.trim();
const taxId = document.getElementById('taxId').value.trim();
const addressPhone = document.getElementById('addressPhone').value.trim();
const bankAccount = document.getElementById('bankAccount').value.trim();
const deliveryMethod = document.getElementById('deliveryMethod').value;
const deliveryAccount = document.getElementById('deliveryAccount').value.trim();
if (!company || !taxId || !deliveryAccount) {
showToast('请填写完整信息 (单位/税号/接收账号)', true);
return;
}
let fileInfo = '未上传';
let file = null;
if (fileInput.files && fileInput.files.length > 0) {
file = fileInput.files[0];
fileInfo = file.name + ' (' + (file.size / 1024).toFixed(1) + ' KB)';
}
const data = {
company,
taxId,
addressPhone,
bankAccount,
fileInfo,
file,
deliveryMethod,
deliveryAccount
};
const sendBtn = form.querySelector('.btn-submit');
const originalText = sendBtn.innerHTML;
sendBtn.innerHTML = '<i class="fas fa-spinner fa-pulse"></i> 发送中...';
sendBtn.disabled = true;
sendToBackend(data)
.then(result => {
console.log('✅ 邮件发送成功:', result);
showToast(`✅ 已成功发送至 ${result.to || '预设邮箱'}`);
// 清空文件选择
fileInput.value = '';
fileNameDisplay.style.display = 'none';
// 可选: 清空其他字段
// document.getElementById('companyName').value = '';
// document.getElementById('taxId').value = '';
// document.getElementById('deliveryAccount').value = '';
})
.catch(error => {
console.error('❌ 邮件发送失败:', error);
showToast('❌ ' + error.message, true);
})
.finally(() => {
sendBtn.innerHTML = originalText;
sendBtn.disabled = false;
});
});
})();
</script>
</body>
</html> |
免费评分
-
查看全部评分
|