feat(系统设置): 服务集成页面搭建

This commit is contained in:
xinxin.wu 2023-08-09 14:25:09 +08:00 committed by fit2-zhao
parent 581ad85559
commit c5b4cc41aa
16 changed files with 839 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -574,3 +574,25 @@
} }
} }
} }
/** 折叠面板样式 **/
.arco-collapse {
padding: 0;
}
.arco-collapse-item-header {
padding: 0;
border-bottom: none;
}
.arco-collapse-item-content-box {
padding: 0;
}
.arco-collapse-item-content {
padding: 0;
background: none;
}
.arco-collapse-item {
margin-bottom: 0 !important;
}
.arco-collapse-item-header-title {
font-weight: 500;
}

View File

@ -0,0 +1,76 @@
<svg width="64" height="46" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="46" rx="4" fill="url(#paint0_linear_2120_250922)"/>
<g opacity="0.3" filter="url(#filter0_f_2120_250922)">
<rect x="20" y="39" width="24" height="2" rx="1" fill="#811FA3"/>
</g>
<path d="M37 36L45.5 27.5L43.5 25.5L35 34V36H37Z" fill="#811FA3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19 6C17.8954 6 17 6.89543 17 8V32C17 33.1046 17.8954 34 19 34H28.5563L42 20.5563V8C42 6.89543 41.1046 6 40 6H19Z" fill="#811FA3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M21 8C19.8954 8 19 8.89543 19 10V34C19 35.1046 19.8954 36 21 36H30.5563L44 22.5563V10C44 8.89543 43.1046 8 42 8H21Z" fill="#811FA3"/>
<g filter="url(#filter1_i_2120_250922)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21 8C19.8954 8 19 8.89543 19 10V34C19 35.1046 19.8954 36 21 36H30.5563L44 22.5563V10C44 8.89543 43.1046 8 42 8H21Z" fill="url(#paint1_linear_2120_250922)"/>
</g>
<g filter="url(#filter2_d_2120_250922)">
<rect x="21" y="12" width="17" height="3" rx="1.5" fill="white"/>
</g>
<g filter="url(#filter3_d_2120_250922)">
<rect x="21" y="19" width="13" height="3" rx="1.5" fill="white"/>
</g>
<g filter="url(#filter4_d_2120_250922)">
<rect x="21" y="26" width="9" height="3" rx="1.5" fill="white"/>
</g>
<defs>
<filter id="filter0_f_2120_250922" x="16" y="35" width="32" height="10" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="2" result="effect1_foregroundBlur_2120_250922"/>
</filter>
<filter id="filter1_i_2120_250922" x="19" y="8" width="25" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_2120_250922"/>
</filter>
<filter id="filter2_d_2120_250922" x="20" y="12" width="19" height="5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.505882 0 0 0 0 0.121569 0 0 0 0 0.639216 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2120_250922"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2120_250922" result="shape"/>
</filter>
<filter id="filter3_d_2120_250922" x="20" y="19" width="15" height="5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.505882 0 0 0 0 0.121569 0 0 0 0 0.639216 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2120_250922"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2120_250922" result="shape"/>
</filter>
<filter id="filter4_d_2120_250922" x="20" y="26" width="11" height="5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.505882 0 0 0 0 0.121569 0 0 0 0 0.639216 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2120_250922"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2120_250922" result="shape"/>
</filter>
<linearGradient id="paint0_linear_2120_250922" x1="62.4941" y1="1.50001" x2="-31.3204" y2="32.2514" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2E9F6"/>
<stop offset="1" stop-color="#F9F4FA" stop-opacity="0.12"/>
</linearGradient>
<linearGradient id="paint1_linear_2120_250922" x1="37" y1="29" x2="20.5" y2="9.5" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.8"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,61 @@
<svg width="64" height="46" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="46" rx="4" fill="url(#paint0_linear_2120_250895)"/>
<g opacity="0.3" filter="url(#filter0_f_2120_250895)">
<rect x="20" y="39" width="24" height="2" rx="1" fill="#811FA3"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M21 18.3333L17 21V34C17 35.1045 17.8954 36 19 36H45C46.1046 36 47 35.1045 47 34V21L43 18.3333V21L32 28L21 21V18.3333Z" fill="#811FA3"/>
<g filter="url(#filter1_i_2120_250895)">
<path d="M21 8C21 6.89543 21.8954 6 23 6H41C42.1046 6 43 6.89543 43 8V19.9021C43 20.5859 42.6506 21.2223 42.0738 21.5894L33.0738 27.3167C32.4186 27.7336 31.5814 27.7336 30.9262 27.3167L21.9263 21.5894C21.3494 21.2223 21 20.5859 21 19.9021V8Z" fill="#811FA3"/>
</g>
<g filter="url(#filter2_i_2120_250895)">
<path d="M21 8C21 6.89543 21.8954 6 23 6H41C42.1046 6 43 6.89543 43 8V19.9021C43 20.5859 42.6506 21.2223 42.0738 21.5894L33.0738 27.3167C32.4186 27.7336 31.5814 27.7336 30.9262 27.3167L21.9263 21.5894C21.3494 21.2223 21 20.5859 21 19.9021V8Z" fill="url(#paint1_linear_2120_250895)"/>
</g>
<g filter="url(#filter3_d_2120_250895)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.4285 12.4286C33.4285 11.6396 32.7889 11 31.9999 11C31.211 11 30.5714 11.6396 30.5714 12.4286V15.9493C30.5714 16.5404 29.8567 16.8364 29.4387 16.4184C28.8808 15.8605 27.9763 15.8605 27.4184 16.4184C26.8605 16.9763 26.8605 17.8808 27.4184 18.4387L30.9898 22.0102C31.5477 22.568 32.4523 22.568 33.0102 22.0102L36.5816 18.4387C37.1395 17.8808 37.1395 16.9763 36.5816 16.4184C36.0237 15.8605 35.1192 15.8605 34.5613 16.4184C34.1433 16.8364 33.4285 16.5404 33.4285 15.9492V12.4286Z" fill="white"/>
</g>
<defs>
<filter id="filter0_f_2120_250895" x="16" y="35" width="32" height="10" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="2" result="effect1_foregroundBlur_2120_250895"/>
</filter>
<filter id="filter1_i_2120_250895" x="21" y="6" width="22" height="21.6294" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_2120_250895"/>
</filter>
<filter id="filter2_i_2120_250895" x="21" y="6" width="22" height="21.6294" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_2120_250895"/>
</filter>
<filter id="filter3_d_2120_250895" x="26" y="11" width="12" height="13.4286" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.505882 0 0 0 0 0.121569 0 0 0 0 0.639216 0 0 0 0.24 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2120_250895"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2120_250895" result="shape"/>
</filter>
<linearGradient id="paint0_linear_2120_250895" x1="62.4941" y1="1.50001" x2="-31.3204" y2="32.2514" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2E9F6"/>
<stop offset="1" stop-color="#F9F4FA" stop-opacity="0.12"/>
</linearGradient>
<linearGradient id="paint1_linear_2120_250895" x1="32.5" y1="28" x2="32.5" y2="6" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.8"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,20 @@
<template>
<FormCreate v-model:api="fApi" :rule="rule" :option="option"></FormCreate>
</template>
<script setup lang="ts">
import PassWord from './formcreate-password.vue';
import formCreate, { Rule, Api } from '@form-create/arco-design';
formCreate.component('PassWord', PassWord);
const FormCreate = formCreate.$form();
defineProps<{
rule: Rule[];
option: any;
}>();
const fApi = {};
</script>
<style scoped></style>

