Merge remote-tracking branch 'origin/dev' into dev
|
@ -0,0 +1,216 @@
|
||||||
|
/* @preserve
|
||||||
|
* gcoord 0.2.2, geographic coordinate library
|
||||||
|
* Copyright (c) 2019 Jiulong Hu <me@hujiulong.com>
|
||||||
|
*/
|
||||||
|
!function (e, t) {
|
||||||
|
"object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t(e.gcoord = {})
|
||||||
|
}(this, function (e) {
|
||||||
|
"use strict";
|
||||||
|
var t = "WGS84", r = t, n = t, o = "GCJ02", a = o, i = "BD09", u = i, f = i, c = i, s = "BD09MC", l = s,
|
||||||
|
M = "EPSG3857", g = M, h = M, v = M, d = M;
|
||||||
|
|
||||||
|
function m(e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
function G(e) {
|
||||||
|
return !isNaN(e) && null !== e && !S(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
function S(e) {
|
||||||
|
return !!e && "[object Array]" === Object.prototype.toString.call(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
function P() {
|
||||||
|
for (var o = [], e = 0; e < arguments.length; e++) o[e] = arguments[e];
|
||||||
|
var a = o.length - 1;
|
||||||
|
return function () {
|
||||||
|
for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
|
||||||
|
for (var r = a, n = o[a].apply(null, e); r--;) n = o[r].call(null, n);
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var b = Math.sin, y = Math.cos, p = Math.sqrt, B = Math.abs, D = Math.PI, C = 6378245, E = .006693421622965823;
|
||||||
|
|
||||||
|
function W(e) {
|
||||||
|
var t = e[0], r = e[1];
|
||||||
|
if (!J(t, r)) return [t, r];
|
||||||
|
for (var n = [t, r], o = n[0], a = n[1], i = x([o, a]), u = i[0] - t, f = i[1] - r; 1e-6 < B(u) || 1e-6 < B(f);) u = (i = x([o -= u, a -= f]))[0] - t, f = i[1] - r;
|
||||||
|
return [o, a]
|
||||||
|
}
|
||||||
|
|
||||||
|
function x(e) {
|
||||||
|
var t = e[0], r = e[1];
|
||||||
|
if (!J(t, r)) return [t, r];
|
||||||
|
var n = function (e, t) {
|
||||||
|
var r = function (e, t) {
|
||||||
|
var r = 300 + e + 2 * t + .1 * e * e + .1 * e * t + .1 * p(B(e));
|
||||||
|
return r += 2 * (20 * b(6 * e * D) + 20 * b(2 * e * D)) / 3, r += 2 * (20 * b(e * D) + 40 * b(e / 3 * D)) / 3, r += 2 * (150 * b(e / 12 * D) + 300 * b(e / 30 * D)) / 3
|
||||||
|
}(e - 105, t - 35), n = function (e, t) {
|
||||||
|
var r = 2 * e - 100 + 3 * t + .2 * t * t + .1 * e * t + .2 * p(B(e));
|
||||||
|
return r += 2 * (20 * b(6 * e * D) + 20 * b(2 * e * D)) / 3, r += 2 * (20 * b(t * D) + 40 * b(t / 3 * D)) / 3, r += 2 * (160 * b(t / 12 * D) + 320 * b(t * D / 30)) / 3
|
||||||
|
}(e - 105, t - 35), o = t / 180 * D, a = b(o), i = p(a = 1 - E * a * a);
|
||||||
|
return [r = 180 * r / (C / i * y(o) * D), n = 180 * n / (C * (1 - E) / (a * i) * D)]
|
||||||
|
}(t, r);
|
||||||
|
return [t + n[0], r + n[1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
function J(e, t) {
|
||||||
|
return 72.004 <= e && e <= 137.8347 && .8293 <= t && t <= 55.8271
|
||||||
|
}
|
||||||
|
|
||||||
|
var k = Math.sin, L = Math.cos, j = Math.atan2, I = Math.sqrt, q = 3e3 * Math.PI / 180;
|
||||||
|
|
||||||
|
function w(e) {
|
||||||
|
var t = e[0] - .0065, r = e[1] - .006, n = I(t * t + r * r) - 2e-5 * k(r * q), o = j(r, t) - 3e-6 * L(t * q);
|
||||||
|
return [n * L(o), n * k(o)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function N(e) {
|
||||||
|
var t = e[0], r = e[1], n = I(t * t + r * r) + 2e-5 * k(r * q), o = j(r, t) + 3e-6 * L(t * q);
|
||||||
|
return [n * L(o) + .0065, n * k(o) + .006]
|
||||||
|
}
|
||||||
|
|
||||||
|
var O = 180 / Math.PI, A = Math.PI / 180, F = 6378137, _ = 20037508.342789244;
|
||||||
|
|
||||||
|
function z(e) {
|
||||||
|
return [e[0] * O / F, (.5 * Math.PI - 2 * Math.atan(Math.exp(-e[1] / F))) * O]
|
||||||
|
}
|
||||||
|
|
||||||
|
function T(e) {
|
||||||
|
var t = Math.abs(e[0]) <= 180 ? e[0] : e[0] - 360 * (e[0] < 0 ? -1 : 1),
|
||||||
|
r = [F * t * A, F * Math.log(Math.tan(.25 * Math.PI + .5 * e[1] * A))];
|
||||||
|
return r[0] > _ && (r[0] = _), r[0] < -_ && (r[0] = -_), r[1] > _ && (r[1] = _), r[1] < -_ && (r[1] = -_), r
|
||||||
|
}
|
||||||
|
|
||||||
|
var U = Math.abs, H = Math.pow, K = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0],
|
||||||
|
Q = [75, 60, 45, 30, 15, 0],
|
||||||
|
R = [[1.410526172116255e-8, 898305509648872e-20, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -.03801003308653, 17337981.2], [-7.435856389565537e-9, 8983055097726239e-21, -.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86], [-3.030883460898826e-8, 898305509983578e-20, .30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, .32710905363475, 6856817.37], [-1.981981304930552e-8, 8983055099779535e-21, .03278182852591, 40.31678527705744, .65659298677277, -4.44255534477492, .85341911805263, .12923347998204, -.04625736007561, 4482777.06], [3.09191371068437e-9, 8983055096812155e-21, 6995724062e-14, 23.10934304144901, -.00023663490511, -.6321817810242, -.00663494467273, .03430082397953, -.00466043876332, 2555164.4], [2.890871144776878e-9, 8983055095805407e-21, -3.068298e-8, 7.47137025468032, -353937994e-14, -.02145144861037, -1234426596e-14, .00010322952773, -323890364e-14, 826088.5]],
|
||||||
|
V = [[-.0015702102444, 111320.7020616939, 0x60e374c3105a3, -0x24bb4115e2e164, 0x5cc55543bb0ae8, -0x7ce070193f3784, 0x5e7ca61ddf8150, -0x261a578d8b24d0, 0x665d60f3742ca, 82.5], [.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142, -15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5], [.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253, 97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5], [.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5], [-.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5], [-.0003218135878613132, 111320.7020701615, .00369383431289, 823725.6402795718, .46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, .37238884252424, 7.45]];
|
||||||
|
|
||||||
|
function X(e, t, r) {
|
||||||
|
var n = U(t) / r[9], o = r[0] + r[1] * U(e),
|
||||||
|
a = r[2] + r[3] * n + r[4] * H(n, 2) + r[5] * H(n, 3) + r[6] * H(n, 4) + r[7] * H(n, 5) + r[8] * H(n, 6);
|
||||||
|
return [o *= e < 0 ? -1 : 1, a *= t < 0 ? -1 : 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
function Y(e) {
|
||||||
|
for (var t = e[0], r = e[1], n = [], o = 0; o < Q.length; o++) if (U(r) > Q[o]) {
|
||||||
|
n = V[o];
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return X(t, r, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Z(e) {
|
||||||
|
for (var t = e[0], r = e[1], n = [], o = 0; o < K.length; o++) if (K[o] <= r) {
|
||||||
|
n = R[o];
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return X(t, r, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
var $ = {to: {GCJ02: x, BD09: P(N, x), BD09MC: P(Y, N, x), EPSG3857: T}},
|
||||||
|
ee = {to: {WGS84: W, BD09: N, BD09MC: P(Y, N), EPSG3857: P(T, W)}},
|
||||||
|
te = {to: {WGS84: P(W, w), GCJ02: w, EPSG3857: P(T, W, w), BD09MC: Y}},
|
||||||
|
re = {to: {WGS84: z, GCJ02: P(x, z), BD09: P(N, x, z), BD09MC: P(Y, N, x, z)}},
|
||||||
|
ne = {to: {WGS84: P(W, w, Z), GCJ02: P(w, Z), EPSG3857: P(T, W, w, Z), BD09: Z}},
|
||||||
|
oe = Object.freeze({WGS84: $, GCJ02: ee, BD09: te, EPSG3857: re, BD09MC: ne});
|
||||||
|
|
||||||
|
function ae(e, t, r) {
|
||||||
|
e || m("coordinate is required"), t || m("original coordinate system is required"), r || m("target coordinate system is required");
|
||||||
|
var n = oe[t];
|
||||||
|
if (n || m("original coordinate system is invalid"), t === r) return e;
|
||||||
|
var o = n.to[r];
|
||||||
|
o || m("target coordinate system is invalid");
|
||||||
|
var a = typeof e;
|
||||||
|
if ("string" != a && "object" != a && m("coordinate must be an geojson or an array of position"), "string" == a) try {
|
||||||
|
e = JSON.parse(e)
|
||||||
|
} catch (e) {
|
||||||
|
m("input is not a legal JSON string")
|
||||||
|
}
|
||||||
|
var i = !1;
|
||||||
|
S(e) && (e.length < 2 && m("position must be at 2 numbers long"), G(e[0]) && G(e[1]) || m("position must contain numbers"), e = e.map(Number), i = !0);
|
||||||
|
var u = o;
|
||||||
|
return i ? u(e) : (function e(t, r, n) {
|
||||||
|
if (void 0 === n && (n = !1), null !== t) for (var o, a, i, u, f, c, s, l, M = 0, g = 0, h = t.type, v = "FeatureCollection" === h, d = "Feature" === h, G = v ? t.features.length : 1, S = 0; S < G; S++) {
|
||||||
|
f = (l = !!(s = v ? t.features[S].geometry : d ? t.geometry : t) && "GeometryCollection" === s.type) ? s.geometries.length : 1;
|
||||||
|
for (var P = 0; P < f; P++) {
|
||||||
|
var b = 0, y = 0;
|
||||||
|
if (null !== (u = l ? s.geometries[P] : s)) {
|
||||||
|
var p = u.type;
|
||||||
|
switch (M = !n || "Polygon" !== p && "MultiPolygon" !== p ? 0 : 1, p) {
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
case"Point":
|
||||||
|
if (!1 === r(c = u.coordinates, g, S, b, y)) return !1;
|
||||||
|
g++, b++;
|
||||||
|
break;
|
||||||
|
case"LineString":
|
||||||
|
case"MultiPoint":
|
||||||
|
for (c = u.coordinates, o = 0; o < c.length; o++) {
|
||||||
|
if (!1 === r(c[o], g, S, b, y)) return !1;
|
||||||
|
g++, "MultiPoint" === p && b++
|
||||||
|
}
|
||||||
|
"LineString" === p && b++;
|
||||||
|
break;
|
||||||
|
case"Polygon":
|
||||||
|
case"MultiLineString":
|
||||||
|
for (c = u.coordinates, o = 0; o < c.length; o++) {
|
||||||
|
for (a = 0; a < c[o].length - M; a++) {
|
||||||
|
if (!1 === r(c[o][a], g, S, b, y)) return !1;
|
||||||
|
g++
|
||||||
|
}
|
||||||
|
"MultiLineString" === p && b++, "Polygon" === p && y++
|
||||||
|
}
|
||||||
|
"Polygon" === p && b++;
|
||||||
|
break;
|
||||||
|
case"MultiPolygon":
|
||||||
|
for (c = u.coordinates, o = 0; o < c.length; o++) {
|
||||||
|
for (a = y = 0; a < c[o].length; a++) {
|
||||||
|
for (i = 0; i < c[o][a].length - M; i++) {
|
||||||
|
if (!1 === r(c[o][a][i], g, S, b, y)) return !1;
|
||||||
|
g++
|
||||||
|
}
|
||||||
|
y++
|
||||||
|
}
|
||||||
|
b++
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case"GeometryCollection":
|
||||||
|
for (o = 0; o < u.geometries.length; o++) if (!1 === e(u.geometries[o], r, n)) return !1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m("Unknown Geometry Type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(e, function (e) {
|
||||||
|
var t;
|
||||||
|
t = u(e), e[0] = t[0], e[1] = t[1]
|
||||||
|
}), e)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ie = {
|
||||||
|
WGS84: t,
|
||||||
|
WGS1984: r,
|
||||||
|
EPSG4326: n,
|
||||||
|
GCJ02: o,
|
||||||
|
AMap: a,
|
||||||
|
BD09: i,
|
||||||
|
BD09LL: u,
|
||||||
|
Baidu: f,
|
||||||
|
BMap: c,
|
||||||
|
BD09MC: s,
|
||||||
|
BD09Meter: l,
|
||||||
|
EPSG3857: M,
|
||||||
|
EPSG900913: g,
|
||||||
|
EPSG102100: h,
|
||||||
|
WebMercator: v,
|
||||||
|
WM: d,
|
||||||
|
transform: ae
|
||||||
|
};
|
||||||
|
e.WGS84 = t, e.WGS1984 = r, e.EPSG4326 = n, e.GCJ02 = o, e.AMap = a, e.BD09 = i, e.BD09LL = u, e.Baidu = f, e.BMap = c, e.BD09MC = s, e.BD09Meter = l, e.EPSG3857 = M, e.EPSG900913 = g, e.EPSG102100 = h, e.WebMercator = v, e.WM = d, e.transform = ae, e.default = ie, Object.defineProperty(e, "__esModule", {value: !0})
|
||||||
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="empty">
|
<view class="empty">
|
||||||
<u--image :showLoading="true" src="/static/svg/empty.svg" width="750upx" height="500upx"></u--image>
|
<u--image :showLoading="true" src="/static/svg/empty.svg" width="750rpx" height="500rpx"></u--image>
|
||||||
<view class="empty-text">{{ message }}</view>
|
<view class="empty-text">{{ message }}</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
@ -24,10 +24,10 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
.empty-text{
|
.empty-text{
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
color: $uni-text-color-placeholder;
|
color: $uni-text-color-placeholder;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 400upx;
|
top: 400rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,61 +1,128 @@
|
||||||
<template>
|
<template>
|
||||||
<u-modal
|
<u-modal
|
||||||
:show="signShow"
|
:show="signShow"
|
||||||
title="签名"
|
:show-confirm-button="false"
|
||||||
showCancelButton
|
class="esign_dialog"
|
||||||
confirmText="完成"
|
width="100vw"
|
||||||
cancelText="重写"
|
|
||||||
@confirm="confirm"
|
|
||||||
@cancel="clear"
|
|
||||||
>
|
>
|
||||||
<view class="handCenter">
|
<view class="footer">
|
||||||
<l-signature disableScroll backgroundColor="#fff" ref="signatureRef" :penSize="5"
|
<view class="button" @click="fnReset">
|
||||||
:openSmooth="true" :landscape="true"></l-signature>
|
<view>重</view>
|
||||||
|
<view>签</view>
|
||||||
|
</view>
|
||||||
|
<view class="button" @click="fnGenerate">
|
||||||
|
<view>确</view>
|
||||||
|
<view>定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-if="signShow" class="content">
|
||||||
|
<sp-sign-board
|
||||||
|
ref="signRef"
|
||||||
|
horizontal
|
||||||
|
bg-color="#fff"
|
||||||
|
:need-back="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="header">
|
||||||
|
<view></view>
|
||||||
|
<view>
|
||||||
|
<view class="title">签</view>
|
||||||
|
<view class="title">字</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-icon name="close" size="26" color="#000" @click="fnClose" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</u-modal>
|
</u-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script >
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
signShow: {
|
signShow: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible:false,
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clear() {
|
fnReset() {
|
||||||
this.$refs.signatureRef.clear()
|
this.$refs.signRef?.reset && this.$refs.signRef.reset();
|
||||||
},
|
},
|
||||||
confirm() {
|
fnGenerate() {
|
||||||
this.$refs.signatureRef.canvasToTempFilePath({
|
this.$refs.signRef.confirm();
|
||||||
fileType: 'jpg',
|
},
|
||||||
quality: 1,
|
fnClose() {
|
||||||
destWidth: 900,
|
this.fnReset();
|
||||||
destHeight: 435,
|
|
||||||
success: (res) => {
|
|
||||||
if (res.isEmpty) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '请签字',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.clear()
|
|
||||||
this.$emit("update:signShow", false);
|
this.$emit("update:signShow", false);
|
||||||
this.$emit('confirm', {id: '', filePath: res.tempFilePath})
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
uni.$on("getSignImg", ({ base64, path }) => {
|
||||||
|
this.$emit('confirm', {id: '', filePath: path});
|
||||||
|
this.fnClose();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
uni.$off("getSignImg");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped lang="scss">
|
||||||
.handCenter {
|
.header {
|
||||||
border: 4upx dashed #e9e9e9;
|
padding: 50rpx 0;
|
||||||
height: 80vh;
|
width: 80rpx;
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
box-sizing: border-box;
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #000;
|
||||||
|
margin-right: -25rpx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
//display: flex;
|
||||||
|
//align-items: center;
|
||||||
|
//justify-content: center;
|
||||||
|
height: 95vh;
|
||||||
|
border: 1rpx dashed #dcdee0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: -25rpx;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
flex: 1;
|
||||||
|
border-top: 1rpx solid #dcdee0;
|
||||||
|
display: block;
|
||||||
|
padding-top: 25vh;
|
||||||
|
padding-left: 14rpx;
|
||||||
|
padding-right: 30rpx;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -67,5 +67,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -566,5 +566,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -198,5 +198,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -329,5 +329,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
shape="circle"
|
shape="circle"
|
||||||
></u--input>
|
></u--input>
|
||||||
<view class="ml-10">
|
<view class="ml-10">
|
||||||
<u-button class="bth-mini ml-10" type="success" text="确定" @click="resetList"></u-button>
|
<u-button class="bth-mini" type="success" text="确定" @click="resetList"></u-button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<u-list @scrolltolower="scrolltolower" v-if="list.length > 0">
|
<u-list @scrolltolower="scrolltolower" v-if="list.length > 0">
|
||||||
<u-list-item v-for="(item, index) in list" :key="index">
|
<u-list-item v-for="(item, index) in list" :key="index">
|
||||||
|
@ -31,10 +30,10 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="flex-between mt-10 subtitle">
|
<view class="flex-between mt-10 subtitle">
|
||||||
<text>重点工程数:{{item.OUTSOURCED_COUNT}}</text>
|
<text>重点工程数:{{item.OUTSOURCED_COUNT}}</text>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="see_btn">
|
<view class="flex-between mt-10 subtitle">
|
||||||
<u-button type="primary" text="进入" size="mini" class="bth-mini" @click="fnNavigatorDetail(item.CORPINFO_ID)"/>
|
<text>在线视频数:{{item.ONLINE_COUNT}}</text>
|
||||||
|
<view class="wrap"><u-button type="primary" text="进入" size="mini" class="bth-mini" @click="fnNavigatorDetail(item.CORPINFO_ID)"/></view>
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="flex-between mt-10 subtitle">-->
|
<!-- <view class="flex-between mt-10 subtitle">-->
|
||||||
<!-- <text>重点工程数:{{ item.OUTSOURCED_COUNT }}</text>-->
|
<!-- <text>重点工程数:{{ item.OUTSOURCED_COUNT }}</text>-->
|
||||||
|
@ -114,11 +113,7 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped>
|
||||||
.see_btn{
|
|
||||||
width: 200rpx;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.btn-corner-label::before,
|
.btn-corner-label::before,
|
||||||
.btn-corner-label::after {
|
.btn-corner-label::after {
|
||||||
content: attr(data-label); /* 使用 attr 获取按钮的 data-label 属性的值作为角标内容 */
|
content: attr(data-label); /* 使用 attr 获取按钮的 data-label 属性的值作为角标内容 */
|
||||||
|
@ -141,4 +136,8 @@ export default {
|
||||||
right: 0;
|
right: 0;
|
||||||
transform: skew(5deg); /* 调整角标的位置使其倾斜,以达到更好的效果 */
|
transform: skew(5deg); /* 调整角标的位置使其倾斜,以达到更好的效果 */
|
||||||
}
|
}
|
||||||
|
.wrap{
|
||||||
|
width: 200rpx;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
<uni-th align="center">隐患描述</uni-th>
|
<uni-th align="center">隐患描述</uni-th>
|
||||||
<uni-th align="center">操作</uni-th>
|
<uni-th align="center">操作</uni-th>
|
||||||
</uni-tr>
|
</uni-tr>
|
||||||
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.HIDDEN_ID || item.id">
|
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.id">
|
||||||
<uni-td>{{ index + 1 }}</uni-td>
|
<uni-td>{{ index + 1 }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENPART }}</uni-td>
|
<uni-td>{{ item.HIDDENPART }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
||||||
|
@ -457,6 +457,7 @@ export default {
|
||||||
async fnGetKeyProjectsCheckView() {
|
async fnGetKeyProjectsCheckView() {
|
||||||
let resData = await getKeyProjectsCheckView({KEYPROJECTCHECK_ID: this.KEYPROJECTCHECK_ID})
|
let resData = await getKeyProjectsCheckView({KEYPROJECTCHECK_ID: this.KEYPROJECTCHECK_ID})
|
||||||
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
||||||
|
resData.pd.hiddenList[i].id = resData.pd.hiddenList[i].HIDDEN_ID
|
||||||
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
||||||
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,52 @@
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<web-view :src="url" @message="fnMessage"></web-view>
|
||||||
<web-view id="webview" :src="url" @message="messageChange"></web-view>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import gcoord from '@/common/gcoord.js'
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
url: '',
|
url: '',
|
||||||
|
longitude: '',
|
||||||
|
latitude: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(option) {
|
onLoad(option) {
|
||||||
let _this = this;
|
uni.getLocation({
|
||||||
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
|
type: 'GCJ02',
|
||||||
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
|
success: (res) => {
|
||||||
eventChannel.on('acceptDataFromOpenerPage', function (data) {
|
var result = gcoord.transform(
|
||||||
_this.init(data.data.title);
|
[res.longitude, res.latitude],
|
||||||
})
|
gcoord.GCJ02,
|
||||||
|
gcoord.BD09
|
||||||
|
);
|
||||||
|
this.longitude = result[0]
|
||||||
|
this.latitude = result[1]
|
||||||
|
this.fnInitMapUrl();
|
||||||
},
|
},
|
||||||
onBackPress(options) {
|
fail: () => {
|
||||||
return false;
|
uni.showToast({
|
||||||
|
title: "获取位置失败",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init(title) {
|
fnInitMapUrl() {
|
||||||
this.url = ("/hybrid/html/jsmap.html?t=" + new Date().getTime() + '&title=' + title);
|
this.url = ('https://skqhdg.porthebei.com:9004/map/map.html?longitude=' + this.longitude + '&latitude=' + this.latitude + 't=' +
|
||||||
|
new Date().getTime());
|
||||||
},
|
},
|
||||||
messageChange(e) {
|
fnMessage(event) {
|
||||||
uni.setStorageSync("info", e.detail.data[0]);
|
const eventChannel = this.getOpenerEventChannel();
|
||||||
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
|
eventChannel.emit('acceptDataFromOpenerPage', {
|
||||||
eventChannel.emit('acceptDataFromOpenedPage', {data: e.detail.data[0]});
|
data: event.detail.data[0]
|
||||||
|
});
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
page,
|
|
||||||
uni-page-body,
|
|
||||||
.container {
|
|
||||||
background: rgba(245, 245, 245, 1);
|
|
||||||
min-height: calc(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -76,13 +76,11 @@
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="value">
|
<view class="pr mt-10 textarea-box" v-for="(item,index) in form.situationList" :key="item.id">
|
||||||
<view class="pr mt-10" v-for="(item,index) in form.situationList" :key="item.id">
|
|
||||||
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" :disabled="disabled"></u--textarea>
|
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" :disabled="disabled"></u--textarea>
|
||||||
<u-badge value="X" type="error" :offset="[-9,-10]" absolute
|
<u-badge value="X" type="error" :offset="[-9,-10]" absolute
|
||||||
@click.native="removeSituation(item,index)" v-if="!disabled"></u-badge>
|
@click.native="removeSituation(item,index)" v-if="!disabled"></u-badge>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell>
|
<u-cell>
|
||||||
<view slot="title" class="title">检查人员:</view>
|
<view slot="title" class="title">检查人员:</view>
|
||||||
|
@ -134,7 +132,7 @@
|
||||||
<uni-th align="center">隐患描述</uni-th>
|
<uni-th align="center">隐患描述</uni-th>
|
||||||
<uni-th align="center">操作</uni-th>
|
<uni-th align="center">操作</uni-th>
|
||||||
</uni-tr>
|
</uni-tr>
|
||||||
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.HIDDEN_ID || item.id">
|
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.id">
|
||||||
<uni-td>{{ index + 1 }}</uni-td>
|
<uni-td>{{ index + 1 }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENPART_NAME?item.HIDDENPART_NAME:item.HIDDENPART }}</uni-td>
|
<uni-td>{{ item.HIDDENPART_NAME?item.HIDDENPART_NAME:item.HIDDENPART }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
||||||
|
@ -152,7 +150,7 @@
|
||||||
<template v-for="item in form.inspectorVerifyList" v-if="!type||!(type==='add' || type==='edit')">
|
<template v-for="item in form.inspectorVerifyList" v-if="!type||!(type==='add' || type==='edit')">
|
||||||
<u-cell class="flex-none" v-show="item.INSPECTION_USER_OPINION">
|
<u-cell class="flex-none" v-show="item.INSPECTION_USER_OPINION">
|
||||||
<view slot="title" class="title">检查人意见:</view>
|
<view slot="title" class="title">检查人意见:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="item.INSPECTION_USER_OPINION" disabled placeholder="请输入检查人意见"></u--textarea>
|
<u--textarea v-model="item.INSPECTION_USER_OPINION" disabled placeholder="请输入检查人意见"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
|
@ -181,20 +179,27 @@
|
||||||
<template v-if="type&&(type==='add' || type==='edit')">
|
<template v-if="type&&(type==='add' || type==='edit')">
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title">检查人意见:</view>
|
<view slot="title" class="title">检查人意见:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="form.INSPECTION_USER_OPINION" placeholder="请输入检查人意见"></u--textarea>
|
<u--textarea v-model="form.INSPECTION_USER_OPINION" placeholder="请输入检查人意见"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell v-if="form.INSPECTION_USER_OPINION" class="flex-none">
|
<u-cell v-if="form.INSPECTION_USER_OPINION" class="flex-none">
|
||||||
<view slot="title" class="title flex-between">
|
<view slot="title" class="title flex-between">
|
||||||
签字:
|
签字:
|
||||||
|
<view>
|
||||||
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10">
|
||||||
|
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
||||||
|
</view>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell v-if="form.INSPECTION_USER_SIGN_IMG">
|
||||||
|
<view slot="value" class="mt-10 flex-1" v-show="form.INSPECTION_USER_SIGN_IMG">
|
||||||
<u--image v-show="form.INSPECTION_USER_SIGN_IMG" :showLoading="true" :src="form.INSPECTION_USER_SIGN_IMG"
|
<u--image v-show="form.INSPECTION_USER_SIGN_IMG" :showLoading="true" :src="form.INSPECTION_USER_SIGN_IMG"
|
||||||
width="100%" height="80px" mode="scaleToFill"
|
width="100%" height="80px" mode="scaleToFill"
|
||||||
@click="previewImage(form.INSPECTION_USER_SIGN_IMG)"></u--image>
|
@click="previewImage(form.INSPECTION_USER_SIGN_IMG)"></u--image>
|
||||||
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
</template>
|
</template>
|
||||||
|
@ -250,7 +255,7 @@
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title required">隐患描述:</view>
|
<view slot="title" class="title required">隐患描述:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="hiddenForm.HIDDENDESCR" placeholder="请输入隐患描述"
|
<u--textarea v-model="hiddenForm.HIDDENDESCR" placeholder="请输入隐患描述"
|
||||||
:disabled="popupDisabled"></u--textarea>
|
:disabled="popupDisabled"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
|
@ -310,7 +315,7 @@
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title">隐患位置描述:</view>
|
<view slot="title" class="title">隐患位置描述:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="hiddenForm.POSITIONDESC" placeholder="请输入隐患位置描述"
|
<u--textarea v-model="hiddenForm.POSITIONDESC" placeholder="请输入隐患位置描述"
|
||||||
:disabled="popupDisabled"></u--textarea>
|
:disabled="popupDisabled"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
|
@ -957,5 +962,14 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
min-width: 170rpx;
|
||||||
|
}
|
||||||
|
.textarea-box {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -38,13 +38,20 @@
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title flex-between">
|
<view slot="title" class="title flex-between">
|
||||||
确认人签字:
|
确认人签字:
|
||||||
|
<view>
|
||||||
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
||||||
|
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10">
|
||||||
|
</view>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell v-if="form.SIGN_IMG">
|
||||||
|
<view slot="value" class="mt-10 flex-1" v-show="form.SIGN_IMG">
|
||||||
<u--image v-show="form.SIGN_IMG" :showLoading="true" :src="form.SIGN_IMG"
|
<u--image v-show="form.SIGN_IMG" :showLoading="true" :src="form.SIGN_IMG"
|
||||||
width="100%" height="80px" mode="scaleToFill"
|
width="100%" height="80px" mode="scaleToFill"
|
||||||
@click="previewImage(form.SIGN_IMG)"></u--image>
|
@click="previewImage(form.SIGN_IMG)"></u--image>
|
||||||
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
</template>
|
</template>
|
||||||
|
@ -58,15 +65,19 @@
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title flex-between">
|
<view slot="title" class="title flex-between">
|
||||||
确认人签字:
|
确认人签字:
|
||||||
|
<view>
|
||||||
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
<u-button type="primary" text="手写添加" size="mini" class="bth-mini" @click="signShow = true"></u-button>
|
||||||
|
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10">
|
||||||
|
</view>
|
||||||
|
</u-cell>
|
||||||
|
<view>
|
||||||
<u--image v-show="form.SIGN_IMG" :showLoading="true" :src="form.SIGN_IMG"
|
<u--image v-show="form.SIGN_IMG" :showLoading="true" :src="form.SIGN_IMG"
|
||||||
width="100%" height="80px" mode="scaleToFill"
|
width="100%" height="80px" mode="scaleToFill"
|
||||||
@click="previewImage(form.SIGN_IMG)"></u--image>
|
@click="previewImage(form.SIGN_IMG)"></u--image>
|
||||||
<sign v-if="signShow" :signShow.sync="signShow" @confirm="signConfirm"></sign>
|
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
|
||||||
</template>
|
</template>
|
||||||
<u-cell class="flex-none" :border="false">
|
<u-cell class="flex-none" :border="false">
|
||||||
<view slot="value" class="flex-between">
|
<view slot="value" class="flex-between">
|
||||||
|
@ -174,5 +185,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<view slot="title" class="title">检查情况:</view>
|
<view slot="title" class="title">检查情况:</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="value">
|
<view slot="value textarea-box">
|
||||||
<view class="pr mt-10" v-for="(item,index) in form.situationList" :key="item.id">
|
<view class="pr mt-10" v-for="(item,index) in form.situationList" :key="item.id">
|
||||||
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" disabled></u--textarea>
|
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" disabled></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
<uni-th align="center">隐患描述</uni-th>
|
<uni-th align="center">隐患描述</uni-th>
|
||||||
<uni-th align="center">操作</uni-th>
|
<uni-th align="center">操作</uni-th>
|
||||||
</uni-tr>
|
</uni-tr>
|
||||||
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.HIDDEN_ID || item.id">
|
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.id">
|
||||||
<uni-td>{{ index + 1 }}</uni-td>
|
<uni-td>{{ index + 1 }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENPART_NAME }}</uni-td>
|
<uni-td>{{ item.HIDDENPART_NAME }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
<template v-for="item in form.inspectorVerifyList">
|
<template v-for="item in form.inspectorVerifyList">
|
||||||
<u-cell class="flex-none" v-show="item.INSPECTION_USER_OPINION">
|
<u-cell class="flex-none" v-show="item.INSPECTION_USER_OPINION">
|
||||||
<view slot="title" class="title">检查人意见:</view>
|
<view slot="title" class="title">检查人意见:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="item.INSPECTION_USER_OPINION" disabled placeholder="请输入检查人意见"></u--textarea>
|
<u--textarea v-model="item.INSPECTION_USER_OPINION" disabled placeholder="请输入检查人意见"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
|
@ -173,7 +173,7 @@
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title required">隐患描述:</view>
|
<view slot="title" class="title required">隐患描述:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="hiddenForm.HIDDENDESCR" placeholder="请输入隐患描述" disabled></u--textarea>
|
<u--textarea v-model="hiddenForm.HIDDENDESCR" placeholder="请输入隐患描述" disabled></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
|
@ -216,7 +216,7 @@
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="title" class="title required">隐患位置描述:</view>
|
<view slot="title" class="title required">隐患位置描述:</view>
|
||||||
<view slot="value" class="mt-10">
|
<view slot="value" class="mt-10 textarea-box">
|
||||||
<u--textarea v-model="hiddenForm.POSITIONDESC" placeholder="请输入隐患位置描述" disabled></u--textarea>
|
<u--textarea v-model="hiddenForm.POSITIONDESC" placeholder="请输入隐患位置描述" disabled></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
|
@ -301,6 +301,7 @@ export default {
|
||||||
async fnGetSafetyenvironmentalGoEdit() {
|
async fnGetSafetyenvironmentalGoEdit() {
|
||||||
let resData = await getSafetyenvironmentalGoEdit({INSPECTION_ID: this.INSPECTION_ID})
|
let resData = await getSafetyenvironmentalGoEdit({INSPECTION_ID: this.INSPECTION_ID})
|
||||||
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
||||||
|
resData.pd.hiddenList[i].id = resData.pd.hiddenList[i].HIDDEN_ID
|
||||||
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
||||||
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
||||||
}
|
}
|
||||||
|
@ -333,5 +334,11 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 170rpx;
|
||||||
|
}
|
||||||
|
.textarea-box {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -59,11 +59,9 @@
|
||||||
<view slot="title" class="title">检查情况:</view>
|
<view slot="title" class="title">检查情况:</view>
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell class="flex-none">
|
<u-cell class="flex-none">
|
||||||
<view slot="value">
|
|
||||||
<view class="pr mt-10" v-for="(item,index) in form.situationList" :key="item.id">
|
<view class="pr mt-10" v-for="(item,index) in form.situationList" :key="item.id">
|
||||||
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" disabled></u--textarea>
|
<u--textarea v-model="item.SITUATION" placeholder="请输入检查情况" disabled></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</u-cell>
|
</u-cell>
|
||||||
<u-cell>
|
<u-cell>
|
||||||
<view slot="title" class="title">检查人员:</view>
|
<view slot="title" class="title">检查人员:</view>
|
||||||
|
@ -100,7 +98,7 @@
|
||||||
<uni-th align="center">隐患描述</uni-th>
|
<uni-th align="center">隐患描述</uni-th>
|
||||||
<uni-th align="center">操作</uni-th>
|
<uni-th align="center">操作</uni-th>
|
||||||
</uni-tr>
|
</uni-tr>
|
||||||
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.HIDDEN_ID || item.id">
|
<uni-tr v-for="(item,index) in form.hiddenList" :key="item.id">
|
||||||
<uni-td>{{ index + 1 }}</uni-td>
|
<uni-td>{{ index + 1 }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENPART_NAME?item.HIDDENPART_NAME:item.HIDDENPART }}</uni-td>
|
<uni-td>{{ item.HIDDENPART_NAME?item.HIDDENPART_NAME:item.HIDDENPART }}</uni-td>
|
||||||
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
<uni-td>{{ item.HIDDENDESCR }}</uni-td>
|
||||||
|
@ -358,6 +356,7 @@ export default {
|
||||||
async fnGetSafetyenvironmentalGoEdit() {
|
async fnGetSafetyenvironmentalGoEdit() {
|
||||||
let resData = await getSafetyenvironmentalGoEdit({INSPECTION_ID: this.INSPECTION_ID})
|
let resData = await getSafetyenvironmentalGoEdit({INSPECTION_ID: this.INSPECTION_ID})
|
||||||
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
for (let i = 0; i < resData.pd.hiddenList.length; i++) {
|
||||||
|
resData.pd.hiddenList[i].id = resData.pd.hiddenList[i].HIDDEN_ID
|
||||||
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
for (let j = 0; j < resData.pd.hiddenList[i].hiddenImgs.length; j++) {
|
||||||
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
resData.pd.hiddenList[i].hiddenImgs[j].url = this.$store.state.filePath + resData.pd.hiddenList[i].hiddenImgs[j].FILEPATH
|
||||||
}
|
}
|
||||||
|
@ -427,5 +426,8 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
|
.title {
|
||||||
|
min-width: 150rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Before Width: | Height: | Size: 594 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 584 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 502 KiB After Width: | Height: | Size: 106 KiB |
|
@ -12,42 +12,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.wui_banner{
|
.wui_banner{
|
||||||
height: 572upx;
|
height: 572rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.wui-bar{
|
.wui-bar{
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 100upx;
|
min-height: 100rpx;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.search-form{
|
.search-form{
|
||||||
background: rgba(255,255,255,0.2);
|
background: rgba(255,255,255,0.2);
|
||||||
border-radius: 100upx;
|
border-radius: 100rpx;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 60upx;
|
height: 60rpx;
|
||||||
line-height: 60upx;
|
line-height: 60rpx;
|
||||||
font-size: 24upx;
|
font-size: 24rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 30upx;
|
margin: 0 30rpx;
|
||||||
padding: 0 30upx;
|
padding: 0 30rpx;
|
||||||
.cuIcon-search{
|
.cuIcon-search{
|
||||||
color: rgba(255,255,255,0.5);
|
color: rgba(255,255,255,0.5);
|
||||||
margin-right: 16upx;
|
margin-right: 16rpx;
|
||||||
font-size: 28upx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
input{
|
input{
|
||||||
color: rgba(255,255,255,0.5);
|
color: rgba(255,255,255,0.5);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-right: 30upx;
|
padding-right: 30rpx;
|
||||||
height: 64upx;
|
height: 64rpx;
|
||||||
line-height: 64upx;
|
line-height: 64rpx;
|
||||||
font-size: 26upx;
|
font-size: 26rpx;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
.phcolor{
|
.phcolor{
|
||||||
color: rgba(255,255,255,0.5);
|
color: rgba(255,255,255,0.5);
|
||||||
|
@ -56,8 +56,8 @@
|
||||||
}
|
}
|
||||||
.icon-ui {
|
.icon-ui {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 42upx;
|
font-size: 42rpx;
|
||||||
margin-right: 22upx;
|
margin-right: 22rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.banner_img{
|
.banner_img{
|
||||||
|
@ -75,11 +75,11 @@
|
||||||
|
|
||||||
.home-apps {
|
.home-apps {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0upx;
|
top: 0rpx;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 30upx 20upx;
|
padding: 30rpx 20rpx;
|
||||||
border-radius: 40upx;
|
border-radius: 40rpx;
|
||||||
margin: 0 30upx;
|
margin: 0 30rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap:wrap;
|
flex-wrap:wrap;
|
||||||
.home-apps-item {
|
.home-apps-item {
|
||||||
|
@ -89,14 +89,14 @@
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
width: 25%;
|
width: 25%;
|
||||||
.text {
|
.text {
|
||||||
margin: 10upx 0;
|
margin: 10rpx 0;
|
||||||
font-size: 28upx;
|
font-size: 28rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 140upx;
|
width: 140rpx;
|
||||||
}
|
}
|
||||||
.home-apps-item-img {
|
.home-apps-item-img {
|
||||||
width: 136upx;
|
width: 136rpx;
|
||||||
height: 136upx;
|
height: 136rpx;
|
||||||
image {
|
image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -106,39 +106,39 @@
|
||||||
}
|
}
|
||||||
.home-message{
|
.home-message{
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -160upx;
|
top: -160rpx;
|
||||||
height: 120upx;
|
height: 120rpx;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 40upx;
|
border-radius: 40rpx;
|
||||||
margin: 0 30upx;
|
margin: 0 30rpx;
|
||||||
padding: 0 30upx;
|
padding: 0 30rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.home-title{
|
.home-title{
|
||||||
width: 54px;
|
width: 54px;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
margin-right: 10upx;
|
margin-right: 10rpx;
|
||||||
image{
|
image{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.home-content{
|
.home-content{
|
||||||
font-size: 28upx;
|
font-size: 28rpx;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
.home-more{
|
.home-more{
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
font-size: 26upx;
|
font-size: 26rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.home-letters{
|
.home-letters{
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -140upx;
|
top: -140rpx;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 40upx;
|
border-radius: 40rpx;
|
||||||
margin: 0 30upx;
|
margin: 0 30rpx;
|
||||||
padding: 30upx;
|
padding: 30rpx;
|
||||||
|
|
||||||
.letters-title{
|
.letters-title{
|
||||||
width: 80px;
|
width: 80px;
|
||||||
|
@ -150,17 +150,17 @@
|
||||||
}
|
}
|
||||||
.letters-content{
|
.letters-content{
|
||||||
.letters-item{
|
.letters-item{
|
||||||
border-bottom: 1upx solid #e5e5e5;
|
border-bottom: 1rpx solid #e5e5e5;
|
||||||
padding: 20upx 0;
|
padding: 20rpx 0;
|
||||||
&:last-child{
|
&:last-child{
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
.lable{
|
.lable{
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.font{
|
.font{
|
||||||
font-size: 28upx;
|
font-size: 28rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
.letters-title{
|
.letters-title{
|
||||||
|
@ -186,14 +186,14 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
margin: 10upx 0;
|
margin: 10rpx 0;
|
||||||
}
|
}
|
||||||
.letters-date{
|
.letters-date{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@
|
||||||
}
|
}
|
||||||
.home-line{
|
.home-line{
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -70upx;
|
top: -70rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
@ -214,19 +214,19 @@
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
.grid_item{
|
.grid_item{
|
||||||
width: calc(47% - 4upx);
|
width: calc(47% - 4rpx);
|
||||||
display: block;
|
display: block;
|
||||||
padding: 30upx 0;
|
padding: 30rpx 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
margin-left: 2%;
|
margin-left: 2%;
|
||||||
margin-top: 2%;
|
margin-top: 2%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-image: linear-gradient(to bottom right, rgba(0,138,255,1), rgba(91,74,255,1));
|
background-image: linear-gradient(to bottom right, rgba(0,138,255,1), rgba(91,74,255,1));
|
||||||
border: 1upx solid #2084d9;
|
border: 1rpx solid #2084d9;
|
||||||
position: relative;
|
position: relative;
|
||||||
.grid_text{
|
.grid_text{
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 30upx;
|
padding-left: 30rpx;
|
||||||
.grid_tut{
|
.grid_tut{
|
||||||
width: 85%;
|
width: 85%;
|
||||||
}
|
}
|
||||||
|
@ -236,28 +236,28 @@
|
||||||
|
|
||||||
|
|
||||||
.message_list{
|
.message_list{
|
||||||
padding: 30upx;
|
padding: 30rpx;
|
||||||
.message_item{
|
.message_item{
|
||||||
position: relative;
|
position: relative;
|
||||||
.message_flex{
|
.message_flex{
|
||||||
width: calc(100% - 30upx);
|
width: calc(100% - 30rpx);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.fontstyle{
|
.fontstyle{
|
||||||
font-size: 32upx;
|
font-size: 32rpx;
|
||||||
line-height: 60upx;
|
line-height: 60rpx;
|
||||||
}
|
}
|
||||||
.font0{
|
.font0{
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
flex-basis: 72upx;
|
flex-basis: 72rpx;
|
||||||
}
|
}
|
||||||
.message_time{
|
.message_time{
|
||||||
font-size: 26upx;
|
font-size: 26rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
line-height: 60upx;
|
line-height: 60rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,12 +270,12 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
width: 30upx;
|
width: 30rpx;
|
||||||
height: 30upx;
|
height: 30rpx;
|
||||||
color: #b4b4b4;
|
color: #b4b4b4;
|
||||||
content: "\e6a3";
|
content: "\e6a3";
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 34upx;
|
font-size: 34rpx;
|
||||||
font-family: cuIcon;
|
font-family: cuIcon;
|
||||||
line-height: 30upx
|
line-height: 30rpx
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
.ml-10{
|
.ml-10{
|
||||||
margin-left: 20upx !important;
|
margin-left: 20rpx !important;
|
||||||
}
|
}
|
||||||
.mt-10{
|
.mt-10{
|
||||||
margin-top: 20upx !important;
|
margin-top: 20rpx !important;
|
||||||
}
|
}
|
||||||
.mb-10{
|
.mb-10{
|
||||||
margin-bottom: 20upx !important;
|
margin-bottom: 20rpx !important;
|
||||||
}
|
}
|
||||||
.mr-10{
|
.mr-10{
|
||||||
margin-right: 20upx !important;
|
margin-right: 20rpx !important;
|
||||||
}
|
}
|
||||||
.m-10{
|
.m-10{
|
||||||
margin: 20upx !important;
|
margin: 20rpx !important;
|
||||||
}
|
}
|
||||||
.p-10{
|
.p-10{
|
||||||
padding: 20upx !important;
|
padding: 20rpx !important;
|
||||||
}
|
}
|
||||||
.pl-10{
|
.pl-10{
|
||||||
padding-left: 20upx !important;
|
padding-left: 20rpx !important;
|
||||||
}
|
}
|
||||||
.pr-10{
|
.pr-10{
|
||||||
padding-right: 20upx !important;
|
padding-right: 20rpx !important;
|
||||||
}
|
}
|
||||||
.pt-10{
|
.pt-10{
|
||||||
padding-top: 20upx !important;
|
padding-top: 20rpx !important;
|
||||||
}
|
}
|
||||||
.pb-10{
|
.pb-10{
|
||||||
padding-bottom: 20upx !important;
|
padding-bottom: 20rpx !important;
|
||||||
}
|
}
|
||||||
.w100{
|
.w100{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
background-color: $uni-bg-color-grey;
|
background-color: $uni-bg-color-grey;
|
||||||
}
|
}
|
||||||
.card{
|
.card{
|
||||||
padding: 20upx;
|
padding: 20rpx;
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
}
|
}
|
||||||
.search{
|
.search{
|
||||||
|
@ -54,25 +54,25 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
.u-text{
|
.u-text{
|
||||||
width: 100upx !important;
|
width: 100rpx !important;
|
||||||
flex: none !important;
|
flex: none !important;
|
||||||
}
|
}
|
||||||
.u-button {
|
.u-button {
|
||||||
height: 68upx !important;
|
height: 68rpx !important;
|
||||||
}
|
}
|
||||||
.u-input__content__field-wrapper__field{
|
.u-input__content__field-wrapper__field{
|
||||||
height: 42upx !important;
|
height: 42rpx !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.bth-mini{
|
.bth-mini{
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
border-radius: 15upx !important;
|
border-radius: 15rpx !important;
|
||||||
margin-left: unset;
|
margin-left: unset;
|
||||||
margin-right: unset;
|
margin-right: unset;
|
||||||
}
|
}
|
||||||
.bth{
|
.bth{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: 15upx !important;
|
border-radius: 15rpx !important;
|
||||||
margin-left: unset;
|
margin-left: unset;
|
||||||
margin-right: unset;
|
margin-right: unset;
|
||||||
}
|
}
|
||||||
|
@ -93,23 +93,23 @@
|
||||||
}
|
}
|
||||||
.main-title{
|
.main-title{
|
||||||
color: #333333;
|
color: #333333;
|
||||||
font-size: 30upx;
|
font-size: 30rpx;
|
||||||
}
|
}
|
||||||
.subtitle{
|
.subtitle{
|
||||||
color: #888888;
|
color: #888888;
|
||||||
font-size: 26upx;
|
font-size: 26rpx;
|
||||||
}
|
}
|
||||||
.view-title{
|
.view-title{
|
||||||
border-left: 8upx solid #1d82fe;
|
border-left: 8rpx solid #1d82fe;
|
||||||
.u-text{
|
.u-text{
|
||||||
padding-left: 10upx;
|
padding-left: 10rpx;
|
||||||
color: #353535 !important;
|
color: #353535 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.title{
|
.title{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
font-size: 28upx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
.title-none{
|
.title-none{
|
||||||
.u-cell__body__content,.u-cell__title{
|
.u-cell__body__content,.u-cell__title{
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
color: #f56c6c;
|
color: #f56c6c;
|
||||||
font-size: 40upx;
|
font-size: 40rpx;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
.u-form-item__body__right__content__slot{
|
.u-form-item__body__right__content__slot{
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-left: 20upx;
|
margin-left: 20rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
.u-list {
|
.u-list {
|
||||||
.u-list-item {
|
.u-list-item {
|
||||||
padding: 20upx;
|
padding: 20rpx;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-bottom: 1px solid rgb(214, 215, 217);
|
border-bottom: 1px solid rgb(214, 215, 217);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.u-textarea{
|
.u-textarea{
|
||||||
padding: 18upx;
|
padding: 18rpx;
|
||||||
}
|
}
|
||||||
.u-form-item__body__left__content__required{
|
.u-form-item__body__left__content__required{
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
|
@ -27,10 +27,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.u-text__value{
|
.u-text__value{
|
||||||
font-size: 28upx !important;
|
font-size: 28rpx !important;
|
||||||
}
|
}
|
||||||
.u-form-item__body__left__content__label{
|
.u-form-item__body__left__content__label{
|
||||||
font-size: 28upx !important;
|
font-size: 28rpx !important;
|
||||||
}
|
}
|
||||||
.u-tabs__wrapper__nav__item{
|
.u-tabs__wrapper__nav__item{
|
||||||
flex: 1 !important;
|
flex: 1 !important;
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
## 1.0.4(2023-04-17)
|
|
||||||
- chore: 删除多余字符
|
|
||||||
## 1.0.3(2023-04-15)
|
|
||||||
- BUG: QQ小程序可以使用,会有报错但不影响使用
|
|
||||||
## 1.0.2(2023-04-15)
|
|
||||||
- feat: 支持横屏
|
|
||||||
- BUG: QQ小程序无法使用,为UNI官方问题,插件所需要的API传this都会报错。
|
|
||||||
## 1.0.1(2023-04-03)
|
|
||||||
- fix: 销毁时报错
|
|
||||||
## 1.0.0(2022-10-27)
|
|
||||||
- feat: 增加背景色
|
|
||||||
- feat: 修复 app canvasToTempFilePath 无操作只能执行一次的问题
|
|
||||||
## 0.8.0(2022-08-22)
|
|
||||||
- feat: 增加beforeDelay 延时初始化,可用于手写板在弹窗里时
|
|
||||||
## 0.7.0(2022-08-16)
|
|
||||||
- fix: 修复缺少 canvasWidth
|
|
||||||
## 0.6.0(2022-07-16)
|
|
||||||
- fix: 修复 success is no defined
|
|
||||||
## 0.5.0(2022-07-09)
|
|
||||||
- feat: canvasToTempFilePath success 增加返回 isEmpty
|
|
||||||
- fix: 修复 微信小程序 canvasToTempFilePath 无效问题
|
|
||||||
## 0.4.0(2022-07-04)
|
|
||||||
- fix: 生成图片缺少最后一笔
|
|
||||||
## 0.3.0(2022-05-24)
|
|
||||||
- chore: 支持多端 H5 小程序 APP APP-NVUE
|
|
||||||
## 0.2.0(2021-07-09)
|
|
||||||
- chore: 统一命名规范,无须主动引入组件
|
|
||||||
- fix: 修复错位问题
|
|
||||||
## 0.1.0(2021-03-07)
|
|
||||||
- 首次上传
|
|
||||||
- 撤消、清空、保存、模拟压感等功能
|
|
|
@ -1,64 +0,0 @@
|
||||||
export const uniContext = (ctx) => {
|
|
||||||
ctx.uniDrawImage = ctx.drawImage
|
|
||||||
ctx.drawImage = (image,...agrs) => {
|
|
||||||
ctx.uniDrawImage(image.src, ...agrs)
|
|
||||||
}
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
class Image {
|
|
||||||
constructor() {
|
|
||||||
this.currentSrc = null
|
|
||||||
this.naturalHeight = 0
|
|
||||||
this.naturalWidth = 0
|
|
||||||
this.width = 0
|
|
||||||
this.height = 0
|
|
||||||
this.tagName = 'IMG'
|
|
||||||
}
|
|
||||||
set src(src) {
|
|
||||||
this.currentSrc = src
|
|
||||||
uni.getImageInfo({
|
|
||||||
src,
|
|
||||||
success: (res) => {
|
|
||||||
this.naturalWidth = this.width = res.width
|
|
||||||
this.naturalHeight = this.height = res.height
|
|
||||||
this.onload()
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
this.onerror()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
get src() {
|
|
||||||
return this.currentSrc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createImage = () => {
|
|
||||||
return new Image()
|
|
||||||
}
|
|
||||||
export function useCurrentPage() {
|
|
||||||
const pages = getCurrentPages();
|
|
||||||
return pages[pages.length - 1];
|
|
||||||
}
|
|
||||||
export const toDataURL = (canvasId, context, options = {}) => {
|
|
||||||
// #ifdef MP-QQ
|
|
||||||
// context = context.$scope
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-ALIPAY
|
|
||||||
context = ''
|
|
||||||
// #endif
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
uni.canvasToTempFilePath({
|
|
||||||
...options,
|
|
||||||
canvasId,
|
|
||||||
success: (res) => {
|
|
||||||
resolve(res.tempFilePath)
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
}, context)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,383 +0,0 @@
|
||||||
<template>
|
|
||||||
<view class="lime-signature" v-if="show" :style="[canvasStyle, styles]" ref="limeSignature">
|
|
||||||
<!-- #ifndef APP-VUE || APP-NVUE -->
|
|
||||||
<canvas
|
|
||||||
v-if="useCanvas2d"
|
|
||||||
class="lime-signature__canvas"
|
|
||||||
:id="canvasId"
|
|
||||||
type="2d"
|
|
||||||
:disableScroll="disableScroll"
|
|
||||||
@touchstart="touchStart"
|
|
||||||
@touchmove="touchMove"
|
|
||||||
@touchend="touchEnd"
|
|
||||||
></canvas>
|
|
||||||
<canvas
|
|
||||||
v-else
|
|
||||||
:disableScroll="disableScroll"
|
|
||||||
class="lime-signature__canvas"
|
|
||||||
:canvas-id="canvasId"
|
|
||||||
:id="canvasId"
|
|
||||||
:width="canvasWidth"
|
|
||||||
:height="canvasHeight"
|
|
||||||
@touchstart="touchStart"
|
|
||||||
@touchmove="touchMove"
|
|
||||||
@touchend="touchEnd"
|
|
||||||
@mousedown="touchStart"
|
|
||||||
@mousemove="touchMove"
|
|
||||||
@mouseup="touchEnd"
|
|
||||||
></canvas>
|
|
||||||
<canvas
|
|
||||||
class="offscreen"
|
|
||||||
canvas-id="offscreen"
|
|
||||||
id="offscreen"
|
|
||||||
:style="'width:' + offscreenSize[0] + 'px;height:' + offscreenSize[1] + 'px'"
|
|
||||||
:width="offscreenSize[0]"
|
|
||||||
:height="offscreenSize[1]">
|
|
||||||
</canvas>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifdef APP-VUE -->
|
|
||||||
<view
|
|
||||||
:id="canvasId"
|
|
||||||
:disableScroll="disableScroll"
|
|
||||||
:rparam="param"
|
|
||||||
:change:rparam="sign.update"
|
|
||||||
|
|
||||||
:rclear="rclear"
|
|
||||||
:change:rclear="sign.clear"
|
|
||||||
|
|
||||||
:rundo="rundo"
|
|
||||||
:change:rundo="sign.undo"
|
|
||||||
|
|
||||||
:rsave="rsave"
|
|
||||||
:change:rsave="sign.save"
|
|
||||||
|
|
||||||
:rempty="rempty"
|
|
||||||
:change:rempty="sign.isEmpty"
|
|
||||||
|
|
||||||
></view>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifdef APP-NVUE -->
|
|
||||||
<web-view
|
|
||||||
src="/uni_modules/lime-signature/static/index.html"
|
|
||||||
class="lime-signature__canvas"
|
|
||||||
ref="webview"
|
|
||||||
@pagefinish="onPageFinish"
|
|
||||||
@error="onError"
|
|
||||||
@onPostMessage="onMessage"
|
|
||||||
></web-view>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<!-- #ifdef APP-VUE -->
|
|
||||||
<script module="sign" lang="renderjs">
|
|
||||||
export {default} from './render'
|
|
||||||
</script>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// #ifndef APP-NVUE
|
|
||||||
import {canIUseCanvas2d, wrapEvent, requestAnimationFrame, sleep} from './utils'
|
|
||||||
import {Signature} from './signature'
|
|
||||||
// import {Signature} from '@signature';
|
|
||||||
import {uniContext, createImage, toDataURL} from './context'
|
|
||||||
// #endif
|
|
||||||
import props from './props';
|
|
||||||
import {base64ToPath, getRect} from './utils'
|
|
||||||
export default {
|
|
||||||
props,
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
canvasWidth: null,
|
|
||||||
canvasHeight: null,
|
|
||||||
useCanvas2d: true,
|
|
||||||
show: true,
|
|
||||||
offscreenStyles: '',
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
rclear: 0,
|
|
||||||
rundo: 0,
|
|
||||||
rsave: 0,
|
|
||||||
rempty: 0,
|
|
||||||
risEmpty: true,
|
|
||||||
toDataURL: null,
|
|
||||||
tempFilePath: [],
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
canvasId() {
|
|
||||||
return `lime-signature${this._uid||this._.uid}`
|
|
||||||
},
|
|
||||||
offscreenId() {
|
|
||||||
return this.canvasId + 'offscreen'
|
|
||||||
},
|
|
||||||
offscreenSize() {
|
|
||||||
const {canvasWidth, canvasHeight} = this
|
|
||||||
return this.landscape ? [canvasHeight, canvasWidth] : [canvasWidth, canvasHeight]
|
|
||||||
},
|
|
||||||
canvasStyle() {
|
|
||||||
const {canvasWidth, canvasHeight, backgroundColor} = this
|
|
||||||
return {
|
|
||||||
width: canvasWidth && (canvasWidth + 'px'),
|
|
||||||
height: canvasHeight && (canvasHeight + 'px'),
|
|
||||||
background: backgroundColor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
param() {
|
|
||||||
const {penColor, penSize, backgroundColor, landscape, openSmooth, minLineWidth, maxLineWidth, minSpeed, maxWidthDiffRate, maxHistoryLength, disableScroll} = this
|
|
||||||
return JSON.parse(JSON.stringify({penColor, penSize, backgroundColor, landscape, openSmooth, minLineWidth, maxLineWidth, minSpeed, maxWidthDiffRate, maxHistoryLength, disableScroll}))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
watch: {
|
|
||||||
param(v) {
|
|
||||||
this.$refs.webview.evalJS(`update(${JSON.stringify(v)})`)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
created() {
|
|
||||||
this.useCanvas2d = this.type == '2d' && canIUseCanvas2d()
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
async mounted() {
|
|
||||||
if(this.beforeDelay) {
|
|
||||||
await sleep(this.beforeDelay)
|
|
||||||
}
|
|
||||||
const config = await this.getContext()
|
|
||||||
this.signature = new Signature(config)
|
|
||||||
this.canvasEl = this.signature.canvas.get('el')
|
|
||||||
this.canvasWidth = this.signature.canvas.get('width')
|
|
||||||
this.canvasHeight = this.signature.canvas.get('height')
|
|
||||||
|
|
||||||
this.stopWatch = this.$watch('param' , (v) => {
|
|
||||||
this.signature.pen.setOption(v)
|
|
||||||
}, {immediate: true})
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
// #ifdef VUE3
|
|
||||||
beforeUnmount() {
|
|
||||||
this.stopWatch && this.stopWatch()
|
|
||||||
this.signature.destroy()
|
|
||||||
this.signature = null
|
|
||||||
this.show = false;
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #ifdef VUE2
|
|
||||||
beforeDestroy() {
|
|
||||||
this.stopWatch && this.stopWatch()
|
|
||||||
this.signature.destroy()
|
|
||||||
this.show = false;
|
|
||||||
this.signature = null
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #endif
|
|
||||||
methods: {
|
|
||||||
// #ifdef MP-QQ
|
|
||||||
// toJSON() { return this },
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
onPageFinish() {
|
|
||||||
this.$refs.webview.evalJS(`update(${JSON.stringify(this.param)})`)
|
|
||||||
},
|
|
||||||
onMessage(e = {}) {
|
|
||||||
const {detail: {data: [res]}} = e
|
|
||||||
if(res.event?.save) {
|
|
||||||
this.toDataURL = res.event.save
|
|
||||||
}
|
|
||||||
if(res.event?.changeSize) {
|
|
||||||
const {width, height} = res.event.changeSize
|
|
||||||
}
|
|
||||||
if(res.event.hasOwnProperty('isEmpty')) {
|
|
||||||
this.risEmpty = res.event.isEmpty
|
|
||||||
}
|
|
||||||
if (res.event?.file) {
|
|
||||||
this.tempFilePath.push(res.event.file)
|
|
||||||
if (this.tempFilePath.length > 7) {
|
|
||||||
this.tempFilePath.shift()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (res.event?.success) {
|
|
||||||
if (res.event.success) {
|
|
||||||
this.tempFilePath.push(res.event.success)
|
|
||||||
if (this.tempFilePath.length > 8) {
|
|
||||||
this.tempFilePath.shift()
|
|
||||||
}
|
|
||||||
this.toDataURL = this.tempFilePath.join('')
|
|
||||||
this.tempFilePath = []
|
|
||||||
} else {
|
|
||||||
this.$emit('fail', 'canvas no data')
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
undo() {
|
|
||||||
// #ifdef APP-VUE || APP-NVUE
|
|
||||||
this.rundo += 1
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
this.$refs.webview.evalJS(`undo()`)
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-VUE
|
|
||||||
if(this.signature)
|
|
||||||
this.signature.undo()
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
clear() {
|
|
||||||
// #ifdef APP-VUE || APP-NVUE
|
|
||||||
this.rclear += 1
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
this.$refs.webview.evalJS(`clear()`)
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-VUE
|
|
||||||
if(this.signature)
|
|
||||||
this.signature.clear()
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
isEmpty() {
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
this.$refs.webview.evalJS(`isEmpty()`)
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-VUE || APP-NVUE
|
|
||||||
this.rempty += 1
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-VUE || APP-NVUE
|
|
||||||
return this.signature.isEmpty()
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
canvasToTempFilePath(param) {
|
|
||||||
const isEmpty = this.isEmpty()
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
this.$refs.webview.evalJS(`save()`)
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-VUE || APP-NVUE
|
|
||||||
const stopURLWatch = this.$watch('toDataURL', (v, n) => {
|
|
||||||
if(v && v !== n) {
|
|
||||||
// if(param.pathType == 'url') {
|
|
||||||
base64ToPath(v).then(res => {
|
|
||||||
param.success({tempFilePath: res,isEmpty: this.risEmpty })
|
|
||||||
})
|
|
||||||
// } else {
|
|
||||||
// param.success({tempFilePath: v,isEmpty: this.risEmpty })
|
|
||||||
// }
|
|
||||||
this.toDataURL = ''
|
|
||||||
}
|
|
||||||
stopURLWatch && stopURLWatch()
|
|
||||||
})
|
|
||||||
this.rsave += 1
|
|
||||||
// #endif
|
|
||||||
// #ifndef APP-VUE || APP-NVUE
|
|
||||||
const success = (success) => param.success && param.success(success)
|
|
||||||
const fail = (fail) => param.fail && param.fail(err)
|
|
||||||
const {canvas} = this.signature.canvas.get('el')
|
|
||||||
const {backgroundColor, landscape} = this
|
|
||||||
const width = this.signature.canvas.get('width')
|
|
||||||
const height = this.signature.canvas.get('height')
|
|
||||||
|
|
||||||
const canvasToTempFilePath = (image) => {
|
|
||||||
const context = uni.createCanvasContext('offscreen', this)
|
|
||||||
context.save()
|
|
||||||
context.setTransform(1,0,0,1,0,0)
|
|
||||||
if(landscape) {
|
|
||||||
context.translate(0, width)
|
|
||||||
context.rotate(-Math.PI / 2)
|
|
||||||
}
|
|
||||||
if(backgroundColor) {
|
|
||||||
context.fillStyle = backgroundColor
|
|
||||||
context.fillRect(0,0, width, height)
|
|
||||||
}
|
|
||||||
context.drawImage(image, 0, 0, width, height);
|
|
||||||
|
|
||||||
context.draw(false, () => {
|
|
||||||
toDataURL('offscreen', this, param).then((res) => {
|
|
||||||
const size = Math.max(width, height)
|
|
||||||
context.restore()
|
|
||||||
context.clearRect(0,0, size, size)
|
|
||||||
success({tempFilePath: res, isEmpty})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.useCanvas2d) {
|
|
||||||
try{
|
|
||||||
// #ifndef MP-ALIPAY
|
|
||||||
base64ToPath(canvas.toDataURL()).then(canvasToTempFilePath)
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-ALIPAY
|
|
||||||
canvas.toTempFilePath({
|
|
||||||
canvasid: this.canvasid,
|
|
||||||
success(res){
|
|
||||||
canvasToTempFilePath(res.tempFilePath)
|
|
||||||
},
|
|
||||||
fail
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
} catch(err){fail(err)}
|
|
||||||
} else {
|
|
||||||
toDataURL(this.canvasId, this).then(canvasToTempFilePath).catch(fail)
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
// #ifndef APP-PLUS
|
|
||||||
getContext() {
|
|
||||||
return getRect(`#${this.canvasId}`, {context: this, type: this.useCanvas2d ? 'fields': 'boundingClientRect'}).then(res => {
|
|
||||||
if(res) {
|
|
||||||
let {width, height, node: canvas, left, top, right} = res
|
|
||||||
let {pixelRatio} = uni.getSystemInfoSync()
|
|
||||||
let context;
|
|
||||||
if(canvas) {
|
|
||||||
context = canvas.getContext('2d')
|
|
||||||
canvas.width = width * pixelRatio;
|
|
||||||
canvas.height = height * pixelRatio;
|
|
||||||
} else {
|
|
||||||
pixelRatio = 1
|
|
||||||
context = uniContext(uni.createCanvasContext(this.canvasId, this))
|
|
||||||
canvas = {
|
|
||||||
createImage,
|
|
||||||
toDataURL: () => toDataURL(this.canvasId, this),
|
|
||||||
requestAnimationFrame
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 支付宝小程序 使用stroke有个默认背景色
|
|
||||||
context.clearRect(0,0,width,height)
|
|
||||||
return { left, top, right, width, height, context, canvas, pixelRatio};
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
touchStart(e) {
|
|
||||||
if(!this.canvasEl) return
|
|
||||||
this.isStart = true
|
|
||||||
this.canvasEl.dispatchEvent('touchstart', wrapEvent(e))
|
|
||||||
},
|
|
||||||
touchMove(e) {
|
|
||||||
if(!this.canvasEl || !this.isStart && this.canvasEl) return
|
|
||||||
this.canvasEl.dispatchEvent('touchmove', wrapEvent(e))
|
|
||||||
},
|
|
||||||
touchEnd(e) {
|
|
||||||
if(!this.canvasEl) return
|
|
||||||
this.isStart = false
|
|
||||||
this.canvasEl.dispatchEvent('touchend', wrapEvent(e))
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="stylus">
|
|
||||||
.lime-signature,.lime-signature__canvas
|
|
||||||
// #ifndef APP-NVUE
|
|
||||||
width: 100%;
|
|
||||||
height: 100%
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-NVUE
|
|
||||||
flex: 1;
|
|
||||||
// #endif
|
|
||||||
.offscreen {
|
|
||||||
position: fixed;
|
|
||||||
top: 0
|
|
||||||
left: 1500rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,56 +0,0 @@
|
||||||
export default {
|
|
||||||
styles: String,
|
|
||||||
disableScroll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: '2d'
|
|
||||||
},
|
|
||||||
// 画笔颜色
|
|
||||||
penColor: {
|
|
||||||
type: String,
|
|
||||||
default: 'black'
|
|
||||||
},
|
|
||||||
penSize: {
|
|
||||||
type: Number,
|
|
||||||
default: 2
|
|
||||||
},
|
|
||||||
// 画板背景颜色
|
|
||||||
backgroundColor: String,
|
|
||||||
// 笔锋
|
|
||||||
openSmooth: Boolean,
|
|
||||||
// 画笔最小值
|
|
||||||
minLineWidth: {
|
|
||||||
type: Number,
|
|
||||||
default: 2
|
|
||||||
},
|
|
||||||
// 画笔最大值
|
|
||||||
maxLineWidth: {
|
|
||||||
type: Number,
|
|
||||||
default: 6
|
|
||||||
},
|
|
||||||
// 画笔达到最小宽度所需最小速度(px/ms),取值范围1.0-10.0,值越小,画笔越容易变细,笔锋效果会比较明显,可以自行调整查看效果,选出自己满意的值。
|
|
||||||
minSpeed: {
|
|
||||||
type: Number,
|
|
||||||
default: 1.5
|
|
||||||
},
|
|
||||||
// 相邻两线宽度增(减)量最大百分比,取值范围1-100,为了达到笔锋效果,画笔宽度会随画笔速度而改变,如果相邻两线宽度差太大,过渡效果就会很突兀,使用maxWidthDiffRate限制宽度差,让过渡效果更自然。可以自行调整查看效果,选出自己满意的值。
|
|
||||||
maxWidthDiffRate: {
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
// 限制历史记录数,即最大可撤销数,传入0则关闭历史记录功能
|
|
||||||
maxHistoryLength: {
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
beforeDelay: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
landscape: {
|
|
||||||
type: Boolean
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
// #ifdef APP-VUE
|
|
||||||
// import { Signature } from '@signature'
|
|
||||||
import { Signature } from './signature'
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
canvasid: null,
|
|
||||||
signature: null,
|
|
||||||
observer: null,
|
|
||||||
options: {},
|
|
||||||
saveCount: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$nextTick(this.init)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
init() {
|
|
||||||
const el = this.$refs.limeSignature;
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
canvas.style = 'width:100%; height: 100%;'
|
|
||||||
el.appendChild(canvas)
|
|
||||||
this.signature = new Signature({
|
|
||||||
el: canvas
|
|
||||||
})
|
|
||||||
this.signature.pen.setOption(this.options)
|
|
||||||
const width = this.signature.canvas.get('width')
|
|
||||||
const height = this.signature.canvas.get('height')
|
|
||||||
|
|
||||||
this.emit({
|
|
||||||
changeSize: {
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
undo(v) {
|
|
||||||
if (v && this.signature) {
|
|
||||||
this.signature.undo()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clear(v) {
|
|
||||||
if (v && this.signature) {
|
|
||||||
this.signature.clear()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
save(v) {
|
|
||||||
if (v !== this.saveCount) {
|
|
||||||
this.saveCount = v;
|
|
||||||
const image = this.signature.canvas.get('el').toDataURL()
|
|
||||||
const {backgroundColor,landscape} = this.options
|
|
||||||
if (landscape || backgroundColor) {
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
const width = this.signature.canvas.get('width')
|
|
||||||
const height = this.signature.canvas.get('height')
|
|
||||||
const pixelRatio = this.signature.canvas.get('pixelRatio')
|
|
||||||
const size = [width, height]
|
|
||||||
if(landscape) {size.reverse()}
|
|
||||||
canvas.width = size[0] * pixelRatio
|
|
||||||
canvas.height = size[1] * pixelRatio
|
|
||||||
const context = canvas.getContext('2d')
|
|
||||||
context.scale(pixelRatio, pixelRatio)
|
|
||||||
if (landscape) {
|
|
||||||
context.translate(0, width)
|
|
||||||
context.rotate(-Math.PI / 2)
|
|
||||||
}
|
|
||||||
if (backgroundColor) {
|
|
||||||
context.fillStyle = backgroundColor
|
|
||||||
context.fillRect(0, 0, width, height)
|
|
||||||
}
|
|
||||||
context.drawImage(this.signature.canvas.get('el'), 0, 0, width, height)
|
|
||||||
this.emit({
|
|
||||||
save: canvas.toDataURL()
|
|
||||||
})
|
|
||||||
canvas.remove()
|
|
||||||
} else {
|
|
||||||
this.emit({
|
|
||||||
save: image
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isEmpty(v) {
|
|
||||||
if (v && this.signature) {
|
|
||||||
const isEmpty = this.signature.isEmpty()
|
|
||||||
this.emit({
|
|
||||||
isEmpty
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emit(event) {
|
|
||||||
this.$ownerInstance.callMethod('onMessage', {
|
|
||||||
detail: {
|
|
||||||
data: [{
|
|
||||||
event
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
update(v) {
|
|
||||||
if (v) {
|
|
||||||
if (this.signature) {
|
|
||||||
this.options = v
|
|
||||||
this.signature.pen.setOption(v)
|
|
||||||
} else {
|
|
||||||
this.options = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #endif
|
|
|
@ -1,139 +0,0 @@
|
||||||
export function compareVersion(v1, v2) {
|
|
||||||
v1 = v1.split('.')
|
|
||||||
v2 = v2.split('.')
|
|
||||||
const len = Math.max(v1.length, v2.length)
|
|
||||||
while (v1.length < len) {
|
|
||||||
v1.push('0')
|
|
||||||
}
|
|
||||||
while (v2.length < len) {
|
|
||||||
v2.push('0')
|
|
||||||
}
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
const num1 = parseInt(v1[i], 10)
|
|
||||||
const num2 = parseInt(v2[i], 10)
|
|
||||||
|
|
||||||
if (num1 > num2) {
|
|
||||||
return 1
|
|
||||||
} else if (num1 < num2) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function gte(version) {
|
|
||||||
let {SDKVersion} = uni.getSystemInfoSync();
|
|
||||||
// #ifdef MP-ALIPAY
|
|
||||||
SDKVersion = my.SDKVersion
|
|
||||||
// #endif
|
|
||||||
return compareVersion(SDKVersion, version) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function canIUseCanvas2d() {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
return gte('2.9.0');
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-ALIPAY
|
|
||||||
return gte('2.7.0');
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-TOUTIAO
|
|
||||||
return gte('1.78.0');
|
|
||||||
// #endif
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const wrapEvent = (e) => {
|
|
||||||
if (!e) return;
|
|
||||||
if (!e.preventDefault) {
|
|
||||||
e.preventDefault = function() {};
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const requestAnimationFrame = (cb) => {
|
|
||||||
setTimeout(cb, 30)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* base64转路径
|
|
||||||
* @param {Object} base64
|
|
||||||
*/
|
|
||||||
export function base64ToPath(base64) {
|
|
||||||
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// #ifdef MP
|
|
||||||
const fs = uni.getFileSystemManager()
|
|
||||||
//自定义文件名
|
|
||||||
if (!format) {
|
|
||||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
|
||||||
}
|
|
||||||
const time = new Date().getTime();
|
|
||||||
const filePath = `${uni.env.USER_DATA_PATH}/${time}.${format}`;
|
|
||||||
fs.writeFile({
|
|
||||||
filePath,
|
|
||||||
data: base64.split(',')[1],
|
|
||||||
encoding: 'base64',
|
|
||||||
success() {
|
|
||||||
resolve(filePath)
|
|
||||||
},
|
|
||||||
fail(err) {
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
|
||||||
bitmap.loadBase64Data(base64, () => {
|
|
||||||
if (!format) {
|
|
||||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
|
||||||
}
|
|
||||||
const time = new Date().getTime();
|
|
||||||
const filePath = `_doc/uniapp_temp/${time}.${format}`
|
|
||||||
bitmap.save(filePath, {},
|
|
||||||
() => {
|
|
||||||
bitmap.clear()
|
|
||||||
resolve(filePath)
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
bitmap.clear()
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
}, (error) => {
|
|
||||||
bitmap.clear()
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function sleep(delay) {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, delay))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRect(selector, options = {}) {
|
|
||||||
const typeDefault = 'boundingClientRect'
|
|
||||||
const { context, type = typeDefault} = options
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const dom = uni.createSelectorQuery().in(context).select(selector);
|
|
||||||
const result = (rect) => {
|
|
||||||
if(rect) {
|
|
||||||
resolve(rect)
|
|
||||||
} else {
|
|
||||||
reject()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(type == typeDefault) {
|
|
||||||
dom[type](result).exec()
|
|
||||||
} else {
|
|
||||||
dom[type]({
|
|
||||||
node: true,
|
|
||||||
size: true,
|
|
||||||
rect: true
|
|
||||||
}, result).exec()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,63 +0,0 @@
|
||||||
<template>
|
|
||||||
<view>
|
|
||||||
<view style="width: 750rpx; height: 950rpx;">
|
|
||||||
<l-signature disableScroll backgroundColor="#000" ref="signatureRef" :penColor="penColor" :penSize="penSize"
|
|
||||||
:minLineWidth="2" :openSmooth="openSmooth"></l-signature>
|
|
||||||
</view>
|
|
||||||
<!-- <uni-popup ref="popup" type="bottom">
|
|
||||||
<l-signature v-if="show" beforeDelay="1000" disableScroll backgroundColor="#000" ref="signatureRef2" :penColor="penColor"
|
|
||||||
:penSize="penSize" :minLineWidth="2" :openSmooth="openSmooth"></l-signature>
|
|
||||||
</uni-popup> -->
|
|
||||||
<view>
|
|
||||||
<!-- <button @click="open">弹出</button> -->
|
|
||||||
<button @click="onClick('clear')">清空</button>
|
|
||||||
<button @click="onClick('undo')">撤销</button>
|
|
||||||
<button @click="onClick('save')">保存</button>
|
|
||||||
<button @click="onClick('openSmooth')">压感{{openSmooth?'开':'关'}}</button>
|
|
||||||
</view>
|
|
||||||
<image :src="url" v-if="url" mode="widthFix"></image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
title: 'Hello',
|
|
||||||
penColor: 'red',
|
|
||||||
penSize: 16,
|
|
||||||
url: '',
|
|
||||||
show: false,
|
|
||||||
openSmooth: true,
|
|
||||||
bottomHeight: 0,
|
|
||||||
customBar: this.CustomBar || 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
open() {
|
|
||||||
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
|
|
||||||
this.$refs.popup.open()
|
|
||||||
this.show = true
|
|
||||||
},
|
|
||||||
onClick(type) {
|
|
||||||
if (type == 'openSmooth') {
|
|
||||||
this.openSmooth = !this.openSmooth
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (type == 'save') {
|
|
||||||
this.$refs.signatureRef.canvasToTempFilePath({
|
|
||||||
success: (res) => {
|
|
||||||
this.url = res.tempFilePath
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.$refs.signatureRef)
|
|
||||||
this.$refs.signatureRef[type]()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
|
@ -1,77 +0,0 @@
|
||||||
{
|
|
||||||
"id": "lime-signature",
|
|
||||||
"displayName": "手写板-签名签字",
|
|
||||||
"version": "1.0.4",
|
|
||||||
"description": "手写板签名插件:一款能跑在uniapp各端中的签名插件,支持横屏、背景色、笔画颜色、笔画大小等功能",
|
|
||||||
"keywords": [
|
|
||||||
"写字",
|
|
||||||
"签名",
|
|
||||||
"电子签名",
|
|
||||||
"签字",
|
|
||||||
"横屏"
|
|
||||||
],
|
|
||||||
"repository": "",
|
|
||||||
"engines": {
|
|
||||||
"HBuilderX": "^3.5.4"
|
|
||||||
},
|
|
||||||
"dcloudext": {
|
|
||||||
"sale": {
|
|
||||||
"regular": {
|
|
||||||
"price": "0.00"
|
|
||||||
},
|
|
||||||
"sourcecode": {
|
|
||||||
"price": "0.00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"qq": ""
|
|
||||||
},
|
|
||||||
"declaration": {
|
|
||||||
"ads": "无",
|
|
||||||
"data": "无",
|
|
||||||
"permissions": "无"
|
|
||||||
},
|
|
||||||
"npmurl": "",
|
|
||||||
"type": "component-vue"
|
|
||||||
},
|
|
||||||
"uni_modules": {
|
|
||||||
"dependencies": [],
|
|
||||||
"encrypt": [],
|
|
||||||
"platforms": {
|
|
||||||
"cloud": {
|
|
||||||
"tcb": "y",
|
|
||||||
"aliyun": "y"
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"App": {
|
|
||||||
"app-vue": "y",
|
|
||||||
"app-nvue": "y"
|
|
||||||
},
|
|
||||||
"H5-mobile": {
|
|
||||||
"Safari": "y",
|
|
||||||
"Android Browser": "y",
|
|
||||||
"微信浏览器(Android)": "y",
|
|
||||||
"QQ浏览器(Android)": "y"
|
|
||||||
},
|
|
||||||
"H5-pc": {
|
|
||||||
"Chrome": "y",
|
|
||||||
"IE": "u",
|
|
||||||
"Edge": "u",
|
|
||||||
"Firefox": "y",
|
|
||||||
"Safari": "y"
|
|
||||||
},
|
|
||||||
"小程序": {
|
|
||||||
"微信": "y",
|
|
||||||
"阿里": "u",
|
|
||||||
"百度": "u",
|
|
||||||
"字节跳动": "u",
|
|
||||||
"QQ": "n"
|
|
||||||
},
|
|
||||||
"快应用": {
|
|
||||||
"华为": "u",
|
|
||||||
"联盟": "u"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
# signature 写字板
|
|
||||||
> uniapp 写字板,可用业务签名等场景
|
|
||||||
> [查看更多 站点1](https://limeui.qcoon.cn/#/signature) <br>
|
|
||||||
> [查看更多 站点2](http://liangei.gitee.io/limeui/#/signature)
|
|
||||||
> Q群:1169785031
|
|
||||||
|
|
||||||
|
|
||||||
## 平台兼容
|
|
||||||
|
|
||||||
| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
|
|
||||||
| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- |
|
|
||||||
| √ | √ | √ | 未测 | 未测 | 未测 | √ |
|
|
||||||
|
|
||||||
|
|
||||||
## 代码演示
|
|
||||||
|
|
||||||
### 基本用法
|
|
||||||
```html
|
|
||||||
<view style="width: 750rpx ;height: 750rpx;">
|
|
||||||
<l-signature disableScroll backgroundColor="#ddd" ref="signatureRef" :penColor="penColor" :penSize="penSize" :openSmooth="openSmooth" ></l-signature>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<button @click="onClick('clear')">清空</button>
|
|
||||||
<button @click="onClick('undo')">撤消</button>
|
|
||||||
<button @click="onClick('save')">保存</button>
|
|
||||||
<button @click="onClick('openSmooth')">压感{{openSmooth?'开':'关'}}</button>
|
|
||||||
</view>
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
title: 'Hello',
|
|
||||||
penColor: 'red',
|
|
||||||
penSize: 5,
|
|
||||||
url: '',
|
|
||||||
openSmooth: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onClick(type) {
|
|
||||||
if(type == 'openSmooth') {
|
|
||||||
this.openSmooth = !this.openSmooth
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (type == 'save') {
|
|
||||||
this.$refs.signatureRef.canvasToTempFilePath({
|
|
||||||
success: (res) => {
|
|
||||||
// 是否为空画板 无签名
|
|
||||||
console.log(res.isEmpty)
|
|
||||||
// 生成图片的临时路径
|
|
||||||
// H5 生成的是base64
|
|
||||||
this.url = res.tempFilePath
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.$refs.signatureRef)
|
|
||||||
this.$refs.signatureRef[type]()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### 插件标签
|
|
||||||
- 默认 l-signature 为 component
|
|
||||||
- 默认 lime-signature 为 demo
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
### Props
|
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 |
|
|
||||||
| -------------- | ------------ | ---------------- | ------------ |
|
|
||||||
| penSize | 画笔大小 | <em>number</em> | `2` |
|
|
||||||
| minLineWidth | 线条最小宽 | <em>number</em> | `2` |
|
|
||||||
| maxLineWidth | 线条最大宽 | <em>number</em> | `6` |
|
|
||||||
| penColor | 画笔颜色 | <em>string</em> | `black` |
|
|
||||||
| backgroundColor | 背景颜色 | <em>string</em> | `` |
|
|
||||||
| type | 指定 canvas 类型 | <em>string</em> | `2d` |
|
|
||||||
| openSmooth | 是否模拟压感 | <em>boolean</em> | `false` |
|
|
||||||
| beforeDelay | 延时初始化,在放在弹窗里可以使用 (毫秒) | <em>number</em> | `0` |
|
|
||||||
| maxHistoryLength | 限制历史记录数,即最大可撤销数,传入0则关闭历史记录功能 | <em>boolean</em> | `20` |
|
|
||||||
| landscape | 横屏 | <em>boolean</em> | `` |
|
|
||||||
| disableScroll | 当在写字时,禁止屏幕滚动以及下拉刷新 | <em>boolean</em> | `true` |
|
|
||||||
|
|
||||||
|
|
||||||
### 事件 Events
|
|
||||||
|
|
||||||
| 事件名 | 说明 | 回调 |
|
|
||||||
| ------- | ------------ | -------------- |
|
|
||||||
| undo | 撤消,回退到上一步 | |
|
|
||||||
| clear | 清空,清空画板 | |
|
|
||||||
| canvasToTempFilePath | 保存,生成图片,与官方保持一致,但不需要传canvasId | |
|
|
||||||
|
|
||||||
### 常见问题
|
|
||||||
- 放在弹窗里时,尺寸不对 可以延时手写板出现时机,给手写板加vif或beforeDelay="300"
|
|
||||||
|
|
||||||
### 打赏
|
|
||||||
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
|
|
||||||

|
|
||||||

|
|
|
@ -1,131 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
|
||||||
<title></title>
|
|
||||||
<style type="text/css">
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
canvas {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: hidden;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<canvas id="lime-signature"></canvas>
|
|
||||||
<script type="text/javascript" src="./uni.webview.1.5.3.js"></script>
|
|
||||||
<script type="text/javascript" src="./signature.js"></script>
|
|
||||||
<script>
|
|
||||||
var signature = null;
|
|
||||||
var timer = null;
|
|
||||||
var isStart = false;
|
|
||||||
var options = null
|
|
||||||
console.log = function(...args) {
|
|
||||||
postMessage(args);
|
|
||||||
};
|
|
||||||
// function stringify(key, value) {
|
|
||||||
// if (typeof value === 'object' && value !== null) {
|
|
||||||
// if (cache.indexOf(value) !== -1) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// cache.push(value);
|
|
||||||
// }
|
|
||||||
// return value;
|
|
||||||
// };
|
|
||||||
function emit(event, data) {
|
|
||||||
postMessage({
|
|
||||||
event,
|
|
||||||
data: typeof data !== "object" && data !== null ? data : JSON.stringify(data),
|
|
||||||
});
|
|
||||||
// cache = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function postMessage(data) {
|
|
||||||
uni.postMessage({
|
|
||||||
data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(v = {}) {
|
|
||||||
if (signature) {
|
|
||||||
options = v
|
|
||||||
signature.pen.setOption(v);
|
|
||||||
} else {
|
|
||||||
signature = new Signature.Signature({el: "lime-signature"});
|
|
||||||
canvasEl = signature.canvas.get("el");
|
|
||||||
options = v
|
|
||||||
signature.pen.setOption(v)
|
|
||||||
const width = signature.canvas.get("width");
|
|
||||||
const height = signature.canvas.get("height");
|
|
||||||
|
|
||||||
emit({changeSize: {width,height}})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear() {
|
|
||||||
signature.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
function undo() {
|
|
||||||
signature.undo()
|
|
||||||
}
|
|
||||||
function isEmpty() {
|
|
||||||
const isEmpty = signature.isEmpty()
|
|
||||||
emit({isEmpty});
|
|
||||||
}
|
|
||||||
function save(args) {
|
|
||||||
// delete args.success;
|
|
||||||
// delete args.fail;
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
let path = canvasEl.toDataURL()
|
|
||||||
const {backgroundColor, landscape} = options
|
|
||||||
if(backgroundColor || landscape) {
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
const width = this.signature.canvas.get('width')
|
|
||||||
const height = this.signature.canvas.get('height')
|
|
||||||
const pixelRatio = this.signature.canvas.get('pixelRatio')
|
|
||||||
const size = [width, height]
|
|
||||||
if(landscape) {size.reverse()}
|
|
||||||
canvas.width = size[0] * pixelRatio
|
|
||||||
canvas.height = size[1] * pixelRatio
|
|
||||||
const context = canvas.getContext('2d')
|
|
||||||
context.scale(pixelRatio, pixelRatio)
|
|
||||||
if (landscape) {
|
|
||||||
context.translate(0, width)
|
|
||||||
context.rotate(-Math.PI / 2)
|
|
||||||
}
|
|
||||||
if (backgroundColor) {
|
|
||||||
context.fillStyle = backgroundColor
|
|
||||||
context.fillRect(0, 0, width, height)
|
|
||||||
}
|
|
||||||
context.drawImage(this.signature.canvas.get('el'), 0, 0, width, height)
|
|
||||||
path = canvas.toDataURL()
|
|
||||||
canvas.remove()
|
|
||||||
}
|
|
||||||
if (typeof path == "string") {
|
|
||||||
const index = Math.ceil(path.length / 8);
|
|
||||||
for (var i = 0; i < 8; i++) {
|
|
||||||
if (i == 7) {
|
|
||||||
emit({"success": path.substr(i * index, index)});
|
|
||||||
} else {
|
|
||||||
emit({"file": path.substr(i * index, index)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error("canvas no data");
|
|
||||||
emit({"fail": "canvas no data"});
|
|
||||||
}
|
|
||||||
}, 30);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
## 1.1.8(2024-08-21)
|
||||||
|
1. 修复h5端横屏时可能会出现签名回显的问题
|
||||||
|
## 1.1.7(2024-07-23)
|
||||||
|
1. 修复签字偏移问题
|
||||||
|
## 1.1.6(2024-06-28)
|
||||||
|
1.新增needBack属性:点击取消时是否需要自动返回(默认true)
|
||||||
|
2.修正原取消事件cancel单词写错成cancle的问题
|
||||||
|
## 1.1.5(2024-06-28)
|
||||||
|
1.优化
|
||||||
|
## 1.1.4(2024-05-10)
|
||||||
|
1. 删除冗余代码
|
||||||
|
2. 文档迁移
|
||||||
|
## 1.1.3(2024-04-29)
|
||||||
|
1. 更新示例工程
|
||||||
|
## 1.1.2(2024-04-29)
|
||||||
|
1. 优化了多场景下签名的需求,详情请看示例工程
|
||||||
|
## 1.1.1(2024-04-29)
|
||||||
|
1. 更新
|
||||||
|
## 1.1.0(2024-04-01)
|
||||||
|
1. 更好的兼容支付宝小程序
|
||||||
|
## 1.0.9(2024-03-20)
|
||||||
|
1. 修复小程序无法横屏的问题
|
||||||
|
## 1.0.8(2024-02-28)
|
||||||
|
1. 修复背景颜色修改无效的问题
|
||||||
|
## 1.0.7(2024-02-04)
|
||||||
|
1. 修复签名板在h5端高度异常问题
|
||||||
|
2. 更新示例工程
|
||||||
|
3. 更新文档
|
||||||
|
## 1.0.6(2023-10-20)
|
||||||
|
1. 新增@firstTouchStart首次触碰绘制的方法
|
||||||
|
2. 修复添加动态水印时,初次加载水印失效的bug
|
||||||
|
3. 更新示例项目中水印的使用方式
|
||||||
|
## 1.0.5(2023-10-17)
|
||||||
|
1. 更新示例项目
|
||||||
|
## 1.0.4(2023-10-17)
|
||||||
|
1. 更新文档说明
|
||||||
|
## 1.0.3(2023-10-17)
|
||||||
|
1. 新增图片导出格式与画质配置
|
||||||
|
2. 更新条件编译以更好适配H5、App和小程序端
|
||||||
|
## 1.0.2(2023-10-16)
|
||||||
|
1. 修复横屏适配问题
|
||||||
|
2. 文档更新
|
||||||
|
## 1.0.1(2023-10-16)
|
||||||
|
1. 修复安卓真机canvas无法动态设置宽高的bug
|
||||||
|
2. 修复安卓真机水印与背景底色失效的bug
|
||||||
|
3. 新增监听path字段,现在不仅可以返回base64图片,也可返回临时的图片路径
|
||||||
|
4. 修复vue2、vue3兼容性
|
||||||
|
## 1.0.0(2023-10-13)
|
||||||
|
1. 签字板可添加水印,背景图片,调整画笔样式等
|
||||||
|
2. 适配横竖屏,生成base64格式图片
|
|
@ -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'))
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,459 @@
|
||||||
|
<template>
|
||||||
|
<view class="sign-page">
|
||||||
|
<view class="sign-body">
|
||||||
|
<canvas
|
||||||
|
id="signCanvas"
|
||||||
|
canvas-id="signCanvas"
|
||||||
|
class="sign-canvas"
|
||||||
|
disable-scroll
|
||||||
|
@touchstart="signCanvasStart"
|
||||||
|
@touchmove="signCanvasMove"
|
||||||
|
@touchend="signCanvasEnd"
|
||||||
|
></canvas>
|
||||||
|
<!-- #ifndef APP -->
|
||||||
|
<!--用于临时储存横屏图片的canvas容器,H5和小程序需要-->
|
||||||
|
<canvas
|
||||||
|
v-if="horizontal"
|
||||||
|
id="hsignCanvas"
|
||||||
|
canvas-id="hsignCanvas"
|
||||||
|
style="position: absolute; left: -1000px; z-index: -1"
|
||||||
|
:style="{ width: canvasHeight + 'px', height: canvasWidth + 'px' }"
|
||||||
|
></canvas>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<!-- <view class="sign-footer" :class="[horizontal ? 'horizontal-btns' : 'vertical-btns']">-->
|
||||||
|
<!-- <view class="btn" @click="cancel">取消</view>-->
|
||||||
|
<!-- <view class="btn" @click="reset">重写</view>-->
|
||||||
|
<!-- <view class="btn" @click="confirm">确认</view>-->
|
||||||
|
<!-- </view>-->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { pathToBase64, base64ToPath } from './index.js'
|
||||||
|
export default {
|
||||||
|
name: 'sign',
|
||||||
|
props: {
|
||||||
|
// 签字板id,用于多签名场景下作为区分
|
||||||
|
sid: {
|
||||||
|
type: String,
|
||||||
|
default: 'sign-board'
|
||||||
|
},
|
||||||
|
// 背景水印图,优先级大于 bgColor
|
||||||
|
bgImg: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 背景纯色底色,为空则透明
|
||||||
|
bgColor: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 是否显示水印
|
||||||
|
showMark: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 水印内容,可多行
|
||||||
|
markText: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [] // ['水印1', '水印2']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 水印样式
|
||||||
|
markStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
fontSize: 12, // 水印字体大小
|
||||||
|
fontFamily: 'microsoft yahei', // 水印字体
|
||||||
|
color: '#cccccc', // 水印字体颜色
|
||||||
|
rotate: 60, // 水印旋转角度
|
||||||
|
step: 2.2 // 步长,部分场景下可通过调节该参数来调整水印间距,建议为1.4-2.6左右
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 是否横屏
|
||||||
|
horizontal: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 画笔样式
|
||||||
|
penStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
lineWidth: 3, // 画笔线宽 建议1~5
|
||||||
|
color: '#000000' // 画笔颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 导出图片配置
|
||||||
|
expFile: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
fileType: 'png', // png/jpg (png不可压缩质量,支持透明;jpg可压缩质量,不支持透明)
|
||||||
|
quality: 1 // 范围 0 - 1 (仅jpg支持)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 取消时是否需要返回
|
||||||
|
needBack: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
canvasCtx: null, // canvascanvasWidth: 0, // canvas宽度
|
||||||
|
canvasWidth: 0, // canvas宽度
|
||||||
|
canvasHeight: 0, // canvas高度
|
||||||
|
x0: 0, // 初始横坐标或上一段touchmove事件中触摸点的横坐标
|
||||||
|
y0: 0, // 初始纵坐标或上一段touchmove事件中触摸点的纵坐标
|
||||||
|
signFlag: false // 签名旗帜
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
created() {},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.createCanvas()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 创建canvas实例
|
||||||
|
createCanvas() {
|
||||||
|
this.canvasCtx = uni.createCanvasContext('signCanvas', this)
|
||||||
|
this.canvasCtx.setLineCap('round') // 向线条的每个末端添加圆形线帽
|
||||||
|
|
||||||
|
// 获取canvas宽高
|
||||||
|
const query = uni.createSelectorQuery().in(this)
|
||||||
|
query
|
||||||
|
.select('.sign-body')
|
||||||
|
.boundingClientRect((data) => {
|
||||||
|
this.canvasWidth = data.width
|
||||||
|
this.canvasHeight = data.height
|
||||||
|
})
|
||||||
|
.exec(async () => {
|
||||||
|
await this.drawBg()
|
||||||
|
this.drawMark(this.markText)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async drawBg() {
|
||||||
|
if (this.bgImg) {
|
||||||
|
const img = await uni.getImageInfo({ src: this.bgImg })
|
||||||
|
this.canvasCtx.drawImage(img.path, 0, 0, this.canvasWidth, this.canvasHeight)
|
||||||
|
} else if (this.bgColor) {
|
||||||
|
// 绘制底色填充,否则为透明
|
||||||
|
this.canvasCtx.setFillStyle(this.bgColor)
|
||||||
|
this.canvasCtx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 绘制动态水印
|
||||||
|
drawMark(textArray) {
|
||||||
|
if (!this.showMark) {
|
||||||
|
this.canvasCtx.draw()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 绘制背景
|
||||||
|
this.drawBg()
|
||||||
|
|
||||||
|
// 水印参数
|
||||||
|
const markStyle = Object.assign(
|
||||||
|
{
|
||||||
|
fontSize: 12, // 水印字体大小
|
||||||
|
fontFamily: 'microsoft yahei', // 水印字体
|
||||||
|
color: '#cccccc', // 水印字体颜色
|
||||||
|
rotate: 60, // 水印旋转角度
|
||||||
|
step: 2 // 步长,部分场景下可通过调节该参数来调整水印间距,建议为1.4-2.6左右
|
||||||
|
},
|
||||||
|
this.markStyle
|
||||||
|
)
|
||||||
|
this.canvasCtx.font = `${markStyle.fontSize}px ${markStyle.fontFamily}`
|
||||||
|
this.canvasCtx.fillStyle = markStyle.color
|
||||||
|
// 文字坐标
|
||||||
|
const maxPx = Math.max(this.canvasWidth / 2, this.canvasHeight / 2)
|
||||||
|
const stepPx = Math.floor(maxPx / markStyle.step)
|
||||||
|
let arrayX = [0] // 初始水印位置 canvas坐标 0 0 点
|
||||||
|
while (arrayX[arrayX.length - 1] < maxPx / 2) {
|
||||||
|
arrayX.push(arrayX[arrayX.length - 1] + stepPx)
|
||||||
|
}
|
||||||
|
arrayX.push(
|
||||||
|
...arrayX.slice(1, arrayX.length).map((item) => {
|
||||||
|
return -item
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
for (let i = 0; i < arrayX.length; i++) {
|
||||||
|
for (let j = 0; j < arrayX.length; j++) {
|
||||||
|
this.canvasCtx.save()
|
||||||
|
this.canvasCtx.translate(this.canvasWidth / 2, this.canvasHeight / 2) // 画布旋转原点 移到 图片中心
|
||||||
|
this.canvasCtx.rotate(Math.PI * (markStyle.rotate / 180))
|
||||||
|
textArray.forEach((item, index) => {
|
||||||
|
let offsetY = markStyle.fontSize * index
|
||||||
|
this.canvasCtx.fillText(item, arrayX[i], arrayX[j] + offsetY)
|
||||||
|
})
|
||||||
|
this.canvasCtx.restore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvasCtx.draw()
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
//取消按钮事件
|
||||||
|
this.$emit('cancel')
|
||||||
|
this.reset()
|
||||||
|
if (this.needBack) uni.navigateBack()
|
||||||
|
},
|
||||||
|
async reset() {
|
||||||
|
this.$emit('reset')
|
||||||
|
this.signFlag = false
|
||||||
|
this.canvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||||
|
await this.drawBg()
|
||||||
|
this.drawMark(this.markText)
|
||||||
|
},
|
||||||
|
async confirm() {
|
||||||
|
this.$emit('confirm')
|
||||||
|
// 确认按钮事件
|
||||||
|
if (!this.signFlag) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请签名后再点击确定',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// uni.showModal({
|
||||||
|
// title: '确认',
|
||||||
|
// content: '确认签名无误吗',
|
||||||
|
// showCancel: true,
|
||||||
|
// success: async ({ confirm }) => {
|
||||||
|
// if (confirm) {
|
||||||
|
let tempFile
|
||||||
|
if (this.horizontal) {
|
||||||
|
tempFile = await this.saveHorizontalCanvas()
|
||||||
|
} else {
|
||||||
|
tempFile = await this.saveCanvas()
|
||||||
|
}
|
||||||
|
const base64 = await pathToBase64(tempFile)
|
||||||
|
const path = await base64ToPath(base64)
|
||||||
|
uni.$emit('getSignImg', { base64, path, sid: this.sid })
|
||||||
|
if (this.needBack) uni.navigateBack()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
signCanvasEnd(e) {
|
||||||
|
// 签名抬起事件
|
||||||
|
// console.log(e, 'signCanvasEnd')
|
||||||
|
this.x0 = 0
|
||||||
|
this.y0 = 0
|
||||||
|
},
|
||||||
|
signCanvasMove(e) {
|
||||||
|
// 签名滑动事件
|
||||||
|
// console.log(e, 'signCanvasMove')
|
||||||
|
let dx = e.touches[0].x
|
||||||
|
let dy = e.touches[0].y
|
||||||
|
|
||||||
|
this.canvasCtx.moveTo(this.x0, this.y0)
|
||||||
|
this.canvasCtx.lineTo(dx, dy)
|
||||||
|
this.canvasCtx.setLineWidth(this.penStyle?.lineWidth || 4)
|
||||||
|
this.canvasCtx.strokeStyle = this.penStyle?.color || '#000000' // 赋值过去
|
||||||
|
this.canvasCtx.stroke()
|
||||||
|
this.canvasCtx.draw(true)
|
||||||
|
|
||||||
|
this.x0 = e.touches[0].x
|
||||||
|
this.y0 = e.touches[0].y
|
||||||
|
},
|
||||||
|
signCanvasStart(e) {
|
||||||
|
// 签名按下事件 app获取的e不一样区分小程序app
|
||||||
|
// console.log('signCanvasStart', e)
|
||||||
|
if (!this.signFlag) {
|
||||||
|
// 第一次开始触碰事件
|
||||||
|
this.$emit('firstTouchStart')
|
||||||
|
}
|
||||||
|
this.signFlag = true
|
||||||
|
this.x0 = e.touches[0].x
|
||||||
|
this.y0 = e.touches[0].y
|
||||||
|
},
|
||||||
|
// 保存竖屏图片
|
||||||
|
async saveCanvas() {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
uni.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvasId: 'signCanvas',
|
||||||
|
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||||
|
quality: this.expFile.quality, // 范围 0 - 1
|
||||||
|
success: (res) => {
|
||||||
|
if (!res.tempFilePath) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '保存签名失败',
|
||||||
|
showCancel: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve(res.tempFilePath)
|
||||||
|
},
|
||||||
|
fail: (r) => {
|
||||||
|
console.log('图片生成失败:' , r)
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 保存横屏图片
|
||||||
|
async saveHorizontalCanvas() {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
uni.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvasId: 'signCanvas',
|
||||||
|
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||||
|
success: (res) => {
|
||||||
|
if (!res.tempFilePath) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '保存签名失败',
|
||||||
|
showCancel: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifdef APP
|
||||||
|
uni.compressImage({
|
||||||
|
src: res.tempFilePath,
|
||||||
|
quality: this.expFile.quality * 100, // 范围 0 - 100
|
||||||
|
rotate: 270,
|
||||||
|
success: (r) => {
|
||||||
|
console.log('==== compressImage :', r)
|
||||||
|
resolve(r.tempFilePath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef APP
|
||||||
|
uni.getImageInfo({
|
||||||
|
src: res.tempFilePath,
|
||||||
|
success: (r) => {
|
||||||
|
// console.log('==== getImageInfo :', r)
|
||||||
|
// 将signCanvas的内容复制到hsignCanvas中
|
||||||
|
const hcanvasCtx = uni.createCanvasContext('hsignCanvas', this)
|
||||||
|
// 横屏宽高互换
|
||||||
|
hcanvasCtx.translate(this.canvasHeight / 2, this.canvasWidth / 2)
|
||||||
|
hcanvasCtx.rotate(Math.PI * (-90 / 180))
|
||||||
|
hcanvasCtx.drawImage(
|
||||||
|
r.path,
|
||||||
|
-this.canvasWidth / 2,
|
||||||
|
-this.canvasHeight / 2,
|
||||||
|
this.canvasWidth,
|
||||||
|
this.canvasHeight
|
||||||
|
)
|
||||||
|
hcanvasCtx.draw(false, async () => {
|
||||||
|
const hpathRes = await uni.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvasId: 'hsignCanvas',
|
||||||
|
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||||
|
quality: this.expFile.quality // 范围 0 - 1
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)
|
||||||
|
let tempFile = ''
|
||||||
|
if (Array.isArray(hpathRes)) {
|
||||||
|
hpathRes.some((item) => {
|
||||||
|
if (item) {
|
||||||
|
tempFile = item.tempFilePath
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tempFile = hpathRes.tempFilePath
|
||||||
|
}
|
||||||
|
resolve(tempFile)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log('图片生成失败:' , err)
|
||||||
|
resolve(false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.sign-page {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.sign-body {
|
||||||
|
width: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.sign-canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-footer {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
border-top: 1px solid #cccccc;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
line-height: 66rpx;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
background-color: #ff0800;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
background-color: #00d000;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
background-color: #0184ff;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical-btns {
|
||||||
|
.btn {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 66rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-btns {
|
||||||
|
.btn {
|
||||||
|
width: 66rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
writing-mode: vertical-lr;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,85 @@
|
||||||
|
{
|
||||||
|
"id": "sp-sign-board",
|
||||||
|
"displayName": "签字板 签名版 手写 动态水印 可叠加背景 可导出图片",
|
||||||
|
"version": "1.1.8",
|
||||||
|
"description": "签字板,可添加背景图或动态水印,可适配横竖屏,并将签名生成base64格式图片",
|
||||||
|
"keywords": [
|
||||||
|
"签字",
|
||||||
|
"签名",
|
||||||
|
"水印",
|
||||||
|
"base64"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.5.0"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"alipay": "n"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "u",
|
||||||
|
"字节跳动": "u",
|
||||||
|
"QQ": "u",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
# sp-sign-board
|
||||||
|
|
||||||
|
### 文档迁移
|
||||||
|
|
||||||
|
> 防止文档失效,提供下列五个地址,内容一致
|
||||||
|
|
||||||
|
- [地址一](https://sonvee.github.io/sv-app-docs/docs-github/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||||
|
- [地址二](https://sv-app-docs.pages.dev/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||||
|
- [地址三](https://sv-app-docs.4everland.app/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||||
|
- [地址四](https://sv-app-docs.vercel.app/src/plugins/sp-sign-board/sp-sign-board.html) (需要梯子)
|
||||||
|
- [地址五](https://static-mp-74bfcbac-6ba6-4f39-8513-8831390ff75a.next.bspapp.com/docs-uni/src/plugins/sp-sign-board/sp-sign-board.html) (有IP限制)
|
|
@ -28,9 +28,11 @@ const updateVersion = {
|
||||||
_this.platform = res.platform
|
_this.platform = res.platform
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// #ifdef APP-PLUS
|
||||||
plus.runtime.getProperty(plus.runtime.appid, function (inf) {
|
plus.runtime.getProperty(plus.runtime.appid, function (inf) {
|
||||||
_this.version = inf.version; //获取当前版本号
|
_this.version = inf.version; //获取当前版本号
|
||||||
});
|
});
|
||||||
|
// #endif
|
||||||
console.info('2')
|
console.info('2')
|
||||||
await _this.getUrlVarsion(toast)
|
await _this.getUrlVarsion(toast)
|
||||||
},
|
},
|
||||||
|
@ -77,6 +79,27 @@ const updateVersion = {
|
||||||
|
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
const updateManager = uni.getUpdateManager();
|
||||||
|
updateManager.onCheckForUpdate(function (res) {
|
||||||
|
// 请求完新版本信息的回调
|
||||||
|
console.log(res.hasUpdate,'版本信息');
|
||||||
|
if (res.hasUpdate) {
|
||||||
|
updateManager.onUpdateReady(function (res) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '更新提示',
|
||||||
|
content: '新版本已经准备好,是否重启应用?',
|
||||||
|
success(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||||
|
updateManager.applyUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
},
|
},
|
||||||
modalConfirm() {
|
modalConfirm() {
|
||||||
this.updateVersion.confirmType === 'download' ? this.downloadNewVersion() : this.installNewVersion()
|
this.updateVersion.confirmType === 'download' ? this.downloadNewVersion() : this.installNewVersion()
|
||||||
|
|