CaiWuXiTong/resources/views/system_settings/partials/workflow-reviewers-script.blade.php

84 lines
4.8 KiB
PHP

@once
@push('scripts_start')
<script>
(() => {
if (window.caiwuWorkflowReviewers) return;
window.caiwuWorkflowReviewers = true;
const people = new Map();
let pending;
async function search(form) {
const input = form.querySelector('[data-reviewer-search]');
const status = form.querySelector('[data-reviewer-search-status]');
const results = form.querySelector('[data-reviewer-results]');
if (!input.value.trim()) { status.textContent = '请输入姓名或花名后查询。'; return; }
pending?.abort();
const controller = new AbortController();
pending = controller;
status.textContent = '正在查询钉钉花名册…';
results.replaceChildren();
const url = new URL(form.dataset.searchUrl);
url.searchParams.set('q', input.value.trim());
try {
const response = await fetch(url, {signal:controller.signal, credentials:'same-origin', headers:{Accept:'application/json'}});
if (!response.ok) throw new Error('unavailable');
const data = await response.json();
people.clear();
for (const person of data.people) {
people.set(person.id, person);
const row = document.createElement('div');
row.className = 'flex flex-wrap items-center justify-between gap-3 border-b border-gray-200 py-3 text-sm';
const name = document.createElement('span');
name.textContent = person.name + (person.account ? ' · 账号:' + person.account : '') + ' · ' + person.reason;
row.append(name);
const actions = document.createElement('div');
actions.className = 'flex gap-3';
for (const [stage, label] of [['first','加入初审'],['final','加入复审']]) {
const button = document.createElement('button');
button.type = 'button'; button.textContent = label;
button.dataset.reviewerAdd = stage; button.dataset.reviewerId = person.id;
button.disabled = !person.selectable;
button.className = person.selectable ? 'settings-accent' : 'text-gray-600 cursor-not-allowed';
actions.append(button);
}
row.append(actions); results.append(row);
}
status.textContent = data.people.length ? '最多显示 12 人,重名请核对对应系统账号;可缩小查询范围。' : '未找到人员,请检查姓名或花名后重试。';
} catch (error) {
if (error.name !== 'AbortError') status.textContent = '钉钉花名册暂时无法查询,请稍后重新点击查询人员。';
}
}
document.addEventListener('click', event => {
const button = event.target.closest('[data-reviewer-search-button], [data-reviewer-add], [data-reviewer-remove]');
const form = button?.closest('[data-reviewers-form]');
if (!form) return;
if (button.hasAttribute('data-reviewer-search-button')) { search(form); return; }
if (button.hasAttribute('data-reviewer-remove')) { button.closest('li').remove(); return; }
const person = people.get(button.dataset.reviewerId);
if (!person?.selectable) return;
const stage = button.dataset.reviewerAdd;
const list = form.querySelector(`[data-reviewer-selected="${stage}"]`);
const selected = [...list.querySelectorAll('input')];
const status = form.querySelector('[data-reviewer-search-status]');
if (selected.some(input => input.value === person.id)) { status.textContent = '该人员已在此环节名单中。'; return; }
if (selected.length >= 10) { status.textContent = '每个环节最多选择 10 人。'; return; }
const row = document.createElement('li');
row.className = 'flex items-center justify-between gap-3 rounded-lg border border-gray-200 px-3 py-2 text-sm';
const input = document.createElement('input');
input.type = 'hidden'; input.name = stage + '[]'; input.value = person.id;
const name = document.createElement('span'); name.textContent = person.name;
const remove = document.createElement('button');
remove.type = 'button'; remove.dataset.reviewerRemove = ''; remove.className = 'settings-accent'; remove.textContent = '移除';
remove.setAttribute('aria-label', '移除' + person.name);
row.append(input, name, remove); list.append(row);
status.textContent = '已加入名单,请保存审核人员。';
});
document.addEventListener('keydown', event => {
if (event.key === 'Enter' && event.target.matches('[data-reviewer-search]')) {
event.preventDefault(); search(event.target.closest('[data-reviewers-form]'));
}
});
})();
</script>
@endpush
@endonce