You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

118 lines
11 KiB

import { defineComponent, ref, reactive, computed, useSSRContext } from 'vue';
import { ssrRenderAttrs, ssrRenderStyle, ssrRenderList, ssrInterpolate, ssrRenderAttr, ssrIncludeBooleanAttr, ssrLooseContain, ssrRenderClass } from 'vue/server-renderer';
import { u as useApi } from './useApi-B-E5eLsI.mjs';
import { u as useToast } from './useToast-CS21XT61.mjs';
import './server.mjs';
import '../nitro/nitro.mjs';
import 'node:http';
import 'node:https';
import 'node:events';
import 'node:buffer';
import 'node:fs';
import 'node:path';
import 'node:crypto';
import 'node:url';
import '../routes/renderer.mjs';
import 'vue-bundle-renderer/runtime';
import 'unhead/server';
import 'devalue';
import 'unhead/utils';
import 'pinia';
import 'perfect-debounce';
import './useLoading-D4zrSa2m.mjs';
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "environments",
__ssrInlineRender: true,
setup(__props) {
useApi();
useToast();
const view = ref("list");
const rows = ref([]);
const loading = ref(false);
const isEditing = ref(false);
const testPassed = ref(false);
const testing = ref(false);
const testResult = reactive({
show: false,
ok: false,
ssh_ok: false,
ssh_msg: "",
etcd_ok: false,
etcd_msg: "",
redis_ok: false,
redis_msg: "",
nats_ok: false,
nats_msg: ""
});
const testItems = computed(() => [
{ key: "ssh", label: "SSH 部署机", ok: testResult.ssh_ok, msg: testResult.ssh_msg },
{ key: "etcd", label: "ETCD", ok: testResult.etcd_ok, msg: testResult.etcd_msg },
{ key: "redis", label: "Redis", ok: testResult.redis_ok, msg: testResult.redis_msg },
{ key: "nats", label: "NATS", ok: testResult.nats_ok, msg: testResult.nats_msg }
]);
function blankForm() {
return {
id: 0,
name: "",
code: "",
remark: "",
enabled: true,
ssh_host: "",
ssh_port: 22,
ssh_user: "root",
ssh_private_key: "",
registry: "",
registry_user: "",
registry_pass: "",
docker_network: "1panel-network",
etcd_servers: "",
redis_addr: "",
redis_pwd: "",
nats_url: ""
};
}
const form = reactive(blankForm());
function sshTarget(e) {
if (!e.ssh_host) return "-";
return `${e.ssh_user || "root"}@${e.ssh_host}:${e.ssh_port || 22}`;
}
function imageLabel(e) {
return e.registry || "-";
}
return (_ctx, _push, _parent, _attrs) => {
_push(`<div${ssrRenderAttrs(_attrs)}><div style="${ssrRenderStyle(view.value === "list" ? null : { display: "none" })}"><div class="flex items-center justify-between mb-5"><div><h2 class="text-lg font-semibold text-slate-800">环境节点(部署服务器)</h2><p class="text-sm text-slate-400 mt-1">部署服务器节点(如 上海 / 日本 / 新加坡):远端 IP、SSH 登录账号与私钥、私有镜像仓库、区域共享基础设施。应用管理里「部署到目标环境」从这里选择、两边对应;下一期即可从页面直接更新服务/部署应用。密钥加密存储,不回显明文。</p></div><button class="btn btn-primary btn-sm text-white">+ 新增节点</button></div><div class="bg-white rounded-xl shadow-sm border border-slate-100"><div class="overflow-x-auto"><table class="table table-zebra text-sm"><thead><tr><th>ID</th><th>名称</th><th>区域码</th><th>SSH 目标</th><th>镜像仓库</th><th>启用</th><th>操作</th></tr></thead><tbody>`);
if (loading.value) {
_push(`<tr><td colspan="7" class="text-center py-8"><span class="loading loading-spinner loading-sm"></span></td></tr>`);
} else if (!rows.value.length) {
_push(`<tr><td colspan="7" class="text-center text-slate-400 py-8">暂无环境</td></tr>`);
} else {
_push(`<!---->`);
}
_push(`<!--[-->`);
ssrRenderList(rows.value, (e) => {
_push(`<tr><td class="font-mono">${ssrInterpolate(e.id)}</td><td class="font-medium">${ssrInterpolate(e.name || "")}</td><td>${ssrInterpolate(e.code || "")}</td><td class="font-mono text-xs text-slate-500">${ssrInterpolate(sshTarget(e))}</td><td class="text-xs text-slate-500">${ssrInterpolate(imageLabel(e))}</td><td>`);
if (e.enabled) {
_push(`<span class="text-green-600">是</span>`);
} else {
_push(`<span class="text-slate-400">否</span>`);
}
_push(`</td><td><div class="flex gap-1"><button class="btn btn-ghost btn-xs">编辑</button><button class="btn btn-ghost btn-xs text-red-500">删除</button></div></td></tr>`);
});
_push(`<!--]--></tbody></table></div></div></div><div style="${ssrRenderStyle(view.value === "form" ? null : { display: "none" })}"><div class="flex items-center gap-3 mb-5"><button class="btn btn-ghost btn-sm">← 返回</button><h2 class="text-lg font-semibold text-slate-800">${ssrInterpolate(isEditing.value ? "编辑节点" : "新增节点")}</h2></div><div class="bg-white rounded-xl shadow-sm border border-slate-100 p-6 max-w-3xl"><form><div class="grid grid-cols-2 gap-4"><div class="form-control"><label class="label"><span class="label-text font-medium">名称 *</span></label><input${ssrRenderAttr("value", form.name)} type="text" class="input input-bordered w-full" required placeholder="如 上海生产"></div><div class="form-control"><label class="label"><span class="label-text font-medium">区域码</span></label><input${ssrRenderAttr("value", form.code)} type="text" class="input input-bordered w-full" list="env-code-list" placeholder="shanghai / japan / singapore"><datalist id="env-code-list"><option value="shanghai"></option><option value="japan"></option><option value="singapore"></option></datalist></div></div><div class="divider text-xs text-slate-400 mt-6">SSH 部署目标</div><div class="grid grid-cols-3 gap-4"><div class="form-control col-span-2"><label class="label"><span class="label-text font-medium">SSH 主机</span></label><input${ssrRenderAttr("value", form.ssh_host)} type="text" class="input input-bordered w-full" placeholder="139.224.212.237"></div><div class="form-control"><label class="label"><span class="label-text font-medium">端口</span></label><input${ssrRenderAttr("value", form.ssh_port)} type="number" class="input input-bordered w-full" placeholder="22"></div></div><div class="form-control mt-4"><label class="label"><span class="label-text font-medium">SSH 用户</span></label><input${ssrRenderAttr("value", form.ssh_user)} type="text" class="input input-bordered w-full" placeholder="root"></div><div class="form-control mt-4"><label class="label"><span class="label-text font-medium">SSH 私钥 (PEM)</span></label><textarea class="textarea textarea-bordered w-full font-mono text-xs h-28" placeholder="-----BEGIN OPENSSH PRIVATE KEY-----">${ssrInterpolate(form.ssh_private_key)}</textarea><span class="text-xs text-slate-400 mt-1">加密存储;编辑时显示 [encrypted] 表示不改,如需更换直接粘贴新私钥。</span></div><div class="divider text-xs text-slate-400 mt-6">私有镜像仓库 + Docker 网络</div><div class="grid grid-cols-2 gap-4"><div class="form-control"><label class="label"><span class="label-text font-medium">仓库地址</span></label><input${ssrRenderAttr("value", form.registry)} type="text" class="input input-bordered w-full" placeholder="docker-registry.ideapsound.com"></div><div class="form-control"><label class="label"><span class="label-text font-medium">Docker 网络</span></label><input${ssrRenderAttr("value", form.docker_network)} type="text" class="input input-bordered w-full" placeholder="1panel-network"></div><div class="form-control"><label class="label"><span class="label-text font-medium">仓库账号</span></label><input${ssrRenderAttr("value", form.registry_user)} type="text" class="input input-bordered w-full" autocomplete="off"></div><div class="form-control"><label class="label"><span class="label-text font-medium">仓库密码</span></label><input${ssrRenderAttr("value", form.registry_pass)} type="password" class="input input-bordered w-full" autocomplete="new-password" placeholder="[encrypted]"></div></div><div class="divider text-xs text-slate-400 mt-6">节点共享集群服务</div><p class="text-xs text-slate-400 -mt-2 mb-2">该服务器上各应用共用的地址。各应用自己的部署目录、业务库 DSN、镜像、redis 库号等,在「应用管理 → 部署到目标环境」里按应用填。</p><div class="grid grid-cols-2 gap-4"><div class="form-control"><label class="label"><span class="label-text font-medium">ETCD</span></label><input${ssrRenderAttr("value", form.etcd_servers)} type="text" class="input input-bordered w-full font-mono text-xs" placeholder="etcd:2379"></div><div class="form-control"><label class="label"><span class="label-text font-medium">NATS</span></label><input${ssrRenderAttr("value", form.nats_url)} type="text" class="input input-bordered w-full font-mono text-xs" placeholder="nats://nats:4222"></div></div><div class="grid grid-cols-2 gap-4 mt-4"><div class="form-control"><label class="label"><span class="label-text font-medium">Redis 地址</span></label><input${ssrRenderAttr("value", form.redis_addr)} type="text" class="input input-bordered w-full font-mono text-xs" placeholder="redis:6379"></div><div class="form-control"><label class="label"><span class="label-text font-medium">Redis 密码</span></label><input${ssrRenderAttr("value", form.redis_pwd)} type="password" class="input input-bordered w-full" autocomplete="new-password" placeholder="[encrypted]"></div></div><div class="form-control mt-4"><label class="label"><span class="label-text font-medium">备注</span></label><input${ssrRenderAttr("value", form.remark)} type="text" class="input input-bordered w-full"></div><div class="flex items-center gap-2 mt-4"><label class="flex items-center gap-2 cursor-pointer"><input${ssrIncludeBooleanAttr(Array.isArray(form.enabled) ? ssrLooseContain(form.enabled, null) : form.enabled) ? " checked" : ""} type="checkbox" class="toggle toggle-primary toggle-sm"><span class="text-sm">启用</span></label></div><div class="mt-4 text-sm space-y-0.5" style="${ssrRenderStyle(testResult.show ? null : { display: "none" })}"><!--[-->`);
ssrRenderList(testItems.value, (it) => {
_push(`<div class="${ssrRenderClass(it.ok ? "text-green-700" : "text-red-600")}"><span class="${ssrRenderClass(it.ok ? "text-green-600" : "text-red-500")}">${ssrInterpolate(it.ok ? "✓" : "✗")}</span> ${ssrInterpolate(it.label)}:${ssrInterpolate(it.msg)}</div>`);
});
_push(`<!--]--></div><div class="flex gap-3 mt-6"><button type="button" class="btn btn-ghost">取消</button><button type="button" class="btn btn-outline"${ssrIncludeBooleanAttr(testing.value) ? " disabled" : ""}>${ssrInterpolate(testing.value ? "测试中..." : "测试连接")}</button><button type="submit" class="btn btn-primary text-white"${ssrIncludeBooleanAttr(!testPassed.value) ? " disabled" : ""}>保存</button></div><p class="text-xs text-slate-400 mt-2">需先「测试连接」(SSH 握手成功即可保存;基础设施逐项仅作提示)。</p></form></div></div></div>`);
};
}
});
const _sfc_setup = _sfc_main.setup;
_sfc_main.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/environments.vue");
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
};
export { _sfc_main as default };
//# sourceMappingURL=environments-DOoKTF6a.mjs.map