diff --git a/common/api.js b/common/api.js index 7c2a110..3dc46e9 100644 --- a/common/api.js +++ b/common/api.js @@ -1,4 +1,13 @@ const http = uni.$u.http +//用户信息 +export const UserInfo = (params, config = {}) => http.post('/user/getinfo', params, config); +//上传base64 +export const uploadBase64 = (params, config = {}) => http.post('/index/uploads', params, config); +//微信登录 +export const wxapplogin= (params, config = {}) => http.post('/user/wxapplogin', params, config); +//修改用户信息 +export const profileUser= (params, config = {}) => http.post('/user/profile', params, config); + //获取首页轮播图 export const getBanner = (params, config = {}) => http.post('/wx_adv/index', params, config); //协议 @@ -37,6 +46,7 @@ export const articalList = (params, config = {}) => http.post('/wx_article/index + //修改用户信息 export const modifyInfo = (params, config = {}) => http.post('/user/mobilelogin', params, config); //第三方登录 diff --git a/common/http.interceptor.js b/common/http.interceptor.js index 7ea6bec..d73a5a8 100644 --- a/common/http.interceptor.js +++ b/common/http.interceptor.js @@ -51,6 +51,8 @@ module.exports = (vm) => { // 自定义参数 const custom = response.config?.custom + + console.log(11,data) if (data.code !== 1) { // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示 // if (custom.toast !== false) { diff --git a/components/okingtz-cropper/components/okingtz-cropper/okingtz-cropper.vue b/components/okingtz-cropper/components/okingtz-cropper/okingtz-cropper.vue index 0ecc644..f2780ee 100644 --- a/components/okingtz-cropper/components/okingtz-cropper/okingtz-cropper.vue +++ b/components/okingtz-cropper/components/okingtz-cropper/okingtz-cropper.vue @@ -43,6 +43,7 @@ + diff --git a/uni_modules/bt-cropper/components/bt-cropper/iconfont.css b/uni_modules/bt-cropper/components/bt-cropper/iconfont.css new file mode 100644 index 0000000..dd39483 --- /dev/null +++ b/uni_modules/bt-cropper/components/bt-cropper/iconfont.css @@ -0,0 +1,22 @@ +@font-face { + font-family: "iconfont"; /* Project id 3311610 */ + src: url('//at.alicdn.com/t/font_3311610_7wh8injedpd.woff2?t=1649382821379') format('woff2'), + url('//at.alicdn.com/t/font_3311610_7wh8injedpd.woff?t=1649382821379') format('woff'), + url('//at.alicdn.com/t/font_3311610_7wh8injedpd.ttf?t=1649382821379') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-reset:before { + content: "\e611"; +} + +.icon-move:before { + content: "\e67b"; +} diff --git a/uni_modules/bt-cropper/components/bt-cropper/js/touchs.js b/uni_modules/bt-cropper/components/bt-cropper/js/touchs.js new file mode 100644 index 0000000..3d8ef50 --- /dev/null +++ b/uni_modules/bt-cropper/components/bt-cropper/js/touchs.js @@ -0,0 +1,225 @@ +var startTouchs = []; +var touchType = '' +var startDistance = 0; +var touchCenter = []; +var cropperRect = null; +var imageRect = null; +var directionX = 0; +var directionY = 0; +var ratio = 0; +// 操作时改变的对象 +var changes = { + imageRect: null, + cropperRect: null +} +export default { + computed: { + imageStyle() { + const imageRect = this.imageRect + if (imageRect) { + return { + left: imageRect.left + 'px', + top: imageRect.top + 'px', + width: imageRect.width + 'px', + height: imageRect.height + 'px' + } + } else { + return {} + } + }, + cropperStyle() { + const cropperRect = this.cropperRect + if (cropperRect) { + return { + left: cropperRect.left + 'px', + top: cropperRect.top + 'px', + width: cropperRect.width + 'px', + height: cropperRect.height + 'px' + } + } else { + return {} + } + } + }, + methods: { + touchStart() { + let ev; + if (arguments.length == 3) { + directionX = arguments[0]; + directionY = arguments[1]; + ev = arguments[2]; + touchType = "controller"; + } else { + touchType = "image"; + ev = arguments[0]; + } + startTouchs = ev.touches; + changes = { + imageRect: this.imageRect, + cropperRect: this.cropperRect + }; + ratio = this.ratio; + cropperRect = { + ...changes.cropperRect + } + imageRect = { + ...changes.imageRect + } + if (startTouchs.length == 2) { + const imageRect = this.imageRect + var x1 = startTouchs[0].clientX + var y1 = startTouchs[0].clientY + var x2 = startTouchs[1].clientX + var y2 = startTouchs[1].clientY + var distance = Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2) + startDistance = Math.sqrt(distance) + var leftPercent = ((x1 + x2) / 2 - imageRect.left) / imageRect.width + var topPercent = ((y1 + y2) / 2 - imageRect.top) / imageRect.height + touchCenter = [leftPercent, topPercent] + } + }, + touchMove(ev) { + if(startTouchs.length!==ev.touches.length) return + var touches = ev.touches; + var changeX1 = touches[0].clientX - startTouchs[0].clientX; + var changeY1 = touches[0].clientY - startTouchs[0].clientY; + if (startTouchs.length == 1) { + if (touchType === 'image') { + changes.imageRect.left = imageRect.left + changeX1; + changes.imageRect.top = imageRect.top + changeY1; + // console.log(startTouchs.length,ev.touches.length) + } else if (touchType === 'controller') { + var changeX = changeX1 * directionX; + var changeY = changeY1 * directionY; + // 比例缩放控制 + if (ratio !== 0) { + if (directionX * directionY !== 0) { + if (changeX / ratio > changeY) { + changeY = changeX / ratio + changeX = changeY * ratio + } else { + changeX = changeY * ratio + changeY = changeX / ratio + } + } else { + if (directionX == 0) { + changeX = changeY * ratio + } else { + changeY = changeX / ratio + } + } + } + + var width = cropperRect.width + changeX + var height = cropperRect.height + changeY + var imageRight = imageRect.left + imageRect.width + var imageBottom = imageRect.top + imageRect.height + if (directionX != -1) { + if (cropperRect.left + width > imageRight) { + width = imageRight - cropperRect.left + if (ratio !== 0) { + height = width / ratio + } + } + } else { + var cLeft = cropperRect.left - changeX + if (cLeft < imageRect.left) { + width = cropperRect.left + cropperRect.width - imageRect.left + if (ratio !== 0) { + height = width / ratio + } + } + } + // 判断是否触底 + if (directionY != -1) { + if (cropperRect.top + height > imageBottom) { + height = imageBottom - cropperRect.top + if (ratio !== 0) { + width = height * ratio + } + } + } else { + var cTop = cropperRect.top - changeY + if (cTop < imageRect.top) { + height = cropperRect.top + cropperRect.height - imageRect.top + if (ratio !== 0) { + width = height * ratio + } + } + } + if (directionX == -1) { + changes.cropperRect.left = cropperRect.left + cropperRect.width - width + } + if (directionY == -1) { + changes.cropperRect.top = cropperRect.top + cropperRect.height - height + } + // 边界控制 + changes.cropperRect.width = width + changes.cropperRect.height = height + } + } else if (touches.length == 2 && startTouchs.length == 2) { + var changeX2 = touches[0].clientX - touches[1].clientX; + var changeY2 = touches[0].clientY - touches[1].clientY; + var distance = Math.pow(changeX2, 2) + Math.pow(changeY2, 2) + distance = Math.sqrt(distance) + // 放大比例 + var scaleRate = distance / startDistance + this.imageScale(scaleRate) + } + }, + touchEnd(ev) { + // console.log('end',ev) + if(ev.touches.length!==0) return + if (touchType === "image") { + var cropperLeft = cropperRect.left + var cropperRight = cropperRect.left + cropperRect.width + var cropperTop = cropperRect.top + var cropperBottom = cropperTop + cropperRect.height + var rate = changes.imageRect.width / changes.imageRect.height + var cropperRate = cropperRect.width / cropperRect.height + if (changes.imageRect.width < cropperRect.width || changes.imageRect.height < cropperRect.height) { + var scale = 1 + if (rate < cropperRate) { + scale = cropperRect.width / changes.imageRect.width + } else { + scale = cropperRect.height / changes.imageRect.height + } + imageRect.width = changes.imageRect.width + imageRect.height = changes.imageRect.height + this.imageScale(scale) + } + // 边界控制start + if (cropperLeft < changes.imageRect.left) { + changes.imageRect.left = cropperLeft + } + if (cropperRight > changes.imageRect.left + changes.imageRect.width) { + changes.imageRect.left = cropperRight - changes.imageRect.width + } + if (cropperTop < changes.imageRect.top) { + changes.imageRect.top = cropperTop + } + if (cropperBottom > changes.imageRect.top + changes.imageRect.height) { + changes.imageRect.top = cropperBottom - changes.imageRect.height + } + // 边界控制end + } + this.updateData({ + cropperRect: changes.cropperRect, + imageRect: changes.imageRect, + }) + touchType = "" + startTouchs = [] + return false; + }, + imageScale(scaleRate) { + var cw = imageRect.width * (scaleRate - 1) + var ch = imageRect.height * (scaleRate - 1) + changes.imageRect = { + width: imageRect.width + cw, + height: imageRect.height + ch, + left: imageRect.left - cw * (touchCenter[0]), + top: imageRect.top - ch * (touchCenter[1]) + } + } + } +} diff --git a/uni_modules/bt-cropper/components/bt-cropper/utils/tools.js b/uni_modules/bt-cropper/components/bt-cropper/utils/tools.js new file mode 100644 index 0000000..9fa9ade --- /dev/null +++ b/uni_modules/bt-cropper/components/bt-cropper/utils/tools.js @@ -0,0 +1,43 @@ +export function getTouchPoints(touchs) { + return Array.from(touchs).map(ev => { + return [ev.clientX, ev.clientY] + }) +} +// 函数防抖 +export function debounce(fn, wait = 200) { + var timer = null; + return function (){ + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(fn.bind(this), wait); + } +} + +/** + * @description 睡眠 + * @param {number} time 等待时间毫秒数 + */ +export function sleep(time = 200) { + return new Promise(resolve => { + setTimeout(resolve, time) + }) +} +const systemInfo = uni.getSystemInfoSync(); + +export function parseUnit(size){ + if(typeof size == 'number' || !isNaN(Number(size))){ + return uni.upx2px(size) + }else if(typeof size === 'string') { + if(size.endsWith('rpx')){ + return parseUnit(size.replace('rpx','')) + }else if(size.endsWith('px')){ + return Number(size.replace('px','')) + }else if(size.endsWith('vw')){ + return Number(size.replace('vw',''))*systemInfo.screenWidth/100 + }else if(size.endsWith('vh')){ + return Number(size.replace('vh',''))*systemInfo.screenHeight/100 + } + } + return 0 +} diff --git a/uni_modules/bt-cropper/package.json b/uni_modules/bt-cropper/package.json new file mode 100644 index 0000000..cb0f8d5 --- /dev/null +++ b/uni_modules/bt-cropper/package.json @@ -0,0 +1,81 @@ +{ + "id": "bt-cropper", + "displayName": "bt-cropper图片裁剪插件", + "version": "3.0.1", + "description": "一款好用的图片裁剪插件", + "keywords": [ + "图片", + "图片裁剪", + "图片裁剪", + "头像裁剪", + "cropper" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.2.1" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "1097122362" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "n" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} diff --git a/uni_modules/bt-cropper/readme.md b/uni_modules/bt-cropper/readme.md new file mode 100644 index 0000000..0e5d0ab --- /dev/null +++ b/uni_modules/bt-cropper/readme.md @@ -0,0 +1,109 @@ + + +## bt-cropper 图片裁切 +> **组件名:bt-cropper** + +图片裁切组件,在页面中裁切图片,输出裁切后的图片,支持app,小程序,H5 +### [在线体验](https://static-a3b890b4-7cb2-4b29-aa78-e652572bdef6.bspapp.com/#/) + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 组件需要依赖 `sass` 插件 ,请自行手动安装 +> - 只测试了头条小程序,app-vue 安卓,微信小程序和H5 大部分平台应该都没问题了 +> - 包裹层或裁剪器需要手动指定高度和宽度,推荐手动指定裁剪器的大小,尤其是头条小程序,js有时候获取不到容器的大小 +> - 如使用过程中有任何问题,或者您有一些好的建议,欢迎联系作者微信:1097122362 + + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +### 基本用法 + +**示例** + +```html + + +``` + + +```javascript +export default { + methods:{ + crop(){ + // 通过组件定义的ref调用cropper方法,返回一个promise对象 + this.$refs.cropper.crop().then(([err,res])=>{ + if(!err){ + console.log(res) + }else{ + console.err(err) + } + }) + } + } +} + +``` + +### 限定裁切比例 + +bt-cropper,指定ratio即可设置裁切框的宽高比,如果你想让用户自由缩放,将ratio设置为0即可 + +**示例** + +```html + +``` + +## API + +### cropper Props + +|属性名|类型|默认值|说明| +|:-:|:-:|:-:|:-:| +|ratio|number|0|裁切图像的宽高比,0表示自由比例| +|dWidth|number|0|生成的图片的宽度,单位:px,如果传入0的话就是按原像素的比例裁剪,也就是说,输出图片的清晰度和输入图片的清晰度一样| +|imageSrc|String|''|原图的路径,支持本地路径和网络路径,如果是网络路径,小程序要注意配置下载域名,H5要注意跨域问题| +|mask|String|''| 裁剪的蒙版url,配合蒙版可以裁剪出任何形状的图形 (示例见全屏裁剪demo) | +|fileType|String|'jpg'|目标文件的类型,只支持 'jpg' 或 'png'。默认为 'jpg'| +|quality|Number|1|图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理| +|showGrid|Boolean|false|是否显示中心网格线,默认不显示| +|initPosition|object|null|图片自定义的初始的位置,内容格式见change事件| +|autoZoom|Boolean|true|是否开启操作结束后自动放大到窗口大小| +|containerSize|object|null|手动指定容器大小,如果裁剪器放在大小会移动或缩放的dom中,则必须手动指定大小,可以带上单位,如果不带单位默认px,支持的单位有:rpx,px,vw,vm,示例:{width:100,height:1100}或者:{width:'100rpx',height:'100rpx'}| +|canvas2d|Boolean|false| 是开启新版的canvas | + + + +### cropper Methods + +|方法名称|说明|参数| +|:-:|:-:|:-:| +|crop|裁剪图片|开始绘制并开始裁剪图片,返回Promise对象| +|init|初始化|-| +|resetImage|重置裁剪框和图片的位置和大小到初始的位置和大小|-| +|redo|撤销,最多可以回退10步|-| +|resume|重做|-| + + +### cropper Events + +|方法名称|说明|返回值| +|:-:|:-:|:-:| +|change|当裁剪框和图片的相对位置发生变化的时候触发,返回裁剪框与图片的相对位置|ev={left:number,top:number,width:number,height:number}| +|loadFail|当图片加载失败时触发| - | +|cropStart|当裁开始时触发| - | +## 帮助 +在使用中如遇到无法解决的问题,请提 [Issues](https://gitee.com/xiaojiang1996/better-uni-cropper/issues) 或者加我 微信:1097122362。