mirror of
https://github.com/certd/certd.git
synced 2026-07-31 09:57:35 +08:00
Compare commits
4 Commits
26b1c4244f
...
bc326489ab
| Author | SHA1 | Date | |
|---|---|---|---|
| bc326489ab | |||
| ea5e7d9563 | |||
| 5b5b48fc06 | |||
| 1548ba0b8d |
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
@@ -35,7 +35,7 @@ defineOptions({
|
||||
|
||||
const projectStore = useProjectStore();
|
||||
onMounted(async () => {
|
||||
await projectStore.reload();
|
||||
await projectStore.init();
|
||||
console.log(projectStore.myProjects);
|
||||
});
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ export default {
|
||||
myProjectManager: "My Projects",
|
||||
myProjectDetail: "Project Detail",
|
||||
projectJoin: "Join Project",
|
||||
currentProject: "Current Project",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "Certificate Repository",
|
||||
|
||||
@@ -225,6 +225,7 @@ export default {
|
||||
myProjectManager: "我的项目",
|
||||
myProjectDetail: "项目详情",
|
||||
projectJoin: "加入项目",
|
||||
currentProject: "当前项目",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "证书仓库",
|
||||
@@ -832,8 +833,8 @@ export default {
|
||||
projectDetailDescription: "管理项目成员",
|
||||
projectPermission: "权限",
|
||||
permission: {
|
||||
read: "读取",
|
||||
write: "写入",
|
||||
read: "查看",
|
||||
write: "修改",
|
||||
admin: "管理员",
|
||||
},
|
||||
projectMemberStatus: "成员状态",
|
||||
|
||||
@@ -82,7 +82,6 @@ export function useCrudPermission({ permission }: UseCrudPermissionProps) {
|
||||
if (isProjectPermission) {
|
||||
removePermission = per.projectPermission || "write";
|
||||
}
|
||||
debugger;
|
||||
return LodashMerge(
|
||||
{
|
||||
actionbar: {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import aboutResource from "/@/router/source/modules/about";
|
||||
import i18n from "/@/locales/i18n";
|
||||
import { useProjectStore } from "/@/store/project";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
|
||||
export const certdResources = [
|
||||
{
|
||||
@@ -28,11 +26,12 @@ export const certdResources = [
|
||||
isMenu: false,
|
||||
icon: "ion:apps",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.myProjectDetail",
|
||||
name: "MyProjectDetail",
|
||||
title: "certd.sysResources.currentProject",
|
||||
name: "CurrentProject",
|
||||
path: "/certd/project/detail",
|
||||
component: "/certd/project/detail/index.vue",
|
||||
meta: {
|
||||
@@ -42,6 +41,7 @@ export const certdResources = [
|
||||
},
|
||||
isMenu: true,
|
||||
icon: "ion:apps",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -53,6 +53,7 @@ export const certdResources = [
|
||||
isMenu: false,
|
||||
show: true,
|
||||
icon: "ion:apps",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -63,6 +64,7 @@ export const certdResources = [
|
||||
meta: {
|
||||
icon: "ion:analytics-sharp",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -72,6 +74,7 @@ export const certdResources = [
|
||||
component: "/certd/pipeline/detail.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -82,6 +85,7 @@ export const certdResources = [
|
||||
meta: {
|
||||
icon: "ion:timer-outline",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -92,6 +96,7 @@ export const certdResources = [
|
||||
meta: {
|
||||
isMenu: true,
|
||||
icon: "ion:duplicate-outline",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -101,6 +106,7 @@ export const certdResources = [
|
||||
component: "/certd/pipeline/template/edit.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -110,6 +116,7 @@ export const certdResources = [
|
||||
component: "/certd/pipeline/template/import/index.vue",
|
||||
meta: {
|
||||
isMenu: false,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import LayoutPass from "/@/layout/layout-pass.vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
import aboutResource from "/@/router/source/modules/about";
|
||||
import i18n from "/@/locales/i18n";
|
||||
|
||||
export const sysResources = [
|
||||
{
|
||||
@@ -13,6 +10,7 @@ export const sysResources = [
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
order: 10,
|
||||
auth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@@ -27,6 +25,7 @@ export const sysResources = [
|
||||
},
|
||||
icon: "ion:speedometer-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -38,6 +37,7 @@ export const sysResources = [
|
||||
meta: {
|
||||
icon: "ion:settings-outline",
|
||||
permission: "sys:settings:view",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -47,6 +47,7 @@ export const sysResources = [
|
||||
component: "/sys/enterprise/project/index.vue",
|
||||
meta: {
|
||||
show: true,
|
||||
auth: true,
|
||||
icon: "ion:apps",
|
||||
permission: "sys:settings:edit",
|
||||
keepAlive: true,
|
||||
@@ -60,6 +61,7 @@ export const sysResources = [
|
||||
meta: {
|
||||
isMenu: false,
|
||||
show: true,
|
||||
auth: true,
|
||||
icon: "ion:apps",
|
||||
permission: "sys:settings:edit",
|
||||
},
|
||||
@@ -73,6 +75,7 @@ export const sysResources = [
|
||||
icon: "ion:earth-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -96,6 +99,7 @@ export const sysResources = [
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
auth: true,
|
||||
icon: "ion:document-text-outline",
|
||||
permission: "sys:settings:view",
|
||||
},
|
||||
@@ -110,6 +114,7 @@ export const sysResources = [
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
auth: true,
|
||||
icon: "ion:menu",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
@@ -125,6 +130,7 @@ export const sysResources = [
|
||||
const settingStore = useSettingStore();
|
||||
return settingStore.isComm;
|
||||
},
|
||||
auth: true,
|
||||
icon: "ion:disc-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
@@ -139,6 +145,7 @@ export const sysResources = [
|
||||
icon: "ion:extension-puzzle-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -151,6 +158,7 @@ export const sysResources = [
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -165,6 +173,7 @@ export const sysResources = [
|
||||
},
|
||||
icon: "ion:extension-puzzle",
|
||||
permission: "sys:settings:view",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -176,6 +185,7 @@ export const sysResources = [
|
||||
icon: "ion:golf-outline",
|
||||
permission: "sys:settings:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -187,6 +197,7 @@ export const sysResources = [
|
||||
icon: "ion:list-outline",
|
||||
permission: "sys:auth:per:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -198,6 +209,7 @@ export const sysResources = [
|
||||
icon: "ion:people-outline",
|
||||
permission: "sys:auth:role:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -209,6 +221,7 @@ export const sysResources = [
|
||||
icon: "ion:person-outline",
|
||||
permission: "sys:auth:user:view",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -224,6 +237,7 @@ export const sysResources = [
|
||||
return settingStore.isComm;
|
||||
},
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@@ -238,6 +252,7 @@ export const sysResources = [
|
||||
},
|
||||
icon: "ion:cart",
|
||||
permission: "sys:settings:edit",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -253,6 +268,7 @@ export const sysResources = [
|
||||
icon: "ion:bag-check",
|
||||
permission: "sys:settings:edit",
|
||||
keepAlive: true,
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -17,7 +17,8 @@ export const useProjectStore = defineStore("app.project", () => {
|
||||
const inited = ref(false);
|
||||
const userStore = useUserStore();
|
||||
const userId = userStore.getUserInfo?.id;
|
||||
const lastProjectId = LocalStorage.get("currentProjectId:" + userId);
|
||||
const lastProjectIdCacheKey = "currentProjectId:" + userId;
|
||||
const lastProjectId = LocalStorage.get(lastProjectIdCacheKey);
|
||||
const currentProjectId = ref(lastProjectId); // 直接调用
|
||||
|
||||
const projects = computed(() => {
|
||||
@@ -63,7 +64,7 @@ export const useProjectStore = defineStore("app.project", () => {
|
||||
|
||||
function changeCurrentProject(id: string, silent?: boolean) {
|
||||
currentProjectId.value = id;
|
||||
LocalStorage.set("currentProjectId", id);
|
||||
LocalStorage.set(lastProjectIdCacheKey, id);
|
||||
if (!silent) {
|
||||
message.success("切换项目成功");
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ const projectPermissionDict = dict({
|
||||
data: [
|
||||
{
|
||||
value: "read",
|
||||
label: "只读",
|
||||
label: "查看",
|
||||
color: "cyan",
|
||||
icon: "material-symbols:folder-eye-outline-sharp",
|
||||
},
|
||||
{
|
||||
value: "write",
|
||||
label: "读写",
|
||||
label: "修改",
|
||||
color: "green",
|
||||
icon: "material-symbols:edit-square-outline-rounded",
|
||||
},
|
||||
|
||||
@@ -50,6 +50,7 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
|
||||
delete form.lastVars;
|
||||
delete form.createTime;
|
||||
delete form.id;
|
||||
delete form.webhook;
|
||||
let pipeline = form.content;
|
||||
if (typeof pipeline === "string" && pipeline.startsWith("{")) {
|
||||
pipeline = JSON.parse(form.content);
|
||||
@@ -75,8 +76,8 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
|
||||
function onDialogOpen(opt: any) {
|
||||
const searchForm = crudExpose.getSearchValidatedFormData();
|
||||
opt.initialForm = {
|
||||
...opt.initialForm,
|
||||
groupId: searchForm.groupId,
|
||||
...opt.initialForm,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -219,7 +220,7 @@ export default function ({ crudExpose, context: { selectedRowKeys, openCertApply
|
||||
row = info.pipeline;
|
||||
row.content = JSON.parse(row.content);
|
||||
row.title = row.title + "_copy";
|
||||
await crudExpose.openCopy({
|
||||
await crudExpose.openAdd({
|
||||
row: row,
|
||||
index: context.index,
|
||||
});
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
<fs-page class="page-project-detail">
|
||||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.ent.projectDetailManager") }}
|
||||
当前项目 :{{ project?.name }}
|
||||
<span class="sub flex-inline items-center">
|
||||
项目名称 :<a-tag color="green">{{ project?.name }}</a-tag>
|
||||
<a-divider type="vertical"></a-divider>
|
||||
管理员:<fs-values-format :model-value="project.adminId" :dict="userDict" color="green"></fs-values-format>
|
||||
<!-- <a-divider type="vertical"></a-divider>
|
||||
<fs-values-format :model-value="project.permission" :dict="projectPermissionDict"></fs-values-format>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useSettingStore } from "/@/store/settings";
|
||||
import { useUserStore } from "/@/store/user";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { userDict } from "../../dicts";
|
||||
import { useDicts } from "/@/views/certd/dicts";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
@@ -35,6 +36,8 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||
context.selectedRowKeys = selectedRowKeys;
|
||||
|
||||
const { projectMemberStatusDict } = useDicts();
|
||||
|
||||
return {
|
||||
crudOptions: {
|
||||
settings: {
|
||||
@@ -133,6 +136,27 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
width: 200,
|
||||
},
|
||||
},
|
||||
status: {
|
||||
title: t("certd.ent.projectMemberStatus"),
|
||||
type: "dict-select",
|
||||
dict: projectMemberStatusDict,
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
show: true,
|
||||
},
|
||||
column: {
|
||||
width: 200,
|
||||
cellRender: ({ row }) => {
|
||||
return (
|
||||
<div class="flex items-center">
|
||||
<fs-values-format model-value={row.status} dict={projectMemberStatusDict}></fs-values-format>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
createTime: {
|
||||
title: t("certd.createTime"),
|
||||
type: "datetime",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</fs-crud>
|
||||
<AdminModeIntro v-if="!projectStore.isEnterprise" title="当前为SaaS管理模式,项目管理需要切换到企业模式" :open="true"></AdminModeIntro>
|
||||
</fs-page>
|
||||
</template>
|
||||
|
||||
@@ -22,7 +23,8 @@ import createCrudOptions from "./crud";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
import { DeleteBatch } from "./api";
|
||||
import { useI18n } from "/src/locales";
|
||||
|
||||
import { useProjectStore } from "/@/store/project";
|
||||
import AdminModeIntro from "./intro.vue";
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
@@ -30,6 +32,7 @@ defineOptions({
|
||||
});
|
||||
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||
|
||||
const projectStore = useProjectStore();
|
||||
const selectedRowKeys = context.selectedRowKeys;
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedRowKeys.value?.length > 0) {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div v-if="open" class="admin-mode-intro" :style="fixed ? 'position: fixed;' : 'position: absolute;'" @click="close()">
|
||||
<div class="mask">
|
||||
<div class="intro-content">
|
||||
<h2 class="intro-title text-xl font-bold">{{ title || "管理模式介绍" }}</h2>
|
||||
<div class="mt-8 image-block">
|
||||
<div class="flex gap-8">
|
||||
<div class="intro-desc flex-1">SaaS模式:每个用户管理自己的流水线和授权资源,独立使用。</div>
|
||||
<div class="intro-desc flex-1">企业模式:企业内部员工使用,通过项目合作管理流水线证书和授权资源。</div>
|
||||
</div>
|
||||
<div class="image-intro">
|
||||
<img :src="src" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="action">
|
||||
<a-button type="primary" html-type="button" @click="goSwitchMode">立即前往切换模式</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
defineOptions({
|
||||
name: "AdminModeIntro",
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
title?: string;
|
||||
open?: boolean;
|
||||
fixed?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["update:open"]);
|
||||
|
||||
function close() {
|
||||
emit("update:open", false);
|
||||
}
|
||||
|
||||
const src = ref("static/images/ent/admin_mode.png");
|
||||
|
||||
const router = useRouter();
|
||||
function goSwitchMode() {
|
||||
router.push("/sys/settings?tab=mode");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.admin-mode-intro {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
|
||||
.mask {
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.intro-content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.image-block {
|
||||
text-align: center;
|
||||
.image-intro {
|
||||
width: 100%;
|
||||
img {
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,13 +2,20 @@
|
||||
<div class="sys-settings-form sys-settings-mode">
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish">
|
||||
<a-form-item :label="t('certd.sys.setting.adminMode')" :name="['public', 'adminMode']">
|
||||
<fs-dict-radio v-model:value="formState.public.adminMode" :dict="adminModeDict" />
|
||||
<div class="w-full flex items-center">
|
||||
<fs-dict-radio v-model:value="formState.public.adminMode" :disabled="!settingsStore.isPlus" :dict="adminModeDict" />
|
||||
<vip-button class="ml-5" mode="button"></vip-button>
|
||||
</div>
|
||||
<div class="helper">建议在开始使用时选择合适的模式,之后就不要随意切换了。</div>
|
||||
<div><a @click="adminModeIntroOpen = true"> 管理模式介绍</a></div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label=" " :colon="false" :wrapper-col="{ span: 8 }">
|
||||
<a-button :loading="saveLoading" type="primary" html-type="submit">{{ t("certd.saveButton") }}</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<AdminModeIntro v-model:open="adminModeIntroOpen" fixed></AdminModeIntro>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,22 +29,25 @@ import { notification } from "ant-design-vue";
|
||||
import { useI18n } from "/src/locales";
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
import { useProjectStore } from "/@/store/project";
|
||||
import AdminModeIntro from "/@/views/sys/enterprise/project/intro.vue";
|
||||
const { t } = useI18n();
|
||||
|
||||
defineOptions({
|
||||
name: "SettingMode",
|
||||
});
|
||||
|
||||
const adminModeIntroOpen = ref(false);
|
||||
|
||||
const adminModeDict = dict({
|
||||
data: [
|
||||
{
|
||||
label: t("certd.sys.setting.enterpriseMode"),
|
||||
value: "enterprise",
|
||||
},
|
||||
{
|
||||
label: t("certd.sys.setting.saasMode"),
|
||||
value: "saas",
|
||||
},
|
||||
{
|
||||
label: t("certd.sys.setting.enterpriseMode"),
|
||||
value: "enterprise",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -251,6 +251,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
if (bean.id > 0) {
|
||||
//修改
|
||||
old = await this.info(bean.id);
|
||||
bean.order = old.order;
|
||||
}
|
||||
if (!old || !old.webhookKey) {
|
||||
bean.webhookKey = await this.genWebhookKey();
|
||||
|
||||
Reference in New Issue
Block a user