feat(系统设置): 服务集成本地联调和插件&服务集成联动调试
This commit is contained in:
parent
6bd1f650b0
commit
cab07f4836
|
@ -30,8 +30,8 @@ export function getValidate(id: string) {
|
|||
return MSR.get({ url: GetValidateServiceUrl, params: id });
|
||||
}
|
||||
// 内部校验测试连接 注:不同的平台对应的不同的字段
|
||||
export function postValidate(data: any) {
|
||||
return MSR.post({ url: PostValidateServiceUrl, data });
|
||||
export function postValidate(data: any, pluginId: string) {
|
||||
return MSR.post({ url: PostValidateServiceUrl, data, params: pluginId });
|
||||
}
|
||||
// 前端配置脚本
|
||||
export function configScript(pluginId: string) {
|
||||
|
|
|
@ -3,6 +3,6 @@ export const AddServiceUrl = '/service/integration/add';
|
|||
export const UpdateServiceUrl = '/service/integration/update';
|
||||
export const ResetServiceUrl = '/service/integration/delete';
|
||||
export const GetValidateServiceUrl = '/service/integration/validate';
|
||||
export const PostValidateServiceUrl = '/service/integration/validate';
|
||||
export const PostValidateServiceUrl = '/service/integration/validate/';
|
||||
export const ConfigServiceScriptUrl = '/service/integration/script/';
|
||||
export const getLogoUrl = '/plugin/image';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface ServiceItem {
|
||||
export type ServiceItem = Partial<{
|
||||
id?: string;
|
||||
pluginId: string; // 插件id
|
||||
title: string;
|
||||
|
@ -8,16 +8,31 @@ export interface ServiceItem {
|
|||
logo: string;
|
||||
organizationId: string; // 组织id
|
||||
configuration?: null; // 配置项
|
||||
}
|
||||
}>;
|
||||
|
||||
export type ServiceList = ServiceItem[];
|
||||
|
||||
// 创建和更新服务
|
||||
|
||||
export interface AddOrUpdateServiceModel {
|
||||
export type AddOrUpdateServiceModel = Partial<{
|
||||
id?: string;
|
||||
pluginId: string;
|
||||
enable: boolean;
|
||||
enable: boolean | undefined;
|
||||
organizationId: string;
|
||||
configuration: any;
|
||||
configuration?: any;
|
||||
}>;
|
||||
|
||||
export interface SkipTitle {
|
||||
name: string;
|
||||
src: string;
|
||||
active: boolean; // 是否激活
|
||||
}
|
||||
|
||||
export interface StepListType {
|
||||
id: string;
|
||||
icon: string;
|
||||
title: string;
|
||||
skipTitle: SkipTitle[];
|
||||
step: string;
|
||||
description: string;
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
:ok-text="t('organization.member.Confirm')"
|
||||
:cancel-text="t('organization.member.Cancel')"
|
||||
>
|
||||
<template #title> 标题 </template>
|
||||
<template #title> {{ title }} </template>
|
||||
<div>
|
||||
<MsFormCreate v-model:api="fApi" :rule="formRules" :option="options" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex flex-row items-center justify-center">
|
||||
<a-switch size="small" />
|
||||
<a-switch v-model="isEnable" :disabled="isDisabled" size="small" />
|
||||
<a-tooltip>
|
||||
<template #content>
|
||||
<div class="text-sm">{{ t('organization.service.statusEnableTip') }}</div>
|
||||
|
@ -24,8 +24,12 @@
|
|||
</div>
|
||||
<a-space>
|
||||
<a-button type="secondary" @click="handleCancel">{{ t('organization.service.Cancel') }}</a-button>
|
||||
<a-button type="outline">{{ t('organization.service.testLink') }}</a-button>
|
||||
<a-button type="primary" @click="saveHandler">{{ t('organization.service.Confirm') }}</a-button>
|
||||
<a-button type="outline" :loading="testLoading" @click="testLink">{{
|
||||
t('organization.service.testLink')
|
||||
}}</a-button>
|
||||
<a-button type="primary" :loading="loading" @click="saveHandler">{{
|
||||
t('organization.service.Confirm')
|
||||
}}</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -36,50 +40,28 @@
|
|||
import { ref, watchEffect, watch } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||
import { configScript, addOrUpdate, postValidate } from '@/api/modules/setting/serviceIntegration';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import type { ServiceItem, AddOrUpdateServiceModel } from '@/models/setting/serviceIntegration';
|
||||
import useLoading from '@/hooks/useLoading';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
const lastOrganizationId = userStore.$state?.lastOrganizationId as string;
|
||||
|
||||
const emits = defineEmits<{
|
||||
(event: 'update:visible', visible: boolean): void;
|
||||
(event: 'success'): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
rule: any;
|
||||
}>();
|
||||
const detailVisible = ref<boolean>(false);
|
||||
const { loading, setLoading } = useLoading(false);
|
||||
|
||||
const fApi = ref<any>({});
|
||||
const formRules = ref([]);
|
||||
|
||||
watchEffect(() => {
|
||||
detailVisible.value = props.visible;
|
||||
formRules.value = props.rule;
|
||||
});
|
||||
watch(
|
||||
() => detailVisible.value,
|
||||
(val) => {
|
||||
emits('update:visible', val);
|
||||
}
|
||||
);
|
||||
|
||||
const handleCancel = () => {
|
||||
detailVisible.value = false;
|
||||
};
|
||||
const submit = () => {
|
||||
fApi.value?.submit((formData: FormData) => {
|
||||
console.log(formData, 'formData');
|
||||
});
|
||||
};
|
||||
const saveHandler = () => {
|
||||
fApi.value?.validate((valid: any, fail: any) => {
|
||||
if (valid) {
|
||||
submit();
|
||||
} else {
|
||||
console.log(fail);
|
||||
}
|
||||
});
|
||||
};
|
||||
const options = ref({
|
||||
resetBtn: false,
|
||||
submitBtn: false,
|
||||
|
@ -93,8 +75,118 @@
|
|||
},
|
||||
wrap: {
|
||||
'asterisk-position': 'end',
|
||||
'validate-trigger': ['change'],
|
||||
},
|
||||
});
|
||||
const formRules = ref<any>([]);
|
||||
const title = ref<string>('');
|
||||
const formItem = ref<any>({});
|
||||
watchEffect(() => {
|
||||
detailVisible.value = props.visible;
|
||||
});
|
||||
watch(
|
||||
() => detailVisible.value,
|
||||
(val) => {
|
||||
emits('update:visible', val);
|
||||
}
|
||||
);
|
||||
|
||||
const testLoading = ref<boolean>(false);
|
||||
// 禁用
|
||||
const isDisabled = ref<boolean>(false);
|
||||
// 是否配置
|
||||
const isConfigOrigin = ref<boolean | undefined>(false);
|
||||
// 状态
|
||||
const isEnable = ref<boolean | undefined>(false);
|
||||
// 插件id
|
||||
const pluginId = ref<string>('');
|
||||
const type = ref<string>('');
|
||||
|
||||
const handleCancel = () => {
|
||||
fApi.value.clearValidateState();
|
||||
detailVisible.value = false;
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
fApi.value?.submit(async (formData: FormData) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: AddOrUpdateServiceModel = {
|
||||
id: type.value === 'edit' ? formItem.value.id : undefined,
|
||||
pluginId: pluginId.value,
|
||||
enable: isEnable.value,
|
||||
organizationId: lastOrganizationId,
|
||||
configuration: { ...formData },
|
||||
};
|
||||
const message =
|
||||
type.value === 'edit' ? t('organization.service.updateSuccess') : t('organization.service.configSuccess');
|
||||
await addOrUpdate(params, type.value);
|
||||
Message.success(message);
|
||||
handleCancel();
|
||||
emits('success');
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
const saveHandler = () => {
|
||||
fApi.value?.validate((valid: any, fail: any) => {
|
||||
if (valid) {
|
||||
submit();
|
||||
} else {
|
||||
console.log(fail);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取配置脚本
|
||||
const getPluginScript = async (cuurentPluginId: string) => {
|
||||
try {
|
||||
const result = await configScript(cuurentPluginId);
|
||||
formRules.value = [...result];
|
||||
if (type.value === 'edit') {
|
||||
fApi.value.nextTick(() => {
|
||||
fApi.value.setValue({ ...formItem.value.configuration });
|
||||
fApi.value.refresh();
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
// 测试连接是否通过
|
||||
const testLink = async () => {
|
||||
testLoading.value = true;
|
||||
try {
|
||||
const formValue = {
|
||||
...fApi.value.formData(),
|
||||
};
|
||||
await postValidate(formValue, pluginId.value);
|
||||
if (!isConfigOrigin.value) isDisabled.value = false;
|
||||
Message.success(t('organization.service.successMessage'));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
testLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 创建&编辑
|
||||
const addOrEdit = (serviceItem: ServiceItem) => {
|
||||
type.value = serviceItem.config ? 'edit' : 'create';
|
||||
isConfigOrigin.value = serviceItem.config;
|
||||
isEnable.value = serviceItem.enable;
|
||||
isDisabled.value = !serviceItem.config;
|
||||
pluginId.value = serviceItem.pluginId as string;
|
||||
formItem.value = { ...serviceItem };
|
||||
getPluginScript(pluginId.value);
|
||||
};
|
||||
defineExpose({
|
||||
addOrEdit,
|
||||
title,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<template>
|
||||
<MsCard simple class="mb-[16px]" auto-height>
|
||||
<MsCard simple class="mb-[16px]" auto-height :loading="loading">
|
||||
<div class="outer-wrapper">
|
||||
<div class="mb-[16px] flex justify-between">
|
||||
<div class="font-medium text-[var(--color-text-000)]">{{ t('organization.service.serviceIntegration') }}</div>
|
||||
<div class="font-medium text-[var(--color-text-000)]">{{ t('organization.service.integrationList') }}</div>
|
||||
<div>
|
||||
<a-input-search
|
||||
v-model="keyword"
|
||||
:placeholder="t('organization.member.searchMember')"
|
||||
class="w-[230px]"
|
||||
:placeholder="t('organization.service.searchService')"
|
||||
:max-length="250"
|
||||
@search="searchHandler"
|
||||
@press-enter="searchHandler"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,17 +17,19 @@
|
|||
<a-scrollbar
|
||||
:style="{
|
||||
overflow: 'auto',
|
||||
height: `calc(100vh - ${collapseHeight} - 220px)`,
|
||||
height: `calc(100vh - ${collapseHeight} - 230px)`,
|
||||
}"
|
||||
>
|
||||
<div class="list">
|
||||
<div v-for="item of data" :key="item.id" class="item">
|
||||
<div v-for="item of filterList" :key="item.id" class="item">
|
||||
<div class="flex">
|
||||
<span class="icon float-left mr-2 h-[40px] w-[40px]">{{ item.name }}</span>
|
||||
<span class="icon float-left mr-2 h-[40px] w-[40px] rounded">
|
||||
<img class="rounded" :src="`http://172.16.200.18:8081${item.logo}`" alt="log" />
|
||||
</span>
|
||||
<div class="flex flex-col justify-start">
|
||||
<p>
|
||||
<span class="mr-4 font-semibold">TAPD</span>
|
||||
<span v-if="!item.isConfig" class="ms-enable">{{ t('organization.service.unconfigured') }}</span>
|
||||
<span class="mr-4 font-semibold">{{ item.title }}</span>
|
||||
<span v-if="!item.config" class="ms-enable">{{ t('organization.service.unconfigured') }}</span>
|
||||
<span
|
||||
v-else
|
||||
class="ms-enable active"
|
||||
|
@ -37,30 +40,37 @@
|
|||
>{{ t('organization.service.configured') }}</span
|
||||
>
|
||||
</p>
|
||||
<p class="mt-2 text-sm text-[var(--color-text-4)]">一站式敏捷研发协作云平台</p>
|
||||
<p class="mt-2 text-sm text-[var(--color-text-4)]">{{ item.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<a-space>
|
||||
<a-tooltip v-if="!item.isConfig" :content="t('organization.service.unconfiguredTip')" position="tl">
|
||||
<a-tooltip v-if="!item.config" :content="t('organization.service.unconfiguredTip')" position="tl">
|
||||
<span>
|
||||
<a-button
|
||||
v-if="!item.config"
|
||||
type="outline"
|
||||
class="arco-btn-outline--secondary"
|
||||
size="mini"
|
||||
:disabled="!item.isConfig"
|
||||
:disabled="!item.config"
|
||||
@click="getValidateHandler(item)"
|
||||
>{{ t('organization.service.testLink') }}</a-button
|
||||
></span
|
||||
>
|
||||
</a-tooltip>
|
||||
<a-button v-else type="outline" class="arco-btn-outline--secondary" size="mini">{{
|
||||
t('organization.service.testLink')
|
||||
}}</a-button>
|
||||
<a-button
|
||||
v-else
|
||||
type="outline"
|
||||
class="arco-btn-outline--secondary"
|
||||
size="mini"
|
||||
@click="getValidateHandler(item)"
|
||||
>{{ t('organization.service.testLink') }}</a-button
|
||||
>
|
||||
<a-button type="outline" class="arco-btn-outline--secondary" size="mini" @click="editHandler(item)">{{
|
||||
t('organization.service.edit')
|
||||
}}</a-button>
|
||||
<a-button
|
||||
v-if="item.isConfig"
|
||||
v-if="item.config"
|
||||
type="outline"
|
||||
class="arco-btn-outline--secondary"
|
||||
size="mini"
|
||||
|
@ -69,10 +79,16 @@
|
|||
>
|
||||
</a-space>
|
||||
<span>
|
||||
<a-tooltip v-if="!item.isConfig" :content="t('organization.service.unconfiguredTip')" position="br">
|
||||
<span><a-switch size="small" :disabled="true" /></span>
|
||||
<a-tooltip v-if="!item.config" :content="t('organization.service.unconfiguredTip')" position="br">
|
||||
<span
|
||||
><a-switch
|
||||
v-model="item.enable"
|
||||
size="small"
|
||||
:disabled="true"
|
||||
@change="(v) => changeStatus(v, item.id)"
|
||||
/></span>
|
||||
</a-tooltip>
|
||||
<a-switch v-else size="small" />
|
||||
<a-switch v-else v-model="item.enable" size="small" @change="(v) => changeStatus(v, item.id)" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -81,163 +97,118 @@
|
|||
</div>
|
||||
</div>
|
||||
</MsCard>
|
||||
<ConfigModal v-model:visible="serviceVisible" :rule="createRules" />
|
||||
<ConfigModal ref="ConfigRef" v-model:visible="serviceVisible" @success="loadList()" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive } from 'vue';
|
||||
import { ref, onBeforeMount } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import { getServiceList, getValidate, resetService, addOrUpdate } from '@/api/modules/setting/serviceIntegration';
|
||||
import ConfigModal from './conifgModal.vue';
|
||||
import { useUserStore } from '@/store';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import Message from '@arco-design/web-vue/es/message';
|
||||
import { characterLimit } from '@/utils';
|
||||
import type { ServiceList, ServiceItem } from '@/models/setting/serviceIntegration';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
|
||||
const props = defineProps<{
|
||||
const userStore = useUserStore();
|
||||
const lastOrganizationId = userStore.$state?.lastOrganizationId as string;
|
||||
|
||||
defineProps<{
|
||||
collapseHeight: string;
|
||||
}>();
|
||||
|
||||
const keyword = ref('');
|
||||
const data = ref([
|
||||
{
|
||||
id: '1-1-1-1',
|
||||
name: 'xxx',
|
||||
enable: true,
|
||||
isConfig: false,
|
||||
},
|
||||
{
|
||||
id: '2-2-2-2',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
isConfig: true,
|
||||
},
|
||||
{
|
||||
id: '3-3-3-3',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: 'xxxx',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: 'xxxx',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: '3-3-3-3',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: '3-3-3-3',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: 'xxxx',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: 'xxxx',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: '3-3-3-3',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
{
|
||||
id: '3-3-3-3',
|
||||
name: 'xxx',
|
||||
enable: false,
|
||||
},
|
||||
]);
|
||||
const filterList = ref<ServiceList>([]);
|
||||
const data = ref<ServiceList>([]);
|
||||
const loading = ref<boolean>(false);
|
||||
|
||||
// 集成列表
|
||||
const loadList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await getServiceList(lastOrganizationId);
|
||||
data.value = result;
|
||||
filterList.value = result;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const searchHandler = () => {
|
||||
filterList.value = data.value.filter((item) => item.title?.includes(keyword.value));
|
||||
};
|
||||
|
||||
const serviceVisible = ref<boolean>(false);
|
||||
let createRules = reactive([]);
|
||||
const ConfigRef = ref();
|
||||
|
||||
const editHandler = (item: any) => {
|
||||
// 添加或配置
|
||||
const editHandler = (serviceItem: ServiceItem) => {
|
||||
serviceVisible.value = true;
|
||||
ConfigRef.value.addOrEdit(serviceItem);
|
||||
ConfigRef.value.title = serviceItem.title;
|
||||
};
|
||||
// 重置
|
||||
const resetHandler = async (serviceItem: ServiceItem) => {
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('organization.service.resetServiceTip', { name: characterLimit(serviceItem.title) }),
|
||||
content: t('organization.service.resetServiceContentTip'),
|
||||
okText: t('organization.service.confirmReset'),
|
||||
cancelText: t('organization.service.Cancel'),
|
||||
okButtonProps: {
|
||||
status: 'normal',
|
||||
},
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
await resetService(serviceItem.id as string);
|
||||
Message.success(t('organization.service.resetConfigTip'));
|
||||
loadList();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
};
|
||||
const resetHandler = (item: any) => {};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
const result = JSON.stringify([
|
||||
{
|
||||
type: 'input',
|
||||
field: 'address',
|
||||
title: 'JIRA地址',
|
||||
value: 'JIRA地址',
|
||||
validate: [{ type: 'string', required: true, message: 'JIRA地址不能为空' }],
|
||||
},
|
||||
{
|
||||
type: 'radio',
|
||||
title: '认证方式',
|
||||
field: 'method',
|
||||
value: '1',
|
||||
options: [
|
||||
{
|
||||
value: '1',
|
||||
label: 'Auth',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: 'Token',
|
||||
},
|
||||
],
|
||||
props: {
|
||||
type: 'button',
|
||||
},
|
||||
wrap: {
|
||||
tooltip: 'info提示',
|
||||
},
|
||||
control: [
|
||||
{
|
||||
value: '1',
|
||||
rule: [
|
||||
{
|
||||
type: 'input',
|
||||
field: 'info',
|
||||
title: 'JIRA-账号',
|
||||
value: '账号',
|
||||
validate: [{ type: 'string', required: true, message: 'JIRA账号不能为空' }],
|
||||
wrap: {},
|
||||
},
|
||||
{
|
||||
type: 'PassWord',
|
||||
value: '',
|
||||
field: 'password',
|
||||
title: 'JIRA密码',
|
||||
validate: [{ type: 'string', required: true, message: 'JIRA密码不能为空' }],
|
||||
props: {
|
||||
placeholder: '请输入密码',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
rule: [
|
||||
{
|
||||
type: 'input',
|
||||
field: 'token',
|
||||
title: 'Token',
|
||||
value: 'token 账号',
|
||||
validate: [{ type: 'string', required: true, message: 'JIRA账号不能为空' }],
|
||||
wrap: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
createRules = JSON.parse(result);
|
||||
}, 1000);
|
||||
// 外部测试连接
|
||||
const getValidateHandler = async (serviceItem: ServiceItem) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
await getValidate(serviceItem.id as string);
|
||||
Message.success(t('organization.service.testLinkStatusTip'));
|
||||
loadList();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 切换状态
|
||||
const changeStatus = async (value: string | number | boolean, id: string | undefined) => {
|
||||
loading.value = true;
|
||||
const message = value ? 'organization.service.enableSuccess' : 'organization.service.closeSuccess';
|
||||
try {
|
||||
await addOrUpdate({ enable: value as boolean, id }, 'edit');
|
||||
Message.success(t(message));
|
||||
loadList();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
loadList();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -245,7 +216,6 @@
|
|||
.ms-card-wrap {
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
min-width: 1150px;
|
||||
height: calc(100% - 58px) !important;
|
||||
min-height: 300px;
|
||||
border-radius: var(--border-radius-small);
|
||||
|
@ -262,7 +232,6 @@
|
|||
height: 144px;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
flex-basis: calc(25% - 16px);
|
||||
@apply flex flex-col justify-between;
|
||||
.icon {
|
||||
border: 1px solid var(--color-text-n9);
|
||||
|
@ -273,27 +242,20 @@
|
|||
@apply px-2 py-1 text-xs;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 992px) {
|
||||
.item {
|
||||
flex-basis: calc(50% - 16px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 800px) {
|
||||
.item {
|
||||
flex-basis: calc(50% - 16px);
|
||||
}
|
||||
@media screen and (min-width: 1000px) and (max-width: 1440px) {
|
||||
.item {
|
||||
flex-basis: calc(33.3% - 16px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1160px) {
|
||||
.item {
|
||||
flex-basis: calc(33.3% - 16px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) and (min-width: 1800px) {
|
||||
.item {
|
||||
flex-basis: calc(25% - 16px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1800px) {
|
||||
.item {
|
||||
flex-basis: calc(25% - 16px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1800px) {
|
||||
.item {
|
||||
flex-basis: calc(25% - 16px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,26 @@
|
|||
<a-collapse :bordered="false" expand-icon-position="right" @change="changeHandler">
|
||||
<a-collapse-item key="1" class="font-medium" :header="t('organization.service.headerTip')">
|
||||
<template #expand-icon="{ active }">
|
||||
<span v-if="active" class="text-[rgb(var(--primary-6))]">{{ t('organization.service.packUp') }}</span>
|
||||
<span v-else class="text-[rgb(var(--primary-6))]">{{ t('organization.service.expand') }}</span>
|
||||
<span v-if="active" class="float-right -mr-4 text-[rgb(var(--primary-6))]">{{
|
||||
t('organization.service.packUp')
|
||||
}}</span>
|
||||
<span v-else class="float-right -mr-4 text-[rgb(var(--primary-6))]">{{
|
||||
t('organization.service.expand')
|
||||
}}</span>
|
||||
</template>
|
||||
<div class="flex w-[100%] flex-row justify-between text-sm font-normal">
|
||||
<div v-for="(item, index) in cardContent" :key="item.id" class="item" :class="`ms-item-${index}`">
|
||||
<span>
|
||||
<div
|
||||
v-for="(item, index) in cardContent"
|
||||
:key="item.id"
|
||||
class="item mt-4 p-[16px]"
|
||||
:class="`ms-item-${index}`"
|
||||
>
|
||||
<span class="mr-3">
|
||||
<svg-icon width="64px" height="46px" :name="item.icon" />
|
||||
</span>
|
||||
<div class="flex h-[100%] flex-1 flex-col justify-between p-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="leading-6">{{ t(item.title) }}</span>
|
||||
<div class="flex h-[100%] flex-1 flex-col justify-between">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-normal">{{ t(item.title) }}</span>
|
||||
<span>
|
||||
<a-button
|
||||
v-for="links of item.skipTitle"
|
||||
|
@ -24,13 +33,14 @@
|
|||
type="text"
|
||||
:href="links.src"
|
||||
target="_blank"
|
||||
@click="jumpHandler(links)"
|
||||
>
|
||||
{{ t(links.name) }}
|
||||
</a-button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-xs text-[var(--color-text-4)]">
|
||||
{{ t(item.description) }}
|
||||
<div class="one-line-text w-[400px]"> {{ t(item.description) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,9 +57,12 @@
|
|||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import ServiceList from './components/serviceList.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import type { StepListType, SkipTitle } from '@/models/setting/serviceIntegration';
|
||||
|
||||
const { t } = useI18n();
|
||||
const cardContent = ref([
|
||||
const router = useRouter();
|
||||
const cardContent = ref<StepListType[]>([
|
||||
{
|
||||
id: '1001',
|
||||
icon: 'configplugin',
|
||||
|
@ -57,11 +70,13 @@
|
|||
skipTitle: [
|
||||
{
|
||||
name: 'organization.service.developmentDoc',
|
||||
src: '',
|
||||
src: 'https://github.com/metersphere/metersphere-platform-plugin/wiki/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
name: 'organization.service.downPlugin',
|
||||
src: 'https://github.com/metersphere/metersphere-platform-plugin',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
step: '@/assets/images/ms_plugindownload.jpg',
|
||||
|
@ -75,6 +90,7 @@
|
|||
{
|
||||
name: 'organization.service.jumpPlugin',
|
||||
src: '',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
step: '@/assets/images/ms_configplugin.jpg',
|
||||
|
@ -88,6 +104,13 @@
|
|||
isCollapse.value = activeKey.length > 0;
|
||||
collapseHeight.value = activeKey.length > 0 ? '158px' : '72px';
|
||||
};
|
||||
|
||||
const jumpHandler = (links: SkipTitle) => {
|
||||
if (links.active)
|
||||
router.push({
|
||||
name: 'settingSystemPluginManger',
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@ -99,9 +122,10 @@
|
|||
}
|
||||
.item {
|
||||
width: calc(50% - 10px);
|
||||
height: 78px;
|
||||
border: 1px solid #ffffff;
|
||||
box-shadow: 0 0 7px rgb(120 56 135 / 10%);
|
||||
@apply flex h-20 items-center rounded-md;
|
||||
@apply flex items-center rounded-md;
|
||||
}
|
||||
.ms-item-0 {
|
||||
background: url('@/assets/images/ms_plugindownload.jpg') no-repeat center / cover;
|
||||
|
|
|
@ -8,15 +8,15 @@ export default {
|
|||
'organization.service.integrationList': 'Integration of List',
|
||||
'organization.service.packUp': 'Pack Up',
|
||||
'organization.service.expand': 'Expand',
|
||||
'organization.service.downloadPluginOrDev': 'Download plug-ins or develop plug-ins',
|
||||
'organization.service.downloadPluginOrDev': 'Download & develop',
|
||||
'organization.service.configPlugin': 'Configuring the plugin',
|
||||
'organization.service.downPlugin': 'Download the plugin',
|
||||
'organization.service.developmentDoc': 'Plug-in development documentation',
|
||||
'organization.service.downPlugin': 'Download',
|
||||
'organization.service.developmentDoc': 'development documentation',
|
||||
'organization.service.description':
|
||||
'Download third-party project management platform plug-ins that need to be integrated; you can also develop your own relevant project management platform plug-ins',
|
||||
'organization.service.configDescription':
|
||||
'Downloaded or developed plug-ins need to be uploaded to plug-in management, upload, you can configure the current page',
|
||||
'organization.service.jumpPlugin': 'JUMP to plug-in management',
|
||||
'organization.service.jumpPlugin': 'Jump to plugin',
|
||||
'organization.service.testLink': 'Test link',
|
||||
'organization.service.testLinkStatusTip': 'Test connection successful!',
|
||||
'organization.service.unconfigured': 'Unconfigured',
|
||||
|
@ -35,21 +35,19 @@ export default {
|
|||
'organization.service.tableColunmUsergroup': 'UserGroup',
|
||||
'organization.service.tableColunmStatus': 'Status',
|
||||
'organization.service.tableColunmActions': 'Actions',
|
||||
'organization.service.service': 'Member',
|
||||
'organization.service.selectMemberScope': 'Select the service you want to add. Multiple selection is supported',
|
||||
'organization.service.selectProjectScope': 'Select the project you want to add. Multiple selection is supported',
|
||||
'organization.service.selectMemberEmptyTip': 'The service can not be empty',
|
||||
'organization.service.selectProjectEmptyTip': 'The project can not be empty',
|
||||
'organization.service.selectUserEmptyTip': 'The user group can not be empty',
|
||||
'organization.service.Confirm': 'Confirm',
|
||||
'organization.service.Cancel': 'Cancel',
|
||||
'organization.service.deleteMemberTip': 'Are you sure to remove the user `{name}` ?',
|
||||
'system.user.deleteUserTip': 'Are you sure to delete the user `{name}` ?',
|
||||
'system.user.deleteUserTip': 'Are you sure to delete the user {name} ?',
|
||||
'organization.service.deleteMemberConfirm': 'Delete',
|
||||
'organization.service.deleteMemberCancel': 'Cancel',
|
||||
'organization.service.deleteMemberSuccess': 'Delete successful',
|
||||
'organization.service.batchModalSuccess': 'Successfully added',
|
||||
'organization.service.batchUpdateSuccess': 'Successfully updated',
|
||||
'organization.service.project': 'Project',
|
||||
'organization.service.selectUserScope': 'Please select a user group for the above members',
|
||||
'organization.service.confirmReset': 'Reset',
|
||||
'organization.service.resetServiceTip': 'Confirm reset {name} this service integration?',
|
||||
'organization.service.resetServiceContentTip':
|
||||
'After the Reset, the integration information will be cleared, the project can not integrate with the platform and the platform default template is not available, be careful!',
|
||||
'organization.service.searchService': 'Search by plug-in name',
|
||||
'organization.service.successMessage': 'The test connection was successful',
|
||||
'organization.service.enableSuccess': 'Enable successfully',
|
||||
'organization.service.closeSuccess': 'Disable successfully',
|
||||
'organization.service.configSuccess': 'Configuration successfully',
|
||||
'organization.service.updateSuccess': 'Update successfully',
|
||||
};
|
||||
|
|
|
@ -31,20 +31,18 @@ export default {
|
|||
'organization.service.tableColunmUsergroup': '用户组',
|
||||
'organization.service.tableColunmStatus': '状态',
|
||||
'organization.service.tableColunmActions': '操作',
|
||||
'organization.service.service': '成员',
|
||||
'organization.service.selectMemberScope': '请选择需要添加的成员支持多选',
|
||||
'organization.service.selectProjectScope': '请选择需要添加的项目支持多选',
|
||||
'organization.service.selectMemberEmptyTip': '成员不能为空',
|
||||
'organization.service.selectProjectEmptyTip': '项目不能为空',
|
||||
'organization.service.selectUserEmptyTip': '用户组不能为空',
|
||||
'organization.service.Confirm': '确定',
|
||||
'organization.service.Cancel': '取消',
|
||||
'organization.service.deleteMemberTip': '确认移除 `{name}` 这个成员吗?',
|
||||
'organization.service.deleteMemberConfirm': '确认删除',
|
||||
'organization.service.deleteMemberCancel': '取消',
|
||||
'organization.service.deleteMemberSuccess': '删除成功',
|
||||
'organization.service.batchModalSuccess': '添加成功',
|
||||
'organization.service.batchUpdateSuccess': '更新成功',
|
||||
'organization.service.project': '项目',
|
||||
'organization.service.selectUserScope': '请为以上成员选择用户组',
|
||||
'organization.service.confirmReset': '确认重置',
|
||||
'organization.service.resetServiceTip': '确认重置 {name} 这个服务集成吗?',
|
||||
'organization.service.resetServiceContentTip':
|
||||
'重置后,集成信息将被清空,项目无法与该平台集成且该平台默认模版不可用,谨慎操作!',
|
||||
'organization.service.searchService': '通过插件名称搜索',
|
||||
'organization.service.successMessage': '测试连接成功',
|
||||
'organization.service.enableSuccess': '启用成功',
|
||||
'organization.service.closeSuccess': '禁用成功',
|
||||
'organization.service.configSuccess': '配置成功',
|
||||
'organization.service.updateSuccess': '更新成功',
|
||||
};
|
||||
|
|
|
@ -32,12 +32,22 @@
|
|||
@expand="handleExpand"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column :width="300" fixed="left" :title="t('system.plugin.tableColumnsName')" :ellipsis="true">
|
||||
<a-table-column
|
||||
:width="300"
|
||||
fixed="left"
|
||||
:title="t('system.plugin.tableColumnsName')"
|
||||
:ellipsis="true"
|
||||
:tooltip="true"
|
||||
>
|
||||
<template #cell="{ record }">
|
||||
{{ record.name }} <span class="text-[--color-text-4]">({{ (record.pluginForms || []).length }})</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column :title="t('system.plugin.tableColumnsDescription')" data-index="description" />
|
||||
<a-table-column
|
||||
:title="t('system.plugin.tableColumnsDescription')"
|
||||
data-index="description"
|
||||
:ellipsis="true"
|
||||
/>
|
||||
<a-table-column :title="t('system.plugin.tableColumnsStatus')">
|
||||
<template #cell="{ record }">
|
||||
<div v-if="record.enable" class="flex items-center">
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
<MsUpload
|
||||
v-model:file-list="fileList"
|
||||
accept="jar"
|
||||
:max-size="50"
|
||||
size-unit="MB"
|
||||
main-text="system.user.importModalDragtext"
|
||||
:sub-text="t('system.plugin.supportFormat')"
|
||||
:show-file-list="false"
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
<div>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="continueAdd">{{ t('system.plugin.continueUpload') }}</a-button>
|
||||
<a-button type="outline">{{ t('system.plugin.ServiceIntegration') }}</a-button>
|
||||
<a-button type="outline" @click="router.push({ name: 'settingOrganizationService' })">{{
|
||||
t('system.plugin.ServiceIntegration')
|
||||
}}</a-button>
|
||||
<a-button type="secondary">{{ t('system.plugin.backPluginList') }}</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
@ -38,8 +40,10 @@
|
|||
import { useDialog } from '@/hooks/useDialog';
|
||||
import useVisit from '@/hooks/useVisit';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const visitedKey = 'doNotShowAgain';
|
||||
const { addVisited } = useVisit(visitedKey);
|
||||
const props = defineProps<{
|
||||
|
|
Loading…
Reference in New Issue