pull/189/head
xiaojunnuo 2024-09-05 14:33:45 +08:00
parent 1dd9a8d4d3
commit ecad7f58c1
13 changed files with 89 additions and 14 deletions

View File

@ -1,4 +1,10 @@
import { logger } from "../utils/index.js"; import { logger } from "../utils/index.js";
import { setLogger } from "@certd/plus"; import { setLogger, isPlus } from "@certd/plus";
setLogger(logger); setLogger(logger);
export * from "@certd/plus"; export * from "@certd/plus";
export function checkPlus() {
if (!isPlus()) {
throw new Error("此为专业版功能,请升级到专业版");
}
}

View File

@ -10,6 +10,7 @@ RUN cd /workspace/certd-server && pnpm install && npm run build-on-docker
FROM node:20-alpine FROM node:20-alpine
RUN apk add --no-cache openssl
WORKDIR /app/ WORKDIR /app/
COPY --from=builder /workspace/certd-server/ /app/ COPY --from=builder /workspace/certd-server/ /app/
RUN chmod +x /app/tools/linux/* RUN chmod +x /app/tools/linux/*

View File

@ -3,7 +3,7 @@ import PiAccessSelector from "../views/certd/access/access-selector/index.vue";
import PiDnsProviderSelector from "./dns-provider-selector/index.vue"; import PiDnsProviderSelector from "./dns-provider-selector/index.vue";
import PiOutputSelector from "../views/certd/pipeline/pipeline/component/output-selector/index.vue"; import PiOutputSelector from "../views/certd/pipeline/pipeline/component/output-selector/index.vue";
import PiEditable from "./editable.vue"; import PiEditable from "./editable.vue";
import VipButton from "./vip-button/index.vue"; import vip from "./vip-button/install.js";
import { CheckCircleOutlined, InfoCircleOutlined, UndoOutlined } from "@ant-design/icons-vue"; import { CheckCircleOutlined, InfoCircleOutlined, UndoOutlined } from "@ant-design/icons-vue";
import CronEditor from "./cron-editor/index.vue"; import CronEditor from "./cron-editor/index.vue";
import { CronLight } from "@vue-js-cron/light"; import { CronLight } from "@vue-js-cron/light";
@ -15,12 +15,14 @@ export default {
app.component("PiEditable", PiEditable); app.component("PiEditable", PiEditable);
app.component("PiOutputSelector", PiOutputSelector); app.component("PiOutputSelector", PiOutputSelector);
app.component("PiDnsProviderSelector", PiDnsProviderSelector); app.component("PiDnsProviderSelector", PiDnsProviderSelector);
app.component("VipButton", VipButton);
app.component("CronLight", CronLight); app.component("CronLight", CronLight);
app.component("CronEditor", CronEditor); app.component("CronEditor", CronEditor);
app.component("CheckCircleOutlined", CheckCircleOutlined); app.component("CheckCircleOutlined", CheckCircleOutlined);
app.component("InfoCircleOutlined", InfoCircleOutlined); app.component("InfoCircleOutlined", InfoCircleOutlined);
app.component("UndoOutlined", UndoOutlined); app.component("UndoOutlined", UndoOutlined);
app.use(vip);
} }
}; };

View File

@ -0,0 +1,23 @@
import { message, notification } from "ant-design-vue";
import { useUserStore } from "/@/store/modules/user";
export default {
mounted(el: any, binding: any, vnode: any) {
const { value } = binding;
const userStore = useUserStore();
el.className = el.className + " need-plus";
if (!userStore.isPlus) {
function checkPlus() {
// 事件处理代码
notification.warn({
message: "此为专业版功能,请升级到专业版"
});
}
el.addEventListener("click", function (event: any) {
checkPlus();
});
el.addEventListener("move", function (event: any) {
checkPlus();
});
}
}
};

View File

@ -0,0 +1,6 @@
import VipButton from "./index.vue";
import plus from "./directive.js";
export default function (app: any) {
app.component("VipButton", VipButton);
app.directive("plus", plus);
}

View File

@ -7,7 +7,7 @@ import * as UserApi from "/src/api/modules/api.user";
import { RegisterReq } from "/src/api/modules/api.user"; import { RegisterReq } from "/src/api/modules/api.user";
// @ts-ignore // @ts-ignore
import { LoginReq, UserInfoRes } from "/@/api/modules/api.user"; import { LoginReq, UserInfoRes } from "/@/api/modules/api.user";
import { Modal, notification } from "ant-design-vue"; import { message, Modal, notification } from "ant-design-vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { mitter } from "/src/utils/util.mitt"; import { mitter } from "/src/utils/util.mitt";
@ -67,7 +67,14 @@ export const useUserStore = defineStore({
LocalStorage.remove(TOKEN_KEY); LocalStorage.remove(TOKEN_KEY);
LocalStorage.remove(USER_INFO_KEY); LocalStorage.remove(USER_INFO_KEY);
}, },
checkPlus() {
if (!this.isPlus) {
notification.warn({
message: "此为专业版功能,请先升级到专业版"
});
throw new Error("此为专业版功能,请升级到专业版");
}
},
async register(user: RegisterReq) { async register(user: RegisterReq) {
await UserApi.register(user); await UserApi.register(user);
notification.success({ notification.success({

View File

@ -162,3 +162,7 @@ h1, h2, h3, h4, h5, h6 {
justify-content: center; justify-content: center;
} }
} }
.need-plus {
color: #c5913f !important;
}

View File

@ -191,6 +191,7 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
}, },
copy: { copy: {
click: async (context) => { click: async (context) => {
userStore.checkPlus();
const { ui } = useUi(); const { ui } = useUi();
// @ts-ignore // @ts-ignore
let row = context[ui.tableColumn.row]; let row = context[ui.tableColumn.row];
@ -200,7 +201,8 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
row: row, row: row,
index: context.index index: context.index
}); });
} },
class: "need-plus"
}, },
config: { config: {
order: 1, order: 1,

View File

@ -43,7 +43,7 @@
<a-button type="primary" @click="stepAdd(currentTask)"></a-button> <a-button type="primary" @click="stepAdd(currentTask)"></a-button>
</template> </template>
</a-descriptions> </a-descriptions>
<v-draggable v-model="currentTask.steps" class="step-list" handle=".handle" item-key="id"> <v-draggable v-model="currentTask.steps" class="step-list" handle=".handle" item-key="id" :disabled="!userStore.isPlus">
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="step-row"> <div class="step-row">
<div class="text"> <div class="text">
@ -54,7 +54,7 @@
<a key="edit" @click="stepEdit(currentTask, element, index)">编辑</a> <a key="edit" @click="stepEdit(currentTask, element, index)">编辑</a>
<a key="edit" @click="stepCopy(currentTask, element, index)">复制</a> <a key="edit" @click="stepCopy(currentTask, element, index)">复制</a>
<a key="remove" @click="stepDelete(currentTask, index)">删除</a> <a key="remove" @click="stepDelete(currentTask, index)">删除</a>
<fs-icon class="icon-button handle" title="拖动排序" icon="ion:move-outline"></fs-icon> <fs-icon v-plus class="icon-button handle" title="拖动排序" icon="ion:move-outline"></fs-icon>
</div> </div>
</div> </div>
</template> </template>
@ -83,6 +83,7 @@ import PiStepForm from "../step-form/index.vue";
import { Modal } from "ant-design-vue"; import { Modal } from "ant-design-vue";
import { CopyOutlined } from "@ant-design/icons-vue"; import { CopyOutlined } from "@ant-design/icons-vue";
import VDraggable from "vuedraggable"; import VDraggable from "vuedraggable";
import { useUserStore } from "/@/store/modules/user";
export default { export default {
name: "PiTaskForm", name: "PiTaskForm",
components: { CopyOutlined, PiStepForm, VDraggable }, components: { CopyOutlined, PiStepForm, VDraggable },
@ -94,6 +95,7 @@ export default {
}, },
emits: ["update"], emits: ["update"],
setup(props: any, ctx: any) { setup(props: any, ctx: any) {
const userStore = useUserStore();
function useStep() { function useStep() {
const stepFormRef: Ref<any> = ref(null); const stepFormRef: Ref<any> = ref(null);
const currentStepIndex = ref(0); const currentStepIndex = ref(0);
@ -248,6 +250,7 @@ export default {
}; };
} }
return { return {
userStore,
labelCol: { span: 6 }, labelCol: { span: 6 },
wrapperCol: { span: 16 }, wrapperCol: { span: 16 },
...useTaskForm(), ...useTaskForm(),

View File

@ -20,7 +20,7 @@
<div class="layout-left"> <div class="layout-left">
<div class="pipeline-container"> <div class="pipeline-container">
<div class="pipeline"> <div class="pipeline">
<v-draggable v-model="pipeline.stages" class="stages" item-key="id" handle=".stage-move-handle"> <v-draggable v-model="pipeline.stages" class="stages" item-key="id" handle=".stage-move-handle" :disabled="!userStore.isPlus">
<template #header> <template #header>
<div class="stage first-stage"> <div class="stage first-stage">
<div class="title stage-move-handle"> <div class="title stage-move-handle">
@ -69,11 +69,11 @@
<div :key="stage.id" class="stage" :class="{ 'last-stage': isLastStage(index) }"> <div :key="stage.id" class="stage" :class="{ 'last-stage': isLastStage(index) }">
<div class="title"> <div class="title">
<pi-editable v-model="stage.title" :disabled="!editMode"></pi-editable> <pi-editable v-model="stage.title" :disabled="!editMode"></pi-editable>
<div class="icon-box stage-move-handle"> <div v-plus class="icon-box stage-move-handle">
<fs-icon v-if="editMode" title="拖动排序" icon="ion:move-outline"></fs-icon> <fs-icon v-if="editMode" title="拖动排序" icon="ion:move-outline"></fs-icon>
</div> </div>
</div> </div>
<v-draggable v-model="stage.tasks" item-key="id" class="tasks" group="task" handle=".task-move-handle"> <v-draggable v-model="stage.tasks" item-key="id" class="tasks" group="task" handle=".task-move-handle" :disabled="!userStore.isPlus">
<template #item="{ element: task, index: taskIndex }"> <template #item="{ element: task, index: taskIndex }">
<div <div
class="task-container" class="task-container"
@ -114,7 +114,7 @@
<div class="icon-box action copy"> <div class="icon-box action copy">
<fs-icon v-if="editMode" title="复制" icon="ion:copy-outline" @click="taskCopy(stage, index, task)"></fs-icon> <fs-icon v-if="editMode" title="复制" icon="ion:copy-outline" @click="taskCopy(stage, index, task)"></fs-icon>
</div> </div>
<div class="icon-box task-move-handle action drag"> <div v-plus class="icon-box task-move-handle action drag">
<fs-icon v-if="editMode" title="拖动排序" icon="ion:move-outline"></fs-icon> <fs-icon v-if="editMode" title="拖动排序" icon="ion:move-outline"></fs-icon>
</div> </div>
</div> </div>
@ -264,6 +264,7 @@ import { PipelineDetail, PipelineOptions, PluginGroups, RunHistory } from "./typ
import type { Runnable } from "@certd/pipeline"; import type { Runnable } from "@certd/pipeline";
import PiHistoryTimelineItem from "/@/views/certd/pipeline/pipeline/component/history-timeline-item.vue"; import PiHistoryTimelineItem from "/@/views/certd/pipeline/pipeline/component/history-timeline-item.vue";
import { FsIcon } from "@fast-crud/fast-crud"; import { FsIcon } from "@fast-crud/fast-crud";
import { useUserStore } from "/@/store/modules/user";
export default defineComponent({ export default defineComponent({
name: "PipelineEdit", name: "PipelineEdit",
// eslint-disable-next-line vue/no-unused-components // eslint-disable-next-line vue/no-unused-components
@ -298,6 +299,8 @@ export default defineComponent({
router.back(); router.back();
} }
const userStore = useUserStore();
const loadCurrentHistoryDetail = async () => { const loadCurrentHistoryDetail = async () => {
console.log("load history logs"); console.log("load history logs");
const detail: RunHistory = await props.options?.getHistoryDetail({ historyId: currentHistory.value.id }); const detail: RunHistory = await props.options?.getHistoryDetail({ historyId: currentHistory.value.id });
@ -653,6 +656,7 @@ export default defineComponent({
currentHistory, currentHistory,
histories, histories,
goBack, goBack,
userStore,
...useTaskRet, ...useTaskRet,
...useStageRet, ...useStageRet,
...useTrigger(), ...useTrigger(),

View File

@ -31,7 +31,7 @@ export class HostShellExecutePlugin extends AbstractTaskPlugin {
vModel: 'value', vModel: 'value',
rows: 6, rows: 6,
}, },
helper:"注意如果目标主机是windows且终端是cmd系统会自动将多行命令通过“&&”连接成一行", helper: '注意如果目标主机是windows且终端是cmd系统会自动将多行命令通过“&&”连接成一行',
required: true, required: true,
}) })
script!: string; script!: string;

3
test/docker/Dockerfile Normal file
View File

@ -0,0 +1,3 @@
FROM node:20-alpine
RUN apk add --no-cache openssl
WORKDIR /app/

View File

@ -0,0 +1,14 @@
version: '3.3' # 指定docker-compose 版本
services: # 要拉起的服务们
certdtest:
build:
context: ./
dockerfile: Dockerfile
image: certd-test:1
container_name: certdtest # 容器名
volumes:
- ./data:/app/data
command: ["tail", "-f", "/dev/null"]
environment:
- TZ=Asia/Shanghai