移动端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

467 line
15 KiB

  1. <template>
  2. <div class="app-container">
  3. <van-nav-bar left-arrow fixed placeholder @click-left="$router.push({path:'/contracted/index'})" >
  4. <template #title>
  5. <div class="tb_main">
  6. {{ $route.query.deptName }}
  7. </div>
  8. </template>
  9. </van-nav-bar>
  10. <div class="tap_block">
  11. <p @click="$router.push({path:'/contracted/village/contractor', query: { deptId: $route.query.deptId, deptName: $route.query.deptName }})">承包方</p>
  12. <p class="active">发包方</p>
  13. <p @click="$router.push({path:'/contracted/village/massif', query: { deptId: $route.query.deptId, deptName: $route.query.deptName }})">地块</p>
  14. <p @click="$router.push({path:'/contracted/village/map', query: { deptId: $route.query.deptId, deptName: $route.query.deptName }})">地图</p>
  15. </div>
  16. <div class="list_main">
  17. <van-form ref="formData">
  18. <van-field v-model="form.fbfbm" label="代码:" placeholder="<自动生成>" :border="false" input-align="right" label-width="auto" :disabled="true" maxlength="14">
  19. <!-- <template #button v-if="!isDisabled">
  20. <van-button size="mini" type="primary" native-type="button" @click="generateCode">生成代码</van-button>
  21. </template> -->
  22. </van-field>
  23. <van-field v-model="form.fbfmc" label="名称:" placeholder="请输入名称" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="50" />
  24. <van-field v-model="form.fbffzrxm" label="负责人姓名:" placeholder="请输入负责人姓名" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="50" />
  25. <van-field v-model="credentialTypeText" label="证件类型:"
  26. placeholder="请选择证件类型"
  27. required
  28. :rules="[{ required: true }]"
  29. :border="false"
  30. input-align="right"
  31. right-icon="arrow-down"
  32. label-width="auto"
  33. readonly
  34. clickable
  35. @click="showCredentialType = true"
  36. />
  37. <van-popup v-model="showCredentialType" position="bottom">
  38. <van-picker
  39. show-toolbar
  40. :columns="credentialTypeOptions"
  41. value-key="dictLabel"
  42. @confirm="onConfirmTypeOptions"
  43. @cancel="showCredentialType = false"
  44. />
  45. </van-popup>
  46. <van-field v-model="form.fzrzjhm" label="证件号码:" placeholder="请输入证件号码" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="30" />
  47. <van-field v-model="form.lxdh" label="联系电话:" placeholder="请输入联系电话" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="15" />
  48. <van-field v-model="form.fbfdz" label="地址:" placeholder="请输入地址" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="100" />
  49. <van-field v-model="form.yzbm" label="邮政编码:" placeholder="请输入邮政编码" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="6" />
  50. <van-field v-model="form.fbfdcy" label="调查员:" placeholder="请输入调查员" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="30" />
  51. <van-field v-model="form.fbfdcrq" label="调查日期:" placeholder="请选择调查日期" required :rules="[{ required: true }]"
  52. :border="false" input-align="right" right-icon="arrow-down" readonly clickable @click="showDcrq = true" />
  53. <van-popup v-model="showDcrq" position="bottom">
  54. <van-datetime-picker
  55. :value="form.fbfdcrq ? new Date(form.fbfdcrq) : new Date()"
  56. type="date"
  57. title="请选择调查日期"
  58. :min-date="minDate"
  59. :max-date="maxDate"
  60. @confirm="onConfirmDcrq"
  61. @cancel="showDcrq = false"
  62. />
  63. </van-popup>
  64. <van-field v-model="form.fbfdcjs" label="调查记事:" placeholder="请输入调查记事" type="textarea" rows="3" required :rules="[{ required: true }]" :border="false" input-align="right" label-width="auto" maxlength="200" />
  65. <van-field label="签字图片:" readonly :border="false" label-width="auto" />
  66. <img :src="'/api'+form.fbfdcqz" width="100%" alt="" />
  67. </van-form>
  68. <div class="btn_main" v-if="taskStatus === '2'">
  69. <p class="btn" @click="submitForm">保存</p>
  70. <p class="btn1" @click="handleSign">签字</p>
  71. </div>
  72. </div>
  73. <van-popup v-model="showSignPopup" closeable position="right" :style="{ height: '100%' }" >
  74. <van-cell-group style="width: 100%;height:100%;overflow: hidden;padding-top: 10px;padding-bottom: 10px;">
  75. <div class="signature-box" @mousedown="canvasTTdown" @touchstart="canvasTTdown">
  76. <vue-esign
  77. ref="esign"
  78. class="mySign"
  79. :width="500"
  80. :height="height"
  81. :isCrop="signature.isCrop"
  82. :lineWidth="signature.lineWidth"
  83. :lineColor="signature.lineColor"
  84. :bgColor.sync="signature.bgColor"
  85. />
  86. </div>
  87. <img src="../../../../assets/images/sunVillage_info/signature_icon_10.png" id="canvasTT" style="position:absolute;top: 50%;left: 50%;transform: translate(-50%,-50%)" alt="">
  88. <div class="signature-footer">
  89. <van-button @click="handleReset" class="clearBtn" type="info" plain size="small">清空画板</van-button>
  90. <van-button @click="handleGenerate" type="info" size="small">保存签字</van-button>
  91. </div>
  92. </van-cell-group>
  93. </van-popup>
  94. </div>
  95. </template>
  96. <script>
  97. import Cookies from "js-cookie";
  98. import { listFbf, addFbf, updateFbf, manualSignature, generateEmployerCode } from "@/api/contracted/fbf";
  99. import vueEsign from "vue-esign";
  100. import $ from "jquery";
  101. export default {
  102. name: "contractedVillageContractor",
  103. components: {
  104. vueEsign
  105. },
  106. data() {
  107. return {
  108. form: {}, // 发包方信息表单
  109. // isDisabled: false, // 是否禁用
  110. credentialTypeOptions: [], // 证件类型字典
  111. credentialTypeText: null, // 证件类型标签名
  112. showCredentialType: false, // 控制证件类型字典弹出层的显示和隐藏
  113. taskStatus: null, // 调查任务的完成状态:1表示已完成,2表示未完成
  114. // 控制签字面板的显示和隐藏
  115. showSignPopup: false,
  116. height: null,
  117. //电子签名
  118. signature: {
  119. lineWidth: 6, // 画笔的线条粗细
  120. lineColor: "#000000", // 画笔的颜色
  121. bgColor: "", // 画布的背景颜色
  122. resultImg: "", // 最终画布生成的base64图片
  123. isCrop: false, // 是否裁剪,在画布设定尺寸基础上裁掉四周空白部分
  124. },
  125. // 调查日期弹出层
  126. showDcrq: false,
  127. minDate: new Date(1978, 0, 1),
  128. maxDate: new Date(2100, 11, 31),
  129. };
  130. },
  131. created() {
  132. this.taskStatus = Cookies.get('taskStatus');
  133. this.height = window.screen.height * 1.28 - 20;
  134. this.getDicts("cert_type").then(response => {
  135. this.credentialTypeOptions = response.data;
  136. });
  137. },
  138. mounted() {
  139. this.getDetail();
  140. },
  141. methods: {
  142. getDetail() {
  143. listFbf({deptId: this.$route.query.deptId}).then(response => {
  144. if (response.rows.length > 0) {
  145. this.form = response.rows[0];
  146. // this.isDisabled = true;
  147. this.$nextTick(() => {
  148. this.credentialTypeText = this.selectDictLabel(this.credentialTypeOptions, this.form.fzrzjlx);
  149. });
  150. } else {
  151. this.resetForm();
  152. // this.isDisabled = false;
  153. }
  154. });
  155. },
  156. /* generateCode() {
  157. generateEmployerCode({deptId: this.$route.query.deptId}).then(response => {
  158. this.$set(this.form, 'fbfbm', response.data);
  159. });
  160. }, */
  161. onConfirmTypeOptions(value){
  162. this.form.fzrzjlx = value.dictValue;
  163. this.credentialTypeText = value.dictLabel;
  164. this.showCredentialType = false;
  165. },
  166. onConfirmDcrq(data) {
  167. this.form.fbfdcrq = this.format(data, 'yyyy-MM-dd');
  168. this.showDcrq = false;
  169. },
  170. submitForm() {
  171. this.$refs.formData.validate().then(() => {
  172. if (this.form.id) {
  173. updateFbf(this.form).then(response => {
  174. if (response.code == 200) {
  175. this.$toast({
  176. icon: 'success',
  177. message: '保存成功',
  178. duration:"1000",
  179. });
  180. }
  181. });
  182. } else {
  183. this.form.deptId = this.$route.query.deptId;
  184. addFbf(this.form).then(response => {
  185. if (response.code == 200) {
  186. this.$toast({
  187. icon: 'success',
  188. message: '保存成功',
  189. duration:"1000",
  190. onClose: () => {
  191. this.getDetail();
  192. }
  193. });
  194. }
  195. });
  196. }
  197. }).catch(() => {
  198. this.$notify({ type: 'danger', message: '请填写完整的表单项' });
  199. });
  200. },
  201. resetForm() {
  202. this.form = {
  203. deptId: null,
  204. fbfbm: null,
  205. fbfmc: null,
  206. fbffzrxm: null,
  207. fzrzjlx: '1',
  208. fzrzjhm: null,
  209. lxdh: null,
  210. fbfdz: null,
  211. yzbm: null,
  212. fbfdcy: null,
  213. fbfdcrq: null,
  214. fbfdcjs: null,
  215. fbfdcqz: null
  216. };
  217. this.credentialTypeText = '居民身份证';
  218. },
  219. handleSign() {
  220. this.showSignPopup = true;
  221. this.handleReset();
  222. },
  223. canvasTTdown() {
  224. $('#canvasTT').css('display', 'none');
  225. },
  226. // 清空画板
  227. handleReset() {
  228. if (this.$refs.esign) {
  229. this.$refs.esign.reset();
  230. }
  231. $('#canvasTT').css('display', 'block')
  232. },
  233. // 生成签字图片
  234. handleGenerate() {
  235. this.$refs.esign
  236. .generate() // 使用生成器调用把签字的图片转换成为base64图片格式
  237. .then((res) => {
  238. this.signature.resultImg = res;
  239. let wj = this.dataURLtoBlob(res);
  240. let param = new FormData(); // 创建form对象
  241. param.append('file', wj); // 通过append向form对象添加数据
  242. param.append('deptId', this.$route.query.deptId);
  243. manualSignature(param).then(response => {
  244. if (response.code === 200) {
  245. this.$toast({
  246. icon: 'success', // 找到自己需要的图标
  247. message: '签字成功',
  248. duration: "1000",
  249. onClose: () => {
  250. this.showSignPopup = false;
  251. this.form.fbfdcqz = response.data;
  252. }
  253. });
  254. }
  255. });
  256. })
  257. .catch((err) => {
  258. // 画布没有签字时会执行这里提示一下
  259. this.$toast.fail('请签名后再保存签字');
  260. });
  261. },
  262. dataURLtoBlob(dataurl, filename = 'file') {
  263. let arr = dataurl.split(',')
  264. let mime = arr[0].match(/:(.*?);/)[1]
  265. let suffix = mime.split('/')[1]
  266. let bstr = atob(arr[1])
  267. let n = bstr.length
  268. let u8arr = new Uint8Array(n)
  269. while (n--) {
  270. u8arr[n] = bstr.charCodeAt(n)
  271. }
  272. return new File([u8arr], `${filename}.${suffix}`, {
  273. type: mime
  274. })
  275. },
  276. },
  277. };
  278. </script>
  279. <style scoped lang="scss">
  280. .app-container{
  281. background: #fff url("../../../../../static/images/contracted/contracted_index_bg.png") no-repeat center;
  282. background-size: 100% 100%;
  283. height: 100vh;
  284. padding: 0 4vw;
  285. overflow: hidden;
  286. }
  287. /deep/ .van-nav-bar{
  288. background: transparent;
  289. }
  290. /deep/ .van-nav-bar .van-icon{
  291. color: #000000;
  292. }
  293. /deep/ .van-hairline--bottom::after{
  294. border: none;
  295. }
  296. /deep/ .van-search__content{
  297. background: rgba(255,255,255,.5);
  298. }
  299. /deep/ .van-search{
  300. padding: 0;
  301. flex: 1;
  302. }
  303. /deep/ .van-ellipsis{
  304. overflow: initial;
  305. }
  306. /deep/ .van-field--disabled .van-field__label {
  307. color: #646566;
  308. }
  309. .tb_main{
  310. position: relative;
  311. p{
  312. position: absolute;
  313. display: inline-block;
  314. margin-left: 10PX;
  315. }
  316. }
  317. .tb{
  318. font-size: 12px;
  319. color: #ff8900;
  320. background: #daf6e7;
  321. border: 1px solid #d7be6e;
  322. padding: 2PX 8PX;
  323. border-radius: 50PX;
  324. margin-right: 5PX;
  325. }
  326. .tap_block{
  327. width: 100%;
  328. display: flex;
  329. justify-content: space-between;
  330. background: #ebfaf2;
  331. padding: 2PX 4PX;
  332. border-radius: 10PX;
  333. margin-top: 1vh;
  334. .active{
  335. background-image: linear-gradient(to right,#c6fe8b,#48e5a2);
  336. box-shadow: 0 0 10PX #cccccc;
  337. color: #333333;
  338. }
  339. p{
  340. width: 25%;
  341. text-align: center;
  342. padding: 5PX 0;
  343. border-radius: 10PX;
  344. color: #666666;
  345. }
  346. }
  347. .search_main{
  348. display: flex;
  349. margin-top: 2vh;
  350. .search_btn{
  351. background: rgba(255,255,255,.5);
  352. width: 25%;
  353. border-radius: 50PX;
  354. margin-left: 10PX;
  355. padding: 2PX;
  356. .active{
  357. background-image: linear-gradient(to right,#c6fe8b,#48e5a2);
  358. color: #333333;
  359. border-radius: 50PX;
  360. display: flex;
  361. align-items: center;
  362. justify-content: center;
  363. height: 100%;
  364. }
  365. }
  366. }
  367. .second_tap{
  368. display: flex;
  369. align-items: center;
  370. margin-top: 1vh;
  371. p{
  372. background: #dbf1ea;
  373. border: 1px solid #cdcdcd;
  374. color: #5f5f5f;
  375. padding: 5PX 15PX;
  376. margin-right: 3vw;
  377. border-radius: 50PX;
  378. }
  379. .active{
  380. background: #99eecb;
  381. border-color: #48e5a2;
  382. color: #333333;
  383. }
  384. }
  385. .list_main{
  386. margin-top: 2vh;
  387. overflow-y: scroll;
  388. text-align: center;
  389. background: #ffffff;
  390. border-top-left-radius: 10PX;
  391. border-top-right-radius: 10PX;
  392. height: 88vh;
  393. .btn_main{
  394. .btn1{
  395. background-image: linear-gradient(to right,#ffd88e,#fc8a0e);
  396. box-shadow: 0 0 10PX #cccccc;
  397. padding: 10PX 0PX;
  398. border-radius: 50PX;
  399. display: inline-block;
  400. width: 30%;
  401. margin-top: 2vh;
  402. margin-left: 2vw;
  403. }
  404. .btn{
  405. background-image: linear-gradient(to right,#c6fe8b,#48e5a2);
  406. box-shadow: 0 0 10PX #cccccc;
  407. padding: 10PX 0PX;
  408. border-radius: 50PX;
  409. display: inline-block;
  410. width: 30%;
  411. margin-top: 2vh;
  412. }
  413. }
  414. }
  415. .mapBox{
  416. width: 94%;
  417. height: 50vw;
  418. background-image: linear-gradient(to right,#c6fe8b,#48e5a2);
  419. border-radius: 10PX;
  420. margin: 2vh auto;
  421. }
  422. .signature-box {
  423. border: 1px dashed #666;
  424. margin: 2px 20px;
  425. height: 100%;
  426. /*canvas{*/
  427. /* height: 100%!important;*/
  428. /*}*/
  429. }
  430. .signature-footer {
  431. transform: rotate(90deg);
  432. width: auto;
  433. position: absolute;
  434. top: 50%;
  435. left: 0PX;
  436. .clearBtn {
  437. margin-left: 15px;
  438. }
  439. }
  440. </style>