index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <template>
  2. <div class="go-canvas-setting">
  3. <n-form inline :label-width="45" size="small" label-placement="left">
  4. <n-form-item label="宽度">
  5. <!-- 尺寸选择 -->
  6. <n-input-number
  7. size="small"
  8. v-model:value="canvasConfig.width"
  9. :disabled="editCanvas.lockScale"
  10. :validator="validator"
  11. @update:value="changeSizeHandle"
  12. ></n-input-number>
  13. </n-form-item>
  14. <n-form-item label="高度">
  15. <n-input-number
  16. size="small"
  17. v-model:value="canvasConfig.height"
  18. :disabled="editCanvas.lockScale"
  19. :validator="validator"
  20. @update:value="changeSizeHandle"
  21. ></n-input-number>
  22. </n-form-item>
  23. </n-form>
  24. <n-card class="upload-box">
  25. <n-upload
  26. v-model:file-list="uploadFileListRef"
  27. :show-file-list="false"
  28. :customRequest="customRequest"
  29. :onBeforeUpload="beforeUploadHandle"
  30. >
  31. <n-upload-dragger>
  32. <img v-if="canvasConfig.backgroundImage" class="upload-show" :src="canvasConfig.backgroundImage" alt="背景" />
  33. <div class="upload-img" v-show="!canvasConfig.backgroundImage">
  34. <img src="@/assets/images/canvas/noImage.png" />
  35. <n-text class="upload-desc" depth="3">
  36. 背景图需小于 {{ backgroundImageSize }}M ,格式为 png/jpg/gif 的文件
  37. </n-text>
  38. </div>
  39. </n-upload-dragger>
  40. </n-upload>
  41. </n-card>
  42. <n-space vertical :size="12">
  43. <n-space>
  44. <n-text>背景颜色</n-text>
  45. <div class="picker-height">
  46. <n-color-picker
  47. v-if="!switchSelectColorLoading"
  48. size="small"
  49. style="width: 250px"
  50. v-model:value="canvasConfig.background"
  51. :showPreview="true"
  52. :swatches="swatchesColors"
  53. ></n-color-picker>
  54. </div>
  55. </n-space>
  56. <n-space>
  57. <n-text>应用类型</n-text>
  58. <n-select
  59. size="small"
  60. style="width: 250px"
  61. v-model:value="selectColorValue"
  62. :disabled="!canvasConfig.backgroundImage"
  63. :options="selectColorOptions"
  64. @update:value="selectColorValueHandle"
  65. />
  66. </n-space>
  67. <n-space>
  68. <n-text>背景控制</n-text>
  69. <n-button class="clear-btn" size="small" :disabled="!canvasConfig.backgroundImage" @click="clearImage">
  70. 清除背景
  71. </n-button>
  72. <n-button class="clear-btn" size="small" :disabled="!canvasConfig.background" @click="clearColor">
  73. 清除颜色
  74. </n-button>
  75. </n-space>
  76. <n-space>
  77. <n-text>适配方式</n-text>
  78. <n-button-group>
  79. <n-button
  80. v-for="item in previewTypeList"
  81. :key="item.key"
  82. :type="canvasConfig.previewScaleType === item.key ? 'primary' : 'tertiary'"
  83. ghost
  84. size="small"
  85. @click="selectPreviewType(item.key)"
  86. >
  87. <n-tooltip :show-arrow="false" trigger="hover">
  88. <template #trigger>
  89. <n-icon class="select-preview-icon" size="18">
  90. <component :is="item.icon"></component>
  91. </n-icon>
  92. </template>
  93. {{ item.desc }}
  94. </n-tooltip>
  95. </n-button>
  96. </n-button-group>
  97. </n-space>
  98. </n-space>
  99. <!-- 滤镜 -->
  100. <styles-setting :isCanvas="true" :chartStyles="canvasConfig"></styles-setting>
  101. <n-divider style="margin: 10px 0"></n-divider>
  102. <!-- 主题选择和全局配置 -->
  103. <n-tabs class="tabs-box" size="small" type="segment">
  104. <n-tab-pane
  105. v-for="item in globalTabList"
  106. :key="item.key"
  107. :name="item.key"
  108. size="small"
  109. display-directive="show:lazy"
  110. >
  111. <template #tab>
  112. <n-space>
  113. <span>{{ item.title }}</span>
  114. <n-icon size="16" class="icon-position">
  115. <component :is="item.icon"></component>
  116. </n-icon>
  117. </n-space>
  118. </template>
  119. <component :is="item.render"></component>
  120. </n-tab-pane>
  121. </n-tabs>
  122. </div>
  123. </template>
  124. <script setup lang="ts">
  125. import { ref, nextTick, watch } from 'vue'
  126. import { backgroundImageSize } from '@/settings/designSetting'
  127. import { FileTypeEnum } from '@/enums/fileTypeEnum'
  128. import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  129. import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
  130. import { useSystemStore } from '@/store/modules/systemStore/systemStore'
  131. import { StylesSetting } from '@/components/Pages/ChartItemSetting'
  132. import { UploadCustomRequestOptions } from 'naive-ui'
  133. import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils'
  134. import { PreviewScaleEnum } from '@/enums/styleEnum'
  135. import { ResultEnum } from '@/enums/httpEnum'
  136. import { icon } from '@/plugins'
  137. import { uploadFile} from '@/api/path'
  138. const { ColorPaletteIcon } = icon.ionicons5
  139. const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
  140. const chartEditStore = useChartEditStore()
  141. const systemStore = useSystemStore()
  142. const canvasConfig = chartEditStore.getEditCanvasConfig
  143. const editCanvas = chartEditStore.getEditCanvas
  144. const uploadFileListRef = ref()
  145. const switchSelectColorLoading = ref(false)
  146. const selectColorValue = ref(0)
  147. const ChartThemeColor = loadAsyncComponent(() => import('./components/ChartThemeColor/index.vue'))
  148. // 默认应用类型
  149. const selectColorOptions = [
  150. {
  151. label: '应用颜色',
  152. value: 0
  153. },
  154. {
  155. label: '应用背景',
  156. value: 1
  157. }
  158. ]
  159. // 默认展示颜色列表
  160. const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa']
  161. const globalTabList = [
  162. {
  163. key: 'ChartTheme',
  164. title: '主题颜色',
  165. icon: ColorPaletteIcon,
  166. render: ChartThemeColor
  167. }
  168. ]
  169. const previewTypeList = [
  170. {
  171. key: PreviewScaleEnum.FIT,
  172. title: '自适应',
  173. icon: ScaleIcon,
  174. desc: '自适应比例展示,页面会有留白'
  175. },
  176. {
  177. key: PreviewScaleEnum.SCROLL_Y,
  178. title: 'Y轴滚动',
  179. icon: FitToWidthIcon,
  180. desc: 'X轴铺满,Y轴自适应滚动'
  181. },
  182. {
  183. key: PreviewScaleEnum.SCROLL_X,
  184. title: 'X轴滚动',
  185. icon: FitToHeightIcon,
  186. desc: 'Y轴铺满,X轴自适应滚动'
  187. },
  188. {
  189. key: PreviewScaleEnum.FULL,
  190. title: '铺满',
  191. icon: FitToScreenIcon,
  192. desc: '强行拉伸画面,填充所有视图'
  193. }
  194. ]
  195. watch(
  196. () => canvasConfig.selectColor,
  197. newValue => {
  198. selectColorValue.value = newValue ? 0 : 1
  199. },
  200. {
  201. immediate: true
  202. }
  203. )
  204. // 画布尺寸规则
  205. const validator = (x: number) => x > 50
  206. // 修改尺寸
  207. const changeSizeHandle = () => {
  208. chartEditStore.computedScale()
  209. }
  210. // 上传图片前置处理
  211. //@ts-ignore
  212. const beforeUploadHandle = async ({ file }) => {
  213. uploadFileListRef.value = []
  214. const type = file.file.type
  215. const size = file.file.size
  216. if (size > 1024 * 1024 * backgroundImageSize) {
  217. window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
  218. return false
  219. }
  220. if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
  221. window['$message'].warning('文件格式不符合,请重新上传!')
  222. return false
  223. }
  224. return true
  225. }
  226. // 应用颜色
  227. const selectColorValueHandle = (value: number) => {
  228. canvasConfig.selectColor = value == 0
  229. }
  230. // 清除背景
  231. const clearImage = () => {
  232. chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, undefined)
  233. chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, true)
  234. }
  235. // 启用/关闭 颜色(强制更新)
  236. const switchSelectColorHandle = () => {
  237. switchSelectColorLoading.value = true
  238. setTimeout(() => {
  239. switchSelectColorLoading.value = false
  240. })
  241. }
  242. // 清除颜色
  243. const clearColor = () => {
  244. chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND, undefined)
  245. if (canvasConfig.backgroundImage) {
  246. chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
  247. }
  248. switchSelectColorHandle()
  249. }
  250. // 自定义上传操作
  251. const customRequest = (options: UploadCustomRequestOptions) => {
  252. const { file } = options
  253. nextTick(async () => {
  254. if (file.file) {
  255. // 修改名称
  256. const newNameFile = new File(
  257. [file.file],
  258. `${fetchRouteParamsLocation()}_index_background.png`,
  259. { type: file.file.type }
  260. )
  261. let uploadParams = new FormData()
  262. uploadParams.append('object', newNameFile)
  263. const uploadRes = await uploadFile(uploadParams) as unknown as MyResponseType
  264. if(uploadRes.code === ResultEnum.SUCCESS) {
  265. chartEditStore.setEditCanvasConfig(
  266. EditCanvasConfigEnum.BACKGROUND_IMAGE,
  267. `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}`
  268. )
  269. chartEditStore.setEditCanvasConfig(
  270. EditCanvasConfigEnum.SELECT_COLOR,
  271. false
  272. )
  273. return
  274. }
  275. window['$message'].error('添加图片失败,请稍后重试!')
  276. } else {
  277. window['$message'].error('添加图片失败,请稍后重试!')
  278. }
  279. })
  280. }
  281. // 选择适配方式
  282. const selectPreviewType = (key: PreviewScaleEnum) => {
  283. chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.PREVIEW_SCALE_TYPE, key)
  284. }
  285. </script>
  286. <style lang="scss" scoped>
  287. $uploadWidth: 326px;
  288. $uploadHeight: 193px;
  289. @include go(canvas-setting) {
  290. padding-top: 20px;
  291. .upload-box {
  292. cursor: pointer;
  293. margin-bottom: 20px;
  294. @include deep() {
  295. .n-card__content {
  296. padding: 0;
  297. overflow: hidden;
  298. }
  299. .n-upload-dragger {
  300. padding: 5px;
  301. width: $uploadWidth;
  302. }
  303. }
  304. .upload-show {
  305. width: -webkit-fill-available;
  306. height: $uploadHeight;
  307. border-radius: 5px;
  308. }
  309. .upload-img {
  310. display: flex;
  311. flex-direction: column;
  312. align-items: center;
  313. img {
  314. height: 150px;
  315. }
  316. .upload-desc {
  317. padding: 10px 0;
  318. }
  319. }
  320. }
  321. .icon-position {
  322. padding-top: 2px;
  323. }
  324. .picker-height {
  325. min-height: 35px;
  326. }
  327. .clear-btn {
  328. padding-left: 2.25em;
  329. padding-right: 2.25em;
  330. }
  331. .select-preview-icon {
  332. padding-right: .68em;
  333. padding-left: .68em;
  334. }
  335. .tabs-box {
  336. margin-top: 20px;
  337. }
  338. }
  339. </style>