Files
Letters/ticket/index.html
T
2026-03-30 19:54:25 +08:00

383 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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 {
--primary-blue: #1a73e8;
--light-blue: #e3f2fd;
--gradient-blue: linear-gradient(135deg, #66b3ff, #1a73e8);
--shadow-light: 0 4px 12px rgba(26, 115, 232, 0.15);
--shadow-medium: 0 8px 24px rgba(26, 115, 232, 0.2);
}
body {
background: linear-gradient(180deg, #f0f7ff, #e8f4fc);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
min-height: 100vh;
padding: 20px;
}
.ticket-container {
max-width: 900px;
margin: 40px auto;
padding: 32px;
background: #fff;
border-radius: 16px;
box-shadow: var(--shadow-medium);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}
h1 {
text-align: center;
font-size: 28px;
font-weight: 600;
margin-bottom: 12px;
background: var(--gradient-blue);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.page-desc {
text-align: center;
color: #6b7280;
font-size: 14px;
margin-bottom: 28px;
}
.search-form {
margin-bottom: 24px;
padding: 24px;
background: linear-gradient(135deg, #f8fbff, #f0f7ff);
border-radius: 12px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
align-items: end;
border: 1px solid #e0f0ff;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
font-size: 13px;
color: #4b5563;
margin-bottom: 8px;
font-weight: 500;
}
.form-control {
padding: 12px 16px;
border: 1.5px solid #d1d5db;
border-radius: 8px;
font-size: 14px;
transition: all 0.3s ease;
background: white;
}
.form-control:focus {
border-color: var(--primary-blue);
outline: none;
box-shadow: 0 0 0 3px rgba(26, 115, 232, 0.15);
}
.form-control::placeholder {
color: #9ca3af;
}
.btn {
height: 44px;
background: var(--gradient-blue);
border-radius: 8px;
color: #fff;
font-weight: 600;
cursor: pointer;
border: none;
transition: all 0.3s ease;
box-shadow: var(--shadow-light);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(26, 115, 232, 0.3);
}
.btn:active {
transform: translateY(0);
}
.result-table {
width: 100%;
border-collapse: collapse;
margin-top: 16px;
font-size: 14px;
border-radius: 10px;
overflow: hidden;
}
.result-table th {
background: linear-gradient(135deg, #f0f7ff, #e3f2fd);
text-align: left;
padding: 16px 12px;
font-weight: 600;
color: #1e40af;
border-bottom: 2px solid #bfdbfe;
}
.result-table td {
padding: 14px 12px;
border-bottom: 1px solid #e5e7eb;
color: #374151;
}
.result-table tr:hover {
background: #f9fafb;
}
.status {
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
display: inline-block;
}
.status.done {
background: linear-gradient(135deg, #dcfce7, #bbf7d0);
color: #166534;
box-shadow: 0 2px 4px rgba(22, 101, 52, 0.1);
}
.status.pending {
background: linear-gradient(135deg, #ffedd5, #fed7aa);
color: #c2410c;
box-shadow: 0 2px 4px rgba(194, 65, 12, 0.1);
}
.no-result {
text-align: center;
padding: 80px 20px;
color: #9ca3af;
font-size: 16px;
background: #f9fafb;
border-radius: 12px;
margin-top: 20px;
}
.loading {
text-align: center;
padding: 40px;
color: var(--primary-blue);
font-size: 15px;
font-weight: 500;
}
.error-message {
background: linear-gradient(135deg, #fee2e2, #fecaca);
color: #b91c1c;
padding: 16px;
border-radius: 10px;
border-left: 4px solid #ef4444;
margin-top: 20px;
}
.back-link {
font-size: 14px;
color: var(--primary-blue);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
margin-bottom: 20px;
padding: 8px 16px;
background: var(--light-blue);
border-radius: 8px;
transition: all 0.3s ease;
}
.back-link:hover {
background: #bfdbfe;
text-decoration: none;
transform: translateX(-4px);
}
/* 响应式优化 */
@media (max-width: 768px) {
body {
padding: 10px;
}
.ticket-container {
margin: 20px auto;
padding: 20px;
}
h1 {
font-size: 24px;
}
.search-form {
grid-template-columns: 1fr;
padding: 16px;
}
.result-table {
font-size: 13px;
}
.result-table th,
.result-table td {
padding: 10px 8px;
}
}
</style>
</head>
<body>
<div class="ticket-container">
<a href="../index.html" class="back-link">← 返回首页</a>
<h1>单据查询</h1>
<p class="page-desc">请输入查询条件,可查询 2024 年至今的单据</p>
<div class="search-form">
<div class="form-group">
<label for="searchTerm">编号 / 姓名</label>
<input type="text" id="searchTerm" class="form-control" placeholder="请输入编号或姓名">
</div>
<div class="form-group">
<label for="dateFrom">开始日期</label>
<input type="date" id="dateFrom" class="form-control" title="选择开始日期">
</div>
<div class="form-group">
<label for="dateTo">结束日期</label>
<input type="date" id="dateTo" class="form-control" title="选择结束日期">
</div>
<button id="searchBtn" class="btn">立即查询</button>
</div>
<div id="searchResults"></div>
</div>
<script>
const SUPABASE_URL = 'https://chixssrphfgxvqqigkzo.supabase.co';
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNoaXhzc3JwaGZneHZxcWlna3pvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ2OTE0OTEsImV4cCI6MjA5MDI2NzQ5MX0.Az_Ew2J2zdOMcSV0UNAjBS-LPqGpqhsaN4IyZ5R7iqU';
// 防止重复初始化
if (!window._sbClient) {
window._sbClient = window.supabase.createClient(
SUPABASE_URL,
SUPABASE_ANON_KEY
);
}
const sbClient = window._sbClient;
async function searchTickets() {
const searchTerm = document.getElementById('searchTerm').value.trim();
const dateFrom = document.getElementById('dateFrom').value;
const dateTo = document.getElementById('dateTo').value;
const resultsDiv = document.getElementById('searchResults');
resultsDiv.innerHTML = '<div class="loading">正在查询...</div>';
try {
let query = sbClient.from('tickets').select('*');
if (searchTerm) {
const escapedTerm = searchTerm
.replace(/%/g, '\\%')
.replace(/_/g, '\\_');
query = query.or(
`ticket_number.ilike.%${escapedTerm}%,customer_name.ilike.%${escapedTerm}%`
);
}
if (dateFrom) query = query.gte('created_at', dateFrom);
if (dateTo) query = query.lte('created_at', dateTo);
const { data, error } = await query;
if (error) throw error;
displayResults(data);
} catch (error) {
resultsDiv.innerHTML = `<div class="error-message">查询失败:${error.message}</div>`;
}
}
function displayResults(tickets) {
const resultsDiv = document.getElementById('searchResults');
if (!tickets || tickets.length === 0) {
resultsDiv.innerHTML = '<div class="no-result">🔍 未找到符合条件的单据</div>';
return;
}
let html = `
<table class="result-table">
<thead>
<tr>
<th>编号</th><th>姓名</th><th>事由</th><th>金额</th><th>日期</th><th>状态</th><th>操作</th>
</tr>
</thead>
<tbody>
`;
tickets.forEach(ticket => {
html += `
<tr>
<td>${ticket.ticket_number || ''}</td>
<td>${ticket.customer_name || ''}</td>
<td>${ticket.reason || ''}</td>
<td style="font-weight: 600; color: #1a73e8;">¥${Number(ticket.amount || 0).toFixed(2)}</td>
<td>${formatDate(ticket.created_at)}</td>
<td>
<span class="status ${ticket.processed ? 'done' : 'pending'}">
${ticket.processed ? '✓ 已处理' : '⏳ 未处理'}
</span>
</td>
<td>
<button class="btn" onclick="viewDetail('${ticket.id}')" style="padding: 6px 16px; font-size: 13px;">查看详情</button>
</td>
</tr>
`;
});
html += '</tbody></table>';
resultsDiv.innerHTML = html;
}
function formatDate(dateString) {
if (!dateString) return '';
return new Date(dateString).toLocaleDateString('zh-CN');
}
function viewDetail(id) {
window.location.href = `detail.html?id=${id}`;
}
// 事件绑定(替代 onclick
document.getElementById('searchBtn').addEventListener('click', searchTickets);
document.getElementById('searchTerm').addEventListener('keypress', function(e) {
if (e.key === 'Enter') searchTickets();
});
</script>
<script src="https://cdn.jsdmirror.cn/gh/bishshi/wechat-detect@main/wechat-detect.js"></script>
</body>
</html>