const $ = (id) => document.getElementById(id);
const msg = (t) => $("msg").textContent = typeof t === 'string' ? t : JSON.stringify(t, null, 2);
const tokenKey = 'asset_tracker_token';
let categories = [];
function token(){ return localStorage.getItem(tokenKey) || ''; }
async function api(path, method='GET', body){
const headers = {};
if(token()) headers['Authorization'] = `Bearer ${token()}`;
if(body) headers['Content-Type'] = 'application/json';
const res = await fetch(path, { method, headers, body: body ? JSON.stringify(body) : undefined });
const data = await res.json().catch(() => ({}));
if(!res.ok) throw new Error(data.error || `${res.status}`);
return data;
}
async function doLogin(){
try{
const data = await api('/api/v1/auth/login', 'POST', {
username: $('username').value.trim(),
password: $('password').value
});
localStorage.setItem(tokenKey, data.access_token);
$('login-section').classList.add('hidden');
$('app-section').classList.remove('hidden');
await reloadAll();
msg('登录成功');
}catch(e){ msg(`登录失败: ${e.message}`); }
}
async function loadCategories(){
const data = await api('/api/v1/categories');
categories = data.data || [];
$('category-list').innerHTML = categories.map(c => `
#${c.id} ${c.name} (${c.type})`).join('') || '暂无分类';
$('asset-category').innerHTML = categories.map(c => ``).join('');
}
async function addCategory(){
try{
await api('/api/v1/categories', 'POST', {
name: $('cat-name').value.trim(),
type: $('cat-type').value
});
$('cat-name').value='';
await loadCategories();
msg('分类创建成功');
}catch(e){ msg(`分类创建失败: ${e.message}`); }
}
function toRFC3339(localVal){
if(!localVal) return '';
const d = new Date(localVal);
return d.toISOString();
}
async function addAsset(){
try{
await api('/api/v1/assets', 'POST', {
name: $('asset-name').value.trim(),
category_id: Number($('asset-category').value),
quantity: Number($('asset-quantity').value || 0),
unit_price: Number($('asset-price').value || 0),
currency: $('asset-currency').value.trim().toUpperCase(),
expiry_date: toRFC3339($('asset-expiry').value)
});
$('asset-name').value='';
await loadAssets();
await loadDashboard();
msg('资产创建成功');
}catch(e){ msg(`资产创建失败: ${e.message}`); }
}
async function loadAssets(){
const data = await api('/api/v1/assets?page=1&page_size=100');
const rows = data.data || [];
const map = new Map(categories.map(c => [c.id, c.name]));
$('asset-tbody').innerHTML = rows.map(a => `
| ${a.id} |
${a.name} |
${map.get(a.category_id) || a.category_id} |
${a.total_value} ${a.currency} |
${a.status} |
${a.expiry_date || '-'} |
|
`).join('') || '| 暂无资产 |
';
$('asset-cards').innerHTML = rows.map(a => `
#${a.id} ${a.name}${a.status}
分类${map.get(a.category_id) || a.category_id}
金额${a.total_value} ${a.currency}
到期${a.expiry_date || '-'}
`).join('') || '暂无资产
';
}
async function delAsset(id){
try{
await api(`/api/v1/assets/${id}`, 'DELETE');
await loadAssets();
await loadDashboard();
msg(`已删除资产 #${id}`);
}catch(e){ msg(`删除失败: ${e.message}`); }
}
window.delAsset = delAsset;
async function loadDashboard(){
const d = await api('/api/v1/dashboard/summary');
const byCat = (d.by_category || []).map(x => `${x.category_name}: ${x.total_value}`).join('
') || '无';
$('dashboard').innerHTML = `
总资产${d.total_assets_value}
30天到期${(d.expiring_in_30_days || []).length} 条
`;
}
async function reloadAll(){
await loadCategories();
await loadAssets();
await loadDashboard();
}
$('login-btn').addEventListener('click', doLogin);
$('add-cat').addEventListener('click', addCategory);
$('add-asset').addEventListener('click', addAsset);
$('refresh-dashboard').addEventListener('click', loadDashboard);
(async function init(){
if(token()){
$('login-section').classList.add('hidden');
$('app-section').classList.remove('hidden');
try{ await reloadAll(); }catch(e){ msg(`自动加载失败: ${e.message}`); }
}
})();