123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- <template>
- <div class="module-wrapper">
- <div
- class="horizontal-line top"
- :style="{ backgroundColor: bgColor }"
- @mousedown="dragStart($event, 'ns-resize', 'top')"
- ></div>
- <div
- class="vertical-line left"
- :style="{ backgroundColor: bgColor }"
- @mousedown="dragStart($event, 'ew-resize', 'left')"
- ></div>
- <div class="module" draggable="false">
- <div class="module-top">
- <span class="title">{{ componentNameList[type] }}</span>
- <div class="module-icon">
- <span><SvgIcon icon-class="copy" size="10" /></span>
- <span :class="[{ active: getCurSettingId() === id }]" @click="showSetting">
- <SvgIcon icon-class="setup" size="10" />
- </span>
- <span @click="deleteComponent"><SvgIcon icon-class="delete" size="10" /></span>
- </div>
- </div>
- <div class="module-content">
- <slot name="content"></slot>
- </div>
- </div>
- <div
- class="vertical-line right"
- :style="{ backgroundColor: bgColor }"
- @mousedown="dragStart($event, 'ew-resize', 'right')"
- ></div>
- <div
- class="horizontal-line bottom"
- :style="{ backgroundColor: bgColor }"
- @mousedown="dragStart($event, 'ns-resize', 'bottom')"
- ></div>
- </div>
- </template>
- <script>
- import { componentNameList } from '@/views/book/courseware/data/bookType.js';
- export default {
- name: 'ModuleBase',
- inject: ['id', 'showSetting', 'getCurSettingId', 'deleteComponent', 'handleComponentMove'],
- props: {
- type: {
- type: String,
- default: 'text',
- },
- },
- data() {
- return {
- componentNameList,
- drag: {
- dragging: false,
- startX: 0,
- startY: 0,
- type: '',
- },
- bgColor: '#ebebeb',
- };
- },
- created() {
- document.addEventListener('mousemove', this.dragMove);
- document.addEventListener('mouseup', this.dragEnd);
- },
- beforeDestroy() {
- document.removeEventListener('mousemove', this.dragMove);
- document.removeEventListener('mouseup', this.dragEnd);
- },
- methods: {
- /**
- * 拖拽开始
- * @param {MouseEvent} event
- * @param {string} cursor
- * @param {string} type
- */
- dragStart(event, cursor, type) {
- const { clientX, clientY } = event;
- this.drag = {
- dragging: true,
- startX: clientX,
- startY: clientY,
- type,
- };
- this.bgColor = '#272727';
- document.body.style.cursor = cursor;
- },
- /**
- * 拖拽移动
- * @param {MouseEvent} event
- */
- dragMove(event) {
- if (!this.drag.dragging) return;
- const { clientX, clientY } = event;
- const { startX, startY, type } = this.drag;
- const offsetX = clientX - startX;
- const offsetY = clientY - startY;
- this.handleComponentMove({ type, offsetX, offsetY });
- this.drag.startX = clientX;
- this.drag.startY = clientY;
- },
- /**
- * 拖拽结束
- */
- dragEnd() {
- this.drag = {
- dragging: false,
- startX: 0,
- startY: 0,
- type: '',
- };
- this.bgColor = '#ebebeb';
- document.body.style.cursor = 'auto';
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .module-wrapper {
- display: grid;
- grid-template:
- 'top top top' 1px
- 'left module right' auto
- 'bottom bottom bottom' 1px
- / 1px auto 1px;
- .horizontal-line {
- width: 100%;
- cursor: ns-resize;
- &.top {
- grid-area: top;
- }
- &.bottom {
- grid-area: bottom;
- }
- }
- .vertical-line {
- cursor: ew-resize;
- &.left {
- grid-area: left;
- }
- &.right {
- grid-area: right;
- }
- }
- .module {
- grid-area: module;
- padding: 8px;
- overflow: auto;
- background-color: #fff;
- &-top {
- display: flex;
- justify-content: space-between;
- margin-bottom: 3px;
- .title {
- font-size: 12px;
- color: $label-color;
- }
- }
- &-icon {
- display: flex;
- column-gap: 8px;
- span {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 16px;
- height: 16px;
- cursor: pointer;
- background-color: #fff;
- border-radius: 20px;
- &.active {
- background-color: #c9c9c9;
- }
- .svg-icon.setup {
- color: #000;
- }
- .svg-icon.delete {
- color: #ed4646;
- }
- }
- }
- &-content {
- position: relative;
- padding: 8px;
- background-color: #fff;
- .option-list {
- .rich-wrapper {
- flex: 1;
- min-height: 32px;
- :deep .rich-text {
- &.mce-content-body {
- padding-top: 4px;
- }
- &:not(.mce-edit-focus) {
- p {
- margin: 0;
- }
- }
- &.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
- top: 6px;
- }
- }
- }
- }
- }
- }
- }
- </style>
|