此功能是透過GPT產生架構,調整後的成果
廢言,有了AIGPT後,是增加了程式開發速度,也讓前端不熟的我能做到一些功能….
有需求是某一欄位可以多筆輸入,但DB只有一欄位,要如何呈現,當下想法就是Modal讓這欄位資料在此輸入,確認何用','串起來,存回!
以下是內容
/**
* 動態輸入框模態彈窗 - 動態生成 TEXTBOX
* @param {Object} options - 彈窗的選項
* @param {string} options.title - 彈窗標題
* @param {string} options.okText - 確定按鈕文字
* @param {string} options.cancelText - 取消按鈕文字
* @param {function} options.onOk - 確定按鈕回調函數
* @param {function} options.onCancel - 取消按鈕回調函數
* @param {boolean} options.showOkButton - 是否顯示確定按鈕
* @param {boolean} options.cancelButton - 是否顯示取消按鈕
* @param {string} options.backdrop - 背景設置
* @param {boolean} options.keyboard - 是否允許鍵盤關閉
* @param {Array} options.fields - 用戶自定義欄位
* @param {number} options.fieldCount - 欄位數量
*/
function dynamicInputModal(options) {
const defaults = {
title: '提醒',
okText: '確定',
cancelText: '取消',
onOk: (values) => { console.log(values); },
onCancel: () => { },
showOkButton: true,
cancelButton: true,
backdrop: 'static',
keyboard: false,
fields: [], // 用戶自定義欄位
fieldCount: 5 // 默認欄位數量
};
options = { ...defaults, ...options };
// 生成唯一ID
const modalId = 'alertModal_' + Date.now();
// 根據欄位配置生成動態的輸入框 HTML
let dynamicFieldsHtml = '';
options.fields.forEach((field) => {
const { name, label, defaultValue = '', placeholder, oninput, maxLength, minLength, pattern } = field;
// 設定欄位數量以 `fieldCount` 為主,並填充不足的值
const values = defaultValue ? defaultValue.split(',').map(v => v.trim()).filter(v => v) : [];
const finalFieldCount = Math.max(values.length, options.fieldCount);
// 如果 values 的長度不足 finalFieldCount,則填充空字串
while (values.length < finalFieldCount) {
values.push('');
}
// 生成動態欄位 HTML
//values.forEach((value, idx) => {
// dynamicFieldsHtml += `
// <div class="col-md-6">
// <label>${label || name} ${idx + 1}</label>
// <input type="text"
// class="form-control ${name}-field"
// value="${value.trim()}"
// ${maxLength ? `maxlength="${maxLength}"` : ''}
// ${minLength ? `minlength="${minLength}"` : ''}
// ${pattern ? `pattern="${pattern}"` : ''}
// oninput="validateField(this, '${pattern}', ${minLength}, ${maxLength})">
// ${minLength ? `<small class="form-text text-muted">至少 ${minLength} 個字元</small>` : ''}
// ${maxLength ? `<small class="form-text text-muted">最多 ${maxLength} 個字元</small>` : ''}
// ${pattern ? `<small class="form-text text-muted">必須符合格式: ${pattern}</small>` : ''}
// <div class="invalid-feedback">輸入不符合格式要求</div>
// </div>
//`;
//});
values.forEach((value, idx) => {
dynamicFieldsHtml += `
<div class="col-md-6">
<label>${label || name} ${idx + 1}</label>
<input type="text" placeholder="${placeholder}" maxLength="${maxLength}"
class="form-control ${name}-field"
value="${value.trim()}"
${maxLength ? `maxlength="${maxLength}"` : ''}
${minLength ? `minlength="${minLength}"` : ''}
${pattern ? `pattern="${pattern}"` : ''}
${oninput ? `oninput="${oninput}"` : ''}
>
</div>
`;
});
});
// 生成並顯示彈窗
const html = `
<div class="modal fade" id="${modalId}" data-bs-backdrop="${options.backdrop}" data-bs-keyboard="${options.keyboard}">
<div class="modal-dialog">
<div class="modal-content position-relative">
<div class="position-absolute top-0 end-0 mt-2 me-2 z-1">
<button class="btn-close btn btn-sm btn-circle d-flex flex-center transition-base" type="button" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div class="rounded-top-3 py-3 ps-4 pe-6 bg-200">
<h4 class="mb-0 fw-semi-bold">${options.title}</h4>
</div>
<div class="p-4 pt-3">
<div class="row gx-2 gy-3 mx-0 pb-1 scrollbar" style="max-height: calc(100vh - 235px);margin-left: 0px;">
${dynamicFieldsHtml}
</div>
<div class="d-flex justify-content-end gap-2 mt-3 pt-2">
${options.cancelButton ? `<button type="button" class="btn btn-secondary btnNo">${options.cancelText}</button>` : ''}
${options.showOkButton ? `<button type="button" class="btn btn-primary btnYes">${options.okText}</button>` : ''}
</div>
</div>
</div>
</div>
</div>
</div>
`;
// 添加彈窗 HTML 到頁面中
document.body.insertAdjacentHTML('beforeend', html);
// 獲取模態框元素
const modalElement = document.getElementById(modalId);
modalElement.style.zIndex = '1060';
// 創建新的背景遮罩
const backdrop = document.createElement('div');
backdrop.className = 'modal-backdrop fade show';
backdrop.style.zIndex = '1059';
document.body.appendChild(backdrop);
// 顯示彈窗
const modal = new bootstrap.Modal(modalElement);
modal.show();
// 定義關閉模態框的函數
const closeModal = () => {
modal.hide();
modalElement.addEventListener('hidden.bs.modal', () => {
modalElement.remove();
backdrop.remove();
}, { once: true });
};
// 綁定確定按鈕的點擊事件
if (options.showOkButton) {
modalElement.querySelector('.btnYes').addEventListener('click', () => {
const values = {};
let valid = true; // 驗證標誌
options.fields.forEach(field => {
const inputs = modalElement.querySelectorAll(`.${field.name}-field`);
values[field.name] = Array.from(inputs).map(input => input.value);
inputs.forEach(input => {
// 驗證最小長度
if (field.minLength && input.value.length < field.minLength) {
valid = false;
input.classList.add('is-invalid');
}
// 驗證最大長度
if (field.maxLength && input.value.length > field.maxLength) {
valid = false;
input.classList.add('is-invalid');
}
// 驗證正規表達式
if (field.pattern && !new RegExp(field.pattern).test(input.value)) {
valid = false;
input.classList.add('is-invalid');
}
});
});
// 只有在所有欄位通過驗證後才執行回調
if (valid) {
if (typeof options.onOk === 'function') {
options.onOk(values);
}
closeModal();
}
});
}
// 綁定取消按鈕的點擊事件
if (options.cancelButton) {
modalElement.querySelector('.btnNo').addEventListener('click', () => {
console.log('使用者取消操作');
if (typeof options.onCancel === 'function') {
options.onCancel();
}
closeModal();
});
}
// 綁定關閉按鈕的點擊事件
modalElement.querySelector('.btn-close').addEventListener('click', closeModal);
// 如果 backdrop 設置為 true,點擊背景也關閉模態框
if (options.backdrop !== 'static') {
backdrop.addEventListener('click', closeModal);
}
}
範例:GPT給予的寫法設定有點不符合使用,所以程式內我修改簡易版
dynamicInputModal({
title: '資料填寫',
fieldCount: 5, // 欄位數量,默認為 5
fields: [
{
name: 'username',
label: '用戶名稱',
defaultValue: 'NA1,NA2,NA3',
minLength: 3,
maxLength: 10,
pattern: '^[A-Za-z0-9]+$'
},
{
name: 'macAddress',
label: 'MAC 地址',
defaultValue: '00:1A:2B:3C:4D:5E,00:1A:2B:3C:4D:5F',
pattern: '^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
},
{
name: 'ipAddress',
label: 'IP 地址',
defaultValue: '192.168.0.1,192.168.0.2',
pattern: '^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$'
}
],
onOk: (values) => {
console.log('提交的資料:', values);
},
onCancel: () => {
console.log('使用者取消操作');
}
});
簡易版
我將pattern: '^[A-Za-z0-9]+$' 改成 呼叫oninput 自訂檢核邏輯涵式。
dynamicInputModal({
title: 'MAC',
fieldCount: 5, // 欄位數量,默認為 5
fields: [
{
name: 'macAddress',
label: 'MAC ',
defaultValue: mac,
placeholder: "00:1A:2B:3C:4D:5E",
oninput:"檢查邏輯(this)",
maxLength: 17
// pattern: '^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
},
],
onOk: (values) => {
this.editmodel.mac=values.macAddress.filter(value => value).join(',');
},
onCancel: () => {
console.log('使用者取消操作');
}
});
這樣改,好像可以用,就先這用…用…