mirror of
https://github.com/certd/certd.git
synced 2026-04-24 20:57:26 +08:00
chore: project manager
This commit is contained in:
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"editor.tabSize": 2,
|
"editor.tabSize": 2,
|
||||||
"explorer.autoReveal": false,
|
"explorer.autoReveal": false,
|
||||||
|
|||||||
@@ -208,6 +208,10 @@ export default {
|
|||||||
orderManager: "Order Management",
|
orderManager: "Order Management",
|
||||||
userSuites: "User Suites",
|
userSuites: "User Suites",
|
||||||
netTest: "Network Test",
|
netTest: "Network Test",
|
||||||
|
|
||||||
|
enterpriseSetting: "Enterprise Settings",
|
||||||
|
projectManager: "Project Management",
|
||||||
|
projectUserManager: "Project User Management",
|
||||||
},
|
},
|
||||||
certificateRepo: {
|
certificateRepo: {
|
||||||
title: "Certificate Repository",
|
title: "Certificate Repository",
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ export default {
|
|||||||
orderManager: "订单管理",
|
orderManager: "订单管理",
|
||||||
userSuites: "用户套餐",
|
userSuites: "用户套餐",
|
||||||
netTest: "网络测试",
|
netTest: "网络测试",
|
||||||
|
enterpriseSetting: "企业管理设置",
|
||||||
|
projectManager: "项目管理",
|
||||||
|
projectUserManager: "项目用户管理",
|
||||||
},
|
},
|
||||||
certificateRepo: {
|
certificateRepo: {
|
||||||
title: "证书仓库",
|
title: "证书仓库",
|
||||||
|
|||||||
@@ -187,7 +187,59 @@ export const sysResources = [
|
|||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.enterpriseManager",
|
||||||
|
name: "EnterpriseManager",
|
||||||
|
path: "/sys/enterprise",
|
||||||
|
redirect: "/sys/enterprise/project",
|
||||||
|
meta: {
|
||||||
|
icon: "ion:cart-outline",
|
||||||
|
permission: "sys:settings:edit",
|
||||||
|
show: () => {
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
return settingStore.isEnterprise;
|
||||||
|
},
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.projectManager",
|
||||||
|
name: "ProjectManager",
|
||||||
|
path: "/sys/enterprise/project",
|
||||||
|
component: "/sys/enterprise/project/index.vue",
|
||||||
|
meta: {
|
||||||
|
show: true,
|
||||||
|
icon: "ion:cart",
|
||||||
|
permission: "sys:settings:edit",
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.projectUserManager",
|
||||||
|
name: "ProjectUserManager",
|
||||||
|
path: "/sys/enterprise/project/user",
|
||||||
|
component: "/sys/enterprise/project/user/index.vue",
|
||||||
|
meta: {
|
||||||
|
isMenu: false,
|
||||||
|
show: true,
|
||||||
|
icon: "ion:cart",
|
||||||
|
permission: "sys:settings:edit",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "certd.sysResources.enterpriseSetting",
|
||||||
|
name: "EnterpriseSetting",
|
||||||
|
path: "/sys/enterprise/setting",
|
||||||
|
redirect: "/sys/settings?tab=enterprise",
|
||||||
|
meta: {
|
||||||
|
isMenu: true,
|
||||||
|
show: true,
|
||||||
|
icon: "ion:cart",
|
||||||
|
permission: "sys:settings:edit",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "certd.sysResources.suiteManager",
|
title: "certd.sysResources.suiteManager",
|
||||||
name: "SuiteManager",
|
name: "SuiteManager",
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ export const useSettingStore = defineStore({
|
|||||||
isComm(): boolean {
|
isComm(): boolean {
|
||||||
return this.plusInfo?.isComm && (this.plusInfo?.expireTime === -1 || this.plusInfo?.expireTime > new Date().getTime());
|
return this.plusInfo?.isComm && (this.plusInfo?.expireTime === -1 || this.plusInfo?.expireTime > new Date().getTime());
|
||||||
},
|
},
|
||||||
|
isEnterprise(): boolean {
|
||||||
|
return this.isPlus && this.sysPublic.adminMode === "enterprise";
|
||||||
|
},
|
||||||
isAgent(): boolean {
|
isAgent(): boolean {
|
||||||
return this.siteEnv?.agent?.enabled === true;
|
return this.siteEnv?.agent?.enabled === true;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/sys/project/provider";
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetDetail(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/detail",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteBatch(ids: any[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/deleteByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDefault(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDefault",
|
||||||
|
method: "post",
|
||||||
|
data: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDisabled(id: any, disabled: boolean) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDisabled",
|
||||||
|
method: "post",
|
||||||
|
data: { id, disabled },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
import * as api from "./api";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
import { computed, Ref, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||||
|
import { useUserStore } from "/@/store/user";
|
||||||
|
import { useSettingStore } from "/@/store/settings";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||||
|
context.selectedRowKeys = selectedRowKeys;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
order: -2,
|
||||||
|
before: true,
|
||||||
|
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: true,
|
||||||
|
selectedRowKeys,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
minWidth: 200,
|
||||||
|
fixed: "right",
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
title: t("certd.cnameDomain"),
|
||||||
|
type: "text",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
placeholder: t("certd.cnameDomainPlaceholder"),
|
||||||
|
},
|
||||||
|
helper: t("certd.cnameDomainHelper"),
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: t("certd.requiredField") },
|
||||||
|
{ pattern: /^[^*]+$/, message: t("certd.cnameDomainPattern") },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dnsProviderType: {
|
||||||
|
title: t("certd.dnsProvider"),
|
||||||
|
type: "dict-select",
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
url: "pi/dnsProvider/list",
|
||||||
|
value: "key",
|
||||||
|
label: "title",
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: t("certd.requiredField") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accessId: {
|
||||||
|
title: t("certd.dnsProviderAuthorization"),
|
||||||
|
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: t("certd.requiredField") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isDefault: {
|
||||||
|
title: t("certd.isDefault"),
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("certd.yes"), value: true, color: "success" },
|
||||||
|
{ label: t("certd.no"), value: false, color: "default" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
rules: [{ required: true, message: t("certd.selectIsDefault") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
align: "center",
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setDefault: {
|
||||||
|
title: t("certd.setDefault"),
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
conditionalRenderDisabled: true,
|
||||||
|
cellRender: ({ row }) => {
|
||||||
|
if (row.isDefault) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const onClick = async () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.prompt"),
|
||||||
|
content: t("certd.confirmSetDefault"),
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDefault(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a-button type={"link"} size={"small"} onClick={onClick}>
|
||||||
|
{t("certd.setAsDefault")}
|
||||||
|
</a-button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
title: t("certd.disabled"),
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("certd.enabled"), value: false, color: "success" },
|
||||||
|
{ label: t("certd.disabledLabel"), value: true, color: "error" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
title: t("certd.clickToToggle"),
|
||||||
|
on: {
|
||||||
|
async click({ value, row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.prompt"),
|
||||||
|
content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }),
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDisabled(row.id, !value);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
title: t("certd.createTime"),
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
width: 160,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updateTime: {
|
||||||
|
title: t("certd.updateTime"),
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<fs-page class="page-cert">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
{{ t("certd.cnameTitle") }}
|
||||||
|
<span class="sub">
|
||||||
|
{{ t("certd.cnameDescription") }}
|
||||||
|
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">
|
||||||
|
{{ t("certd.cnameLinkText") }}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip :title="t('certd.batchDelete')">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onActivated, onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { DeleteBatch } from "./api";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CnameProvider",
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
const selectedRowKeys = context.selectedRowKeys;
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.confirmTitle"),
|
||||||
|
content: t("certd.confirmDeleteBatch", { count: selectedRowKeys.value.length }),
|
||||||
|
async onOk() {
|
||||||
|
await DeleteBatch(selectedRowKeys.value);
|
||||||
|
message.info(t("certd.deleteSuccess"));
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error(t("certd.selectRecordsFirst"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
onActivated(async () => {
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { request } from "/src/api/service";
|
||||||
|
|
||||||
|
const apiPrefix = "/sys/project/provider";
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/page",
|
||||||
|
method: "post",
|
||||||
|
data: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function AddObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/add",
|
||||||
|
method: "post",
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function UpdateObj(obj: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/update",
|
||||||
|
method: "post",
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DelObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/delete",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetObj(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/info",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetDetail(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/detail",
|
||||||
|
method: "post",
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteBatch(ids: any[]) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/deleteByIds",
|
||||||
|
method: "post",
|
||||||
|
data: { ids },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDefault(id: any) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDefault",
|
||||||
|
method: "post",
|
||||||
|
data: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function SetDisabled(id: any, disabled: boolean) {
|
||||||
|
return await request({
|
||||||
|
url: apiPrefix + "/setDisabled",
|
||||||
|
method: "post",
|
||||||
|
data: { id, disabled },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
import * as api from "./api";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
import { computed, Ref, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { AddReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery, UserPageRes, utils } from "@fast-crud/fast-crud";
|
||||||
|
import { useUserStore } from "/@/store/user";
|
||||||
|
import { useSettingStore } from "/@/store/settings";
|
||||||
|
import { Modal } from "ant-design-vue";
|
||||||
|
|
||||||
|
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const router = useRouter();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const pageRequest = async (query: UserPageQuery): Promise<UserPageRes> => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
form.id = row.id;
|
||||||
|
const res = await api.UpdateObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
const res = await api.AddObj(form);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const selectedRowKeys: Ref<any[]> = ref([]);
|
||||||
|
context.selectedRowKeys = selectedRowKeys;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
settings: {
|
||||||
|
plugins: {
|
||||||
|
//这里使用行选择插件,生成行选择crudOptions配置,最终会与crudOptions合并
|
||||||
|
rowSelection: {
|
||||||
|
enabled: true,
|
||||||
|
order: -2,
|
||||||
|
before: true,
|
||||||
|
// handle: (pluginProps,useCrudProps)=>CrudOptions,
|
||||||
|
props: {
|
||||||
|
multiple: true,
|
||||||
|
crossPage: true,
|
||||||
|
selectedRowKeys,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
minWidth: 200,
|
||||||
|
fixed: "right",
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
id: {
|
||||||
|
title: "ID",
|
||||||
|
key: "id",
|
||||||
|
type: "number",
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
domain: {
|
||||||
|
title: t("certd.cnameDomain"),
|
||||||
|
type: "text",
|
||||||
|
editForm: {
|
||||||
|
component: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
component: {
|
||||||
|
placeholder: t("certd.cnameDomainPlaceholder"),
|
||||||
|
},
|
||||||
|
helper: t("certd.cnameDomainHelper"),
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: t("certd.requiredField") },
|
||||||
|
{ pattern: /^[^*]+$/, message: t("certd.cnameDomainPattern") },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dnsProviderType: {
|
||||||
|
title: t("certd.dnsProvider"),
|
||||||
|
type: "dict-select",
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
url: "pi/dnsProvider/list",
|
||||||
|
value: "key",
|
||||||
|
label: "title",
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
rules: [{ required: true, message: t("certd.requiredField") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accessId: {
|
||||||
|
title: t("certd.dnsProviderAuthorization"),
|
||||||
|
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: t("certd.requiredField") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 150,
|
||||||
|
component: {
|
||||||
|
color: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isDefault: {
|
||||||
|
title: t("certd.isDefault"),
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("certd.yes"), value: true, color: "success" },
|
||||||
|
{ label: t("certd.no"), value: false, color: "default" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
rules: [{ required: true, message: t("certd.selectIsDefault") }],
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
align: "center",
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setDefault: {
|
||||||
|
title: t("certd.setDefault"),
|
||||||
|
type: "text",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
align: "center",
|
||||||
|
conditionalRenderDisabled: true,
|
||||||
|
cellRender: ({ row }) => {
|
||||||
|
if (row.isDefault) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const onClick = async () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.prompt"),
|
||||||
|
content: t("certd.confirmSetDefault"),
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDefault(row.id);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a-button type={"link"} size={"small"} onClick={onClick}>
|
||||||
|
{t("certd.setAsDefault")}
|
||||||
|
</a-button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
title: t("certd.disabled"),
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ label: t("certd.enabled"), value: false, color: "success" },
|
||||||
|
{ label: t("certd.disabledLabel"), value: true, color: "error" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
width: 100,
|
||||||
|
component: {
|
||||||
|
title: t("certd.clickToToggle"),
|
||||||
|
on: {
|
||||||
|
async click({ value, row }) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.prompt"),
|
||||||
|
content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }),
|
||||||
|
onOk: async () => {
|
||||||
|
await api.SetDisabled(row.id, !value);
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createTime: {
|
||||||
|
title: t("certd.createTime"),
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
sorter: true,
|
||||||
|
width: 160,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updateTime: {
|
||||||
|
title: t("certd.updateTime"),
|
||||||
|
type: "datetime",
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<fs-page class="page-cert">
|
||||||
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
{{ t("certd.cnameTitle") }}
|
||||||
|
<span class="sub">
|
||||||
|
{{ t("certd.cnameDescription") }}
|
||||||
|
<a href="https://certd.docmirror.cn/guide/feature/cname/" target="_blank">
|
||||||
|
{{ t("certd.cnameLinkText") }}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-left>
|
||||||
|
<a-tooltip :title="t('certd.batchDelete')">
|
||||||
|
<fs-button icon="DeleteOutlined" @click="handleBatchDelete"></fs-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onActivated, onMounted } from "vue";
|
||||||
|
import { useFs } from "@fast-crud/fast-crud";
|
||||||
|
import createCrudOptions from "./crud";
|
||||||
|
import { message, Modal } from "ant-design-vue";
|
||||||
|
import { DeleteBatch } from "./api";
|
||||||
|
import { useI18n } from "/src/locales";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "CnameProvider",
|
||||||
|
});
|
||||||
|
const { crudBinding, crudRef, crudExpose, context } = useFs({ createCrudOptions });
|
||||||
|
|
||||||
|
const selectedRowKeys = context.selectedRowKeys;
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value?.length > 0) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("certd.confirmTitle"),
|
||||||
|
content: t("certd.confirmDeleteBatch", { count: selectedRowKeys.value.length }),
|
||||||
|
async onOk() {
|
||||||
|
await DeleteBatch(selectedRowKeys.value);
|
||||||
|
message.info(t("certd.deleteSuccess"));
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
selectedRowKeys.value = [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error(t("certd.selectRecordsFirst"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
onActivated(async () => {
|
||||||
|
await crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="less"></style>
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { CrudController, SysSettingsService } from "@certd/lib-server";
|
||||||
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||||
|
import { ProjectService } from "../../../modules/sys/enterprise/service/project-service.js";
|
||||||
|
import { ProjectEntity } from "../../../modules/sys/enterprise/entity/project.js";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
@Controller("/api/sys/enterprise/project")
|
||||||
|
export class SysProjectController extends CrudController<ProjectEntity> {
|
||||||
|
@Inject()
|
||||||
|
service: ProjectService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
getService<T>() {
|
||||||
|
return this.service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/page", { summary: "sys:settings:view" })
|
||||||
|
async page(@Body(ALL) body: any) {
|
||||||
|
body.query = body.query ?? {};
|
||||||
|
return await super.page(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/list", { summary: "sys:settings:view" })
|
||||||
|
async list(@Body(ALL) body: any) {
|
||||||
|
return super.list(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/add", { summary: "sys:settings:edit" })
|
||||||
|
async add(@Body(ALL) bean: any) {
|
||||||
|
const def: any = {
|
||||||
|
isDefault: false,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
merge(bean, def);
|
||||||
|
bean.userId = this.getUserId();
|
||||||
|
return super.add(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/update", { summary: "sys:settings:edit" })
|
||||||
|
async update(@Body(ALL) bean: any) {
|
||||||
|
bean.userId = this.getUserId();
|
||||||
|
return super.update(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/info", { summary: "sys:settings:view" })
|
||||||
|
async info(@Query("id") id: number) {
|
||||||
|
return super.info(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/delete", { summary: "sys:settings:edit" })
|
||||||
|
async delete(@Query("id") id: number) {
|
||||||
|
return super.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/deleteByIds", { summary: "sys:settings:edit" })
|
||||||
|
async deleteByIds(@Body("ids") ids: number[]) {
|
||||||
|
const res = await this.service.delete(ids);
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
@Post("/setDisabled", { summary: "sys:settings:edit" })
|
||||||
|
async setDisabled(@Body("id") id: number, @Body("disabled") disabled: boolean) {
|
||||||
|
await this.service.setDisabled(id, disabled);
|
||||||
|
return this.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { CrudController, SysSettingsService } from "@certd/lib-server";
|
||||||
|
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||||
|
import { ProjectUserEntity } from "../../../modules/sys/enterprise/entity/project-user.js";
|
||||||
|
import { ProjectUserService } from "../../../modules/sys/enterprise/service/project-user-service.js";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
@Controller("/api/sys/enterprise/projectUser")
|
||||||
|
export class SysProjectUserController extends CrudController<ProjectUserEntity> {
|
||||||
|
@Inject()
|
||||||
|
service: ProjectUserService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
getService<T>() {
|
||||||
|
return this.service;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/page", { summary: "sys:settings:view" })
|
||||||
|
async page(@Body(ALL) body: any) {
|
||||||
|
body.query = body.query ?? {};
|
||||||
|
return await super.page(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/list", { summary: "sys:settings:view" })
|
||||||
|
async list(@Body(ALL) body: any) {
|
||||||
|
return super.list(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/add", { summary: "sys:settings:edit" })
|
||||||
|
async add(@Body(ALL) bean: any) {
|
||||||
|
const def: any = {
|
||||||
|
isDefault: false,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
merge(bean, def);
|
||||||
|
bean.userId = this.getUserId();
|
||||||
|
return super.add(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/update", { summary: "sys:settings:edit" })
|
||||||
|
async update(@Body(ALL) bean: any) {
|
||||||
|
bean.userId = this.getUserId();
|
||||||
|
return super.update(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/info", { summary: "sys:settings:view" })
|
||||||
|
async info(@Query("id") id: number) {
|
||||||
|
return super.info(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/delete", { summary: "sys:settings:edit" })
|
||||||
|
async delete(@Query("id") id: number) {
|
||||||
|
return super.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("/deleteByIds", { summary: "sys:settings:edit" })
|
||||||
|
async deleteByIds(@Body("ids") ids: number[]) {
|
||||||
|
const res = await this.service.delete(ids);
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,7 +54,6 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
|
|||||||
throw new Error('域名已存在');
|
throw new Error('域名已存在');
|
||||||
}
|
}
|
||||||
return await super.add(bean)
|
return await super.add(bean)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
|
||||||
|
import {BaseService, SysSettingsService} from '@certd/lib-server';
|
||||||
|
import {InjectEntityModel} from '@midwayjs/typeorm';
|
||||||
|
import {Repository} from 'typeorm';
|
||||||
|
import { ProjectEntity } from '../entity/project.js';
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
|
export class ProjectService extends BaseService<ProjectEntity> {
|
||||||
|
@InjectEntityModel(ProjectEntity)
|
||||||
|
repository: Repository<ProjectEntity>;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
getRepository() {
|
||||||
|
return this.repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(bean: ProjectEntity) {
|
||||||
|
const {name} = bean;
|
||||||
|
if (!name) {
|
||||||
|
throw new Error('项目名称不能为空');
|
||||||
|
}
|
||||||
|
const exist = await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
name,
|
||||||
|
userId:0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (exist) {
|
||||||
|
throw new Error('项目名称已存在');
|
||||||
|
}
|
||||||
|
bean.userId = 0
|
||||||
|
bean.disabled = false
|
||||||
|
return await super.add(bean)
|
||||||
|
}
|
||||||
|
|
||||||
|
async setDisabled(id: number, disabled: boolean) {
|
||||||
|
const project = await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
userId:0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!project) {
|
||||||
|
throw new Error('项目不存在');
|
||||||
|
}
|
||||||
|
await this.repository.update({
|
||||||
|
userId:0,
|
||||||
|
}, {
|
||||||
|
disabled,
|
||||||
|
});
|
||||||
|
project.disabled = disabled;
|
||||||
|
await this.repository.save(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import {Inject, Provide, Scope, ScopeEnum} from '@midwayjs/core';
|
||||||
|
import {BaseService, SysSettingsService} from '@certd/lib-server';
|
||||||
|
import {InjectEntityModel} from '@midwayjs/typeorm';
|
||||||
|
import {Repository} from 'typeorm';
|
||||||
|
import { ProjectUserEntity } from '../entity/project-user.js';
|
||||||
|
|
||||||
|
@Provide()
|
||||||
|
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||||
|
export class ProjectUserService extends BaseService<ProjectUserEntity> {
|
||||||
|
@InjectEntityModel(ProjectUserEntity)
|
||||||
|
repository: Repository<ProjectUserEntity>;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
sysSettingsService: SysSettingsService;
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
getRepository() {
|
||||||
|
return this.repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(bean: ProjectUserEntity) {
|
||||||
|
const {projectId, userId} = bean;
|
||||||
|
if (!projectId) {
|
||||||
|
throw new Error('项目ID不能为空');
|
||||||
|
}
|
||||||
|
if (!userId) {
|
||||||
|
throw new Error('用户ID不能为空');
|
||||||
|
}
|
||||||
|
const exist = await this.repository.findOne({
|
||||||
|
where: {
|
||||||
|
projectId,
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (exist) {
|
||||||
|
throw new Error('项目用户已存在');
|
||||||
|
}
|
||||||
|
return await super.add(bean)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user