Skip to content

Commit

Permalink
feat:分组管理增加跨页全选功能 --story=118110616
Browse files Browse the repository at this point in the history
  • Loading branch information
q15971095971 committed Jun 29, 2024
1 parent 4ec62ac commit fe3cbc0
Show file tree
Hide file tree
Showing 7 changed files with 443 additions and 43 deletions.
172 changes: 172 additions & 0 deletions bcs-services/bcs-bscp/ui/src/components/across-check.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<template>
<div class="check">
<bk-checkbox
:checked="isChecked"
:indeterminate="indeterminate"
:class="{
'across-all-check': localValue === CheckType.AcrossChecked,
'half-indeterminate': localValue === CheckType.HalfAcrossChecked,
}"
:disabled="disabled"
:true-label="localValue === CheckType.AcrossChecked ? CheckType.AcrossChecked : CheckType.Checked"
:false-label="setCheckBoxStatus"
@change="handleCheckChange">
</bk-checkbox>
<bk-popover
ref="popover"
theme="light"
trigger="click"
placement="bottom"
:arrow="false"
:offset="{ mainAxis: 10, crossAxis: 30 }"
:disabled="disabled"
@after-show="isDropDownShow = true"
@after-hidden="isDropDownShow = false">
<angle-down
v-if="arrowShow"
:class="['check-icon', { 'icon-angle-up': isDropDownShow }, { disabled: disabled }]" />
<template #content>
<ul class="dropdown-ul">
<li
class="dropdown-li"
v-for="item in checkTypeList"
:key="item.id"
:class="{ active: localValue === item.id }"
@click="handleCheckAll(item.id)">
{{ item.name }}
</li>
</ul>
</template>
</bk-popover>
</div>
</template>
<script lang="ts" setup>
import { computed, ref, toRefs, watch } from 'vue';
import CheckType from '../../types/across-checked';
import { AngleDown } from 'bkui-vue/lib/icon';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const props = defineProps({
value: {
type: Number,
default: CheckType.Uncheck,
},
disabled: {
type: Boolean,
default: false,
},
arrowShow: {
type: Boolean,
default: true,
},
});
const emits = defineEmits(['change']);
const popover = ref<any>(null);
const isDropDownShow = ref(false);
const { value } = toRefs(props);
const localValue = ref(value.value);
const checkTypeList = ref([
{
id: CheckType.Checked,
name: t('全选'),
},
{
id: CheckType.AcrossChecked,
name: t('跨页全选'),
},
]);
// 跨页半选和跨页全选
// const allChecked = computed(() => [CheckType.HalfAcrossChecked, CheckType.AcrossChecked].includes(localValue.value));
// 当前页半选和跨页半选
const indeterminate = computed(() => [CheckType.HalfChecked, CheckType.HalfAcrossChecked].includes(localValue.value));
// 当前页全选和跨页全选
const isChecked = computed(() => [CheckType.Checked, CheckType.AcrossChecked].includes(localValue.value));
const setCheckBoxStatus = computed(() => {
const status = value.value;
switch (status) {
case CheckType.HalfAcrossChecked:
return CheckType.HalfAcrossChecked; // 跨页半选
case CheckType.HalfChecked:
return CheckType.HalfChecked; // 当前页半选
case CheckType.Checked:
case CheckType.AcrossChecked:
default:
return CheckType.Uncheck;
}
});
watch(value, (newV) => {
localValue.value = newV;
});
const handleCheckChange = (id: number) => {
localValue.value = id;
emits('change', id);
};
const handleCheckAll = (id: number) => {
handleCheckChange(id);
popover.value.hide();
};
</script>
<style lang="scss" scoped>
.check {
text-align: left;
.across-all-check {
:deep(.bk-checkbox-input) {
background-color: #fff;
&::after {
content: '';
border-color: #3a84ff;
}
}
}
.half-indeterminate {
:deep(.bk-checkbox-input) {
background-color: #fff;
&::after {
content: '';
background-color: #3a84ff;
}
}
}
&-icon {
margin-left: 5px;
font-size: 20px;
cursor: pointer;
color: #63656e;
&.disabled {
display: none;
// color: #c4c6cc;
}
&.icon-angle-up {
transform: rotate(180deg);
}
}
}
.dropdown-ul {
margin: -12px;
font-size: 12px;
.dropdown-li {
padding: 0 16px;
min-width: 68px;
font-size: 12px;
text-align: center;
line-height: 32px;
cursor: pointer;
&:hover {
background: #e5efff;
color: #3a84ff;
}
&.active {
background: #e5efff;
color: #3a84ff;
}
}
}
</style>
70 changes: 70 additions & 0 deletions bcs-services/bcs-bscp/ui/src/components/across-checkbox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<span class="custom-checkbox-wrap">
<input type="checkbox" :checked="checked" :disabled="disabled" @change="handleChangeNew" class="custom-checkbox" />
</span>
</template>

