Кабинет: поиск клиентов с подсказками, чистая страница документов, ширина настроек
Поиск клиентов (режим сотрудника): - поле поиска вынесено наверх страницы, рядом «Найти» и «Сбросить»; - браузер сам подсказывает выпадающим списком по мере ввода — договоры депозитария отдаются страницей в <datalist> (скриптов в кабинете нет, CSP остаётся строгой), список кэшируется в ядре на 10 минут; - по запросу фильтруются и учётки кабинета, и договоры депозитария, под формой показывается, сколько найдено; - шаблон LIKE экранируется, чтобы % и _ в номере договора означали себя. Документы: убраны пустое табло, «Мои заявки» и форма заказа документа — остался список готовых документов депозитария и пояснение, куда обращаться. Настройка: колонка сетки больше не растягивается широкой таблицей (min-width:0), у страницы пропал горизонтальный ползунок. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
@@ -47,6 +47,19 @@ func fakeBJ(t *testing.T) *httptest.Server {
|
||||
}})
|
||||
}
|
||||
})
|
||||
mux.HandleFunc("/api/lk/admin/clients", func(w http.ResponseWriter, r *http.Request) {
|
||||
if !keyOK(w, r) || r.Header.Get("X-BJ-Session") != "sess-1" {
|
||||
return
|
||||
}
|
||||
search := r.URL.Query().Get("search")
|
||||
clients := []any{map[string]any{"login": "bublikov", "contract_number": "БР-719", "full_name": "Аминов Вячеслав Маркович", "active": true}}
|
||||
depo := []any{map[string]any{"contract": "БР-719 Аминов Вячеслав Маркович", "name": "Аминов Вячеслав Маркович", "securities": 14}}
|
||||
if search != "" && !strings.Contains(strings.ToLower("БР-719 Аминов Вячеслав Маркович"), strings.ToLower(search)) {
|
||||
clients, depo = nil, nil
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"clients": clients, "depo": depo, "search": search,
|
||||
"suggest": []string{"БР-719 Аминов Вячеслав Маркович", "БР-746 Бубликов Иван Петрович"}})
|
||||
})
|
||||
mux.HandleFunc("/api/lk/security", func(w http.ResponseWriter, r *http.Request) {
|
||||
if keyOK(w, r) && r.Header.Get("X-BJ-Session") == "sess-1" {
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"security": map[string]any{
|
||||
@@ -510,3 +523,41 @@ func TestAgentMode(t *testing.T) {
|
||||
t.Fatalf("чужой ключ принят: код %d", rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// Поиск клиентов в режиме сотрудника: подсказки списком и результат под формой.
|
||||
func TestClientsSearch(t *testing.T) {
|
||||
bj := fakeBJ(t)
|
||||
s, err := New(Config{BJURL: bj.URL, BJKey: "lk-key", Title: "Кабинет"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := s.Handler()
|
||||
get := func(path string) string {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
req.AddCookie(&http.Cookie{Name: "bj_lk", Value: "sess-1"})
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("%s: код %d", path, rec.Code)
|
||||
}
|
||||
return rec.Body.String()
|
||||
}
|
||||
page := get("/clients")
|
||||
for _, want := range []string{`list="cl-suggest"`, `<datalist id="cl-suggest">`,
|
||||
`<option value="БР-746 Бубликов Иван Петрович"></option>`, "Найти"} {
|
||||
if !strings.Contains(page, want) {
|
||||
t.Errorf("на странице клиентов нет %q", want)
|
||||
}
|
||||
}
|
||||
found := get("/clients?search=" + url.QueryEscape("Аминов"))
|
||||
if !strings.Contains(found, "найдено: 2") {
|
||||
t.Errorf("не показан итог поиска: %s", found)
|
||||
}
|
||||
if !strings.Contains(found, "БР-719 Аминов Вячеслав Маркович") {
|
||||
t.Error("найденный договор не выведен списком")
|
||||
}
|
||||
empty := get("/clients?search=" + url.QueryEscape("Петров"))
|
||||
if !strings.Contains(empty, "договоров не найдено") {
|
||||
t.Errorf("пустой результат не объяснён: %s", empty)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user