节点表单内支持快捷新建参与人成员(批 29)
This commit is contained in:
@@ -1321,6 +1321,15 @@ video.video-thumb.video-thumb-mini {
|
||||
.member-pick-avatar {
|
||||
width: 22px; height: 22px; border-radius: 50%; object-fit: cover; display: block;
|
||||
}
|
||||
/* 快捷新建成员(批 29):参与人勾选区下的一行「名字输入 + 新建」 */
|
||||
.member-quickadd {
|
||||
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
||||
margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border);
|
||||
}
|
||||
.member-quickadd input[type="text"] { flex: 1 1 200px; min-width: 0; }
|
||||
.member-quickadd-msg { font-size: 12.5px; }
|
||||
.member-quickadd-msg.is-ok { color: var(--ok, #1a7f37); }
|
||||
.member-quickadd-msg.is-err { color: var(--danger, #c62828); }
|
||||
/* 联想选中后回填的详细地址(让人看见记下来的是什么) */
|
||||
.loc-detail { margin-top: 6px; font-size: 12.5px; word-break: break-all; }
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ $map = [
|
||||
'users/index' => [UserController::class, 'index'],
|
||||
'users/create' => [UserController::class, 'create'],
|
||||
'users/store' => [UserController::class, 'store'],
|
||||
'users/quickCreate' => [UserController::class, 'quickCreate'],
|
||||
'users/edit' => [UserController::class, 'edit'],
|
||||
'users/update' => [UserController::class, 'update'],
|
||||
'users/destroy' => [UserController::class, 'destroy'],
|
||||
|
||||
@@ -100,6 +100,46 @@ class UserController
|
||||
redirect('users/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点表单内「快捷新建成员」(批 29):只填名字,建一个 guest 成员,JSON 应答。
|
||||
* 手机号 / 密码 / 头像都不收 —— 需要时去「成员管理」完善。AJAX 专用,不做页面跳转。
|
||||
*/
|
||||
public function quickCreate(): void
|
||||
{
|
||||
$this->requireAdmin();
|
||||
csrf_check();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$db = Database::get();
|
||||
$familyId = Auth::familyId();
|
||||
$name = trim((string)($_POST['name'] ?? ''));
|
||||
|
||||
$fail = static function (int $code, string $error): void {
|
||||
http_response_code($code);
|
||||
echo json_encode(['ok' => false, 'error' => $error], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
};
|
||||
if ($name === '') {
|
||||
$fail(422, '名字不能为空');
|
||||
}
|
||||
if (mb_strlen($name) > 50) {
|
||||
$fail(422, '名字太长(最多 50 字)');
|
||||
}
|
||||
$chk = $db->prepare('SELECT id FROM users WHERE family_id = ? AND name = ? LIMIT 1');
|
||||
$chk->execute([$familyId, $name]);
|
||||
if ($chk->fetch()) {
|
||||
$fail(409, '已有同名成员(直接勾选即可)');
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('INSERT INTO users (family_id, name) VALUES (?, ?)');
|
||||
$stmt->execute([$familyId, $name]);
|
||||
|
||||
echo json_encode(['ok' => true, 'id' => (int)$db->lastInsertId(), 'name' => $name],
|
||||
JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function edit(): void
|
||||
{
|
||||
$id = (int)($_GET['id'] ?? 0);
|
||||
|
||||
@@ -257,6 +257,18 @@ $tripField = [
|
||||
</div>
|
||||
<p class="form-hint">勾选后保存即生效;已选的人重新勾选不会清掉之前记的签到 / 心情。</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php /* 快捷新建成员(批 29):只填名字建一个 guest 成员并自动勾上,不离开表单。
|
||||
想补手机号/头像/角色,去「成员管理」完善。 */ ?>
|
||||
<?php if (\App\Auth::isAdmin()): ?>
|
||||
<div class="member-quickadd" id="member-quickadd"
|
||||
data-url="<?= e(url('users/quickCreate')) ?>" data-csrf="<?= e(csrf_token()) ?>">
|
||||
<input type="text" id="new-member-name" maxlength="50"
|
||||
placeholder="没找到?输入名字直接新建成员" autocomplete="off">
|
||||
<button type="button" class="btn" id="new-member-add">+ 新建并勾选</button>
|
||||
<span class="member-quickadd-msg" id="new-member-msg" aria-live="polite"></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</fieldset>
|
||||
|
||||
<?php
|
||||
@@ -1223,6 +1235,72 @@ $tripField = [
|
||||
restoreDraft(saved);
|
||||
setStatus('已恢复上次没保存成功的内容(照片需要重新选择)。', false);
|
||||
})();
|
||||
|
||||
// ===== 快捷新建成员(批 29):AJAX 建 guest 成员 → 插入已勾选的参与人 =====
|
||||
(function initQuickAdd() {
|
||||
var box = document.getElementById('member-quickadd');
|
||||
if (!box) return;
|
||||
var input = document.getElementById('new-member-name');
|
||||
var btn = document.getElementById('new-member-add');
|
||||
var msg = document.getElementById('new-member-msg');
|
||||
var list = document.querySelector('#member-field .member-pick');
|
||||
if (!input || !btn || !msg || !list) return;
|
||||
|
||||
function say(text, ok) {
|
||||
msg.textContent = text;
|
||||
msg.classList.toggle('is-ok', !!ok);
|
||||
msg.classList.toggle('is-err', !ok);
|
||||
}
|
||||
|
||||
function addOption(name, id) {
|
||||
var label = document.createElement('label');
|
||||
label.className = 'member-pick-item';
|
||||
var cb = document.createElement('input');
|
||||
cb.type = 'checkbox';
|
||||
cb.name = 'members[]';
|
||||
cb.value = String(id);
|
||||
cb.checked = true;
|
||||
label.appendChild(cb);
|
||||
var span = document.createElement('span');
|
||||
span.className = 'member-pick-name';
|
||||
span.textContent = name;
|
||||
label.appendChild(span);
|
||||
list.appendChild(label);
|
||||
}
|
||||
|
||||
function submit() {
|
||||
var name = input.value.replace(/\s+/g, ' ').trim();
|
||||
if (!name) { say('先输入名字', false); input.focus(); return; }
|
||||
btn.disabled = true;
|
||||
say('创建中…', true);
|
||||
var fd = new FormData();
|
||||
fd.append('name', name);
|
||||
fd.append('_csrf', box.dataset.csrf || '');
|
||||
fetch(box.dataset.url, { method: 'POST', body: fd, credentials: 'same-origin' })
|
||||
.then(function (r) {
|
||||
return r.json().then(function (j) { return { status: r.status, j: j }; });
|
||||
})
|
||||
.then(function (res) {
|
||||
if (res.j && res.j.ok) {
|
||||
addOption(res.j.name, res.j.id);
|
||||
input.value = '';
|
||||
say('已创建「' + res.j.name + '」并勾选', true);
|
||||
} else {
|
||||
say((res.j && res.j.error) || ('创建失败(' + res.status + ')'), false);
|
||||
}
|
||||
})
|
||||
.catch(function () { say('网络错误,请重试', false); })
|
||||
.finally(function () {
|
||||
btn.disabled = false;
|
||||
input.focus();
|
||||
});
|
||||
}
|
||||
|
||||
btn.addEventListener('click', submit);
|
||||
input.addEventListener('keydown', function (ev) {
|
||||
if (ev.key === 'Enter') { ev.preventDefault(); submit(); }
|
||||
});
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user