mirror of https://github.com/certd/certd
chore: suite first
parent
64319937a1
commit
8057586dc1
|
@ -0,0 +1,10 @@
|
||||||
|
# 证书申请失败情况
|
||||||
|
|
||||||
|
|
||||||
|
## DNS记录问题
|
||||||
|
|
||||||
|
1. DNS 不要设置CAA记录,删除即可
|
||||||
|
|
||||||
|
2. DNSSEC相关报错,DNSSEC管理中删除即可
|
||||||
|
|
||||||
|
3. DNS 有其他平台申请过的_acme-challenge记录,删除即可
|
|
@ -1,5 +1,4 @@
|
||||||
import { SysSettingsEntity } from './system/index.js';
|
import { SysSettingsEntity } from './system/index.js';
|
||||||
|
|
||||||
export * from './basic/index.js';
|
export * from './basic/index.js';
|
||||||
export * from './system/index.js';
|
export * from './system/index.js';
|
||||||
export { LibServerConfiguration as Configuration } from './configuration.js';
|
export { LibServerConfiguration as Configuration } from './configuration.js';
|
||||||
|
|
|
@ -169,6 +169,48 @@ export const sysResources = [
|
||||||
icon: "ion:person-outline",
|
icon: "ion:person-outline",
|
||||||
permission: "sys:auth:user:view"
|
permission: "sys:auth:user:view"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "套餐支付",
|
||||||
|
name: "SuiteManager",
|
||||||
|
path: "/sys/suite",
|
||||||
|
redirect: "/sys/suite/product",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:golf-outline",
|
||||||
|
permission: "sys:settings:view"
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "套餐管理",
|
||||||
|
name: "ProductManager",
|
||||||
|
path: "/sys/suite/product",
|
||||||
|
component: "/sys/suite/product/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:person-outline",
|
||||||
|
permission: "sys:settings:edit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "支付管理",
|
||||||
|
name: "PaymentManager",
|
||||||
|
path: "/sys/suite/payment",
|
||||||
|
component: "/sys/suite/payment/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:person-outline",
|
||||||
|
permission: "sys:settings:edit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "订单管理",
|
||||||
|
name: "OrderManager",
|
||||||
|
path: "/sys/suite/order",
|
||||||
|
component: "/sys/suite/order/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:person-outline",
|
||||||
|
permission: "sys:settings:edit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
// {
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/sys/suite/order";
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetDetail(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/detail",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteBatch(ids: any[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/deleteByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDefault(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDefault",
|
||||||
|
method: "post",
|
||||||
|
data: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDisabled(id: any, disabled: boolean) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDisabled",
|
||||||
|
method: "post",
|
||||||
|
data: { id, disabled }
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,254 @@
|
||||||
|
import * as api from "./api";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { computed, Ref, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||||
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
form.content = JSON.stringify({
|
||||||
|
title: form.title
|
||||||
|
});
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||||
|
context.selectedRowKeys = selectedRowKeys;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
order: -2,
|
||||||
|
before: true,
|
||||||
|
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: true,
|
||||||
|
selectedRowKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
minWidth: 200,
|
||||||
|
fixed: "right"
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
title: "CNAME域名",
|
||||||
|
type: "text",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
placeholder: "cname.handsfree.work"
|
||||||
|
},
|
||||||
|
helper: "需要一个右边DNS提供商注册的域名(也可以将其他域名的dns服务器转移到这几家来)。\nCNAME域名一旦确定不可修改,建议使用一级子域名",
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dnsProviderType: {
|
||||||
|
title: "DNS提供商",
|
||||||
|
type: "dict-select",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
url: "pi/dnsProvider/list",
|
||||||
|
value: "key",
|
||||||
|
label: "title"
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
accessId: {
|
||||||
|
title: "DNS提供商授权",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
url: "/pi/access/list",
|
||||||
|
value: "id",
|
||||||
|
label: "name"
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: "access-selector",
|
||||||
|
vModel: "modelValue",
|
||||||
|
type: compute(({ form }) => {
|
||||||
|
return form.dnsProviderType;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDefault: {
|
||||||
|
title: "是否默认",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "是", value: true, color: "success" },
|
||||||
|
{ label: "否", value: false, color: "default" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
rules: [{ required: true, message: "请选择是否默认" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
align: "center",
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setDefault: {
|
||||||
|
title: "设置默认",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
conditionalRenderDisabled: true,
|
||||||
|
cellRender: ({ row }) => {
|
||||||
|
if (row.isDefault) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const onClick = async () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "提示",
|
||||||
|
content: `确定要设置为默认吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDefault(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a-button type={"link"} size={"small"} onClick={onClick}>
|
||||||
|
设为默认
|
||||||
|
</a-button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
title: "禁用/启用",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "启用", value: false, color: "success" },
|
||||||
|
{ label: "禁用", value: true, color: "error" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
title: "点击可禁用/启用",
|
||||||
|
on: {
|
||||||
|
async click({ value, row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "提示",
|
||||||
|
content: `确定要${!value ? "禁用" : "启用"}吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDisabled(row.id, !value);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
title: "创建时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
width: 160,
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTime: {
|
||||||
|
title: "更新时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
width: 160
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<template>
|
||||||
|
<fs-page class="page-cert">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
CNAME服务配置
|
||||||
|
<span class="sub">
|
||||||
|
此处配置的域名作为其他域名校验的代理,当别的域名需要申请证书时,通过CNAME映射到此域名上来验证所有权。好处是任何域名都可以通过此方式申请证书,也无需填写AccessSecret。
|
||||||
|
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">CNAME功能原理及使用说明</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip title="批量删除">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { DeleteBatch } from "./api";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CnameProvider"
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
const selectedRowKeys = context.selectedRowKeys;
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||||
|
async onOk() {
|
||||||
|
await DeleteBatch(selectedRowKeys.value);
|
||||||
|
message.info("删除成功");
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error("请先勾选记录");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
export function createPaymentApi() {
|
||||||
|
const apiPrefix = "/sys/suite/payment";
|
||||||
|
return {
|
||||||
|
async GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async DelObj(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetObj(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetOptions(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/options",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetSimpleInfo(id: number) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/simpleInfo",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetDefineTypes() {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/getTypeDict",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async GetProviderDefine(type: string) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/define",
|
||||||
|
method: "post",
|
||||||
|
params: { type }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
import { ColumnCompositionProps, compute, dict } from "@fast-crud/fast-crud";
|
||||||
|
import { computed, provide, ref, toRef } from "vue";
|
||||||
|
import { useReference } from "/@/use/use-refrence";
|
||||||
|
import { forEach, get, merge, set } from "lodash-es";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
import * as api from "/@/views/sys/cname/provider/api";
|
||||||
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
|
|
||||||
|
export function getCommonColumnDefine(crudExpose: any, typeRef: any, api: any) {
|
||||||
|
const notificationTypeDictRef = dict({
|
||||||
|
url: "/sys/suite/payment/getList"
|
||||||
|
});
|
||||||
|
const defaultPluginConfig = {
|
||||||
|
component: {
|
||||||
|
name: "a-input",
|
||||||
|
vModel: "value"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildDefineFields(define: any, form: any, mode: string) {
|
||||||
|
const formWrapperRef = crudExpose.getFormWrapperRef();
|
||||||
|
const columnsRef = toRef(formWrapperRef.formOptions, "columns");
|
||||||
|
|
||||||
|
for (const key in columnsRef.value) {
|
||||||
|
if (key.indexOf(".") >= 0) {
|
||||||
|
delete columnsRef.value[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('crudBinding.value[mode + "Form"].columns', columnsRef.value);
|
||||||
|
forEach(define.input, (value: any, mapKey: any) => {
|
||||||
|
const key = "body." + mapKey;
|
||||||
|
const field = {
|
||||||
|
...value,
|
||||||
|
key
|
||||||
|
};
|
||||||
|
const column = merge({ title: key }, defaultPluginConfig, field);
|
||||||
|
//eval
|
||||||
|
useReference(column);
|
||||||
|
|
||||||
|
if (column.required) {
|
||||||
|
if (!column.rules) {
|
||||||
|
column.rules = [];
|
||||||
|
}
|
||||||
|
column.rules.push({ required: true, message: "此项必填" });
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置默认值
|
||||||
|
if (column.value != null && get(form, key) == null) {
|
||||||
|
set(form, key, column.value);
|
||||||
|
}
|
||||||
|
//字段配置赋值
|
||||||
|
columnsRef.value[key] = column;
|
||||||
|
console.log("form", columnsRef.value, form);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentDefine = ref();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
title: "支付类型",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: notificationTypeDictRef,
|
||||||
|
search: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
disabled: false,
|
||||||
|
showSearch: true,
|
||||||
|
filterOption: (input: string, option: any) => {
|
||||||
|
input = input?.toLowerCase();
|
||||||
|
return option.value.toLowerCase().indexOf(input) >= 0 || option.label.toLowerCase().indexOf(input) >= 0;
|
||||||
|
},
|
||||||
|
renderLabel(item: any) {
|
||||||
|
return (
|
||||||
|
<span class={"flex-o flex-between"}>
|
||||||
|
{item.label}
|
||||||
|
{item.needPlus && <fs-icon icon={"mingcute:vip-1-line"} className={"color-plus"}></fs-icon>}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "请选择通知类型" }],
|
||||||
|
valueChange: {
|
||||||
|
immediate: true,
|
||||||
|
async handle({ value, mode, form, immediate }) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lastTitle = currentDefine.value?.title;
|
||||||
|
const define = await api.GetProviderDefine(value);
|
||||||
|
currentDefine.value = define;
|
||||||
|
console.log("define", define);
|
||||||
|
|
||||||
|
if (!immediate) {
|
||||||
|
form.body = {};
|
||||||
|
if (define.needPlus) {
|
||||||
|
mitter.emit("openVipModal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!form.name || form.name === lastTitle) {
|
||||||
|
form.name = define.title;
|
||||||
|
}
|
||||||
|
buildDefineFields(define, form, mode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
helper: computed(() => {
|
||||||
|
const define = currentDefine.value;
|
||||||
|
if (define == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return define.desc;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} as ColumnCompositionProps,
|
||||||
|
name: {
|
||||||
|
title: "通知名称",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
type: ["text"],
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "请填写名称" }],
|
||||||
|
helper: "随便填,当多个相同类型的通知时,便于区分"
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
title: "测试",
|
||||||
|
form: {
|
||||||
|
show: compute(({ form }) => {
|
||||||
|
return !!form.type;
|
||||||
|
}),
|
||||||
|
component: {
|
||||||
|
name: "api-test",
|
||||||
|
action: "TestRequest"
|
||||||
|
},
|
||||||
|
order: 990,
|
||||||
|
col: {
|
||||||
|
span: 24
|
||||||
|
}
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setting: {
|
||||||
|
column: { show: false },
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
valueBuilder({ value, form }) {
|
||||||
|
form.body = {};
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const setting = JSON.parse(value);
|
||||||
|
for (const key in setting) {
|
||||||
|
form.body[key] = setting[key];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueResolve({ form }) {
|
||||||
|
const setting = form.body;
|
||||||
|
form.setting = JSON.stringify(setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as ColumnCompositionProps
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { getCommonColumnDefine } from "./common";
|
||||||
|
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||||
|
import { createNotificationApi } from "/@/views/certd/notification/api";
|
||||||
|
const api = createNotificationApi();
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async (req: EditReq) => {
|
||||||
|
const { form, row } = req;
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async (req: DelReq) => {
|
||||||
|
const { row } = req;
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async (req: AddReq) => {
|
||||||
|
const { form } = req;
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeRef = ref();
|
||||||
|
const commonColumnsDefine = getCommonColumnDefine(crudExpose, typeRef, api);
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
labelCol: {
|
||||||
|
//固定label宽度
|
||||||
|
span: null,
|
||||||
|
style: {
|
||||||
|
width: "145px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
...commonColumnsDefine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<fs-page>
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
支付方式管理
|
||||||
|
<span class="sub">管理支付方式</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onActivated, onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { createPaymentApi } from "./api";
|
||||||
|
import { notificationProvide } from "/@/views/certd/notification/common";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PaymentManager",
|
||||||
|
setup() {
|
||||||
|
const api = createPaymentApi();
|
||||||
|
notificationProvide(api);
|
||||||
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { api } });
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
onActivated(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudBinding,
|
||||||
|
crudRef
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,163 @@
|
||||||
|
<template>
|
||||||
|
<div class="notification-selector">
|
||||||
|
<div class="flex-o w-100">
|
||||||
|
<fs-dict-select
|
||||||
|
class="flex-1"
|
||||||
|
:value="modelValue"
|
||||||
|
:dict="optionsDictRef"
|
||||||
|
:disabled="disabled"
|
||||||
|
:render-label="renderLabel"
|
||||||
|
:slots="selectSlots"
|
||||||
|
:allow-clear="true"
|
||||||
|
@update:value="onChange"
|
||||||
|
/>
|
||||||
|
<fs-table-select
|
||||||
|
ref="tableSelectRef"
|
||||||
|
class="flex-0"
|
||||||
|
:model-value="modelValue"
|
||||||
|
:dict="optionsDictRef"
|
||||||
|
:create-crud-options="createCrudOptions"
|
||||||
|
:crud-options-override="{
|
||||||
|
search: { show: false },
|
||||||
|
table: {
|
||||||
|
scroll: {
|
||||||
|
x: 540
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
:show-current="false"
|
||||||
|
:show-select="false"
|
||||||
|
:dialog="{ width: 960 }"
|
||||||
|
:destroy-on-close="false"
|
||||||
|
height="400px"
|
||||||
|
@update:model-value="onChange"
|
||||||
|
@dialog-closed="doRefresh"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<fs-button class="ml-5" :disabled="disabled" :size="size" type="primary" icon="ant-design:edit-outlined" @click="scope.open"></fs-button>
|
||||||
|
</template>
|
||||||
|
</fs-table-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import { inject, ref, Ref, watch } from "vue";
|
||||||
|
import { createNotificationApi } from "../api";
|
||||||
|
import { message } from "ant-design-vue";
|
||||||
|
import { dict } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "../crud";
|
||||||
|
import { notificationProvide } from "/@/views/certd/notification/common";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "NotificationSelector"
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue?: number | string;
|
||||||
|
type?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
size?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onChange = async (value: number) => {
|
||||||
|
await emitValue(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:modelValue", "selectedChange", "change"]);
|
||||||
|
|
||||||
|
const api = createNotificationApi();
|
||||||
|
notificationProvide(api);
|
||||||
|
// const types = ref({});
|
||||||
|
// async function loadNotificationTypes() {
|
||||||
|
// const types = await api.GetDefineTypes();
|
||||||
|
// const map: any = {};
|
||||||
|
// for (const item of types) {
|
||||||
|
// map[item.type] = item;
|
||||||
|
// }
|
||||||
|
// types.value = map;
|
||||||
|
// }
|
||||||
|
// loadNotificationTypes();
|
||||||
|
const tableSelectRef = ref();
|
||||||
|
const optionsDictRef = dict({
|
||||||
|
url: "/pi/notification/options",
|
||||||
|
value: "id",
|
||||||
|
label: "name",
|
||||||
|
onReady: ({ dict }) => {
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "使用默认通知",
|
||||||
|
icon: "ion:notifications"
|
||||||
|
},
|
||||||
|
...dict.data
|
||||||
|
];
|
||||||
|
dict.setData(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const renderLabel = (option: any) => {
|
||||||
|
return <span>{option.name}</span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function openTableSelectDialog(e: any) {
|
||||||
|
e.preventDefault();
|
||||||
|
await tableSelectRef.value.open();
|
||||||
|
await tableSelectRef.value.crudExpose.openAdd({});
|
||||||
|
}
|
||||||
|
const selectSlots = ref({
|
||||||
|
dropdownRender({ menuNode }: any) {
|
||||||
|
const res = [];
|
||||||
|
res.push(menuNode);
|
||||||
|
res.push(<a-divider style="margin: 4px 0" />);
|
||||||
|
res.push(<a-space style="padding: 4px 8px" />);
|
||||||
|
res.push(<fs-button class="w-100" type="text" icon="plus-outlined" text="新建通知渠道" onClick={openTableSelectDialog}></fs-button>);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const target: Ref<any> = ref({});
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function emitValue(value: any) {
|
||||||
|
target.value = optionsDictRef.dataMap[value];
|
||||||
|
if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) {
|
||||||
|
message.error("对不起,您不能修改他人流水线的通知");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit("change", value);
|
||||||
|
emit("update:modelValue", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => {
|
||||||
|
return props.modelValue;
|
||||||
|
},
|
||||||
|
async (value) => {
|
||||||
|
await optionsDictRef.loadDict();
|
||||||
|
target.value = optionsDictRef.dataMap[value];
|
||||||
|
emit("selectedChange", target.value);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//当不在pipeline中编辑时,可能为空
|
||||||
|
const pipeline = inject("pipeline", null);
|
||||||
|
|
||||||
|
async function doRefresh() {
|
||||||
|
await optionsDictRef.reloadDict();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.notification-selector {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/sys/suite/product";
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetDetail(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/detail",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteBatch(ids: any[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/deleteByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDefault(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDefault",
|
||||||
|
method: "post",
|
||||||
|
data: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDisabled(id: any, disabled: boolean) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDisabled",
|
||||||
|
method: "post",
|
||||||
|
data: { id, disabled }
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,195 @@
|
||||||
|
import * as api from "./api";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { computed, Ref, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||||
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
form.content = JSON.stringify({
|
||||||
|
title: form.title
|
||||||
|
});
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||||
|
context.selectedRowKeys = selectedRowKeys;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
order: -2,
|
||||||
|
before: true,
|
||||||
|
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: true,
|
||||||
|
selectedRowKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
minWidth: 200,
|
||||||
|
fixed: "right"
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
title: "套餐名称",
|
||||||
|
type: "text",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
title: "类型",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "套餐", value: "suite" },
|
||||||
|
{ label: "加量包", value: "addon" }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
maxDomainCount: {
|
||||||
|
title: "域名数量",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
maxPipelineCount: {
|
||||||
|
title: "流水线数量",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
maxDeployCount: {
|
||||||
|
title: "部署次数",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
title: "单价",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
originPrice: {
|
||||||
|
title: "原价",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
title: "有效时长",
|
||||||
|
type: "number"
|
||||||
|
},
|
||||||
|
intro: {
|
||||||
|
title: "说明",
|
||||||
|
type: "textarea"
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
title: "排序",
|
||||||
|
type: "number",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
title: "禁用/启用",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "启用", value: false, color: "success" },
|
||||||
|
{ label: "禁用", value: true, color: "error" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
title: "点击可禁用/启用",
|
||||||
|
on: {
|
||||||
|
async click({ value, row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "提示",
|
||||||
|
content: `确定要${!value ? "禁用" : "启用"}吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDisabled(row.id, !value);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
title: "创建时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
width: 160,
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTime: {
|
||||||
|
title: "更新时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
width: 160
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<template>
|
||||||
|
<fs-page class="page-cert">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
CNAME服务配置
|
||||||
|
<span class="sub">
|
||||||
|
此处配置的域名作为其他域名校验的代理,当别的域名需要申请证书时,通过CNAME映射到此域名上来验证所有权。好处是任何域名都可以通过此方式申请证书,也无需填写AccessSecret。
|
||||||
|
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">CNAME功能原理及使用说明</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip title="批量删除">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { DeleteBatch } from "./api";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CnameProvider"
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
const selectedRowKeys = context.selectedRowKeys;
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||||
|
async onOk() {
|
||||||
|
await DeleteBatch(selectedRowKeys.value);
|
||||||
|
message.info("删除成功");
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error("请先勾选记录");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/sys/suite/userSuite";
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetDetail(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/detail",
|
||||||
|
method: "post",
|
||||||
|
params: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteBatch(ids: any[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/deleteByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDefault(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDefault",
|
||||||
|
method: "post",
|
||||||
|
data: { id }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDisabled(id: any, disabled: boolean) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDisabled",
|
||||||
|
method: "post",
|
||||||
|
data: { id, disabled }
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,254 @@
|
||||||
|
import * as api from "./api";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { computed, Ref, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||||
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
form.content = JSON.stringify({
|
||||||
|
title: form.title
|
||||||
|
});
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||||
|
context.selectedRowKeys = selectedRowKeys;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
order: -2,
|
||||||
|
before: true,
|
||||||
|
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: true,
|
||||||
|
selectedRowKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
minWidth: 200,
|
||||||
|
fixed: "right"
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
title: "CNAME域名",
|
||||||
|
type: "text",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
placeholder: "cname.handsfree.work"
|
||||||
|
},
|
||||||
|
helper: "需要一个右边DNS提供商注册的域名(也可以将其他域名的dns服务器转移到这几家来)。\nCNAME域名一旦确定不可修改,建议使用一级子域名",
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dnsProviderType: {
|
||||||
|
title: "DNS提供商",
|
||||||
|
type: "dict-select",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
url: "pi/dnsProvider/list",
|
||||||
|
value: "key",
|
||||||
|
label: "title"
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
accessId: {
|
||||||
|
title: "DNS提供商授权",
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
url: "/pi/access/list",
|
||||||
|
value: "id",
|
||||||
|
label: "name"
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
name: "access-selector",
|
||||||
|
vModel: "modelValue",
|
||||||
|
type: compute(({ form }) => {
|
||||||
|
return form.dnsProviderType;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isDefault: {
|
||||||
|
title: "是否默认",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "是", value: true, color: "success" },
|
||||||
|
{ label: "否", value: false, color: "default" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
rules: [{ required: true, message: "请选择是否默认" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
align: "center",
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setDefault: {
|
||||||
|
title: "设置默认",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
conditionalRenderDisabled: true,
|
||||||
|
cellRender: ({ row }) => {
|
||||||
|
if (row.isDefault) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const onClick = async () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "提示",
|
||||||
|
content: `确定要设置为默认吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDefault(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a-button type={"link"} size={"small"} onClick={onClick}>
|
||||||
|
设为默认
|
||||||
|
</a-button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
title: "禁用/启用",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "启用", value: false, color: "success" },
|
||||||
|
{ label: "禁用", value: true, color: "error" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
title: "点击可禁用/启用",
|
||||||
|
on: {
|
||||||
|
async click({ value, row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "提示",
|
||||||
|
content: `确定要${!value ? "禁用" : "启用"}吗?`,
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDisabled(row.id, !value);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
title: "创建时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
width: 160,
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTime: {
|
||||||
|
title: "更新时间",
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
width: 160
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<template>
|
||||||
|
<fs-page class="page-cert">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
CNAME服务配置
|
||||||
|
<span class="sub">
|
||||||
|
此处配置的域名作为其他域名校验的代理,当别的域名需要申请证书时,通过CNAME映射到此域名上来验证所有权。好处是任何域名都可以通过此方式申请证书,也无需填写AccessSecret。
|
||||||
|
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">CNAME功能原理及使用说明</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip title="批量删除">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { DeleteBatch } from "./api";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CnameProvider"
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
const selectedRowKeys = context.selectedRowKeys;
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: `确定要批量删除这${selectedRowKeys.value.length}条记录吗`,
|
||||||
|
async onOk() {
|
||||||
|
await DeleteBatch(selectedRowKeys.value);
|
||||||
|
message.info("删除成功");
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error("请先勾选记录");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
|
@ -0,0 +1,77 @@
|
||||||
|
CREATE TABLE "cd_product"
|
||||||
|
(
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"icon" varchar(100),
|
||||||
|
"title" varchar(100),
|
||||||
|
"type" varchar(100),
|
||||||
|
"max_domain_count" integer,
|
||||||
|
"max_pipeline_count" integer,
|
||||||
|
"max_deploy_count" integer,
|
||||||
|
"deploy_count_period" varchar(100),
|
||||||
|
"site_monitor" boolean,
|
||||||
|
"expires_time" integer,
|
||||||
|
"price" integer,
|
||||||
|
"origin_price" integer,
|
||||||
|
"intro" varchar(2048),
|
||||||
|
"order" integer,
|
||||||
|
"disabled" boolean NOT NULL DEFAULT (false),
|
||||||
|
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE "cd_payment"
|
||||||
|
(
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"type" varchar(100),
|
||||||
|
"title" varchar(100),
|
||||||
|
"setting" text,
|
||||||
|
"order" integer,
|
||||||
|
"disabled" boolean NOT NULL DEFAULT (false),
|
||||||
|
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE "cd_order"
|
||||||
|
(
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"user_id" integer,
|
||||||
|
"product_id" integer,
|
||||||
|
"title" varchar(100),
|
||||||
|
"count" integer,
|
||||||
|
"price" integer,
|
||||||
|
"amount" integer,
|
||||||
|
"remark" varchar(100),
|
||||||
|
"status" varchar(100),
|
||||||
|
"pay_id" integer,
|
||||||
|
"pay_time" integer,
|
||||||
|
"pay_type" varchar(100),
|
||||||
|
"pay_no" varchar(100),
|
||||||
|
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE "cd_user_suite"
|
||||||
|
(
|
||||||
|
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
"user_id" integer,
|
||||||
|
"product_id" integer,
|
||||||
|
"icon" varchar(100),
|
||||||
|
"title" varchar(100),
|
||||||
|
"max_domain_count" integer,
|
||||||
|
"max_pipeline_count" integer,
|
||||||
|
"max_deploy_count" integer,
|
||||||
|
"used_deploy_count" integer,
|
||||||
|
"site_monitor" boolean,
|
||||||
|
"expires_time" integer,
|
||||||
|
"disabled" boolean NOT NULL DEFAULT (false),
|
||||||
|
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||||
|
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -208,31 +208,37 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||||
const handle = async ({ reader, tmpCrtPath, tmpKeyPath, tmpDerPath, tmpPfxPath, tmpIcPath, tmpJksPath }) => {
|
const handle = async ({ reader, tmpCrtPath, tmpKeyPath, tmpDerPath, tmpPfxPath, tmpIcPath, tmpJksPath }) => {
|
||||||
this.logger.info('复制到目标路径');
|
this.logger.info('复制到目标路径');
|
||||||
if (crtPath) {
|
if (crtPath) {
|
||||||
|
crtPath = crtPath.trim();
|
||||||
crtPath = crtPath.startsWith('/') ? crtPath : path.join(Constants.dataDir, crtPath);
|
crtPath = crtPath.startsWith('/') ? crtPath : path.join(Constants.dataDir, crtPath);
|
||||||
this.copyFile(tmpCrtPath, crtPath);
|
this.copyFile(tmpCrtPath, crtPath);
|
||||||
this.hostCrtPath = crtPath;
|
this.hostCrtPath = crtPath;
|
||||||
}
|
}
|
||||||
if (keyPath) {
|
if (keyPath) {
|
||||||
|
keyPath = keyPath.trim();
|
||||||
keyPath = keyPath.startsWith('/') ? keyPath : path.join(Constants.dataDir, keyPath);
|
keyPath = keyPath.startsWith('/') ? keyPath : path.join(Constants.dataDir, keyPath);
|
||||||
this.copyFile(tmpKeyPath, keyPath);
|
this.copyFile(tmpKeyPath, keyPath);
|
||||||
this.hostKeyPath = keyPath;
|
this.hostKeyPath = keyPath;
|
||||||
}
|
}
|
||||||
if (icPath) {
|
if (icPath) {
|
||||||
|
icPath = icPath.trim();
|
||||||
icPath = icPath.startsWith('/') ? icPath : path.join(Constants.dataDir, icPath);
|
icPath = icPath.startsWith('/') ? icPath : path.join(Constants.dataDir, icPath);
|
||||||
this.copyFile(tmpIcPath, icPath);
|
this.copyFile(tmpIcPath, icPath);
|
||||||
this.hostIcPath = icPath;
|
this.hostIcPath = icPath;
|
||||||
}
|
}
|
||||||
if (pfxPath) {
|
if (pfxPath) {
|
||||||
|
pfxPath = icPath.trim();
|
||||||
pfxPath = pfxPath.startsWith('/') ? pfxPath : path.join(Constants.dataDir, pfxPath);
|
pfxPath = pfxPath.startsWith('/') ? pfxPath : path.join(Constants.dataDir, pfxPath);
|
||||||
this.copyFile(tmpPfxPath, pfxPath);
|
this.copyFile(tmpPfxPath, pfxPath);
|
||||||
this.hostPfxPath = pfxPath;
|
this.hostPfxPath = pfxPath;
|
||||||
}
|
}
|
||||||
if (derPath) {
|
if (derPath) {
|
||||||
|
derPath = derPath.trim();
|
||||||
derPath = derPath.startsWith('/') ? derPath : path.join(Constants.dataDir, derPath);
|
derPath = derPath.startsWith('/') ? derPath : path.join(Constants.dataDir, derPath);
|
||||||
this.copyFile(tmpDerPath, derPath);
|
this.copyFile(tmpDerPath, derPath);
|
||||||
this.hostDerPath = derPath;
|
this.hostDerPath = derPath;
|
||||||
}
|
}
|
||||||
if (jksPath) {
|
if (jksPath) {
|
||||||
|
jksPath = jksPath.trim();
|
||||||
jksPath = jksPath.startsWith('/') ? jksPath : path.join(Constants.dataDir, jksPath);
|
jksPath = jksPath.startsWith('/') ? jksPath : path.join(Constants.dataDir, jksPath);
|
||||||
this.copyFile(tmpJksPath, jksPath);
|
this.copyFile(tmpJksPath, jksPath);
|
||||||
this.hostJksPath = jksPath;
|
this.hostJksPath = jksPath;
|
||||||
|
|
|
@ -239,7 +239,8 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||||
this.logger.info(`复制文件:${srcFile} => ${destFile}`);
|
this.logger.info(`复制文件:${srcFile} => ${destFile}`);
|
||||||
}
|
}
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
const { crtPath, keyPath, cert, accessId } = this;
|
const { cert, accessId } = this;
|
||||||
|
let { crtPath, keyPath, icPath, pfxPath, derPath, jksPath } = this;
|
||||||
const certReader = new CertReader(cert);
|
const certReader = new CertReader(cert);
|
||||||
|
|
||||||
const handle = async (opts: CertReaderHandleContext) => {
|
const handle = async (opts: CertReaderHandleContext) => {
|
||||||
|
@ -269,6 +270,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||||
|
|
||||||
const transports: any = [];
|
const transports: any = [];
|
||||||
if (crtPath) {
|
if (crtPath) {
|
||||||
|
crtPath = crtPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpCrtPath,
|
localPath: tmpCrtPath,
|
||||||
remotePath: crtPath,
|
remotePath: crtPath,
|
||||||
|
@ -276,39 +278,44 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||||
this.logger.info(`上传证书到主机:${crtPath}`);
|
this.logger.info(`上传证书到主机:${crtPath}`);
|
||||||
}
|
}
|
||||||
if (keyPath) {
|
if (keyPath) {
|
||||||
|
keyPath = keyPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpKeyPath,
|
localPath: tmpKeyPath,
|
||||||
remotePath: keyPath,
|
remotePath: keyPath,
|
||||||
});
|
});
|
||||||
this.logger.info(`上传私钥到主机:${keyPath}`);
|
this.logger.info(`上传私钥到主机:${keyPath}`);
|
||||||
}
|
}
|
||||||
if (this.icPath) {
|
if (icPath) {
|
||||||
|
icPath = icPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpIcPath,
|
localPath: tmpIcPath,
|
||||||
remotePath: this.icPath,
|
remotePath: icPath,
|
||||||
});
|
});
|
||||||
this.logger.info(`上传中间证书到主机:${this.icPath}`);
|
this.logger.info(`上传中间证书到主机:${icPath}`);
|
||||||
}
|
}
|
||||||
if (this.pfxPath) {
|
if (pfxPath) {
|
||||||
|
pfxPath = pfxPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpPfxPath,
|
localPath: tmpPfxPath,
|
||||||
remotePath: this.pfxPath,
|
remotePath: pfxPath,
|
||||||
});
|
});
|
||||||
this.logger.info(`上传PFX证书到主机:${this.pfxPath}`);
|
this.logger.info(`上传PFX证书到主机:${pfxPath}`);
|
||||||
}
|
}
|
||||||
if (this.derPath) {
|
if (derPath) {
|
||||||
|
derPath = derPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpDerPath,
|
localPath: tmpDerPath,
|
||||||
remotePath: this.derPath,
|
remotePath: derPath,
|
||||||
});
|
});
|
||||||
this.logger.info(`上传DER证书到主机:${this.derPath}`);
|
this.logger.info(`上传DER证书到主机:${derPath}`);
|
||||||
}
|
}
|
||||||
if (this.jksPath) {
|
if (this.jksPath) {
|
||||||
|
jksPath = jksPath.trim();
|
||||||
transports.push({
|
transports.push({
|
||||||
localPath: tmpJksPath,
|
localPath: tmpJksPath,
|
||||||
remotePath: this.jksPath,
|
remotePath: jksPath,
|
||||||
});
|
});
|
||||||
this.logger.info(`上传jks证书到主机:${this.jksPath}`);
|
this.logger.info(`上传jks证书到主机:${jksPath}`);
|
||||||
}
|
}
|
||||||
this.logger.info('开始上传文件到服务器');
|
this.logger.info('开始上传文件到服务器');
|
||||||
await sshClient.uploadFiles({
|
await sshClient.uploadFiles({
|
||||||
|
@ -320,10 +327,10 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||||
//输出
|
//输出
|
||||||
this.hostCrtPath = crtPath;
|
this.hostCrtPath = crtPath;
|
||||||
this.hostKeyPath = keyPath;
|
this.hostKeyPath = keyPath;
|
||||||
this.hostIcPath = this.icPath;
|
this.hostIcPath = icPath;
|
||||||
this.hostPfxPath = this.pfxPath;
|
this.hostPfxPath = pfxPath;
|
||||||
this.hostDerPath = this.derPath;
|
this.hostDerPath = derPath;
|
||||||
this.hostJksPath = this.jksPath;
|
this.hostJksPath = jksPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
await certReader.readCertFile({
|
await certReader.readCertFile({
|
||||||
|
|
Loading…
Reference in New Issue