<script lang="ts" setup>
const props = defineProps({
checked: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
handleChange: {
type: Function,
default: () => {},
},
});
const handleChangeNew = () => {
props.handleChange();
};
</script>

<style lang="scss" scoped>
.custom-checkbox-wrap {
position: relative;
display: inline-block;
width: 16px;
height: 16px;
vertical-align: sub;
.custom-checkbox {
position: relative;
appearance: none;
width: 100%;
height: 100%;
border: 1px solid #979ba5;
border-radius: 2px;
cursor: pointer;
transition: all 0.1s;
&:checked {
background-color: #3a84ff;
border-color: #3a84ff;
// color: red;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 8px;
border: 2px solid #fff;
border-top: 0;
border-left: 0;
transform: translate(-50%, -60%) scaleY(1) rotate(45deg);
transform-origin: center;
}
}
&:disabled {
border-color: #dcdee5;
background-color: #fafbfd;
cursor: not-allowed;
}
}
}
</style>
6 changes: 6 additions & 0 deletions bcs-services/bcs-bscp/ui/src/i18n/en-us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,4 +944,10 @@ export default {
'组件类型 / 版本分布': 'Component type / Version distribution',
下钻: 'Drill down',
总和: 'Total',

// 跨页全选
跨页全选: 'AcrossChecked',
已选择: 'Selected',
选择所有: 'Choose all',
取消选择所有数据: 'Cancel all data'
};
6 changes: 6 additions & 0 deletions bcs-services/bcs-bscp/ui/src/i18n/zh-cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,4 +951,10 @@ export default {
'组件类型 / 版本分布': '组件类型 / 版本分布',
下钻: '下钻',
总和: '总和',

// 跨页全选
跨页全选: '跨页全选',
已选择: '已选择',
选择所有:'选择所有',
取消选择所有数据: '取消选择所有数据'
};
98 changes: 98 additions & 0 deletions bcs-services/bcs-bscp/ui/src/utils/hooks/use-table-across-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { h, Ref, ref } from 'vue';
import AcrossCheck from '../../components/across-check.vue';
import CheckType from '../../../types/across-checked';

export interface IAcrossCheckConfig {
tableData: Ref<any[]>;
curPageData: Ref<any[]>;
rowKey?: string[];
arrowShow?: Ref<boolean>;
}
// 表格跨页全选功能
export default function useTableAcrossCheck({
tableData,
curPageData,
rowKey = ['name', 'id'],
arrowShow,
}: IAcrossCheckConfig) {
const selectType = ref(CheckType.Uncheck);
const selections = ref<any[]>([]);
const renderSelection = () => {
return h(AcrossCheck, {
value: selectType.value,
disabled: !tableData.value.length,
arrowShow: !arrowShow?.value,
onChange: handleSelectTypeChange,
});
};
// 表头全选事件
const handleSelectTypeChange = (value: number) => {
switch (value) {
case CheckType.Uncheck:
handleClearSelection();
break;
case CheckType.Checked:
handleSelectCurrentPage();
break;
case CheckType.AcrossChecked:
handleSelectionAll();
break;
}
};
// 当前页全选
const handleSelectCurrentPage = () => {
selectType.value = CheckType.Checked;
selections.value = [...curPageData.value];
};
// 跨页全选
const handleSelectionAll = () => {
selectType.value = CheckType.AcrossChecked;
selections.value = [...tableData.value];
};
// 清空全选
const handleClearSelection = () => {
selectType.value = CheckType.Uncheck;
selections.value = [];
};
// 表格行勾选后重置状态
const handleSetSelectType = () => {
if (selections.value.length === 0) {
selectType.value = CheckType.Uncheck;
} else if (
selections.value.length < curPageData.value.length &&
[CheckType.Checked, CheckType.Uncheck].includes(selectType.value)
) {
// 从当前页全选 -> 当前页半选
selectType.value = CheckType.HalfChecked;
} else if (
selections.value.length === curPageData.value.length &&
selectType.value !== CheckType.HalfAcrossChecked
) {
selectType.value = CheckType.Checked;
} else if (selections.value.length < tableData.value.length && selectType.value === CheckType.AcrossChecked) {
// 从跨页全选 -> 跨页半选
selectType.value = CheckType.HalfAcrossChecked;
} else if (selections.value.length === tableData.value.length) {
selectType.value = CheckType.AcrossChecked;
}
};
// 当前行选中事件
const handleRowCheckChange = (value: boolean, row: any) => {
const index = selections.value.findIndex((item) => rowKey.every((key) => item[key] === row[key]));
if (value && index === -1) {
selections.value.push(row);
} else if (!value && index > -1) {
selections.value.splice(index, 1);
}
handleSetSelectType();
};

return {
selectType, // 选择状态
selections, // 选中的数据
renderSelection, // 渲染全选框组件
handleRowCheckChange, // 行的全选框操作
handleSelectionAll, // 全选操作
handleClearSelection, // 清空全选
};
}
Loading

0 comments on commit fe3cbc0

Please sign in to comment.