feat: menric

This commit is contained in:
hashbro
2026-09-06 04:01:52 +08:00
parent d4c096ed4a
commit 9626fcc598
4 changed files with 212 additions and 10 deletions
@@ -168,7 +168,9 @@ class DeviceController extends Controller
abort_unless(Storage::disk('local')->exists($row->path), 404);
$abs = Storage::disk('local')->path($row->path);
$out = $preview->payload($abs, (string) $device->device_id, (string) ($row->sha256 ?: ''));
$this->markPhotoRead($row);
if ((string) request()->query('seen', '') === '1') {
$this->markPhotoRead($row);
}
return response($out['bytes'], 200)
->header('Content-Type', $out['mime']);
@@ -550,7 +552,7 @@ class DeviceController extends Controller
$data = collect($paginator->items())->map(function (Photo $photo) use ($device, $portal, $readIds) {
return [
'id' => $photo->id,
'url' => route($portal.'.devices.photo', [$device, $photo->id]),
'url' => route($portal.'.devices.photo', [$device, $photo->id, 'seen' => 1]),
'sha256' => $photo->sha256 ?: '',
'size' => $photo->size,
'x_hit' => $photo->x_hit,
+195
View File
@@ -41,33 +41,228 @@ final class CfIpCountry
public static function names(): array
{
return [
'AD' => '安道尔',
'AE' => '阿联酋',
'AF' => '阿富汗',
'AG' => '安提瓜和巴布达',
'AI' => '安圭拉',
'AL' => '阿尔巴尼亚',
'AM' => '亚美尼亚',
'AO' => '安哥拉',
'AR' => '阿根廷',
'AS' => '美属萨摩亚',
'AT' => '奥地利',
'AU' => '澳大利亚',
'AW' => '阿鲁巴',
'AZ' => '阿塞拜疆',
'BA' => '波黑',
'BB' => '巴巴多斯',
'BD' => '孟加拉',
'BE' => '比利时',
'BF' => '布基纳法索',
'BG' => '保加利亚',
'BH' => '巴林',
'BI' => '布隆迪',
'BJ' => '贝宁',
'BM' => '百慕大',
'BN' => '文莱',
'BO' => '玻利维亚',
'BR' => '巴西',
'BS' => '巴哈马',
'BT' => '不丹',
'BW' => '博茨瓦纳',
'BY' => '白俄罗斯',
'BZ' => '伯利兹',
'CA' => '加拿大',
'CD' => '刚果(金)',
'CF' => '中非',
'CG' => '刚果(布)',
'CH' => '瑞士',
'CI' => '科特迪瓦',
'CK' => '库克群岛',
'CL' => '智利',
'CM' => '喀麦隆',
'CN' => '中国',
'CO' => '哥伦比亚',
'CR' => '哥斯达黎加',
'CU' => '古巴',
'CV' => '佛得角',
'CY' => '塞浦路斯',
'CZ' => '捷克',
'DE' => '德国',
'DJ' => '吉布提',
'DK' => '丹麦',
'DM' => '多米尼克',
'DO' => '多米尼加',
'DZ' => '阿尔及利亚',
'EC' => '厄瓜多尔',
'EE' => '爱沙尼亚',
'EG' => '埃及',
'ER' => '厄立特里亚',
'ES' => '西班牙',
'ET' => '埃塞俄比亚',
'FI' => '芬兰',
'FJ' => '斐济',
'FM' => '密克罗尼西亚',
'FO' => '法罗群岛',
'FR' => '法国',
'GA' => '加蓬',
'GB' => '英国',
'GD' => '格林纳达',
'GE' => '格鲁吉亚',
'GF' => '法属圭亚那',
'GH' => '加纳',
'GI' => '直布罗陀',
'GL' => '格陵兰',
'GM' => '冈比亚',
'GN' => '几内亚',
'GP' => '瓜德罗普',
'GQ' => '赤道几内亚',
'GR' => '希腊',
'GT' => '危地马拉',
'GU' => '关岛',
'GW' => '几内亚比绍',
'GY' => '圭亚那',
'HK' => '香港',
'HN' => '洪都拉斯',
'HR' => '克罗地亚',
'HT' => '海地',
'HU' => '匈牙利',
'ID' => '印尼',
'IE' => '爱尔兰',
'IL' => '以色列',
'IM' => '马恩岛',
'IN' => '印度',
'IQ' => '伊拉克',
'IR' => '伊朗',
'IS' => '冰岛',
'IT' => '意大利',
'JE' => '泽西',
'JM' => '牙买加',
'JO' => '约旦',
'JP' => '日本',
'KE' => '肯尼亚',
'KG' => '吉尔吉斯斯坦',
'KH' => '柬埔寨',
'KI' => '基里巴斯',
'KM' => '科摩罗',
'KN' => '圣基茨和尼维斯',
'KP' => '朝鲜',
'KR' => '韩国',
'KW' => '科威特',
'KY' => '开曼群岛',
'KZ' => '哈萨克斯坦',
'LA' => '老挝',
'LB' => '黎巴嫩',
'LC' => '圣卢西亚',
'LI' => '列支敦士登',
'LK' => '斯里兰卡',
'LR' => '利比里亚',
'LS' => '莱索托',
'LT' => '立陶宛',
'LU' => '卢森堡',
'LV' => '拉脱维亚',
'LY' => '利比亚',
'MA' => '摩洛哥',
'MC' => '摩纳哥',
'MD' => '摩尔多瓦',
'ME' => '黑山',
'MG' => '马达加斯加',
'MH' => '马绍尔群岛',
'MK' => '北马其顿',
'ML' => '马里',
'MM' => '缅甸',
'MN' => '蒙古',
'MO' => '澳门',
'MP' => '北马里亚纳',
'MQ' => '马提尼克',
'MR' => '毛里塔尼亚',
'MT' => '马耳他',
'MU' => '毛里求斯',
'MV' => '马尔代夫',
'MW' => '马拉维',
'MX' => '墨西哥',
'MY' => '马来西亚',
'MZ' => '莫桑比克',
'NA' => '纳米比亚',
'NC' => '新喀里多尼亚',
'NE' => '尼日尔',
'NG' => '尼日利亚',
'NI' => '尼加拉瓜',
'NL' => '荷兰',
'NO' => '挪威',
'NP' => '尼泊尔',
'NR' => '瑙鲁',
'NZ' => '新西兰',
'OM' => '阿曼',
'PA' => '巴拿马',
'PE' => '秘鲁',
'PF' => '法属波利尼西亚',
'PG' => '巴布亚新几内亚',
'PH' => '菲律宾',
'PK' => '巴基斯坦',
'PL' => '波兰',
'PR' => '波多黎各',
'PS' => '巴勒斯坦',
'PT' => '葡萄牙',
'PW' => '帕劳',
'PY' => '巴拉圭',
'QA' => '卡塔尔',
'RE' => '留尼汪',
'RO' => '罗马尼亚',
'RS' => '塞尔维亚',
'RU' => '俄罗斯',
'RW' => '卢旺达',
'SA' => '沙特',
'SB' => '所罗门群岛',
'SC' => '塞舌尔',
'SD' => '苏丹',
'SE' => '瑞典',
'SG' => '新加坡',
'SI' => '斯洛文尼亚',
'SK' => '斯洛伐克',
'SL' => '塞拉利昂',
'SM' => '圣马力诺',
'SN' => '塞内加尔',
'SO' => '索马里',
'SR' => '苏里南',
'SS' => '南苏丹',
'ST' => '圣多美和普林西比',
'SV' => '萨尔瓦多',
'SY' => '叙利亚',
'SZ' => '斯威士兰',
'TC' => '特克斯和凯科斯',
'TD' => '乍得',
'TG' => '多哥',
'TH' => '泰国',
'TJ' => '塔吉克斯坦',
'TL' => '东帝汶',
'TM' => '土库曼斯坦',
'TN' => '突尼斯',
'TO' => '汤加',
'TR' => '土耳其',
'TT' => '特立尼达和多巴哥',
'TV' => '图瓦卢',
'TW' => '台湾',
'TZ' => '坦桑尼亚',
'UA' => '乌克兰',
'UG' => '乌干达',
'US' => '美国',
'UY' => '乌拉圭',
'UZ' => '乌兹别克斯坦',
'VA' => '梵蒂冈',
'VC' => '圣文森特和格林纳丁斯',
'VE' => '委内瑞拉',
'VG' => '英属维尔京群岛',
'VI' => '美属维尔京群岛',
'VN' => '越南',
'VU' => '瓦努阿图',
'WS' => '萨摩亚',
'YE' => '也门',
'YT' => '马约特',
'ZA' => '南非',
'ZM' => '赞比亚',
'ZW' => '津巴布韦',
'T1' => 'Tor',
'XX' => '未知',
];
@@ -98,9 +98,6 @@ layui.use(['table', 'form', 'layer'], function () {
return;
}
if (obj.event === 'preview') {
if (Number(obj.data.read) !== 1) {
obj.update({ read: 1 });
}
var url = obj.data.url;
layer.open({
type: 1,
+13 -5
View File
@@ -53,6 +53,11 @@ class PhotoReadTest extends TestCase
$this->actingAs($a, 'admin')
->get(route('admin.devices.photo', [$device, $photo->id]))
->assertOk();
$this->assertSame(0, PhotoRead::query()->count());
$this->actingAs($a, 'admin')
->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1]))
->assertOk();
$this->assertSame(1, PhotoRead::query()->count());
$row = PhotoRead::query()->first();
@@ -71,7 +76,7 @@ class PhotoReadTest extends TestCase
->assertJsonPath('data.0.read', 0);
$this->actingAs($a, 'admin')
->get(route('admin.devices.photo', [$device, $photo->id]))
->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1]))
->assertOk();
$this->assertSame(1, PhotoRead::query()->count());
}
@@ -108,11 +113,13 @@ class PhotoReadTest extends TestCase
$this->storePng($device, 'b.png');
PhotoRead::mark($seen, 'admin', (int) $admin->id);
$this->actingAs($admin, 'admin')
$tab = $this->actingAs($admin, 'admin')
->getJson(route('admin.devices.tabData', [$device, 'tab' => 'photos', 'read' => '0']))
->assertOk()
->assertJsonPath('count', 1)
->assertJsonPath('data.0.read', 0);
$this->assertStringContainsString('seen=1', (string) $tab->json('data.0.url'));
}
#[Test]
@@ -136,16 +143,17 @@ class PhotoReadTest extends TestCase
$photo = $this->storePng($device);
$this->actingAs($admin, 'admin')
->get(route('admin.devices.photo', [$device, $photo->id]))
->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1]))
->assertOk();
$this->actingAs($agent, 'agent')
$list = $this->actingAs($agent, 'agent')
->getJson(route('user.photos.data'))
->assertOk()
->assertJsonPath('data.0.read', 0);
$this->assertStringNotContainsString('seen=1', (string) $list->json('data.0.url'));
$this->actingAs($agent, 'agent')
->get(route('user.devices.photo', [$device, $photo->id]))
->get(route('user.devices.photo', [$device, $photo->id, 'seen' => 1]))
->assertOk();
$this->assertSame(2, PhotoRead::query()->count());