feat: 矩阵抽离组件

- 矩阵的三个组件抽离,由 MatrixQuestion 内部管理
This commit is contained in:
Huangzhe
2025-03-22 12:18:06 +08:00
parent 7727ea5b2b
commit d647cc3a02
10 changed files with 268 additions and 829 deletions

View File

@@ -1,86 +1,25 @@
<template>
<el-table :data="rows" style="width: 100%">
<el-table-column :width="tableWidth">
<template #header></template>
<template #default="{ row /*, column, $index*/ }">
<div style="position: relative">
<el-text truncated :style="{ width: `${tableWidth}px` }">
<contenteditable v-model="row.option" :active="active" @blur="emitValue" />
</el-text>
<van-popover
v-model="row.showAction"
placement="left-end"
trigger="click"
:actions="popoverActions"
@select="handleActionSelect($event, row, 'row')"
>
<template #reference>
<div v-if="active" class="icon">
<Io5EllipsisVerticalSharp />
</div>
</template>
</van-popover>
</div>
</template>
</el-table-column>
<el-table-column v-for="(col, colIndex) in cols" :key="col.option" :width="tableWidth">
<template #header>
<div style="position: relative">
<el-text truncated :style="{ width: `${tableWidth}px` }">
<contenteditable v-model="col.option" :active="active" @blur="emitValue" />
</el-text>
<van-popover
v-model="col.showAction"
placement="left-end"
trigger="click"
:actions="popoverActions"
@select="handleActionSelect($event, col, 'col')"
>
<template #reference>
<div v-if="active" class="icon">
<Io5EllipsisVerticalSharp />
</div>
</template>
</van-popover>
</div>
</template>
<template #default="{ /*row, column, */ $index: rowIndex }">
<input
type="checkbox"
:name="`R${rowIndex + 1}`"
:checked="isOptionChecked(rowIndex, colIndex)"
@change="handleMatrixCheckboxChange(rowIndex, colIndex)"
/>
</template>
</el-table-column>
</el-table>
<input
type="checkbox"
:name="`R${rowIndex + 1}`"
:checked="isOptionChecked(rowIndex, colIndex)"
@change="handleMatrixCheckboxChange(rowIndex, colIndex)"
/>
</template>
<script setup lang="ts">
import { Io5EllipsisVerticalSharp } from 'vue-icons-plus/io5';
// 接受获取到的 col row 的索引参数
const rowIndex = defineModel<number>('rowIndex', { required: true, default: 0 });
const colIndex = defineModel<number>('colIndex', { required: true, default: 0 });
// 添加激活 action 的选项
interface _questionOptionType extends questionOptionType {
showAction?: boolean;
}
// 记录行和列的索引
const rowRecord = defineModel<number[][]>('rowRecord', { required: false, default: () => [] });
// const matrixAnswer = defineModel<{ [key: string]: 1 }>('matrixAnswer', { required: false, default: () => ({}) });
// 检查 rowRecord 是否存在
// console.log(`rowRecord:`, rowRecord.value);
const tableWidth = defineModel<number>('tableWidth', { required: false, default: 110 });
const active = defineModel<boolean>('active', { required: false, default: true });
/* const isPreview = */ defineModel<boolean>('isPreview', { required: false, default: false });
const rows = defineModel<_questionOptionType[]>('rows', { required: false, default: () => [] });
const cols = defineModel<_questionOptionType[]>('cols', { required: false, default: () => [] });
const element = defineModel<question>('element', {
required: false,
default: () => {
/**/
}
});
const emit = defineEmits(['update:matrixAnswer', 'update:rowRecord', 'update:element']);
// 判断是否选中
@@ -95,45 +34,6 @@ const isOptionChecked = (rowIndex: number, colIndex: number): boolean => {
return rowRecord.value[rowIndex].includes(colIndex);
};
addShowActionOption();
/**
* 给行或者列选项 添加 showAction 选项
*/
function addShowActionOption() {
rows.value.forEach((row) => {
row.showAction = true;
});
cols.value.forEach((col) => {
col.showAction = true;
});
}
// 增加 popover 的 actions
const popoverActions = [
{
text: '删除'
}
// {
// text: '置底'
// }
];
// popover 的事件
function handleActionSelect(action: { text: string }, axi: any, type: 'row' | 'col') {
const data = type === 'row' ? rows : cols;
const index = data.value.indexOf(axi);
if (index < 0) return;
switch (action.text) {
case '删除':
data.value.splice(index, 1);
break;
case '置底':
data.value.push(data.value.splice(index, 1)[0]);
break;
}
}
// 当 matrix radio 选中时,更新 rowRecord 和 matrixAnswer
function handleMatrixCheckboxChange(row: number, col: number) {
// 获取 colIndexArray
@@ -158,49 +58,3 @@ const emitValue = (/* val: unknown */) => {
emit('update:element', element.value);
};
</script>
<style scoped lang="scss">
@import '@/assets/css/theme';
.matrix-table {
text-align: left;
}
.matrix-checkbox {
position: relative;
overflow: hidden;
width: 15px;
height: 15px;
border: 1px solid #f4f4f4;
border-radius: 4px;
outline: none;
cursor: pointer;
appearance: none; /* 去除默认样式 */
//transition: border-color 0.3s;
}
.matrix-checkbox:checked {
border-color: transparent; /* 选中时边框颜色 */
}
.matrix-checkbox:checked::before {
content: '\e728';
position: absolute;
width: 15px;
height: 15px;
background-color: $theme-color; /* 选中颜色 */
color: #fff;
line-height: 15px;
text-align: center;
}
.icon {
position: absolute;
top: 3px;
right: -10px;
& > svg {
height: 15px;
}
}
</style>