Журнал: онлайн-статус «чего ждёт заявка», ссылка из ручного ввода в журнал, правки формы
- livestatus.go: одна фраза состояния для исходящих (сделка M2M + черновик/подача/MS010 поручения 16) и входящих (наше решение → поручение 16/1); признак «в работе» - строки журналов и карточки показывают её и обновляют по /admin/journal/live каждые 8 с, пока заявка в работе; завершённые и отклонённые не опрашиваются - ручной ввод: у отправленного поручения ссылка «в журнале →» и тот же онлайн-статус; вид документа занимает две колонки - выбор участника: по ИНН и коду с кнопки, а не по номеру строки; Enter выбирает только при единственном совпадении Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
.mf-grid label{display:block;font-size:12px;color:var(--muted);margin-bottom:3px}
|
||||
.mf-grid input,.mf-grid select,.mf-grid textarea{width:100%;padding:7px 9px;border-radius:8px;border:1px solid var(--border);background:var(--card);color:var(--text);font-size:13.5px;box-sizing:border-box}
|
||||
.mf-grid .wide{grid-column:1/-1}
|
||||
.mf-grid .w2{grid-column:span 2}
|
||||
@media (max-width:520px){.mf-grid .w2{grid-column:auto}}
|
||||
.mf-h{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:18px 0 8px}
|
||||
.mf-sec{display:grid;grid-template-columns:1.2fr .9fr 2fr .7fr auto;gap:8px;align-items:center;margin-bottom:6px}
|
||||
.mf-sec input{width:100%;padding:7px 9px;border-radius:8px;border:1px solid var(--border);background:var(--card);color:var(--text);font-size:13.5px;box-sizing:border-box}
|
||||
@@ -82,8 +84,8 @@
|
||||
<td>{{.O.FullName}}</td>
|
||||
<td class="num">{{len .O.Securities}}</td>
|
||||
<td>{{if .O.RecvName}}{{.O.RecvName}}{{else}}ИНН {{.O.RecvINN}}{{end}}</td>
|
||||
<td><span class="badge {{if eq .State "done"}}done{{else if or (eq .State "rejected") (eq .State "declined")}}rejected{{else if eq .State "sent"}}awaiting_decision{{else}}draft{{end}}">{{.StateRu}}</span></td>
|
||||
<td><a href="/admin/manual/{{.O.ID}}">открыть →</a></td>
|
||||
<td><span class="badge {{if eq .State "done"}}done{{else if or (eq .State "rejected") (eq .State "declined")}}rejected{{else if eq .State "sent"}}awaiting_decision{{else}}draft{{end}}">{{.StateRu}}</span>{{if .O.DealID}}<div class="live live-wait" data-live="out:{{.O.DealID}}" data-active="1">…</div>{{end}}</td>
|
||||
<td style="white-space:nowrap"><a href="/admin/manual/{{.O.ID}}">открыть →</a>{{if .O.DealID}} · <a href="/admin/claims/{{.O.DealID}}">в журнале →</a>{{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
@@ -317,7 +319,7 @@ function mfRerun(){const f=document.getElementById('mf');if(f&&f.closest('detail
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="mf-grid">
|
||||
<div><label class="mf-req">Вид документа</label>
|
||||
<div class="w2"><label class="mf-req">Вид документа</label>
|
||||
<select name="doc_type">{{$dt := .O.DocType}}{{range .DocTypes}}<option value="{{.Code}}" {{if eq $dt .Code}}selected{{end}}>{{.Code}} — {{.Title}}</option>{{end}}</select></div>
|
||||
<div><label>Серия</label><input name="doc_series" value="{{.O.DocSeries}}" placeholder="4 цифры для паспорта РФ"></div>
|
||||
<div><label class="mf-req">Номер</label><input name="doc_number" value="{{.O.DocNumber}}"></div>
|
||||
@@ -406,14 +408,16 @@ function hbBind(inp,box,list,onPick){
|
||||
const esc=s=>String(s??'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));
|
||||
let hits=[],picked=inp.dataset.picked==='1';
|
||||
const q=()=>picked?'':inp.value;
|
||||
const draw=()=>{hits=hbFind(list,q());box.innerHTML=(hits.length?'<div class="hb-m" style="padding:2px 4px">'+(q().trim()?'Найдено: ':'Все участники: ')+hits.length+'</div>'+hits.map((p,i)=>'<button type="button" class="hb-hit" data-i="'+i+'"><b>'+esc(p.name)+'</b> <span class="hb-m">ИНН '+esc(p.inn)+' · '+esc(p.code)+(p.kind==='broker'?' · брокер':'')+'</span></button>').join(''):'<div class="hb-m" style="padding:6px 2px">В справочнике не найдено — введите ИНН и наименование в поля ниже.</div>');box.classList.add('open')};
|
||||
const draw=()=>{hits=hbFind(list,q());box.innerHTML=(hits.length?'<div class="hb-m" style="padding:2px 4px">'+(q().trim()?'Найдено: ':'Все участники: ')+hits.length+'</div>'+hits.map((p,i)=>'<button type="button" class="hb-hit" data-i="'+i+'" data-inn="'+esc(p.inn)+'" data-code="'+esc(p.code)+'"><b>'+esc(p.name)+'</b> <span class="hb-m">ИНН '+esc(p.inn)+' · '+esc(p.code)+(p.kind==='broker'?' · брокер':'')+'</span></button>').join(''):'<div class="hb-m" style="padding:6px 2px">В справочнике не найдено — введите ИНН и наименование в поля ниже.</div>');box.classList.add('open')};
|
||||
const close=()=>{box.innerHTML='';box.classList.remove('open')};
|
||||
inp.addEventListener('focus',()=>{if(picked)inp.select();draw()});
|
||||
inp.addEventListener('input',()=>{picked=false;draw()});
|
||||
inp.addEventListener('keydown',e=>{if(e.key==='Enter'){e.preventDefault();if(hits[0]){pick(hits[0])}}if(e.key==='Escape')close()});
|
||||
// Enter выбирает только при единственном совпадении: иначе молча ушёл бы первый попавшийся.
|
||||
inp.addEventListener('keydown',e=>{if(e.key==='Enter'){e.preventDefault();if(hits.length===1)pick(hits[0]);else if(hits.length>1){const m=box.querySelector('.hb-m');if(m)m.textContent='Найдено: '+hits.length+' — уточните запрос или выберите мышью'}}if(e.key==='Escape')close()});
|
||||
const pick=p=>{onPick(p);picked=true;close()};
|
||||
box.addEventListener('mousedown',e=>e.preventDefault());
|
||||
box.addEventListener('click',e=>{const b=e.target.closest('.hb-hit');if(b)pick(hits[+b.dataset.i])});
|
||||
// Участник — по ИНН и коду с самой кнопки, а не по номеру строки: список мог перерисоваться между показом и нажатием.
|
||||
box.addEventListener('click',e=>{const b=e.target.closest('.hb-hit');if(!b)return;const p=list.find(x=>String(x.inn)===b.dataset.inn&&String(x.code)===b.dataset.code)||hits[+b.dataset.i];if(p)pick(p)});
|
||||
inp.addEventListener('blur',()=>setTimeout(close,150));
|
||||
const tg=inp.parentNode.querySelector('.hb-toggle');
|
||||
if(tg)tg.addEventListener('click',()=>{if(box.classList.contains('open'))close();else{inp.focus();draw()}});
|
||||
|
||||
Reference in New Issue
Block a user