diff --git a/package.json b/package.json index 0793cc9..96260bd 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "v-viewer": "^3.0.13", "viewerjs": "^1.11.6", "vue": "^3.4.29", + "vue-cropper": "^1.1.4", "vue-toastification": "^2.0.0-rc.5", "vue3-colorpicker": "^2.3.0" }, diff --git a/src/layout/adder/CustomAdder.tsx b/src/layout/adder/CustomAdder.tsx index 1929961..2427580 100644 --- a/src/layout/adder/CustomAdder.tsx +++ b/src/layout/adder/CustomAdder.tsx @@ -11,6 +11,7 @@ import type { Block } from '../layout.types' import { ColorPicker } from 'vue3-colorpicker' import 'vue3-colorpicker/style.css' import { globalToast } from '@/main' +import UploadAndCut from '@/utils/UploadAndCut' import { AddToToken } from './AdderPage' addIcons(MdUpload, MdImage, MdCheck) @@ -77,7 +78,7 @@ const TypeSelector = defineComponent({
{ ctx.emit('update:value', 1) @@ -106,13 +107,17 @@ const TypeSelector = defineComponent({ 文字
-
- + {/* { ctx.emit('update:icon', e) }} - > + > */} + { + ctx.emit('update:icon', e) + + }}>
自定义
diff --git a/src/utils/NativeColorPicker.tsx b/src/utils/NativeColorPicker.tsx new file mode 100644 index 0000000..9c113ca --- /dev/null +++ b/src/utils/NativeColorPicker.tsx @@ -0,0 +1,109 @@ +import clsx from "clsx"; +import { computed } from "vue"; +import { defineComponent } from "vue"; +import { MdCheck } from "oh-vue-icons/icons"; +import { addIcons, OhVueIcon } from "oh-vue-icons"; +addIcons(MdCheck) +export default defineComponent({ + name: "NativeColorPicker", + props: { + value: { + type: String, + default: '' + }, + colorList: { + type: Array + }, + class: { + type: String, + }, + transparent: { + type: Boolean, + }, + firstColor: { + type: String, + + } + }, + emits: { + "update:value": (_value: string) => true, + }, + setup(props, context) { + const firstColor = props.value + const colorList = computed(() => { + let list = [ + '#ffffff', + '#000000', + '#FA9B3F', + '#333333', + '#6D7278', + '#D8D8D8', + '#0091FF', + '#B620E0', + '#F31260' + ] + if (props.colorList) { + list = props.colorList + } + if (props.transparent) { + list.push('transparent') + } + if (!list.includes(firstColor)) { + list.unshift(firstColor) + } + return list + }) + return () =>
+ { + colorList.value.map((item, index) => < div + key={index} + onClick={() => context.emit('update:value', item)} + class="text-[12px] cursor-pointer w-[20px] h-[20px] shadow-[0_0_2px_#999] rounded-full" + style={{ + backgroundColor: item === 'transparent' ? '' : item, + backgroundImage: + item === 'transparent' + ? `linear-gradient(45deg, rgba(0, 0, 0, 0.4) 25%, white 25%, transparent 75%,rgba(0, 0, 0, 0.4) 75%), + linear-gradient(45deg,rgba(0, 0, 0, 0.4) 25%, white 25%, transparent 75%, rgba(0, 0, 0, 0.4) 75%)` + : '', + backgroundPosition: item === 'transparent' ? '0 0, 2px 2px' : '', + backgroundSize: item === 'transparent' ? '4px 4px' : '' + }} + > + {/* + */} + { + props.value === item && + + + } +
) + } + +
+
+ { + context.emit('update:value', e?.target.value) + }} + ref="inputRef" + type="color" + style="opacity: 0" + /> +
+
+ + } +}) \ No newline at end of file diff --git a/src/utils/UploadAndCut.tsx b/src/utils/UploadAndCut.tsx new file mode 100644 index 0000000..9696307 --- /dev/null +++ b/src/utils/UploadAndCut.tsx @@ -0,0 +1,170 @@ +import { Modal } from 'ant-design-vue' +import { defineComponent, ref, watch } from 'vue' +import { VueCropper } from 'vue-cropper' +import 'vue-cropper/dist/index.css' +import upload from './upload' +import { v4 as uuid } from "uuid" +import { MdCroprotateRound, BiPlusLg } from "oh-vue-icons/icons"; +import { OhVueIcon, addIcons, } from 'oh-vue-icons' +import NativeColorPicker from './NativeColorPicker' +addIcons(MdCroprotateRound, BiPlusLg) + +export default defineComponent({ + + emits: { + 'update:value': (() => true) as (val: string) => boolean + }, + setup(props, ctx) { + const inputRef = ref(null) + const showCutModel = ref(false) + const originFile = ref('') + const fillColor = ref('transparent') + const cropper = ref(null) + const handleFile = (e: any) => { + const target = e.target as HTMLInputElement + + const file = target.files?.[0] + target.value = '' + console.log(file?.name); + + if (!file) return + // upload(file).then(res => { + const reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = (e: any) => { + originFile.value = e?.target.result // 显示原始图片 + showCutModel.value = true + } + // emit('update:icon', res || '') + // }) + } + const handleFinish = (blob: any) => { + // 根据前几个字节推测文件类型(这里只考虑常见的图片类型) + + // 使用 FileReader 对象读取 Blob 的前几个字节 + const reader = new FileReader() + reader.onloadend = function () { + // 打印 File 对象以验证 + + const fileData = new File([blob], `${uuid()}.png`, { + type: 'image/jpg', + lastModified: Date.now() + }) + upload(fileData, 'customIcon').then((res) => { + showCutModel.value = false + + ctx.emit('update:value', res || '') + }) + } + reader.readAsArrayBuffer(blob) + } + watch( + fillColor, + (e: string) => { + const elements = document.querySelectorAll('.cropper-crop-box') + elements.forEach((element: any) => { + element.style.backgroundColor = e // 修改颜色为蓝色 + }) + }, + { + immediate: true + } + ) + return () => ( + <> + showCutModel.value = false} + onOk={() => { + cropper.value.getCropBlob((blob: any) => { + handleFinish(blob) + + }) + }} + > +
+
+ +
+
+ {/* ($refs.cropper as any).rotateRight()} + /> */} + { + cropper.value.rotateRight() + }}> + + + + + cropper.value?.changeScale(1)} + class="icon cursor-pointer" + viewBox="0 0 1024 1024" + width="2rem" + height="2rem" + > + + + cropper.value?.changeScale(-1)} + class="icon cursor-pointer" + viewBox="0 0 1024 1024" + width="2rem" + height="2rem" + > + + + +
+ fillColor.value = e} transparent={true} /> + {/* {props.colorList && ( +
+ { }} + transparent={true} + /> +
+ )} */} + +
+
+
{ + inputRef.value?.click?.() + }} + > + +
+ + + ) + } + +}) diff --git a/tsconfig.app.json b/tsconfig.app.json index e14c754..db4bf17 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -5,7 +5,6 @@ "compilerOptions": { "composite": true, "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "baseUrl": ".", "paths": { "@/*": ["./src/*"]