Compare commits
3
Commits
e7d7bc53ee
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17f31c9d92 | ||
|
|
d4a3ef13ac | ||
|
|
3e2059e634 |
@@ -22,7 +22,9 @@
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<compilerArgs>
|
||||
<arg>--enable-preview</arg>
|
||||
</compilerArgs>
|
||||
<useIncrementalCompilation>false</useIncrementalCompilation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -70,13 +72,6 @@
|
||||
<artifactId>nutzboot-maven-plugin</artifactId>
|
||||
<version>${nutzboot.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
|
||||
@@ -546,7 +546,10 @@
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<!-- Java 15 预览功能必须由 JDK 15 编译,运行时也需启用预览功能。 -->
|
||||
<compilerArgs>
|
||||
<arg>--enable-preview</arg>
|
||||
</compilerArgs>
|
||||
<useIncrementalCompilation>false</useIncrementalCompilation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -598,14 +601,6 @@
|
||||
<artifactId>nutzboot-maven-plugin</artifactId>
|
||||
<version>${nutzboot.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
|
||||
@@ -52,6 +52,11 @@ public class CondolenceType extends BaseModel implements Serializable {
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Boolean need_files;
|
||||
|
||||
@Column
|
||||
@Comment("附件说明,供申请人查看材料要求,最多200字")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String files_desc;
|
||||
|
||||
@Column
|
||||
@Comment("排序字段")
|
||||
@Prev({
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 706 KiB |
@@ -0,0 +1,150 @@
|
||||
"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};!function(t,e){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self,t.Signature=e)}(void 0,function(t){function e(){o.step++,o.step<status.length&&(o.status.length=o.step),o.status.push(o.getContentBase64())}var o=this;this.obj=t&&!Array.isArray(t)?t:{},this.option={el:o.obj.el?o.obj.el:"body",lineWidth:o.obj.lineWidth&&!isNaN(parseInt(o.obj.lineWidth))?o.obj.lineWidth:5,lineColor:o.obj.lineColor&&/^#[1-9|A-F]{6}/.test(o.obj.lineColor.substr(0,7).toLocaleUpperCase())?o.obj.lineColor:"#000000",overflow:"boolean"===typeof o.obj.overflow?o.obj.overflow:true,background:o.obj.background&&/^#[1-9|A-F]{6}/.test(o.obj.background.substr(0,7).toLocaleUpperCase())?o.obj.background:"#ffffff"},this.status=[],this.step=-1,this.firstStatus="";var n=document.querySelector(this.option.el);if("CANVAS"!==n.tagName)throw new Error("Target element must be canvas");n.style.backgroundColor=this.option.background;var i=n.getContext("2d");// 根据浏览器输入能力绑定事件;不依赖 Android/iPhone 标识,兼容鸿蒙触屏。
|
||||
// overflow=false 仅限制画布手势,不禁止整页滚动;未传时保持原默认行为。
|
||||
this.create = (options = o.option) => {
|
||||
i.lineWidth = options.lineWidth;
|
||||
i.strokeStyle = options.lineColor;
|
||||
if (options.overflow === true) document.body.style.overflow = 'hidden';
|
||||
n.style.touchAction = 'none';
|
||||
try {
|
||||
o.firstStatus = o.getContentBase64();
|
||||
} catch (error) {
|
||||
// 空白快照失败时,清空仍可直接擦除画布,不依赖图片解码。
|
||||
o.reset = () => {
|
||||
i.clearRect(0, 0, n.width, n.height);
|
||||
o.step = -1;
|
||||
o.status = [];
|
||||
};
|
||||
}
|
||||
let point = null;
|
||||
let activeId = null;
|
||||
// client 坐标按画布实际显示尺寸换算,避免边框、缩放造成笔迹偏移。
|
||||
const position = (event) => {
|
||||
const rect = n.getBoundingClientRect();
|
||||
return {
|
||||
x: (event.clientX - rect.left - n.clientLeft) * n.width / n.clientWidth,
|
||||
y: (event.clientY - rect.top - n.clientTop) * n.height / n.clientHeight
|
||||
};
|
||||
};
|
||||
const begin = (event) => {
|
||||
point = position(event);
|
||||
try {
|
||||
const snapshot = o.getContentBase64();
|
||||
o.step++;
|
||||
o.status.length = o.step;
|
||||
o.status.push(snapshot);
|
||||
} catch (error) {
|
||||
// 历史记录仅用于撤销;快照失败不能阻断当前笔画。
|
||||
}
|
||||
};
|
||||
const move = (event) => {
|
||||
if (!point) return;
|
||||
const next = position(event);
|
||||
i.beginPath();
|
||||
i.moveTo(point.x, point.y);
|
||||
i.lineTo(next.x, next.y);
|
||||
i.stroke();
|
||||
point = next;
|
||||
};
|
||||
let source = '';
|
||||
let pointerType = '';
|
||||
let captured = false;
|
||||
let ignoreMouseUntil = 0;
|
||||
// 仅阻止画布内可取消的手势,避免被动监听异常和浏览器滚动抢占笔画。
|
||||
const prevent = (event) => {
|
||||
if (event.cancelable) event.preventDefault();
|
||||
};
|
||||
const end = () => {
|
||||
point = null;
|
||||
activeId = null;
|
||||
source = '';
|
||||
pointerType = '';
|
||||
captured = false;
|
||||
};
|
||||
const suppressMouse = () => { ignoreMouseUntil = Date.now() + 800; };
|
||||
// changedTouches 是 TouchList,不要求内核实现迭代器;只处理当前落笔手指。
|
||||
const findTouch = (list) => {
|
||||
for (let index = 0; list && index < list.length; index++) {
|
||||
if (list[index].identifier === activeId) return list[index];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
n.addEventListener('pointerdown', (event) => {
|
||||
const type = event.pointerType || '';
|
||||
if (source || (type === 'mouse' && (event.button !== 0 || Date.now() < ignoreMouseUntil))) return;
|
||||
source = 'pointer';
|
||||
pointerType = type;
|
||||
activeId = event.pointerId;
|
||||
begin(event);
|
||||
if (type !== 'mouse') suppressMouse();
|
||||
// 部分内核提供 PointerEvent 却不支持捕获;捕获失败仍允许在画布内绘制。
|
||||
try {
|
||||
if (typeof n.setPointerCapture === 'function') {
|
||||
n.setPointerCapture(event.pointerId);
|
||||
captured = true;
|
||||
}
|
||||
} catch (error) {
|
||||
captured = false;
|
||||
}
|
||||
prevent(event);
|
||||
});
|
||||
n.addEventListener('pointermove', (event) => {
|
||||
if (source !== 'pointer' || event.pointerId !== activeId) return;
|
||||
move(event);
|
||||
prevent(event);
|
||||
});
|
||||
['pointerup', 'pointercancel', 'lostpointercapture'].forEach((name) => {
|
||||
n.addEventListener(name, (event) => {
|
||||
if (source !== 'pointer' || event.pointerId !== activeId) return;
|
||||
if (pointerType !== 'mouse') suppressMouse();
|
||||
end();
|
||||
});
|
||||
});
|
||||
n.addEventListener('pointerleave', () => {
|
||||
if (source === 'pointer' && !captured) end();
|
||||
});
|
||||
// 始终绑定触摸兜底。若只收到 pointerdown 而没有 pointermove,touchstart 可接管该笔画。
|
||||
n.addEventListener('touchstart', (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
const touch = event.changedTouches && event.changedTouches[0];
|
||||
if (!touch || source === 'touch' || source === 'mouse') return;
|
||||
if (source === 'pointer') {
|
||||
if (pointerType === 'mouse' || pointerType === 'pen') return;
|
||||
// 接管不再保存第二份历史,也不重复画线;后续指针事件由来源锁忽略。
|
||||
point = position(touch);
|
||||
} else {
|
||||
begin(touch);
|
||||
}
|
||||
source = 'touch';
|
||||
activeId = touch.identifier;
|
||||
}, {passive: false});
|
||||
n.addEventListener('touchmove', (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
if (source !== 'touch') return;
|
||||
const touch = findTouch(event.changedTouches);
|
||||
if (touch) move(touch);
|
||||
}, {passive: false});
|
||||
['touchend', 'touchcancel'].forEach((name) => {
|
||||
n.addEventListener(name, (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
if (source === 'touch' && findTouch(event.changedTouches)) end();
|
||||
}, {passive: false});
|
||||
});
|
||||
// 兼容旧内核鼠标输入,并过滤触摸结束后生成的合成鼠标事件。
|
||||
n.addEventListener('mousedown', (event) => {
|
||||
if (source || event.button !== 0 || Date.now() < ignoreMouseUntil) return;
|
||||
source = 'mouse';
|
||||
begin(event);
|
||||
prevent(event);
|
||||
});
|
||||
n.addEventListener('mousemove', (event) => {
|
||||
if (source === 'mouse') move(event);
|
||||
});
|
||||
['mouseup', 'mouseleave'].forEach((name) => {
|
||||
n.addEventListener(name, () => {
|
||||
if (source === 'mouse') end();
|
||||
});
|
||||
});
|
||||
},this.getContentBase64=function(t,e){if(t){var i=!0,s=!1,a=void 0;try{for(var r,f=document.querySelectorAll('canvas[data-none="1"]')[Symbol.iterator]();!(i=(r=f.next()).done);i=!0){var d=r.value;d.parentNode.removeChild(d)}}catch(t){s=!0,a=t}finally{try{!i&&f.return&&f.return()}finally{if(s)throw a}}var l=document.createElement("canvas");l.dataset.none="1",l.width=n.offsetHeight,l.height=n.offsetWidth,document.body.appendChild(l);var c=document.querySelector('canvas[data-none="1"]').getContext("2d"),u=new Image;u.src=o.getContentBase64(),u.onload=function(){var t=Math.round(n.offsetHeight/2),o=Math.round(n.offsetWidth/2);c.save(),c.translate(t,o),c.rotate(-90*Math.PI/180),c.drawImage(u,-u.width/2,-u.height/2),c.restore(),e&&e(document.querySelector('canvas[data-none="1"]').toDataURL("image/png"))}}else{if(!e)return n.toDataURL("image/png");e(n.toDataURL("image/png"))}},this.getBlob=function(){for(var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.getContentBase64(),e=t.split(","),o=e[0].match(/:(.*?);/)[1],n=atob(e[1]),i=n.length,s=new Uint8Array(i);i--;)s[i]=n.charCodeAt(i);return new Blob([s],{type:o})},this.getFile=function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.getContentBase64(),o=t||"file",n=e.split(","),i=n[0].match(/:(.*?);/)[1],s=i.split("/")[1],a=atob(n[1]),r=a.length,f=new Uint8Array(r);r--;)f[r]=a.charCodeAt(r);return new File([f],o+"."+s,{type:i})},this.reset=function(){if(!o.firstStatus)return!1;i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var t=new Image;try{t.src=o.firstStatus,t.addEventListener("load",function(){i.drawImage(t,0,0)}),o.step=-1,o.status=[]}catch(t){}},this.undo=function(t){if(o.step>=0){i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var e=new Image;try{e.src=o.status[o.step],e.addEventListener("load",function(){i.drawImage(e,0,0)})}catch(t){}o.step--}else console.warn("no more undo"),t&&t()},this.redo=function(t){if(o.step<o.status.length-2){o.step++;var e=new Image;o.status[o.step+1]&&(e.src=o.status[o.step+1],e.addEventListener("load",function(){i.clearRect(0,0,n.offsetWidth,n.offsetHeight),i.drawImage(e,0,0)}))}else console.warn("no more redo"),t&&t()}});
|
||||
+150
-1
@@ -1 +1,150 @@
|
||||
"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};!function(t,e){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self,t.Signature=e)}(void 0,function(t){function e(){o.step++,o.step<status.length&&(o.status.length=o.step),o.status.push(o.getContentBase64())}var o=this;this.obj=t&&!Array.isArray(t)?t:{},this.option={el:o.obj.el?o.obj.el:"body",lineWidth:o.obj.lineWidth&&!isNaN(parseInt(o.obj.lineWidth))?o.obj.lineWidth:5,lineColor:o.obj.lineColor&&/^#[1-9|A-F]{6}/.test(o.obj.lineColor.substr(0,7).toLocaleUpperCase())?o.obj.lineColor:"#000000",overflow:!o.obj.direction||"boolean"!=typeof o.obj.direction||o.obj.direction,background:o.obj.background&&/^#[1-9|A-F]{6}/.test(o.obj.background.substr(0,7).toLocaleUpperCase())?o.obj.background:"#ffffff"},this.status=[],this.step=-1,this.firstStatus="";var n=document.querySelector(this.option.el);if("CANVAS"!==n.tagName)throw new Error("Target element must be canvas");n.style.backgroundColor=this.option.background;var i=n.getContext("2d");this.create=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:o.option;i.lineWidth=t.lineWidth,i.strokeStyle=t.lineColor,!0===t.overflow&&(document.querySelector("body").style.overflow="hidden");var s="",a=navigator.userAgent.toLocaleLowerCase();o.firstStatus=o.getContentBase64(),-1!==a.indexOf("iphone")||-1!==a.indexOf("android")?(n.addEventListener("touchstart",function(t){s={x:t.touches[0].clientX-this.offsetLeft,y:t.touches[0].clientY-this.offsetTop}}),n.addEventListener("touchmove",function(t){i.beginPath(),i.moveTo(s.x,s.y),s={x:t.touches[0].clientX-this.offsetLeft,y:t.touches[0].clientY-this.offsetTop},i.lineTo(s.x,s.y),i.fill(),i.closePath(),i.stroke()}),n.addEventListener("touchend",function(){s=""})):(n.addEventListener("mousedown",function(t){e(),s={x:t.clientX-this.offsetLeft,y:t.clientY-this.offsetTop}}),n.addEventListener("mousemove",function(t){s.x&&s.y&&(i.beginPath(),i.moveTo(s.x,s.y),s={x:t.clientX-this.offsetLeft,y:t.clientY-this.offsetTop},i.lineTo(s.x,s.y),i.fill(),i.closePath(),i.stroke())}),n.addEventListener("mouseup",function(){s=""}),n.addEventListener("mouseout",function(){s=""}))},this.getContentBase64=function(t,e){if(t){var i=!0,s=!1,a=void 0;try{for(var r,f=document.querySelectorAll('canvas[data-none="1"]')[Symbol.iterator]();!(i=(r=f.next()).done);i=!0){var d=r.value;d.parentNode.removeChild(d)}}catch(t){s=!0,a=t}finally{try{!i&&f.return&&f.return()}finally{if(s)throw a}}var l=document.createElement("canvas");l.dataset.none="1",l.width=n.offsetHeight,l.height=n.offsetWidth,document.body.appendChild(l);var c=document.querySelector('canvas[data-none="1"]').getContext("2d"),u=new Image;u.src=o.getContentBase64(),u.onload=function(){var t=Math.round(n.offsetHeight/2),o=Math.round(n.offsetWidth/2);c.save(),c.translate(t,o),c.rotate(-90*Math.PI/180),c.drawImage(u,-u.width/2,-u.height/2),c.restore(),e&&e(document.querySelector('canvas[data-none="1"]').toDataURL("image/png"))}}else{if(!e)return n.toDataURL("image/png");e(n.toDataURL("image/png"))}},this.getBlob=function(){for(var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.getContentBase64(),e=t.split(","),o=e[0].match(/:(.*?);/)[1],n=atob(e[1]),i=n.length,s=new Uint8Array(i);i--;)s[i]=n.charCodeAt(i);return new Blob([s],{type:o})},this.getFile=function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.getContentBase64(),o=t||"file",n=e.split(","),i=n[0].match(/:(.*?);/)[1],s=i.split("/")[1],a=atob(n[1]),r=a.length,f=new Uint8Array(r);r--;)f[r]=a.charCodeAt(r);return new File([f],o+"."+s,{type:i})},this.reset=function(){if(!o.firstStatus)return!1;i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var t=new Image;try{t.src=o.firstStatus,t.addEventListener("load",function(){i.drawImage(t,0,0)}),o.step=-1,o.status=[]}catch(t){}},this.undo=function(t){if(o.step>=0){i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var e=new Image;try{e.src=o.status[o.step],e.addEventListener("load",function(){i.drawImage(e,0,0)})}catch(t){}o.step--}else console.warn("no more undo"),t&&t()},this.redo=function(t){if(o.step<o.status.length-2){o.step++;var e=new Image;o.status[o.step+1]&&(e.src=o.status[o.step+1],e.addEventListener("load",function(){i.clearRect(0,0,n.offsetWidth,n.offsetHeight),i.drawImage(e,0,0)}))}else console.warn("no more redo"),t&&t()}});
|
||||
"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};!function(t,e){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self,t.Signature=e)}(void 0,function(t){function e(){o.step++,o.step<status.length&&(o.status.length=o.step),o.status.push(o.getContentBase64())}var o=this;this.obj=t&&!Array.isArray(t)?t:{},this.option={el:o.obj.el?o.obj.el:"body",lineWidth:o.obj.lineWidth&&!isNaN(parseInt(o.obj.lineWidth))?o.obj.lineWidth:5,lineColor:o.obj.lineColor&&/^#[1-9|A-F]{6}/.test(o.obj.lineColor.substr(0,7).toLocaleUpperCase())?o.obj.lineColor:"#000000",overflow:"boolean"===typeof o.obj.overflow?o.obj.overflow:true,background:o.obj.background&&/^#[1-9|A-F]{6}/.test(o.obj.background.substr(0,7).toLocaleUpperCase())?o.obj.background:"#ffffff"},this.status=[],this.step=-1,this.firstStatus="";var n=document.querySelector(this.option.el);if("CANVAS"!==n.tagName)throw new Error("Target element must be canvas");n.style.backgroundColor=this.option.background;var i=n.getContext("2d");// 根据浏览器输入能力绑定事件;不依赖 Android/iPhone 标识,兼容鸿蒙触屏。
|
||||
// overflow=false 仅限制画布手势,不禁止整页滚动;未传时保持原默认行为。
|
||||
this.create = (options = o.option) => {
|
||||
i.lineWidth = options.lineWidth;
|
||||
i.strokeStyle = options.lineColor;
|
||||
if (options.overflow === true) document.body.style.overflow = 'hidden';
|
||||
n.style.touchAction = 'none';
|
||||
try {
|
||||
o.firstStatus = o.getContentBase64();
|
||||
} catch (error) {
|
||||
// 空白快照失败时,清空仍可直接擦除画布,不依赖图片解码。
|
||||
o.reset = () => {
|
||||
i.clearRect(0, 0, n.width, n.height);
|
||||
o.step = -1;
|
||||
o.status = [];
|
||||
};
|
||||
}
|
||||
let point = null;
|
||||
let activeId = null;
|
||||
// client 坐标按画布实际显示尺寸换算,避免边框、缩放造成笔迹偏移。
|
||||
const position = (event) => {
|
||||
const rect = n.getBoundingClientRect();
|
||||
return {
|
||||
x: (event.clientX - rect.left - n.clientLeft) * n.width / n.clientWidth,
|
||||
y: (event.clientY - rect.top - n.clientTop) * n.height / n.clientHeight
|
||||
};
|
||||
};
|
||||
const begin = (event) => {
|
||||
point = position(event);
|
||||
try {
|
||||
const snapshot = o.getContentBase64();
|
||||
o.step++;
|
||||
o.status.length = o.step;
|
||||
o.status.push(snapshot);
|
||||
} catch (error) {
|
||||
// 历史记录仅用于撤销;快照失败不能阻断当前笔画。
|
||||
}
|
||||
};
|
||||
const move = (event) => {
|
||||
if (!point) return;
|
||||
const next = position(event);
|
||||
i.beginPath();
|
||||
i.moveTo(point.x, point.y);
|
||||
i.lineTo(next.x, next.y);
|
||||
i.stroke();
|
||||
point = next;
|
||||
};
|
||||
let source = '';
|
||||
let pointerType = '';
|
||||
let captured = false;
|
||||
let ignoreMouseUntil = 0;
|
||||
// 仅阻止画布内可取消的手势,避免被动监听异常和浏览器滚动抢占笔画。
|
||||
const prevent = (event) => {
|
||||
if (event.cancelable) event.preventDefault();
|
||||
};
|
||||
const end = () => {
|
||||
point = null;
|
||||
activeId = null;
|
||||
source = '';
|
||||
pointerType = '';
|
||||
captured = false;
|
||||
};
|
||||
const suppressMouse = () => { ignoreMouseUntil = Date.now() + 800; };
|
||||
// changedTouches 是 TouchList,不要求内核实现迭代器;只处理当前落笔手指。
|
||||
const findTouch = (list) => {
|
||||
for (let index = 0; list && index < list.length; index++) {
|
||||
if (list[index].identifier === activeId) return list[index];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
n.addEventListener('pointerdown', (event) => {
|
||||
const type = event.pointerType || '';
|
||||
if (source || (type === 'mouse' && (event.button !== 0 || Date.now() < ignoreMouseUntil))) return;
|
||||
source = 'pointer';
|
||||
pointerType = type;
|
||||
activeId = event.pointerId;
|
||||
begin(event);
|
||||
if (type !== 'mouse') suppressMouse();
|
||||
// 部分内核提供 PointerEvent 却不支持捕获;捕获失败仍允许在画布内绘制。
|
||||
try {
|
||||
if (typeof n.setPointerCapture === 'function') {
|
||||
n.setPointerCapture(event.pointerId);
|
||||
captured = true;
|
||||
}
|
||||
} catch (error) {
|
||||
captured = false;
|
||||
}
|
||||
prevent(event);
|
||||
});
|
||||
n.addEventListener('pointermove', (event) => {
|
||||
if (source !== 'pointer' || event.pointerId !== activeId) return;
|
||||
move(event);
|
||||
prevent(event);
|
||||
});
|
||||
['pointerup', 'pointercancel', 'lostpointercapture'].forEach((name) => {
|
||||
n.addEventListener(name, (event) => {
|
||||
if (source !== 'pointer' || event.pointerId !== activeId) return;
|
||||
if (pointerType !== 'mouse') suppressMouse();
|
||||
end();
|
||||
});
|
||||
});
|
||||
n.addEventListener('pointerleave', () => {
|
||||
if (source === 'pointer' && !captured) end();
|
||||
});
|
||||
// 始终绑定触摸兜底。若只收到 pointerdown 而没有 pointermove,touchstart 可接管该笔画。
|
||||
n.addEventListener('touchstart', (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
const touch = event.changedTouches && event.changedTouches[0];
|
||||
if (!touch || source === 'touch' || source === 'mouse') return;
|
||||
if (source === 'pointer') {
|
||||
if (pointerType === 'mouse' || pointerType === 'pen') return;
|
||||
// 接管不再保存第二份历史,也不重复画线;后续指针事件由来源锁忽略。
|
||||
point = position(touch);
|
||||
} else {
|
||||
begin(touch);
|
||||
}
|
||||
source = 'touch';
|
||||
activeId = touch.identifier;
|
||||
}, {passive: false});
|
||||
n.addEventListener('touchmove', (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
if (source !== 'touch') return;
|
||||
const touch = findTouch(event.changedTouches);
|
||||
if (touch) move(touch);
|
||||
}, {passive: false});
|
||||
['touchend', 'touchcancel'].forEach((name) => {
|
||||
n.addEventListener(name, (event) => {
|
||||
suppressMouse();
|
||||
prevent(event);
|
||||
if (source === 'touch' && findTouch(event.changedTouches)) end();
|
||||
}, {passive: false});
|
||||
});
|
||||
// 兼容旧内核鼠标输入,并过滤触摸结束后生成的合成鼠标事件。
|
||||
n.addEventListener('mousedown', (event) => {
|
||||
if (source || event.button !== 0 || Date.now() < ignoreMouseUntil) return;
|
||||
source = 'mouse';
|
||||
begin(event);
|
||||
prevent(event);
|
||||
});
|
||||
n.addEventListener('mousemove', (event) => {
|
||||
if (source === 'mouse') move(event);
|
||||
});
|
||||
['mouseup', 'mouseleave'].forEach((name) => {
|
||||
n.addEventListener(name, () => {
|
||||
if (source === 'mouse') end();
|
||||
});
|
||||
});
|
||||
},this.getContentBase64=function(t,e){if(t){var i=!0,s=!1,a=void 0;try{for(var r,f=document.querySelectorAll('canvas[data-none="1"]')[Symbol.iterator]();!(i=(r=f.next()).done);i=!0){var d=r.value;d.parentNode.removeChild(d)}}catch(t){s=!0,a=t}finally{try{!i&&f.return&&f.return()}finally{if(s)throw a}}var l=document.createElement("canvas");l.dataset.none="1",l.width=n.offsetHeight,l.height=n.offsetWidth,document.body.appendChild(l);var c=document.querySelector('canvas[data-none="1"]').getContext("2d"),u=new Image;u.src=o.getContentBase64(),u.onload=function(){var t=Math.round(n.offsetHeight/2),o=Math.round(n.offsetWidth/2);c.save(),c.translate(t,o),c.rotate(-90*Math.PI/180),c.drawImage(u,-u.width/2,-u.height/2),c.restore(),e&&e(document.querySelector('canvas[data-none="1"]').toDataURL("image/png"))}}else{if(!e)return n.toDataURL("image/png");e(n.toDataURL("image/png"))}},this.getBlob=function(){for(var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.getContentBase64(),e=t.split(","),o=e[0].match(/:(.*?);/)[1],n=atob(e[1]),i=n.length,s=new Uint8Array(i);i--;)s[i]=n.charCodeAt(i);return new Blob([s],{type:o})},this.getFile=function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.getContentBase64(),o=t||"file",n=e.split(","),i=n[0].match(/:(.*?);/)[1],s=i.split("/")[1],a=atob(n[1]),r=a.length,f=new Uint8Array(r);r--;)f[r]=a.charCodeAt(r);return new File([f],o+"."+s,{type:i})},this.reset=function(){if(!o.firstStatus)return!1;i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var t=new Image;try{t.src=o.firstStatus,t.addEventListener("load",function(){i.drawImage(t,0,0)}),o.step=-1,o.status=[]}catch(t){}},this.undo=function(t){if(o.step>=0){i.clearRect(0,0,n.offsetWidth,n.offsetHeight);var e=new Image;try{e.src=o.status[o.step],e.addEventListener("load",function(){i.drawImage(e,0,0)})}catch(t){}o.step--}else console.warn("no more undo"),t&&t()},this.redo=function(t){if(o.step<o.status.length-2){o.step++;var e=new Image;o.status[o.step+1]&&(e.src=o.status[o.step+1],e.addEventListener("load",function(){i.clearRect(0,0,n.offsetWidth,n.offsetHeight),i.drawImage(e,0,0)}))}else console.warn("no more redo"),t&&t()}});
|
||||
|
||||
@@ -222,10 +222,10 @@ layout("/mobile/platform.html"){
|
||||
:min-date="new Date('1999-01-01')"
|
||||
:color="themeColor"></van-calendar>
|
||||
|
||||
<van-field v-model="formData.the_hospital" name="the_hospital" name="type"
|
||||
<!-- 所在医院暂不采集,连同字段内的必填校验一起停用。 <van-field v-model="formData.the_hospital" name="the_hospital" name="type"
|
||||
label="所在医院"
|
||||
placeholder="请填写所在医院" required
|
||||
:rules="[{ required:true, message: '请填写所在医院' }]"></van-field>
|
||||
:rules="[{ required:true, message: '请填写所在医院' }]"></van-field> -->
|
||||
</template>
|
||||
|
||||
<!-- <van-field v-model="formData.remark" name="remark" label="申请事由"
|
||||
@@ -309,7 +309,10 @@ layout("/mobile/platform.html"){
|
||||
<div class="mb10">附  件</div>
|
||||
</template>
|
||||
<template #input>
|
||||
<div style="width: 100%;">
|
||||
<vant-file-upload :files.sync="formData.files"></vant-file-upload>
|
||||
<div v-if="attachmentDescription" style="white-space: pre-wrap; overflow-wrap: anywhere; color: #f56c6c; line-height: 20px; margin-top: 8px;">{{ attachmentDescription }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
@@ -373,6 +376,13 @@ layout("/mobile/platform.html"){
|
||||
money: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 按当前类型读取材料说明,无说明时返回空串,避免切换类型后残留旧提示。
|
||||
attachmentDescription() {
|
||||
const selectedType = this.typeColumns.find(item => item.value === this.formData.type)
|
||||
return selectedType ? (selectedType.files_desc || '') : ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"formData.money"(val) {
|
||||
if (val > this.money) {
|
||||
@@ -568,7 +578,7 @@ layout("/mobile/platform.html"){
|
||||
this.formData.apply_time = moment().format('YYYY-MM-DD')
|
||||
const {code, data} = await $.get("/platform/condolence/type/getAll")
|
||||
data.forEach(v => {
|
||||
this.typeColumns.push({value: v.id, text: v.name + "(" + v.money + ")"})
|
||||
this.typeColumns.push({value: v.id, text: v.name + "(" + v.money + ")", files_desc: v.files_desc})
|
||||
})
|
||||
for (let i in condolence.way) {
|
||||
this.wayColumns.push({value: condolence.way[i], text: condolence.way[i]})
|
||||
|
||||
@@ -16,6 +16,12 @@ layout("/mobile/platform.html"){
|
||||
max-height: 300px !important;
|
||||
}
|
||||
|
||||
/* 校园全景图等比例填满轮播区域,靠右保留建筑主体,超宽部分裁剪左侧。 */
|
||||
.my-swipe .home-panorama .van-image__img {
|
||||
object-fit: cover;
|
||||
object-position: right center;
|
||||
}
|
||||
|
||||
.not_open {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
@@ -84,6 +90,7 @@ layout("/mobile/platform.html"){
|
||||
<van-swipe class="my-swipe" :autoplay="2000" indicator-color="white">
|
||||
<van-swipe-item v-for="item in photoArray">
|
||||
<van-image width="100%" :height="$(document).height() * 0.26"
|
||||
:class="item.cropLeft ? 'home-panorama' : ''"
|
||||
:src="item.src"></van-image>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
@@ -119,6 +126,7 @@ layout("/mobile/platform.html"){
|
||||
{src: '/assets/mobile/img/home/home1.png'},
|
||||
{src: '/assets/mobile/img/home/home2.png'},
|
||||
{src: '/assets/mobile/img/home/home3.png'},
|
||||
{src: '/assets/mobile/img/home/home4.png', cropLeft: true},
|
||||
],
|
||||
gridArray: [
|
||||
// {src: '/assets/mobile/img/home/8活动报名.jpg', text: '活动报名', isOpen: true,},
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<van-number-keyboard safe-area-inset-bottom/>
|
||||
<title></title>
|
||||
<title>广西师范大学智慧工会</title>
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.min.css">
|
||||
<link rel="stylesheet" href="${base!}/assets/mobile/css/theme.css">
|
||||
<link rel="stylesheet" href="${base!}/assets/mobile/css/main.css">
|
||||
|
||||
@@ -8,23 +8,26 @@
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
|
||||
<title>签字</title>
|
||||
<!-- 引入样式文件 -->
|
||||
<link rel="stylesheet" href="https://cdn.staticfile.org/vant/2.12.5/index.min.css">
|
||||
<link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/2.2.0/weui.min.css">
|
||||
<link rel="stylesheet" href="/assets/platform/plugins/vant/index.min.css">
|
||||
|
||||
|
||||
<!-- 引入 Vue 和 Vant 的 JS 文件 -->
|
||||
<script src="https://cdn.staticfile.org/vue/2.6.9/vue.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/vant/2.12.5/vant.min.js"></script>
|
||||
<script src="/assets/platform/plugins/vue/vue.min.js"></script>
|
||||
<script src="/assets/platform/plugins/vant/vant.min.js"></script>
|
||||
<script src="/assets/platform/plugins/jquery/jquery-1.11.1.min.js"></script>
|
||||
<script src="/assets/platform/plugins/moment/moment.min.js"></script>
|
||||
<script src="/assets/platform/js/signature.min.js"></script>
|
||||
|
||||
<script src="/assets/platform/js/signature-20261112-4.js?v=20261112-5"></script>
|
||||
</head>
|
||||
<style>
|
||||
[v-clock] {
|
||||
html, body { height: 100%; overflow: hidden; }
|
||||
#canvas { touch-action: none; }
|
||||
[v-cloak] {
|
||||
display: none
|
||||
}
|
||||
</style>
|
||||
<body style="height: 100%;width: 100%">
|
||||
<div v-clock id="app" style="height: 100%;width: 100%">
|
||||
<p id="sign-status" role="status" style="padding: 24px;text-align: center">签字页面正在加载;若长时间未显示,请刷新页面重试。</p>
|
||||
<div v-cloak id="app" style="height: 100%;width: 100%">
|
||||
<van-row style="margin-top: 10vh;text-align: center">
|
||||
<h3 style="color: #1989fa">提示:请在下方区域签字!</h3>
|
||||
</van-row>
|
||||
@@ -38,7 +41,7 @@
|
||||
<van-button @click="reset" type="default" size="large">清 空</van-button>
|
||||
</van-col>
|
||||
<van-col span="11">
|
||||
<van-button type="info" @click="doSub" size="large" :disabled="subDis">提 交</van-button>
|
||||
<van-button type="info" @click="doSub" size="large" :disabled="subDis || formLoading" :loading="formLoading">提 交</van-button>
|
||||
</van-col>
|
||||
</van-row>
|
||||
</van-col>
|
||||
@@ -46,110 +49,75 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.body.addEventListener('touchmove', function (e) {
|
||||
e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)
|
||||
}, {passive: false}); //passive 参数不能省略,用来兼容ios和android
|
||||
|
||||
function getQueryVariable(variable) {
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split("&");
|
||||
for (var i = 0; i < vars.length; i++) {
|
||||
var pair = vars[i].split("=");
|
||||
if (pair[0] == variable) {
|
||||
return pair[1];
|
||||
// prefix 为业务标识、id 为二维码会话标识,原样提交以保持 PC 轮询对应关系。
|
||||
const getQueryVariable = (name) => {
|
||||
const parts = window.location.search.substring(1).split('&');
|
||||
for (let index = 0; index < parts.length; index++) {
|
||||
const separator = parts[index].indexOf('=');
|
||||
if (parts[index].substring(0, separator) === name) {
|
||||
return decodeURIComponent(parts[index].substring(separator + 1));
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
let qm;
|
||||
try {
|
||||
if (!window.Vue || !window.vant || !window.Signature || !window.jQuery) {
|
||||
throw new Error('签字页面依赖未加载');
|
||||
}
|
||||
|
||||
var qmoption = {
|
||||
el: '#canvas',
|
||||
lineWidth: 4,
|
||||
lineColor: '#000',
|
||||
overflow: false,
|
||||
background: '#fff'
|
||||
}
|
||||
var qm
|
||||
|
||||
var
|
||||
vue = new Vue({
|
||||
el: "#app",
|
||||
data: function () {
|
||||
return {
|
||||
prefix: '',
|
||||
id: '',
|
||||
base64: '',
|
||||
subDis: false,
|
||||
isNull: function (val) {
|
||||
if (val === null || val === undefined || val === '') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
none2str: function (value) {
|
||||
if (vue.isNull(value)) {
|
||||
return '暂无'
|
||||
}
|
||||
return value
|
||||
}
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {prefix: '', id: '', subDis: true, formLoading: false};
|
||||
},
|
||||
methods: {
|
||||
reset() {
|
||||
qm.reset()
|
||||
if (qm) qm.reset();
|
||||
},
|
||||
doSub() {
|
||||
qm.getContentBase64(false, (val) => {
|
||||
this.base64 = val
|
||||
})
|
||||
|
||||
$.post("/signature/doSub", {
|
||||
if (!qm || this.subDis || this.formLoading) return;
|
||||
// 提交 PNG Base64;接口返回 {code, msg},code=0 表示可由 PC 获取签名。
|
||||
this.formLoading = true;
|
||||
$.post('/signature/doSub', {
|
||||
prefix: this.prefix,
|
||||
id: this.id,
|
||||
base64: this.base64
|
||||
}, (data) => {
|
||||
if (data.code == 0) {
|
||||
this.$notify({
|
||||
message: data.msg,
|
||||
type: 'success'
|
||||
});
|
||||
this.subDis = true
|
||||
base64: qm.getContentBase64()
|
||||
}).then((data) => {
|
||||
if (data && data.code === 0) {
|
||||
this.$notify({message: data.msg || '签字提交成功', type: 'success'});
|
||||
this.subDis = true;
|
||||
} else {
|
||||
this.$notify({
|
||||
message: data.msg,
|
||||
type: 'danger'
|
||||
this.$notify({message: (data && data.msg) || '提交失败,请重试', type: 'danger'});
|
||||
}
|
||||
}, () => {
|
||||
this.$notify({message: '提交失败,请检查网络后重试', type: 'danger'});
|
||||
}).always(() => {
|
||||
this.formLoading = false;
|
||||
});
|
||||
}
|
||||
}, "json");
|
||||
}
|
||||
},
|
||||
mounted: () => {
|
||||
canvas = document.getElementById("canvas");
|
||||
if (canvas.width < window.innerWidth) {
|
||||
canvas.width = window.innerWidth;
|
||||
}
|
||||
|
||||
if (canvas.height < window.innerHeight) {
|
||||
canvas.height = window.innerHeight * 0.5;
|
||||
}
|
||||
|
||||
qm = new Signature(qmoption);
|
||||
mounted() {
|
||||
try {
|
||||
this.id = getQueryVariable('id');
|
||||
this.prefix = getQueryVariable('prefix');
|
||||
const canvas = document.getElementById('canvas');
|
||||
canvas.width = Math.max(1, window.innerWidth - 2);
|
||||
canvas.height = Math.max(1, Math.floor(window.innerHeight * 0.5));
|
||||
qm = new Signature({el: '#canvas', lineWidth: 4, lineColor: '#000', overflow: true, background: '#fff'});
|
||||
qm.create();
|
||||
},
|
||||
created: function () {
|
||||
if (this.isNull(getQueryVariable("id")) || this.isNull(getQueryVariable("prefix"))) {
|
||||
this.$notify({
|
||||
message: '缺少参数!',
|
||||
type: 'danger'
|
||||
this.subDis = !this.id || !this.prefix;
|
||||
const status = document.getElementById('sign-status');
|
||||
status.textContent = this.subDis ? '缺少签字参数,请重新扫描二维码。' : '';
|
||||
status.style.display = this.subDis ? 'block' : 'none';
|
||||
} catch (error) {
|
||||
// 初始化异常仍保留可见提示,避免用户只能看到白屏。
|
||||
document.getElementById('sign-status').textContent = '签字初始化失败,请刷新页面重试。';
|
||||
}
|
||||
}
|
||||
});
|
||||
this.subDis = true
|
||||
} catch (error) {
|
||||
document.getElementById('sign-status').textContent = '签字页面加载失败,请检查网络并刷新页面重试。';
|
||||
}
|
||||
this.id = getQueryVariable("id")
|
||||
this.prefix = getQueryVariable("prefix")
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -104,6 +104,11 @@ layout("/layouts/platform.html"){
|
||||
<el-radio v-model="formData.need_files" :label="true" border>是</el-radio>
|
||||
<el-radio v-model="formData.need_files" :label="false" border>否</el-radio>
|
||||
</el-form-item>
|
||||
<!-- 附件说明为选填文本,双端申请页在上传框下方展示,最多200字。 -->
|
||||
<el-form-item label="附件说明" prop="files_desc">
|
||||
<el-input v-model="formData.files_desc" type="textarea" :rows="3"
|
||||
maxlength="200" show-word-limit placeholder="请填写附件材料要求,最多200字"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
@@ -130,6 +135,7 @@ layout("/layouts/platform.html"){
|
||||
searchName: "name",
|
||||
},
|
||||
formRules: {
|
||||
files_desc: [{max: 200, message: '附件说明最多200字', trigger: ['blur', 'change']}],
|
||||
name: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
money: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
way: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
@@ -177,7 +183,7 @@ layout("/layouts/platform.html"){
|
||||
});
|
||||
},
|
||||
openAdd() {
|
||||
this.formData = {need_files: false}
|
||||
this.formData = {need_files: false, files_desc: ''}
|
||||
this.dialogVisible = true
|
||||
if (this.$refs['form']) {
|
||||
this.$refs['form'].resetFields()
|
||||
|
||||
@@ -348,6 +348,7 @@ layout("/layouts/platform.html"){
|
||||
<el-col :span="24" v-if="needFiles()">
|
||||
<el-form-item prop="files" label="附  件" required>
|
||||
<file-upload :files.sync="formData.files" card></file-upload>
|
||||
<div v-if="attachmentDescription" style="white-space: pre-wrap; overflow-wrap: anywhere; color: #f56c6c; line-height: 20px; margin-top: 8px;">{{ attachmentDescription }}</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
@@ -443,6 +444,13 @@ layout("/layouts/platform.html"){
|
||||
typeOptions: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 按当前类型读取材料说明,无说明时返回空串,避免切换类型后残留旧提示。
|
||||
attachmentDescription() {
|
||||
const selectedType = this.typeOptions.find(item => item.id === this.formData.type)
|
||||
return selectedType ? (selectedType.files_desc || '') : ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"formData.money"(val) {
|
||||
if (val > this.money) {
|
||||
|
||||
Reference in New Issue
Block a user