Merge pull request 'feature/xinhan-branch' (#2) from feature/xinhan-branch into master
Vercel Deploy / deploy (push) Successful in 1m22s

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-04-04 15:02:58 +08:00
Unverified
2 changed files with 142 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>信函查询</title>
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<style>
:root { --bg: #f7f7f7; --card: #fff; --primary: #1a73e8; --text: #222; font-size: 14px; }
html, body { margin: 0; padding: 0; height: 100%; font-family: Arial, Helvetica, sans-serif; background: var(--bg); color: var(--text); }
.container { max-width: 1000px; margin: 20px auto; padding: 0 12px; }
.card { background: var(--card); border-radius: 8px; padding: 16px; box-shadow: 0 2px 6px rgba(0,0,0,.05); }
h1 { font-size: 20px; margin: 0 0 12px; }
.form-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; margin-bottom: 12px; }
.form-control { width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; }
.btn { padding: 8px 14px; background: var(--primary); color: white; border-radius: 6px; border: none; font-weight: 600; cursor: pointer; }
.table-wrapper { margin-top: 12px; overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 10px 12px; border-bottom: 1px solid #eee; text-align: left; }
th { background: #f6f7f9; }
.loading { text-align: center; color: #666; padding: 20px; }
@media (max-width: 900px) {
.form-row { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}
@media (max-width: 700px) {
.form-row { grid-template-columns: 1fr; }
}
/* 更紧凑的表格在小屏上隐藏部分列,保持可读性,同时允许横向滚动查看完整信息 */
@media (max-width: 600px) {
table thead th:nth-child(4), table tbody td:nth-child(4),
table thead th:nth-child(5), table tbody td:nth-child(5) { display: none; }
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<h1>信函查询</h1>
<div class="form-row">
<div>
<label>收件人</label><br />
<input id="recipientTerm" class="form-control" placeholder="收件人" />
</div>
<div>
<label>编号/关键词</label><br />
<input id="searchTerm" class="form-control" placeholder="内容搜索" />
</div>
<div>
<label>开始日期</label><br />
<input id="dateFrom" type="date" class="form-control" />
</div>
<div>
<label>结束日期</label><br />
<input id="dateTo" type="date" class="form-control" />
</div>
</div>
<button id="searchBtn" class="btn">立即查询</button>
</div>
<div id="searchResults" class="card table-wrapper"></div>
</div>
<script>
const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNoaXhzc3JwaGZneHZxcWlna3pvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ2OTE0OTEsImV4cCI6MjA5MDI2NzQ5MX0.Az_Ew2J2zdOMcSV0UNAjBS-LPqGpqhsaN4IyZ5R7iqU';
const sb = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
async function handleSearch(){
const recipientTerm = document.getElementById('recipientTerm').value.trim();
const contentTerm = document.getElementById('searchTerm').value.trim();
const from = document.getElementById('dateFrom').value;
const to = document.getElementById('dateTo').value;
const out = document.getElementById('searchResults');
out.innerHTML = '<div class="loading">正在查询...</div>';
let q = sb.from('xinhan').select('*');
if (recipientTerm) q = q.ilike('recipient', `%${recipientTerm}%`);
if (contentTerm) q = q.ilike('content', `%${contentTerm}%`);
if (from) q = q.gte('sent_date', from);
if (to) q = q.lte('sent_date', to);
const { data, error } = await q.order('sent_date', { ascending: false });
if (error){ out.innerHTML = `<div class="loading" style="color:red">查询失败:${error.message}</div>`; return; }
renderResults(data || []);
}
function renderResults(rows){
const c = document.getElementById('searchResults');
if (!rows.length){ c.innerHTML = '<div class="loading">未找到符合条件的信函</div>'; return; }
let html = '<div class="table-wrapper"><table><thead><tr><th>ID</th><th>收件人</th><th>寄达地</th><th>寄出日期</th><th>寄达日期</th><th>内容</th></tr></thead><tbody>';
for (const r of rows){
html += `<tr><td>${r.id}</td><td>${r.recipient||''}</td><td>${r.destination||''}</td><td>${r.sent_date||''}</td><td>${r.arrival_date||''}</td><td>${(r.content||'').slice(0,60)}${(r.content||'').length>60?'…':''}</td></tr>`;
}
html += '</tbody></table></div>';
c.innerHTML = html;
}
document.getElementById('searchBtn').addEventListener('click', handleSearch);
</script>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
# Xinhan 数据表结构说明
本文档提供针对 xinhan 表的 SQL 创建语句与示例查询。注意:以下 SQL 仅用于创建结构;本任务仅生成 MD 文档,不执行 SQL。
## 数据字段与含义
- recipient: 收件人,为文本类型,必填
- content: 内容物,文本型,可包含多行描述
- sent_date: 寄出日期,时间戳(timestamptz/ TIMESTAMP),必填
- destination: 寄达地,文本
- arrival_date: 寄达日期,时间戳
## 建表 SQLPostgreSQLSupabase/ Postgres 兼容)
```sql
CREATE TABLE xinhan (
id SERIAL PRIMARY KEY,
recipient TEXT NOT NULL,
content TEXT,
sent_date TIMESTAMP WITHOUT TIME ZONE NOT NULL,
destination TEXT,
arrival_date TIMESTAMP WITHOUT TIME ZONE
);
-- 索引,提升按收件人、寄出日期/寄达日期的查询性能
CREATE INDEX IF NOT EXISTS idx_xinhan_recipient ON xinhan (recipient);
CREATE INDEX IF NOT EXISTS idx_xinhan_sent_date ON xinhan (sent_date);
CREATE INDEX IF NOT EXISTS idx_xinhan_arrival_date ON xinhan (arrival_date);
```
## 示例查询
```sql
-- 查询某个收件人相关信函的简单示例
SELECT * FROM xinhan
WHERE recipient ILIKE '%张三%'
ORDER BY sent_date DESC
LIMIT 100;
-- 根据日期范围查询示例
SELECT * FROM xinhan
WHERE sent_date BETWEEN '2024-01-01' AND '2026-12-31'
ORDER BY sent_date DESC;
```
> 说明:此文件仅用于记录数据库结构与查询示例,实际部署请在你的数据库实例中执行上述 SQL。