| <template> |
| <div class="table-generator"> |
| <div class="title"> |
| <div class="lef">表格 {{endCell.length ? `${endCell[0]} x ${endCell[1]}` : ''}}</div> |
| <div class="right" @click="isCustom = !isCustom">{{ isCustom ? '返回' : '自定义'}}</div> |
| </div> |
| <table |
| @mouseleave="endCell = []" |
| @click="handleClickTable()" |
| v-if="!isCustom" |
| > |
| <tbody> |
| <tr v-for="row in 10" :key="row"> |
| <td |
| @mouseenter="endCell = [row, col]" |
| v-for="col in 10" :key="col" |
| > |
| <div |
| class="cell" |
| :class="{ 'active': endCell.length && row <= endCell[0] && col <= endCell[1] }" |
| ></div> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <div class="custom" v-else> |
| <div class="row"> |
| <div class="label" style="width: 25%;">行数:</div> |
| <NumberInput |
| :min="1" |
| :max="20" |
| v-model:value="customRow" |
| style="width: 75%;" |
| /> |
| </div> |
| <div class="row"> |
| <div class="label" style="width: 25%;">列数:</div> |
| <NumberInput |
| :min="1" |
| :max="20" |
| v-model:value="customCol" |
| style="width: 75%;" |
| /> |
| </div> |
| <div class="btns"> |
| <Button class="btn" @click="close()">取消</Button> |
| <Button class="btn" type="primary" @click="insertCustomTable()">确认</Button> |
| </div> |
| </div> |
| </div> |
| </template> |
| |
| <script lang="ts" setup> |
| import { ref } from 'vue' |
| import message from '@/utils/message' |
| import Button from '@/components/Button.vue' |
| import NumberInput from '@/components/NumberInput.vue' |
| |
| interface InsertData { |
| row: number |
| col: number |
| } |
| |
| const emit = defineEmits<{ |
| (event: 'insert', payload: InsertData): void |
| (event: 'close'): void |
| }>() |
| |
| const endCell = ref<number[]>([]) |
| const customRow = ref(3) |
| const customCol = ref(3) |
| const isCustom = ref(false) |
| |
| const handleClickTable = () => { |
| if (!endCell.value.length) return |
| const [row, col] = endCell.value |
| emit('insert', { row, col }) |
| } |
| |
| const insertCustomTable = () => { |
| if (customRow.value < 1 || customRow.value > 20) return message.warning('行数/列数必须在0~20之间!') |
| if (customCol.value < 1 || customCol.value > 20) return message.warning('行数/列数必须在0~20之间!') |
| emit('insert', { row: customRow.value, col: customCol.value }) |
| isCustom.value = false |
| } |
| |
| const close = () => { |
| emit('close') |
| isCustom.value = false |
| } |
| </script> |
| |
| <style lang="scss" scoped> |
| .table-generator { |
| width: 100%; |
| margin-top: -10px; |
| } |
| .title { |
| height: 28px; |
| line-height: 28px; |
| background-color: $lightGray; |
| margin: 0 -10px 10px -10px; |
| padding: 0 14px; |
| font-size: 12px; |
| display: flex; |
| justify-content: space-between; |
| border-top-left-radius: $borderRadius; |
| border-top-right-radius: $borderRadius; |
| user-select: none; |
| |
| .right { |
| cursor: pointer; |
| |
| &:hover { |
| color: $themeColor; |
| } |
| } |
| } |
| table { |
| border-collapse: separate; |
| } |
| td { |
| width: 23px; |
| height: 23px; |
| line-height: 23px; |
| border: 2px solid #fff; |
| background-color: #f7f7f7; |
| } |
| .cell { |
| width: 100%; |
| height: 100%; |
| border: 1px solid #dcdcdc; |
| |
| &.active { |
| background-color: rgba($color: $themeColor, $alpha: .1); |
| border-color: $themeColor; |
| } |
| } |
| |
| .custom { |
| width: 230px; |
| |
| .row { |
| display: flex; |
| align-items: center; |
| |
| & + .row { |
| margin-top: 10px; |
| } |
| } |
| } |
| |
| .btns { |
| margin-top: 10px; |
| text-align: right; |
| |
| .btn { |
| margin-left: 10px; |
| } |
| } |
| </style> |