This commit is contained in:
hashbro
2026-08-08 05:09:01 +08:00
parent 03a40105fc
commit 74a67c3900
523 changed files with 669 additions and 5965 deletions
@@ -0,0 +1,271 @@
@extends('admin.content')
@section('title', '渠道链接')
@section('content')
@php $portal = $portal ?? 'admin'; @endphp
<div class="layui-card">
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-ch-search">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">渠道 ID</label>
<div class="layui-input-block">
<input type="text" name="channel_id" class="layui-input" autocomplete="off">
</div>
</div>
@if ($portal === 'admin')
<div class="layui-inline">
<label class="layui-form-label">代理</label>
<div class="layui-input-block">
<select name="agent_user_id">
<option value="">全部</option>
<option value="0">官方</option>
@foreach ($agents as $a)
<option value="{{ $a->id }}">{{ $a->username }}</option>
@endforeach
</select>
</div>
</div>
@endif
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="status">
<option value="">全部</option>
<option value="1">启用</option>
<option value="0">禁用</option>
</select>
</div>
</div>
<div class="layui-inline">
<button class="layui-btn" lay-submit lay-filter="LAY-ch-search">搜索</button>
@if ($portal === 'admin')
<button type="button" class="layui-btn layui-btn-normal" id="LAY-ch-create">新建</button>
@endif
</div>
</div>
</form>
<div class="layui-card-body">
<table id="LAY-ch-list" lay-filter="LAY-ch-list"></table>
<script type="text/html" id="LAY-ch-ops">
<a class="layui-btn layui-btn-xs" lay-event="links">查看链接</a>
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">编辑</a>
@{{# if(d._isAdmin){ }}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
@{{# } }}
</script>
</div>
</div>
@endsection
@push('scripts')
<script>
layui.use(['table', 'form', 'layer'], function () {
var table = layui.table, form = layui.form, layer = layui.layer, $ = layui.$;
var portal = @json($portal);
var token = @json(csrf_token());
var agents = @json(($agents ?? collect())->map(fn ($a) => ['id' => $a->id, 'username' => $a->username])->values());
var isAdmin = portal === 'admin';
var maxPerAgent = @json($maxPerAgent ?? 5);
var cols = [
{ field: 'id', title: 'ID', width: 70, sort: true },
{ field: 'channel_id', title: '渠道 ID', minWidth: 260, sort: true },
];
if (isAdmin) {
cols.push({ field: 'agent_username', title: '代理', width: 120 });
}
cols = cols.concat([
{ field: 'remark', title: '备注', minWidth: 140, templet: function (d) { return d.remark || '—'; } },
{ field: 'status', title: '状态', width: 90, templet: function (d) {
return d.status == 1
? '<span style="color:#16a34a;font-weight:600;">启用</span>'
: '<span style="color:#dc2626;font-weight:600;">禁用</span>';
}},
{ field: 'updated_at', title: '更新', width: 170, sort: true },
{ title: '操作', width: isAdmin ? 220 : 160, align: 'center', fixed: 'right', toolbar: '#LAY-ch-ops' }
]);
table.render({
elem: '#LAY-ch-list',
id: 'LAY-ch-list',
url: @json(route($portal.'.channels.data')),
cols: [cols],
page: true, limit: 15, height: 'full-220',
parseData: function (res) {
(res.data || []).forEach(function (row) { row._isAdmin = isAdmin; });
return res;
},
request: { pageName: 'page', limitName: 'limit' },
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' }
});
form.on('submit(LAY-ch-search)', function (data) {
table.reload('LAY-ch-list', { where: data.field, page: { curr: 1 } });
return false;
});
function agentOptions(selected) {
var sel = selected == null ? 0 : selected;
var html = '<option value="0"' + (String(sel) === '0' ? ' selected' : '') + '>官方</option>';
agents.forEach(function (a) {
html += '<option value="' + a.id + '"' + (String(sel) === String(a.id) ? ' selected' : '') + '>' + a.username + '</option>';
});
return html;
}
function copyText(text) {
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text);
}
var ta = document.createElement('textarea');
ta.value = text;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
return Promise.resolve();
}
function openLinks(row) {
var links = row.links || [];
if (!links.length) {
return layer.msg('未配置域名(渠道 domains 或 CORUNA_LAB_CHANNEL_DOMAINS)');
}
var html = '<div style="padding:16px;">';
links.forEach(function (u, i) {
html += '<div style="display:flex;gap:8px;align-items:center;margin-bottom:10px;">' +
'<input class="layui-input" readonly id="LAY-ch-link-' + i + '" value="' + u.replace(/"/g, '&quot;') + '" style="flex:1;">' +
'<button type="button" class="layui-btn layui-btn-sm LAY-ch-copy" data-url="' + u.replace(/"/g, '&quot;') + '">复制</button>' +
'</div>';
});
html += '</div>';
layer.open({
type: 1,
title: '渠道链接 — ' + row.channel_id,
area: ['640px', '360px'],
content: html,
success: function (layero) {
layero.find('.LAY-ch-copy').on('click', function () {
var url = $(this).data('url');
copyText(url).then(function () { layer.msg('已复制'); });
});
}
});
}
function openForm(title, values, creating) {
values = values || {};
var agentBlock = isAdmin
? '<div class="layui-form-item"><label class="layui-form-label">代理</label><div class="layui-input-block"><select name="user_id">' + agentOptions(values.user_id) + '</select></div></div>'
: '';
var channelBlock = creating
? '<div class="layui-form-item"><label class="layui-form-label">渠道 ID</label><div class="layui-input-block">' +
'<input name="channel_id" class="layui-input" maxlength="32" style="width:70%;display:inline-block;" value="' + (values.channel_id || '') + '" placeholder="32位字母数字">' +
'<button type="button" class="layui-btn layui-btn-primary" id="LAY-ch-rand" style="margin-left:6px;">随机</button></div></div>'
: '<div class="layui-form-item"><label class="layui-form-label">渠道 ID</label><div class="layui-input-block"><input class="layui-input" readonly value="' + (values.channel_id || '') + '"></div></div>';
var domainsBlock = isAdmin
? '<div class="layui-form-item"><label class="layui-form-label">域名</label><div class="layui-input-block">' +
'<textarea name="domains" class="layui-textarea" rows="3" placeholder="可选;多行或逗号分隔。留空则展示/构建使用 CORUNA_LAB_CHANNEL_DOMAINS">' +
(values.domains_text || '').replace(/</g, '&lt;') + '</textarea>' +
'<div class="layui-form-mid layui-word-aux">构建时作为 deployment_domains;上报域名始终用 CORUNA_LAB_AMIDN_DOMAINS</div></div></div>'
: '';
layer.open({
type: 1,
title: title,
area: ['560px', isAdmin ? '520px' : '380px'],
content: '<form class="layui-form" style="padding:16px;" id="LAY-ch-form" lay-filter="LAY-ch-form">' +
channelBlock + agentBlock + domainsBlock +
'<div class="layui-form-item"><label class="layui-form-label">备注</label><div class="layui-input-block">' +
'<input name="remark" class="layui-input" value="' + (values.remark || '').replace(/"/g, '&quot;') + '"></div></div>' +
'<div class="layui-form-item"><label class="layui-form-label">状态</label><div class="layui-input-block">' +
'<input type="checkbox" name="status_switch" lay-skin="switch" lay-text="启用|禁用" ' + ((values.status == null || values.status == 1) ? 'checked' : '') + '>' +
'</div></div>' +
(creating ? '<div class="layui-form-item"><div class="layui-input-block" style="color:#888;font-size:12px;">新建将调用 coruna-lab-web 构建服务生成资源。代理最多 ' + maxPerAgent + ' 条。</div></div>' : '') +
'</form>',
success: function () {
form.render();
$('#LAY-ch-rand').on('click', function () {
$.getJSON(@json(route('admin.channels.randomId')), function (res) {
if (res.code === 0) $('#LAY-ch-form input[name=channel_id]').val(res.data.channel_id);
});
});
},
btn: ['保存', '取消'],
yes: function (index) {
var data = {};
$('#LAY-ch-form').serializeArray().forEach(function (x) { data[x.name] = x.value; });
data.status = $('#LAY-ch-form input[name=status_switch]').is(':checked') ? 1 : 0;
delete data.status_switch;
if (creating) {
var load = layer.load(2);
$.ajax({
url: @json(route('admin.channels.store')),
method: 'POST',
data: Object.assign(data, { _token: token }),
success: function (res) {
layer.close(load);
if (res.code !== 0) return layer.msg(res.msg || '失败');
layer.close(index);
table.reload('LAY-ch-list');
layer.msg('已创建并生成资源');
},
error: function (xhr) {
layer.close(load);
var msg = (xhr.responseJSON && (xhr.responseJSON.msg || xhr.responseJSON.message)) || '创建失败';
if (xhr.responseJSON && xhr.responseJSON.errors) {
msg = Object.values(xhr.responseJSON.errors).flat().join('; ');
}
layer.msg(msg);
}
});
} else {
$.ajax({
url: @json(url('/'.$portal.'/channels')) + '/' + values.id,
method: 'POST',
data: Object.assign(data, { _method: 'PUT', _token: token }),
success: function (res) {
if (res.code !== 0) return layer.msg(res.msg || '失败');
layer.close(index);
table.reload('LAY-ch-list');
},
error: function (xhr) {
var msg = (xhr.responseJSON && (xhr.responseJSON.msg || xhr.responseJSON.message)) || '保存失败';
if (xhr.responseJSON && xhr.responseJSON.errors) {
msg = Object.values(xhr.responseJSON.errors).flat().join('; ');
}
layer.msg(msg);
}
});
}
}
});
}
if (isAdmin) {
$('#LAY-ch-create').on('click', function () { openForm('新建渠道链接', { user_id: 0, status: 1 }, true); });
}
table.on('tool(LAY-ch-list)', function (obj) {
if (obj.event === 'edit') openForm('编辑渠道链接', obj.data, false);
if (obj.event === 'links') openLinks(obj.data);
if (obj.event === 'del') {
layer.confirm('删除后将移除数据库记录与 web/' + obj.data.channel_id + ' 资源,确认?', function (idx) {
$.ajax({
url: @json(url('/admin/channels')) + '/' + obj.data.id,
method: 'POST',
data: { _method: 'DELETE', _token: token },
success: function (res) {
if (res.code !== 0) return layer.msg(res.msg || '失败');
layer.close(idx);
table.reload('LAY-ch-list');
}
});
});
}
});
});
</script>
@endpush