自定义字段

This commit is contained in:
jeremygan2021
2026-03-26 20:15:10 +08:00
parent cc46eb03cd
commit 1b5faf00cc
4 changed files with 926 additions and 86 deletions

View File

@@ -261,26 +261,10 @@
</div>
<form id="paymentForm" onsubmit="handlePayment(event)">
{% set ordered_keys = ['name', 'phone', 'industry_company'] %}
{% for key in ordered_keys %}
{% set field = config.ticket_field_config.get(key) %}
{% if field and field.show %}
<div class="form-group">
<label>{{ field.label }}{% if field.required %} *{% endif %}</label>
{% if key == 'phone' %}
<input type="tel" id="{{ key }}" {% if field.required %}required{% endif %} placeholder="请输入{{ field.label }}" pattern="[0-9]{11}">
{% if config.enable_sms_verification %}
<div style="display: flex; gap: 10px; margin-top: 10px;">
<input type="text" id="verification_code" placeholder="请先发送验证码" style="flex: 1;" disabled>
<button type="button" id="send-code-btn" onclick="sendSmsCode()" style="width: auto; padding: 10px; font-size: 0.9rem; background: var(--secondary-color); margin-top: 0; border: none; border-radius: 8px; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; min-width: 100px;">发送验证码</button>
</div>
{% endif %}
{% else %}
<input type="text" id="{{ key }}" {% if field.required %}required{% endif %} placeholder="请输入{{ field.label }}">
{% endif %}
</div>
{% endif %}
{% endfor %}
<!-- 动态渲染报名字段 -->
<div id="registration_fields">
<!-- Fields will be rendered dynamically by JavaScript -->
</div>
<button type="submit" class="submit-btn" id="submitBtn">
立即支付报名
@@ -306,8 +290,73 @@
</div>
<script>
let pollTimer = null;
let isCodeVerified = false;
// 字段配置(从后端传入)
var ticketFieldConfig = {{ config.ticket_field_config | tojson | safe }};
var enableSmsVerification = {{ 'true' if config.enable_sms_verification else 'false' }};
// 字段渲染顺序(锁定字段优先)
var lockedFields = ['name', 'phone'];
// 页面加载完成后渲染字段
window.addEventListener('DOMContentLoaded', function() {
renderRegistrationFields();
});
function renderRegistrationFields() {
var container = document.getElementById('registration_fields');
if (!container) return;
container.innerHTML = '';
// 定义字段渲染顺序
var orderedKeys = Object.keys(ticketFieldConfig).sort(function(a, b) {
// 锁定字段优先
var aLocked = lockedFields.indexOf(a) !== -1;
var bLocked = lockedFields.indexOf(b) !== -1;
if (aLocked && !bLocked) return -1;
if (!aLocked && bLocked) return 1;
return 0;
});
// 按顺序渲染字段
orderedKeys.forEach(function(key) {
var field = ticketFieldConfig[key];
if (!field || !field.show) return;
var div = document.createElement('div');
div.className = 'form-group';
// 创建标签
var label = document.createElement('label');
label.textContent = field.label + (field.required ? ' *' : '');
// 创建输入框
var inputHtml = '';
if (key === 'phone') {
// 手机号特殊处理
inputHtml = '<input type="tel" id="' + key + '"' + (field.required ? ' required' : '') + ' placeholder="请输入' + field.label + '" pattern="[0-9]{11}">';
if (enableSmsVerification) {
inputHtml += '<div style="display: flex; gap: 10px; margin-top: 10px;">' +
'<input type="text" id="verification_code" placeholder="请先发送验证码" style="flex: 1;" disabled>' +
'<button type="button" id="send-code-btn" onclick="sendSmsCode()" style="width: auto; padding: 10px; font-size: 0.9rem; background: var(--secondary-color); margin-top: 0; border: none; border-radius: 8px; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; min-width: 100px;">发送验证码</button>' +
'</div>';
}
} else {
inputHtml = '<input type="text" id="' + key + '"' + (field.required ? ' required' : '') + ' placeholder="请输入' + field.label + '">';
}
div.appendChild(label);
div.insertAdjacentHTML('beforeend', inputHtml);
container.appendChild(div);
});
// 初始化按钮状态
updateSubmitButtonState();
}
var pollTimer = null;
var isCodeVerified = false;
function updateSubmitButtonState() {
const btn = document.getElementById('submitBtn');
@@ -391,21 +440,30 @@
async function handlePayment(e) {
e.preventDefault();
const btn = document.getElementById('submitBtn');
const msg = document.getElementById('message');
const originalText = "立即支付报名"; // Hardcoded or get from element
var btn = document.getElementById('submitBtn');
var msg = document.getElementById('message');
var originalText = "立即支付报名";
// Validate
const getVal = (id) => {
const el = document.getElementById(id);
// Validate - 收集所有动态字段
var getVal = function(id) {
var el = document.getElementById(id);
return el ? el.value.trim() : '';
};
const name = getVal('name');
const phone = getVal('phone');
if (!name || !phone) {
showMessage('请填写必填项', 'error');
// 验证必填字段
var hasError = false;
Object.keys(ticketFieldConfig).forEach(function(key) {
var field = ticketFieldConfig[key];
if (field && field.required) {
var value = getVal(key);
if (!value) {
hasError = true;
}
}
});
if (hasError) {
showMessage('请填写所有必填项', 'error');
return;
}
@@ -414,16 +472,23 @@
btn.innerHTML = '<span class="loading"></span> 处理中...';
msg.style.display = 'none';
const data = {
name: name,
phone: phone,
verification_code: getVal('verification_code'),
company_name: getVal('industry_company')
// 收集所有字段数据
var data = {
name: getVal('name'),
phone: getVal('phone'),
verification_code: getVal('verification_code')
};
// 添加所有动态字段
Object.keys(ticketFieldConfig).forEach(function(key) {
if (key !== 'name' && key !== 'phone') {
data[key] = getVal(key);
}
});
// Check Screen Width
const isWideScreen = window.innerWidth > 768;
const apiEndpoint = isWideScreen ? '/api/payment/native' : '/api/payment/h5';
var isWideScreen = window.innerWidth > 768;
var apiEndpoint = isWideScreen ? '/api/payment/native' : '/api/payment/h5';
try {
const res = await fetch(apiEndpoint, {