节点详情:照片灯箱浏览、参与人点击编辑、花销只记总计
1) 照片与附件不再新开窗口看 之前点缩略图直接 target=_blank 打开原始文件,看完还得切回来。 现在统一走当前页灯箱(templates/_lightbox.php,详情页照片墙与 照片管理页共用):左右箭头 / 键盘 ←→ / 手机滑动切上一张下一张, Esc 或点背景关闭,带「第几张 / 共几张」计数并预加载相邻两张。 非图片附件(PDF 等)仍保留直接打开与下载。 2) 参与人可以直接改了 之前加完只能移出重加。现在每个参与人旁有「编辑」,点开预填弹窗 (角色标签 / 心情 / 签到时间),保存仍走 members/store —— Members::save() 本来就是 upsert(同节点同人一条),服务端零改动。 失败回填按 user_id 精确匹配,只回填刚才没保存成的那个人。 3) 花销去掉预算,只记真实花费 明细上移,底部一行「总计(N 笔)¥X」。表单不再有「预算」选项, 查询一律 is_budget=0(历史预算行不再出现在列表与合计里); 活动页统计同步改成「共 N 笔 · 总计」。列保留在库里不删数据。 已验证:本地全链 11 步全绿(php -l / 渲染 286 项 / SQL / PDO / CSS / Mime / amap / 内联 JS×11 / 布局几何 / 表单交互 73 项);远端 e2e 296 项 0 失败(含灯箱、编辑弹窗、历史预算行排除的专项断言); 部署后双 PHP 渲染逐字节一致、60 文件哈希一致,线上 style.css 含新规则。
This commit is contained in:
+23
-39
@@ -6,8 +6,11 @@ namespace App;
|
||||
/**
|
||||
* 花销与分摊
|
||||
*
|
||||
* 表结构:expenses(挂在 trip_nodes 上,is_budget 区分"预算"和"实际")
|
||||
* + expense_splits(这笔钱按人分摊,谁承担多少)
|
||||
* 表结构:expenses(挂在 trip_nodes 上)+ expense_splits(这笔钱按人分摊,谁承担多少)
|
||||
*
|
||||
* ⚠️ 历史上 expenses 有 is_budget(预算 / 实际)之分,用户明确反馈「预算没有意义」,
|
||||
* 现在只记真实花销:查询一律 is_budget = 0,表单也不再提供「预算」选项。
|
||||
* 列本身保留(老数据还在库里,不至于丢),但 UI 与汇总都不再出现预算概念。
|
||||
*/
|
||||
class Expenses
|
||||
{
|
||||
@@ -23,7 +26,7 @@ class Expenses
|
||||
return ['CNY' => '人民币 ¥', 'JPY' => '日元 ¥', 'USD' => '美元 $', 'EUR' => '欧元 €', 'HKD' => '港币 HK$'];
|
||||
}
|
||||
|
||||
/** 某个节点下的花销,带付款人和分摊明细 */
|
||||
/** 某个节点下的花销(只看真实花销),带付款人和分摊明细 */
|
||||
public static function forNode(int $nodeId): array
|
||||
{
|
||||
$db = Database::get();
|
||||
@@ -31,8 +34,8 @@ class Expenses
|
||||
SELECT e.*, u.name AS payer_name, u.avatar AS payer_avatar
|
||||
FROM expenses e
|
||||
LEFT JOIN users u ON u.id = e.payer_user_id
|
||||
WHERE e.trip_node_id = ?
|
||||
ORDER BY e.is_budget ASC, e.created_at ASC, e.id ASC');
|
||||
WHERE e.trip_node_id = ? AND e.is_budget = 0
|
||||
ORDER BY e.created_at ASC, e.id ASC');
|
||||
$stmt->execute([$nodeId]);
|
||||
$rows = $stmt->fetchAll();
|
||||
if (empty($rows)) return [];
|
||||
@@ -56,41 +59,32 @@ class Expenses
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/** 活动下的花销合计(预算 / 实际),以及各节点的小计 */
|
||||
/** 活动下的真实花销总计,以及各节点的小计 */
|
||||
public static function summaryForActivity(int $activityId): array
|
||||
{
|
||||
$db = Database::get();
|
||||
$stmt = $db->prepare('
|
||||
SELECT tn.id AS node_id, e.is_budget, SUM(e.total_amount) AS amount, COUNT(*) AS cnt
|
||||
SELECT tn.id AS node_id, SUM(e.total_amount) AS amount, COUNT(*) AS cnt
|
||||
FROM expenses e
|
||||
JOIN trip_nodes tn ON tn.id = e.trip_node_id
|
||||
WHERE tn.activity_id = ?
|
||||
GROUP BY tn.id, e.is_budget');
|
||||
WHERE tn.activity_id = ? AND e.is_budget = 0
|
||||
GROUP BY tn.id');
|
||||
$stmt->execute([$activityId]);
|
||||
|
||||
$byNode = [];
|
||||
$budgetTotal = 0.0;
|
||||
$actualTotal = 0.0;
|
||||
$total = 0.0;
|
||||
$count = 0;
|
||||
foreach ($stmt->fetchAll() as $row) {
|
||||
$nodeId = (int)$row['node_id'];
|
||||
$isBudget = (int)$row['is_budget'] === 1;
|
||||
$amount = (float)$row['amount'];
|
||||
$byNode[$nodeId][$isBudget ? 'budget' : 'actual'] = $amount;
|
||||
if ($isBudget) {
|
||||
$budgetTotal += $amount;
|
||||
} else {
|
||||
$actualTotal += $amount;
|
||||
}
|
||||
$byNode[(int)$row['node_id']] = $amount;
|
||||
$total += $amount;
|
||||
$count += (int)$row['cnt'];
|
||||
}
|
||||
|
||||
return [
|
||||
'budget' => $budgetTotal,
|
||||
'actual' => $actualTotal,
|
||||
'count' => $count,
|
||||
'by_node' => $byNode,
|
||||
'diff' => $actualTotal - $budgetTotal,
|
||||
'total' => $total,
|
||||
'count' => $count,
|
||||
'by_node' => $byNode,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -191,23 +185,13 @@ class Expenses
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 某个节点的花销合计 */
|
||||
/** 某个节点的真实花销合计 */
|
||||
public static function summaryForNode(int $nodeId): array
|
||||
{
|
||||
$stmt = Database::get()->prepare('SELECT is_budget, SUM(total_amount) AS amount, COUNT(*) AS cnt
|
||||
FROM expenses WHERE trip_node_id = ? GROUP BY is_budget');
|
||||
$stmt = Database::get()->prepare('SELECT COALESCE(SUM(total_amount), 0) AS amount, COUNT(*) AS cnt
|
||||
FROM expenses WHERE trip_node_id = ? AND is_budget = 0');
|
||||
$stmt->execute([$nodeId]);
|
||||
$budget = 0.0;
|
||||
$actual = 0.0;
|
||||
$count = 0;
|
||||
foreach ($stmt->fetchAll() as $row) {
|
||||
if ((int)$row['is_budget'] === 1) {
|
||||
$budget = (float)$row['amount'];
|
||||
} else {
|
||||
$actual = (float)$row['amount'];
|
||||
}
|
||||
$count += (int)$row['cnt'];
|
||||
}
|
||||
return ['budget' => $budget, 'actual' => $actual, 'count' => $count, 'diff' => $actual - $budget];
|
||||
$row = $stmt->fetch();
|
||||
return ['total' => (float)$row['amount'], 'count' => (int)$row['cnt']];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user