mirror of https://github.com/certd/certd
feat: 套餐购买支持易支付、支付宝支付
parent
9c8c7a7812
commit
faa28f88f9
|
@ -144,6 +144,19 @@ export class RunnableCollection {
|
|||
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) {
|
||||
list.forEach((item) => {
|
||||
exec(item);
|
||||
|
|
|
@ -39,4 +39,12 @@ export abstract class BaseController {
|
|||
}
|
||||
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;
|
||||
}
|
||||
const qb = this.buildListQuery(pageReq);
|
||||
|
||||
qb.offset(page.offset).limit(page.limit);
|
||||
const list = await qb.getMany();
|
||||
const total = await qb.getCount();
|
||||
|
|
|
@ -14,7 +14,7 @@ export const uploadTmpFileCacheKey = 'tmpfile_key_';
|
|||
/**
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class FileService {
|
||||
async saveFile(userId: number, tmpCacheKey: any, permission: 'public' | 'private') {
|
||||
if (tmpCacheKey.startsWith(`/${permission}`)) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SysInstallInfo, SysLicenseInfo, SysSettingsService } from '../../settin
|
|||
import { merge } from 'lodash-es';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PlusService {
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
|
|
@ -12,7 +12,7 @@ import * as dns from 'node:dns';
|
|||
* 设置
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class SysSettingsService extends BaseService<SysSettingsEntity> {
|
||||
@InjectEntityModel(SysSettingsEntity)
|
||||
repository: Repository<SysSettingsEntity>;
|
||||
|
|
|
@ -10,7 +10,7 @@ import { EncryptService } from './encrypt-service.js';
|
|||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class AccessService extends BaseService<AccessEntity> {
|
||||
@InjectEntityModel(AccessEntity)
|
||||
repository: Repository<AccessEntity>;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { SysPrivateSettings, SysSettingsService } from '../../../system/index.js
|
|||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class EncryptService {
|
||||
secretKey: Buffer;
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ function createService() {
|
|||
if (response.config.responseType === "blob") {
|
||||
return response;
|
||||
}
|
||||
//@ts-ignore
|
||||
if (response.config.returnResponse) {
|
||||
return response;
|
||||
}
|
||||
// dataAxios 是 axios 返回数据中的 data
|
||||
const dataAxios = response.data;
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<template>
|
||||
<span class="cd-expires-time-text">
|
||||
<template v-if="label != null">
|
||||
{{ label }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<FsTimeHumanize :model-value="value" :use-format-greater="1000000000000" :options="{ units: ['d'] }"></FsTimeHumanize>
|
||||
</template>
|
||||
<component :is="wrapperComp" :color="color">
|
||||
<template v-if="label != null">
|
||||
{{ label }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<FsTimeHumanize :model-value="value" :use-format-greater="1000000000000" :options="{ units: ['d'] }"></FsTimeHumanize>
|
||||
</template>
|
||||
</component>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
@ -19,8 +21,32 @@ defineOptions({
|
|||
|
||||
const props = defineProps<{
|
||||
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(() => {
|
||||
if (props.value == null) {
|
||||
return "";
|
||||
|
|
|
@ -153,7 +153,7 @@ export default defineComponent({
|
|||
if (item.value instanceof Array) {
|
||||
return;
|
||||
}
|
||||
keys.push(item.value.index);
|
||||
keys.push(item.value.path);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<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">
|
||||
<img :src="siteInfo.logo" />
|
||||
<span v-if="!asideCollapsed" class="title">{{ siteInfo.title }}</span>
|
||||
|
|
|
@ -39,98 +39,146 @@ export const certdResources = [
|
|||
}
|
||||
},
|
||||
{
|
||||
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: "站点证书监控",
|
||||
title: "证书监控",
|
||||
name: "SiteCertMonitor",
|
||||
path: "/certd/monitor/site",
|
||||
component: "/certd/monitor/site/index.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
icon: "ion:videocam-outline",
|
||||
auth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "证书仓库",
|
||||
name: "CertStore",
|
||||
path: "/certd/monitor/cert",
|
||||
component: "/certd/monitor/cert/index.vue",
|
||||
title: "设置",
|
||||
name: "MineSetting",
|
||||
path: "/certd/mine",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
auth: true
|
||||
}
|
||||
icon: "ion:settings-outline",
|
||||
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: "邮箱设置",
|
||||
// name: "EmailSetting",
|
||||
|
@ -141,17 +189,6 @@ export const certdResources = [
|
|||
// 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",
|
||||
component: "/sys/suite/setting/index.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit"
|
||||
}
|
||||
},
|
||||
|
@ -186,7 +186,7 @@ export const sysResources = [
|
|||
path: "/sys/suite/trade",
|
||||
component: "/sys/suite/trade/index.vue",
|
||||
meta: {
|
||||
icon: "ion:person-outline",
|
||||
icon: "ion:bag-check",
|
||||
permission: "sys:settings:edit"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ interface ResourceState {
|
|||
|
||||
export const useResourceStore = defineStore({
|
||||
id: "app.resource",
|
||||
//@ts-ignore
|
||||
state: (): ResourceState => ({
|
||||
// user info
|
||||
topMenus: [],
|
||||
|
|
|
@ -68,3 +68,11 @@
|
|||
width: 800px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.fs-crud-table{
|
||||
.ant-table-body {
|
||||
height: 1000px !important;
|
||||
table {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="access-selector">
|
||||
<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>
|
||||
</span>
|
||||
<span v-else class="mlr-5 text-gray">{{ placeholder }}</span>
|
||||
|
|
|
@ -53,4 +53,6 @@ onMounted(() => {
|
|||
crudExpose.doRefresh();
|
||||
});
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
<style lang="less">
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { request } from "/src/api/service";
|
||||
|
||||
export function createApi() {
|
||||
const apiPrefix = "/pi/pipeline/group";
|
||||
const apiPrefix = "/monitor/cert";
|
||||
return {
|
||||
async GetList(query: any) {
|
||||
return await request({
|
||||
|
|
|
@ -49,8 +49,16 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
width: 600
|
||||
}
|
||||
},
|
||||
actionbar: { show: false },
|
||||
rowHandle: {
|
||||
width: 200
|
||||
width: 200,
|
||||
fixed: "right",
|
||||
buttons: {
|
||||
view: { show: false },
|
||||
copy: { show: false },
|
||||
edit: { show: false },
|
||||
remove: { show: false }
|
||||
}
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
|
@ -80,8 +88,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
sorter: true
|
||||
width: 180,
|
||||
sorter: true,
|
||||
component: {
|
||||
name: "fs-values-format"
|
||||
}
|
||||
}
|
||||
},
|
||||
domains: {
|
||||
|
@ -94,8 +105,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
rules: [{ required: true, message: "请输入域名" }]
|
||||
},
|
||||
column: {
|
||||
width: 300,
|
||||
sorter: true
|
||||
width: 350,
|
||||
sorter: true,
|
||||
component: {
|
||||
name: "fs-values-format"
|
||||
}
|
||||
}
|
||||
},
|
||||
domainCount: {
|
||||
|
@ -106,19 +120,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
},
|
||||
column: {
|
||||
width: 120,
|
||||
sorter: true
|
||||
sorter: true,
|
||||
show: false
|
||||
}
|
||||
},
|
||||
pipelineId: {
|
||||
"pipeline.title": {
|
||||
title: "已关联流水线",
|
||||
search: { show: false },
|
||||
type: "text",
|
||||
type: "link",
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
sorter: true
|
||||
width: 250,
|
||||
sorter: true,
|
||||
component: {}
|
||||
}
|
||||
},
|
||||
applyTime: {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<template #header>
|
||||
<div class="title">
|
||||
证书仓库
|
||||
<span class="sub">管理证书,支持手动上传证书并部署</span>
|
||||
<span class="sub">管理证书,后续将支持手动上传证书并部署</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { request } from "/src/api/service";
|
||||
|
||||
export function createApi() {
|
||||
const apiPrefix = "/pi/pipeline/group";
|
||||
const apiPrefix = "/monitor/site";
|
||||
return {
|
||||
async GetList(query: any) {
|
||||
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: {
|
||||
title: "站点名称",
|
||||
search: {
|
||||
|
@ -82,35 +110,22 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
rules: [{ required: true, message: "请输入站点名称" }]
|
||||
},
|
||||
column: {
|
||||
width: 100
|
||||
}
|
||||
},
|
||||
domain: {
|
||||
title: "主域名",
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
type: "text",
|
||||
form: {
|
||||
rules: [{ required: true, message: "请输入域名" }]
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
sorter: true
|
||||
width: 200
|
||||
}
|
||||
},
|
||||
domains: {
|
||||
title: "其他域名",
|
||||
search: {
|
||||
show: true
|
||||
show: false
|
||||
},
|
||||
type: "text",
|
||||
form: {
|
||||
rules: [{ required: true, message: "请输入其他域名" }]
|
||||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 300,
|
||||
sorter: true
|
||||
sorter: true,
|
||||
show: false
|
||||
}
|
||||
},
|
||||
certInfo: {
|
||||
|
@ -123,7 +138,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
show: false
|
||||
},
|
||||
column: {
|
||||
width: 100
|
||||
width: 100,
|
||||
show: false
|
||||
}
|
||||
},
|
||||
certStatus: {
|
||||
|
@ -185,6 +201,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
search: {
|
||||
show: false
|
||||
},
|
||||
form: { show: false },
|
||||
type: "number",
|
||||
column: {
|
||||
width: 200,
|
||||
|
@ -197,7 +214,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
show: false
|
||||
},
|
||||
type: "number",
|
||||
form: {},
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 100,
|
||||
sorter: true,
|
||||
|
@ -212,11 +229,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
type: "dict-switch",
|
||||
dict: dict({
|
||||
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: {
|
||||
width: 100,
|
||||
sorter: true
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { request } from "/src/api/service";
|
||||
|
||||
const apiPrefix = "/pay";
|
||||
const apiPrefix = "/payment";
|
||||
export async function Notify(type: string, query: any) {
|
||||
return await request({
|
||||
url: apiPrefix + `/notify/${type}`,
|
||||
method: "post",
|
||||
data: query,
|
||||
returnResponse: true
|
||||
unpack: false
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
<template>
|
||||
<div class="cd-payment-return">
|
||||
<a-card title="支付结果" class="mt-10">
|
||||
<div class="flex-o">
|
||||
<div class="flex-1">
|
||||
<a-tag v-if="payResult" color="green" class="m-0">支付成功</a-tag>
|
||||
<a-tag v-else color="red" class="m-0">支付失败</a-tag>
|
||||
</div>
|
||||
<div class="m-10">
|
||||
<a-button type="primary" @click="goHome">回首页</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
<div class="cd-payment-return w-100">
|
||||
<div v-if="payResult == null" class="flex-o m-20 w-100">
|
||||
<a-spin />
|
||||
</div>
|
||||
<a-result v-else-if="payResult" status="success" title="支付成功">
|
||||
<template #extra>
|
||||
<a-button key="console" type="primary" @click="goHome">回首页</a-button>
|
||||
</template>
|
||||
</a-result>
|
||||
<a-result v-else status="error" title="支付失败">
|
||||
<template #extra>
|
||||
<a-button key="console" type="primary" @click="goHome">回首页</a-button>
|
||||
</template>
|
||||
</a-result>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -40,6 +42,7 @@ async function check() {
|
|||
payResult.value = true;
|
||||
}
|
||||
}
|
||||
check();
|
||||
|
||||
const router = useRouter();
|
||||
function goHome() {
|
||||
|
|
|
@ -112,16 +112,20 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se
|
|||
}
|
||||
let pipeline = {
|
||||
title: form.domains[0] + "证书自动化",
|
||||
runnableType: "pipeline",
|
||||
stages: [
|
||||
{
|
||||
title: "证书申请阶段",
|
||||
maxTaskCount: 1,
|
||||
runnableType: "stage",
|
||||
tasks: [
|
||||
{
|
||||
title: "证书申请任务",
|
||||
runnableType: "task",
|
||||
steps: [
|
||||
{
|
||||
title: "申请证书",
|
||||
runnableType: "step",
|
||||
input: {
|
||||
renewDays: 35,
|
||||
...form
|
||||
|
@ -141,10 +145,18 @@ export default function ({ crudExpose, context: { certdFormRef, groupDictRef, se
|
|||
};
|
||||
pipeline = setRunnableIds(pipeline);
|
||||
|
||||
/**
|
||||
* // cert: 证书; backup: 备份; custom:自定义;
|
||||
* type: string;
|
||||
* // custom: 自定义; monitor: 监控;
|
||||
* from: string;
|
||||
*/
|
||||
const id = await api.Save({
|
||||
title: pipeline.title,
|
||||
content: JSON.stringify(pipeline),
|
||||
keepHistoryCount: 30
|
||||
keepHistoryCount: 30,
|
||||
type: "cert",
|
||||
from: "custom"
|
||||
});
|
||||
message.success("创建成功,请添加证书部署任务");
|
||||
router.push({ path: "/certd/pipeline/detail", query: { id, editMode: "true" } });
|
||||
|
|
|
@ -4,13 +4,17 @@
|
|||
<div class="title">套餐购买</div>
|
||||
</template>
|
||||
<div class="suite-buy-content">
|
||||
<div class="mb-10">
|
||||
<a-card>
|
||||
<div>套餐说明:多个套餐内的数量可以叠加</div>
|
||||
<div v-if="suiteIntro" v-html="suiteIntro"></div>
|
||||
</a-card>
|
||||
</div>
|
||||
<a-row :gutter="8">
|
||||
<a-row class="w-100" :gutter="8">
|
||||
<a-col :span="24">
|
||||
<a-card>
|
||||
<div class="suite-intro-box">
|
||||
<div>套餐说明:多个套餐内的数量可以叠加</div>
|
||||
<div v-if="suiteIntro" v-html="suiteIntro"></div>
|
||||
</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">
|
||||
<product-info :product="item" @order="doOrder" />
|
||||
</a-col>
|
||||
|
@ -57,11 +61,23 @@ loadSuiteIntro();
|
|||
background: #f0f2f5;
|
||||
.suite-buy-content {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
|
||||
.hr {
|
||||
border-top: 1px solid #cdcdcd;
|
||||
margin-top: 5px;
|
||||
padding-top: 5px;
|
||||
.suite-intro-box {
|
||||
//height: 60px;
|
||||
//overflow: hidden;
|
||||
//text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.suite-list {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
.my-suites {
|
||||
width: 360px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.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>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { GetPaymentTypes, OrderModalOpenReq, TradeCreate } from "/@/views/certd/suite/api";
|
||||
import SuiteValue from "/@/views/sys/suite/product/suite-value.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 { notification } from "ant-design-vue";
|
||||
import DurationValue from "/@/views/sys/suite/product/duration-value.vue";
|
||||
import { ref } from 'vue';
|
||||
import { GetPaymentTypes, OrderModalOpenReq, TradeCreate } from '/@/views/certd/suite/api';
|
||||
import SuiteValue from '/@/views/sys/suite/product/suite-value.vue';
|
||||
import PriceInput from '/@/views/sys/suite/product/price-input.vue';
|
||||
import { dict } from '@fast-crud/fast-crud';
|
||||
import { Modal, notification } from 'ant-design-vue';
|
||||
import DurationValue from '/@/views/sys/suite/product/duration-value.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const openRef = ref(false);
|
||||
|
||||
|
@ -60,6 +60,8 @@ const paymentsDictRef = dict({
|
|||
}
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
async function orderCreate() {
|
||||
console.log("orderCreate", formRef.value);
|
||||
if (!formRef.value.payType) {
|
||||
|
@ -80,22 +82,41 @@ async function orderCreate() {
|
|||
//易支付表单提交
|
||||
if (formRef.value.payType === "yizhifu") {
|
||||
doYizhifu(paymentReq);
|
||||
} else if (formRef.value.payType === "alipay") {
|
||||
//支付宝、
|
||||
doAlipay(paymentReq);
|
||||
} else if (formRef.value.payType === "wxpay") {
|
||||
//微信支付
|
||||
doWxpay(paymentReq);
|
||||
} else {
|
||||
//支付宝、微信支付
|
||||
window.open(paymentReq);
|
||||
notification.error({
|
||||
message: "暂不支持该支付方式"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
modal.open({
|
||||
title: "支付",
|
||||
content: "请在新页面完成支付",
|
||||
onOk: () => {
|
||||
Modal.confirm({
|
||||
title: "请在新页面完成支付",
|
||||
content: "是否确认已完成支付",
|
||||
onOk: async () => {
|
||||
openRef.value = false;
|
||||
router.push({
|
||||
path: "/"
|
||||
});
|
||||
},
|
||||
cancelText: "取消支付",
|
||||
onText: "已完成支付"
|
||||
okText: "已完成支付"
|
||||
});
|
||||
}
|
||||
|
||||
function doAlipay(paymentReq: any) {
|
||||
window.open(paymentReq.api);
|
||||
}
|
||||
|
||||
function doWxpay(paymentReq: any) {
|
||||
window.open(paymentReq.api);
|
||||
}
|
||||
|
||||
function doYizhifu(paymentReq: any) {
|
||||
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({
|
||||
url: apiPrefix + "/setDefault",
|
||||
url: apiPrefix + "/syncStatus",
|
||||
method: "post",
|
||||
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
|
||||
},
|
||||
rowHandle: {
|
||||
width: 100,
|
||||
width: 240,
|
||||
fixed: "right",
|
||||
buttons: {
|
||||
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: {
|
||||
name: "status",
|
||||
show: true
|
||||
|
|
|
@ -53,7 +53,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
groups: {
|
||||
base: {
|
||||
header: "基础信息",
|
||||
columns: ["title", "type", "isBootstrap", "disabled", "order", "intro"]
|
||||
columns: ["title", "type", "disabled", "order", "supportBuy", "intro"]
|
||||
},
|
||||
content: {
|
||||
header: "套餐内容",
|
||||
|
@ -244,12 +244,12 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "是", value: true, color: "success" },
|
||||
{ label: "否", value: false, color: "gray" }
|
||||
{ label: "支持购买", value: true, color: "success" },
|
||||
{ label: "不能购买", value: false, color: "gray" }
|
||||
]
|
||||
}),
|
||||
form: {
|
||||
value: false
|
||||
value: true
|
||||
},
|
||||
column: {
|
||||
width: 120
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { durationDict } from "/@/views/certd/suite/api";
|
||||
|
||||
defineOptions({
|
||||
name: "DurationValue"
|
||||
});
|
||||
const props = defineProps<{
|
||||
modelValue: number;
|
||||
}>();
|
||||
|
|
|
@ -1,17 +1,34 @@
|
|||
<template>
|
||||
<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>
|
||||
<span v-else class="price-text">{{ priceLabel }}</span>
|
||||
<span v-else class="price-text" :style="style">{{ priceLabel }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue?: number;
|
||||
edit?: boolean;
|
||||
}>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
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(() => {
|
||||
if (props.modelValue == null) {
|
||||
|
@ -37,7 +54,6 @@ const onPriceChange = (price: number) => {
|
|||
<style lang="less">
|
||||
.price-input {
|
||||
.price-text {
|
||||
font-size: 18px;
|
||||
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({
|
||||
url: apiPrefix + "/setDefault",
|
||||
url: apiPrefix + "/updatePaid",
|
||||
method: "post",
|
||||
data: { id }
|
||||
});
|
||||
}
|
||||
|
||||
export async function SetDisabled(id: any, disabled: boolean) {
|
||||
export async function SyncStatus(id: any) {
|
||||
return await request({
|
||||
url: apiPrefix + "/setDisabled",
|
||||
url: apiPrefix + "/syncStatus",
|
||||
method: "post",
|
||||
data: { id, disabled }
|
||||
data: { id }
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq,
|
|||
import { useUserStore } from "/@/store/modules/user";
|
||||
import { useSettingStore } from "/@/store/modules/settings";
|
||||
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 {
|
||||
const router = useRouter();
|
||||
|
@ -56,9 +58,63 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
editRequest,
|
||||
delRequest
|
||||
},
|
||||
actionbar: {
|
||||
buttons: {
|
||||
add: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
toolbar: { show: false },
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right"
|
||||
width: 320,
|
||||
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: {
|
||||
id: {
|
||||
|
@ -72,156 +128,88 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
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: "设置默认",
|
||||
tradeNo: {
|
||||
title: "订单号",
|
||||
type: "text",
|
||||
search: { show: true },
|
||||
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>
|
||||
);
|
||||
}
|
||||
width: 250
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
title: "禁用/启用",
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "启用", value: false, color: "success" },
|
||||
{ label: "禁用", value: true, color: "error" }
|
||||
]
|
||||
}),
|
||||
form: {
|
||||
value: false
|
||||
},
|
||||
title: {
|
||||
title: "商品名称",
|
||||
type: "text",
|
||||
search: { show: true },
|
||||
column: {
|
||||
width: 150
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
title: "时长",
|
||||
type: "number",
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
name: DurationValue,
|
||||
vModel: "modelValue"
|
||||
}
|
||||
}
|
||||
},
|
||||
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: {
|
||||
title: "创建时间",
|
||||
type: "datetime",
|
||||
|
|
|
@ -2,11 +2,8 @@
|
|||
<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>
|
||||
订单管理
|
||||
<span class="sub"> </span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
|
@ -27,7 +24,7 @@ import { message, Modal } from "ant-design-vue";
|
|||
import { DeleteBatch } from "./api";
|
||||
|
||||
defineOptions({
|
||||
name: "CnameProvider"
|
||||
name: "TradeManager"
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
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()
|
||||
@Controller('/api/monitor/site')
|
||||
export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||
@Controller('/api/monitor/cert')
|
||||
export class CertInfoController extends CrudController<CertInfoService> {
|
||||
@Inject()
|
||||
service: SiteInfoService;
|
||||
service: CertInfoService;
|
||||
@Inject()
|
||||
authService: AuthService;
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
|
||||
getService(): SiteInfoService {
|
||||
getService(): CertInfoService {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
|
@ -22,11 +24,23 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
|
|||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
|
||||
const res = await this.service.page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import { Constants, CrudController } from '@certd/lib-server';
|
||||
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()
|
||||
@Controller('/api/monitor/cert')
|
||||
export class CertInfoController extends CrudController<CertInfoService> {
|
||||
@Controller('/api/monitor/site')
|
||||
export class SiteInfoController extends CrudController<SiteInfoService> {
|
||||
@Inject()
|
||||
service: CertInfoService;
|
||||
service: SiteInfoService;
|
||||
@Inject()
|
||||
authService: AuthService;
|
||||
|
||||
getService(): CertInfoService {
|
||||
getService(): SiteInfoService {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
|
@ -22,7 +21,6 @@ export class CertInfoController extends CrudController<CertInfoService> {
|
|||
async page(@Body(ALL) body: any) {
|
||||
body.query = body.query ?? {};
|
||||
body.query.userId = this.getUserId();
|
||||
|
||||
const res = await this.service.page({
|
||||
query: body.query,
|
||||
page: body.page,
|
||||
|
|
|
@ -6,7 +6,7 @@ import { nanoid } from 'nanoid';
|
|||
import crypto from 'crypto';
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class AutoInitSite {
|
||||
@Inject()
|
||||
userService: UserService;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { logger } from '@certd/basic';
|
|||
import { SysSettingsService } from '@certd/lib-server';
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class AutoRegisterCron {
|
||||
@Inject()
|
||||
pipelineService: PipelineService;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Application } from '@midwayjs/koa';
|
|||
import { httpsServer, HttpsServerOptions } from './https/server.js';
|
||||
|
||||
@Autoload()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class AutoZPrint {
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
|
|
@ -27,7 +27,7 @@ export type EmailConfig = {
|
|||
usePlus?: boolean;
|
||||
} & SMTPConnection.Options;
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class EmailService implements IEmailService {
|
||||
@Inject()
|
||||
settingsService: UserSettingsService;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { CommonProviders } from './common-provider.js';
|
|||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class CnameProviderService extends BaseService<CnameProviderEntity> {
|
||||
@InjectEntityModel(CnameProviderEntity)
|
||||
repository: Repository<CnameProviderEntity>;
|
||||
|
|
|
@ -26,7 +26,7 @@ type CnameCheckCacheValue = {
|
|||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
@InjectEntityModel(CnameRecordEntity)
|
||||
repository: Repository<CnameRecordEntity>;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SqlAdapter } from './d.js';
|
|||
import { MysqlAdapter } from './mysql.js';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class DbAdapter implements SqlAdapter {
|
||||
adapter: SqlAdapter;
|
||||
@Config('typeorm.dataSource.default.type')
|
||||
|
|
|
@ -8,7 +8,7 @@ import { UserSettingsEntity } from '../entity/user-settings.js';
|
|||
* 授权
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class UserSettingsService extends BaseService<UserSettingsEntity> {
|
||||
@InjectEntityModel(UserSettingsEntity)
|
||||
repository: Repository<UserSettingsEntity>;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { PipelineEntity } from '../../pipeline/entity/pipeline.js';
|
||||
|
||||
@Entity('cd_cert_info')
|
||||
export class CertInfoEntity {
|
||||
|
@ -51,4 +52,6 @@ export class CertInfoEntity {
|
|||
default: () => 'CURRENT_TIMESTAMP',
|
||||
})
|
||||
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 { BaseService } from '@certd/lib-server';
|
||||
import { BaseService, PageReq } from '@certd/lib-server';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { CertInfoEntity } from '../entity/cert-info.js';
|
||||
|
@ -14,6 +14,10 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
|||
return this.repository;
|
||||
}
|
||||
|
||||
async page(pageReq: PageReq<CertInfoEntity>) {
|
||||
return await super.page(pageReq);
|
||||
}
|
||||
|
||||
async getUserDomainCount(userId: number) {
|
||||
if (!userId) {
|
||||
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({
|
||||
where: {
|
||||
pipelineId,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
const bean = new CertInfoEntity();
|
||||
|
@ -36,11 +41,21 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
|
|||
} else {
|
||||
//create
|
||||
bean.pipelineId = pipelineId;
|
||||
bean.userId = userId;
|
||||
if (!domains || domains.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bean.domain = domains[0];
|
||||
bean.domains = domains.join(',');
|
||||
bean.domainCount = domains.length;
|
||||
if (!domains || domains.length === 0) {
|
||||
bean.domain = '';
|
||||
bean.domains = '';
|
||||
bean.domainCount = 0;
|
||||
} else {
|
||||
bean.domain = domains[0];
|
||||
bean.domains = domains.join(',');
|
||||
bean.domainCount = domains.length;
|
||||
}
|
||||
|
||||
await this.addOrUpdate(bean);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { pluginGroups, pluginRegistry } from '@certd/pipeline';
|
|||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class BuiltInPluginService {
|
||||
getList() {
|
||||
const collection = pluginRegistry.storage;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { HistoryLogEntity } from '../entity/history-log.js';
|
|||
* 证书申请
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class HistoryLogService extends BaseService<HistoryLogEntity> {
|
||||
@InjectEntityModel(HistoryLogEntity)
|
||||
repository: Repository<HistoryLogEntity>;
|
||||
|
|
|
@ -16,7 +16,7 @@ import { logger } from '@certd/basic';
|
|||
* 证书申请
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class HistoryService extends BaseService<HistoryEntity> {
|
||||
@InjectEntityModel(HistoryEntity)
|
||||
repository: Repository<HistoryEntity>;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { EmailService } from '../../basic/service/email-service.js';
|
|||
import { isComm } from '@certd/plus-core';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class NotificationService extends BaseService<NotificationEntity> {
|
||||
@InjectEntityModel(NotificationEntity)
|
||||
repository: Repository<NotificationEntity>;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { PipelineGroupEntity } from '../entity/pipeline-group.js';
|
|||
import { merge } from 'lodash-es';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PipelineGroupService extends BaseService<PipelineGroupEntity> {
|
||||
@InjectEntityModel(PipelineGroupEntity)
|
||||
repository: Repository<PipelineGroupEntity>;
|
||||
|
|
|
@ -160,14 +160,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
old = await this.info(bean.id);
|
||||
}
|
||||
const pipeline = JSON.parse(bean.content || '{}');
|
||||
RunnableCollection.initPipelineRunnableType(pipeline);
|
||||
const isUpdate = bean.id > 0 && old != null;
|
||||
|
||||
let domains = [];
|
||||
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
||||
if (runnable.runnableType === 'step' && runnable.type.startsWith('CertApply')) {
|
||||
domains = runnable.input.domains || [];
|
||||
}
|
||||
});
|
||||
if (pipeline.stages) {
|
||||
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
||||
if (runnable.runnableType === 'step' && runnable.type.startsWith('CertApply')) {
|
||||
domains = runnable.input.domains || [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!isUpdate) {
|
||||
//如果是添加,校验数量
|
||||
|
@ -188,7 +191,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
await this.registerTriggerById(bean.id);
|
||||
|
||||
//保存域名信息到certInfo表
|
||||
await this.certInfoService.updateDomains(pipeline.id, domains);
|
||||
await this.certInfoService.updateDomains(pipeline.id, pipeline.userId || bean.userId, domains);
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
@ -622,4 +625,17 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||
async getUserPipelineCount(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()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class StorageService extends BaseService<StorageEntity> {
|
||||
@InjectEntityModel(StorageEntity)
|
||||
repository: Repository<StorageEntity>;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
|||
import { SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class UrlService implements IUrlService {
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { IPluginConfigService, PluginConfig } from '@certd/pipeline';
|
|||
import { PluginConfigService } from './plugin-config-service.js';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PluginConfigGetter implements IPluginConfigService {
|
||||
@Inject()
|
||||
pluginConfigService: PluginConfigService;
|
||||
|
|
|
@ -19,7 +19,7 @@ export type PluginFindReq = {
|
|||
type: string;
|
||||
};
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PluginConfigService {
|
||||
@Inject()
|
||||
pluginService: PluginService;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { BuiltInPluginService } from '../../pipeline/service/builtin-plugin-serv
|
|||
import { merge } from 'lodash-es';
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PluginService extends BaseService<PluginEntity> {
|
||||
@InjectEntityModel(PluginEntity)
|
||||
repository: Repository<PluginEntity>;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { RoleService } from './role-service.js';
|
|||
* 权限校验
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class AuthService {
|
||||
@Inject()
|
||||
roleService: RoleService;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { PermissionEntity } from '../entity/permission.js';
|
|||
* 权限资源
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class PermissionService extends BaseService<PermissionEntity> {
|
||||
@InjectEntityModel(PermissionEntity)
|
||||
repository: Repository<PermissionEntity>;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { RolePermissionEntity } from '../entity/role-permission.js';
|
|||
* 角色->权限
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class RolePermissionService extends BaseService<RolePermissionEntity> {
|
||||
@InjectEntityModel(RolePermissionEntity)
|
||||
repository: Repository<RolePermissionEntity>;
|
||||
|
|
|
@ -13,7 +13,7 @@ import { LRUCache } from 'lru-cache';
|
|||
* 角色
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class RoleService extends BaseService<RoleEntity> {
|
||||
@InjectEntityModel(RoleEntity)
|
||||
repository: Repository<RoleEntity>;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { UserRoleEntity } from '../entity/user-role.js';
|
|||
* 用户->角色
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class UserRoleService extends BaseService<UserRoleEntity> {
|
||||
@InjectEntityModel(UserRoleEntity)
|
||||
repository: Repository<UserRoleEntity>;
|
||||
|
|
|
@ -19,7 +19,7 @@ export type RegisterType = 'username' | 'mobile' | 'email';
|
|||
* 系统用户
|
||||
*/
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Singleton)
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class UserService extends BaseService<UserEntity> {
|
||||
@InjectEntityModel(UserEntity)
|
||||
repository: Repository<UserEntity>;
|
||||
|
|
Loading…
Reference in New Issue