File size: 4,051 Bytes
89ce340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<template>
  <div class="slide-toolbar">
    <div class="remark">
      <textarea
        :value="remark"
        placeholder="点击输入演讲者备注"
        @input="$event => handleInputMark($event)"
      ></textarea>
    </div>
    <div class="toolbar">
      <ButtonGroup class="row">
        <Button style="flex: 1;" @click="createSlide()"><IconPlus class="icon" /> 新幻灯片</Button>
        <Button style="flex: 1;" @click="copyAndPasteSlide()"><IconCopy class="icon" /> 复制</Button>
        <Button style="flex: 1;" @click="deleteSlide()"><IconDelete class="icon" /> 删除</Button>
      </ButtonGroup>
      <ButtonGroup class="row">
        <Button style="flex: 1;" @click="insertTextElement()"><IconFontSize class="icon" /> 文字</Button>
        <Button style="flex: 1;">
          <FileInput @change="files => insertImageElement(files)">
            <IconPicture class="icon" />图片
          </FileInput>
        </Button>
        <Button style="flex: 1;" @click="insertShapeElement('square')"><IconSquare class="icon" /> 矩形</Button>
        <Button style="flex: 1;" @click="insertShapeElement('round')"><IconRound class="icon" /> 圆形</Button>
      </ButtonGroup>
    </div>

    <MobileThumbnails />
  </div>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import useSlideHandler from '@/hooks/useSlideHandler'
import useCreateElement from '@/hooks/useCreateElement'
import { getImageDataURL } from '@/utils/image'
import type { ShapePoolItem } from '@/configs/shapes'

import MobileThumbnails from '../MobileThumbnails.vue'
import FileInput from '@/components/FileInput.vue'
import Button from '@/components/Button.vue'
import ButtonGroup from '@/components/ButtonGroup.vue'

const slidesStore = useSlidesStore()
const { viewportRatio, currentSlide, viewportSize } = storeToRefs(slidesStore)

const { createSlide, copyAndPasteSlide, deleteSlide, } = useSlideHandler()
const { createTextElement, createImageElement, createShapeElement } = useCreateElement()

const insertTextElement = () => {
  const width = 400
  const height = 56

  createTextElement({
    left: (viewportSize.value - width) / 2,
    top: (viewportSize.value * viewportRatio.value - height) / 2,
    width,
    height,
  }, { content: '<p>新添加文本</p>' })
}

const insertImageElement = (files: FileList) => {
  if (!files || !files[0]) return
  getImageDataURL(files[0]).then(dataURL => createImageElement(dataURL))
}

const insertShapeElement = (type: 'square' | 'round') => {
  const square: ShapePoolItem = {
    viewBox: [200, 200],
    path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z',
  }
  const round: ShapePoolItem = {
    viewBox: [200, 200],
    path: 'M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z',
  }
  const shape = { square, round }

  const size = 200

  createShapeElement({
    left: (viewportSize.value - size) / 2,
    top: (viewportSize.value * viewportRatio.value - size) / 2,
    width: size,
    height: size,
  }, shape[type])
}

const remark = computed(() => currentSlide.value?.remark || '')

const handleInputMark = (e: Event) => {
  const value = (e.target as HTMLTextAreaElement).value
  slidesStore.updateSlide({ remark: value })
}
</script>

<style lang="scss" scoped>
.slide-toolbar {
  height: 230px;
  background-color: #fff;
  box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  position: relative;
  z-index: 2;
}
.remark {
  position: relative;
  flex: 1;
  border-bottom: 1px solid $borderColor;
  line-height: 1.5;

  textarea {
    width: 100%;
    height: 100%;
    overflow-y: auto;
    resize: none;
    border: 0;
    outline: 0;
    padding: 8px 10px;
    font-size: 12px;
    box-sizing: border-box;

    @include absolute-0();
  }
}
.toolbar {
  height: 90px;
  border-bottom: 1px solid $borderColor;
  padding: 10px;
}
.row {
  width: 100%;
  display: flex;
  align-items: center;
  margin-bottom: 5px;

  .icon {
    margin-right: 3px;
  }
}
</style>