mirror of https://github.com/certd/certd
chore: 1
parent
584378a32b
commit
b817cb4a1b
|
@ -30,11 +30,6 @@ services:
|
||||||
# 配置规则: certd_ + 配置项, 点号用_代替
|
# 配置规则: certd_ + 配置项, 点号用_代替
|
||||||
# ↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
# ↓↓↓↓ ----------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false
|
||||||
- certd_system_resetAdminPasswd=false
|
- certd_system_resetAdminPasswd=false
|
||||||
# ↓↓↓↓ -------------------------------- 默认同时启动https,https访问地址https://your.domain:7002
|
|
||||||
#- certd_https_key=./data/ssl/cert.key
|
|
||||||
#- certd_https_cert=./data/ssl/cert.crt
|
|
||||||
#- certd_https_enabled=true
|
|
||||||
#- certd_https_port=7002
|
|
||||||
# ↓↓↓↓ ------------------------------- 使用postgresql数据库
|
# ↓↓↓↓ ------------------------------- 使用postgresql数据库
|
||||||
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
# - certd_flyway_scriptDir=./db/migration-pg # 升级脚本目录
|
||||||
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
# - certd_typeorm_dataSource_default_type=postgres # 数据库类型
|
||||||
|
|
|
@ -84,6 +84,13 @@ export async function GetFiles(pipelineId: number) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function GetCount() {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/count",
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export type CertInfo = {
|
export type CertInfo = {
|
||||||
crt: string;
|
crt: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
|
|
@ -438,6 +438,9 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
|
||||||
status: {
|
status: {
|
||||||
title: "状态",
|
title: "状态",
|
||||||
type: "dict-select",
|
type: "dict-select",
|
||||||
|
search: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: statusUtil.getOptions()
|
data: statusUtil.getOptions()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<fs-page class="fs-pipeline-detail">
|
<fs-page class="fs-pipeline-detail">
|
||||||
<pipeline-edit v-model:edit-mode="editMode" :pipeline-id="pipelineId" :options="pipelineOptionsRef"></pipeline-edit>
|
<pipeline-edit v-model:edit-mode="editMode" :pipeline-id="pipelineId" :options="pipelineOptionsRef"></pipeline-edit>
|
||||||
<a-tour v-model:current="tourCurrent" :open="tourOpen" :steps="tourSteps" @close="tourHandleOpen(false)" />
|
<a-tour v-bind="tour" v-model:current="tour.current" />
|
||||||
</fs-page>
|
</fs-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import * as api from "./api";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { PipelineDetail, PipelineOptions, PluginGroups, RunHistory } from "./pipeline/type";
|
import { PipelineDetail, PipelineOptions, PluginGroups, RunHistory } from "./pipeline/type";
|
||||||
import { TourProps } from "ant-design-vue";
|
import { TourProps } from "ant-design-vue";
|
||||||
|
import { LocalStorage } from "/@/utils/util.storage";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "PipelineDetail"
|
name: "PipelineDetail"
|
||||||
|
@ -24,7 +25,7 @@ const pipelineId: Ref = ref(route.query.id);
|
||||||
const pipelineOptions: PipelineOptions = {
|
const pipelineOptions: PipelineOptions = {
|
||||||
async getPipelineDetail({ pipelineId }) {
|
async getPipelineDetail({ pipelineId }) {
|
||||||
const detail = await api.GetDetail(pipelineId);
|
const detail = await api.GetDetail(pipelineId);
|
||||||
onLoaded();
|
onLoaded(detail);
|
||||||
return {
|
return {
|
||||||
pipeline: {
|
pipeline: {
|
||||||
id: detail.pipeline.id,
|
id: detail.pipeline.id,
|
||||||
|
@ -70,30 +71,37 @@ if (route.query.editMode !== "false") {
|
||||||
}
|
}
|
||||||
|
|
||||||
function useTour() {
|
function useTour() {
|
||||||
const tourOpen = ref<boolean>(false);
|
const tour = ref({
|
||||||
|
open: false,
|
||||||
const tourCurrent = ref(0);
|
current: 0,
|
||||||
//@ts-ignore
|
steps: [],
|
||||||
const tourSteps: TourProps["steps"] = ref([]);
|
onClose: () => {
|
||||||
|
tour.value.open = false;
|
||||||
|
},
|
||||||
|
onFinish: () => {
|
||||||
|
tour.value.open = false;
|
||||||
|
LocalStorage.set("tour-off", true, 999999999);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const tourHandleOpen = (val: boolean): void => {
|
const tourHandleOpen = (val: boolean): void => {
|
||||||
initSteps();
|
initSteps();
|
||||||
tourOpen.value = val;
|
tour.value.open = val;
|
||||||
};
|
};
|
||||||
|
|
||||||
function initSteps() {
|
function initSteps() {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
tourSteps.value = [
|
tour.value.steps = [
|
||||||
{
|
{
|
||||||
title: "恭喜创建证书流水线成功",
|
title: "恭喜创建证书流水线成功",
|
||||||
description: "这里就是我们刚创建的证书任务,点击可以修改证书申请参数",
|
description: "这里就是我们刚创建的证书任务,点击可以修改证书申请参数",
|
||||||
target: () => {
|
target: () => {
|
||||||
return document.querySelector(".pipeline .stages .stage_0 .task");
|
return document.querySelector(".pipeline .stages .stage_0 .task");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "添加部署证书任务",
|
title: "添加部署证书任务",
|
||||||
description: "证书申请成功之后还需要部署证书,点击这里可以添加部署任务",
|
description: "证书申请成功之后还需要部署证书,点击这里可以添加证书部署任务",
|
||||||
target: () => {
|
target: () => {
|
||||||
return document.querySelector(".pipeline .stages .last-stage .tasks .task");
|
return document.querySelector(".pipeline .stages .last-stage .tasks .task");
|
||||||
}
|
}
|
||||||
|
@ -109,18 +117,28 @@ function useTour() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tourOpen,
|
tour,
|
||||||
tourCurrent,
|
|
||||||
tourSteps,
|
|
||||||
tourHandleOpen
|
tourHandleOpen
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { tourOpen, tourCurrent, tourSteps, tourHandleOpen } = useTour();
|
const { tour, tourHandleOpen } = useTour();
|
||||||
|
|
||||||
async function onLoaded() {
|
async function onLoaded(pipeline: PipelineDetail) {
|
||||||
await nextTick();
|
const count = LocalStorage.get("pipeline-count") ?? 0;
|
||||||
tourHandleOpen(true);
|
if (count > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const off = LocalStorage.get("tour-off") ?? false;
|
||||||
|
if (off) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await api.GetCount();
|
||||||
|
LocalStorage.set("pipeline-count", res.count);
|
||||||
|
if (res.count <= 1) {
|
||||||
|
await nextTick();
|
||||||
|
tourHandleOpen(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div>
|
<div>
|
||||||
<span>您好,{{ userInfo.nickName || userInfo.username }}。 欢迎使用 {{ siteInfo.title }}</span>
|
<span>您好,{{ userInfo.nickName || userInfo.username }}, 欢迎使用 【{{ siteInfo.title }}】</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a-tag color="green" class="flex-inline"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
|
<a-tag color="green" class="flex-inline"> <fs-icon icon="ion:time-outline" class="mr-5"></fs-icon> {{ now }}</a-tag>
|
||||||
|
@ -215,7 +215,7 @@ onMounted(async () => {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
> div {
|
> div {
|
||||||
margin: 2px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,4 +103,10 @@ export class PipelineController extends CrudController<PipelineService> {
|
||||||
await this.service.cancel(historyId);
|
await this.service.cancel(historyId);
|
||||||
return this.ok({});
|
return this.ok({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/count', { summary: Constants.per.authOnly })
|
||||||
|
async count() {
|
||||||
|
const count = await this.service.count({ userId: this.getUserId() });
|
||||||
|
return this.ok({ count });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface SqlAdapter {
|
||||||
|
date(columnName: string): string;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { SqliteAdapter } from './sqlite.js';
|
||||||
|
import { PostgresqlAdapter } from './postgresql.js';
|
||||||
|
import { Config, Init, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
|
import { SqlAdapter } from './d.js';
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Singleton)
|
||||||
|
export class DbAdapter implements SqlAdapter {
|
||||||
|
adapter: SqlAdapter;
|
||||||
|
@Config('typeorm.dataSource.default.type')
|
||||||
|
dbType: string;
|
||||||
|
|
||||||
|
@Init()
|
||||||
|
async init() {
|
||||||
|
if (this.isSqlite()) {
|
||||||
|
this.adapter = new SqliteAdapter();
|
||||||
|
} else if (this.isPostgresql()) {
|
||||||
|
this.adapter = new PostgresqlAdapter();
|
||||||
|
} else {
|
||||||
|
throw new Error(`dbType ${this.dbType} not support`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isSqlite() {
|
||||||
|
return this.dbType === 'better-sqlite3';
|
||||||
|
}
|
||||||
|
isPostgresql() {
|
||||||
|
return this.dbType === 'postgres';
|
||||||
|
}
|
||||||
|
|
||||||
|
date(columnName: string) {
|
||||||
|
return this.adapter.date(columnName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { SqlAdapter } from './d.js';
|
||||||
|
|
||||||
|
export class PostgresqlAdapter implements SqlAdapter {
|
||||||
|
date(columnName: string) {
|
||||||
|
return `to_char(${columnName}, 'YYYY-MM-DD')`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { SqlAdapter } from './d.js';
|
||||||
|
|
||||||
|
export class SqliteAdapter implements SqlAdapter {
|
||||||
|
date(columnName: string) {
|
||||||
|
return `date(${columnName}, 'localtime')`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,10 @@ import { HistoryEntity } from '../entity/history.js';
|
||||||
import { PipelineEntity } from '../entity/pipeline.js';
|
import { PipelineEntity } from '../entity/pipeline.js';
|
||||||
import { HistoryDetail } from '../entity/vo/history-detail.js';
|
import { HistoryDetail } from '../entity/vo/history-detail.js';
|
||||||
import { HistoryLogService } from './history-log-service.js';
|
import { HistoryLogService } from './history-log-service.js';
|
||||||
import { FileItem, Pipeline, RunnableCollection } from '@certd/pipeline';
|
import { FileItem, FileStore, logger, Pipeline, RunnableCollection } from '@certd/pipeline';
|
||||||
import { FileStore } from '@certd/pipeline';
|
|
||||||
import { logger } from '@certd/pipeline';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { DbAdapter } from '../../db/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 证书申请
|
* 证书申请
|
||||||
*/
|
*/
|
||||||
|
@ -24,6 +24,9 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||||
@Inject()
|
@Inject()
|
||||||
logService: HistoryLogService;
|
logService: HistoryLogService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
dbAdapter: DbAdapter;
|
||||||
|
|
||||||
@Config('certd')
|
@Config('certd')
|
||||||
private certdConfig: any;
|
private certdConfig: any;
|
||||||
|
|
||||||
|
@ -178,8 +181,6 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||||
async countPerDay(param: { days: number; userId?: any }) {
|
async countPerDay(param: { days: number; userId?: any }) {
|
||||||
const todayEnd = dayjs().endOf('day');
|
const todayEnd = dayjs().endOf('day');
|
||||||
const where: any = {
|
const where: any = {
|
||||||
// 0点
|
|
||||||
// userId: param.userId,
|
|
||||||
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
||||||
};
|
};
|
||||||
if (param.userId > 0) {
|
if (param.userId > 0) {
|
||||||
|
@ -187,8 +188,8 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||||
}
|
}
|
||||||
const result = await this.getRepository()
|
const result = await this.getRepository()
|
||||||
.createQueryBuilder('main')
|
.createQueryBuilder('main')
|
||||||
.select('date(main.createTime) AS date') // 将UNIX时间戳转换为日期
|
.select(`${this.dbAdapter.date('main.createTime')} AS date`) // 将UNIX时间戳转换为日期
|
||||||
.addSelect('COUNT(*) AS count')
|
.addSelect('COUNT(1) AS count')
|
||||||
.where(where)
|
.where(where)
|
||||||
.groupBy('date')
|
.groupBy('date')
|
||||||
.getRawMany();
|
.getRawMany();
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { CnameRecordService } from '../../cname/service/cname-record-service.js'
|
||||||
import { CnameProxyService } from './cname-proxy-service.js';
|
import { CnameProxyService } from './cname-proxy-service.js';
|
||||||
import { PluginConfigGetter } from '../../plugin/service/plugin-config-getter.js';
|
import { PluginConfigGetter } from '../../plugin/service/plugin-config-getter.js';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { DbAdapter } from '../../db/index.js';
|
||||||
|
|
||||||
const runningTasks: Map<string | number, Executor> = new Map();
|
const runningTasks: Map<string | number, Executor> = new Map();
|
||||||
const freeCount = 10;
|
const freeCount = 10;
|
||||||
|
@ -60,6 +61,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
@Config('certd')
|
@Config('certd')
|
||||||
private certdConfig: any;
|
private certdConfig: any;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
dbAdapter: DbAdapter;
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
|
@ -522,8 +526,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||||
const todayEnd = dayjs().endOf('day');
|
const todayEnd = dayjs().endOf('day');
|
||||||
const result = await this.getRepository()
|
const result = await this.getRepository()
|
||||||
.createQueryBuilder('main')
|
.createQueryBuilder('main')
|
||||||
.select('date(main.createTime) AS date') // 将UNIX时间戳转换为日期
|
.select(`${this.dbAdapter.date('main.createTime')} AS date`) // 将UNIX时间戳转换为日期
|
||||||
.addSelect('COUNT(*) AS count')
|
.addSelect('COUNT(1) AS count')
|
||||||
.where({
|
.where({
|
||||||
// 0点
|
// 0点
|
||||||
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
||||||
|
|
|
@ -4,18 +4,15 @@ import { MoreThan, Repository } from 'typeorm';
|
||||||
import { UserEntity } from '../entity/user.js';
|
import { UserEntity } from '../entity/user.js';
|
||||||
import * as _ from 'lodash-es';
|
import * as _ from 'lodash-es';
|
||||||
import md5 from 'md5';
|
import md5 from 'md5';
|
||||||
import { CommonException, FileService } from '@certd/lib-server';
|
import { BaseService, CommonException, Constants, FileService, SysInstallInfo, SysSettingsService } from '@certd/lib-server';
|
||||||
import { BaseService } from '@certd/lib-server';
|
|
||||||
import { RoleService } from './role-service.js';
|
import { RoleService } from './role-service.js';
|
||||||
import { PermissionService } from './permission-service.js';
|
import { PermissionService } from './permission-service.js';
|
||||||
import { UserRoleService } from './user-role-service.js';
|
import { UserRoleService } from './user-role-service.js';
|
||||||
import { Constants } from '@certd/lib-server';
|
|
||||||
import { UserRoleEntity } from '../entity/user-role.js';
|
import { UserRoleEntity } from '../entity/user-role.js';
|
||||||
import bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
import { SysSettingsService } from '@certd/lib-server';
|
|
||||||
import { SysInstallInfo } from '@certd/lib-server';
|
|
||||||
import { RandomUtil } from '../../../../utils/random.js';
|
import { RandomUtil } from '../../../../utils/random.js';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import { DbAdapter } from '../../../db/index.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统用户
|
* 系统用户
|
||||||
|
@ -37,6 +34,8 @@ export class UserService extends BaseService<UserEntity> {
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
fileService: FileService;
|
fileService: FileService;
|
||||||
|
@Inject()
|
||||||
|
dbAdapter: DbAdapter;
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
getRepository() {
|
getRepository() {
|
||||||
|
@ -260,8 +259,8 @@ export class UserService extends BaseService<UserEntity> {
|
||||||
const todayEnd = dayjs().endOf('day');
|
const todayEnd = dayjs().endOf('day');
|
||||||
const result = await this.getRepository()
|
const result = await this.getRepository()
|
||||||
.createQueryBuilder('main')
|
.createQueryBuilder('main')
|
||||||
.select('date(main.createTime) AS date') // 将UNIX时间戳转换为日期
|
.select(`${this.dbAdapter.date('main.createTime')} AS date`) // 将UNIX时间戳转换为日期
|
||||||
.addSelect('COUNT(*) AS count')
|
.addSelect('COUNT(1) AS count')
|
||||||
.where({
|
.where({
|
||||||
// 0点
|
// 0点
|
||||||
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
||||||
|
|
Loading…
Reference in New Issue