code: color input use blur

This commit is contained in:
ShawnPhang 2023-08-23 00:06:16 +08:00
parent aac211eafa
commit 6d42f3a6ab
20 changed files with 117 additions and 29433 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
node_modules
/dist
config.json
package-lock.json
screenshot/node_modules/
screenshot/dist/

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 ShawnPhang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,4 +1,6 @@
[在线体验](https://design.palxp.com/) | [文档网站](https://xp.palxp.com/) | [项目架构及目录](https://xp.palxp.com/#/articles/1689321259854)
**[在线体验](https://design.palxp.com/)** | **[中文文档网站](https://xp.palxp.com/)** | [架构及目录说明](https://xp.palxp.com/#/articles/1689321259854)
---
## 迅排设计
@ -29,7 +31,7 @@
### 拉取源码
> 环境需求:**Node.js v16** 以上版本
> 环境需求:**Node.js v16.18** 以上版本
```
git clone https://github.com/palxiao/poster-design.git
@ -50,78 +52,33 @@ npm run prepared
npm run serve
```
> 将会同时运行前端界面与图片生成服务:
> 将会同时运行前端界面与图片生成服务(`3000`端口为前端项目,`7001`端口为图片生成服务)
>
> ![](https://xp.palxp.com/images/2023-7-16-1689498291322.png)
> 如果你本地没有成功启动两个服务,可能是 win 系统不兼容,手动进 `screenshot` 目录安装依赖并启动服务,或是使用 VSCode 自带的终端来运行命令,不要使用 CMD。
> 如果你本地没有成功启动两个服务,可能是 win 系统不兼容,手动进 `screenshot` 目录安装依赖(`npm install`)并启动服务(`npm run dev`)
> 或者使用 VSCode 自带的终端来运行命令,不要使用 CMD。
合成图片时本地会启动一个 Chrome 浏览器实例。
### 打包
```
npm run v-build <- 前端页面
npm run build <- 图片生成服务 sreenshot 目录下
```
| 前端页面 | 图片生成服务 |
| ----------------- | ------------------------------------- |
| `npm run v-build` | `cd sreenshot` <br /> `npm run build` |
### 服务
###
可参考[接口 API 文档](https://xp.palxp.com/apidoc/index.html)自行实现服务端
根据你的具体场景自行实现,目前本项目中的所有服务端接口可参考[接口 API 文档](https://xp.palxp.com/apidoc/index.html)。
### 图片生成服务
代码位于 `screenshots` 目录下,查看[接口 API 文档](https://xp.palxp.com/apidoc/screenshot.html)。
代码位于 [screenshots/](https://github.com/palxiao/poster-design/tree/main/screenshot) 目录下,查看[接口 API 文档](https://xp.palxp.com/apidoc/screenshot.html)。
目录结构比较简单,主要就实现了三个接口,其中 api/screenshots 即是项目中所使用到的图片生成接口,在真实生产项目中可以把该服务单独部署,于内网调用,这样利于做一些鉴权之类的处理。
另外 api/printscreen 这个接口实现的是网页截图的 API该接口可以传入一个 URL 对整个网页进行截图,本项目中不依赖此接口。
### 服务器配置
在 Linux 环境下npm 自动安装的 Chrome 浏览器有可能会出错,所以推荐从外部安装好浏览器,再给项目中的配置文件 `config.js` 设置好路径,例如:
```js
exports.executablePath = '/opt/google/chrome-unstable/chrome'
```
一些可能用到的 linux 命令参考:
```shell
google-chrome --version # 查看浏览器版本号
apt-get update
apt-get install -y google-chrome-stable // 安装最新稳定版谷歌浏览器
```
> 打包注意事项与服务器配置相关请进入该目录下查看 README 文件说明。
### Docker 容器部署
可以通过 Docker 运行一个带 Linux 浏览器的容器,然后暴露一个截图服务以供使用,我所使用的基础镜像为:
```
docker pull howard86/puppeteer_node:12
```
运行容器命令参考(其中映射了 `/cache` 为临时目录,放生成图片用):
```
docker run -itd -v /data/docker-home:/home -v /data/cache:/cache -p 7001:7001 --name screenshot howard86/puppeteer_node:12
```
运行后可以手动进入容器中查看谷歌浏览器版本,看需不需要升级,然后安装 pm2 作为服务管理工具,服务启动/重部署相关脚本命令可参考:
```shell
docker exec screenshot /bin/bash -c 'pm2 delete screenshot-service'
docker exec screenshot /bin/bash -c 'cd /home/ && yarn'
docker exec screenshot /bin/bash -c 'pm2 start /home/screenshot-service.js'
docker exec screenshot /bin/bash -c 'pm2 flush'
```
如果不想像上面这样直接操作容器,可以在本地/服务器先运行镜像,进入容器中照例配置好 pm2然后把该容器导出为新的镜像例如new-design/screenshot命令运行参考
```
docker run -itd -u root -v ~/data/tmp/screenshot:/cache -p 9001:9001 --name screenshot2 new-design/screenshot /bin/sh -c "/usr/local/bin/pm2 start /home/dist/server.js && /usr/local/bin/pm2 flush"
```
这种方式只需要一个镜像以及一个启动命令即可部署,重新跑一遍命令也就相当于重启整个容器。
可以通过 Docker 运行一个带 Linux 浏览器的容器,[参考说明](https://xp.palxp.com/#/articles/1689319644311?id=docker%e5%ae%b9%e5%99%a8)。
### 感谢
@ -130,24 +87,27 @@ docker run -itd -u root -v ~/data/tmp/screenshot:/cache -p 9001:9001 --name scre
- [moveable](https://github.com/daybrush/moveable): 提供了画布中选择、拖动缩放等能力
- [html2canvas](https://github.com/niklasvh/html2canvas): 前端生成图片兜底方案
- [qr-code-styling](https://qr-code-styling.com/): 风格化二维码
- [sky](https://github.com/cfour-hi/sky): 参考了其 PSD 解析的实现
- [sky](https://github.com/cfour-hi/sky): 参考了其 PSD 解析的代码实现
- [rembg](https://github.com/danielgatis/rembg): 图片删除背景,使用 u2net 预训练模型
### Q&A
Q**我想二次开发,但是不会编写代码,可以付费开发吗?**
A抱歉本人时间精力有限无法提供私有化部署或二次开发的服务不接受定制化开发的需求。如果您对项目有任何建议或意见,非常欢迎与我交流。
A抱歉本人时间精力有限,无法提供私有化部署或二次开发的服务,不接受定制化开发的需求。如果您对项目有任何建议,非常欢迎与我交流。
Q**服务端源码不开源吗?**
Q**端源码不开源吗?**
A考虑到服务端的开发语言、数据库类型都可能不尽相同分离代码出来有一定成本,所以暂时不考虑直接开源,只提供接口 API 文档供参考。目前服务端仅是一些简单的增删改查,自行实现的技术难度并不高。
A考虑到服务端的开发语言、数据库类型都可能不尽相同本项目中实现简单,代码不具备参考性,所以暂时只提供接口 API 文档。(仅是一些增删改查,实现的技术难度并不高)
### 其它
项目最早使用 Vue2 开发,后改用 Vue3 重构,所以有部分代码混合了 Options 写法。
如果你也对开发图片编辑器感兴趣,欢迎一起共建项目
或许你在工作中有这类需求,这个项目能给到你一些微薄帮助的话,那就再好不过了
或许你在工作中有这类需求,如果能给到你一些微薄的帮助,那就更好不过了
目前本项目也还在不断迭代中,有很多的不足之处,我也是一边学习一边成长。开源不易,希望看到这里的你可以给本项目点个 **Star** 支持一下~ 感谢
目前本项目也还在不断迭代中,有很多的不足之处,我也是一边学习一边成长。开源不易,希望看到这里的你可以给本项目点个 Star 支持一下~ 感谢!
### LICENSE
[MIT License](https://github.com/palxiao/poster-design/blob/main/LICENSE)

28999
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
},
"dependencies": {
"@gradio/client": "^0.1.4",
"@palxp/color-picker": "^1.2.5",
"@palxp/color-picker": "^1.3.1",
"@scena/guides": "^0.18.1",
"axios": "^0.21.1",
"core-js": "^3.6.5",

View File

@ -1,10 +0,0 @@
/*
* @Author: ShawnPhang
* @Date: 2023-07-12 09:51:07
* @Description: AI接口
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-13 16:59:21
*/
import fetch from '@/utils/axios'
export const kt = (params: Type.Object = {}) => fetch('https://kt.palxp.com/api/remove', params, 'post', {}, { responseType: 'arraybuffer' })

View File

@ -3,13 +3,12 @@
* @Date: 2023-07-13 17:01:37
* @Description: github api
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-14 00:01:05
* @LastEditTime: 2023-08-10 10:33:59
*/
import fetch from '@/utils/axios'
const reader = new FileReader()
const knock = 'qpV8PUxwY7as4jc'
const cut = 'AqYfNFb6G2f2OVl4IVFOY'
const cutToken = 'ghp_qpV8PUxwY7as4jc'
const reader = new FileReader()
function getBase64(file: File) {
return new Promise((resolve) => {
reader.onload = function (event: any) {
@ -21,22 +20,17 @@ function getBase64(file: File) {
}
const putPic = async (file: any) => {
const content = typeof file === 'string' ? file : await getBase64(file)
const repo = 'shawnphang/files'
const d = new Date()
const content = typeof file === 'string' ? file : await getBase64(file)
const path = `${d.getFullYear()}/${d.getMonth()}/${d.getTime()}${file.name?.split('.').pop() || '.png'}`
const imageUrl = 'https://api.github.com/repos/' + repo + '/contents/' + path
const body = {
branch: 'main',
message: 'upload',
content,
path,
}
await fetch(imageUrl, body, 'put', {
Authorization: 'token ' + 'ghp_' + knock + cut,
const body = { branch: 'main', message: 'upload', content, path }
const res = await fetch(imageUrl, body, 'put', {
Authorization: `token ${cutToken}AqYfNFb6G2f2OVl4IVFOY`,
'Content-Type': 'application/json; charset=utf-8',
})
return `https://fastly.jsdelivr.net/gh/shawnphang/files@main/${path}`
return res?.content?.download_url || `https://fastly.jsdelivr.net/gh/shawnphang/files@main/${path}`
}
export default { putPic }

View File

@ -1,6 +1,7 @@
@font-face {
font-family: TitleFont;
src: url(../fonts/xpsj.subset.woff2) format('woff2');
font-display: swap;
}
body {
--el-color-primary: #2254f4;

View File

@ -1,9 +1,9 @@
<!--
* @Author: ShawnPhang
* @Date: 2021-08-01 11:12:17
* @Description: 前端出图 - 生成封面
* @Description: 前端出图 - 用于封面
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-11 19:47:24
* @LastEditTime: 2023-07-26 10:22:17
-->
<template>
<div id="cover-wrap">
@ -24,21 +24,6 @@ export default defineComponent({
setup(props, context) {
let gridSizeIndex: number = 0
// function fileOrBlobToDataURL(obj: any, cb: Function) {
// let a = new FileReader()
// a.readAsDataURL(obj)
// a.onload = (e: any) => {
// cb(e.target.result)
// }
// }
// function blobToImage(blob: any) {
// return new Promise((resolve) => {
// fileOrBlobToDataURL(blob, (dataurl: string) => {
// resolve(dataurl)
// })
// })
// }
const { proxy }: any = getCurrentInstance() as ComponentInternalInstance
async function createCover(cb: any) {

View File

@ -1,253 +0,0 @@
<!--
* @Author: ShawnPhang
* @Date: 2021-08-01 11:12:17
* @Description: 前端出图 - 已废弃
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-11 16:58:34
-->
<template>
<div v-show="fillInfoing" class="fill-info-wrap">
<div v-loading="loading" class="fill-info-content">
<div class="fill-info-step">
<div id="cover-wrap">
<img id="cover" />
</div>
<div class="publish-btn" @click="saveImg">
<span v-show="!publishing">下载图片</span>
<i v-show="publishing" class="el-icon-loading"></i>
</div>
<div class="close-publish" @click="closePublish">关闭</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, watch, getCurrentInstance, ComponentInternalInstance } from 'vue'
import { mapGetters, mapActions } from 'vuex'
import html2canvas from 'html2canvas'
import api from '@/api'
import useLoading from '@/common/methods/loading'
export default defineComponent({
props: ['modelValue'],
emits: ['update:modelValue'],
setup(props, context) {
let gridSizeIndex: number = 0
const state = reactive({
fillInfoing: false,
loading: false,
publishing: false,
})
watch(
() => props.modelValue,
(open) => {
if (open) {
save()
}
},
)
const closePublish = () => {
state.fillInfoing = false
context.emit('update:modelValue', false)
}
function fileOrBlobToDataURL(obj: any, cb: Function) {
let a = new FileReader()
a.readAsDataURL(obj)
a.onload = (e: any) => {
cb(e.target.result)
}
}
function blobToImage(blob: any) {
return new Promise((resolve) => {
fileOrBlobToDataURL(blob, (dataurl: string) => {
resolve(dataurl)
})
})
}
const { proxy }: any = getCurrentInstance() as ComponentInternalInstance
async function save() {
// state.loading = true
// state.fillInfoing = true
let nowGrideSizeIndex = gridSizeIndex
let nowZoom = proxy?.dZoom
//
proxy?.selectWidget({
uuid: '-1',
})
gridSizeIndex = 0
proxy?.updateZoom(100)
const opts = {
useCORS: true, //
scale: 0.4,
}
setTimeout(async () => {
html2canvas(document.getElementById('page-design-canvas'), opts).then((canvas) => {
canvas.toBlob(
async (blob: any) => {
const data = await blobToImage(blob)
document.getElementById('cover').src = data
state.loading = false
gridSizeIndex = nowGrideSizeIndex
proxy?.updateZoom(nowZoom)
proxy?.saveImg()
},
'image/jpeg',
0.2,
)
})
}, 300)
}
function saveImg() {
if (state.publishing) {
return
}
state.publishing = true
let image = new Image()
// Canvas
image.setAttribute('crossOrigin', 'anonymous')
image.onload = function () {
let canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')
context?.drawImage(image, 0, 0, image.width, image.height)
let url = canvas.toDataURL('image/png')
let a = document.createElement('a')
let event = new MouseEvent('click')
// adownloadname使
a.download = name || '生成图片'
a.href = url
// a
a.dispatchEvent(event)
}
image.src = document.getElementById('cover').src
state.publishing = false
state.fillInfoing = false
}
async function createImg(cb: any) {
let loading: any = useLoading('保存封面中')
let nowGrideSizeIndex = gridSizeIndex
let nowZoom = proxy?.dZoom
//
proxy?.selectWidget({
uuid: '-1',
})
gridSizeIndex = 0
proxy?.updateZoom(100)
const opts = {
useCORS: true, //
scale: 0.4,
}
setTimeout(async () => {
html2canvas(document.getElementById('page-design-canvas'), opts).then(async (canvas) => {
cb(canvas.toDataURL('image/jpeg', 0.6))
gridSizeIndex = nowGrideSizeIndex
proxy?.updateZoom(nowZoom)
loading.close()
})
}, 301)
}
return {
save,
closePublish,
saveImg,
createImg,
...toRefs(state),
}
},
computed: {
...mapGetters(['dZoom', 'dPage']),
},
methods: {
...mapActions(['selectWidget', 'updateZoom']),
},
})
</script>
<style lang="less" scoped>
// Width variables (appears count calculates by raw css)
@width00: 400px; // Appears 2 times
@width20: 100%; // Appears 2 times
// Height variables (appears count calculates by raw css)
@height20: 400px; // Appears 2 times
.fill-info-wrap {
background-color: rgba(0, 0, 0, 0.8);
height: 100%;
padding: 50px;
position: absolute;
width: @width20;
z-index: 9999;
.fill-info-content {
background-color: @color-white;
border-radius: 10px;
display: flex;
flex-direction: column;
margin: 0 auto;
max-height: 861px;
min-height: 600px;
padding: 20px;
width: 600px;
.fill-info-step {
flex: 1;
width: @width20;
#cover-wrap {
align-items: center;
display: flex;
height: @height20;
justify-content: center;
margin: 20px auto;
width: @width00;
#cover {
box-shadow: 1px 1px 10px 3px rgba(0, 0, 0, 0.1);
max-height: @height20;
max-width: @width00;
}
}
.publish-btn {
background-color: @color-main;
border-radius: 5px;
color: @color-white;
cursor: pointer;
margin: 20px auto;
padding: 10px;
text-align: center;
&:hover {
background-color: @color-dark-gray;
}
}
.close-publish {
background-color: @color-white;
border-radius: 5px;
color: @color-main;
cursor: pointer;
margin-bottom: 0px;
margin: 20px auto;
outline: 1px solid @color-main;
padding: 10px;
text-align: center;
&:hover {
background-color: @color-dark-gray;
color: @color-white;
}
}
}
}
}
</style>

View File

@ -7,6 +7,7 @@
<p>{{ item.name }}</p>
</li>
</ul>
<a href="https://github.com/palxiao/poster-design" target="_blank" class="github"><img src="https://fe-doc.palxp.com/images/github.svg" alt="Github" title="Github" /> 源码</a>
</div>
<div v-show="active" class="widget-wrap">
<temp-list-wrap :style="getStyle(0)" />
@ -109,6 +110,7 @@ export default {
position: relative;
// width: 360px;
.widget-classify {
position: relative;
border-right: 1px solid rgba(0, 0, 0, 0.07);
background-color: #ffffff;
height: 100%;
@ -212,4 +214,20 @@ export default {
}
}
}
.github {
cursor: pointer;
position: absolute;
bottom: 12px;
font-size: 12px;
display: flex;
align-items: flex-end;
justify-content: center;
width: 100%;
img {
width: 21px;
height: 21px;
margin: 0 2px;
}
}
</style>

View File

@ -6,7 +6,7 @@
<div class="content">
<el-popover placement="left-end" width="auto">
<!-- eslint-disable-next-line vue/no-v-model-argument -->
<color-picker v-model:value="innerColor" :modes="['纯色']" @nativePick="dropColor" />
<color-picker v-model:value="innerColor" :modes="['纯色']" @blur="inputBlur" @nativePick="dropColor" />
<template #reference>
<div class="color__bar" :style="{ background: innerColor }"></div>
</template>
@ -19,10 +19,11 @@
const NAME = 'color-select'
import { defineComponent, toRefs, reactive, computed, onMounted, watch } from 'vue'
import { useStore } from 'vuex'
import { debounce } from 'throttle-debounce'
import { toolTip } from '@/common/methods/helper'
// import { debounce } from 'throttle-debounce'
// import { toolTip } from '@/common/methods/helper'
// import colorPicker from '@/utils/plugins/color-picker/index.vue'
import colorPicker from '@palxp/color-picker'
// import colorPicker from '@palxp/color-picker'
import colorPicker from '@palxp/color-picker/index.vue'
export default defineComponent({
name: NAME,
@ -90,12 +91,17 @@ export default defineComponent({
// state.innerColor = e + (e.length === 7 ? 'ff' : '')
// })
const inputBlur = (color: string) => {
state.innerColor = color
}
return {
...toRefs(state),
// dColorHistory,
activeChange,
onChange,
dropColor,
inputBlur,
}
},
})

View File

@ -45,6 +45,7 @@ export default {
step: {
default: 1,
},
maxValue: {},
},
emits: ['finish', 'update:modelValue'],
data() {
@ -66,12 +67,18 @@ export default {
methods: {
fixedNum() {
//
const num = String(this.modelValue).split('.')[1]
if (num && num.length > 2) {
const decimal = String(this.modelValue).split('.')[1]
if (decimal && decimal.length > 2) {
setTimeout(() => {
this.updateValue(Number(this.modelValue).toFixed(2))
}, 10)
}
//
if (this.maxValue && this.modelValue > this.maxValue) {
setTimeout(() => {
this.updateValue(Number(this.maxValue))
}, 10)
}
},
updateValue(value) {
this.$emit('update:modelValue', value)
@ -220,4 +227,4 @@ export default {
width: 100%;
}
}
</style>
</style>

View File

@ -3,8 +3,8 @@
<el-collapse v-model="activeNames">
<el-collapse-item title="画布尺寸" name="1">
<div class="position-size">
<number-input v-model="innerElement.width" label="宽" @finish="(value) => finish('width', value)" />
<number-input v-model="innerElement.height" label="高" @finish="(value) => finish('height', value)" />
<number-input v-model="innerElement.width" label="宽" :maxValue="5000" @finish="(value) => finish('width', value)" />
<number-input v-model="innerElement.height" label="高" :maxValue="5000" @finish="(value) => finish('height', value)" />
</div>
</el-collapse-item>
<el-collapse-item title="背景设置" name="2">
@ -25,10 +25,6 @@
<!-- <el-collapse-item title="其他设置" name="3">
<el-input v-model="innerElement.name" label="名称" @finish="(value) => finish('name', value)" />
</el-collapse-item> -->
<!-- <el-collapse-item title="客户端配置(设置客户端是否允许修改)" name="4">
<setting-switch v-for="item in dActiveElement.setting" :key="item.key" v-model="item.value" :label="item.label" />
</el-collapse-item> -->
<!-- <el-button v-loading="canvasRunning" size="small" @click="pickColor">取色器测试</el-button> -->
</el-collapse>
</div>
</template>

View File

@ -14,7 +14,7 @@ export default {
SCREEN_URL: isDev ? 'http://localhost:7001' : '${SCREEN_URL}',
IMG_URL: 'https://store.palxp.com/',
// ICONFONT_URL: '//at.alicdn.com/t/font_3223711_74mlzj4jdue.css',
ICONFONT_URL: '//at.alicdn.com/t/font_2717063_ypy8vprc3b.css',
ICONFONT_EXTRA: '//at.alicdn.com/t/c/font_3228074_6qsac4kteu7.css',
ICONFONT_URL: '//at.alicdn.com/t/font_2717063_ypy8vprc3b.css?display=swap',
ICONFONT_EXTRA: '//at.alicdn.com/t/c/font_3228074_6qsac4kteu7.css?&display=swap',
QINIUYUN_PLUGIN: 'https://cdn.jsdelivr.net/npm/qiniu-js@2.5.5/dist/qiniu.min.js',
}

View File

@ -1,37 +0,0 @@
/*
* @Author: ShawnPhang
* @Date: 2022-03-28 09:23:10
* @Description:
* @LastEditors: ShawnPhang
* @LastEditTime: 2022-03-28 10:08:38
*/
import store from '@/store'
import { onMounted, onBeforeUnmount, nextTick } from 'vue'
export default async (elName: string | Element) => {
onMounted(async () => {
await nextTick()
const el: any = typeof elName === 'string' ? document.querySelector(elName) : elName
el.onmousedown = function(ev: any) {
console.log('点击')
const distanceX = ev.clientX - el.offsetLeft
const distanceY = ev.clientY - el.offsetTop
document.onmousemove = function(ev) {
console.log('拖动')
// var oevent = ev || event;
// entrance.style.left = oevent.clientX - distanceX + 'px';
// entrance.style.top = oevent.clientY - distanceY + 'px';
}
document.onmouseup = function(ev) {
console.log('释放')
document.onmousemove = null
document.onmouseup = null
}
}
})
}

View File

@ -2,23 +2,19 @@
* @Author: ShawnPhang
* @Date: 2021-08-19 18:43:22
* @Description:
* @LastEditors: ShawnPhang
* @LastEditTime: 2021-10-08 18:27:13
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-31 09:31:52
*/
// import { moveByDom, resizeByDom, initLine } from 'view-line'
// import 'view-line/dist/view-line.css'
// let isDraging = false
// const offset = { top: 0, left: 0 }
import store from '@/store'
const move = {
methods: {
initmovement(e: any) {
// let target = this.$store.state.pageDesign.dActiveElement
const target = this.$store.getters.dActiveElement
// let target = store.state.pageDesign.dActiveElement
const target = store.getters.dActiveElement
// 设置移动状态初始值
this.$store.dispatch('initDMove', {
store.dispatch('initDMove', {
startX: e.pageX,
startY: e.pageY,
originX: target.left,
@ -32,11 +28,11 @@ const move = {
document.addEventListener('mouseup', this.handlemouseup, true)
},
handlemousemove(e) {
handlemousemove(e: any) {
e.stopPropagation()
e.preventDefault()
this.$store.dispatch('dMove', {
store.dispatch('dMove', {
x: e.pageX,
y: e.pageY,
})
@ -45,7 +41,7 @@ const move = {
handlemouseup() {
document.removeEventListener('mousemove', this.handlemousemove, true)
document.removeEventListener('mouseup', this.handlemouseup, true)
this.$store.dispatch('stopDMove')
store.dispatch('stopDMove')
},
},
}
@ -56,11 +52,11 @@ const moveInit = {
if (!store.getters.dAltDown) {
// 设置mouseevent给moveable初始
// 在组合操作时排除
this.$store.commit('setMouseEvent', e)
store.commit('setMouseEvent', e)
}
const target = this.$store.getters.dActiveElement
this.$store.dispatch('initDMove', {
const target = store.getters.dActiveElement
store.dispatch('initDMove', {
startX: e.pageX,
startY: e.pageY,
originX: target.left,
@ -69,7 +65,7 @@ const moveInit = {
const handlemouseup = () => {
// 销毁选中即刻移动
this.$store.commit('setMouseEvent', null)
store.commit('setMouseEvent', null)
document.removeEventListener('mouseup', handlemouseup, true)
}
document.addEventListener('mouseup', handlemouseup, true)

View File

@ -3,7 +3,7 @@
* @Date: 2021-07-13 02:48:38
* @Description: code为200时返回result结果对象
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-12 10:43:34
* @LastEditTime: 2023-07-31 09:34:34
*/
import axios from 'axios'
import store from '@/store'
@ -11,8 +11,6 @@ import app_config from '@/config'
axios.defaults.timeout = 30000
// axios.defaults.headers.Authorization = 'Bearer ';
// axios.defaults.headers.AppKey = '9e8nbMCqDkMhSRkTo8nYb7VF3qUa43EI'
// const version = app_config.VERSION;
const baseUrl = app_config.API_URL

View File

@ -3,7 +3,7 @@
* @Date: 2022-03-25 15:19:02
* @Description: 版权声明
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-06 16:48:12
* @LastEditTime: 2023-08-08 10:09:59
-->
<template>
<tool-tip title="免责声明" :width="340" :content="content">
@ -20,7 +20,7 @@ import toolTip from '@/components/common/PopoverTip.vue'
export default defineComponent({
components: { toolTip },
setup() {
const content = '本站为个人项目,素材资源均来源于网络不提供任何版权保障下载之作品仅供学习研究或欣赏目的而使用请于24h内自行删除。'
const content = '本站为个人项目,所使用素材图片等均为网络收集而来,下载之作品仅供学习研究或欣赏目的而使用,无法提供商用授权哦。'
return {
content,
}

View File

@ -3,7 +3,7 @@
* @Date: 2021-08-19 18:30:38
* @Description: Vite配置文件
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-20 18:48:25
* @LastEditTime: 2023-08-01 10:46:59
*/
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'