赛事证书发放
This commit is contained in:
parent
06cbee57a7
commit
0b8390e64c
@ -89,11 +89,11 @@ export const eventscoreIssuecertificatePost = (data) => {
|
||||
|
||||
/**
|
||||
* 查看证书
|
||||
* @param {number} id - 报名人员ID (EventRegistrationPerson的Id) (路径参数)
|
||||
* @param {number} id - 报名人员ID (EventRegistrationPerson的Id)
|
||||
* @returns {Promise<Object>} 返回证书详情
|
||||
*/
|
||||
export const eventscoreGetCertificateDetailGet = (id) => {
|
||||
return http.get(`/EventScore/GetCertificateDetail/${id}`);
|
||||
return http.post('/eventscore/getcertificatedetail', { id });
|
||||
};
|
||||
|
||||
/**
|
||||
@ -139,4 +139,22 @@ export const eventscoreDeleteDelete = (data) => {
|
||||
*/
|
||||
export const eventscoreSetstatusPatch = (data) => {
|
||||
return http.patch('/eventscore/setstatus', data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 查看证书 URL
|
||||
* @param {Object} params - 查询参数
|
||||
* @param {number} params.id - 报名人员ID
|
||||
*/
|
||||
export const eventscoreViewcertificateGet = (params) => {
|
||||
return http.get('/eventscore/viewcertificate', { params });
|
||||
};
|
||||
|
||||
/**
|
||||
* 发放积分
|
||||
* @param {Object} data - 发放积分参数
|
||||
* @param {number} data.eventId - 赛事ID
|
||||
*/
|
||||
export const eventscoreIssuepointsPost = (data) => {
|
||||
return http.post('/eventscore/issuePoints', data);
|
||||
};
|
||||
@ -128,35 +128,61 @@
|
||||
<el-radio-button value="教练">教练</el-radio-button>
|
||||
<el-radio-button value="领队">领队</el-radio-button>
|
||||
</el-radio-group>
|
||||
<ProTable v-if="user == '运动员'" ref="tableuu" :request-api="eventscorePageathletePost"
|
||||
:columns="columnsScore" :pagination="true" :tool-button="false" :initParam="initParam" toolButton
|
||||
preserve-expanded-content @selectionChange="selection">
|
||||
<template #tools>
|
||||
<el-button v-auth="'event:add'" type="primary" :loading="importingScore" @click="inScore"> 导入成绩 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="downloadTemplate"> 下载模板 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="exportCertificate"> 导出证书 </el-button>
|
||||
</template>
|
||||
<template #index="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
<template #action="scope">
|
||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<div v-if="user == '运动员'" class="score-certificate-container">
|
||||
<div class="project-group-panel">
|
||||
<div class="panel-header">项目-组别列表</div>
|
||||
<el-tree
|
||||
ref="projectGroupTreeRef"
|
||||
:data="projectGroupTreeData"
|
||||
:props="treeProps"
|
||||
node-key="nodeKey"
|
||||
highlight-current
|
||||
:expand-on-click-node="false"
|
||||
@node-click="handleTreeNodeClick"
|
||||
default-expand-all
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span class="tree-node-label">
|
||||
{{ node.label }}
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
|
||||
<div class="athlete-list-panel">
|
||||
<ProTable ref="tableuu" :request-api="eventscorePageathletePost"
|
||||
:columns="columnsScore" :pagination="true" :tool-button="false" :initParam="scoreQueryParam" toolButton
|
||||
preserve-expanded-content @selectionChange="selection">
|
||||
<template #tools>
|
||||
<el-button v-auth="'event:add'" type="primary" :loading="importingScore" @click="inScore"> 导入成绩 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="downloadTemplate"> 下载模板 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="exportCertificate"> 导出证书 </el-button>
|
||||
<el-button v-auth="'event:add'" type="success" :loading="issuingPoints" @click="handleIssuePoints"> 发放积分 </el-button>
|
||||
</template>
|
||||
<template #index="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
<template #action="scope">
|
||||
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProTable v-if="user == '教练'" ref="tableCoach" :request-api="eventscorePagecoachleaderPost"
|
||||
:columns="columnsCoach" :pagination="true" :tool-button="false" :initParam="initParamCoach" toolButton
|
||||
preserve-expanded-content @selectionChange="selection">
|
||||
<template #tools>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||
</template>
|
||||
<template #index="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
<template #action="scope">
|
||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
||||
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
@ -165,16 +191,34 @@
|
||||
:columns="columnsLeader" :pagination="true" :tool-button="false" :initParam="initParamLeader" toolButton
|
||||
preserve-expanded-content @selectionChange="selection">
|
||||
<template #tools>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="allSure"> 发放证书 </el-button>
|
||||
<el-button v-auth="'event:add'" type="primary" @click="openIssueCertificateDialog"> 发放证书 </el-button>
|
||||
</template>
|
||||
<template #index="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
<template #action="scope">
|
||||
<el-button size="small" text type="primary" @click="onLookBook(scope.row.id)"> 查看证书
|
||||
<el-button size="small" text type="primary" @click="viewCertificate(scope.row.id)"> 查看证书
|
||||
</el-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<!-- 发放证书对话框 -->
|
||||
<el-dialog v-model="certificateDialogVisible" title="发放证书" width="500px">
|
||||
<el-form :model="certificateForm" label-width="120px">
|
||||
<el-form-item label="选择证书模板">
|
||||
<el-select v-model="selectedTemplateId" placeholder="请选择证书模板" style="width: 100%;">
|
||||
<el-option label="默认模板" :value="undefined" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="已选人数">
|
||||
<span>{{ selectListIds.value?.length || 0 }} 人</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="certificateDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="issuingCertificate" @click="issueCertificate">确定发放</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
@ -247,7 +291,7 @@ import { Check, View, Download, Rank, Warning } from '@element-plus/icons-vue';
|
||||
import { eventDetailGet } from '/@/api/match/event';
|
||||
import { eventarrangementListGet, eventarrangementPut, eventarrangementExportPost, eventarrangementPreviewPost } from '/@/api/match/eventarrangement';
|
||||
import { eventregistrationPagePost, eventregistrationBatchauditPost, eventregistrationMaterialurlsPost } from '/@/api/match/eventregistration';
|
||||
import { eventscorePageathletePost, eventscorePagecoachleaderPost,eventscoreImportscorePost, eventscoreDownloadtemplateGet, eventscoreExportcertificatePost } from '/@/api/match/eventscore';
|
||||
import { eventscorePageathletePost, eventscorePagecoachleaderPost,eventscoreImportscorePost, eventscoreDownloadtemplateGet, eventscoreExportcertificatePost, eventscoreIssuecertificatePost, eventscoreGetCertificateDetailGet, eventscoreIssuepointsPost } from '/@/api/match/eventscore';
|
||||
import Step1BasicInfo from './Steps/Step1BasicInfo.vue';
|
||||
import Step2Units from './Steps/Step2Units.vue';
|
||||
import Step3ProjectConfig from './Steps/Step3ProjectConfig.vue';
|
||||
@ -261,6 +305,7 @@ const isShowDialog = ref(false);
|
||||
const activeName = ref('first')
|
||||
const eventlist = ref([]);
|
||||
const importingScore = ref(false);
|
||||
const issuingPoints = ref(false);
|
||||
const arrangementContainerRef = ref(null);
|
||||
let sortableInstance = null;
|
||||
|
||||
@ -272,6 +317,12 @@ const scoreFileInputRef = ref(null);
|
||||
const tableuu = ref();
|
||||
const tableCoach = ref();
|
||||
const tableLeader = ref();
|
||||
|
||||
// 证书发放相关
|
||||
const certificateDialogVisible = ref(false);
|
||||
const selectedTemplateId = ref();
|
||||
const issuingCertificate = ref(false);
|
||||
const certificateForm = ref({});
|
||||
// 表单数据(响应式对象)
|
||||
const formData = ref({
|
||||
// 步骤1:基本信息
|
||||
@ -353,6 +404,9 @@ const openDialog = async (id) => {
|
||||
};
|
||||
formData.value.feeConfig = { ...formData.value.feeConfig, ...(d.feeConfig ?? {}) };
|
||||
console.log('formData.value', formData.value);
|
||||
|
||||
projectGroupTreeData.value = buildProjectGroupTree(d.projects)
|
||||
resetSelectedGroup()
|
||||
}
|
||||
|
||||
const res2 = await eventarrangementListGet(id);
|
||||
@ -541,6 +595,13 @@ const selection = (e) => {
|
||||
//预览赛事编排
|
||||
const previewArrangement = async () => {
|
||||
try {
|
||||
// 验证场地数
|
||||
const validation = validateVenueCount();
|
||||
if (!validation.valid) {
|
||||
ElMessage.warning(validation.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await eventarrangementPreviewPost(initParam.value.id);
|
||||
if (res.succeeded) {
|
||||
previewData.value = res.data || [];
|
||||
@ -610,6 +671,13 @@ const downloadByBlob = (blob, filename = '赛事编排.xlsx') => {
|
||||
|
||||
const getArr = async () => {
|
||||
try {
|
||||
// 验证场地数
|
||||
const validation = validateVenueCount();
|
||||
if (!validation.valid) {
|
||||
ElMessage.warning(validation.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const { succeeded, data, errors } = await eventarrangementExportPost(initParam.value.id);
|
||||
if (!succeeded) {
|
||||
ElMessage.error(errors || '导出失败');
|
||||
@ -659,7 +727,8 @@ const columnsScore = ref([
|
||||
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
||||
{ prop: 'name', label: '姓名', width: '120px', },
|
||||
{ prop: 'score', label: '成绩', width: '120px', },
|
||||
{ prop: 'rank', label: '名次', },
|
||||
{ prop: 'unitName', label: '单位', width: '180px', },
|
||||
{ prop: 'rankText', label: '名次', width: '120px', },
|
||||
{
|
||||
prop: 'gender',
|
||||
label: '性别',
|
||||
@ -671,9 +740,67 @@ const columnsScore = ref([
|
||||
{ label: '女', value: 1 },
|
||||
],
|
||||
},
|
||||
{ prop: 'unitName', label: '单位', },
|
||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||
])
|
||||
|
||||
const projectGroupTreeRef = ref()
|
||||
const projectGroupTreeData = ref([])
|
||||
const treeProps = {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
const selectedProjectGroup = ref(null)
|
||||
|
||||
const scoreQueryParam = computed(() => ({
|
||||
refresh: initParam.value.refresh,
|
||||
eventId: initParam.value.eventId,
|
||||
projectId: selectedProjectGroup.value?.type === 'project' ? selectedProjectGroup.value?.id : undefined,
|
||||
groupName: selectedProjectGroup.value?.type === 'group' ? selectedProjectGroup.value?.groupName : undefined
|
||||
}))
|
||||
|
||||
const buildProjectGroupTree = (projects) => {
|
||||
const treeData = []
|
||||
if (!projects || !Array.isArray(projects)) return treeData
|
||||
|
||||
projects.forEach(project => {
|
||||
const projectNode = {
|
||||
nodeKey: `project-${project.id}`,
|
||||
id: project.id,
|
||||
type: 'project',
|
||||
label: project.name,
|
||||
children: []
|
||||
}
|
||||
|
||||
if (project.groups && Array.isArray(project.groups)) {
|
||||
project.groups.forEach((group, idx) => {
|
||||
projectNode.children.push({
|
||||
nodeKey: `group-${project.id}-${idx}`,
|
||||
id: project.id,
|
||||
type: 'group',
|
||||
groupName: group.groupName,
|
||||
label: group.groupName
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
treeData.push(projectNode)
|
||||
})
|
||||
|
||||
return treeData
|
||||
}
|
||||
|
||||
const handleTreeNodeClick = (data) => {
|
||||
selectedProjectGroup.value = data
|
||||
initParam.value.refresh = !initParam.value.refresh
|
||||
}
|
||||
|
||||
const resetSelectedGroup = () => {
|
||||
selectedProjectGroup.value = null
|
||||
if (projectGroupTreeRef.value) {
|
||||
projectGroupTreeRef.value.setCurrentKey(null)
|
||||
}
|
||||
initParam.value.refresh = !initParam.value.refresh
|
||||
}
|
||||
const columnsCoach = ref([
|
||||
{ prop: 'index', label: '序号', align: 'center', type: 'selection' },
|
||||
{ prop: 'name', label: '教练姓名', width: '120px', search: { el: 'input' }, },
|
||||
@ -689,8 +816,8 @@ const columnsCoach = ref([
|
||||
{ label: '女', value: 1 },
|
||||
],
|
||||
},
|
||||
{ prop: 'idCard', label: '身份证号', },
|
||||
{ prop: 'phone', label: '联系电话', search: { el: 'input' }, },
|
||||
{ prop: 'idCardNumber', label: '身份证号', },
|
||||
{ prop: 'mobile', label: '联系电话', search: { el: 'input' }, },
|
||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||
])
|
||||
const columnsLeader = ref([
|
||||
@ -708,8 +835,8 @@ const columnsLeader = ref([
|
||||
{ label: '女', value: 1 },
|
||||
],
|
||||
},
|
||||
{ prop: 'idCard', label: '身份证号', },
|
||||
{ prop: 'phone', label: '联系电话', search: { el: 'input' }, },
|
||||
{ prop: 'idCardNumber', label: '身份证号', },
|
||||
{ prop: 'mobile', label: '联系电话', search: { el: 'input' }, },
|
||||
{ prop: 'action', label: '操作', align: 'center', width: 140, fixed: 'right' }
|
||||
])
|
||||
|
||||
@ -810,6 +937,99 @@ const exportCertificate = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 打开发放证书对话框
|
||||
const openIssueCertificateDialog = () => {
|
||||
if (!selectListIds.value || selectListIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要发放证书的人员');
|
||||
return;
|
||||
}
|
||||
selectedTemplateId.value = undefined;
|
||||
certificateDialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 发放证书
|
||||
const issueCertificate = async () => {
|
||||
if (!selectListIds.value || selectListIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要发放证书的人员');
|
||||
return;
|
||||
}
|
||||
|
||||
issuingCertificate.value = true;
|
||||
try {
|
||||
const res = await eventscoreIssuecertificatePost({
|
||||
personIds: selectListIds.value,
|
||||
eventId: initParam.value.eventId,
|
||||
templateId: selectedTemplateId.value
|
||||
});
|
||||
if (res?.succeeded) {
|
||||
ElMessage.success(`证书发放成功!成功 ${res.data?.successCount || 0} 条,失败 ${res.data?.failCount || 0} 条`);
|
||||
certificateDialogVisible.value = false;
|
||||
refreshScoreTable();
|
||||
} else {
|
||||
ElMessage.error(res?.errors || '证书发放失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发放证书失败:', error);
|
||||
ElMessage.error('发放证书失败');
|
||||
} finally {
|
||||
issuingCertificate.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 发放积分
|
||||
const handleIssuePoints = async () => {
|
||||
try {
|
||||
ElMessageBox.confirm('确定要发放积分吗?系统将根据赛事积分规则为符合条件的用户发放积分。', '发放积分确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
issuingPoints.value = true;
|
||||
try {
|
||||
const res = await eventscoreIssuepointsPost({
|
||||
eventId: initParam.value.eventId
|
||||
});
|
||||
if (res?.succeeded) {
|
||||
ElMessage.success(res.data?.Message || '积分发放成功');
|
||||
refreshScoreTable();
|
||||
} else {
|
||||
ElMessage.error(res?.errors || '积分发放失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('发放积分失败:', error);
|
||||
ElMessage.error(error?.message || '积分发放失败');
|
||||
} finally {
|
||||
issuingPoints.value = false;
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('发放积分确认失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 查看证书
|
||||
const viewCertificate = async (id) => {
|
||||
try {
|
||||
const { succeeded, data, errors } = await eventscoreGetCertificateDetailGet(id);
|
||||
if (succeeded) {
|
||||
if (data?.url) {
|
||||
window.open(data.url, '_blank');
|
||||
} else if (data?.Url) {
|
||||
window.open(data.Url, '_blank');
|
||||
} else {
|
||||
ElMessage.warning('该人员暂无证书');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(errors || '查看证书失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查看证书失败:', error);
|
||||
ElMessage.error('查看证书失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 获取组别单位显示
|
||||
const getGroupUnit = (projectType) => {
|
||||
return projectType && projectType.includes('团队') ? '组' : '人';
|
||||
@ -907,16 +1127,34 @@ const calculateProjectDuration = (item) => {
|
||||
return { totalMinutes, totalSeconds, error };
|
||||
};
|
||||
|
||||
// 监听 eventlist 变化,实时计算总时长
|
||||
// 验证场地数是否有效
|
||||
const validateVenueCount = () => {
|
||||
if (!eventlist.value || eventlist.value.length === 0) {
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
const invalidProjects = [];
|
||||
eventlist.value.forEach((item) => {
|
||||
if (item.venueCount === 0 || !item.venueCount) {
|
||||
invalidProjects.push(item.projectName);
|
||||
}
|
||||
});
|
||||
|
||||
if (invalidProjects.length > 0) {
|
||||
const message = invalidProjects.map(name => `${name}: 场地数不能为0`).join('\n');
|
||||
return { valid: false, message };
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
};
|
||||
|
||||
// 监听 eventlist 变化,实时计算总时长(不显示错误提示)
|
||||
watch(
|
||||
eventlist,
|
||||
(newList) => {
|
||||
if (newList && newList.length > 0) {
|
||||
newList.forEach((item) => {
|
||||
const result = calculateProjectDuration(item);
|
||||
if (result.error) {
|
||||
ElMessage.warning(`${item.projectName}: ${result.error}`);
|
||||
}
|
||||
item.totalDurationMinutes = result.totalMinutes;
|
||||
});
|
||||
}
|
||||
@ -1240,4 +1478,105 @@ defineExpose({
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
/* 成绩与证书页面样式 */
|
||||
.score-certificate-container {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.project-group-panel {
|
||||
flex: 0 0 280px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
background: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
padding: 12px 16px;
|
||||
background: #409eff;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.project-group-panel :deep(.el-tree) {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.project-group-panel :deep(.el-tree-node__content) {
|
||||
height: 36px;
|
||||
padding-left: 16px !important;
|
||||
}
|
||||
|
||||
.project-group-panel :deep(.el-tree-node__content:hover) {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.project-group-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
|
||||
background: #ecf5ff;
|
||||
color: #409eff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tree-node-label {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.athlete-list-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.athlete-list-panel :deep(.el-card__body) {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.score-certificate-container {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.project-group-panel {
|
||||
flex: none;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.athlete-list-panel {
|
||||
flex: 1;
|
||||
min-height: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.score-certificate-container {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.project-group-panel {
|
||||
flex: none;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user