@@ -2,7 +2,19 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNoaXhzc3JwaGZneHZxcWlna3pvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ2OTE0OTEsImV4cCI6MjA5MDI2NzQ5MX0.Az_Ew2J2zdOMcSV0UNAjBS-LPqGpqhsaN4IyZ5R7iqU';
|
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNoaXhzc3JwaGZneHZxcWlna3pvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ2OTE0OTEsImV4cCI6MjA5MDI2NzQ5MX0.Az_Ew2J2zdOMcSV0UNAjBS-LPqGpqhsaN4IyZ5R7iqU';
|
||||||
const sb = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
const sb = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
||||||
|
|
||||||
|
function escapeHtml(value) {
|
||||||
|
return String(value ?? '').replace(/[&<>"']/g, char => ({
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
"'": '''
|
||||||
|
}[char]));
|
||||||
|
}
|
||||||
|
|
||||||
async function handleSearch() {
|
async function handleSearch() {
|
||||||
|
const selfNumberTerm = document.getElementById('selfNumberTerm').value.trim();
|
||||||
|
const trackingNumberTerm = document.getElementById('trackingNumberTerm').value.trim();
|
||||||
const recipientTerm = document.getElementById('recipientTerm').value.trim();
|
const recipientTerm = document.getElementById('recipientTerm').value.trim();
|
||||||
const contentTerm = document.getElementById('searchTerm').value.trim();
|
const contentTerm = document.getElementById('searchTerm').value.trim();
|
||||||
const from = document.getElementById('dateFrom').value;
|
const from = document.getElementById('dateFrom').value;
|
||||||
@@ -12,6 +24,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
out.innerHTML = '<div class="loading-state">正在连接信函数据库并执行检索...</div>';
|
out.innerHTML = '<div class="loading-state">正在连接信函数据库并执行检索...</div>';
|
||||||
|
|
||||||
let q = sb.from('xinhan').select('*');
|
let q = sb.from('xinhan').select('*');
|
||||||
|
if (selfNumberTerm) q = q.ilike('self_number', `%${selfNumberTerm}%`);
|
||||||
|
if (trackingNumberTerm) q = q.ilike('tracking_number', `%${trackingNumberTerm}%`);
|
||||||
if (recipientTerm) q = q.ilike('recipient', `%${recipientTerm}%`);
|
if (recipientTerm) q = q.ilike('recipient', `%${recipientTerm}%`);
|
||||||
if (contentTerm) q = q.ilike('content', `%${contentTerm}%`);
|
if (contentTerm) q = q.ilike('content', `%${contentTerm}%`);
|
||||||
if (from) q = q.gte('sent_date', from);
|
if (from) q = q.gte('sent_date', from);
|
||||||
@@ -19,7 +33,7 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
|
|
||||||
const { data, error } = await q.order('sent_date', { ascending: false });
|
const { data, error } = await q.order('sent_date', { ascending: false });
|
||||||
if (error) {
|
if (error) {
|
||||||
out.innerHTML = `<div class="error-state">查询失败:${error.message}</div>`;
|
out.innerHTML = `<div class="error-state">查询失败:${escapeHtml(error.message)}</div>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renderResults(data || []);
|
renderResults(data || []);
|
||||||
@@ -38,6 +52,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
<th>自编号</th>
|
||||||
|
<th>快递号</th>
|
||||||
<th>收件人</th>
|
<th>收件人</th>
|
||||||
<th>目的地</th>
|
<th>目的地</th>
|
||||||
<th>寄出日期</th>
|
<th>寄出日期</th>
|
||||||
@@ -51,16 +67,18 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
const content = row.content || '';
|
const content = row.content || '';
|
||||||
const summary = content.length > 60
|
const summary = content.length > 60
|
||||||
? `<span class="text-truncate" title="${content}">${content}</span>`
|
? `<span class="text-truncate" title="${escapeHtml(content)}">${escapeHtml(content)}</span>`
|
||||||
: content;
|
: escapeHtml(content);
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-highlight">${row.id}</td>
|
<td class="table-highlight">${escapeHtml(row.id)}</td>
|
||||||
<td>${row.recipient || ''}</td>
|
<td class="table-highlight">${escapeHtml(row.self_number || '')}</td>
|
||||||
<td>${row.destination || ''}</td>
|
<td>${escapeHtml(row.tracking_number || '')}</td>
|
||||||
<td>${row.sent_date || ''}</td>
|
<td>${escapeHtml(row.recipient || '')}</td>
|
||||||
<td>${row.arrival_date || ''}</td>
|
<td>${escapeHtml(row.destination || '')}</td>
|
||||||
|
<td>${escapeHtml(row.sent_date || '')}</td>
|
||||||
|
<td>${escapeHtml(row.arrival_date || '')}</td>
|
||||||
<td>${summary}</td>
|
<td>${summary}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
@@ -71,3 +89,18 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
||||||
|
|
||||||
|
function applyQueryParams() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const selfNumber =
|
||||||
|
params.get('q') ||
|
||||||
|
params.get('self_number') ||
|
||||||
|
params.get('selfNumber');
|
||||||
|
|
||||||
|
if (!selfNumber) return;
|
||||||
|
|
||||||
|
document.getElementById('selfNumberTerm').value = selfNumber.trim();
|
||||||
|
handleSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
applyQueryParams();
|
||||||
|
|||||||
+12
-4
@@ -19,8 +19,8 @@
|
|||||||
<h1>信函流转查询台</h1>
|
<h1>信函流转查询台</h1>
|
||||||
<p>可按收件人、关键字与寄送时间进行检索,统一展示寄达信息与内容摘要,方便快速确认记录。</p>
|
<p>可按收件人、关键字与寄送时间进行检索,统一展示寄达信息与内容摘要,方便快速确认记录。</p>
|
||||||
<div class="hero-meta">
|
<div class="hero-meta">
|
||||||
<span class="meta-chip">检索字段:收件人 / 内容关键字</span>
|
<span class="meta-chip">检索字段:自编号 / 快递号 / 收件人 / 内容关键字</span>
|
||||||
<span class="meta-chip">输出内容:目的地 / 时间 / 摘要</span>
|
<span class="meta-chip">输出内容:自编号 / 快递号 / 目的地 / 时间 / 摘要</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<aside class="stat-card">
|
<aside class="stat-card">
|
||||||
@@ -41,12 +41,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-grid compact">
|
<div class="search-grid compact">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="selfNumberTerm">自编号</label>
|
||||||
|
<input id="selfNumberTerm" class="tech-input" placeholder="输入自编号">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="trackingNumberTerm">快递号</label>
|
||||||
|
<input id="trackingNumberTerm" class="tech-input" placeholder="输入快递号">
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="recipientTerm">收件人</label>
|
<label class="form-label" for="recipientTerm">收件人</label>
|
||||||
<input id="recipientTerm" class="tech-input" placeholder="输入收件人姓名">
|
<input id="recipientTerm" class="tech-input" placeholder="输入收件人姓名">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="searchTerm">编号 / 关键字</label>
|
<label class="form-label" for="searchTerm">内容关键字</label>
|
||||||
<input id="searchTerm" class="tech-input" placeholder="输入内容关键字">
|
<input id="searchTerm" class="tech-input" placeholder="输入内容关键字">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -78,7 +86,7 @@
|
|||||||
<p>© 2026 BI Intelligent Query Interface</p>
|
<p>© 2026 BI Intelligent Query Interface</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="../js/xinhan-index.js"></script>
|
<script src="../js/xinhan-index.js?v=20260617"></script>
|
||||||
<script src="../js/notice-banner.js"></script>
|
<script src="../js/notice-banner.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleSearch() {
|
async function handleSearch() {
|
||||||
|
const selfNumberTerm = document.getElementById('selfNumberTerm').value.trim();
|
||||||
|
const trackingNumberTerm = document.getElementById('trackingNumberTerm').value.trim();
|
||||||
const recipientTerm = document.getElementById('recipientTerm').value.trim();
|
const recipientTerm = document.getElementById('recipientTerm').value.trim();
|
||||||
const contentTerm = document.getElementById('searchTerm').value.trim();
|
const contentTerm = document.getElementById('searchTerm').value.trim();
|
||||||
const from = document.getElementById('dateFrom').value;
|
const from = document.getElementById('dateFrom').value;
|
||||||
@@ -22,6 +24,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
out.innerHTML = '<div class="loading-state">正在连接信函数据库并执行检索...</div>';
|
out.innerHTML = '<div class="loading-state">正在连接信函数据库并执行检索...</div>';
|
||||||
|
|
||||||
let q = sb.from('xinhan').select('*');
|
let q = sb.from('xinhan').select('*');
|
||||||
|
if (selfNumberTerm) q = q.ilike('self_number', `%${selfNumberTerm}%`);
|
||||||
|
if (trackingNumberTerm) q = q.ilike('tracking_number', `%${trackingNumberTerm}%`);
|
||||||
if (recipientTerm) q = q.ilike('recipient', `%${recipientTerm}%`);
|
if (recipientTerm) q = q.ilike('recipient', `%${recipientTerm}%`);
|
||||||
if (contentTerm) q = q.ilike('content', `%${contentTerm}%`);
|
if (contentTerm) q = q.ilike('content', `%${contentTerm}%`);
|
||||||
if (from) q = q.gte('sent_date', from);
|
if (from) q = q.gte('sent_date', from);
|
||||||
@@ -48,6 +52,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
<th>自编号</th>
|
||||||
|
<th>快递号</th>
|
||||||
<th>收件人</th>
|
<th>收件人</th>
|
||||||
<th>目的地</th>
|
<th>目的地</th>
|
||||||
<th>寄出日期</th>
|
<th>寄出日期</th>
|
||||||
@@ -67,6 +73,8 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
html += `
|
html += `
|
||||||
<tr>
|
<tr>
|
||||||
<td class="table-highlight">${escapeHtml(row.id)}</td>
|
<td class="table-highlight">${escapeHtml(row.id)}</td>
|
||||||
|
<td class="table-highlight">${escapeHtml(row.self_number || '')}</td>
|
||||||
|
<td>${escapeHtml(row.tracking_number || '')}</td>
|
||||||
<td>${escapeHtml(row.recipient || '')}</td>
|
<td>${escapeHtml(row.recipient || '')}</td>
|
||||||
<td>${escapeHtml(row.destination || '')}</td>
|
<td>${escapeHtml(row.destination || '')}</td>
|
||||||
<td>${escapeHtml(row.sent_date || '')}</td>
|
<td>${escapeHtml(row.sent_date || '')}</td>
|
||||||
@@ -81,3 +89,18 @@ const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
||||||
|
|
||||||
|
function applyQueryParams() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const selfNumber =
|
||||||
|
params.get('q') ||
|
||||||
|
params.get('self_number') ||
|
||||||
|
params.get('selfNumber');
|
||||||
|
|
||||||
|
if (!selfNumber) return;
|
||||||
|
|
||||||
|
document.getElementById('selfNumberTerm').value = selfNumber.trim();
|
||||||
|
handleSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
applyQueryParams();
|
||||||
|
|||||||
+2
-2
@@ -6,11 +6,11 @@
|
|||||||
"level": "info",
|
"level": "info",
|
||||||
"badge": "通知",
|
"badge": "通知",
|
||||||
"title": "重要通知",
|
"title": "重要通知",
|
||||||
"message": "2026 年上半年 4 月数据已完成更新。请按需进入相关查询页面查看最新记录。",
|
"message": "2026 年上半年 6 月数据已完成更新。请按需进入相关查询页面查看最新记录。",
|
||||||
"linkText": "查看详情",
|
"linkText": "查看详情",
|
||||||
"url": "notice/index.html",
|
"url": "notice/index.html",
|
||||||
"dismissible": true,
|
"dismissible": true,
|
||||||
"startsAt": "2026-05-01T00:00:00+08:00",
|
"startsAt": "2026-06-22T00:00:00+08:00",
|
||||||
"endsAt": ""
|
"endsAt": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
+12
-4
@@ -19,8 +19,8 @@
|
|||||||
<h1>信函流转查询台</h1>
|
<h1>信函流转查询台</h1>
|
||||||
<p>可按收件人、关键字与寄送时间进行检索,统一展示寄达信息与内容摘要,方便快速确认记录。</p>
|
<p>可按收件人、关键字与寄送时间进行检索,统一展示寄达信息与内容摘要,方便快速确认记录。</p>
|
||||||
<div class="hero-meta">
|
<div class="hero-meta">
|
||||||
<span class="meta-chip">检索字段:收件人 / 内容关键字</span>
|
<span class="meta-chip">检索字段:自编号 / 快递号 / 收件人 / 内容关键字</span>
|
||||||
<span class="meta-chip">输出内容:目的地 / 时间 / 摘要</span>
|
<span class="meta-chip">输出内容:自编号 / 快递号 / 目的地 / 时间 / 摘要</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<aside class="stat-card">
|
<aside class="stat-card">
|
||||||
@@ -41,12 +41,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-grid compact">
|
<div class="search-grid compact">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="selfNumberTerm">自编号</label>
|
||||||
|
<input id="selfNumberTerm" class="tech-input" placeholder="输入自编号">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="trackingNumberTerm">快递号</label>
|
||||||
|
<input id="trackingNumberTerm" class="tech-input" placeholder="输入快递号">
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="recipientTerm">收件人</label>
|
<label class="form-label" for="recipientTerm">收件人</label>
|
||||||
<input id="recipientTerm" class="tech-input" placeholder="输入收件人姓名">
|
<input id="recipientTerm" class="tech-input" placeholder="输入收件人姓名">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="searchTerm">编号 / 关键字</label>
|
<label class="form-label" for="searchTerm">内容关键字</label>
|
||||||
<input id="searchTerm" class="tech-input" placeholder="输入内容关键字">
|
<input id="searchTerm" class="tech-input" placeholder="输入内容关键字">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -78,7 +86,7 @@
|
|||||||
<p>© 2026 BI Intelligent Query Interface</p>
|
<p>© 2026 BI Intelligent Query Interface</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script defer src="../js/xinhan-index.js?v=20260614"></script>
|
<script defer src="../js/xinhan-index.js?v=20260617"></script>
|
||||||
<script defer src="../js/notice-banner.js?v=20260614"></script>
|
<script defer src="../js/notice-banner.js?v=20260614"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+13
-1
@@ -3,6 +3,8 @@
|
|||||||
本文档提供针对 xinhan 表的 SQL 创建语句与示例查询。注意:以下 SQL 仅用于创建结构;本任务仅生成 MD 文档,不执行 SQL。
|
本文档提供针对 xinhan 表的 SQL 创建语句与示例查询。注意:以下 SQL 仅用于创建结构;本任务仅生成 MD 文档,不执行 SQL。
|
||||||
|
|
||||||
## 数据字段与含义
|
## 数据字段与含义
|
||||||
|
- self_number: 自编号,文本类型,用于内部检索
|
||||||
|
- tracking_number: 快递号,文本类型,用于记录物流单号
|
||||||
- recipient: 收件人,为文本类型,必填
|
- recipient: 收件人,为文本类型,必填
|
||||||
- content: 内容物,文本型,可包含多行描述
|
- content: 内容物,文本型,可包含多行描述
|
||||||
- sent_date: 寄出日期,时间戳(timestamptz/ TIMESTAMP),必填
|
- sent_date: 寄出日期,时间戳(timestamptz/ TIMESTAMP),必填
|
||||||
@@ -13,6 +15,8 @@
|
|||||||
```sql
|
```sql
|
||||||
CREATE TABLE xinhan (
|
CREATE TABLE xinhan (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
self_number TEXT,
|
||||||
|
tracking_number TEXT,
|
||||||
recipient TEXT NOT NULL,
|
recipient TEXT NOT NULL,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
sent_date TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
sent_date TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||||
@@ -20,7 +24,9 @@ CREATE TABLE xinhan (
|
|||||||
arrival_date TIMESTAMP WITHOUT TIME ZONE
|
arrival_date TIMESTAMP WITHOUT TIME ZONE
|
||||||
);
|
);
|
||||||
|
|
||||||
-- 索引,提升按收件人、寄出日期/寄达日期的查询性能
|
-- 索引,提升按自编号、快递号、收件人、寄出日期/寄达日期的查询性能
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_xinhan_self_number ON xinhan (self_number);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_xinhan_tracking_number ON xinhan (tracking_number);
|
||||||
CREATE INDEX IF NOT EXISTS idx_xinhan_recipient ON xinhan (recipient);
|
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_sent_date ON xinhan (sent_date);
|
||||||
CREATE INDEX IF NOT EXISTS idx_xinhan_arrival_date ON xinhan (arrival_date);
|
CREATE INDEX IF NOT EXISTS idx_xinhan_arrival_date ON xinhan (arrival_date);
|
||||||
@@ -34,6 +40,12 @@ WHERE recipient ILIKE '%张三%'
|
|||||||
ORDER BY sent_date DESC
|
ORDER BY sent_date DESC
|
||||||
LIMIT 100;
|
LIMIT 100;
|
||||||
|
|
||||||
|
-- 根据自编号查询示例
|
||||||
|
SELECT * FROM xinhan
|
||||||
|
WHERE self_number ILIKE '%XH-2026-001%'
|
||||||
|
ORDER BY sent_date DESC
|
||||||
|
LIMIT 100;
|
||||||
|
|
||||||
-- 根据日期范围查询示例
|
-- 根据日期范围查询示例
|
||||||
SELECT * FROM xinhan
|
SELECT * FROM xinhan
|
||||||
WHERE sent_date BETWEEN '2024-01-01' AND '2026-12-31'
|
WHERE sent_date BETWEEN '2024-01-01' AND '2026-12-31'
|
||||||
|
|||||||
Reference in New Issue
Block a user