View File

@ -0,0 +1,46 @@
<template>
<a-input
v-model="inputValue"
:max-length="250"
:type="isShowPassword ? 'password' : 'text'"
:placeholder="placeholder"
style="width: 100%"
autocomplete="username"
>
<template #suffix>
<span v-if="!isShowPassword" @click="togglePasswordVisibility">
<icon-eye />
</span>
<span v-else>
<icon-eye-invisible @click="togglePasswordVisibility" />
</span>
</template>
</a-input>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
defineProps<{
placeholder?: string;
value?: string;
}>();
const inputValue = ref('');
const emits = defineEmits<{
(event: 'update:modelValue', value: string): void;
}>();
watch(
() => inputValue.value,
(val: string) => {
emits('update:modelValue', val);
}
);
const isShowPassword = ref<boolean>(true);
const togglePasswordVisibility = () => {
isShowPassword.value = !isShowPassword.value;
};
</script>
<style scoped></style>

View File

@ -29,6 +29,7 @@ export default {
'menu.settings.system': 'System', 'menu.settings.system': 'System',
'menu.settings.organization': 'Organization', 'menu.settings.organization': 'Organization',
'menu.settings.organization.member': 'Member', 'menu.settings.organization.member': 'Member',
'menu.settings.organization.serviceIntegration': 'Service Integration',
'menu.settings.system.usergroup': 'User Group', 'menu.settings.system.usergroup': 'User Group',
'menu.settings.system.pluginmanger': 'Plugin Manger', 'menu.settings.system.pluginmanger': 'Plugin Manger',
'menu.settings.system.user': 'User', 'menu.settings.system.user': 'User',

View File

@ -29,6 +29,7 @@ export default {
'menu.settings.system': '系统', 'menu.settings.system': '系统',
'menu.settings.organization': '组织', 'menu.settings.organization': '组织',
'menu.settings.organization.member': '成员', 'menu.settings.organization.member': '成员',
'menu.settings.organization.serviceIntegration': '服务集成',
'menu.settings.system.user': '用户', 'menu.settings.system.user': '用户',
'menu.settings.system.usergroup': '用户组', 'menu.settings.system.usergroup': '用户组',
'menu.settings.system.pluginmanger': '插件管理', 'menu.settings.system.pluginmanger': '插件管理',

View File

@ -1,7 +1,6 @@
import { createApp } from 'vue'; import { createApp } from 'vue';
import ArcoVue from '@arco-design/web-vue'; import ArcoVue from '@arco-design/web-vue';
import '@arco-themes/vue-ms-theme-default/index.less'; import '@arco-themes/vue-ms-theme-default/index.less';
import FormCreate from '@form-create/arco-design';
import ArcoVueIcon from '@arco-design/web-vue/es/icon'; import ArcoVueIcon from '@arco-design/web-vue/es/icon';
import SvgIcon from '@/components/pure/svg-icon/index.vue'; import SvgIcon from '@/components/pure/svg-icon/index.vue';
import MSIcon from '@/components/pure/ms-icon-font/index.vue'; import MSIcon from '@/components/pure/ms-icon-font/index.vue';
@ -28,7 +27,6 @@ async function bootstrap() {
app.use(router); app.use(router);
app.use(directive); app.use(directive);
app.use(FormCreate);
app.mount('#app'); app.mount('#app');
} }

View File

@ -122,6 +122,16 @@ const Setting: AppRouteRecordRaw = {
isTopMenu: true, isTopMenu: true,
}, },
}, },
{
path: 'serviceIntegration',
name: 'settingOrganizationService',
component: () => import('@/views/setting/organization/serviceIntegration/index.vue'),
meta: {
locale: 'menu.settings.organization.serviceIntegration',
roles: ['*'],
isTopMenu: true,
},
},
], ],
}, },
], ],

