ExportPPTX.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <div class="export-pptx-dialog">
  3. <div class="configs" :style="{ width: lang.lang === 'en' ? '475px' : '350px' }">
  4. <div class="row">
  5. <div class="title">{{ lang.ssExpRange }}</div>
  6. <RadioGroup
  7. class="config-item"
  8. v-model:value="rangeType"
  9. >
  10. <RadioButton style="width: 33.33%;" value="all">{{ lang.ssShowAll }}</RadioButton>
  11. <RadioButton style="width: 33.33%;" value="current">{{ lang.ssCurPage }}</RadioButton>
  12. <RadioButton style="width: 33.33%;" value="custom">{{ lang.ssCustom }}</RadioButton>
  13. </RadioGroup>
  14. </div>
  15. <div class="row" v-if="rangeType === 'custom'">
  16. <div class="title" :data-range="`(${range[0]} ~ ${range[1]})`">{{ lang.ssCustomRange }}</div>
  17. <Slider
  18. class="config-item"
  19. range
  20. :min="1"
  21. :max="slides.length"
  22. :step="1"
  23. v-model:value="range"
  24. />
  25. </div>
  26. <div class="row">
  27. <div class="title">{{ lang.ssIgnoreMedia }}</div>
  28. <div class="config-item">
  29. <Switch v-model:value="ignoreMedia" v-tooltip="lang.ssIgnoreMediaTip" />
  30. </div>
  31. </div>
  32. <div class="row">
  33. <div class="title">{{ lang.ssMastOver }}</div>
  34. <div class="config-item">
  35. <Switch v-model:value="masterOverwrite" />
  36. </div>
  37. </div>
  38. <div class="tip" v-if="!ignoreMedia">
  39. {{ lang.ssPptxTip }}
  40. </div>
  41. </div>
  42. <div class="btns">
  43. <Button class="btn export" type="primary" @click="exportPPTX(selectedSlides, masterOverwrite, ignoreMedia)">{{ lang.ssExportPptx }}</Button>
  44. <Button class="btn close" @click="emit('close')">{{ lang.ssClose }}</Button>
  45. </div>
  46. <FullscreenSpin :loading="exporting" :tip="lang.ssExporting" />
  47. </div>
  48. </template>
  49. <script lang="ts" setup>
  50. import { computed, ref } from 'vue'
  51. import { storeToRefs } from 'pinia'
  52. import { useSlidesStore } from '@/store'
  53. import useExport from '@/hooks/useExport'
  54. import { lang } from '@/main'
  55. import FullscreenSpin from '@/components/FullscreenSpin.vue'
  56. import Switch from '@/components/Switch.vue'
  57. import Slider from '@/components/Slider.vue'
  58. import Button from '@/components/Button.vue'
  59. import RadioButton from '@/components/RadioButton.vue'
  60. import RadioGroup from '@/components/RadioGroup.vue'
  61. const emit = defineEmits<{
  62. (event: 'close'): void
  63. }>()
  64. const { slides, currentSlide } = storeToRefs(useSlidesStore())
  65. const { exportPPTX, exporting } = useExport()
  66. const rangeType = ref<'all' | 'current' | 'custom'>('all')
  67. const range = ref<[number, number]>([1, slides.value.length])
  68. const masterOverwrite = ref(true)
  69. const ignoreMedia = ref(true)
  70. const selectedSlides = computed(() => {
  71. if (rangeType.value === 'all') return slides.value
  72. if (rangeType.value === 'current') return [currentSlide.value]
  73. return slides.value.filter((item, index) => {
  74. const [min, max] = range.value
  75. return index >= min - 1 && index <= max - 1
  76. })
  77. })
  78. </script>
  79. <style lang="scss" scoped>
  80. .export-pptx-dialog {
  81. height: 100%;
  82. display: flex;
  83. justify-content: center;
  84. align-items: center;
  85. flex-direction: column;
  86. position: relative;
  87. overflow: hidden;
  88. }
  89. .configs {
  90. width: 350px;
  91. height: calc(100% - 80px);
  92. display: flex;
  93. flex-direction: column;
  94. justify-content: center;
  95. .row {
  96. display: flex;
  97. justify-content: center;
  98. align-items: center;
  99. margin-bottom: 25px;
  100. }
  101. .title {
  102. width: 110px;
  103. position: relative;
  104. &::after {
  105. content: attr(data-range);
  106. position: absolute;
  107. top: 20px;
  108. left: 0;
  109. }
  110. }
  111. .config-item {
  112. flex: 1;
  113. }
  114. .tip {
  115. font-size: 12px;
  116. color: #aaa;
  117. line-height: 1.8;
  118. margin-top: 10px;
  119. }
  120. }
  121. .btns {
  122. width: 300px;
  123. height: 80px;
  124. display: flex;
  125. justify-content: center;
  126. align-items: center;
  127. .export {
  128. flex: 1;
  129. }
  130. .close {
  131. width: 100px;
  132. margin-left: 10px;
  133. }
  134. }
  135. </style>