From 9e760ddfb25e69a6c764114b847fdb435a60a7c1 Mon Sep 17 00:00:00 2001
From: expdsn <18111002318@163.com>
Date: Fri, 27 Sep 2024 16:35:30 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=E4=B8=8A=E4=BC=A0=E8=A3=81=E5=89=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package.json | 1 +
src/layout/adder/CustomAdder.tsx | 13 ++-
src/utils/NativeColorPicker.tsx | 109 ++++++++++++++++++++
src/utils/UploadAndCut.tsx | 170 +++++++++++++++++++++++++++++++
tsconfig.app.json | 1 -
5 files changed, 289 insertions(+), 5 deletions(-)
create mode 100644 src/utils/NativeColorPicker.tsx
create mode 100644 src/utils/UploadAndCut.tsx
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 1feea76..657ce13 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'
addIcons(MdUpload, MdImage, MdCheck)
@@ -76,7 +77,7 @@ const TypeSelector = defineComponent({
{
ctx.emit('update:value', 1)
@@ -105,13 +106,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..205e421
--- /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 } from "oh-vue-icons/icons";
+import { OhVueIcon, addIcons } from 'oh-vue-icons'
+import NativeColorPicker from './NativeColorPicker'
+
+addIcons(MdCroprotateRound)
+
+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()
+ }}>
+
+
+
+
+
+
+
+
+
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/*"]
From f87299ac6fa2a305d63622f912afad3c5a721d81 Mon Sep 17 00:00:00 2001
From: expdsn <18111002318@163.com>
Date: Fri, 27 Sep 2024 17:17:56 +0800
Subject: [PATCH 2/2] save
---
src/utils/UploadAndCut.tsx | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/utils/UploadAndCut.tsx b/src/utils/UploadAndCut.tsx
index 205e421..9696307 100644
--- a/src/utils/UploadAndCut.tsx
+++ b/src/utils/UploadAndCut.tsx
@@ -4,11 +4,10 @@ import { VueCropper } from 'vue-cropper'
import 'vue-cropper/dist/index.css'
import upload from './upload'
import { v4 as uuid } from "uuid"
-import { MdCroprotateRound } from "oh-vue-icons/icons";
-import { OhVueIcon, addIcons } from 'oh-vue-icons'
+import { MdCroprotateRound, BiPlusLg } from "oh-vue-icons/icons";
+import { OhVueIcon, addIcons, } from 'oh-vue-icons'
import NativeColorPicker from './NativeColorPicker'
-
-addIcons(MdCroprotateRound)
+addIcons(MdCroprotateRound, BiPlusLg)
export default defineComponent({
@@ -62,15 +61,15 @@ export default defineComponent({
watch(
fillColor,
(e: string) => {
- const elements = document.querySelectorAll('.cropper-crop-box')
- elements.forEach((element: any) => {
- element.style.backgroundColor = e // 修改颜色为蓝色
- })
+ const elements = document.querySelectorAll('.cropper-crop-box')
+ elements.forEach((element: any) => {
+ element.style.backgroundColor = e // 修改颜色为蓝色
+ })
},
{
- immediate: true
+ immediate: true
}
- )
+ )
return () => (
<>
@@ -138,7 +137,7 @@ export default defineComponent({
- fillColor.value = e} transparent={true}/>
+ fillColor.value = e} transparent={true} />
{/* {props.colorList && (