View File

@ -0,0 +1,290 @@
<template>
<MsCard simple class="mb-[16px]" auto-height>
<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>
<a-input-search
v-model="keyword"
:placeholder="t('organization.member.searchMember')"
class="w-[230px]"
:max-length="250"
/>
</div>
</div>
<div class="ms-card-wrap">
<a-scrollbar
:style="{
overflow: 'auto',
height: `calc(100vh - ${collapseHeight} - 220px)`,
}"
>
<div class="list">
<div v-for="item of data" :key="item.id" class="item">
<div class="flex">
<span class="icon float-left mr-2 h-[40px] w-[40px]">{{ item.name }}</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
v-else
class="ms-enable active"
:style="{
background: 'rgb(var(--success-1))',
color: 'rgb(var(--success-6))',
}"
>{{ t('organization.service.configured') }}</span
>
</p>
<p class="mt-2 text-sm text-[var(--color-text-4)]">一站式敏捷研发协作云平台</p>
</div>
</div>
<div class="flex justify-between">
<a-space>
<a-tooltip v-if="!item.isConfig" :content="t('organization.service.unconfiguredTip')" position="tl">
<span>
<a-button
type="outline"
class="arco-btn-outline--secondary"
size="mini"
:disabled="!item.isConfig"
>{{ 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 type="outline" class="arco-btn-outline--secondary" size="mini" @click="editHanlder(item)">{{
t('organization.service.edit')
}}</a-button>
</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>
<a-switch v-else size="small" />
</span>
</div>
</div>
</div>
</a-scrollbar>
</div>
</div>
</MsCard>
<ShowModal v-model:visible="serviceVisible" :rule="createRules" />
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import MsCard from '@/components/pure/ms-card/index.vue';
import ShowModal from './showModal.vue';
const { t } = useI18n();
const props = 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 serviceVisible = ref<boolean>(false);
let createRules = reactive([]);
const editHanlder = (item: any) => {
serviceVisible.value = true;
};
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);
});
</script>
<style scoped lang="less">
.ms-card-wrap {
overflow: hidden;
padding: 8px;
min-width: 1150px;
height: calc(100% - 58px) !important;
min-height: 300px;
border-radius: var(--border-radius-small);
background: var(--color-text-n9);
.list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: flex-start;
width: 100%;
.item {
margin: 8px;
padding: 24px;
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);
}
.ms-enable {
border-radius: var(--border-radius-small);
background: var(--color-text-n9);
@apply px-2 py-1 text-xs;
}
}
@media screen and (max-width: 992px) {
.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 (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);
}
}
}
}
</style>

