From 9559ddc77d25d049862eb0fb6bdcfa90f792830e Mon Sep 17 00:00:00 2001
From: Lou <luzhiping@qqyjz.com>
Date: Mon, 18 Dec 2023 18:09:05 +0800
Subject: [PATCH] 扫码逻辑修改,楼盘表修改
---
uni_modules/jushi-signature/components/image-tools/README.md | 76 ++
uni_modules/jushi-signature/components/image-tools/package.json | 25
subPackage/article/signature.vue | 44 +
uni_modules/jushi-signature/package.json | 83 ++
components/am-sign-input/u-mask/u-mask.vue | 124 +++
subPackage/label/index.vue | 6
static/other/color_black_selected.png | 0
pages/home/index.vue | 14
static/other/color_red.png | 0
uni_modules/jushi-signature/changelog.md | 4
subPackage/bs/views/repair.vue | 6
components/am-sign-input/README.md | 83 ++
uni_modules/jushi-signature/components/jushi-signature/jushi-signature.vue | 228 ++++++
static/other/color_red_selected.png | 0
uni_modules/jushi-signature/readme.md | 82 ++
pages.json | 25
static/other/color_black.png | 0
static/other/signs.png | 0
uni_modules/jushi-signature/components/image-tools/index.js | 196 +++++
components/am-sign-input/pickerColor.vue | 143 ++++
pages/user/center.vue | 3
subPackage/house/roomDetails/index.vue | 43
common/setting.js | 4
subPackage/house/family/index.vue | 34
components/am-sign-input/am-sign-input.vue | 781 ++++++++++++++++++++++
subPackage/house/list/index.vue | 7
26 files changed, 1,973 insertions(+), 38 deletions(-)
diff --git a/common/setting.js b/common/setting.js
index 16845c4..9be882d 100644
--- a/common/setting.js
+++ b/common/setting.js
@@ -13,8 +13,8 @@
// 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/",
diff --git a/components/am-sign-input/README.md b/components/am-sign-input/README.md
new file mode 100644
index 0000000..b2dfd2d
--- /dev/null
+++ b/components/am-sign-input/README.md
@@ -0,0 +1,83 @@
+### 使用方法
+* 注意
++ 同一个页面不同的输入框需要设置不同的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)
\ No newline at end of file
diff --git a/components/am-sign-input/am-sign-input.vue b/components/am-sign-input/am-sign-input.vue
new file mode 100644
index 0000000..932b50b
--- /dev/null
+++ b/components/am-sign-input/am-sign-input.vue
@@ -0,0 +1,781 @@
+<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>
\ No newline at end of file
diff --git a/components/am-sign-input/pickerColor.vue b/components/am-sign-input/pickerColor.vue
new file mode 100644
index 0000000..37509d3
--- /dev/null
+++ b/components/am-sign-input/pickerColor.vue
@@ -0,0 +1,143 @@
+<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>
\ No newline at end of file
diff --git a/components/am-sign-input/u-mask/u-mask.vue b/components/am-sign-input/u-mask/u-mask.vue
new file mode 100644
index 0000000..34b1e1e
--- /dev/null
+++ b/components/am-sign-input/u-mask/u-mask.vue
@@ -0,0 +1,124 @@
+<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>
\ No newline at end of file
diff --git a/pages.json b/pages.json
index 56889a0..b448dc7 100644
--- a/pages.json
+++ b/pages.json
@@ -189,6 +189,15 @@
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black"
}
+ },
+ {
+ "path": "signature",
+ "style": {
+ "navigationBarTitleText": "签名",
+ "enablePullDownRefresh": false,
+ "navigationBarBackgroundColor": "#fff",
+ "navigationBarTextStyle": "black"
+ }
}
]
@@ -213,11 +222,11 @@
"pages": [{
"path": "index",
"style": {
- "navigationBarTitleText": "标签事件",
+ "navigationBarTitleText": "标签报事",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#4586fe",
- "navigationBarTextStyle": "white",
- "navigationStyle": "custom"
+ "navigationBarTextStyle": "white"
+ // "navigationStyle": "custom"
}
},
{
@@ -517,11 +526,11 @@
{
"path": "views/repair",
"style": {
- "navigationBarTitleText": "报事报修",
- "navigationBarBackgroundColor": "#fff",
- "navigationBarTextStyle": "black",
- "enablePullDownRefresh": false,
- "navigationStyle": "custom"
+ "navigationBarTitleText": "公共报事",
+ "navigationBarBackgroundColor": "#4586fe",
+ "navigationBarTextStyle": "white",
+ "enablePullDownRefresh": false
+ // "navigationStyle": "custom"
}
},
{
diff --git a/pages/home/index.vue b/pages/home/index.vue
index a386c99..14645ce 100644
--- a/pages/home/index.vue
+++ b/pages/home/index.vue
@@ -764,13 +764,19 @@
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")
}
- })
+ })
}
}
}
diff --git a/pages/user/center.vue b/pages/user/center.vue
index 029647b..85ed2c0 100644
--- a/pages/user/center.vue
+++ b/pages/user/center.vue
@@ -64,6 +64,9 @@
<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>
diff --git a/static/other/color_black.png b/static/other/color_black.png
new file mode 100644
index 0000000..4b19b54
--- /dev/null
+++ b/static/other/color_black.png
Binary files differ
diff --git a/static/other/color_black_selected.png b/static/other/color_black_selected.png
new file mode 100644
index 0000000..9ff5984
--- /dev/null
+++ b/static/other/color_black_selected.png
Binary files differ
diff --git a/static/other/color_red.png b/static/other/color_red.png
new file mode 100644
index 0000000..8dcbfe0
--- /dev/null
+++ b/static/other/color_red.png
Binary files differ
diff --git a/static/other/color_red_selected.png b/static/other/color_red_selected.png
new file mode 100644
index 0000000..6d40ed9
--- /dev/null
+++ b/static/other/color_red_selected.png
Binary files differ
diff --git a/static/other/signs.png b/static/other/signs.png
new file mode 100644
index 0000000..62b4f5d
--- /dev/null
+++ b/static/other/signs.png
Binary files differ
diff --git a/subPackage/article/signature.vue b/subPackage/article/signature.vue
new file mode 100644
index 0000000..325e244
--- /dev/null
+++ b/subPackage/article/signature.vue
@@ -0,0 +1,44 @@
+<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>
\ No newline at end of file
diff --git a/subPackage/bs/views/repair.vue b/subPackage/bs/views/repair.vue
index 36c2b7a..deeedb5 100644
--- a/subPackage/bs/views/repair.vue
+++ b/subPackage/bs/views/repair.vue
@@ -1,7 +1,7 @@
<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>
@@ -163,7 +163,7 @@
padding: 0 30rpx;
position: fixed;
box-sizing: border-box;
- top: 130rpx;
+ top: 40rpx;
left: 0;
z-index: 100;
diff --git a/subPackage/house/family/index.vue b/subPackage/house/family/index.vue
index f633d96..63442a4 100644
--- a/subPackage/house/family/index.vue
+++ b/subPackage/house/family/index.vue
@@ -1,10 +1,19 @@
<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"
@@ -21,7 +30,7 @@
<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>
@@ -135,7 +144,8 @@
neiCode: "",
buildingList: [],
shopList: [],
- curSelectSite: {}
+ curSelectSite: {},
+ addressName:""
}
},
onLoad(e) {
@@ -149,8 +159,16 @@
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() {
@@ -214,7 +232,8 @@
}
},
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")
},
// 跳转到商铺页面
@@ -385,4 +404,9 @@
/deep/ .u-cell__body {
background-color: rgb(236, 244, 255);
}
+
+ .house-address{
+ padding:20rpx;
+
+ }
</style>
\ No newline at end of file
diff --git a/subPackage/house/list/index.vue b/subPackage/house/list/index.vue
index 246e6f0..eb8cd26 100644
--- a/subPackage/house/list/index.vue
+++ b/subPackage/house/list/index.vue
@@ -4,6 +4,7 @@
<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"
@@ -59,11 +60,13 @@
const {
id,
title,
- addressType
} = e
this.currentId = id
this.curHouseTitle = title
- this.addressType = addressType
+ if(e.addressType){
+ this.addressType = e.addressType
+ }
+
},
onShow() {
diff --git a/subPackage/house/roomDetails/index.vue b/subPackage/house/roomDetails/index.vue
index 1d433b4..814149a 100644
--- a/subPackage/house/roomDetails/index.vue
+++ b/subPackage/house/roomDetails/index.vue
@@ -10,11 +10,15 @@
{{ 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"
@@ -41,7 +45,7 @@
</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>
@@ -161,7 +165,8 @@
unitName: '',
houseTitle: '',
// 人员数量
- allNum: 0
+ allNum: 0,
+ buildingName:""
},
ownerInfoList: [],
rentOutList: [],
@@ -182,18 +187,28 @@
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()
@@ -248,7 +263,8 @@
unitName,
houseRentalList,
householdList,
- subAoi
+ subAoi,
+ addressName
} = res.data
this.houseCode = addressCode
this.rentOutList = houseRentalList
@@ -256,6 +272,8 @@
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 => {
// 事件格式处理
@@ -420,8 +438,7 @@
.house-info {
font-weight: 700;
-
- text {
+ .c-aa{
color: #AAAAAA;
}
}
@@ -549,4 +566,8 @@
border: 0;
}
}
+ .house-address{
+ padding:10rpx 0;
+ border-bottom: 1rpx solid #f6f6f6;
+ }
</style>
\ No newline at end of file
diff --git a/subPackage/label/index.vue b/subPackage/label/index.vue
index 22d2b17..614d7c7 100644
--- a/subPackage/label/index.vue
+++ b/subPackage/label/index.vue
@@ -1,7 +1,7 @@
<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>
@@ -181,7 +181,7 @@
padding: 0 30rpx;
position: fixed;
box-sizing: border-box;
- top:130rpx;
+ top:40rpx;
left:0;
z-index: 100;
.serve-box{
diff --git a/uni_modules/jushi-signature/changelog.md b/uni_modules/jushi-signature/changelog.md
new file mode 100644
index 0000000..b9a4cc7
--- /dev/null
+++ b/uni_modules/jushi-signature/changelog.md
@@ -0,0 +1,4 @@
+## 1.0.1(2023-09-12)
+增加组件属性 base64,该属性用于设置返回的结果是图片base64还是临时地址,默认为图片临时地址
+## 1.0.0(2023-08-16)
+手写签名、电子签名组件首次提交发布
diff --git a/uni_modules/jushi-signature/components/image-tools/README.md b/uni_modules/jushi-signature/components/image-tools/README.md
new file mode 100644
index 0000000..1f24012
--- /dev/null
+++ b/uni_modules/jushi-signature/components/image-tools/README.md
@@ -0,0 +1,76 @@
+# 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)
+ })
+```
\ No newline at end of file
diff --git a/uni_modules/jushi-signature/components/image-tools/index.js b/uni_modules/jushi-signature/components/image-tools/index.js
new file mode 100644
index 0000000..acf40bc
--- /dev/null
+++ b/uni_modules/jushi-signature/components/image-tools/index.js
@@ -0,0 +1,196 @@
+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'))
+ })
+}
\ No newline at end of file
diff --git a/uni_modules/jushi-signature/components/image-tools/package.json b/uni_modules/jushi-signature/components/image-tools/package.json
new file mode 100644
index 0000000..edbdc1d
--- /dev/null
+++ b/uni_modules/jushi-signature/components/image-tools/package.json
@@ -0,0 +1,25 @@
+{
+ "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"
+ }
+}
diff --git a/uni_modules/jushi-signature/components/jushi-signature/jushi-signature.vue b/uni_modules/jushi-signature/components/jushi-signature/jushi-signature.vue
new file mode 100644
index 0000000..f5ff4d0
--- /dev/null
+++ b/uni_modules/jushi-signature/components/jushi-signature/jushi-signature.vue
@@ -0,0 +1,228 @@
+<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>
\ No newline at end of file
diff --git a/uni_modules/jushi-signature/package.json b/uni_modules/jushi-signature/package.json
new file mode 100644
index 0000000..87dff53
--- /dev/null
+++ b/uni_modules/jushi-signature/package.json
@@ -0,0 +1,83 @@
+{
+ "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"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/jushi-signature/readme.md b/uni_modules/jushi-signature/readme.md
new file mode 100644
index 0000000..3b123cd
--- /dev/null
+++ b/uni_modules/jushi-signature/readme.md
@@ -0,0 +1,82 @@
+#### 手写签名、电子签名组件,支持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
+ ```
--
Gitblit v1.9.3