9 files modified
17 files added
| | |
| | | // devUrl: 'http://192.168.1.156:9528', |
| | | // devUrl:'http://192.168.1.50:9528', |
| | | // devUrl: 'http://192.168.0.102:9528', |
| | | // devUrl:'https://srgdjczzxtpt.com:2080/api', |
| | | devUrl: 'http://192.168.0.103:9528', |
| | | devUrl:'https://srgdjczzxtpt.com:2080/api', |
| | | // devUrl: 'http://192.168.0.103:9528', |
| | | // devUrl: 'https://srgdjczzxtpt.com:2080/api', |
| | | minioBaseUrl: "https://srgdjczzxtpt.com:2080/gminio/jczz/", |
| | | // minioBaseUrl:"http://192.168.0.103:9528/", |
| New file |
| | |
| | | ### 使用方法 |
| | | * 注意 |
| | | + 同一个页面不同的输入框需要设置不同的canvasId和canvasIds,否则在同一个页面会出现冲突 |
| | | ``` |
| | | <template> |
| | | <view class="content"> |
| | | <signInput ref="sign" canvasId="twoDrowCanvas" canvasIds="twoRotateCanvas" :header="header" :action="action" |
| | | @signToUrl="signToUrl"> |
| | | </signInput> |
| | | </view> |
| | | </template> |
| | | ``` |
| | | ``` |
| | | <script> |
| | | import signInput from "@/components/am-sign-input/am-sign-input.vue" |
| | | export default { |
| | | components: { |
| | | signInput |
| | | }, |
| | | data() { |
| | | return { |
| | | action: "", //上传服务器的地址 |
| | | header: {}, //图片上传携带头部信息 |
| | | } |
| | | }, |
| | | methods: { |
| | | /** |
| | | * @param {Object} e |
| | | * 签名完成回调 |
| | | */ |
| | | signToUrl(e) { |
| | | if (e.error_code && e.error_code === '201') { |
| | | uni.showToast({ |
| | | title: e.msg, |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | ``` |
| | | ``` |
| | | <style lang="scss"> |
| | | .content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | </style> |
| | | ``` |
| | | |
| | | #### 实际效果演示H5 |
| | | - 打开演示后,按F12调整到手机调试模式查看效果 |
| | | [实际效果演示](https://static-mp-2766f90e-0e50-4c71-87fb-0ab51aedcf85.next.bspapp.com/signInput/#/) |
| | | |
| | | ### 参数说明Props |
| | | |
| | | 参数|类型|说明|必传 |
| | | ---|---|---|--- |
| | | action|String|生成图片后上传的接口地址|true |
| | | canvasId|String|canvasId|true |
| | | canvasIds|String|canvasIds与上一个id不可重复|true |
| | | header|Object|文件上传携带的头部属性|true |
| | | outSignWidth|Number|输出图片文件大小-宽度|false |
| | | outSignHeight|Number|输出图片文件大小-高度|false |
| | | minSpeed|Number|画笔最小速度|false |
| | | minWidth|Number|线条最小粗度|false |
| | | maxWidth|Number|线条最大粗度|false |
| | | openSmooth|Boolean|开启平滑线条(笔锋)|false |
| | | maxHistoryLength|Number|历史最大长度(用于撤销的步数)|false |
| | | maxWidthDiffRate|Number|最大差异率|false |
| | | undoScan|Number|撤销重新渲染偏移缩放校准|false |
| | | bgColor|String|背景色如#ffffff 不传则为透明|false |
| | | |
| | | ### 相关同源插件 |
| | | - 以页面形式展现 |
| | | - [电子签名组件](https://ext.dcloud.net.cn/plugin?id=5768) |
| | | |
| | | ### 相关致谢 |
| | | - 插件参考 [大佬的npm库](https://github.com/linjc/smooth-signature) |
| New file |
| | |
| | | <template> |
| | | <view class="sign"> |
| | | <view class="imgBox"> |
| | | <view class="nom_img" v-if="!showImg" @click="signModShow=true"> |
| | | <image v-if="!showImg" src="/static/other/signs.png" style="width: 34px;height: 34px;"> |
| | | </image> |
| | | </view> |
| | | <view class="across_img" v-if="showImg"> |
| | | <view v-if="showImg" class="delete_icon" @click.stop="deleteImg"> |
| | | x |
| | | </view> |
| | | <image v-if="showImg" :src="showImg" style="width: 140px;height: 80px;" @click="previewImg(showImg)"> |
| | | </image> |
| | | </view> |
| | | </view> |
| | | |
| | | <umask :show="signModShow" @click="signModShow=false" :duration="0"> |
| | | <view class="warp"> |
| | | <view class="signBox" @tap.stop> |
| | | <view class="wrapper"> |
| | | <view class="handBtn"> |
| | | <!-- #ifdef MP-WEIXIN --> |
| | | <image @click="selectColorEvent('black','#1A1A1A')" |
| | | :src="selectColor === 'black' ? '/static/other/color_black_selected.png' : '/static/other/color_black.png'" |
| | | class="black-select"></image> |
| | | <image @click="selectColorEvent('red','#ca262a')" |
| | | :src="selectColor === 'red' ? '/static/other/color_red_selected.png' : '/static/other/color_red.png'" |
| | | class="red-select"></image> |
| | | <!-- #endif --> |
| | | <!-- #ifndef MP-WEIXIN --> |
| | | <view class="color_pic" :style="{background:lineColor}" @click="showPickerColor=true"> |
| | | </view> |
| | | <!-- #endif --> |
| | | <button @click="clear" class="delBtn">清空</button> |
| | | <button @click="saveCanvasAsImg" class="saveBtn">保存</button> |
| | | <button @click="previewCanvasImg" class="previewBtn">预览</button> |
| | | <button @click="subCanvas" class="subBtn">完成</button> |
| | | <button @click="undo" class="undoBtn">撤销</button> |
| | | <span class="emptyInfo" style="color: red;" v-if="emptyShow">你还没有绘制任何东西哦</span> |
| | | </view> |
| | | <view class="handCenter" :style="{left:canvasLeft+'px'}"> |
| | | <canvas :disable-scroll="true" @touchstart="uploadScaleStart" @touchmove="uploadScaleMove" |
| | | @touchend="uploadScaleEnd" :style="{width:'100%',height:'calc(85vh - 8rpx)'}" |
| | | :canvas-id="canvasId"></canvas> |
| | | </view> |
| | | |
| | | <view class="handCenters"> |
| | | <canvas :canvas-id="canvasIds" |
| | | :style="{width:outSignWidth+'px',height:outSignHeight+'px'}"></canvas> |
| | | </view> |
| | | <view class="handRight"> |
| | | <view class="handTitle">请签名 |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </umask> |
| | | <pickerColor :isShow="showPickerColor" :bottom="0" @callback='getPickerColor' /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import umask from "./u-mask/u-mask.vue" |
| | | import pickerColor from "./pickerColor.vue" |
| | | export default { |
| | | components: { |
| | | umask, |
| | | pickerColor |
| | | }, |
| | | data() { |
| | | return { |
| | | canvasLeft: 10000, |
| | | emptyShow: false, |
| | | signModShow: false, |
| | | showImg: "", |
| | | showPickerColor: false, |
| | | ctx: '', |
| | | ctxs: '', |
| | | canvasWidth: 0, |
| | | canvasHeight: 0, |
| | | selectColor: 'black', |
| | | lineColor: '#1A1A1A', |
| | | points: [], |
| | | historyList: [], |
| | | canAddHistory: true, |
| | | getImagePath: () => { |
| | | let that = this |
| | | return new Promise((resolve) => { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: that.canvasId, |
| | | fileType: 'png', |
| | | quality: 1, //图片质量 |
| | | success: res => resolve(res.tempFilePath) |
| | | }, this) |
| | | }) |
| | | }, |
| | | requestAnimationFrame: void 0, |
| | | }; |
| | | }, |
| | | watch: { |
| | | signModShow(newValue, oldValue) { |
| | | newValue ? this.canvasLeft = 74 : this.canvasLeft = 10000 |
| | | } |
| | | }, |
| | | props: { //可用于修改的参数放在props里 也可单独放在外面做成组件调用 传值 |
| | | action: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | canvasId: { |
| | | type: String, |
| | | default: 'canvasDr' |
| | | }, |
| | | canvasIds: { |
| | | type: String, |
| | | default: 'canvasRo' |
| | | }, |
| | | header: { |
| | | type: Object, |
| | | default: {} |
| | | }, |
| | | outSignWidth: { |
| | | type: Number, |
| | | default: 54 |
| | | }, |
| | | outSignHeight: { |
| | | type: Number, |
| | | default: 24 |
| | | }, |
| | | minSpeed: { //画笔最小速度 |
| | | type: Number, |
| | | default: 1.5 |
| | | }, |
| | | minWidth: { //线条最小粗度 |
| | | type: Number, |
| | | default: 3, |
| | | }, |
| | | maxWidth: { //线条最大粗度 |
| | | type: Number, |
| | | default: 10 |
| | | }, |
| | | openSmooth: { //开启平滑线条(笔锋) |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | maxHistoryLength: { //历史最大长度 |
| | | type: Number, |
| | | default: 20 |
| | | }, |
| | | maxWidthDiffRate: { //最大差异率 |
| | | type: Number, |
| | | default: 20 |
| | | }, |
| | | undoScan: { //撤销重新渲染偏移缩放校准 |
| | | type: Number, |
| | | default: 0.83 |
| | | }, |
| | | bgColor: { //背景色 |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | }, |
| | | mounted() { |
| | | if (!this.ctx) { |
| | | this.ctx = uni.createCanvasContext(this.canvasId, this); |
| | | } |
| | | if (!this.ctxs) { |
| | | this.ctxs = uni.createCanvasContext(this.canvasIds, this); |
| | | } |
| | | let that = this |
| | | this.$nextTick(() => { |
| | | uni.createSelectorQuery().in(this).select('.handCenter').boundingClientRect(rect => { |
| | | that.canvasWidth = rect.width; |
| | | that.canvasHeight = rect.height; |
| | | that.drawBgColor() |
| | | }) |
| | | .exec(); |
| | | }) |
| | | }, |
| | | methods: { |
| | | getPickerColor(color) { |
| | | this.showPickerColor = false; |
| | | if (color) { |
| | | this.lineColor = color; |
| | | } |
| | | }, |
| | | // 笔迹开始 |
| | | uploadScaleStart(e) { |
| | | this.canAddHistory = true |
| | | this.ctx.setStrokeStyle(this.lineColor) |
| | | this.ctx.setLineCap("round") //'butt'、'round'、'square' |
| | | }, |
| | | // 笔迹移动 |
| | | uploadScaleMove(e) { |
| | | let temX = e.changedTouches[0].x |
| | | let temY = e.changedTouches[0].y |
| | | this.initPoint(temX, temY) |
| | | this.onDraw() |
| | | }, |
| | | /** |
| | | * 触摸结束 |
| | | */ |
| | | uploadScaleEnd() { |
| | | this.canAddHistory = true; |
| | | this.points = []; |
| | | }, |
| | | /** |
| | | * 记录点属性 |
| | | */ |
| | | initPoint(x, y) { |
| | | var point = { |
| | | x: x, |
| | | y: y, |
| | | t: Date.now() |
| | | }; |
| | | var prePoint = this.points.slice(-1)[0]; |
| | | if (prePoint && (prePoint.t === point.t || prePoint.x === x && prePoint.y === y)) { |
| | | return; |
| | | } |
| | | if (prePoint && this.openSmooth) { |
| | | var prePoint2 = this.points.slice(-2, -1)[0]; |
| | | point.distance = Math.sqrt(Math.pow(point.x - prePoint.x, 2) + Math.pow(point.y - prePoint.y, 2)); |
| | | point.speed = point.distance / (point.t - prePoint.t || 0.1); |
| | | point.lineWidth = this.getLineWidth(point.speed); |
| | | if (prePoint2 && prePoint2.lineWidth && prePoint.lineWidth) { |
| | | var rate = (point.lineWidth - prePoint.lineWidth) / prePoint.lineWidth; |
| | | var maxRate = this.maxWidthDiffRate / 100; |
| | | maxRate = maxRate > 1 ? 1 : maxRate < 0.01 ? 0.01 : maxRate; |
| | | if (Math.abs(rate) > maxRate) { |
| | | var per = rate > 0 ? maxRate : -maxRate; |
| | | point.lineWidth = prePoint.lineWidth * (1 + per); |
| | | } |
| | | } |
| | | } |
| | | this.points.push(point); |
| | | this.points = this.points.slice(-3); |
| | | }, |
| | | /** |
| | | * @param {Object} |
| | | * 线宽 |
| | | */ |
| | | getLineWidth(speed) { |
| | | var minSpeed = this.minSpeed > 10 ? 10 : this.minSpeed < 1 ? 1 : this.minSpeed; //1.5 |
| | | var addWidth = (this.maxWidth - this.minWidth) * speed / minSpeed; |
| | | var lineWidth = Math.max(this.maxWidth - addWidth, this.minWidth); |
| | | return Math.min(lineWidth, this.maxWidth); |
| | | }, |
| | | /** |
| | | * 绘画逻辑 |
| | | */ |
| | | onDraw() { |
| | | if (this.points.length < 2) return; |
| | | this.addHistory(); |
| | | var point = this.points.slice(-1)[0]; |
| | | var prePoint = this.points.slice(-2, -1)[0]; |
| | | let that = this |
| | | var onDraw = function onDraw() { |
| | | if (that.openSmooth) { |
| | | that.drawSmoothLine(prePoint, point); |
| | | } else { |
| | | that.drawNoSmoothLine(prePoint, point); |
| | | } |
| | | }; |
| | | if (typeof this.requestAnimationFrame === 'function') { |
| | | this.requestAnimationFrame(function() { |
| | | return onDraw(); |
| | | }); |
| | | } else { |
| | | onDraw(); |
| | | } |
| | | }, |
| | | //添加历史图片地址 |
| | | addHistory() { |
| | | if (!this.maxHistoryLength || !this.canAddHistory) return; |
| | | this.canAddHistory = false; |
| | | if (!this.getImagePath) { |
| | | this.historyList.length++; |
| | | return; |
| | | } |
| | | //历史地址 (暂时无用) |
| | | let that = this |
| | | that.getImagePath().then(function(url) { |
| | | if (url) { |
| | | that.historyList.push(url) |
| | | that.historyList = that.historyList.slice(-that.maxHistoryLength); |
| | | } |
| | | }); |
| | | }, |
| | | //画平滑线 |
| | | drawSmoothLine(prePoint, point) { |
| | | var dis_x = point.x - prePoint.x; |
| | | var dis_y = point.y - prePoint.y; |
| | | |
| | | if (Math.abs(dis_x) + Math.abs(dis_y) <= 2) { |
| | | point.lastX1 = point.lastX2 = prePoint.x + dis_x * 0.5; |
| | | point.lastY1 = point.lastY2 = prePoint.y + dis_y * 0.5; |
| | | } else { |
| | | point.lastX1 = prePoint.x + dis_x * 0.3; |
| | | point.lastY1 = prePoint.y + dis_y * 0.3; |
| | | point.lastX2 = prePoint.x + dis_x * 0.7; |
| | | point.lastY2 = prePoint.y + dis_y * 0.7; |
| | | } |
| | | point.perLineWidth = (prePoint.lineWidth + point.lineWidth) / 2; |
| | | if (typeof prePoint.lastX1 === 'number') { |
| | | this.drawCurveLine(prePoint.lastX2, prePoint.lastY2, prePoint.x, prePoint.y, point.lastX1, point |
| | | .lastY1, point.perLineWidth); |
| | | if (prePoint.isFirstPoint) return; |
| | | if (prePoint.lastX1 === prePoint.lastX2 && prePoint.lastY1 === prePoint.lastY2) return; |
| | | var data = this.getRadianData(prePoint.lastX1, prePoint.lastY1, prePoint.lastX2, prePoint.lastY2); |
| | | var points1 = this.getRadianPoints(data, prePoint.lastX1, prePoint.lastY1, prePoint.perLineWidth / 2); |
| | | var points2 = this.getRadianPoints(data, prePoint.lastX2, prePoint.lastY2, point.perLineWidth / 2); |
| | | this.drawTrapezoid(points1[0], points2[0], points2[1], points1[1]); |
| | | } else { |
| | | point.isFirstPoint = true; |
| | | } |
| | | }, |
| | | //画不平滑线 |
| | | drawNoSmoothLine(prePoint, point) { |
| | | point.lastX = prePoint.x + (point.x - prePoint.x) * 0.5; |
| | | point.lastY = prePoint.y + (point.y - prePoint.y) * 0.5; |
| | | if (typeof prePoint.lastX === 'number') { |
| | | this.drawCurveLine(prePoint.lastX, prePoint.lastY, prePoint.x, prePoint.y, point.lastX, point.lastY, |
| | | this.maxWidth); |
| | | } |
| | | }, |
| | | //画线 |
| | | drawCurveLine(x1, y1, x2, y2, x3, y3, lineWidth) { |
| | | lineWidth = Number(lineWidth.toFixed(1)); |
| | | this.ctx.setLineWidth && this.ctx.setLineWidth(lineWidth); |
| | | this.ctx.lineWidth = lineWidth; |
| | | this.ctx.beginPath(); |
| | | this.ctx.moveTo(Number(x1.toFixed(1)), Number(y1.toFixed(1))); |
| | | this.ctx.quadraticCurveTo(Number(x2.toFixed(1)), Number(y2.toFixed(1)), Number(x3.toFixed(1)), Number(y3 |
| | | .toFixed(1))); |
| | | this.ctx.stroke(); |
| | | this.ctx.draw && this.ctx.draw(true); |
| | | }, |
| | | //画梯形 |
| | | drawTrapezoid(point1, point2, point3, point4) { |
| | | this.ctx.beginPath(); |
| | | this.ctx.moveTo(Number(point1.x.toFixed(1)), Number(point1.y.toFixed(1))); |
| | | this.ctx.lineTo(Number(point2.x.toFixed(1)), Number(point2.y.toFixed(1))); |
| | | this.ctx.lineTo(Number(point3.x.toFixed(1)), Number(point3.y.toFixed(1))); |
| | | this.ctx.lineTo(Number(point4.x.toFixed(1)), Number(point4.y.toFixed(1))); |
| | | this.ctx.setFillStyle && this.ctx.setFillStyle(this.lineColor); |
| | | this.ctx.fillStyle = this.lineColor; |
| | | this.ctx.fill(); |
| | | this.ctx.draw && this.ctx.draw(true); |
| | | }, |
| | | //获取弧度 |
| | | getRadianData(x1, y1, x2, y2) { |
| | | var dis_x = x2 - x1; |
| | | var dis_y = y2 - y1; |
| | | if (dis_x === 0) { |
| | | return { |
| | | val: 0, |
| | | pos: -1 |
| | | }; |
| | | } |
| | | if (dis_y === 0) { |
| | | return { |
| | | val: 0, |
| | | pos: 1 |
| | | }; |
| | | } |
| | | var val = Math.abs(Math.atan(dis_y / dis_x)); |
| | | if (x2 > x1 && y2 < y1 || x2 < x1 && y2 > y1) { |
| | | return { |
| | | val: val, |
| | | pos: 1 |
| | | }; |
| | | } |
| | | return { |
| | | val: val, |
| | | pos: -1 |
| | | }; |
| | | }, |
| | | //获取弧度点 |
| | | getRadianPoints(radianData, x, y, halfLineWidth) { |
| | | if (radianData.val === 0) { |
| | | if (radianData.pos === 1) { |
| | | return [{ |
| | | x: x, |
| | | y: y + halfLineWidth |
| | | }, { |
| | | x: x, |
| | | y: y - halfLineWidth |
| | | }]; |
| | | } |
| | | return [{ |
| | | y: y, |
| | | x: x + halfLineWidth |
| | | }, { |
| | | y: y, |
| | | x: x - halfLineWidth |
| | | }]; |
| | | } |
| | | var dis_x = Math.sin(radianData.val) * halfLineWidth; |
| | | var dis_y = Math.cos(radianData.val) * halfLineWidth; |
| | | if (radianData.pos === 1) { |
| | | return [{ |
| | | x: x + dis_x, |
| | | y: y + dis_y |
| | | }, { |
| | | x: x - dis_x, |
| | | y: y - dis_y |
| | | }]; |
| | | } |
| | | return [{ |
| | | x: x + dis_x, |
| | | y: y - dis_y |
| | | }, { |
| | | x: x - dis_x, |
| | | y: y + dis_y |
| | | }]; |
| | | }, |
| | | /** |
| | | * 背景色 |
| | | */ |
| | | drawBgColor() { |
| | | if (!this.bgColor) return; |
| | | this.ctx.setFillStyle && this.ctx.setFillStyle(this.bgColor); |
| | | this.ctx.fillStyle = this.bgColor; |
| | | this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); |
| | | this.ctx.draw && this.ctx.draw(true); |
| | | }, |
| | | //图片绘制 |
| | | drawByImage(url) { |
| | | this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
| | | try { |
| | | this.ctx.drawImage(url, 0, 0, this.canvasWidth * this.undoScan, this.canvasHeight * this.undoScan); |
| | | this.ctx.draw && this.ctx.draw(true); |
| | | } catch (e) { |
| | | this.historyList.length = 0; |
| | | } |
| | | }, |
| | | /** |
| | | * 清空 |
| | | */ |
| | | clear() { |
| | | this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
| | | this.ctx.draw && this.ctx.draw(); |
| | | this.drawBgColor(); |
| | | this.historyList.length = 0; |
| | | }, |
| | | //撤消 |
| | | undo() { |
| | | if (!this.getImagePath || !this.historyList.length) return; |
| | | var pngURL = this.historyList.splice(-1)[0]; |
| | | this.drawByImage(pngURL); |
| | | if (this.historyList.length === 0) { |
| | | this.clear(); |
| | | } |
| | | }, |
| | | //是否为空 |
| | | isEmpty() { |
| | | return this.historyList.length === 0; |
| | | }, |
| | | /** |
| | | * @param {Object} str |
| | | * @param {Object} color |
| | | * 选择颜色 |
| | | */ |
| | | selectColorEvent(str, color) { |
| | | this.selectColor = str; |
| | | this.lineColor = color; |
| | | this.ctx.setStrokeStyle(this.lineColor) |
| | | }, |
| | | |
| | | //完成 |
| | | subCanvas() { |
| | | let that = this |
| | | if (that.isEmpty()) { |
| | | that.emptyShow = true |
| | | setTimeout(function() { |
| | | that.emptyShow = false |
| | | }, 1000) |
| | | return |
| | | } |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: that.canvasId, |
| | | fileType: 'png', |
| | | quality: 1, //图片质量 |
| | | success(res) { |
| | | that.ctxs.translate(0, that.outSignHeight); |
| | | that.ctxs.rotate(-90 * Math.PI / 180) |
| | | that.ctxs.drawImage(res.tempFilePath, 0, 0, that.outSignHeight, that.outSignWidth) |
| | | that.ctxs.draw() |
| | | setTimeout(() => { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: that.canvasIds, |
| | | fileType: 'png', |
| | | quality: 1, //图片质量 |
| | | success: function(res1) { |
| | | if (that.action) { |
| | | uni.showLoading() |
| | | uni.uploadFile({ |
| | | url: that.action, //图片上传post请求的地址 |
| | | filePath: res1.tempFilePath, |
| | | name: "file", |
| | | header: that.header, |
| | | success: (uploadFileRes) => { |
| | | uni.hideLoading() |
| | | that.showImg = res1.tempFilePath |
| | | that.$emit('signToUrl', |
| | | uploadFileRes) |
| | | that.signModShow = false |
| | | that.clear() |
| | | }, |
| | | fail: (error) => { |
| | | uni.hideLoading() |
| | | } |
| | | }); |
| | | } else { |
| | | that.showImg = res1.tempFilePath |
| | | that.$emit('signToUrl', { |
| | | error_code: "201", |
| | | msg: "请配置上传文件接口参数action" |
| | | }) |
| | | that.signModShow = false |
| | | that.clear() |
| | | } |
| | | }, |
| | | fail: (err) => {} |
| | | }, that) |
| | | }, 200); |
| | | } |
| | | }, this); |
| | | }, |
| | | //保存到相册 |
| | | saveCanvasAsImg() { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: this.canvasId, |
| | | fileType: 'png', |
| | | quality: 1, //图片质量 |
| | | success(res) { |
| | | uni.saveImageToPhotosAlbum({ |
| | | filePath: res.tempFilePath, |
| | | success(res) { |
| | | uni.showToast({ |
| | | title: '已保存到相册', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | }, this); |
| | | }, |
| | | //预览 |
| | | previewCanvasImg() { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: this.canvasId, |
| | | fileType: 'jpg', |
| | | quality: 1, //图片质量 |
| | | success(res) { |
| | | uni.previewImage({ |
| | | urls: [res.tempFilePath] //预览图片 数组 |
| | | }); |
| | | } |
| | | }, this); |
| | | }, |
| | | deleteImg() { |
| | | this.showImg = "" |
| | | }, |
| | | |
| | | previewImg(img) { |
| | | uni.previewImage({ |
| | | urls: [img] //预览图片 数组 |
| | | }); |
| | | }, |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background: #d9d9d9; |
| | | height: auto; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .imgBox { |
| | | width: 140px; |
| | | height: 80px; |
| | | position: relative; |
| | | |
| | | .nom_img { |
| | | border-radius: 8px; |
| | | border: 1px dashed; |
| | | border-color: #a3a3a3; |
| | | overflow: hidden; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 80px; |
| | | width: 140px; |
| | | } |
| | | |
| | | .nom_img:hover { |
| | | border-color: #008ef6 !important; |
| | | } |
| | | |
| | | .across_img { |
| | | border: 1px dashed #a3a3a3; |
| | | border-radius: 8px; |
| | | height: 80px; |
| | | width: 140px; |
| | | |
| | | .delete_icon { |
| | | position: absolute; |
| | | top: -12px; |
| | | right: -12px; |
| | | width: 24px; |
| | | height: 24px; |
| | | overflow: hidden; |
| | | color: #ffffff; |
| | | font-size: 24px; |
| | | text-align: center; |
| | | line-height: 20px; |
| | | background: #ff3c0c; |
| | | border-radius: 25px; |
| | | z-index: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .warp { |
| | | width: 100%; |
| | | height: 100vh; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | .signBox { |
| | | width: 85vw; |
| | | height: 85vh; |
| | | background: #ffffff; |
| | | border-radius: 8px; |
| | | } |
| | | } |
| | | |
| | | .wrapper { |
| | | width: 85vw; |
| | | height: 85vh; |
| | | overflow: hidden; |
| | | display: flex; |
| | | align-content: center; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .handRight { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .handCenter { |
| | | position: fixed; |
| | | border: 4rpx dashed #e9e9e9; |
| | | flex: 5; |
| | | margin-top: 4rpx; |
| | | overflow: hidden; |
| | | box-sizing: border-box; |
| | | width: calc(100% - 84rpx - 200rpx); |
| | | height: calc(85vh - 8rpx) |
| | | } |
| | | |
| | | .handCenters { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 10000rpx; |
| | | flex: 5; |
| | | overflow: hidden; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | |
| | | .handTitle { |
| | | transform: rotate(90deg); |
| | | flex: 1; |
| | | color: #666; |
| | | } |
| | | |
| | | .handBtn button { |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .handBtn { |
| | | height: 85vh; |
| | | display: inline-flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | align-content: space-between; |
| | | flex: 1; |
| | | } |
| | | |
| | | .delBtn { |
| | | position: absolute; |
| | | top: 380rpx; |
| | | left: 46rpx; |
| | | transform: rotate(90deg); |
| | | color: #666; |
| | | } |
| | | |
| | | .subBtn { |
| | | position: absolute; |
| | | bottom: 158rpx; |
| | | left: 46rpx; |
| | | display: inline-flex; |
| | | transform: rotate(90deg); |
| | | background: #008ef6; |
| | | color: #fff; |
| | | text-align: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | /*Peach - 新增 - 保存*/ |
| | | |
| | | .saveBtn { |
| | | position: absolute; |
| | | top: 650rpx; |
| | | left: 46rpx; |
| | | transform: rotate(90deg); |
| | | color: #666; |
| | | } |
| | | |
| | | .previewBtn { |
| | | position: absolute; |
| | | top: 516rpx; |
| | | left: 46rpx; |
| | | transform: rotate(90deg); |
| | | color: #666; |
| | | } |
| | | |
| | | .undoBtn { |
| | | position: absolute; |
| | | top: 780rpx; |
| | | left: 46rpx; |
| | | transform: rotate(90deg); |
| | | color: #666; |
| | | } |
| | | |
| | | .emptyInfo { |
| | | position: absolute; |
| | | bottom: 418rpx; |
| | | left: -56rpx; |
| | | transform: rotate(90deg); |
| | | color: #666; |
| | | } |
| | | |
| | | .color_pic { |
| | | width: 70rpx; |
| | | height: 70rpx; |
| | | border-radius: 25px; |
| | | position: absolute; |
| | | top: 200rpx; |
| | | left: 62rpx; |
| | | border: 1px solid #ddd; |
| | | } |
| | | |
| | | /*Peach - 新增 - 保存*/ |
| | | |
| | | .black-select { |
| | | width: 60rpx; |
| | | height: 60rpx; |
| | | position: absolute; |
| | | top: 150rpx; |
| | | left: 70rpx; |
| | | } |
| | | |
| | | .red-select { |
| | | width: 60rpx; |
| | | height: 60rpx; |
| | | position: absolute; |
| | | top: 260rpx; |
| | | left: 70rpx; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view v-show="isShow"> |
| | | <view class="shade" @tap="hide"> |
| | | <view class="pop"> |
| | | <view class="list flex_col" v-for="(item,index) in colorArr" :key="index"> |
| | | <view v-for="(v,i) in item" :key="i" :style="{'backgroundColor':v}" :data-color="v" |
| | | :data-index="index" :data-i="i" :class="{'active':(index==pickerArr[0] && i==pickerArr[1])}" |
| | | @tap.stop="picker"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'picker-color', |
| | | props: { |
| | | isShow: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | bottom: { |
| | | type: Number, |
| | | default: 0, |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | colorArr: [ |
| | | ['#000000', '#111111', '#222222', '#333333', '#444444', '#666666', '#999999', '#CCCCCC', '#EEEEEE', |
| | | '#FFFFFF' |
| | | ], |
| | | ['#ff0000', '#ff0033', '#ff3399', '#ff33cc', '#cc00ff', '#9900ff', '#cc00cc', '#cc0099', '#cc3399', |
| | | '#cc0066' |
| | | ], |
| | | ['#cc3300', '#cc6600', '#ff9933', '#ff9966', '#ff9999', '#ff99cc', '#ff99ff', '#cc66ff', '#9966ff', |
| | | '#cc33ff' |
| | | ], |
| | | ['#663300', '#996600', '#996633', '#cc9900', '#a58800', '#cccc00', '#ffff66', '#ffff99', '#ffffcc', |
| | | '#ffcccc' |
| | | ], |
| | | ['#336600', '#669900', '#009900', '#009933', '#00cc00', '#66ff66', '#339933', '#339966', '#009999', |
| | | '#33cccc' |
| | | ], |
| | | ['#003366', '#336699', '#3366cc', '#0099ff', '#000099', '#0000cc', '#660066', '#993366', '#993333', |
| | | '#800000' |
| | | ] |
| | | ], |
| | | pickerColor: '', |
| | | pickerArr: [-1, -1] |
| | | }; |
| | | }, |
| | | methods: { |
| | | picker(e) { |
| | | let data = e.currentTarget.dataset; |
| | | this.pickerColor = data.color; |
| | | this.pickerArr = [data.index, data.i]; |
| | | this.$emit("callback", this.pickerColor); |
| | | }, |
| | | hide() { |
| | | this.$emit("callback", ''); |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .shade { |
| | | position: fixed; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | z-index: 10080; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center |
| | | } |
| | | |
| | | .pop { |
| | | border-radius: 8px; |
| | | background-color: #fff; |
| | | z-index: 100; |
| | | padding: 12upx; |
| | | font-size: 32upx; |
| | | transform: rotate(90deg); |
| | | } |
| | | |
| | | .flex_col { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: nowrap; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | align-content: center; |
| | | } |
| | | |
| | | .list { |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .list>view { |
| | | width: 60upx; |
| | | height: 60upx; |
| | | margin: 5upx; |
| | | box-sizing: border-box; |
| | | border-radius: 3px; |
| | | box-shadow: 0 0 2px #ccc; |
| | | } |
| | | |
| | | .list .active { |
| | | box-shadow: 0 0 2px #09f; |
| | | transform: scale(1.05, 1.05); |
| | | } |
| | | |
| | | .preview { |
| | | width: 180upx; |
| | | height: 60upx; |
| | | } |
| | | |
| | | .value { |
| | | margin: 0 40upx; |
| | | flex-grow: 1; |
| | | } |
| | | |
| | | .ok { |
| | | width: 160upx; |
| | | height: 60upx; |
| | | line-height: 60upx; |
| | | text-align: center; |
| | | background-color: #ff9933; |
| | | color: #fff; |
| | | border-radius: 4px; |
| | | letter-spacing: 3px; |
| | | font-size: 32upx; |
| | | } |
| | | |
| | | .ok:active { |
| | | background-color: rgb(255, 107, 34); |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="u-mask" hover-stop-propagation :style="[maskStyle, zoomStyle]" @tap="click" |
| | | @touchmove.stop.prevent="() => {}" :class="{ |
| | | 'u-mask-zoom': zoom, |
| | | 'u-mask-show': show |
| | | }"> |
| | | <slot /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * mask 遮罩 |
| | | * @description 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景 |
| | | * @tutorial https://www.uviewui.com/components/mask.html |
| | | * @property {Boolean} show 是否显示遮罩(默认false) |
| | | * @property {String Number} z-index z-index 层级(默认1070) |
| | | * @property {Object} custom-style 自定义样式对象,见上方说明 |
| | | * @property {String Number} duration 动画时长,单位毫秒(默认300) |
| | | * @property {Boolean} zoom 是否使用scale对遮罩进行缩放(默认true) |
| | | * @property {Boolean} mask-click-able 遮罩是否可点击,为false时点击不会发送click事件(默认true) |
| | | * @event {Function} click mask-click-able为true时,点击遮罩发送此事件 |
| | | * @example <u-mask :show="show" @click="show = false"></u-mask> |
| | | */ |
| | | export default { |
| | | name: "u-mask", |
| | | props: { |
| | | // 是否显示遮罩 |
| | | show: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // 层级z-index |
| | | zIndex: { |
| | | type: [Number, String], |
| | | default: '10070' |
| | | }, |
| | | // 用户自定义样式 |
| | | customStyle: { |
| | | type: Object, |
| | | default () { |
| | | return {} |
| | | } |
| | | }, |
| | | // 遮罩的动画样式, 是否使用使用zoom进行scale进行缩放 |
| | | zoom: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // 遮罩的过渡时间,单位为ms |
| | | duration: { |
| | | type: [Number, String], |
| | | default: 300 |
| | | }, |
| | | // 是否可以通过点击遮罩进行关闭 |
| | | maskClickAble: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | zoomStyle: { |
| | | transform: '' |
| | | }, |
| | | scale: 'scale(1.2, 1.2)' |
| | | } |
| | | }, |
| | | watch: { |
| | | show(n) { |
| | | if (n && this.zoom) { |
| | | // 当展示遮罩的时候,设置scale为1,达到缩小(原来为1.2)的效果 |
| | | this.zoomStyle.transform = 'scale(1, 1)'; |
| | | } else if (!n && this.zoom) { |
| | | // 当隐藏遮罩的时候,设置scale为1.2,达到放大(因为显示遮罩时已重置为1)的效果 |
| | | this.zoomStyle.transform = this.scale; |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | maskStyle() { |
| | | let style = {}; |
| | | style.backgroundColor = "rgba(0, 0, 0, 0.6)"; |
| | | if (this.show) style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.mask; |
| | | else style.zIndex = -1; |
| | | style.transition = `all ${this.duration / 1000}s ease-in-out`; |
| | | // 判断用户传递的对象是否为空,不为空就进行合并 |
| | | if (Object.keys(this.customStyle).length) style = { |
| | | ...style, |
| | | ...this.customStyle |
| | | }; |
| | | return style; |
| | | } |
| | | }, |
| | | methods: { |
| | | click() { |
| | | if (!this.maskClickAble) return; |
| | | this.$emit('click'); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | // @import "../../libs/css/style.components.scss"; |
| | | |
| | | .u-mask { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | opacity: 0; |
| | | transition: transform 0.3s; |
| | | } |
| | | |
| | | .u-mask-show { |
| | | opacity: 1; |
| | | } |
| | | |
| | | .u-mask-zoom { |
| | | transform: scale(1.2, 1.2); |
| | | } |
| | | </style> |
| | |
| | | "navigationBarBackgroundColor": "#fff", |
| | | "navigationBarTextStyle": "black" |
| | | } |
| | | }, |
| | | { |
| | | "path": "signature", |
| | | "style": { |
| | | "navigationBarTitleText": "签名", |
| | | "enablePullDownRefresh": false, |
| | | "navigationBarBackgroundColor": "#fff", |
| | | "navigationBarTextStyle": "black" |
| | | } |
| | | } |
| | | |
| | | ] |
| | |
| | | "pages": [{ |
| | | "path": "index", |
| | | "style": { |
| | | "navigationBarTitleText": "标签事件", |
| | | "navigationBarTitleText": "标签报事", |
| | | "enablePullDownRefresh": false, |
| | | "navigationBarBackgroundColor": "#4586fe", |
| | | "navigationBarTextStyle": "white", |
| | | "navigationStyle": "custom" |
| | | "navigationBarTextStyle": "white" |
| | | // "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | |
| | | { |
| | | "path": "views/repair", |
| | | "style": { |
| | | "navigationBarTitleText": "报事报修", |
| | | "navigationBarBackgroundColor": "#fff", |
| | | "navigationBarTextStyle": "black", |
| | | "enablePullDownRefresh": false, |
| | | "navigationStyle": "custom" |
| | | "navigationBarTitleText": "公共报事", |
| | | "navigationBarBackgroundColor": "#4586fe", |
| | | "navigationBarTextStyle": "white", |
| | | "enablePullDownRefresh": false |
| | | // "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | |
| | | addressCode:code
|
| | | }).then(res=>{
|
| | | console.log(res)
|
| | | if(res.data.doorplateType == "户室牌"){
|
| | | this.$u.func.globalNavigator(`/subPackage/house/roomDetails/index?id=${code}`,"navTo")
|
| | | }else if (res.data.addressLevel == 4){
|
| | | let { doorplateType, addressLevel,aoiName,addressName,neiName } = res.data;
|
| | | if(doorplateType == "户室牌"){
|
| | | this.$u.func.globalNavigator(`/subPackage/house/roomDetails/index?id=${code}&from=scan`,"navTo")
|
| | | }else if (addressLevel == 4){
|
| | | this.$u.func.globalNavigator(
|
| | | `/subPackage/house/houseNumber/index?stdId=${code}`, "navTo")
|
| | | }else if (doorplateType == "楼幢牌"){
|
| | | let url = "/subPackage/house/family/index"
|
| | | this.$u.func.globalNavigator(`${url}?id=${code}&address=${addressName}&neiName=${neiName}&aoiName=${aoiName}`,"navTo")
|
| | | }else if (doorplateType =="大门牌"){
|
| | | this.$u.func.globalNavigator(`/subPackage/house/list/index?id=${code}&title=${aoiName}`,"navTo")
|
| | | }
|
| | | })
|
| | | }) |
| | | }
|
| | | }
|
| | | }
|
| | |
| | | <u-cell title="修改密码" :border="false" isLink url="/subPackage/user/password/index"> |
| | | <image slot="icon" src="/static/icon/menu-center-03.png" class="icon" mode=""></image> |
| | | </u-cell> |
| | | <u-cell title="签名" :border="false" isLink url="/subPackage/article/signature"> |
| | | <image slot="icon" src="/static/icon/menu-center-03.png" class="icon" mode=""></image> |
| | | </u-cell> |
| | | <!-- <u-cell-item title="评分"> |
| | | <image slot="icon" src="/static/images/user/c5.png" class="icon" mode=""></image> |
| | | </u-cell-item> |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <jushi-signature :settings="settings" @change="signatureChange"></jushi-signature> |
| | | <view class="" style="margin-top: 20rpx;"> |
| | | <text class="text">保存后的签名图片</text> |
| | | <view class="preview"> |
| | | <image :src="imgUrl" mode="" style="width: 100%;"></image> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | settings:{ //签名设置 |
| | | width: '750',//签名区域的宽 |
| | | height: '500',//签名区域的高 |
| | | lineWidth:3,//签名时线宽 |
| | | textColor:'#007AFF' //签名文字颜色 |
| | | }, |
| | | imgUrl: '' |
| | | } |
| | | }, |
| | | methods: { |
| | | signatureChange(e) { |
| | | this.imgUrl = e |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .preview{ |
| | | margin: 10rpx; |
| | | border: 1rpx solid #aaaaaa; |
| | | border-radius: 10rpx; |
| | | } |
| | | .text { |
| | | margin: 20rpx; |
| | | color: #aaaaaa; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class=""> |
| | | <u-navbar height="48" :autoBack="true" safeAreaInsetTop placeholder bgColor="transparent" leftIconColor="#fff"> |
| | | </u-navbar> |
| | | <!-- <u-navbar height="48" :autoBack="true" safeAreaInsetTop placeholder bgColor="transparent" leftIconColor="#fff"> |
| | | </u-navbar> --> |
| | | <view class="top"> |
| | | <image class="top-img" src="/static/img/repair-bg.png" mode="aspectFill"></image> |
| | | </view> |
| | |
| | | padding: 0 30rpx; |
| | | position: fixed; |
| | | box-sizing: border-box; |
| | | top: 130rpx; |
| | | top: 40rpx; |
| | | left: 0; |
| | | z-index: 100; |
| | | |
| | |
| | | <template>
|
| | | <view class="container">
|
| | | <view class="flex f-d-c main">
|
| | | <view class="cur-header">
|
| | | <view class="cur-header" v-if="!addressName">
|
| | | <u-icon name="/static/icon/map.png" width="15" height="18"></u-icon>
|
| | | <view>{{ curSelectSite.name }}/{{housingName}}{{buildingName}}</view>
|
| | | </view>
|
| | | <block v-if="addressName">
|
| | | <view class="cur-header">
|
| | | <u-icon name="/static/icon/map.png" width="15" height="18"></u-icon>
|
| | | <view>{{housingName}}/{{buildingName}}</view>
|
| | | </view>
|
| | | <view class="house-address f-26 bgc-ff" >
|
| | | {{addressName}}
|
| | | </view>
|
| | | </block>
|
| | | <view class="h0 flex-1 build-list-box content">
|
| | | <u-collapse :value="buildingList.length == 1?['0']:''">
|
| | | <u-collapse-item v-if="isShowBuild" style="border: none;" :name="index" :title="item.unitName"
|
| | |
| | | <view class="room-content">
|
| | | <view class="flex flex-wrap j-c-s-b" style="width: 100%;">
|
| | | <view class="room-box flex f-d-c" v-for="(scItem, scIndex) in cItem.children"
|
| | | :key="scItem.id" @click="pushPage" :data-code="scItem.addressCode">
|
| | | :key="scItem.id" @click="pushPage" :data-code="scItem.addressCode" :data-unit="item.unitName">
|
| | | <view class="flex a-i-c j-c-s-b">
|
| | | <!-- <view class="l">
|
| | | <u-icon name="/static/icon/person.png" size="16"></u-icon>
|
| | |
| | | neiCode: "",
|
| | | buildingList: [],
|
| | | shopList: [],
|
| | | curSelectSite: {}
|
| | | curSelectSite: {},
|
| | | addressName:""
|
| | | }
|
| | | },
|
| | | onLoad(e) {
|
| | |
| | | this.currentId = id
|
| | | this.housingName = housingName
|
| | | this.buildingName = buildingName
|
| | | this.addressType = addressType
|
| | | if(addressType){
|
| | | this.addressType = addressType
|
| | | }
|
| | | |
| | | this.neiCode = neiCode
|
| | | if(e.address){
|
| | | this.addressName = e.address;
|
| | | this.housingName = e.neiName;
|
| | | this.buildingName = e.aoiName
|
| | | }
|
| | |
|
| | | },
|
| | | onShow() {
|
| | |
| | | }
|
| | | },
|
| | | pushPage(e) {
|
| | | let url = `/subPackage/house/roomDetails/index?id=${e.currentTarget.dataset.code}`
|
| | | let { code,unit } = e.currentTarget.dataset;
|
| | | let url = `/subPackage/house/roomDetails/index?id=${code}&unit=${unit}`
|
| | | this.$u.func.globalNavigator(url, "navTo")
|
| | | },
|
| | | // 跳转到商铺页面
|
| | |
| | | /deep/ .u-cell__body {
|
| | | background-color: rgb(236, 244, 255);
|
| | | }
|
| | | |
| | | .house-address{
|
| | | padding:20rpx;
|
| | | |
| | | }
|
| | | </style> |
| | |
| | | <u-icon name="/static/icon/map.png" width="15" height="18"></u-icon>
|
| | | <text>{{ curSelectSite.name }}/{{ curHouseTitle }}</text>
|
| | | </view>
|
| | | |
| | | <view class="flex f-d-c main">
|
| | | <view class="flex house-container">
|
| | | <view class="house-list-box" v-if="isShowAoi" v-for="(item, index) in houseList"
|
| | |
| | | const {
|
| | | id,
|
| | | title,
|
| | | addressType
|
| | | } = e
|
| | | this.currentId = id
|
| | | this.curHouseTitle = title
|
| | | this.addressType = addressType
|
| | | if(e.addressType){
|
| | | this.addressType = e.addressType
|
| | | }
|
| | | |
| | |
|
| | | },
|
| | | onShow() {
|
| | |
| | | {{ houseInfo.houseTitle }}
|
| | | </view>
|
| | | </view>
|
| | | |
| | | <view class="house-address f-26" v-if="from">
|
| | | {{houseInfo.addressName}}
|
| | | </view>
|
| | | |
| | | <view class="flex j-c-s-b info-content">
|
| | | <view class="house-info">
|
| | | <text v-if="houseInfo.unitName != null">{{ houseInfo.unitName }}单元</text>
|
| | | {{ houseInfo.houseName }}室
|
| | | <text>(共{{ houseInfo.allNum }}人)</text>
|
| | | <text> {{houseInfo.buildingName}} {{houseInfo.unitName?houseInfo.unitName:"一单元"}} {{ houseInfo.houseName }}室 </text>
|
| | | <text class="c-aa">(共{{ houseInfo.allNum }}人)</text>
|
| | | </view>
|
| | | <view class="flex a-i-c">
|
| | | <u-button @click="rommManage" size='small' type="primary" class="u_btn_blue"
|
| | |
| | | </view>
|
| | | <view class="flex">
|
| | | 关系:
|
| | | <view class="flex a-i-c">
|
| | | <view class="flex a-i-c" v-if="item.roleRelationName">
|
| | | <u-tag :text="item.roleRelationName" size="mini"
|
| | | :borderColor="item.relationship == 1 ? '#F2BF42' : '#1989FA'"
|
| | | :bgColor="item.relationship == 1 ? '#F2BF42' : '#1989FA'"></u-tag>
|
| | |
| | | unitName: '',
|
| | | houseTitle: '',
|
| | | // 人员数量
|
| | | allNum: 0
|
| | | allNum: 0,
|
| | | buildingName:""
|
| | | },
|
| | | ownerInfoList: [],
|
| | | rentOutList: [],
|
| | |
| | | value: 2
|
| | | },
|
| | | ],
|
| | | currentTime: null
|
| | | currentTime: null,
|
| | | unitName:"",
|
| | | from:""
|
| | | }
|
| | | },
|
| | | onLoad(e) {
|
| | | if(e.id){
|
| | | const {
|
| | | id
|
| | | id,
|
| | | unit
|
| | | } = e
|
| | | this.currentId = id
|
| | | this.currentId = id;
|
| | | this.unitName = unit;
|
| | | }else {
|
| | | this.currentId = uni.getStorageSync("siteInfo").houseCode
|
| | | }
|
| | | |
| | | if(e.from){
|
| | | this.from = e.from;
|
| | | }
|
| | | |
| | | |
| | | },
|
| | | onShow() {
|
| | | this.getHouseRentInfoList()
|
| | |
| | | unitName,
|
| | | houseRentalList,
|
| | | householdList,
|
| | | subAoi
|
| | | subAoi,
|
| | | addressName
|
| | | } = res.data
|
| | | this.houseCode = addressCode
|
| | | this.rentOutList = houseRentalList
|
| | |
| | | this.houseInfo.houseName = houseName
|
| | | this.houseInfo.unitName = unitName
|
| | | this.houseInfo.houseTitle = aoiName || subAoi
|
| | | this.houseInfo.buildingName = buildingName
|
| | | this.houseInfo.addressName = addressName
|
| | | // 判断当前租客有没有过期
|
| | | this.rentOutList.forEach(item => {
|
| | | // 事件格式处理
|
| | |
| | |
|
| | | .house-info {
|
| | | font-weight: 700;
|
| | |
|
| | | text {
|
| | | .c-aa{
|
| | | color: #AAAAAA;
|
| | | }
|
| | | }
|
| | |
| | | border: 0;
|
| | | }
|
| | | }
|
| | | .house-address{
|
| | | padding:10rpx 0;
|
| | | border-bottom: 1rpx solid #f6f6f6;
|
| | | }
|
| | | </style> |
| | |
| | | <template> |
| | | <view class=""> |
| | | <u-navbar height="48" :autoBack="true" safeAreaInsetTop placeholder bgColor="transparent" leftIconColor="#fff"> |
| | | </u-navbar> |
| | | <!-- <u-navbar height="48" :autoBack="true" safeAreaInsetTop placeholder bgColor="transparent" leftIconColor="#fff"> |
| | | </u-navbar> --> |
| | | <view class="top"> |
| | | <image class="top-img" src="/static/img/repair-bg.png" mode="aspectFill"></image> |
| | | </view> |
| | |
| | | padding: 0 30rpx; |
| | | position: fixed; |
| | | box-sizing: border-box; |
| | | top:130rpx; |
| | | top:40rpx; |
| | | left:0; |
| | | z-index: 100; |
| | | .serve-box{ |
| New file |
| | |
| | | ## 1.0.1(2023-09-12) |
| | | 增加组件属性 base64,该属性用于设置返回的结果是图片base64还是临时地址,默认为图片临时地址 |
| | | ## 1.0.0(2023-08-16) |
| | | 手写签名、电子签名组件首次提交发布 |
| New file |
| | |
| | | # image-tools |
| | | 图像转换工具,可用于如下环境:uni-app、微信小程序、5+APP、浏览器(需允许跨域) |
| | | |
| | | ## 使用方式 |
| | | |
| | | ### NPM |
| | | |
| | | ``` |
| | | npm i image-tools --save |
| | | ``` |
| | | |
| | | ```js |
| | | import { pathToBase64, base64ToPath } from 'image-tools' |
| | | ``` |
| | | |
| | | ### 直接下载 |
| | | |
| | | ```js |
| | | // 以下路径需根据项目实际情况填写 |
| | | import { pathToBase64, base64ToPath } from '../../js/image-tools/index.js' |
| | | ``` |
| | | |
| | | ## API |
| | | |
| | | ### pathToBase64 |
| | | |
| | | 从图像路径转换为base64,uni-app、微信小程序和5+APP使用的路径不支持网络路径,如果是网络路径需要先使用下载API下载下来。 |
| | | |
| | | ```js |
| | | pathToBase64(path) |
| | | .then(base64 => { |
| | | console.log(base64) |
| | | }) |
| | | .catch(error => { |
| | | console.error(error) |
| | | }) |
| | | ``` |
| | | |
| | | ### base64ToPath |
| | | |
| | | 将图像base64保存为文件,返回文件路径。 |
| | | |
| | | ```js |
| | | base64ToPath(base64) |
| | | .then(path => { |
| | | console.log(path) |
| | | }) |
| | | .catch(error => { |
| | | console.error(error) |
| | | }) |
| | | ``` |
| | | |
| | | ## 提示 |
| | | |
| | | 可以利用promise来串行和并行的执行多个任务 |
| | | |
| | | ```js |
| | | // 并行 |
| | | Promise.all(paths.map(path => pathToBase64(path))) |
| | | .then(res => { |
| | | console.log(res) |
| | | // [base64, base64...] |
| | | }) |
| | | .catch(error => { |
| | | console.error(error) |
| | | }) |
| | | // 串行 |
| | | paths.reduce((promise, path) => promise.then(res => pathToBase64(path).then(base64 => (res.push(base64), res))), Promise.resolve([])) |
| | | .then(res => { |
| | | console.log(res) |
| | | // [base64, base64...] |
| | | }) |
| | | .catch(error => { |
| | | console.error(error) |
| | | }) |
| | | ``` |
| New file |
| | |
| | | function getLocalFilePath(path) { |
| | | if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) { |
| | | return path |
| | | } |
| | | if (path.indexOf('file://') === 0) { |
| | | return path |
| | | } |
| | | if (path.indexOf('/storage/emulated/0/') === 0) { |
| | | return path |
| | | } |
| | | if (path.indexOf('/') === 0) { |
| | | var localFilePath = plus.io.convertAbsoluteFileSystem(path) |
| | | if (localFilePath !== path) { |
| | | return localFilePath |
| | | } else { |
| | | path = path.substr(1) |
| | | } |
| | | } |
| | | return '_www/' + path |
| | | } |
| | | |
| | | function dataUrlToBase64(str) { |
| | | var array = str.split(',') |
| | | return array[array.length - 1] |
| | | } |
| | | |
| | | var index = 0 |
| | | function getNewFileId() { |
| | | return Date.now() + String(index++) |
| | | } |
| | | |
| | | function biggerThan(v1, v2) { |
| | | var v1Array = v1.split('.') |
| | | var v2Array = v2.split('.') |
| | | var update = false |
| | | for (var index = 0; index < v2Array.length; index++) { |
| | | var diff = v1Array[index] - v2Array[index] |
| | | if (diff !== 0) { |
| | | update = diff > 0 |
| | | break |
| | | } |
| | | } |
| | | return update |
| | | } |
| | | |
| | | export function pathToBase64(path) { |
| | | return new Promise(function(resolve, reject) { |
| | | if (typeof window === 'object' && 'document' in window) { |
| | | if (typeof FileReader === 'function') { |
| | | var xhr = new XMLHttpRequest() |
| | | xhr.open('GET', path, true) |
| | | xhr.responseType = 'blob' |
| | | xhr.onload = function() { |
| | | if (this.status === 200) { |
| | | let fileReader = new FileReader() |
| | | fileReader.onload = function(e) { |
| | | resolve(e.target.result) |
| | | } |
| | | fileReader.onerror = reject |
| | | fileReader.readAsDataURL(this.response) |
| | | } |
| | | } |
| | | xhr.onerror = reject |
| | | xhr.send() |
| | | return |
| | | } |
| | | var canvas = document.createElement('canvas') |
| | | var c2x = canvas.getContext('2d') |
| | | var img = new Image |
| | | img.onload = function() { |
| | | canvas.width = img.width |
| | | canvas.height = img.height |
| | | c2x.drawImage(img, 0, 0) |
| | | resolve(canvas.toDataURL()) |
| | | canvas.height = canvas.width = 0 |
| | | } |
| | | img.onerror = reject |
| | | img.src = path |
| | | return |
| | | } |
| | | if (typeof plus === 'object') { |
| | | plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) { |
| | | entry.file(function(file) { |
| | | var fileReader = new plus.io.FileReader() |
| | | fileReader.onload = function(data) { |
| | | resolve(data.target.result) |
| | | } |
| | | fileReader.onerror = function(error) { |
| | | reject(error) |
| | | } |
| | | fileReader.readAsDataURL(file) |
| | | }, function(error) { |
| | | reject(error) |
| | | }) |
| | | }, function(error) { |
| | | reject(error) |
| | | }) |
| | | return |
| | | } |
| | | if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) { |
| | | wx.getFileSystemManager().readFile({ |
| | | filePath: path, |
| | | encoding: 'base64', |
| | | success: function(res) { |
| | | resolve('data:image/png;base64,' + res.data) |
| | | }, |
| | | fail: function(error) { |
| | | reject(error) |
| | | } |
| | | }) |
| | | return |
| | | } |
| | | reject(new Error('not support')) |
| | | }) |
| | | } |
| | | |
| | | export function base64ToPath(base64) { |
| | | return new Promise(function(resolve, reject) { |
| | | if (typeof window === 'object' && 'document' in window) { |
| | | base64 = base64.split(',') |
| | | var type = base64[0].match(/:(.*?);/)[1] |
| | | var str = atob(base64[1]) |
| | | var n = str.length |
| | | var array = new Uint8Array(n) |
| | | while (n--) { |
| | | array[n] = str.charCodeAt(n) |
| | | } |
| | | return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type }))) |
| | | } |
| | | var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/) |
| | | if (extName) { |
| | | extName = extName[1] |
| | | } else { |
| | | reject(new Error('base64 error')) |
| | | } |
| | | var fileName = getNewFileId() + '.' + extName |
| | | if (typeof plus === 'object') { |
| | | var basePath = '_doc' |
| | | var dirPath = 'uniapp_temp' |
| | | var filePath = basePath + '/' + dirPath + '/' + fileName |
| | | if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) { |
| | | plus.io.resolveLocalFileSystemURL(basePath, function(entry) { |
| | | entry.getDirectory(dirPath, { |
| | | create: true, |
| | | exclusive: false, |
| | | }, function(entry) { |
| | | entry.getFile(fileName, { |
| | | create: true, |
| | | exclusive: false, |
| | | }, function(entry) { |
| | | entry.createWriter(function(writer) { |
| | | writer.onwrite = function() { |
| | | resolve(filePath) |
| | | } |
| | | writer.onerror = reject |
| | | writer.seek(0) |
| | | writer.writeAsBinary(dataUrlToBase64(base64)) |
| | | }, reject) |
| | | }, reject) |
| | | }, reject) |
| | | }, reject) |
| | | return |
| | | } |
| | | var bitmap = new plus.nativeObj.Bitmap(fileName) |
| | | bitmap.loadBase64Data(base64, function() { |
| | | bitmap.save(filePath, {}, function() { |
| | | bitmap.clear() |
| | | resolve(filePath) |
| | | }, function(error) { |
| | | bitmap.clear() |
| | | reject(error) |
| | | }) |
| | | }, function(error) { |
| | | bitmap.clear() |
| | | reject(error) |
| | | }) |
| | | return |
| | | } |
| | | if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) { |
| | | var filePath = wx.env.USER_DATA_PATH + '/' + fileName |
| | | wx.getFileSystemManager().writeFile({ |
| | | filePath: filePath, |
| | | data: dataUrlToBase64(base64), |
| | | encoding: 'base64', |
| | | success: function() { |
| | | resolve(filePath) |
| | | }, |
| | | fail: function(error) { |
| | | reject(error) |
| | | } |
| | | }) |
| | | return |
| | | } |
| | | reject(new Error('not support')) |
| | | }) |
| | | } |
| New file |
| | |
| | | { |
| | | "name": "image-tools", |
| | | "version": "1.4.0", |
| | | "description": "图像转换工具,可用于如下环境:uni-app、微信小程序、5+APP、浏览器", |
| | | "main": "index.js", |
| | | "scripts": { |
| | | "test": "echo \"Error: no test specified\" && exit 1" |
| | | }, |
| | | "repository": { |
| | | "type": "git", |
| | | "url": "git+https://github.com/zhetengbiji/image-tools.git" |
| | | }, |
| | | "keywords": [ |
| | | "base64" |
| | | ], |
| | | "author": "Shengqiang Guo", |
| | | "license": "ISC", |
| | | "bugs": { |
| | | "url": "https://github.com/zhetengbiji/image-tools/issues" |
| | | }, |
| | | "homepage": "https://github.com/zhetengbiji/image-tools#readme", |
| | | "devDependencies": { |
| | | "@types/html5plus": "^1.0.0" |
| | | } |
| | | } |
| New file |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <view class="center" id="center"> |
| | | <text class="sign-area">签名区域</text> |
| | | <canvas canvas-id="jushiSignature" :style="{width:`${settings.width}rpx`,height:`${settings.height}rpx`}" |
| | | disable-scroll="true" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas> |
| | | </view> |
| | | <view class="btn-view"> |
| | | <view class="save" @click="save()">保存</view> |
| | | <view class="clear" @click="clear()">清除</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | pathToBase64, |
| | | base64ToPath |
| | | } from '../image-tools/index.js' |
| | | var ctx = null |
| | | var tempPoint = [] //存放当前画纸上的轨迹点 |
| | | export default { |
| | | props: { |
| | | settings: { //签名设置 |
| | | type: Object, |
| | | default: () => { |
| | | return { |
| | | width: '750', //签名区域的宽 |
| | | height: '500', //签名区域的高 |
| | | lineWidth: 4, //签名时线宽 |
| | | textColor: '#000000' //签名文字颜色 |
| | | } |
| | | } |
| | | }, |
| | | base64: { //是否强制返回base64 |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | points: [], //路径点 |
| | | canvasWidth: 0, |
| | | canvasHeight: 0 |
| | | }; |
| | | }, |
| | | created() { |
| | | //微信小程序 需传第二个参数 this才生效 |
| | | ctx = uni.createCanvasContext('jushiSignature', this) |
| | | this.setPaintStyle() |
| | | }, |
| | | onReady() { |
| | | // #ifdef MP-WEIXIN |
| | | const query = uni.createSelectorQuery().in(this); |
| | | query.select('#center').boundingClientRect(data => { |
| | | this.canvasWidth = data.width |
| | | this.canvasHeight = data.height |
| | | this.setCanvasBg() |
| | | }).exec(); |
| | | // #endif |
| | | }, |
| | | methods: { |
| | | setPaintStyle() { //画笔样式 |
| | | ctx.lineWidth = this.settings.lineWidth |
| | | ctx.lineCap = "round" |
| | | ctx.lineJoin = "round" |
| | | ctx.setStrokeStyle(this.settings.textColor) |
| | | }, |
| | | touchstart(e) { |
| | | const startX = e.changedTouches[0].x |
| | | const startY = e.changedTouches[0].y |
| | | let startPoint = { |
| | | X: startX, |
| | | Y: startY |
| | | } |
| | | this.points.push(startPoint) |
| | | //每次触摸开始,开启新的路径 |
| | | ctx.beginPath() |
| | | }, |
| | | touchmove(e) { |
| | | let moveX = e.changedTouches[0].x |
| | | let moveY = e.changedTouches[0].y |
| | | let movePoint = { |
| | | X: moveX, |
| | | Y: moveY |
| | | } |
| | | this.points.push(movePoint); //存点 |
| | | if (this.points.length >= 2) { |
| | | this.draw() //绘制路径 |
| | | } |
| | | tempPoint.push(movePoint) |
| | | }, |
| | | touchend() { // 清空未绘制的点避免对后续路径产生干扰 |
| | | this.points = [] |
| | | }, |
| | | /* |
| | | * 绘制笔迹 |
| | | * 1.移动的同时绘制笔迹,保证实时显示 |
| | | * 2.从路径中取两个点作为起点(moveTo)和终点(lineTo)保证笔迹连续性 |
| | | * 3.把上一次的终点作为下一次绘制的起点(即清除第一个点) |
| | | * */ |
| | | draw() { |
| | | let p1 = this.points[0] |
| | | let p2 = this.points[1] |
| | | this.points.shift() |
| | | ctx.moveTo(p1.X, p1.Y) |
| | | ctx.lineTo(p2.X, p2.Y) |
| | | ctx.stroke() |
| | | ctx.draw(true) |
| | | }, |
| | | clear() { //清空画布 |
| | | let that = this |
| | | uni.getSystemInfo({ |
| | | success: function(res) { |
| | | ctx.clearRect(0, 0, res.windowWidth, res.windowHeight) |
| | | ctx.draw(true) |
| | | // #ifdef MP-WEIXIN |
| | | that.setCanvasBg() |
| | | // #endif |
| | | that.setPaintStyle() |
| | | }, |
| | | }) |
| | | tempPoint = [] |
| | | that.emit('') |
| | | }, |
| | | save() { //保存 |
| | | let that = this |
| | | if (tempPoint.length == 0) { |
| | | uni.showToast({ |
| | | title: '您还未签名,请先签名', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return |
| | | } |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: 'jushiSignature', |
| | | fileType: 'jpg', |
| | | quality: 1, |
| | | success: function(res) { |
| | | //强制返回base64 |
| | | if (that.base64) { |
| | | if (res.tempFilePath.startsWith('data:image/jpeg;base64')) { |
| | | that.emit(res.tempFilePath) |
| | | } else { |
| | | pathToBase64(res.tempFilePath).then(e => { |
| | | that.emit(e) |
| | | }).catch(e => { |
| | | console.log(JSON.stringify(e)) |
| | | }) |
| | | } |
| | | } else { |
| | | if (res.tempFilePath.startsWith('data:image/jpeg;base64')) { |
| | | base64ToPath(res.tempFilePath).then(e => { |
| | | that.emit(e) |
| | | }).catch(e => { |
| | | console.log(JSON.stringify(e)) |
| | | }) |
| | | } else { |
| | | that.emit(res.tempFilePath) |
| | | } |
| | | } |
| | | }, |
| | | fail(e) { |
| | | console.log(JSON.stringify(e)) |
| | | } |
| | | }, this) |
| | | }, |
| | | emit(tempFilePath) { |
| | | this.$emit('change', tempFilePath) |
| | | }, |
| | | setCanvasBg() { //设置canvas背景色 不设置 导出的canvas的背景为黑色 |
| | | ctx.rect(0, 0, this.canvasWidth, this.canvasHeight) |
| | | ctx.setFillStyle('#ffffff') |
| | | ctx.fill() |
| | | ctx.draw() |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .center { |
| | | background-color: #ffffff; |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: relative; |
| | | } |
| | | |
| | | .btn-view { |
| | | margin-top: 20rpx; |
| | | font-size: 14px; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | } |
| | | |
| | | .save, |
| | | .clear { |
| | | height: 70rpx; |
| | | width: 200rpx; |
| | | text-align: center; |
| | | font-weight: bold; |
| | | color: white; |
| | | border-radius: 5rpx; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-direction: row; |
| | | display: flex; |
| | | } |
| | | |
| | | .save { |
| | | background: #007AFF; |
| | | } |
| | | |
| | | .clear { |
| | | background: orange; |
| | | } |
| | | |
| | | .sign-area { |
| | | position: absolute; |
| | | top: 40%; |
| | | left: 15%; |
| | | color: #eeeeee; |
| | | font-size: 130rpx; |
| | | transform: rotate(-20deg); |
| | | } |
| | | </style> |
| New file |
| | |
| | | { |
| | | "id": "jushi-signature", |
| | | "displayName": "手写签名、电子签名组件,支持APP、微信小程序、H5", |
| | | "version": "1.0.1", |
| | | "description": "手写签名、电子签名组件,支持APP、微信小程序、H5", |
| | | "keywords": [ |
| | | "在线签名", |
| | | "手写签名", |
| | | "电子签名", |
| | | "手写板" |
| | | ], |
| | | "repository": "", |
| | | "engines": { |
| | | }, |
| | | "dcloudext": { |
| | | "type": "component-vue", |
| | | "sale": { |
| | | "regular": { |
| | | "price": "0.00" |
| | | }, |
| | | "sourcecode": { |
| | | "price": "0.00" |
| | | } |
| | | }, |
| | | "contact": { |
| | | "qq": "" |
| | | }, |
| | | "declaration": { |
| | | "ads": "无", |
| | | "data": "插件不采集任何数据", |
| | | "permissions": "无" |
| | | }, |
| | | "npmurl": "" |
| | | }, |
| | | "uni_modules": { |
| | | "dependencies": [], |
| | | "encrypt": [], |
| | | "platforms": { |
| | | "cloud": { |
| | | "tcb": "y", |
| | | "aliyun": "y" |
| | | }, |
| | | "client": { |
| | | "Vue": { |
| | | "vue2": "y", |
| | | "vue3": "u" |
| | | }, |
| | | "App": { |
| | | "app-vue": "y", |
| | | "app-nvue": "y" |
| | | }, |
| | | "H5-mobile": { |
| | | "Safari": "y", |
| | | "Android Browser": "y", |
| | | "微信浏览器(Android)": "y", |
| | | "QQ浏览器(Android)": "y" |
| | | }, |
| | | "H5-pc": { |
| | | "Chrome": "u", |
| | | "IE": "u", |
| | | "Edge": "u", |
| | | "Firefox": "u", |
| | | "Safari": "u" |
| | | }, |
| | | "小程序": { |
| | | "微信": "y", |
| | | "阿里": "u", |
| | | "百度": "u", |
| | | "字节跳动": "u", |
| | | "QQ": "u", |
| | | "钉钉": "u", |
| | | "快手": "u", |
| | | "飞书": "u", |
| | | "京东": "u" |
| | | }, |
| | | "快应用": { |
| | | "华为": "u", |
| | | "联盟": "u" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | #### 手写签名、电子签名组件,支持APP、微信小程序、H5 |
| | | - 支持APP、微信小程序、H5 |
| | | ``` |
| | | 本插件为手写签名(电子签名)组件,支持APP、微信小程序、H5三端使用 |
| | | ``` |
| | | |
| | | - 组件属性说明 |
| | | |
| | | | 序号 | 属性名称|属性说明 |
| | | |--|--|--| |
| | | |1 |settings|签名设置项,签名区域宽高、文字颜色等设置 |
| | | |2 |base64|是否强制返回图片base64,默认为false,即返回的是临时地址 |
| | | |
| | | - settings属性说明 |
| | | ``` |
| | | { //签名设置 |
| | | width: '750',//签名区域的宽 |
| | | height: '500',//签名区域的高 |
| | | lineWidth:3,//签名时线宽 |
| | | textColor:'#007AFF' //签名文字颜色 |
| | | } |
| | | ``` |
| | | |
| | | - 组件事件说明 |
| | | |
| | | |序号|事件名称|事件说明 |
| | | |--|--|--| |
| | | |1|change|点击保存/清除按钮事件,返回图片地址或图片base64(根据base64属性的值返回相应的结果),点击清除按钮是返回 '' |
| | | |
| | | |
| | | - 使用示例 |
| | | ``` |
| | | <template> |
| | | <view> |
| | | <jushi-signature base64 :settings="settings" @change="signatureChange"></jushi-signature> |
| | | <view class="" style="margin-top: 20rpx;"> |
| | | <text class="text">保存后的签名图片</text> |
| | | <view class="preview"> |
| | | <image :src="imgUrl" mode="" style="width: 100%;"></image> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | settings:{ //签名设置 |
| | | width: '750',//签名区域的宽 |
| | | height: '500',//签名区域的高 |
| | | lineWidth:3,//签名时线宽 |
| | | textColor:'#007AFF' //签名文字颜色 |
| | | }, |
| | | imgUrl: '' |
| | | } |
| | | }, |
| | | methods: { |
| | | signatureChange(e) { |
| | | this.imgUrl = e |
| | | console.log(e) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .preview{ |
| | | margin: 10rpx; |
| | | border: 1rpx solid #aaaaaa; |
| | | border-radius: 10rpx; |
| | | } |
| | | .text { |
| | | margin: 20rpx; |
| | | color: #aaaaaa; |
| | | } |
| | | </style> |
| | | ``` |
| | | - 备注 |
| | | ``` |
| | | 欢迎来邮件咨询和讨论,邮箱:1052775690@qq.com |
| | | ``` |