View File

@ -0,0 +1,101 @@
<template>
<a-modal
v-model:visible="detailVisible"
title-align="start"
class="ms-modal-form ms-modal-medium"
:ok-text="t('organization.member.Confirm')"
:cancel-text="t('organization.member.Cancel')"
>
<template #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-tooltip>
<template #content>
<div class="text-sm">{{ t('organization.service.statusEnableTip') }}</div>
<div class="text-sm">{{ t('organization.service.statusDisableTip') }}</div>
</template>
<icon-question-circle class="ml-2 text-[--color-text-4]" />
</a-tooltip>
</div>
<a-space>
<a-button type="secondary" @click="handleCancel">取消</a-button>
<a-button type="outline">测试链接</a-button>
<a-button type="primary" @click="saveHandler">确定</a-button>
</a-space>
</div>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { ref, watchEffect, watch } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
const { t } = useI18n();
const emits = defineEmits<{
(event: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
visible: boolean;
rule: any;
}>();
const detailVisible = ref<boolean>(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 = () => {
fApi.value.resetFields();
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,
on: false,
form: {
layout: 'vertical',
labelAlign: 'left',
},
row: {
gutter: 0,
},
wrap: {
'asterisk-position': 'end',
},
});
</script>
<style scoped></style>

View File

@ -0,0 +1,110 @@
<template>
<MsCard class="mb-[16px]" :title="t('system.config.parameterConfig')" simple auto-height>
<div class="h-30">
<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>
</template>
<div class="mt-[16px] flex w-[100%] flex-row justify-between text-sm font-normal">
<div v-for="(item, index) in cardContent" :key="index" class="item" :class="`ms-item-${index}`">
<span>
<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>
<span>
<a-button
v-for="links of item.skipTitle"
:key="links.name"
size="mini"
class="ml-3 px-0 text-sm"
type="text"
:href="links.src"
target="_blank"
>
{{ t(links.name) }}
</a-button>
</span>
</div>
<div class="text-xs text-[var(--color-text-4)]">
{{ t(item.description) }}
</div>
</div>
</div>
</div>
</a-collapse-item>
</a-collapse>
</div>
</MsCard>
<ServiceList :collapse-height="collapseHeight" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import MsCard from '@/components/pure/ms-card/index.vue';
import ServiceList from './components/serviceList.vue';
const { t } = useI18n();
const cardContent = ref([
{
icon: 'configplugin',
title: 'organization.service.downloadPluginOrDev',
skipTitle: [
{
name: 'organization.service.developmentDoc',
src: '',
},
{
name: 'organization.service.downPlugin',
src: 'https://github.com/metersphere/metersphere-platform-plugin',
},
],
step: '@/assets/images/ms_plugindownload.jpg',
description: 'organization.service.description',
},
{
icon: 'downloadplugin',
title: 'organization.service.configPlugin',
skipTitle: [
{
name: 'organization.service.jumpPlugin',
src: '',
},
],
step: '@/assets/images/ms_configplugin.jpg',
description: 'organization.service.configDescription',
},
]);
const isCollapse = ref<boolean>(false);
const collapseHeight = ref<string>('72px');
const changeHandler = (activeKey: (string | number)[]) => {
isCollapse.value = activeKey.length > 0;
collapseHeight.value = activeKey.length > 0 ? '158px' : '72px';
};
</script>
<style scoped lang="less">
:deep(.arco-icon-hover::before) {
display: none;
}
:deep(.arco-scrollbar-container) {
width: 100% !important;
}
.item {
width: calc(50% - 10px);
border: 1px solid #ffffff;
box-shadow: 0 0 7px rgb(120 56 135 / 10%);
@apply flex h-20 items-center rounded-md;
}
.ms-item-0 {
background: url('@/assets/images/ms_plugindownload.jpg') no-repeat center / cover;
}
.ms-item-1 {
background: url('@/assets/images/ms_configplugin.jpg') no-repeat center / cover;
}
</style>

View File

@ -0,0 +1,53 @@
export default {
'organization.service.searchPlugin': 'Search by plug-in name',
'system.service.statusEnableTip':
'Open: projects can integrate with the platform and generate default templates for the platform',
'system.service.statusDisableTip':
'Shutdown: the project can not integrate with the platform and the default template for the platform is not available',
'organization.service.headerTip': 'Service integration usage guidelines',
'organization.service.serviceIntegration': 'Service Integration',
'organization.service.packUp': 'Pack Up',
'organization.service.expand': 'Expand',
'organization.service.downloadPluginOrDev': 'Download plug-ins or develop plug-ins',
'organization.service.configPlugin': 'Configuring the plugin',
'organization.service.downPlugin': 'Download the plugin',
'organization.service.developmentDoc': 'Plug-in 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.testLink': 'Test link',
'organization.service.unconfigured': 'Unconfigured',
'organization.service.configured': 'Configured',
'organization.service.methodOfAuthentication': 'Method of authentication',
'organization.service.edit': 'Edit',
'organization.service.unconfiguredTip': 'Not configured yet. Configure and open on the edit page',
'organization.service.batchActionAddUsergroup': 'Add to usergroup',
'organization.service.tableEnable': 'Enabled',
'organization.service.tableDisable': 'Disabled',
'organization.service.tableColunmEmail': 'Email',
'organization.service.tableColunmName': 'Name',
'organization.service.tableColunmPhone': 'Phone',
'organization.service.tableColunmPro': 'Project',
'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}` ?',
'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.proejct': 'Project',
'organization.service.selectUserScope': 'Please select a user group for the above members',
};

View File

@ -0,0 +1,48 @@
export default {
'organization.service.searchPlugin': '通过插件名称搜索',
'organization.service.statusEnableTip': '开启:项目可以与该平台集成并生成该平台的默认模版',
'organization.service.statusDisableTip': '关闭:项目无法与该平台集成且该平台默认模版不可用',
'organization.service.headerTip': '服务集成 使用指引',
'organization.service.serviceIntegration': '服务集成',
'organization.service.packUp': '收起',
'organization.service.expand': '展开',
'organization.service.downloadPluginOrDev': '下载插件或开发插件',
'organization.service.configPlugin': '配置插件',
'organization.service.downPlugin': '下载插件',
'organization.service.developmentDoc': '插件开发文档',
'organization.service.description': '下载需要集成的第三方项目管理平台插件;也可以自行开发相关项目管理平台插件',
'organization.service.configDescription': '已下载或已开发的插件需上传至插件管理,上传后,可在当前页进行配置',
'organization.service.jumpPlugin': '跳转至插件管理',
'organization.service.testLink': '测试链接',
'organization.service.unconfigured': '未配置',
'organization.service.configured': '已配置',
'organization.service.methodOfAuthentication': '认证方式',
'organization.service.edit': '编辑',
'organization.service.unconfiguredTip': '暂未配置,可在编辑页配置并开启',
'organization.service.batchActionAddUsergroup': '添加至用户组',
'organization.service.tableEnable': '正常',
'organization.service.tableDisable': '禁用',
'organization.service.tableColunmEmail': '邮箱',
'organization.service.tableColunmName': '姓名',
'organization.service.tableColunmPhone': '手机',
'organization.service.tableColunmPro': '项目',
'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.proejct': '项目',
'organization.service.selectUserScope': '请为以上成员选择用户组',
};