Merge branch 'master' of https://gitcode.com/hk_openRepo/OpenRepo_Portal into junjie_dev
# Conflicts: # src/views/Jyh/Search/Components/BatchVerify.vue
This commit is contained in:
@@ -5,10 +5,10 @@ VITE_ENV = 'production'
|
|||||||
VITE_HOST = 'http://222.20.126.217:10010/openRepoPortal'
|
VITE_HOST = 'http://222.20.126.217:10010/openRepoPortal'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_API_HOST = 'https://web-api.gitcode.com'
|
VITE_API_HOST = '/gateway/official'
|
||||||
|
|
||||||
# devPress接口地址
|
# devPress接口地址
|
||||||
VITE_DEV_API_HOST = 'https://gitcode.com'
|
VITE_DEV_API_HOST = '/gateway/official'
|
||||||
|
|
||||||
# devPress地址
|
# devPress地址
|
||||||
VITE_DEV_HOST = 'https://gitcode.com'
|
VITE_DEV_HOST = 'https://gitcode.com'
|
||||||
|
|||||||
@@ -1,50 +1,45 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import {
|
||||||
|
type CreateOrganizationApiResultType,
|
||||||
|
type OrganizationMemberItemType,
|
||||||
|
type UnitRes
|
||||||
|
} from "@/api/organizationManage/organizationManageType";
|
||||||
|
|
||||||
// TODO 获取组织信息功能 没有相关接口,待对齐
|
export function createOrganizationApi(params: { groupName: string, groupDesc: string }): Promise<UnitRes<CreateOrganizationApiResultType>> {
|
||||||
export function getOrganizationInfoApi(params) {
|
|
||||||
return request({
|
return request({
|
||||||
url: ``,
|
url: `/api/v1/group/create`,
|
||||||
|
method: 'post',
|
||||||
|
data: params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateOrganizationInfoApi(params: { id: number, name: string, desc: string }): Promise<UnitRes<CreateOrganizationApiResultType>> {
|
||||||
|
return request({
|
||||||
|
url: `/api/v1/group/update`,
|
||||||
|
method: 'post',
|
||||||
|
data: params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOrganizationMemberListApi(params: { groupId: number }): Promise<UnitRes<any>> {
|
||||||
|
return request({
|
||||||
|
url: `/api/v1/group/member/list`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOrganizationApi(params) {
|
export function inviteOrganizationMemberApi(params: { groupId: number, username: string, roleCode: string }): Promise<UnitRes<boolean>> {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/v1/user/group/create`,
|
url: `/api/v1/group/member/invite `,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: params,
|
data: params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 更新组织信息功能 没有相关接口,待对齐
|
export function deleteOrganizationMemberApi(params: { groupId: number, username: string }): Promise<UnitRes<boolean>> {
|
||||||
export function updateOrganizationInfoApi(params) {
|
|
||||||
return request({
|
return request({
|
||||||
url: `/api/v1/user/group/create`,
|
url: `/api/v1/group/member/remove`,
|
||||||
method: 'post',
|
|
||||||
data: params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getOrganizationMemberListApi(params) {
|
|
||||||
return request({
|
|
||||||
url: `/api/v1/user/group/member/list`,
|
|
||||||
method: 'get',
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inviteOrganizationMemberApi(params) {
|
|
||||||
return request({
|
|
||||||
url: `/api/v1/user/group/member/invite `,
|
|
||||||
method: 'post',
|
|
||||||
data: params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteOrganizationMemberApi(params) {
|
|
||||||
return request({
|
|
||||||
url: `/api/v1/user/group/member/remove`,
|
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
data: params,
|
data: params,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,65 @@
|
|||||||
|
import { type AxiosResponse } from "axios";
|
||||||
|
|
||||||
|
export interface ApiDefaultType<T> {
|
||||||
|
data?: {
|
||||||
|
data?: T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CommonRes<T> {
|
||||||
|
code: number;
|
||||||
|
msg: string;
|
||||||
|
data: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UnitRes<T> = AxiosResponse<CommonRes<T>>;
|
||||||
|
|
||||||
|
export interface CreateOrganizationApiResultType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
ext: null;
|
||||||
|
status: null;
|
||||||
|
deleted: null;
|
||||||
|
createUser: string;
|
||||||
|
createTime: string;
|
||||||
|
updateTime: null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface OrganizationInfoType {
|
export interface OrganizationInfoType {
|
||||||
|
groupId: number;
|
||||||
organizationName: string;
|
organizationName: string;
|
||||||
organizationProfile: string;
|
organizationProfile: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrganizationMemberItemType {
|
export interface UserInfoType {
|
||||||
id: string;
|
username: string;
|
||||||
userName: string;
|
mobile: null;
|
||||||
role: string;
|
email: string;
|
||||||
email: string;
|
avatar: string;
|
||||||
joinDate: string;
|
noticeUnreadNum: number;
|
||||||
|
inviteNum: number;
|
||||||
|
groupId: null | number;
|
||||||
|
groupName: null | string;
|
||||||
|
groupDesc: null | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OrganizationMemberRoleEnum {
|
||||||
|
OWNER = 'OWNER',
|
||||||
|
MEMBER = 'MEMBER',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OrganizationMemberStatusEnum {
|
||||||
|
TO_ACCEPTED = 0,
|
||||||
|
ACCEPTED = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrganizationMemberItemType {
|
||||||
|
id: number;
|
||||||
|
groupId: number;
|
||||||
|
name: string; // 组织名称
|
||||||
|
username: string;
|
||||||
|
roleCode: OrganizationMemberRoleEnum;
|
||||||
|
status: OrganizationMemberStatusEnum;
|
||||||
|
createTime: string;
|
||||||
|
updateTime: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,24 @@
|
|||||||
<div class="bg-white w-full flex flex-col items-center py-[20px]">
|
<div class="bg-white w-full flex flex-col items-center py-[20px]">
|
||||||
<slot name="img">
|
<slot name="img">
|
||||||
<img
|
<img
|
||||||
v-if="!hideImg"
|
v-if="!hideImg && imgSrc"
|
||||||
class="block mb-[20px]"
|
class="block mb-[20px]"
|
||||||
:width="imgWidth"
|
:width="imgWidth"
|
||||||
:src="src"
|
:src="imgSrc"
|
||||||
|
alt="NoData"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
v-if="!hideImg && !small"
|
||||||
|
class="block mb-[20px]"
|
||||||
|
:width="imgWidth"
|
||||||
|
src="/src/assets/imgs/jyh/nodata.svg"
|
||||||
|
alt="NoData"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
v-if="!hideImg && small"
|
||||||
|
class="block mb-[20px]"
|
||||||
|
:width="imgWidth"
|
||||||
|
src="/src/assets/imgs/jyh/nodata_small.svg"
|
||||||
alt="NoData"
|
alt="NoData"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -36,12 +50,6 @@ const props = defineProps({
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const src = computed(() => {
|
|
||||||
if (props.imgSrc) {
|
|
||||||
return props.imgSrc;
|
|
||||||
}
|
|
||||||
return props.small ? '/src/assets/imgs/jyh/nodata_small.svg' : '/src/assets/imgs/jyh/nodata.svg';
|
|
||||||
});
|
|
||||||
const imgWidth = computed(() => {
|
const imgWidth = computed(() => {
|
||||||
if (props.width) {
|
if (props.width) {
|
||||||
return props.width;
|
return props.width;
|
||||||
|
|||||||
@@ -40,7 +40,16 @@ const toolbarConfig = [
|
|||||||
['ul', 'ol', 'checklist', 'code', 'link', 'image', 'table'],
|
['ul', 'ol', 'checklist', 'code', 'link', 'image', 'table'],
|
||||||
];
|
];
|
||||||
const mode = ref('readonly');
|
const mode = ref('readonly');
|
||||||
warningData.value = JSON.parse(propsData.warningData.alertMsg ?? '{}');
|
warningData.value = JSON.parse(propsData.warningData.alertMsg ?? JSON.stringify({
|
||||||
|
subject: '【漏洞排查预警】ApacheIgnite远程代码执行漏洞排查(CVE-2024-52577)',
|
||||||
|
importance: '高',
|
||||||
|
group: '可信开源代码库运营团队',
|
||||||
|
pulishTime: '2025-2-20',
|
||||||
|
overview: `## 一、概要
|
||||||
|
近日,安全中心发现Apache lgnite远程代码执行漏洞(CVE-2024-52577)。在 2.6.0<Apache Ignite< 2.17.0版本中,由于lgnite未能正确实施类序列化过滤器,攻击者能够利用恶意序列化对象绕过安全检查,从而在服务器端反序列化时触发任意代码的执行。经可信开源代码库运营团队评审漏洞技术定级2级/3级,若不满足利用条件可举证降为6级。请你按要求在XX时间内完成修复。
|
||||||
|
## 二、修复方案
|
||||||
|
升级Apache Ignite至安全版本:2.17.0`
|
||||||
|
}));
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
emit('close');
|
emit('close');
|
||||||
};
|
};
|
||||||
@@ -78,7 +87,7 @@ const handleModeChange = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.warning-text {
|
.warning-text {
|
||||||
padding: 20px;
|
padding: 20px 20px 0;
|
||||||
background: #F6F6F8;
|
background: #F6F6F8;
|
||||||
color: initial;
|
color: initial;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mt-3">
|
<div v-loading="searchOrganizationLoading" class="mt-3">
|
||||||
<div v-if="hasOrganization">
|
<div v-if="hasOrganization">
|
||||||
<d-card class="mb-[16px] bg-white" shadow="never">
|
<d-card class="mb-[16px] bg-white" shadow="never">
|
||||||
<div class="text-[14px] w-full flex items-center justify-between">
|
<div class="text-[14px] w-full flex items-center justify-between">
|
||||||
@@ -36,19 +36,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<d-table
|
<d-table
|
||||||
:data="memberTableData"
|
:data="memberTableData"
|
||||||
|
:show-loading="memberListSearchLoading"
|
||||||
class="w-full mb-[20px] organ-table"
|
class="w-full mb-[20px] organ-table"
|
||||||
:fix-header="memberTableData.length > 0"
|
:fix-header="memberTableData.length > 0"
|
||||||
header-bg
|
header-bg
|
||||||
max-height="500px"
|
max-height="500px"
|
||||||
>
|
>
|
||||||
<d-column field="userName" header="成员名" />
|
<d-column field="username" header="成员名" />
|
||||||
<d-column field="role" header="角色">
|
<d-column field="roleCode" header="角色">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ memberRoleMap[row.role] ?? '' }}
|
{{ memberRoleMap[row.roleCode] ?? '' }}
|
||||||
</template>
|
</template>
|
||||||
</d-column>
|
</d-column>
|
||||||
<d-column field="email" header="邮箱" />
|
<d-column field="email" header="邮箱" />
|
||||||
<d-column field="joinDate" header="加入时间" />
|
<d-column field="createTime" header="加入时间" />
|
||||||
<d-column header="操作">
|
<d-column header="操作">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<d-button size="sm" variant="text" color="primary" class="p-0 justify-start" @click="openDeleteModal(row)">删除</d-button>
|
<d-button size="sm" variant="text" color="primary" class="p-0 justify-start" @click="openDeleteModal(row)">删除</d-button>
|
||||||
@@ -66,6 +67,8 @@
|
|||||||
:can-view-total="true"
|
:can-view-total="true"
|
||||||
:can-change-page-size="true"
|
:can-change-page-size="true"
|
||||||
:max-items="5"
|
:max-items="5"
|
||||||
|
@page-index-change="pagerIndexChange"
|
||||||
|
@page-size-change="pagerSizeChange"
|
||||||
/>
|
/>
|
||||||
</d-card>
|
</d-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +92,7 @@
|
|||||||
</d-form>
|
</d-form>
|
||||||
|
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<d-button variant="solid" class="mr-[8px]" @click="confirmCreateOrganizationBtnClick">确定</d-button>
|
<d-button :loading="createOrganizationLoading" variant="solid" class="mr-[8px]" @click="confirmCreateOrganizationBtnClick">确定</d-button>
|
||||||
<d-button @click="closeOrganizationModal">取消</d-button>
|
<d-button @click="closeOrganizationModal">取消</d-button>
|
||||||
</div>
|
</div>
|
||||||
</d-modal>
|
</d-modal>
|
||||||
@@ -107,15 +110,15 @@
|
|||||||
</d-form>
|
</d-form>
|
||||||
|
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<d-button variant="solid" class="mr-[8px]" @click="inviteMemberConfirmBtnClick">确定</d-button>
|
<d-button variant="solid" class="mr-[8px]" :loading="inviteMemberLoading" @click="inviteMemberConfirmBtnClick">确定</d-button>
|
||||||
<d-button @click="closeInviteMemberModal">取消</d-button>
|
<d-button @click="closeInviteMemberModal">取消</d-button>
|
||||||
</div>
|
</div>
|
||||||
</d-modal>
|
</d-modal>
|
||||||
|
|
||||||
<d-modal v-model="deleteMemberModalCtrl" title="删除成员" class="w-[600px]">
|
<d-modal v-model="deleteMemberModalCtrl" title="删除成员" class="w-[600px]">
|
||||||
<div class="mb-[20px]">即将删除成员‘{{ deleteRow.userName }}’,请确认是否继续?</div>
|
<div class="mb-[20px]">即将删除成员‘{{ deleteRow.username }}’,请确认是否继续?</div>
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<d-button variant="solid" class="mr-[8px]" @click="deleteMember">确定</d-button>
|
<d-button variant="solid" class="mr-[8px]" :loading="deleteMemberLoading" @click="deleteMember">确定</d-button>
|
||||||
<d-button @click="closeDeleteMemberModal">取消</d-button>
|
<d-button @click="closeDeleteMemberModal">取消</d-button>
|
||||||
</div>
|
</div>
|
||||||
</d-modal>
|
</d-modal>
|
||||||
@@ -123,24 +126,38 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, shallowRef } from 'vue';
|
import { reactive, ref, shallowRef } from 'vue';
|
||||||
|
import { Message } from 'vue-devui';
|
||||||
import NoData from '@/components/NoData/NoData.vue';
|
import NoData from '@/components/NoData/NoData.vue';
|
||||||
import {
|
import {
|
||||||
createOrganizationApi,
|
createOrganizationApi,
|
||||||
deleteOrganizationMemberApi,
|
deleteOrganizationMemberApi,
|
||||||
getOrganizationInfoApi,
|
|
||||||
getOrganizationMemberListApi,
|
getOrganizationMemberListApi,
|
||||||
inviteOrganizationMemberApi,
|
inviteOrganizationMemberApi,
|
||||||
updateOrganizationInfoApi
|
updateOrganizationInfoApi
|
||||||
} from '@/api/organizationManage/organizationManageApi';
|
} from '@/api/organizationManage/organizationManageApi';
|
||||||
import {
|
import {
|
||||||
type OrganizationInfoType,
|
type OrganizationInfoType,
|
||||||
type OrganizationMemberItemType
|
type OrganizationMemberItemType,
|
||||||
|
OrganizationMemberRoleEnum,
|
||||||
|
type UserInfoType,
|
||||||
} from '@/api/organizationManage/organizationManageType';
|
} from '@/api/organizationManage/organizationManageType';
|
||||||
import table from '@/components/AIRepair/Table.vue';
|
import {getUserInfo} from "@/api/user";
|
||||||
|
|
||||||
|
const userInfo = shallowRef<UserInfoType>({
|
||||||
|
username: '',
|
||||||
|
mobile: null,
|
||||||
|
email: '',
|
||||||
|
avatar: '',
|
||||||
|
noticeUnreadNum: 0,
|
||||||
|
inviteNum: 0,
|
||||||
|
groupId: null,
|
||||||
|
groupName: null,
|
||||||
|
groupDesc: null,
|
||||||
|
});
|
||||||
const searchOrganizationLoading = ref(false);
|
const searchOrganizationLoading = ref(false);
|
||||||
const hasOrganization = ref(false);
|
const hasOrganization = ref(false);
|
||||||
const organizationInfo = shallowRef<OrganizationInfoType>({
|
const organizationInfo = shallowRef<OrganizationInfoType>({
|
||||||
|
groupId: 0,
|
||||||
organizationName: '',
|
organizationName: '',
|
||||||
organizationProfile: ''
|
organizationProfile: ''
|
||||||
});
|
});
|
||||||
@@ -158,6 +175,8 @@ const editLoading = ref(false);
|
|||||||
|
|
||||||
const memberListSearchLoading = ref(false);
|
const memberListSearchLoading = ref(false);
|
||||||
const memberListSearchParam = ref('');
|
const memberListSearchParam = ref('');
|
||||||
|
let originMemberList: OrganizationMemberItemType[] = [];
|
||||||
|
let filterMemberList: OrganizationMemberItemType[] = [];
|
||||||
const memberTableData = shallowRef<OrganizationMemberItemType[]>([]);
|
const memberTableData = shallowRef<OrganizationMemberItemType[]>([]);
|
||||||
const pager = reactive({
|
const pager = reactive({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -177,45 +196,40 @@ const inviteMemberFormData = reactive({
|
|||||||
role: ''
|
role: ''
|
||||||
});
|
});
|
||||||
const inviteMemberSelectOptions = [
|
const inviteMemberSelectOptions = [
|
||||||
{ name: '创建者', value: 'creator' },
|
{ name: '创建者', value: OrganizationMemberRoleEnum.OWNER },
|
||||||
{ name: '成员', value: 'member' }
|
{ name: '成员', value: OrganizationMemberRoleEnum.MEMBER }
|
||||||
];
|
];
|
||||||
const memberRoleMap = {
|
const memberRoleMap = {
|
||||||
creator: '创建者',
|
[OrganizationMemberRoleEnum.OWNER]: '创建者',
|
||||||
member: '成员'
|
[OrganizationMemberRoleEnum.MEMBER]: '成员'
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockTableData = [
|
init();
|
||||||
{ userName: '张三', role: 'member', email: '111@gmail.com', joinDate: '2090-02-30', id: '1' },
|
function init() {
|
||||||
{ userName: '李四', role: 'creator', email: '111@gmail.com', joinDate: '2090-02-30', id: '2' },
|
queryUserInfo();
|
||||||
{ userName: '王五', role: 'member', email: '111@gmail.com', joinDate: '2090-02-30', id: '3' },
|
|
||||||
{ userName: '赵六', role: 'member', email: '111@gmail.com', joinDate: '2090-02-30', id: '4' },
|
|
||||||
{ userName: '秦七', role: 'member', email: '111@gmail.com', joinDate: '2090-02-30', id: '5' }
|
|
||||||
];
|
|
||||||
|
|
||||||
// -------------------- 获取组织信息 --------------------
|
|
||||||
async function getOrganizationInfo() {
|
|
||||||
const params = {
|
|
||||||
organizationName: createFormData.organizationName,
|
|
||||||
organizationProfile: createFormData.organizationProfile
|
|
||||||
};
|
|
||||||
searchOrganizationLoading.value = true;
|
|
||||||
try {
|
|
||||||
const res = await getOrganizationInfoApi(params);
|
|
||||||
} catch (e) {}
|
|
||||||
searchOrganizationLoading.value = false;
|
|
||||||
getMemberList();
|
|
||||||
// TODO 待接口定义好后删除下面两行固定赋值语句
|
|
||||||
hasOrganization.value = true;
|
|
||||||
organizationInfo.value = {
|
|
||||||
organizationName: createFormData.organizationName,
|
|
||||||
organizationProfile: createFormData.organizationProfile
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- 获取成员信息 --------------------
|
// -------------------- 获取组织信息 --------------------
|
||||||
async function getOrganizationMember(organizationId: string) {
|
async function queryUserInfo() {
|
||||||
const params = {};
|
searchOrganizationLoading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getUserInfo();
|
||||||
|
if (res.data?.data?.code === 200) {
|
||||||
|
userInfo.value = res.data?.data.data;
|
||||||
|
}
|
||||||
|
if (userInfo.value.groupId) {
|
||||||
|
hasOrganization.value = true;
|
||||||
|
organizationInfo.value = {
|
||||||
|
groupId: userInfo.value.groupId,
|
||||||
|
organizationName: userInfo.value.groupName as string,
|
||||||
|
organizationProfile: userInfo.value.groupDesc as string,
|
||||||
|
};
|
||||||
|
getMemberList();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('查询用户信息失败');
|
||||||
|
}
|
||||||
|
searchOrganizationLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- 创建组织 --------------------
|
// -------------------- 创建组织 --------------------
|
||||||
@@ -229,16 +243,21 @@ function confirmCreateOrganizationBtnClick() {
|
|||||||
|
|
||||||
async function createOrganization() {
|
async function createOrganization() {
|
||||||
const params = {
|
const params = {
|
||||||
organizationName: createFormData.organizationName,
|
groupName: createFormData.organizationName,
|
||||||
organizationProfile: createFormData.organizationProfile
|
groupDesc: createFormData.organizationProfile
|
||||||
};
|
};
|
||||||
createOrganizationLoading.value = true;
|
createOrganizationLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await createOrganizationApi(params);
|
const res = await createOrganizationApi(params);
|
||||||
} catch (e) {}
|
if (res.data?.code !== 200) {
|
||||||
closeOrganizationModal();
|
Message.error(res.data?.msg || '创建失败');
|
||||||
// TODO 待接口定义好后删除下面调用逻辑
|
} else {
|
||||||
getOrganizationInfo();
|
closeOrganizationModal();
|
||||||
|
queryUserInfo();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('接口错误,创建失败');
|
||||||
|
}
|
||||||
createOrganizationLoading.value = false;
|
createOrganizationLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,31 +266,46 @@ function openCreateOrganizationModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeOrganizationModal() {
|
function closeOrganizationModal() {
|
||||||
|
createFormData.organizationName = '';
|
||||||
|
createFormData.organizationProfile = '';
|
||||||
createOrganizationModalCtrl.value = false;
|
createOrganizationModalCtrl.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- 编辑组织信息 --------------------
|
// -------------------- 编辑组织信息 --------------------
|
||||||
function editIconClick() {
|
function editIconClick() {
|
||||||
|
createFormData.organizationName = organizationInfo.value.organizationName;
|
||||||
|
createFormData.organizationProfile = organizationInfo.value.organizationProfile;
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function editOrganizationConfirm() {
|
async function editOrganizationConfirm() {
|
||||||
|
if (!createFormData.organizationName || !createFormData.organizationProfile) {
|
||||||
|
Message.warning('组织名称和组织简介不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
editLoading.value = true;
|
editLoading.value = true;
|
||||||
const params = {
|
const params = {
|
||||||
organizationName: createFormData.organizationName,
|
id: organizationInfo.value.groupId,
|
||||||
organizationProfile: createFormData.organizationProfile
|
name: createFormData.organizationName,
|
||||||
|
desc: createFormData.organizationProfile
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const res = await updateOrganizationInfoApi(params);
|
const res = await updateOrganizationInfoApi(params);
|
||||||
} catch (e) {}
|
if (res.data?.code === 200) {
|
||||||
|
organizationInfo.value = {
|
||||||
|
groupId: organizationInfo.value.groupId,
|
||||||
|
...createFormData,
|
||||||
|
};
|
||||||
|
createFormData.organizationName = '';
|
||||||
|
createFormData.organizationProfile = '';
|
||||||
|
} else {
|
||||||
|
Message.error(res.data?.msg || '更新失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('接口错误,更新失败');
|
||||||
|
}
|
||||||
editLoading.value = false;
|
editLoading.value = false;
|
||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
// TODO 待接口定义好后删除下面两行固定赋值语句
|
|
||||||
hasOrganization.value = true;
|
|
||||||
organizationInfo.value = {
|
|
||||||
organizationName: createFormData.organizationName,
|
|
||||||
organizationProfile: createFormData.organizationProfile
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function editOrganizationCancel() {
|
function editOrganizationCancel() {
|
||||||
@@ -282,21 +316,41 @@ function editOrganizationCancel() {
|
|||||||
|
|
||||||
// -------------------- 邀请、查询成员 --------------------
|
// -------------------- 邀请、查询成员 --------------------
|
||||||
async function getMemberList() {
|
async function getMemberList() {
|
||||||
const params = {
|
|
||||||
organizationName: createFormData.organizationName,
|
|
||||||
pageIndex: pager.pageIndex,
|
|
||||||
pageSize: pager.pageSize,
|
|
||||||
searchParam: memberListSearchParam.value
|
|
||||||
};
|
|
||||||
memberListSearchLoading.value = true;
|
memberListSearchLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await getOrganizationMemberListApi(params);
|
const res = await getOrganizationMemberListApi({ groupId: organizationInfo.value.groupId });
|
||||||
} catch (e) {}
|
if (res.data?.code === 200) {
|
||||||
memberTableData.value = mockTableData;
|
originMemberList = res.data?.data;
|
||||||
pager.total = 6;
|
updateFilterTableList();
|
||||||
|
} else {
|
||||||
|
Message.warning(res.data?.msg || '查询失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.error('接口错误,查询失败');
|
||||||
|
}
|
||||||
memberListSearchLoading.value = false;
|
memberListSearchLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateFilterTableList() {
|
||||||
|
const queryStr = memberListSearchParam.value;
|
||||||
|
filterMemberList = queryStr ? originMemberList.filter(item => item.username.includes(queryStr)) : originMemberList;
|
||||||
|
updateCurrentPageTableList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCurrentPageTableList() {
|
||||||
|
const endIndex = pager.pageIndex * pager.pageSize;
|
||||||
|
memberTableData.value = filterMemberList.slice(endIndex - pager.pageSize, endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pagerIndexChange() {
|
||||||
|
updateCurrentPageTableList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function pagerSizeChange() {
|
||||||
|
pager.pageIndex = 1;
|
||||||
|
updateCurrentPageTableList();
|
||||||
|
}
|
||||||
|
|
||||||
function openInviteMemberModal() {
|
function openInviteMemberModal() {
|
||||||
inviteMemberModalCtrl.value = true;
|
inviteMemberModalCtrl.value = true;
|
||||||
}
|
}
|
||||||
@@ -309,7 +363,6 @@ function openDeleteModal(row: any) {
|
|||||||
function inviteMemberConfirmBtnClick() {
|
function inviteMemberConfirmBtnClick() {
|
||||||
inviteMemberFormRef.value.validate((isValid: boolean) => {
|
inviteMemberFormRef.value.validate((isValid: boolean) => {
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
console.log('aaaaaaaa');
|
|
||||||
inviteMember();
|
inviteMember();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -317,24 +370,24 @@ function inviteMemberConfirmBtnClick() {
|
|||||||
|
|
||||||
async function inviteMember() {
|
async function inviteMember() {
|
||||||
const params = {
|
const params = {
|
||||||
userName: inviteMemberFormData.userName,
|
groupId: organizationInfo.value.groupId,
|
||||||
role: inviteMemberFormData.role
|
username: inviteMemberFormData.userName,
|
||||||
|
roleCode: inviteMemberFormData.role
|
||||||
};
|
};
|
||||||
inviteMemberLoading.value = true;
|
inviteMemberLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await inviteOrganizationMemberApi(params);
|
const res = await inviteOrganizationMemberApi(params);
|
||||||
} catch (e) {}
|
if (res.data?.data) {
|
||||||
|
Message.success('邀请成功');
|
||||||
|
getMemberList();
|
||||||
|
} else {
|
||||||
|
Message.warning(res.data?.msg || '邀请失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.warning('接口错误,邀请失败');
|
||||||
|
}
|
||||||
inviteMemberLoading.value = false;
|
inviteMemberLoading.value = false;
|
||||||
closeInviteMemberModal();
|
closeInviteMemberModal();
|
||||||
// TODO 待接口定义好后删除下面调用逻辑
|
|
||||||
mockTableData.unshift({
|
|
||||||
userName: inviteMemberFormData.userName,
|
|
||||||
role: inviteMemberFormData.role,
|
|
||||||
joinDate: new Date().toDateString(),
|
|
||||||
id: String(pager.total++),
|
|
||||||
email: `${inviteMemberFormData.userName}@gmail.com`
|
|
||||||
});
|
|
||||||
memberTableData.value = [...mockTableData];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeInviteMemberModal() {
|
function closeInviteMemberModal() {
|
||||||
@@ -343,19 +396,23 @@ function closeInviteMemberModal() {
|
|||||||
|
|
||||||
async function deleteMember() {
|
async function deleteMember() {
|
||||||
const params = {
|
const params = {
|
||||||
id: deleteRow.value.id
|
groupId: organizationInfo.value.groupId,
|
||||||
|
username: deleteRow.value.username
|
||||||
};
|
};
|
||||||
deleteMemberLoading.value = true;
|
deleteMemberLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await deleteOrganizationMemberApi(params);
|
const res = await deleteOrganizationMemberApi(params);
|
||||||
} catch (e) {}
|
if (res.data?.data) {
|
||||||
|
Message.success('删除成功');
|
||||||
|
getMemberList();
|
||||||
|
} else {
|
||||||
|
Message.error(res.data?.msg || '删除失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Message.warning('接口错误,删除失败');
|
||||||
|
}
|
||||||
deleteMemberLoading.value = false;
|
deleteMemberLoading.value = false;
|
||||||
closeDeleteMemberModal();
|
closeDeleteMemberModal();
|
||||||
// TODO 待接口定义好后删除下面调用逻辑
|
|
||||||
const index = mockTableData.findIndex((item) => item.id === deleteRow.value.id);
|
|
||||||
mockTableData.splice(index, 1);
|
|
||||||
memberTableData.value = [...mockTableData];
|
|
||||||
pager.total--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDeleteMemberModal() {
|
function closeDeleteMemberModal() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="BatchVerify">
|
<div class="BatchVerify">
|
||||||
<div class="search-form">
|
<div class="search-form">
|
||||||
<FileUploadButton
|
<FileUploadButton
|
||||||
buttonText="导入"
|
buttonText="批量导入"
|
||||||
accept=".xml"
|
accept=".xml"
|
||||||
:onFileUpload="handleFileUpload"
|
:onFileUpload="handleFileUpload"
|
||||||
/>
|
/>
|
||||||
@@ -20,13 +20,13 @@
|
|||||||
<div class="tjsj">
|
<div class="tjsj">
|
||||||
<span style="height: 14px" class="split"></span>
|
<span style="height: 14px" class="split"></span>
|
||||||
<span>可使用:</span>
|
<span>可使用:</span>
|
||||||
<span class="green" @click="filterVerifyResult(1)">3</span>
|
<span class="green">3</span>
|
||||||
<span style="height: 14px" class="split"></span>
|
|
||||||
<span>未治理:</span>
|
|
||||||
<span class="yellow" @click="filterVerifyResult(2)">3</span>
|
|
||||||
<span style="height: 14px" class="split"></span>
|
<span style="height: 14px" class="split"></span>
|
||||||
<span>有风险:</span>
|
<span>有风险:</span>
|
||||||
<span class="red" @click="filterVerifyResult(0)">3</span>
|
<span class="red">3</span>
|
||||||
|
<span style="height: 14px" class="split"></span>
|
||||||
|
<span>未治理:</span>
|
||||||
|
<span class="yellow">3</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="left-btn">
|
<div class="left-btn">
|
||||||
<a v-if="isLogin" class="cursor-pointer" href="/static/template.xlsx" download><i class="icon icon-download-2"></i>下载excel模板</a>
|
<a v-if="isLogin" class="cursor-pointer" href="/static/template.xlsx" download><i class="icon icon-download-2"></i>下载excel模板</a>
|
||||||
@@ -72,8 +72,11 @@
|
|||||||
<template v-else-if="column.key === 'versionName'">
|
<template v-else-if="column.key === 'versionName'">
|
||||||
<a>{{ scope.row.versionName }}</a>
|
<a>{{ scope.row.versionName }}</a>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'version'">
|
<template v-else-if="column.key === 'softwareName'">
|
||||||
<a @click="gotoDetail(scope.row)">{{ scope.row.version }}</a>
|
<a @click="gotoDetail(scope.row)">{{ scope.row.softwareName }}</a>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'softwareVersion'">
|
||||||
|
<a @click="gotoDetail(scope.row)">{{ scope.row.softwareVersion }}</a>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'versionCode'">
|
<template v-else-if="column.key === 'versionCode'">
|
||||||
<a @click="gotoDetail(scope.row)">{{ scope.row.versionCode }}</a>
|
<a @click="gotoDetail(scope.row)">{{ scope.row.versionCode }}</a>
|
||||||
@@ -98,6 +101,7 @@
|
|||||||
</d-column>
|
</d-column>
|
||||||
</template>
|
</template>
|
||||||
<d-column header="操作" width="200" fixed-right="0px">
|
<d-column header="操作" width="200" fixed-right="0px">
|
||||||
|
<!--TODO:申请入口只有校验不通过的才显示-->
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<d-button
|
<d-button
|
||||||
variant="text"
|
variant="text"
|
||||||
@@ -132,7 +136,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SettingTitle from '@/components/Setting/SettingTitle/index.vue';
|
import SettingTitle from '@/components/Setting/SettingTitle/index.vue';
|
||||||
import SettingText from '@/components/Setting/SettingText/index.vue';
|
import SettingText from '@/components/Setting/SettingText/index.vue';
|
||||||
import { ref,reactive } from 'vue';
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
import { getGroupClaList, setGroupClaStatus, deleteGroupCla } from '@/api/cla';
|
import { getGroupClaList, setGroupClaStatus, deleteGroupCla } from '@/api/cla';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import { GModal } from '@/components/Setting/index';
|
import { GModal } from '@/components/Setting/index';
|
||||||
@@ -143,6 +147,7 @@ import { useAccountStore } from '@/stores/user';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import TableSetting from '@/components/TableSetting/index.vue';
|
import TableSetting from '@/components/TableSetting/index.vue';
|
||||||
import FileUploadButton from '@/components/FileUploadButton/index.vue';
|
import FileUploadButton from '@/components/FileUploadButton/index.vue';
|
||||||
|
import { releasePage } from '@/api/jyh';
|
||||||
|
|
||||||
// 处理文件上传
|
// 处理文件上传
|
||||||
const handleFileUpload = async (file) => {
|
const handleFileUpload = async (file) => {
|
||||||
@@ -156,43 +161,21 @@ const handleFileUpload = async (file) => {
|
|||||||
}, 2000); // 模拟 2 秒上传时间
|
}, 2000); // 模拟 2 秒上传时间
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const currentReusltFilter = ref(null);
|
|
||||||
const userInfo = useAccountStore();
|
const userInfo = useAccountStore();
|
||||||
const { isLogin } = storeToRefs(userInfo);
|
const { isLogin } = storeToRefs(userInfo);
|
||||||
|
|
||||||
const { namespace } = getOrgInfo();
|
const { namespace } = getOrgInfo();
|
||||||
|
|
||||||
const allTableData = ref([
|
const tableData = ref([]);
|
||||||
{result:1,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:1,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:0,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:0,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:0,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:1,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:2,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:2,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:1,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
{result:1,tjsj: '可使用', versionName:'CleanSource V8.0', name:'eslint-plugin-import',code: '05811AFV',version: '2.29.0',versionCode: '0583423820',smStatus: '同主软件(GA)',type:'依赖软件',license:'Apache License V2.0',risk:'中',useType:'软件',status:'未开始',url:'https://example17.com/security_updates_page',key:'',created:'2025-03-10 17:25:19',updated:'2025-03-10 17:25:19'},
|
|
||||||
])
|
|
||||||
|
|
||||||
const tableData = ref([...allTableData.value]);
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{ key: 'result', label: '校验结果', visible: true, filterable: true, sortable: false },
|
{ key: 'result', label: '校验结果', visible: true, filterable: true, sortable: false },
|
||||||
{ key: 'versionName', label: '选取版本火车名称', visible: true, filterable: true, sortable: false },
|
{ key: 'softwareName', label: '软件名称', visible: true, filterable: true, sortable: false },
|
||||||
{ key: 'name', label: '软件名称', visible: true, filterable: true, sortable: false },
|
{ key: 'softwareVersion', label: '软件版本', visible: true, filterable: true, sortable: false },
|
||||||
{ key: 'code', label: '软件编码', visible: true, filterable: true, sortable: false },
|
{ key: 'securityScore', label: '软件评分', visible: true, filterable: false, sortable: true },
|
||||||
{ key: 'version', label: '软件版本', visible: true, filterable: true, sortable: false },
|
{ key: 'licenseCount', label: 'License数量', visible: true, filterable: false, sortable: false },
|
||||||
{ key: 'versionCode', label: '版本编码', visible: true, filterable: true, sortable: true },
|
{ key: 'industryCategory', label: '行业类型', visible: true, filterable: true, sortable: false },
|
||||||
{ key: 'smStatus', label: '生命周期状态', visible: true, filterable: true, sortable: true },
|
{ key: 'primaryLanguage', label: '编程语言', visible: true, filterable: true, sortable: false },
|
||||||
{ key: 'type', label: '主/依赖软件类型', visible: true, filterable: false, sortable: false },
|
{ key: 'codeLines', label: '代码量', visible: true, filterable: false, sortable: false },
|
||||||
{ key: 'license', label: 'License名称', visible: true, filterable: true, sortable: false },
|
|
||||||
{ key: 'url', label: '官网漏洞披露地址', visible: true, filterable: false, sortable: false },
|
|
||||||
{ key: 'risk', label: '集成风险', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
{ key: 'useType', label: '适用类型', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
{ key: 'status', label: '状态', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
{ key: 'key', label: '键值', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
{ key: 'created', label: '创建时间', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
{ key: 'updated', label: '更新时间', visible: false, filterable: false, sortable: false }, // 隐藏字段
|
|
||||||
]);
|
]);
|
||||||
const formData = ref({ title: '',type: '', useType: '',formData:'',select: '',time1:null,name:'',versionCode:'',pulishTime:'' });
|
const formData = ref({ title: '',type: '', useType: '',formData:'',select: '',time1:null,name:'',versionCode:'',pulishTime:'' });
|
||||||
const typeOptions = reactive(['主软件', '依赖软件']);
|
const typeOptions = reactive(['主软件', '依赖软件']);
|
||||||
@@ -220,6 +203,20 @@ const openDelete = (row: any) => {
|
|||||||
deletevModels.value = true;
|
deletevModels.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getReleaseList = async() => {
|
||||||
|
const { data, error } = await releasePage({ current: pager.value.pageIndex,size: pager.value.pageSize });
|
||||||
|
if (!error && data) {
|
||||||
|
debugger
|
||||||
|
tableData.value = data.data.records;
|
||||||
|
pager.value.total = data.data.total;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async() => {
|
||||||
|
getReleaseList();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
// 定义 showColumnList 状态
|
// 定义 showColumnList 状态
|
||||||
@@ -241,6 +238,7 @@ const handleBatchImport = async() => { // 多个项目导入
|
|||||||
|
|
||||||
// 跳转
|
// 跳转
|
||||||
const gotoDetail = (row) => {
|
const gotoDetail = (row) => {
|
||||||
|
/*TODO:如果是可使用、有风险的,点击软件版本,可跳转到软件详情页面;如果是未治理的,无法跳转*/
|
||||||
// 后续请换成params,暂时params传参没传过去
|
// 后续请换成params,暂时params传参没传过去
|
||||||
router.push({
|
router.push({
|
||||||
path: 'repoDetail/' + row.version
|
path: 'repoDetail/' + row.version
|
||||||
@@ -285,18 +283,6 @@ const goMember = (row: any) => {
|
|||||||
query: { claId: row.object_id, claName: row.cla_name, group_path: namespace.value, pageType: 'edit' }
|
query: { claId: row.object_id, claName: row.cla_name, group_path: namespace.value, pageType: 'edit' }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterVerifyResult = (type) => {
|
|
||||||
if (currentReusltFilter.value === type) {
|
|
||||||
currentReusltFilter.value = null;
|
|
||||||
tableData.value = [...allTableData.value]
|
|
||||||
} else {
|
|
||||||
tableData.value = allTableData.value.filter(row => row.result === type);
|
|
||||||
currentReusltFilter.value = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const getGroupClaListData = async () => {
|
const getGroupClaListData = async () => {
|
||||||
// const params = {
|
// const params = {
|
||||||
// group_id: namespace.value,
|
// group_id: namespace.value,
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ const sendSubscribe = async () => {
|
|||||||
type: 'error'
|
type: 'error'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
Message({
|
||||||
|
message: '订阅成功!',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
emit('close');
|
emit('close');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
|
|
||||||
<!-- 漏洞详情 -->
|
<!-- 漏洞详情 -->
|
||||||
<d-drawer v-model="vulnDetailVisable" style="width: auto;">
|
<d-drawer v-model="vulnDetailVisable" style="width: auto;">
|
||||||
<VulnerabilityDetail :vulnId="currentVuln.id"></VulnerabilityDetail>
|
<VulnerabilityDetail :vulnId="currentVuln.id" :vulnInfo="currentVuln"></VulnerabilityDetail>
|
||||||
</d-drawer>
|
</d-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="vuln-detail-container">
|
<div class="vuln-detail-container">
|
||||||
<div class="vuln-title mb-2">{{ vulnDetail.id }}</div>
|
<div class="vuln-title mb-2">{{ vulnDetail.vulnId }}</div>
|
||||||
<div class="vuln-sub-title mb-3">
|
<div class="vuln-sub-title mb-3">
|
||||||
<span>{{ vulnDetail.cveId || '--' }}</span>
|
<span>{{ vulnDetail.cweId || '--' }}</span>
|
||||||
<span class="split-line"></span>
|
<span class="split-line"></span>
|
||||||
<span><span class="release-time">发布时间:</span>{{ vulnDetail.releaseTime || '--' }}</span>
|
<span><span class="release-time">发布时间:</span>{{ vulnDetail.publishDate || '--' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<Card simple class="jyh-card mb-4">
|
<Card simple class="jyh-card mb-4">
|
||||||
<div class="card-title">漏洞名称</div>
|
<div class="card-title">漏洞名称</div>
|
||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">漏洞名称</span>
|
<span class="card-key width-90">漏洞名称</span>
|
||||||
<span class="card-val">{{vulnDetail.id || '--'}}</span>
|
<span class="card-val">{{vulnDetail.vulnId || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">关联漏洞编号</span>
|
<span class="card-key width-90">关联漏洞编号</span>
|
||||||
<span class="card-val">{{vulnDetail.cnvdId || '--'}}</span>
|
<span class="card-val">{{vulnDetail.cweId || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
@@ -28,8 +28,7 @@
|
|||||||
<d-col :span="24">
|
<d-col :span="24">
|
||||||
<span class="card-key width-90">额外信息</span>
|
<span class="card-key width-90">额外信息</span>
|
||||||
<span class="card-val">
|
<span class="card-val">
|
||||||
<a v-for="link in vulnDetail.links" class="devui-link" :href="link" target="_blank" rel="noreferrer noopener">{{link}}</a>
|
<span class="card-val">{{vulnDetail.extraInfo || '--'}}</span>
|
||||||
<span v-if="!vulnDetail.links || vulnDetail.links.length === 0">--</span>
|
|
||||||
</span>
|
</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
@@ -37,8 +36,7 @@
|
|||||||
<d-col :span="24">
|
<d-col :span="24">
|
||||||
<span class="card-key width-90">补丁链接</span>
|
<span class="card-key width-90">补丁链接</span>
|
||||||
<span class="card-val">
|
<span class="card-val">
|
||||||
<a v-for="link in vulnDetail.links2" class="devui-link" :href="link" target="_blank" rel="noreferrer noopener">{{link}}</a>
|
<span class="card-val">{{vulnDetail.patchLink || '--'}}</span>
|
||||||
<span v-if="!vulnDetail.links || vulnDetail.links.length === 0">--</span>
|
|
||||||
</span>
|
</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
@@ -48,11 +46,11 @@
|
|||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">严重性</span>
|
<span class="card-key width-90">严重性</span>
|
||||||
<span class="card-val">{{vulnDetail.id || '--'}}</span>
|
<span class="card-val">{{vulnDetail.severity || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">分值</span>
|
<span class="card-key width-90">分值</span>
|
||||||
<span class="card-val">{{vulnDetail.code || '--'}}</span>
|
<span class="card-val">{{vulnDetail.cvssScore || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -61,21 +59,21 @@
|
|||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">攻击向量</span>
|
<span class="card-key width-90">攻击向量</span>
|
||||||
<span class="card-val">{{vulnDetail.id || '--'}}</span>
|
<span class="card-val">{{vulnDetail.attackVector || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">攻击复杂度</span>
|
<span class="card-key width-90">攻击复杂度</span>
|
||||||
<span class="card-val">{{vulnDetail.complexity || '--'}}</span>
|
<span class="card-val">{{vulnDetail.attackComplexity || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">用户交互</span>
|
<span class="card-key width-90">用户交互</span>
|
||||||
<span class="card-val">{{vulnDetail.compName || '--'}}</span>
|
<span class="card-val">{{vulnDetail.userInteraction || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">需要特殊权限</span>
|
<span class="card-key width-90">需要特殊权限</span>
|
||||||
<span class="card-val">{{vulnDetail.cnvdId || '--'}}</span>
|
<span class="card-val">{{vulnDetail.privilegesRequired || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -113,7 +111,7 @@
|
|||||||
<d-row class="mb-3">
|
<d-row class="mb-3">
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">补丁版本</span>
|
<span class="card-key width-90">补丁版本</span>
|
||||||
<span class="card-val">{{vulnDetail.id || '--'}}</span>
|
<span class="card-val">{{vulnDetail.fixVersion || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
<d-col :span="12">
|
<d-col :span="12">
|
||||||
<span class="card-key width-90">修复兼容性</span>
|
<span class="card-key width-90">修复兼容性</span>
|
||||||
@@ -123,7 +121,7 @@
|
|||||||
<d-row>
|
<d-row>
|
||||||
<d-col :span="24">
|
<d-col :span="24">
|
||||||
<span class="card-key width-90">修复建议</span>
|
<span class="card-key width-90">修复建议</span>
|
||||||
<span class="card-val">{{vulnDetail.description || '--'}}</span>
|
<span class="card-val">{{vulnDetail.fixIssue || '--'}}</span>
|
||||||
</d-col>
|
</d-col>
|
||||||
</d-row>
|
</d-row>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -134,22 +132,27 @@
|
|||||||
import { getVulnDetail } from '@/api/repo';
|
import { getVulnDetail } from '@/api/repo';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
const propsData = defineProps(['repoId', 'vulnId']);
|
const propsData = defineProps(['repoId', 'vulnId', 'vulnInfo']);
|
||||||
const vulnDetail = ref({
|
const vulnDetail = ref({
|
||||||
id: 'HWPSIRT-2022-29348',
|
vulnId: 'HWPSIRT-2022-29348',
|
||||||
cveId: 'CVE-2013-0293',
|
cweId: 'CVE-2013-0293',
|
||||||
cnvdId: 'CNVD-201105-215',
|
cnvdId: 'CNVD-201105-215',
|
||||||
name: '',
|
name: '',
|
||||||
code: '',
|
code: '',
|
||||||
description: '华为开发者社区致力于打造华为开发者专属的官方技术交流平台,帮助开发者探索开发实践、交流心得经验、获悉业界动态、解决开发问题。汇聚华为云社区“华为云”领域博客、问答、视频等精彩内容,形成开发者和技术爱好者交流与分享主阵地。',
|
description: '攻击者通过特制的PUT请求执行任意SQL命令,可能导致数据库内容被操控。',
|
||||||
links: ['/home'],
|
extraInfo: '腾讯云丁安全实验室发现并报告该漏洞。',
|
||||||
links2: ['/home'],
|
fixIssue: '使用参数化查询或预编译语句,避免SQL注入。',
|
||||||
vector: '',
|
attackVector: '',
|
||||||
complexity: '',
|
attackComplexity: '',
|
||||||
interactive: '',
|
userInteraction: '',
|
||||||
releaseTime: '2018-07-31',
|
publishDate: '2018-07-31',
|
||||||
compName: 'mplayer',
|
compName: 'mplayer',
|
||||||
version: '1.4',
|
fixVersion: '1.4',
|
||||||
|
"privilegesRequired": "None",
|
||||||
|
"exploitabilityScore": 9.8,
|
||||||
|
"impactScore": 10.0,
|
||||||
|
"cvssScore": 9.9,
|
||||||
|
"severity": "Critical",
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryVulnDetail = async () => {
|
const queryVulnDetail = async () => {
|
||||||
@@ -157,6 +160,7 @@ const queryVulnDetail = async () => {
|
|||||||
vulnDetail.value = data;
|
vulnDetail.value = data;
|
||||||
};
|
};
|
||||||
// queryVulnDetail();
|
// queryVulnDetail();
|
||||||
|
// vulnDetail.value = propsData.vulnInfo;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<span>订阅漏洞预警通知</span>
|
<span>订阅漏洞预警通知</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<SubscriptionModal @close="colseSubscription" :softwareData="softwareData"></SubscriptionModal>
|
<SubscriptionModal @close="colseSubscription" :softwareData="{id: softwareId}"></SubscriptionModal>
|
||||||
</d-modal>
|
</d-modal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +73,7 @@ import SubscriptionModal from '@/views/Jyh/Version/Detail/SubscriptionModal.vue'
|
|||||||
import { releaseInfo } from '@/api/jyh';
|
import { releaseInfo } from '@/api/jyh';
|
||||||
|
|
||||||
const selectTab = ref('bbxx');
|
const selectTab = ref('bbxx');
|
||||||
|
const softwareId = ref();
|
||||||
// 删除弹窗
|
// 删除弹窗
|
||||||
const item = ref('');
|
const item = ref('');
|
||||||
const deleteModal = ref();
|
const deleteModal = ref();
|
||||||
@@ -96,6 +96,7 @@ const getReleaseInfo = async(versionId) => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const versionId = route.params.versionId; // 获取路由参数 versionId
|
const versionId = route.params.versionId; // 获取路由参数 versionId
|
||||||
|
softwareId.value = versionId;
|
||||||
if (versionId) {
|
if (versionId) {
|
||||||
getReleaseInfo(versionId); // 调用接口获取数据
|
getReleaseInfo(versionId); // 调用接口获取数据
|
||||||
}
|
}
|
||||||
@@ -194,13 +195,6 @@ const signCla = (row: any) => {
|
|||||||
router.push('/cla/' + row.object_id);
|
router.push('/cla/' + row.object_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const softwareData = ref({
|
|
||||||
name: 'vue',
|
|
||||||
version: '3.5.13',
|
|
||||||
lifecycle: '选中型',
|
|
||||||
risk: '低风险',
|
|
||||||
});
|
|
||||||
|
|
||||||
const subscribeModalVisable = ref(false);
|
const subscribeModalVisable = ref(false);
|
||||||
const openSubscription = () => {
|
const openSubscription = () => {
|
||||||
subscribeModalVisable.value = true;
|
subscribeModalVisable.value = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user