189 lines
5.2 KiB
Vue
189 lines
5.2 KiB
Vue
<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="radio"
|
|
:name="`R${rowIndex + 1}`"
|
|
:checked="isOptionChecked(rowIndex, colIndex)"
|
|
@change="handleMatrixRadioChange(rowIndex, colIndex)"
|
|
/>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { Io5EllipsisVerticalSharp } from 'vue-icons-plus/io5';
|
|
|
|
// 添加激活 action 的选项
|
|
interface _questionOptionType extends questionOptionType {
|
|
showAction?: boolean;
|
|
}
|
|
|
|
const rowRecord = defineModel<number[]>('rowRecord', { required: false, default: () => [] });
|
|
/* const isPreview = */ defineModel<boolean>('isPreview', { required: false, default: false });
|
|
const tableWidth = defineModel<number>('tableWidth', { required: false, default: 110 });
|
|
const rows = defineModel<_questionOptionType[]>('rows', { required: false, default: () => [] });
|
|
const cols = defineModel<_questionOptionType[]>('cols', { required: false, default: () => [] });
|
|
const active = defineModel<boolean>('active', { required: false, default: true });
|
|
const element = defineModel<question>('element', {
|
|
required: false,
|
|
default: () => {
|
|
/**/
|
|
}
|
|
});
|
|
const emit = defineEmits(['update:matrixAnswer', 'update:rowRecord', 'update:element']);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// 判断是否选中
|
|
const isOptionChecked = (rowIndex: number, colIndex: number): boolean => {
|
|
// console.log(`rowIndex: ${rowIndex}, colIndex: ${colIndex}`);
|
|
// console.log(`rowRecord.value[rowIndex] === colIndex`, rowRecord.value[rowIndex] === colIndex);
|
|
|
|
return rowRecord.value[rowIndex] === colIndex;
|
|
// const key = `R${rowIndex + 1}_C${colIndex + 1}`;
|
|
// return !!matrixAnswer.value?.[key];
|
|
};
|
|
|
|
// 当 matrix radio 选中时,更新 rowRecord 和 matrixAnswer
|
|
function handleMatrixRadioChange(row: number, col: number) {
|
|
rowRecord.value[row] = col;
|
|
// matrixAnswer.value = {};
|
|
// rowRecord.value.forEach((row, col) => {
|
|
// matrixAnswer.value[`${col + 1}_${row}`] = 1;
|
|
// });
|
|
}
|
|
|
|
const emitValue = () => {
|
|
emit('update:element', element.value);
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '@/assets/css/theme';
|
|
|
|
.matrix-table {
|
|
text-align: left;
|
|
}
|
|
|
|
.matrix-radio {
|
|
position: relative;
|
|
overflow: hidden;
|
|
width: 15px;
|
|
height: 15px;
|
|
border: 1px solid #f4f4f4;
|
|
border-radius: 50%;
|
|
outline: none;
|
|
cursor: pointer;
|
|
appearance: none; /* 去除默认样式 */
|
|
//transition: border-color 0.3s;
|
|
}
|
|
|
|
.matrix-radio:checked {
|
|
border-color: transparent; /* 选中时边框颜色 */
|
|
}
|
|
|
|
.matrix-radio: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>
|