164 lines
12 KiB
PHP

<x-layouts.admin>
<x-slot name="title">上游数据字典</x-slot>
<x-slot name="content">
<div class="my-6">
@include('system_settings.partials.navigation')
<div class="mb-5 flex flex-wrap items-start justify-between gap-3">
<div>
<h2 class="text-[14px] font-semibold leading-5 text-[#171717]">表与字段目录</h2>
<p class="mt-1 max-w-3xl text-[13px] leading-5 text-[#595959]">
这里展示后台低频同步到系统数据库的表、视图和字段结构,不需要开发者直接连接云数据库。
</p>
</div>
<a href="{{ route('system-settings.databases.index') }}" class="inline-flex h-[34px] items-center rounded-lg border border-[#D8D2C7] bg-white px-4 text-[13px] font-medium text-[#171717] hover:border-[#856632] hover:bg-[#F7F0DE] focus:outline-none focus:ring-2 focus:ring-[#856632]/20">
返回数据库管理
</a>
</div>
@if (! $ready)
<div class="rounded-xl border border-[#D8D2C7] bg-white p-6" role="status">
<div class="flex items-start gap-3">
<span class="material-icons-outlined mt-0.5 text-xl text-[#935F07]" aria-hidden="true">schedule</span>
<div>
<h3 class="text-[13px] font-semibold text-[#171717]">数据字典正在准备</h3>
<p class="mt-1 text-[13px] leading-5 text-[#595959]">
共享系统数据库完成结构迁移后,后台会自动同步两套云数据库的表和字段。现有业务和数据库连接不受影响。
</p>
</div>
</div>
</div>
@else
<div class="mb-4 flex flex-wrap gap-2" aria-label="数据源同步状态">
@foreach ($sourceLabels as $sourceKey => $sourceLabel)
@php($status = $sourceStatus->get($sourceKey))
<span class="inline-flex items-center gap-2 rounded-full bg-[#F7F0DE] px-3 py-1.5 text-[12px] text-[#595959]">
<span class="font-semibold text-[#171717]">{{ $sourceLabel }}</span>
@if ($status)
{{ number_format((int) $status->column_count) }} 个字段 ·
{{ \Illuminate\Support\Carbon::parse($status->synchronized_at)->format('m-d H:i') }}
@else
等待后台首次同步
@endif
</span>
@endforeach
</div>
<form method="GET" action="{{ route('system-settings.databases.dictionary') }}" class="mb-4 rounded-xl border border-[#D8D2C7] bg-white p-4">
<div class="flex flex-wrap items-end gap-3">
<label class="min-w-48 flex-1">
<span class="mb-1 block text-[12px] font-medium text-[#171717]">数据来源</span>
<select name="source" class="h-[34px] w-full rounded-lg border border-[#D8D2C7] bg-white px-3 text-[13px] text-[#171717] focus:border-[#856632] focus:outline-none focus:ring-2 focus:ring-[#856632]/20">
<option value="">全部来源</option>
@foreach ($sourceLabels as $sourceKey => $sourceLabel)
<option value="{{ $sourceKey }}" @selected(($filters['source'] ?? '') === $sourceKey)>{{ $sourceLabel }}</option>
@endforeach
</select>
</label>
<label class="min-w-40">
<span class="mb-1 block text-[12px] font-medium text-[#171717]">对象类型</span>
<select name="type" class="h-[34px] w-full rounded-lg border border-[#D8D2C7] bg-white px-3 text-[13px] text-[#171717] focus:border-[#856632] focus:outline-none focus:ring-2 focus:ring-[#856632]/20">
<option value="">表和视图</option>
<option value="table" @selected(($filters['type'] ?? '') === 'table')>数据表</option>
<option value="view" @selected(($filters['type'] ?? '') === 'view')>视图</option>
</select>
</label>
<label class="min-w-64 flex-[2]">
<span class="mb-1 block text-[12px] font-medium text-[#171717]">搜索表或字段</span>
<input name="search" value="{{ $filters['search'] ?? '' }}" placeholder="输入表名、视图名或字段名" class="h-[34px] w-full rounded-lg border border-[#D8D2C7] bg-white px-3 text-[13px] text-[#171717] placeholder:text-[#595959] focus:border-[#856632] focus:outline-none focus:ring-2 focus:ring-[#856632]/20">
</label>
<button type="submit" class="inline-flex h-[34px] items-center rounded-lg bg-[#856632] px-4 text-[13px] font-medium text-white hover:bg-[#6A5129] focus:outline-none focus:ring-2 focus:ring-[#856632]/20">查询</button>
</div>
</form>
<div class="overflow-x-auto rounded-xl border border-[#D8D2C7] bg-white">
<table class="min-w-full divide-y divide-[#D8D2C7] text-[12.5px]">
<thead class="bg-[#F7F0DE] text-left text-[12px] font-semibold text-[#171717]">
<tr>
<th class="px-4 py-3">来源</th>
<th class="px-4 py-3">Schema</th>
<th class="px-4 py-3">表或视图</th>
<th class="px-4 py-3">类型</th>
<th class="px-4 py-3 text-right">字段数</th>
<th class="px-4 py-3 text-right">操作</th>
</tr>
</thead>
<tbody class="divide-y divide-[#D8D2C7]">
@forelse ($objects as $object)
<tr class="hover:bg-[#F7F0DE]/50">
<td class="px-4 py-3 text-[#595959]">{{ $sourceLabels[$object->source_key] ?? $object->source_key }}</td>
<td class="px-4 py-3 font-mono text-[#595959]">{{ $object->schema_name }}</td>
<td class="px-4 py-3 font-mono font-semibold text-[#171717]">{{ $object->object_name }}</td>
<td class="px-4 py-3 text-[#595959]">{{ $object->object_type === 'view' ? '视图' : '数据表' }}</td>
<td class="px-4 py-3 text-right tabular-nums text-[#595959]">{{ $object->column_count }}</td>
<td class="px-4 py-3 text-right">
<a href="{{ route('system-settings.databases.dictionary', array_merge(request()->except(['page', 'selected_source', 'selected_schema', 'selected_object']), [
'selected_source' => $object->source_key,
'selected_schema' => $object->schema_name,
'selected_object' => $object->object_name,
])) }}" class="font-semibold text-[#856632] hover:text-[#6A5129] hover:underline">查看字段</a>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-5 py-12 text-center text-[13px] text-[#595959]">
还没有匹配的表或字段。若尚未首次同步,请等待后台任务完成。
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if ($objects && $objects->hasPages())
<div class="mt-4">{{ $objects->links() }}</div>
@endif
@if ($columns->isNotEmpty())
<section class="mt-6" aria-labelledby="dictionary-columns-heading">
<div class="mb-3">
<h3 id="dictionary-columns-heading" class="text-[14px] font-semibold text-[#171717]">
{{ $columns->first()->schema_name }}.{{ $columns->first()->object_name }}
</h3>
<p class="mt-1 text-[12px] text-[#595959]">字段结构来自共享系统数据库中的最近一次后台同步。</p>
</div>
<div class="overflow-x-auto rounded-xl border border-[#D8D2C7] bg-white">
<table class="min-w-full divide-y divide-[#D8D2C7] text-[12.5px]">
<thead class="bg-[#F7F0DE] text-left text-[12px] font-semibold text-[#171717]">
<tr>
<th class="px-4 py-3 text-right">序号</th>
<th class="px-4 py-3">字段名称</th>
<th class="px-4 py-3">数据类型</th>
<th class="px-4 py-3 text-right">长度/精度</th>
<th class="px-4 py-3">允许为空</th>
</tr>
</thead>
<tbody class="divide-y divide-[#D8D2C7]">
@foreach ($columns as $column)
<tr>
<td class="px-4 py-3 text-right tabular-nums text-[#595959]">{{ $column->ordinal_position }}</td>
<td class="px-4 py-3 font-mono font-semibold text-[#171717]">{{ $column->column_name }}</td>
<td class="px-4 py-3 font-mono text-[#595959]">{{ $column->data_type }}</td>
<td class="px-4 py-3 text-right tabular-nums text-[#595959]">
@if ($column->max_length !== null)
{{ $column->max_length }}
@elseif ($column->numeric_precision !== null)
{{ $column->numeric_precision }}{{ $column->numeric_scale !== null ? ',' . $column->numeric_scale : '' }}
@else
—
@endif
</td>
<td class="px-4 py-3 text-[#595959]">{{ $column->is_nullable ? '是' : '否' }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</section>
@endif
@endif
</div>
</x-slot>
</x-layouts.admin>