mirror of https://github.com/certd/certd
feat: 套餐购买支持易支付、支付宝支付
parent
9c8c7a7812
commit
faa28f88f9
|
@ -144,6 +144,19 @@ export class RunnableCollection {
|
||||||
this.collection = map;
|
this.collection = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static initPipelineRunnableType(pipeline: Pipeline) {
|
||||||
|
pipeline.runnableType = "pipeline";
|
||||||
|
pipeline.stages.forEach((stage) => {
|
||||||
|
stage.runnableType = "stage";
|
||||||
|
stage.tasks.forEach((task) => {
|
||||||
|
task.runnableType = "task";
|
||||||
|
task.steps.forEach((step) => {
|
||||||
|
step.runnableType = "step";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static each<T extends Runnable>(list: T[], exec: (item: Runnable) => void) {
|
static each<T extends Runnable>(list: T[], exec: (item: Runnable) => void) {
|
||||||
list.forEach((item) => {
|
list.forEach((item) => {
|
||||||
exec(item);
|
exec(item);
|
||||||
|
|
|
@ -39,4 +39,12 @@ export abstract class BaseController {
|
||||||
}
|
}
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLoginUser() {
|
||||||
|
const user = this.ctx.user;
|
||||||
|
if (user == null) {
|
||||||
|
throw new Error('Token已过期');
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,7 @@ export abstract class BaseService<T> {
|
||||||
page.limit = 20;
|
page.limit = 20;
|
||||||
}
|
}
|
||||||
const qb = this.buildListQuery(pageReq);
|
const qb = this.buildListQuery(pageReq);
|
||||||
|
|
||||||
qb.offset(page.offset).limit(page.limit);
|
qb.offset(page.offset).limit(page.limit);
|
||||||
const list = await qb.getMany();
|
const list = await qb.getMany();
|
||||||
const total = await qb.getCount();
|
const total = await qb.getCount();
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const uploadTmpFileCacheKey = 'tmpfile_key_';
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class FileService {
|
export class FileService {
|
||||||
async saveFile(userId: number, tmpCacheKey: any, permission: 'public' | 'private') {
|
async saveFile(userId: number, tmpCacheKey: any, permission: 'public' | 'private') {
|
||||||
if (tmpCacheKey.startsWith(`/${permission}`)) {
|
if (tmpCacheKey.startsWith(`/${permission}`)) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { SysInstallInfo, SysLicenseInfo, SysSettingsService } from '../../settin
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PlusService {
|
export class PlusService {
|
||||||
@Inject()
|
@Inject()
|
||||||
sysSettingsService: SysSettingsService;
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as dns from 'node:dns';
|
||||||
* 设置
|
* 设置
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||||
@InjectEntityModel(SysSettingsEntity)
|
@InjectEntityModel(SysSettingsEntity)
|
||||||
repository: Repository<SysSettingsEntity>;
|
repository: Repository<SysSettingsEntity>;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { EncryptService } from './encrypt-service.js';
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AccessService extends BaseService<AccessEntity> {
|
export class AccessService extends BaseService<AccessEntity> {
|
||||||
@InjectEntityModel(AccessEntity)
|
@InjectEntityModel(AccessEntity)
|
||||||
repository: Repository<AccessEntity>;
|
repository: Repository<AccessEntity>;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { SysPrivateSettings, SysSettingsService } from '../../../system/index.js
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class EncryptService {
|
export class EncryptService {
|
||||||
secretKey: Buffer;
|
secretKey: Buffer;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,10 @@ function createService() {
|
||||||
if (response.config.responseType === "blob") {
|
if (response.config.responseType === "blob") {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
//@ts-ignore
|
||||||
|
if (response.config.returnResponse) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
// dataAxios 是 axios 返回数据中的 data
|
// dataAxios 是 axios 返回数据中的 data
|
||||||
const dataAxios = response.data;
|
const dataAxios = response.data;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<span class="cd-expires-time-text">
|
<span class="cd-expires-time-text">
|
||||||
<template v-if="label != null">
|
<component :is="wrapperComp" :color="color">
|
||||||
{{ label }}
|
<template v-if="label != null">
|
||||||
</template>
|
{{ label }}
|
||||||
<template v-else>
|
</template>
|
||||||
<FsTimeHumanize :model-value="value" :use-format-greater="1000000000000" :options="{ units: ['d'] }"></FsTimeHumanize>
|
<template v-else>
|
||||||
</template>
|
<FsTimeHumanize :model-value="value" :use-format-greater="1000000000000" :options="{ units: ['d'] }"></FsTimeHumanize>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -19,8 +21,32 @@ defineOptions({
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
value?: number;
|
value?: number;
|
||||||
|
mode?: "tag" | "text";
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const wrapperComp = computed(() => {
|
||||||
|
if (props.mode === "tag") {
|
||||||
|
return "a-tag";
|
||||||
|
}
|
||||||
|
return "span";
|
||||||
|
});
|
||||||
|
|
||||||
|
const color = computed(() => {
|
||||||
|
if (props.value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (props.value === -1) {
|
||||||
|
return "green";
|
||||||
|
}
|
||||||
|
|
||||||
|
//小于3天 红色
|
||||||
|
if (dayjs().add(3, "day").valueOf() > props.value) {
|
||||||
|
return "red";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "blue";
|
||||||
|
});
|
||||||
|
|
||||||
const label = computed(() => {
|
const label = computed(() => {
|
||||||
if (props.value == null) {
|
if (props.value == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -153,7 +153,7 @@ export default defineComponent({
|
||||||
if (item.value instanceof Array) {
|
if (item.value instanceof Array) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keys.push(item.value.index);
|
keys.push(item.value.path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<a-layout class="fs-framework">
|
<a-layout class="fs-framework">
|
||||||
<a-layout-sider v-model:collapsed="asideCollapsed" :trigger="null" collapsible>
|
<a-layout-sider v-model:collapsed="asideCollapsed" :trigger="null" collapsible :width="210">
|
||||||
<div class="header-logo">
|
<div class="header-logo">
|
||||||
<img :src="siteInfo.logo" />
|
<img :src="siteInfo.logo" />
|
||||||
<span v-if="!asideCollapsed" class="title">{{ siteInfo.title }}</span>
|
<span v-if="!asideCollapsed" class="title">{{ siteInfo.title }}</span>
|
||||||
|
|
|
@ -39,98 +39,146 @@ export const certdResources = [
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "授权管理",
|
title: "证书监控",
|
||||||
name: "AccessManager",
|
|
||||||
path: "/certd/access",
|
|
||||||
component: "/certd/access/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:disc-outline",
|
|
||||||
auth: true,
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "通知设置",
|
|
||||||
name: "NotificationManager",
|
|
||||||
path: "/certd/notification",
|
|
||||||
component: "/certd/notification/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:megaphone-outline",
|
|
||||||
auth: true,
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "CNAME记录管理",
|
|
||||||
name: "CnameRecord",
|
|
||||||
path: "/certd/cname/record",
|
|
||||||
component: "/certd/cname/record/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:link-outline",
|
|
||||||
auth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "流水线分组管理",
|
|
||||||
name: "PipelineGroupManager",
|
|
||||||
path: "/certd/pipeline/group",
|
|
||||||
component: "/certd/pipeline/group/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "mdi:format-list-group",
|
|
||||||
auth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "套餐购买",
|
|
||||||
name: "SuiteProductBuy",
|
|
||||||
path: "/certd/suite/buy",
|
|
||||||
component: "/certd/suite/buy.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "mdi:format-list-group",
|
|
||||||
auth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "我的订单",
|
|
||||||
name: "MyTrade",
|
|
||||||
path: "/certd/trade",
|
|
||||||
component: "/certd/trade/index.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:person-outline",
|
|
||||||
auth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "支付返回",
|
|
||||||
name: "PaymentReturn",
|
|
||||||
path: "/certd/payment/return/:type",
|
|
||||||
component: "/certd/payment/return.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:person-outline",
|
|
||||||
auth: false,
|
|
||||||
isMenu: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "站点证书监控",
|
|
||||||
name: "SiteCertMonitor",
|
name: "SiteCertMonitor",
|
||||||
path: "/certd/monitor/site",
|
path: "/certd/monitor/site",
|
||||||
component: "/certd/monitor/site/index.vue",
|
component: "/certd/monitor/site/index.vue",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:person-outline",
|
icon: "ion:videocam-outline",
|
||||||
auth: true
|
auth: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "证书仓库",
|
title: "设置",
|
||||||
name: "CertStore",
|
name: "MineSetting",
|
||||||
path: "/certd/monitor/cert",
|
path: "/certd/mine",
|
||||||
component: "/certd/monitor/cert/index.vue",
|
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:person-outline",
|
icon: "ion:settings-outline",
|
||||||
auth: true
|
auth: true,
|
||||||
}
|
cache: true
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "CNAME记录管理",
|
||||||
|
name: "CnameRecord",
|
||||||
|
path: "/certd/cname/record",
|
||||||
|
component: "/certd/cname/record/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:link-outline",
|
||||||
|
auth: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "流水线分组管理",
|
||||||
|
name: "PipelineGroupManager",
|
||||||
|
path: "/certd/pipeline/group",
|
||||||
|
component: "/certd/pipeline/group/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "mdi:format-list-group",
|
||||||
|
auth: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "证书仓库",
|
||||||
|
name: "CertStore",
|
||||||
|
path: "/certd/monitor/cert",
|
||||||
|
component: "/certd/monitor/cert/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:shield-checkmark-outline",
|
||||||
|
auth: true,
|
||||||
|
isMenu: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "授权管理",
|
||||||
|
name: "AccessManager",
|
||||||
|
path: "/certd/access",
|
||||||
|
component: "/certd/access/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:disc-outline",
|
||||||
|
auth: true,
|
||||||
|
cache: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "通知设置",
|
||||||
|
name: "NotificationManager",
|
||||||
|
path: "/certd/notification",
|
||||||
|
component: "/certd/notification/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:megaphone-outline",
|
||||||
|
auth: true,
|
||||||
|
cache: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "账号信息",
|
||||||
|
name: "UserProfile",
|
||||||
|
path: "/certd/mine/user-profile",
|
||||||
|
component: "/certd/mine/user-profile.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:person-outline",
|
||||||
|
auth: true,
|
||||||
|
isMenu: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "套餐",
|
||||||
|
name: "SuiteProduct",
|
||||||
|
path: "/certd/suite",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:cart-outline",
|
||||||
|
auth: true
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "我的套餐",
|
||||||
|
name: "MySuite",
|
||||||
|
path: "/certd/suite/mine",
|
||||||
|
component: "/certd/suite/mine/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:gift-outline",
|
||||||
|
auth: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "套餐购买",
|
||||||
|
name: "SuiteProductBuy",
|
||||||
|
path: "/certd/suite/buy",
|
||||||
|
component: "/certd/suite/buy.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:cart-outline",
|
||||||
|
auth: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "我的订单",
|
||||||
|
name: "MyTrade",
|
||||||
|
path: "/certd/trade",
|
||||||
|
component: "/certd/trade/index.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:bag-check-outline",
|
||||||
|
auth: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "支付返回",
|
||||||
|
name: "PaymentReturn",
|
||||||
|
path: "/certd/payment/return/:type",
|
||||||
|
component: "/certd/payment/return.vue",
|
||||||
|
meta: {
|
||||||
|
icon: "ant-design:pay-circle-outlined",
|
||||||
|
auth: false,
|
||||||
|
isMenu: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// title: "邮箱设置",
|
// title: "邮箱设置",
|
||||||
// name: "EmailSetting",
|
// name: "EmailSetting",
|
||||||
|
@ -141,17 +189,6 @@ export const certdResources = [
|
||||||
// auth: true
|
// auth: true
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
{
|
|
||||||
title: "账号信息",
|
|
||||||
name: "UserProfile",
|
|
||||||
path: "/certd/mine/user-profile",
|
|
||||||
component: "/certd/mine/user-profile.vue",
|
|
||||||
meta: {
|
|
||||||
icon: "ion:person-outline",
|
|
||||||
auth: true,
|
|
||||||
isMenu: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -176,7 +176,7 @@ export const sysResources = [
|
||||||
path: "/sys/suite/setting",
|
path: "/sys/suite/setting",
|
||||||
component: "/sys/suite/setting/index.vue",
|
component: "/sys/suite/setting/index.vue",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:person-outline",
|
icon: "ion:cart",
|
||||||
permission: "sys:settings:edit"
|
permission: "sys:settings:edit"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -186,7 +186,7 @@ export const sysResources = [
|
||||||
path: "/sys/suite/trade",
|
path: "/sys/suite/trade",
|
||||||
component: "/sys/suite/trade/index.vue",
|
component: "/sys/suite/trade/index.vue",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:person-outline",
|
icon: "ion:bag-check",
|
||||||
permission: "sys:settings:edit"
|
permission: "sys:settings:edit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ interface ResourceState {
|
||||||
|
|
||||||
export const useResourceStore = defineStore({
|
export const useResourceStore = defineStore({
|
||||||
id: "app.resource",
|
id: "app.resource",
|
||||||
|
//@ts-ignore
|
||||||
state: (): ResourceState => ({
|
state: (): ResourceState => ({
|
||||||
// user info
|
// user info
|
||||||
topMenus: [],
|
topMenus: [],
|
||||||
|
|
|
@ -68,3 +68,11 @@
|
||||||
width: 800px;
|
width: 800px;
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fs-crud-table{
|
||||||
|
.ant-table-body {
|
||||||
|
height: 1000px !important;
|
||||||
|
table {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="access-selector">
|
<div class="access-selector">
|
||||||
<span v-if="modelValue" class="mr-5 cd-flex-inline">
|
<span v-if="modelValue" class="mr-5 cd-flex-inline">
|
||||||
<a-tag class="mr-5" color="green">{{ target.name || modelValue }}</a-tag>
|
<a-tag class="mr-5" color="green">{{ target?.name || modelValue }}</a-tag>
|
||||||
<fs-icon class="cd-icon-button" icon="ion:close-circle-outline" @click="clear"></fs-icon>
|
<fs-icon class="cd-icon-button" icon="ion:close-circle-outline" @click="clear"></fs-icon>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="mlr-5 text-gray">{{ placeholder }}</span>
|
<span v-else class="mlr-5 text-gray">{{ placeholder }}</span>
|
||||||
|
|
|
@ -53,4 +53,6 @@ onMounted(() => {
|
||||||
crudExpose.doRefresh();
|
crudExpose.doRefresh();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less"></style>
|
<style lang="less">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { request } from "/src/api/service";
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
export function createApi() {
|
export function createApi() {
|
||||||
const apiPrefix = "/pi/pipeline/group";
|
const apiPrefix = "/monitor/cert";
|
||||||
return {
|
return {
|
||||||
async GetList(query: any) {
|
async GetList(query: any) {
|
||||||
return await request({
|
return await request({
|
||||||
|
|
|
@ -49,8 +49,16 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
width: 600
|
width: 600
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
actionbar: { show: false },
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
width: 200
|
width: 200,
|
||||||
|
fixed: "right",
|
||||||
|
buttons: {
|
||||||
|
view: { show: false },
|
||||||
|
copy: { show: false },
|
||||||
|
edit: { show: false },
|
||||||
|
remove: { show: false }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
id: {
|
id: {
|
||||||
|
@ -80,8 +88,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 180,
|
||||||
sorter: true
|
sorter: true,
|
||||||
|
component: {
|
||||||
|
name: "fs-values-format"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domains: {
|
domains: {
|
||||||
|
@ -94,8 +105,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
rules: [{ required: true, message: "请输入域名" }]
|
rules: [{ required: true, message: "请输入域名" }]
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 300,
|
width: 350,
|
||||||
sorter: true
|
sorter: true,
|
||||||
|
component: {
|
||||||
|
name: "fs-values-format"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domainCount: {
|
domainCount: {
|
||||||
|
@ -106,19 +120,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 120,
|
width: 120,
|
||||||
sorter: true
|
sorter: true,
|
||||||
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pipelineId: {
|
"pipeline.title": {
|
||||||
title: "已关联流水线",
|
title: "已关联流水线",
|
||||||
search: { show: false },
|
search: { show: false },
|
||||||
type: "text",
|
type: "link",
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 250,
|
||||||
sorter: true
|
sorter: true,
|
||||||
|
component: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
applyTime: {
|
applyTime: {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
证书仓库
|
证书仓库
|
||||||
<span class="sub">管理证书,支持手动上传证书并部署</span>
|
<span class="sub">管理证书,后续将支持手动上传证书并部署</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { request } from "/src/api/service";
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
export function createApi() {
|
export function createApi() {
|
||||||
const apiPrefix = "/pi/pipeline/group";
|
const apiPrefix = "/monitor/site";
|
||||||
return {
|
return {
|
||||||
async GetList(query: any) {
|
async GetList(query: any) {
|
||||||
return await request({
|
return await request({
|
||||||
|
|
|
@ -72,6 +72,34 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
domain: {
|
||||||
|
title: "网站域名",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "请输入域名" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
sorter: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
port: {
|
||||||
|
title: "HTTPS端口",
|
||||||
|
search: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
type: "number",
|
||||||
|
form: {
|
||||||
|
value: 443,
|
||||||
|
rules: [{ required: true, message: "请输入端口" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
name: {
|
name: {
|
||||||
title: "站点名称",
|
title: "站点名称",
|
||||||
search: {
|
search: {
|
||||||
|
@ -82,35 +110,22 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
rules: [{ required: true, message: "请输入站点名称" }]
|
rules: [{ required: true, message: "请输入站点名称" }]
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100
|
width: 200
|
||||||
}
|
|
||||||
},
|
|
||||||
domain: {
|
|
||||||
title: "主域名",
|
|
||||||
search: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
type: "text",
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, message: "请输入域名" }]
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
width: 100,
|
|
||||||
sorter: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domains: {
|
domains: {
|
||||||
title: "其他域名",
|
title: "其他域名",
|
||||||
search: {
|
search: {
|
||||||
show: true
|
show: false
|
||||||
},
|
},
|
||||||
type: "text",
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
rules: [{ required: true, message: "请输入其他域名" }]
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 300,
|
width: 300,
|
||||||
sorter: true
|
sorter: true,
|
||||||
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
certInfo: {
|
certInfo: {
|
||||||
|
@ -123,7 +138,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100
|
width: 100,
|
||||||
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
certStatus: {
|
certStatus: {
|
||||||
|
@ -185,6 +201,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
search: {
|
search: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
|
form: { show: false },
|
||||||
type: "number",
|
type: "number",
|
||||||
column: {
|
column: {
|
||||||
width: 200,
|
width: 200,
|
||||||
|
@ -197,7 +214,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
type: "number",
|
type: "number",
|
||||||
form: {},
|
form: { show: false },
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
|
@ -212,11 +229,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
type: "dict-switch",
|
type: "dict-switch",
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "禁用", value: true, color: "red" },
|
{ label: "启用", value: false, color: "green" },
|
||||||
{ label: "启用", value: false, color: "green" }
|
{ label: "禁用", value: true, color: "red" }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
form: {},
|
form: {
|
||||||
|
value: true
|
||||||
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
sorter: true
|
sorter: true
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { request } from "/src/api/service";
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
const apiPrefix = "/pay";
|
const apiPrefix = "/payment";
|
||||||
export async function Notify(type: string, query: any) {
|
export async function Notify(type: string, query: any) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + `/notify/${type}`,
|
url: apiPrefix + `/notify/${type}`,
|
||||||
method: "post",
|
method: "post",
|
||||||
data: query,
|
data: query,
|
||||||
returnResponse: true
|
unpack: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cd-payment-return">
|
<div class="cd-payment-return w-100">
|
||||||
<a-card title="支付结果" class="mt-10">
|
<div v-if="payResult == null" class="flex-o m-20 w-100">
|
||||||
<div class="flex-o">
|
<a-spin />
|
||||||
<div class="flex-1">
|
</div>
|
||||||
<a-tag v-if="payResult" color="green" class="m-0">支付成功</a-tag>
|
<a-result v-else-if="payResult" status="success" title="支付成功">
|
||||||
<a-tag v-else color="red" class="m-0">支付失败</a-tag>
|
<template #extra>
|
||||||
</div>
|
<a-button key="console" type="primary" @click="goHome">回首页</a-button>
|
||||||
<div class="m-10">
|
</template>
|
||||||
<a-button type="primary" @click="goHome">回首页</a-button>
|
</a-result>
|
||||||
</div>
|
<a-result v-else status="error" title="支付失败">
|
||||||
</div>
|
<template #extra>
|
||||||
</a-card>
|
<a-button key="console" type="primary" @click="goHome">回首页</a-button>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ async function check() {
|
||||||
payResult.value = true;
|
payResult.value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
check();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
function goHome() {
|
function goHome() {
|
||||||
|
|
|
@ -112,16 +112,20 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se
|
||||||
}
|
}
|
||||||
let pipeline = {
|
let pipeline = {
|
||||||
title: form.domains[0] + "证书自动化",
|
title: form.domains[0] + "证书自动化",
|
||||||
|
runnableType: "pipeline",
|
||||||
stages: [
|
stages: [
|
||||||
{
|
{
|
||||||
title: "证书申请阶段",
|
title: "证书申请阶段",
|
||||||
maxTaskCount: 1,
|
maxTaskCount: 1,
|
||||||
|
runnableType: "stage",
|
||||||
tasks: [
|
tasks: [
|
||||||
{
|
{
|
||||||
title: "证书申请任务",
|
title: "证书申请任务",
|
||||||
|
runnableType: "task",
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
title: "申请证书",
|
title: "申请证书",
|
||||||
|
runnableType: "step",
|
||||||
input: {
|
input: {
|
||||||
renewDays: 35,
|
renewDays: 35,
|
||||||
...form
|
...form
|
||||||
|
@ -141,10 +145,18 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se
|
||||||
};
|
};
|
||||||
pipeline = setRunnableIds(pipeline);
|
pipeline = setRunnableIds(pipeline);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* // cert: 证书; backup: 备份; custom:自定义;
|
||||||
|
* type: string;
|
||||||
|
* // custom: 自定义; monitor: 监控;
|
||||||
|
* from: string;
|
||||||
|
*/
|
||||||
const id = await api.Save({
|
const id = await api.Save({
|
||||||
title: pipeline.title,
|
title: pipeline.title,
|
||||||
content: JSON.stringify(pipeline),
|
content: JSON.stringify(pipeline),
|
||||||
keepHistoryCount: 30
|
keepHistoryCount: 30,
|
||||||
|
type: "cert",
|
||||||
|
from: "custom"
|
||||||
});
|
});
|
||||||
message.success("创建成功,请添加证书部署任务");
|
message.success("创建成功,请添加证书部署任务");
|
||||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||||
|
|
|
@ -4,13 +4,17 @@
|
||||||
<div class="title">套餐购买</div>
|
<div class="title">套餐购买</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="suite-buy-content">
|
<div class="suite-buy-content">
|
||||||
<div class="mb-10">
|
<a-row class="w-100" :gutter="8">
|
||||||
<a-card>
|
<a-col :span="24">
|
||||||
<div>套餐说明:多个套餐内的数量可以叠加</div>
|
<a-card>
|
||||||
<div v-if="suiteIntro" v-html="suiteIntro"></div>
|
<div class="suite-intro-box">
|
||||||
</a-card>
|
<div>套餐说明:多个套餐内的数量可以叠加</div>
|
||||||
</div>
|
<div v-if="suiteIntro" v-html="suiteIntro"></div>
|
||||||
<a-row :gutter="8">
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="8" class="mt-10">
|
||||||
<a-col v-for="item of products" :key="item.id" class="mb-10 suite-card-col">
|
<a-col v-for="item of products" :key="item.id" class="mb-10 suite-card-col">
|
||||||
<product-info :product="item" @order="doOrder" />
|
<product-info :product="item" @order="doOrder" />
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -57,11 +61,23 @@ loadSuiteIntro();
|
||||||
background: #f0f2f5;
|
background: #f0f2f5;
|
||||||
.suite-buy-content {
|
.suite-buy-content {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
.hr {
|
.suite-intro-box {
|
||||||
border-top: 1px solid #cdcdcd;
|
//height: 60px;
|
||||||
margin-top: 5px;
|
//overflow: hidden;
|
||||||
padding-top: 5px;
|
//text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suite-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
.my-suites {
|
||||||
|
width: 360px;
|
||||||
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-text {
|
.price-text {
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
export function createApi() {
|
||||||
|
const apiPrefix = "/mine/suite";
|
||||||
|
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 ListAll() {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/all",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pipelineGroupApi = createApi();
|
|
@ -0,0 +1,323 @@
|
||||||
|
import { AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes } from "@fast-crud/fast-crud";
|
||||||
|
import { pipelineGroupApi } from "./api";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import SuiteValueEdit from "/@/views/sys/suite/product/suite-value-edit.vue";
|
||||||
|
import SuiteValue from "/@/views/sys/suite/product/suite-value.vue";
|
||||||
|
import DurationValue from "/@/views/sys/suite/product/duration-value.vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const api = pipelineGroupApi;
|
||||||
|
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 router = useRouter();
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
labelCol: {
|
||||||
|
//固定label宽度
|
||||||
|
span: null,
|
||||||
|
style: {
|
||||||
|
width: "100px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 22
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
width: 600
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
add: { show: false },
|
||||||
|
buy: {
|
||||||
|
text: "购买",
|
||||||
|
type: "primary",
|
||||||
|
click() {
|
||||||
|
router.push({
|
||||||
|
path: "/certd/suite/buy"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
width: 200,
|
||||||
|
fixed: "right",
|
||||||
|
buttons: {
|
||||||
|
view: { show: false },
|
||||||
|
copy: { show: false },
|
||||||
|
edit: { show: false },
|
||||||
|
remove: { show: false }
|
||||||
|
// continue:{
|
||||||
|
// text:"续期",
|
||||||
|
// type:"link",
|
||||||
|
// click(){
|
||||||
|
// console.log("续期");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
search: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
editable: {
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
title: "套餐名称",
|
||||||
|
type: "text",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
productType: {
|
||||||
|
title: "类型",
|
||||||
|
type: "dict-select",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "套餐", value: "suite", color: "green" },
|
||||||
|
{ label: "加量包", value: "addon", color: "blue" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 80,
|
||||||
|
align: "center"
|
||||||
|
},
|
||||||
|
valueBuilder: ({ row }) => {
|
||||||
|
if (row.content) {
|
||||||
|
row.content = JSON.parse(row.content);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueResolve: ({ form }) => {
|
||||||
|
if (form.content) {
|
||||||
|
form.content = JSON.stringify(form.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content.maxDomainCount": {
|
||||||
|
title: "域名数量",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
key: ["content", "maxDomainCount"],
|
||||||
|
component: {
|
||||||
|
name: SuiteValueEdit,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "个"
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
name: SuiteValue,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "个"
|
||||||
|
},
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content.maxPipelineCount": {
|
||||||
|
title: "流水线数量",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
key: ["content", "maxPipelineCount"],
|
||||||
|
component: {
|
||||||
|
name: SuiteValueEdit,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "条"
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
name: SuiteValue,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "条"
|
||||||
|
},
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content.maxDeployCount": {
|
||||||
|
title: "部署次数",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
key: ["content", "maxDeployCount"],
|
||||||
|
component: {
|
||||||
|
name: SuiteValueEdit,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "次"
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
name: SuiteValue,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "次"
|
||||||
|
},
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content.maxMonitorCount": {
|
||||||
|
title: "证书监控数量",
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
key: ["content", "maxMonitorCount"],
|
||||||
|
component: {
|
||||||
|
name: SuiteValueEdit,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "个"
|
||||||
|
},
|
||||||
|
rules: [{ required: true, message: "此项必填" }]
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 120,
|
||||||
|
component: {
|
||||||
|
name: SuiteValue,
|
||||||
|
vModel: "modelValue",
|
||||||
|
unit: "个"
|
||||||
|
},
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
title: "时长",
|
||||||
|
type: "text",
|
||||||
|
form: {},
|
||||||
|
column: {
|
||||||
|
component: {
|
||||||
|
name: DurationValue,
|
||||||
|
vModel: "modelValue"
|
||||||
|
},
|
||||||
|
width: 100,
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
title: "状态",
|
||||||
|
type: "text",
|
||||||
|
form: { show: false },
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
conditionalRender: {
|
||||||
|
match() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cellRender({ row }) {
|
||||||
|
if (row.activeTime == null) {
|
||||||
|
return <a-tag color="blue">未使用</a-tag>;
|
||||||
|
}
|
||||||
|
const now = dayjs().valueOf();
|
||||||
|
//已过期
|
||||||
|
const isExpired = row.expiresTime != -1 && now > row.expiresTime;
|
||||||
|
if (isExpired) {
|
||||||
|
return <a-tag color="error">已过期</a-tag>;
|
||||||
|
}
|
||||||
|
//如果在激活时间之前
|
||||||
|
if (now < row.activeTime) {
|
||||||
|
return <a-tag color="blue">待生效</a-tag>;
|
||||||
|
}
|
||||||
|
// 是否在激活时间和过期时间之间
|
||||||
|
if (now > row.activeTime && (row.expiresTime == -1 || now < row.expiresTime)) {
|
||||||
|
return <a-tag color="success">生效中</a-tag>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activeTime: {
|
||||||
|
title: "激活时间",
|
||||||
|
type: "date",
|
||||||
|
column: {
|
||||||
|
width: 150
|
||||||
|
}
|
||||||
|
},
|
||||||
|
expiresTime: {
|
||||||
|
title: "过期时间",
|
||||||
|
type: "date",
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
name: "expires-time-text",
|
||||||
|
vModel: "value",
|
||||||
|
mode: "tag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isPresent: {
|
||||||
|
title: "是否赠送",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "是", value: true, color: "success" },
|
||||||
|
{ label: "否", value: false, color: "blue" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<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" setup>
|
||||||
|
import { defineComponent, onActivated, onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { createApi } from "./api";
|
||||||
|
defineOptions({
|
||||||
|
name: "MySuites"
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} });
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
onActivated(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -25,14 +25,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue';
|
||||||
import { GetPaymentTypes, OrderModalOpenReq, TradeCreate } from "/@/views/certd/suite/api";
|
import { GetPaymentTypes, OrderModalOpenReq, TradeCreate } from '/@/views/certd/suite/api';
|
||||||
import SuiteValue from "/@/views/sys/suite/product/suite-value.vue";
|
import SuiteValue from '/@/views/sys/suite/product/suite-value.vue';
|
||||||
import PriceInput from "/@/views/sys/suite/product/price-input.vue";
|
import PriceInput from '/@/views/sys/suite/product/price-input.vue';
|
||||||
import modal from "/@/views/certd/notification/notification-selector/modal/index.vue";
|
import { dict } from '@fast-crud/fast-crud';
|
||||||
import { dict } from "@fast-crud/fast-crud";
|
import { Modal, notification } from 'ant-design-vue';
|
||||||
import { notification } from "ant-design-vue";
|
import DurationValue from '/@/views/sys/suite/product/duration-value.vue';
|
||||||
import DurationValue from "/@/views/sys/suite/product/duration-value.vue";
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
const openRef = ref(false);
|
const openRef = ref(false);
|
||||||
|
|
||||||
|
@ -60,6 +60,8 @@ const paymentsDictRef = dict({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
async function orderCreate() {
|
async function orderCreate() {
|
||||||
console.log("orderCreate", formRef.value);
|
console.log("orderCreate", formRef.value);
|
||||||
if (!formRef.value.payType) {
|
if (!formRef.value.payType) {
|
||||||
|
@ -80,22 +82,41 @@ async function orderCreate() {
|
||||||
//易支付表单提交
|
//易支付表单提交
|
||||||
if (formRef.value.payType === "yizhifu") {
|
if (formRef.value.payType === "yizhifu") {
|
||||||
doYizhifu(paymentReq);
|
doYizhifu(paymentReq);
|
||||||
|
} else if (formRef.value.payType === "alipay") {
|
||||||
|
//支付宝、
|
||||||
|
doAlipay(paymentReq);
|
||||||
|
} else if (formRef.value.payType === "wxpay") {
|
||||||
|
//微信支付
|
||||||
|
doWxpay(paymentReq);
|
||||||
} else {
|
} else {
|
||||||
//支付宝、微信支付
|
notification.error({
|
||||||
window.open(paymentReq);
|
message: "暂不支持该支付方式"
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.open({
|
Modal.confirm({
|
||||||
title: "支付",
|
title: "请在新页面完成支付",
|
||||||
content: "请在新页面完成支付",
|
content: "是否确认已完成支付",
|
||||||
onOk: () => {
|
onOk: async () => {
|
||||||
openRef.value = false;
|
openRef.value = false;
|
||||||
|
router.push({
|
||||||
|
path: "/"
|
||||||
|
});
|
||||||
},
|
},
|
||||||
cancelText: "取消支付",
|
cancelText: "取消支付",
|
||||||
onText: "已完成支付"
|
okText: "已完成支付"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doAlipay(paymentReq: any) {
|
||||||
|
window.open(paymentReq.api);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doWxpay(paymentReq: any) {
|
||||||
|
window.open(paymentReq.api);
|
||||||
|
}
|
||||||
|
|
||||||
function doYizhifu(paymentReq: any) {
|
function doYizhifu(paymentReq: any) {
|
||||||
console.log("doYizhifu", paymentReq);
|
console.log("doYizhifu", paymentReq);
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -58,18 +58,10 @@ export async function DeleteBatch(ids: any[]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function SetDefault(id: any) {
|
export async function SyncStatus(id: any) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/setDefault",
|
url: apiPrefix + "/syncStatus",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { id }
|
data: { id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function SetDisabled(id: any, disabled: boolean) {
|
|
||||||
return await request({
|
|
||||||
url: apiPrefix + "/setDisabled",
|
|
||||||
method: "post",
|
|
||||||
data: { id, disabled }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -60,13 +60,38 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
delRequest
|
delRequest
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
width: 100,
|
width: 240,
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
buttons: {
|
buttons: {
|
||||||
edit: { show: false },
|
edit: { show: false },
|
||||||
copy: { show: false }
|
copy: { show: false },
|
||||||
|
syncStatus: {
|
||||||
|
show: compute(({ row }) => {
|
||||||
|
return row.status === "wait_pay";
|
||||||
|
}),
|
||||||
|
text: "同步订单状态",
|
||||||
|
type: "link",
|
||||||
|
click: async ({ row }) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: "确认同步订单状态?",
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SyncStatus(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
add: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbar: { show: false },
|
||||||
tabs: {
|
tabs: {
|
||||||
name: "status",
|
name: "status",
|
||||||
show: true
|
show: true
|
||||||
|
|
|
@ -53,7 +53,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
groups: {
|
groups: {
|
||||||
base: {
|
base: {
|
||||||
header: "基础信息",
|
header: "基础信息",
|
||||||
columns: ["title", "type", "isBootstrap", "disabled", "order", "intro"]
|
columns: ["title", "type", "disabled", "order", "supportBuy", "intro"]
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
header: "套餐内容",
|
header: "套餐内容",
|
||||||
|
@ -244,12 +244,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
type: "dict-switch",
|
type: "dict-switch",
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: [
|
data: [
|
||||||
{ label: "是", value: true, color: "success" },
|
{ label: "支持购买", value: true, color: "success" },
|
||||||
{ label: "否", value: false, color: "gray" }
|
{ label: "不能购买", value: false, color: "gray" }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
form: {
|
form: {
|
||||||
value: false
|
value: true
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 120
|
width: 120
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { durationDict } from "/@/views/certd/suite/api";
|
import { durationDict } from "/@/views/certd/suite/api";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "DurationValue"
|
||||||
|
});
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: number;
|
modelValue: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
|
@ -1,17 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex-o price-input">
|
<div class="flex-o price-input">
|
||||||
<a-input-number v-if="edit" prefix="¥" :value="priceValue" :precision="2" class="ml-5" @update:value="onPriceChange"> </a-input-number>
|
<a-input-number v-if="edit" prefix="¥" :value="priceValue" :precision="2" class="ml-5" @update:value="onPriceChange"> </a-input-number>
|
||||||
<span v-else class="price-text">{{ priceLabel }}</span>
|
<span v-else class="price-text" :style="style">{{ priceLabel }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
modelValue?: number;
|
defineProps<{
|
||||||
edit?: boolean;
|
modelValue?: number;
|
||||||
}>();
|
edit?: boolean;
|
||||||
|
fontSize?: number;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
modelValue: 0,
|
||||||
|
edit: false,
|
||||||
|
fontSize: 14
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const style = computed(() => {
|
||||||
|
if (props.fontSize == null) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fontSize: props.fontSize + "px"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const priceValue = computed(() => {
|
const priceValue = computed(() => {
|
||||||
if (props.modelValue == null) {
|
if (props.modelValue == null) {
|
||||||
|
@ -37,7 +54,6 @@ const onPriceChange = (price: number) => {
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.price-input {
|
.price-input {
|
||||||
.price-text {
|
.price-text {
|
||||||
font-size: 18px;
|
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,18 +58,18 @@ export async function DeleteBatch(ids: any[]) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function SetDefault(id: any) {
|
export async function UpdatePaid(id: any) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/setDefault",
|
url: apiPrefix + "/updatePaid",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { id }
|
data: { id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function SetDisabled(id: any, disabled: boolean) {
|
export async function SyncStatus(id: any) {
|
||||||
return await request({
|
return await request({
|
||||||
url: apiPrefix + "/setDisabled",
|
url: apiPrefix + "/syncStatus",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: { id, disabled }
|
data: { id }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq,
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
import { Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
|
import DurationValue from "/@/views/sys/suite/product/duration-value.vue";
|
||||||
|
import PriceInput from "/@/views/sys/suite/product/price-input.vue";
|
||||||
|
|
||||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -56,9 +58,63 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
editRequest,
|
editRequest,
|
||||||
delRequest
|
delRequest
|
||||||
},
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
add: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbar: { show: false },
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
minWidth: 200,
|
width: 320,
|
||||||
fixed: "right"
|
fixed: "right",
|
||||||
|
buttons: {
|
||||||
|
copy: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
syncStatus: {
|
||||||
|
show: compute(({ row }) => {
|
||||||
|
return row.status === "wait_pay";
|
||||||
|
}),
|
||||||
|
text: "同步订单状态",
|
||||||
|
type: "link",
|
||||||
|
click: async ({ row }) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: "确认同步订单状态?",
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SyncStatus(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updatePaid: {
|
||||||
|
show: compute(({ row }) => {
|
||||||
|
return row.status === "wait_pay";
|
||||||
|
}),
|
||||||
|
text: "确认已支付",
|
||||||
|
type: "link",
|
||||||
|
click({ row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "确认",
|
||||||
|
content: "确认修改订单状态为已支付?",
|
||||||
|
onOk: async () => {
|
||||||
|
await api.UpdatePaid(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabs: {
|
||||||
|
name: "status",
|
||||||
|
show: true
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
id: {
|
id: {
|
||||||
|
@ -72,156 +128,88 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domain: {
|
tradeNo: {
|
||||||
title: "CNAME域名",
|
title: "订单号",
|
||||||
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",
|
type: "text",
|
||||||
|
search: { show: true },
|
||||||
form: {
|
form: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 250
|
||||||
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: {
|
||||||
title: "禁用/启用",
|
title: "商品名称",
|
||||||
type: "dict-switch",
|
type: "text",
|
||||||
dict: dict({
|
search: { show: true },
|
||||||
data: [
|
column: {
|
||||||
{ label: "启用", value: false, color: "success" },
|
width: 150
|
||||||
{ label: "禁用", value: true, color: "error" }
|
}
|
||||||
]
|
},
|
||||||
}),
|
duration: {
|
||||||
form: {
|
title: "时长",
|
||||||
value: false
|
type: "number",
|
||||||
},
|
|
||||||
column: {
|
column: {
|
||||||
width: 100,
|
width: 100,
|
||||||
component: {
|
component: {
|
||||||
title: "点击可禁用/启用",
|
name: DurationValue,
|
||||||
on: {
|
vModel: "modelValue"
|
||||||
async click({ value, row }) {
|
|
||||||
Modal.confirm({
|
|
||||||
title: "提示",
|
|
||||||
content: `确定要${!value ? "禁用" : "启用"}吗?`,
|
|
||||||
onOk: async () => {
|
|
||||||
await api.SetDisabled(row.id, !value);
|
|
||||||
await crudExpose.doRefresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
amount: {
|
||||||
|
title: "金额",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
name: PriceInput,
|
||||||
|
vModel: "modelValue",
|
||||||
|
edit: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
title: "状态",
|
||||||
|
search: { show: true },
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "待支付", value: "wait_pay", color: "warning" },
|
||||||
|
{ label: "已支付", value: "paid", color: "success" },
|
||||||
|
{ label: "已取消", value: "canceled", color: "error" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
column: {
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
payType: {
|
||||||
|
title: "支付方式",
|
||||||
|
search: { show: true },
|
||||||
|
type: "dict-select",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: "聚合支付", value: "yizhifu" },
|
||||||
|
{ label: "支付宝", value: "alipay" },
|
||||||
|
{ label: "微信", value: "wxpay" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
color: "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
payTime: {
|
||||||
|
title: "支付时间",
|
||||||
|
type: "datetime",
|
||||||
|
column: {
|
||||||
|
width: 160
|
||||||
|
}
|
||||||
|
},
|
||||||
createTime: {
|
createTime: {
|
||||||
title: "创建时间",
|
title: "创建时间",
|
||||||
type: "datetime",
|
type: "datetime",
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
<fs-page class="page-cert">
|
<fs-page class="page-cert">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
CNAME服务配置
|
订单管理
|
||||||
<span class="sub">
|
<span class="sub"> </span>
|
||||||
此处配置的域名作为其他域名校验的代理,当别的域名需要申请证书时,通过CNAME映射到此域名上来验证所有权。好处是任何域名都可以通过此方式申请证书,也无需填写AccessSecret。
|
|
||||||
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">CNAME功能原理及使用说明</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
@ -27,7 +24,7 @@ import { message, Modal } from "ant-design-vue";
|
||||||
import { DeleteBatch } from "./api";
|
import { DeleteBatch } from "./api";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "CnameProvider"
|
name: "TradeManager"
|
||||||
});
|
});
|
||||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||||
import { Constants, CrudController } from '@certd/lib-server';
|
import { Constants, CrudController } from '@certd/lib-server';
|
||||||
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
||||||
import { SiteInfoService } from '../../modules/monitor/service/site-info-service.js';
|
import { CertInfoService } from '../../modules/monitor/index.js';
|
||||||
|
import { PipelineService } from '../../modules/pipeline/service/pipeline-service.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知
|
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Controller('/api/monitor/site')
|
@Controller('/api/monitor/cert')
|
||||||
export class SiteInfoController extends CrudController<SiteInfoService> {
|
export class CertInfoController extends CrudController<CertInfoService> {
|
||||||
@Inject()
|
@Inject()
|
||||||
service: SiteInfoService;
|
service: CertInfoService;
|
||||||
@Inject()
|
@Inject()
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
|
@Inject()
|
||||||
|
pipelineService: PipelineService;
|
||||||
|
|
||||||
getService(): SiteInfoService {
|
getService(): CertInfoService {
|
||||||
return this.service;
|
return this.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +24,23 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||||
async page(@Body(ALL) body: any) {
|
async page(@Body(ALL) body: any) {
|
||||||
body.query = body.query ?? {};
|
body.query = body.query ?? {};
|
||||||
body.query.userId = this.getUserId();
|
body.query.userId = this.getUserId();
|
||||||
|
|
||||||
const res = await this.service.page({
|
const res = await this.service.page({
|
||||||
query: body.query,
|
query: body.query,
|
||||||
page: body.page,
|
page: body.page,
|
||||||
sort: body.sort,
|
sort: body.sort,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const records = res.records;
|
||||||
|
const pipelineIds = records.map(r => r.pipelineId);
|
||||||
|
const pipelines = await this.pipelineService.getSimplePipelines(pipelineIds);
|
||||||
|
const pMap = new Map();
|
||||||
|
for (const p of pipelines) {
|
||||||
|
pMap.set(p.id, p);
|
||||||
|
}
|
||||||
|
for (const record of records) {
|
||||||
|
record.pipeline = pMap.get(record.pipelineId);
|
||||||
|
}
|
||||||
return this.ok(res);
|
return this.ok(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||||
import { Constants, CrudController } from '@certd/lib-server';
|
import { Constants, CrudController } from '@certd/lib-server';
|
||||||
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
import { AuthService } from '../../modules/sys/authority/service/auth-service.js';
|
||||||
import { CertInfoService } from '../../modules/monitor/service/cert-info-service.js';
|
import { SiteInfoService } from '../../modules/monitor/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知
|
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Controller('/api/monitor/cert')
|
@Controller('/api/monitor/site')
|
||||||
export class CertInfoController extends CrudController<CertInfoService> {
|
export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||||
@Inject()
|
@Inject()
|
||||||
service: CertInfoService;
|
service: SiteInfoService;
|
||||||
@Inject()
|
@Inject()
|
||||||
authService: AuthService;
|
authService: AuthService;
|
||||||
|
|
||||||
getService(): CertInfoService {
|
getService(): SiteInfoService {
|
||||||
return this.service;
|
return this.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +21,6 @@ export class CertInfoController extends CrudController<CertInfoService> {
|
||||||
async page(@Body(ALL) body: any) {
|
async page(@Body(ALL) body: any) {
|
||||||
body.query = body.query ?? {};
|
body.query = body.query ?? {};
|
||||||
body.query.userId = this.getUserId();
|
body.query.userId = this.getUserId();
|
||||||
|
|
||||||
const res = await this.service.page({
|
const res = await this.service.page({
|
||||||
query: body.query,
|
query: body.query,
|
||||||
page: body.page,
|
page: body.page,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { nanoid } from 'nanoid';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
@Autoload()
|
@Autoload()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AutoInitSite {
|
export class AutoInitSite {
|
||||||
@Inject()
|
@Inject()
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { logger } from '@certd/basic';
|
||||||
import { SysSettingsService } from '@certd/lib-server';
|
import { SysSettingsService } from '@certd/lib-server';
|
||||||
|
|
||||||
@Autoload()
|
@Autoload()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AutoRegisterCron {
|
export class AutoRegisterCron {
|
||||||
@Inject()
|
@Inject()
|
||||||
pipelineService: PipelineService;
|
pipelineService: PipelineService;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Application } from '@midwayjs/koa';
|
||||||
import { httpsServer, HttpsServerOptions } from './https/server.js';
|
import { httpsServer, HttpsServerOptions } from './https/server.js';
|
||||||
|
|
||||||
@Autoload()
|
@Autoload()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AutoZPrint {
|
export class AutoZPrint {
|
||||||
@Inject()
|
@Inject()
|
||||||
sysSettingsService: SysSettingsService;
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export type EmailConfig = {
|
||||||
usePlus?: boolean;
|
usePlus?: boolean;
|
||||||
} & SMTPConnection.Options;
|
} & SMTPConnection.Options;
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class EmailService implements IEmailService {
|
export class EmailService implements IEmailService {
|
||||||
@Inject()
|
@Inject()
|
||||||
settingsService: UserSettingsService;
|
settingsService: UserSettingsService;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { CommonProviders } from './common-provider.js';
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||||
@InjectEntityModel(CnameProviderEntity)
|
@InjectEntityModel(CnameProviderEntity)
|
||||||
repository: Repository<CnameProviderEntity>;
|
repository: Repository<CnameProviderEntity>;
|
||||||
|
|
|
@ -26,7 +26,7 @@ type CnameCheckCacheValue = {
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||||
@InjectEntityModel(CnameRecordEntity)
|
@InjectEntityModel(CnameRecordEntity)
|
||||||
repository: Repository<CnameRecordEntity>;
|
repository: Repository<CnameRecordEntity>;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { SqlAdapter } from './d.js';
|
||||||
import { MysqlAdapter } from './mysql.js';
|
import { MysqlAdapter } from './mysql.js';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class DbAdapter implements SqlAdapter {
|
export class DbAdapter implements SqlAdapter {
|
||||||
adapter: SqlAdapter;
|
adapter: SqlAdapter;
|
||||||
@Config('typeorm.dataSource.default.type')
|
@Config('typeorm.dataSource.default.type')
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { UserSettingsEntity } from '../entity/user-settings.js';
|
||||||
* 授权
|
* 授权
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class UserSettingsService extends BaseService<UserSettingsEntity> {
|
export class UserSettingsService extends BaseService<UserSettingsEntity> {
|
||||||
@InjectEntityModel(UserSettingsEntity)
|
@InjectEntityModel(UserSettingsEntity)
|
||||||
repository: Repository<UserSettingsEntity>;
|
repository: Repository<UserSettingsEntity>;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
import { PipelineEntity } from '../../pipeline/entity/pipeline.js';
|
||||||
|
|
||||||
@Entity('cd_cert_info')
|
@Entity('cd_cert_info')
|
||||||
export class CertInfoEntity {
|
export class CertInfoEntity {
|
||||||
|
@ -51,4 +52,6 @@ export class CertInfoEntity {
|
||||||
default: () => 'CURRENT_TIMESTAMP',
|
default: () => 'CURRENT_TIMESTAMP',
|
||||||
})
|
})
|
||||||
updateTime: Date;
|
updateTime: Date;
|
||||||
|
|
||||||
|
pipeline?: PipelineEntity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export * from "./entity/site-info.js";
|
||||||
|
export * from "./entity/cert-info.js";
|
||||||
|
|
||||||
|
export * from "./service/cert-info-service.js";
|
||||||
|
export * from "./service/site-info-service.js";
|
|
@ -1,5 +1,5 @@
|
||||||
import { Provide } from '@midwayjs/core';
|
import { Provide } from '@midwayjs/core';
|
||||||
import { BaseService } from '@certd/lib-server';
|
import { BaseService, PageReq } from '@certd/lib-server';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { CertInfoEntity } from '../entity/cert-info.js';
|
import { CertInfoEntity } from '../entity/cert-info.js';
|
||||||
|
@ -14,6 +14,10 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async page(pageReq: PageReq<CertInfoEntity>) {
|
||||||
|
return await super.page(pageReq);
|
||||||
|
}
|
||||||
|
|
||||||
async getUserDomainCount(userId: number) {
|
async getUserDomainCount(userId: number) {
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
throw new Error('userId is required');
|
throw new Error('userId is required');
|
||||||
|
@ -23,10 +27,11 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateDomains(pipelineId: number, domains: string[]) {
|
async updateDomains(pipelineId: number, userId: number, domains: string[]) {
|
||||||
const found = await this.repository.findOne({
|
const found = await this.repository.findOne({
|
||||||
where: {
|
where: {
|
||||||
pipelineId,
|
pipelineId,
|
||||||
|
userId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const bean = new CertInfoEntity();
|
const bean = new CertInfoEntity();
|
||||||
|
@ -36,11 +41,21 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
||||||
} else {
|
} else {
|
||||||
//create
|
//create
|
||||||
bean.pipelineId = pipelineId;
|
bean.pipelineId = pipelineId;
|
||||||
|
bean.userId = userId;
|
||||||
|
if (!domains || domains.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bean.domain = domains[0];
|
if (!domains || domains.length === 0) {
|
||||||
bean.domains = domains.join(',');
|
bean.domain = '';
|
||||||
bean.domainCount = domains.length;
|
bean.domains = '';
|
||||||
|
bean.domainCount = 0;
|
||||||
|
} else {
|
||||||
|
bean.domain = domains[0];
|
||||||
|
bean.domains = domains.join(',');
|
||||||
|
bean.domainCount = domains.length;
|
||||||
|
}
|
||||||
|
|
||||||
await this.addOrUpdate(bean);
|
await this.addOrUpdate(bean);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { pluginGroups, pluginRegistry } from '@certd/pipeline';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class BuiltInPluginService {
|
export class BuiltInPluginService {
|
||||||
getList() {
|
getList() {
|
||||||
const collection = pluginRegistry.storage;
|
const collection = pluginRegistry.storage;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { HistoryLogEntity } from '../entity/history-log.js';
|
||||||
* 证书申请
|
* 证书申请
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class HistoryLogService extends BaseService<HistoryLogEntity> {
|
export class HistoryLogService extends BaseService<HistoryLogEntity> {
|
||||||
@InjectEntityModel(HistoryLogEntity)
|
@InjectEntityModel(HistoryLogEntity)
|
||||||
repository: Repository<HistoryLogEntity>;
|
repository: Repository<HistoryLogEntity>;
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { logger } from '@certd/basic';
|
||||||
* 证书申请
|
* 证书申请
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class HistoryService extends BaseService<HistoryEntity> {
|
export class HistoryService extends BaseService<HistoryEntity> {
|
||||||
@InjectEntityModel(HistoryEntity)
|
@InjectEntityModel(HistoryEntity)
|
||||||
repository: Repository<HistoryEntity>;
|
repository: Repository<HistoryEntity>;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { EmailService } from '../../basic/service/email-service.js';
|
||||||
import { isComm } from '@certd/plus-core';
|
import { isComm } from '@certd/plus-core';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class NotificationService extends BaseService<NotificationEntity> {
|
export class NotificationService extends BaseService<NotificationEntity> {
|
||||||
@InjectEntityModel(NotificationEntity)
|
@InjectEntityModel(NotificationEntity)
|
||||||
repository: Repository<NotificationEntity>;
|
repository: Repository<NotificationEntity>;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { PipelineGroupEntity } from '../entity/pipeline-group.js';
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PipelineGroupService extends BaseService<PipelineGroupEntity> {
|
export class PipelineGroupService extends BaseService<PipelineGroupEntity> {
|
||||||
@InjectEntityModel(PipelineGroupEntity)
|
@InjectEntityModel(PipelineGroupEntity)
|
||||||
repository: Repository<PipelineGroupEntity>;
|
repository: Repository<PipelineGroupEntity>;
|
||||||
|
|
|
@ -160,14 +160,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
old = await this.info(bean.id);
|
old = await this.info(bean.id);
|
||||||
}
|
}
|
||||||
const pipeline = JSON.parse(bean.content || '{}');
|
const pipeline = JSON.parse(bean.content || '{}');
|
||||||
|
RunnableCollection.initPipelineRunnableType(pipeline);
|
||||||
const isUpdate = bean.id > 0 && old != null;
|
const isUpdate = bean.id > 0 && old != null;
|
||||||
|
|
||||||
let domains = [];
|
let domains = [];
|
||||||
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
if (pipeline.stages) {
|
||||||
if (runnable.runnableType === 'step' && runnable.type.startsWith('CertApply')) {
|
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
||||||
domains = runnable.input.domains || [];
|
if (runnable.runnableType === 'step' && runnable.type.startsWith('CertApply')) {
|
||||||
}
|
domains = runnable.input.domains || [];
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!isUpdate) {
|
if (!isUpdate) {
|
||||||
//如果是添加,校验数量
|
//如果是添加,校验数量
|
||||||
|
@ -188,7 +191,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
await this.registerTriggerById(bean.id);
|
await this.registerTriggerById(bean.id);
|
||||||
|
|
||||||
//保存域名信息到certInfo表
|
//保存域名信息到certInfo表
|
||||||
await this.certInfoService.updateDomains(pipeline.id, domains);
|
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains);
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,4 +625,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
async getUserPipelineCount(userId) {
|
async getUserPipelineCount(userId) {
|
||||||
return await this.repository.count({ where: { userId } });
|
return await this.repository.count({ where: { userId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSimplePipelines(pipelineIds: number[], userId?: number) {
|
||||||
|
return await this.repository.find({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: In(pipelineIds),
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { StorageEntity } from '../entity/storage.js';
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class StorageService extends BaseService<StorageEntity> {
|
export class StorageService extends BaseService<StorageEntity> {
|
||||||
@InjectEntityModel(StorageEntity)
|
@InjectEntityModel(StorageEntity)
|
||||||
repository: Repository<StorageEntity>;
|
repository: Repository<StorageEntity>;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
import { SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class UrlService implements IUrlService {
|
export class UrlService implements IUrlService {
|
||||||
@Inject()
|
@Inject()
|
||||||
sysSettingsService: SysSettingsService;
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { IPluginConfigService, PluginConfig } from '@certd/pipeline';
|
||||||
import { PluginConfigService } from './plugin-config-service.js';
|
import { PluginConfigService } from './plugin-config-service.js';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PluginConfigGetter implements IPluginConfigService {
|
export class PluginConfigGetter implements IPluginConfigService {
|
||||||
@Inject()
|
@Inject()
|
||||||
pluginConfigService: PluginConfigService;
|
pluginConfigService: PluginConfigService;
|
||||||
|
|
|
@ -19,7 +19,7 @@ export type PluginFindReq = {
|
||||||
type: string;
|
type: string;
|
||||||
};
|
};
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PluginConfigService {
|
export class PluginConfigService {
|
||||||
@Inject()
|
@Inject()
|
||||||
pluginService: PluginService;
|
pluginService: PluginService;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { BuiltInPluginService } from '../../pipeline/service/builtin-plugin-serv
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
|
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PluginService extends BaseService<PluginEntity> {
|
export class PluginService extends BaseService<PluginEntity> {
|
||||||
@InjectEntityModel(PluginEntity)
|
@InjectEntityModel(PluginEntity)
|
||||||
repository: Repository<PluginEntity>;
|
repository: Repository<PluginEntity>;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { RoleService } from './role-service.js';
|
||||||
* 权限校验
|
* 权限校验
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@Inject()
|
@Inject()
|
||||||
roleService: RoleService;
|
roleService: RoleService;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { PermissionEntity } from '../entity/permission.js';
|
||||||
* 权限资源
|
* 权限资源
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class PermissionService extends BaseService<PermissionEntity> {
|
export class PermissionService extends BaseService<PermissionEntity> {
|
||||||
@InjectEntityModel(PermissionEntity)
|
@InjectEntityModel(PermissionEntity)
|
||||||
repository: Repository<PermissionEntity>;
|
repository: Repository<PermissionEntity>;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { RolePermissionEntity } from '../entity/role-permission.js';
|
||||||
* 角色->权限
|
* 角色->权限
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class RolePermissionService extends BaseService<RolePermissionEntity> {
|
export class RolePermissionService extends BaseService<RolePermissionEntity> {
|
||||||
@InjectEntityModel(RolePermissionEntity)
|
@InjectEntityModel(RolePermissionEntity)
|
||||||
repository: Repository<RolePermissionEntity>;
|
repository: Repository<RolePermissionEntity>;
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { LRUCache } from 'lru-cache';
|
||||||
* 角色
|
* 角色
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class RoleService extends BaseService<RoleEntity> {
|
export class RoleService extends BaseService<RoleEntity> {
|
||||||
@InjectEntityModel(RoleEntity)
|
@InjectEntityModel(RoleEntity)
|
||||||
repository: Repository<RoleEntity>;
|
repository: Repository<RoleEntity>;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { UserRoleEntity } from '../entity/user-role.js';
|
||||||
* 用户->角色
|
* 用户->角色
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class UserRoleService extends BaseService<UserRoleEntity> {
|
export class UserRoleService extends BaseService<UserRoleEntity> {
|
||||||
@InjectEntityModel(UserRoleEntity)
|
@InjectEntityModel(UserRoleEntity)
|
||||||
repository: Repository<UserRoleEntity>;
|
repository: Repository<UserRoleEntity>;
|
||||||
|
|
|
@ -19,7 +19,7 @@ export type RegisterType = 'username' | 'mobile' | 'email';
|
||||||
* 系统用户
|
* 系统用户
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
@Scope(ScopeEnum.Singleton)
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
export class UserService extends BaseService<UserEntity> {
|
export class UserService extends BaseService<UserEntity> {
|
||||||
@InjectEntityModel(UserEntity)
|
@InjectEntityModel(UserEntity)
|
||||||
repository: Repository<UserEntity>;
|
repository: Repository<UserEntity>;
|
||||||
|
|
Loading…
Reference in New Issue