Simplify visitor QR result page

main
wangqiyang 3 weeks ago
parent 280ca87082
commit 50e6e91231

@ -352,8 +352,8 @@ func renderResultHTML(raw []byte) template.HTML {
for i, record := range records { for i, record := range records {
b.WriteString(renderVisitorCard(record, i+1, len(records))) b.WriteString(renderVisitorCard(record, i+1, len(records)))
} }
b.WriteString(`<details class="field-details"><summary>详细字段</summary>`) b.WriteString(`<details class="field-details"><summary>展开表格</summary>`)
b.WriteString(renderAny(result, "访客记录")) b.WriteString(renderRecordsTable(records))
b.WriteString(`</details>`) b.WriteString(`</details>`)
} else { } else {
b.WriteString(renderAny(result, "访客记录")) b.WriteString(renderAny(result, "访客记录"))
@ -387,34 +387,18 @@ func collectRecords(v any) []map[string]any {
} }
func renderVisitorCard(obj map[string]any, index, total int) string { func renderVisitorCard(obj map[string]any, index, total int) string {
name := firstField(obj, "姓名", "访客姓名")
if name == "" {
name = "访客"
}
gender := firstField(obj, "性别", "性别_dict", "性别_dictText")
title := "访客"
if gender == "男" {
title = "先生"
} else if gender == "女" {
title = "女士"
}
company := firstField(obj, "访客公司", "公司", "单位")
start := firstField(obj, "开始时间", "来访时间") start := firstField(obj, "开始时间", "来访时间")
end := firstField(obj, "结束时间", "离开时间") end := firstField(obj, "结束时间", "离开时间")
reason := firstField(obj, "来访事由_dictText", "来访事由_dict", "来访事由")
host := firstField(obj, "接待人名称", "接待人", "person")
qrText := firstField(obj, "备注", "二维码", "通行码", "访客码", "QRCode", "qrCode", "qr") qrText := firstField(obj, "备注", "二维码", "通行码", "访客码", "QRCode", "qrCode", "qr")
qrSrc, qrErr := qrImageDataURL(qrText) qrSrc, qrErr := qrImageDataURL(qrText)
var b strings.Builder var b strings.Builder
b.WriteString(`<article class="visitor-card">`) b.WriteString(`<article class="visitor-card">`)
b.WriteString(`<div class="card-head"><span>访客</span>`) b.WriteString(`<div class="card-head"><span>访客二维码</span>`)
if total > 1 { if total > 1 {
b.WriteString(`<strong>` + html.EscapeString(fmt.Sprintf("%d / %d", index, total)) + `</strong>`) b.WriteString(`<strong>` + html.EscapeString(fmt.Sprintf("%d / %d", index, total)) + `</strong>`)
} }
b.WriteString(`</div>`) b.WriteString(`</div>`)
b.WriteString(`<div class="welcome"><span>尊敬的</span><b>` + html.EscapeString(name) + `</b><span>` + html.EscapeString(title) + `</span></div>`)
if qrSrc != "" { if qrSrc != "" {
b.WriteString(`<div class="qr-wrap"><img class="qr-code" src="` + html.EscapeString(qrSrc) + `" alt="访客二维码"></div>`) b.WriteString(`<div class="qr-wrap"><img class="qr-code" src="` + html.EscapeString(qrSrc) + `" alt="访客二维码"></div>`)
} else { } else {
@ -424,13 +408,9 @@ func renderVisitorCard(obj map[string]any, index, total int) string {
} }
b.WriteString(`<div class="qr-missing">` + html.EscapeString(msg) + `</div>`) b.WriteString(`<div class="qr-missing">` + html.EscapeString(msg) + `</div>`)
} }
b.WriteString(`<div class="qr-tip">进园区时,请出示此二维码</div>`)
b.WriteString(`<div class="company">` + html.EscapeString(firstNonEmpty(company, "-")) + `</div>`)
b.WriteString(`<div class="card-meta">`) b.WriteString(`<div class="card-meta">`)
b.WriteString(renderMetaRow("开始时间", start)) b.WriteString(renderMetaRow("开始时间", start))
b.WriteString(renderMetaRow("结束时间", end)) b.WriteString(renderMetaRow("结束时间", end))
b.WriteString(renderMetaRow("来访事由", reason))
b.WriteString(renderMetaRow("接待人", host))
b.WriteString(`</div></article>`) b.WriteString(`</div></article>`)
return b.String() return b.String()
} }
@ -442,6 +422,35 @@ func renderMetaRow(label, value string) string {
return `<div class="meta-row"><span>` + html.EscapeString(label) + `</span><strong>` + html.EscapeString(value) + `</strong></div>` return `<div class="meta-row"><span>` + html.EscapeString(label) + `</span><strong>` + html.EscapeString(value) + `</strong></div>`
} }
func renderRecordsTable(records []map[string]any) string {
var b strings.Builder
for i, record := range records {
keys := make([]string, 0, len(record))
for k := range record {
keys = append(keys, k)
}
sort.Strings(keys)
if len(records) > 1 {
b.WriteString(`<h3 class="table-title">记录 ` + html.EscapeString(fmt.Sprint(i+1)) + `</h3>`)
}
b.WriteString(`<div class="table-wrap"><table class="detail-table"><tbody>`)
for _, key := range keys {
value := stringify(record[key])
b.WriteString(`<tr><th>` + html.EscapeString(key) + `</th><td>`)
if src, ok := imageSrc(key, value); ok {
b.WriteString(`<img class="result-image" src="` + html.EscapeString(src) + `" alt="` + html.EscapeString(key) + `">`)
b.WriteString(`<div class="image-text">` + html.EscapeString(value) + `</div>`)
} else {
b.WriteString(html.EscapeString(value))
}
b.WriteString(`</td></tr>`)
}
b.WriteString(`</tbody></table></div>`)
}
return b.String()
}
func renderAny(v any, title string) string { func renderAny(v any, title string) string {
switch x := v.(type) { switch x := v.(type) {
case map[string]any: case map[string]any:
@ -721,19 +730,10 @@ var pageTemplate = template.Must(template.New("page").Parse(`<!doctype html>
font-weight: 700; font-weight: 700;
} }
.card-head strong { font-size: 13px; font-weight: 600; } .card-head strong { font-size: 13px; font-weight: 600; }
.welcome {
display: flex;
align-items: baseline;
justify-content: center;
gap: 8px;
padding: 20px 18px 12px;
font-size: 16px;
}
.welcome b { font-size: 22px; }
.qr-wrap { .qr-wrap {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 8px 0 10px; padding: 20px 0 10px;
background: #fff; background: #fff;
} }
.qr-code { .qr-code {
@ -752,22 +752,10 @@ var pageTemplate = template.Must(template.New("page").Parse(`<!doctype html>
line-height: 1.6; line-height: 1.6;
background: #fff7f7; background: #fff7f7;
} }
.qr-tip { .card-meta {
padding: 0 18px 14px; padding: 12px 18px 18px;
color: #8f6f34;
text-align: center;
font-size: 14px;
}
.company {
padding: 14px 18px;
border-top: 1px solid #efe2c8; border-top: 1px solid #efe2c8;
border-bottom: 1px solid #efe2c8;
text-align: center;
font-size: 15px;
line-height: 1.6;
word-break: break-word;
} }
.card-meta { padding: 12px 18px 16px; }
.meta-row { .meta-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -797,6 +785,39 @@ var pageTemplate = template.Must(template.New("page").Parse(`<!doctype html>
font-size: 14px; font-size: 14px;
user-select: none; user-select: none;
} }
.table-title {
margin: 0;
padding: 12px 14px 0;
color: var(--text);
font-size: 15px;
}
.table-wrap {
width: 100%;
overflow-x: auto;
padding: 12px 14px 14px;
}
.detail-table {
width: 100%;
min-width: 520px;
border-collapse: collapse;
table-layout: fixed;
font-size: 14px;
line-height: 1.55;
}
.detail-table th, .detail-table td {
border: 1px solid var(--line);
padding: 10px 12px;
vertical-align: top;
white-space: pre-wrap;
word-break: break-word;
}
.detail-table th {
width: 170px;
color: var(--muted);
background: #f8fafc;
font-weight: 500;
text-align: left;
}
.api-message, .empty, .single-value { .api-message, .empty, .single-value {
padding: 14px 16px; padding: 14px 16px;
color: var(--muted); color: var(--muted);
@ -907,7 +928,7 @@ var pageTemplate = template.Must(template.New("page").Parse(`<!doctype html>
{{.ResultHTML}} {{.ResultHTML}}
{{if .RawJSON}}<details class="raw-json"><summary></summary><pre>{{.RawJSON}}</pre></details>{{end}} {{if .RawJSON}}<details class="raw-json"><summary> JSON</summary><pre>{{.RawJSON}}</pre></details>{{end}}
</main> </main>
</body> </body>
</html>`)) </html>`))

Loading…
Cancel
Save