info.ejs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  6. <meta http-equiv="x-ua-compatible" content="ie=edge">
  7. <title>电子签名-计量支付</title>
  8. <style>
  9. #app {
  10. position: absolute;
  11. top: 0;
  12. left: 0;
  13. right: 0;
  14. bottom: 0;
  15. font-family: 'Avenir', Helvetica, Arial, sans-serif;
  16. -webkit-font-smoothing: antialiased;
  17. -moz-osx-font-smoothing: grayscale;
  18. text-align: center;
  19. color: #2c3e50;
  20. }
  21. .container {
  22. width: 100%;
  23. height: 100%;
  24. }
  25. #canvasBox {
  26. display: flex;
  27. flex-direction: column;
  28. height: 100%;
  29. align-items: center; /*定义body的元素垂直居中*/
  30. justify-content: center; /*定义body的里的元素水平居中*/
  31. }
  32. .greet {
  33. padding: 20px;
  34. font-size: 20px;
  35. user-select: none;
  36. }
  37. input {
  38. font-size: 20px;
  39. }
  40. .greet select {
  41. font-size: 18px;
  42. }
  43. canvas {
  44. flex: 1;
  45. cursor: crosshair;
  46. border:2px dashed #007bff;
  47. }
  48. .image-box {
  49. width: 100%;
  50. height: 100%;
  51. }
  52. .image-box header{
  53. font-size: 18px;
  54. }
  55. .image-box img {
  56. max-width: 80%;
  57. max-height: 80%;
  58. margin-top: 50px;
  59. border: 1px solid gray;
  60. }
  61. </style>
  62. </head>
  63. <body>
  64. <div id="app">
  65. <% if (error !== undefined && error) { %>
  66. <div>参数有误, 无法访问本页.</div>
  67. <% } else { %>
  68. <div class="container">
  69. <div id="canvasBox" :style="getHorizontalStyle" v-show="!showBox">
  70. <div class="greet">
  71. <span>{{msg}}</span>
  72. <input type="button" value="清空" @touchstart="clear" @mousedown="clear"/>
  73. <input type="button" value="下一步 生成签名图" @touchstart="savePNG" @mousedown="savePNG"/>
  74. </div>
  75. <canvas></canvas>
  76. </div>
  77. <div class="image-box" v-show="showBox">
  78. <header>
  79. <input type="button" value="返回" @click="showBox = false"/>
  80. <input type="button" value="上传" @click="upload" :disabled="showSuccess"/>
  81. <span v-show="showSuccess">已成功上传!</span>
  82. </header>
  83. <img :src="signImage">
  84. </div>
  85. </div>
  86. <% } %>
  87. </div>
  88. <% if (error === false) { %>
  89. <script type="text/javascript" src="/public/js/vue/vue.js"></script>
  90. <script type="text/javascript" src="/public/js/draw.js"></script>
  91. <script>
  92. const id = '<%- id %>';
  93. const name = '<%- name %>';
  94. const csrf = '<%= ctx.csrf %>';
  95. new Vue({
  96. el: '#app',
  97. data() {
  98. return {
  99. msg: '您好,' + name + ',请在虚线框内手写您的签名。',
  100. degree: 90, // 屏幕整体旋转的角度, 可取 -90,90,180等值
  101. signImage: null,
  102. showBox: false,
  103. showSuccess: false
  104. };
  105. },
  106. components: {
  107. Draw,
  108. },
  109. beforeCreate() {
  110. // document.title = '手写签名';
  111. },
  112. mounted() {
  113. this.canvasBox = document.getElementById('canvasBox');
  114. this.initCanvas();
  115. },
  116. computed: {
  117. getHorizontalStyle() {
  118. const d = document;
  119. const w = window.innerWidth || d.documentElement.clientWidth || d.body.clientWidth;
  120. const h = window.innerHeight || d.documentElement.clientHeight || d.body.clientHeight;
  121. let length = (h - w) / 2;
  122. let width = w;
  123. let height = h;
  124. switch (this.degree) {
  125. case -90:
  126. length = -length;
  127. case 90:
  128. width = h;
  129. height = w;
  130. break;
  131. default:
  132. length = 0;
  133. }
  134. if (this.canvasBox) {
  135. this.canvasBox.removeChild(document.querySelector('canvas'));
  136. this.canvasBox.appendChild(document.createElement('canvas'));
  137. setTimeout(() => {
  138. this.initCanvas();
  139. }, 200);
  140. }
  141. return {
  142. transform: `rotate(${this.degree}deg) translate(${length}px,${length}px)`,
  143. width: `${width}px`,
  144. height: `${height}px`,
  145. transformOrigin: 'center center',
  146. };
  147. },
  148. },
  149. methods: {
  150. initCanvas() {
  151. const canvas = document.querySelector('canvas');
  152. this.draw = new Draw(canvas, -this.degree);
  153. },
  154. clear() {
  155. this.draw.clear();
  156. },
  157. download() {
  158. this.draw.downloadPNGImage(this.draw.getPNGImage());
  159. },
  160. savePNG() {
  161. this.signImage = this.draw.getPNGImage();
  162. this.showBox = true;
  163. this.showSuccess = false;
  164. },
  165. upload() {
  166. if (!this.showSuccess) {
  167. const image = this.draw.getPNGImage();
  168. const blob = this.draw.dataURLtoBlob(image);
  169. const url = '/sign/save';
  170. const successCallback = (response) => {
  171. // console.log(response);
  172. if (JSON.parse(response).err === 0) {
  173. this.showSuccess = true;
  174. } else {
  175. this.showSuccess = false;
  176. }
  177. };
  178. const failureCallback = (error) => {
  179. // console.log(error);
  180. this.showSuccess = false;
  181. };
  182. this.draw.upload(blob, url, successCallback, failureCallback);
  183. }
  184. },
  185. },
  186. });
  187. </script>
  188. <% } %>
  189. </body>
  190. </html>