特易招,招聘小程序
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.

503 lines
12 KiB

8 months ago
7 months ago
8 months ago
8 months ago
6 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
6 months ago
8 months ago
7 months ago
7 months ago
8 months ago
7 months ago
6 months ago
7 months ago
8 months ago
7 months ago
7 months ago
7 months ago
8 months ago
6 months ago
8 months ago
7 months ago
8 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
8 months ago
7 months ago
3 weeks ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
6 months ago
7 months ago
3 weeks ago
7 months ago
7 months ago
8 months ago
7 months ago
8 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
7 months ago
7 months ago
8 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
6 months ago
7 months ago
8 months ago
7 months ago
8 months ago
6 months ago
8 months ago
6 months ago
7 months ago
8 months ago
  1. <template>
  2. <view class="page">
  3. <navbar title="编辑模板" leftClick @leftClick="$utils.navigateBack" />
  4. <view class="title">
  5. <input type="text" placeholder="请输入标题" v-model="form.title"/>
  6. </view>
  7. <view style="padding: 25rpx;background-color: #fff;">
  8. <!-- 没有模板时的提示 -->
  9. <view v-if="!form.template || imageArr.length === 0" class="no-template-tip">
  10. <text>请先点击"导入合同"按钮上传PDF合同模板</text>
  11. </view>
  12. <canvas-drag ref="canvasRef"
  13. id="canvas-drag" :graph="graph"
  14. :width="width" :height="height"
  15. @onDrawArrChange="onDrawArrChange"
  16. enableUndo="true"></canvas-drag>
  17. </view>
  18. <view class="btn-list" v-if="imageArr.length > 0">
  19. <view class="uni-color-btn" @tap="pro">上一页</view>
  20. <view>{{ imagesIndex + 1 }}/{{ imageArr.length }}</view>
  21. <view class="uni-color-btn" @tap="next">下一页</view>
  22. </view>
  23. <view class="btn-list">
  24. <!-- <view class="uni-color-btn" @tap="onAddImage">新建签名</view> -->
  25. <view class="uni-color-btn" @tap="onChangeBgImage">导入合同</view>
  26. <view class="uni-color-btn" @tap="onUndo">后退</view>
  27. <!-- <view class="uni-color-btn" @tap="onClearCanvas">清空</view> -->
  28. <view class="uni-color-btn" @tap="submit">保存</view>
  29. <!-- <view class="uni-color-btn" @tap="onExportJSON">导出模板</view> -->
  30. <!-- <view class="uni-color-btn" @tap="onAddText">添加文字</view> -->
  31. <view class="uni-color-btn" @tap="previewContract" v-if="form.template">预览合同</view>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. import canvasDrag from "../components/canvas-drag/index";
  37. import setData from "../components/canvas-drag/setData.js";
  38. import wxBase64src from '@/utils/wxBase64src.js'
  39. export default {
  40. components: {
  41. canvasDrag
  42. },
  43. mixins : [setData],
  44. data() {
  45. return {
  46. height: 750,
  47. width: 700,
  48. drawArr : {},
  49. form : {
  50. template : '',
  51. employeePage : 0,//求职者(乙方)签字页码
  52. employeePosition : '',//求职者(乙方)签字坐标
  53. bossPage : 0,//招聘者(甲方)签字页码
  54. bossPosition : '',//招聘者(甲方)签字坐标
  55. title : '',
  56. },
  57. imagesIndex : 0,
  58. imageArr : [],
  59. id : 0,
  60. }
  61. },
  62. onLoad({id}) {
  63. // uni.request({
  64. // url : 'http://192.168.1.5:5173/arr',
  65. // method: 'GET',
  66. // success : res => {
  67. // this.imageArr = res.data
  68. // this.onChangeBgImage()
  69. // }
  70. // })
  71. this.id = id
  72. this.getDetail()
  73. },
  74. mounted() {
  75. console.log("mounted mounted mounted");
  76. },
  77. methods: {
  78. // async pro(){
  79. // if(this.imagesIndex == 0){
  80. // uni.showToast({
  81. // title: '已经是第一页了'
  82. // })
  83. // return
  84. // }
  85. // this.imagesIndex--
  86. // await wxBase64src.unlink()
  87. // this.changeBgImage()
  88. // },
  89. // async next(){
  90. // if(this.imagesIndex == this.imageArr.length - 1){
  91. // uni.showToast({
  92. // title: '已经是最后一页了'
  93. // })
  94. // return
  95. // }
  96. // this.imagesIndex++
  97. // await wxBase64src.unlink()
  98. // this.changeBgImage()
  99. // },
  100. async pro(){
  101. if(this.imagesIndex == 0){
  102. uni.showToast({
  103. title: '已经是第一页了'
  104. })
  105. return
  106. }
  107. this.imagesIndex--
  108. await wxBase64src.unlink()
  109. // 强制重新渲染canvas
  110. this.$nextTick(async () => {
  111. await this.changeBgImage()
  112. })
  113. },
  114. async next(){
  115. if(this.imagesIndex == this.imageArr.length - 1){
  116. uni.showToast({
  117. title: '已经是最后一页了'
  118. })
  119. return
  120. }
  121. this.imagesIndex++
  122. await wxBase64src.unlink()
  123. // 强制重新渲染canvas
  124. this.$nextTick(async () => {
  125. await this.changeBgImage()
  126. })
  127. },
  128. // 预览合同
  129. previewContract(){
  130. uni.downloadFile({
  131. url : this.form.template,
  132. success : res => {
  133. uni.openDocument({
  134. filePath: res.tempFilePath,
  135. })
  136. }
  137. })
  138. },
  139. // 签名位置更新时
  140. onDrawArrChange(arr){
  141. console.log(arr);
  142. this.drawArr = arr
  143. },
  144. /**
  145. * 添加签名位置
  146. */
  147. onAddImage() {
  148. // wx.chooseImage({
  149. // success: res => {
  150. // this.setData({
  151. // graph: {
  152. // w: 100,
  153. // h: 50,
  154. // type: 'image',
  155. // url: res.tempFilePaths[0]
  156. // }
  157. // });
  158. // }
  159. // });
  160. let a = {}
  161. let b = {}
  162. if(this.id){
  163. a = JSON.parse(this.form.bossPosition)
  164. b = JSON.parse(this.form.employeePosition)
  165. for(let ak in a){
  166. a[ak] = this.$utils.screenSystemInfoInt(a[ak]) - 0
  167. }
  168. for(let bk in b){
  169. b[bk] = this.$utils.screenSystemInfoInt(b[bk]) - 0
  170. }
  171. console.log(a, b);
  172. }
  173. uni.getImageInfo({
  174. src: this.configList.config_sign_a,
  175. // src: 'https://img.teyizhao.com/2025-02-07/3d837c0e-91f4-4682-82d9-a04c2af737e8.png',
  176. success : res => {
  177. this.setData({
  178. graph: {
  179. id : 'a',
  180. w: a.w || 40,
  181. h: a.h || 20,
  182. x: a.x || 30,
  183. y: a.y || 30,
  184. type: 'image',
  185. url : res.path
  186. }
  187. });
  188. },
  189. fail(e) {
  190. console.log(e);
  191. }
  192. })
  193. uni.getImageInfo({
  194. src: this.configList.config_sign_b,
  195. // src: 'https://img.teyizhao.com/2025-02-07/af4786c0-7b62-4a86-a090-9f28eca3674a.png',
  196. success : res => {
  197. this.setData({
  198. graph: {
  199. id : 'b',
  200. w: b.w || 40,
  201. h: b.h || 20,
  202. x: b.x || 160,
  203. y: b.y || 30,
  204. type: 'image',
  205. url : res.path
  206. }
  207. });
  208. },
  209. fail(e) {
  210. console.log(e);
  211. }
  212. })
  213. },
  214. /**
  215. * 导入合同
  216. */
  217. async onChangeBgImage() {
  218. let self = this
  219. let pdfUrl = await self.loadFDP()
  220. this.form.template = pdfUrl
  221. await this.pdf2imagebase64()
  222. this.changeBgImage()
  223. },
  224. // async changeBgImage(){
  225. // let self = this
  226. // let src = await wxBase64src.base64src(this.imageArr[this.imagesIndex])
  227. // uni.getImageInfo({
  228. // src,
  229. // success: image => {
  230. // console.log(image);
  231. // let allwh = image.height + image.width
  232. // let imgw = (image.width / allwh).toFixed(2)
  233. // let imgh = (image.height / allwh).toFixed(2)
  234. // self.height = imgh * Math.ceil(this.width / imgw)
  235. // self.$nextTick(() => {
  236. // uni.hideLoading()
  237. // this.$refs.canvasRef.changeBgImage(image.path)
  238. // })
  239. // },
  240. // fail(err) {
  241. // wxBase64src.unlink()
  242. // console.log(err);
  243. // }
  244. // })
  245. // },
  246. async changeBgImage(){
  247. let self = this
  248. try {
  249. uni.showLoading({
  250. title: '加载中...'
  251. })
  252. let src = await wxBase64src.base64src(this.imageArr[this.imagesIndex])
  253. const imageInfo = await new Promise((resolve, reject) => {
  254. uni.getImageInfo({
  255. src,
  256. success: resolve,
  257. fail: reject
  258. })
  259. })
  260. let allwh = imageInfo.height + imageInfo.width
  261. let imgw = (imageInfo.width / allwh).toFixed(2)
  262. let imgh = (imageInfo.height / allwh).toFixed(2)
  263. self.height = imgh * Math.ceil(this.width / imgw)
  264. // 确保DOM更新后再更新canvas
  265. await this.$nextTick()
  266. // 先清空画布再设置新图片
  267. // await this.$refs.canvasRef.clearCanvas()
  268. await this.$refs.canvasRef.changeBgImage(imageInfo.path)
  269. // 重新添加签名位置
  270. // this.onAddImage()
  271. } catch(err) {
  272. console.error('changeBgImage error:', err)
  273. wxBase64src.unlink()
  274. } finally {
  275. uni.hideLoading()
  276. }
  277. },
  278. loadFDP(){
  279. let that = this
  280. return new Promise((success, error) => {
  281. uni.chooseMessageFile({
  282. count: 1, //一次可以上传多少个
  283. type: 'file',
  284. // 移除extension限制,改为后续检查文件类型
  285. success(res) {
  286. const file = res.tempFiles[0]
  287. const fileName = file.name || ''
  288. const fileExtension = fileName.toLowerCase().split('.').pop()
  289. // 检查文件类型
  290. if (fileExtension !== 'pdf') {
  291. uni.showToast({
  292. title: '只能上传PDF文件,请重新选择',
  293. icon: 'none',
  294. duration: 3000
  295. })
  296. error(new Error('文件类型不正确'))
  297. return
  298. }
  299. // 文件类型正确,继续上传
  300. success(that.$Oss.ossUpload(file.path))
  301. },
  302. fail: (err) => {
  303. error(err)
  304. console.log(err, 'err');
  305. }
  306. });
  307. })
  308. },
  309. // 后退
  310. onUndo(event) {
  311. this.$refs.canvasRef.undo();
  312. },
  313. /**
  314. * 导出当前画布为模板
  315. */
  316. onExportJSON() {
  317. this.$refs.canvasRef.exportFun().then(imgArr => {
  318. console.log(imgArr);
  319. uni.previewImage({
  320. urls: [imgArr],
  321. current: 0,
  322. })
  323. }).catch(e => {
  324. console.error(e);
  325. });
  326. },
  327. /**
  328. * 添加文本
  329. */
  330. onAddText() {
  331. this.setData({
  332. graph: {
  333. type: 'text',
  334. text: 'helloworld'
  335. }
  336. });
  337. },
  338. onClearCanvas(event) {
  339. let _this = this;
  340. _this.setData({
  341. canvasBg: null
  342. });
  343. this.$refs.canvasRef.clearCanvas();
  344. },
  345. async submit() {
  346. if(this.$utils.verificationAll(this.form, {
  347. title : '请输入标题',
  348. })){
  349. return
  350. }
  351. let bossPosition = {
  352. // ...this.drawArr.a,
  353. x : this.$utils.rpxSystemInfoInt(this.drawArr.a.x),
  354. y : this.$utils.rpxSystemInfoInt(this.drawArr.a.y),
  355. w : this.$utils.rpxSystemInfoInt(this.drawArr.a.w),
  356. h : this.$utils.rpxSystemInfoInt(this.drawArr.a.h),
  357. }
  358. let employeePosition = {
  359. // ...this.drawArr.b,
  360. x : this.$utils.rpxSystemInfoInt(this.drawArr.b.x),
  361. y : this.$utils.rpxSystemInfoInt(this.drawArr.b.y),
  362. w : this.$utils.rpxSystemInfoInt(this.drawArr.b.w),
  363. h : this.$utils.rpxSystemInfoInt(this.drawArr.b.h),
  364. }
  365. this.form.bossPosition = JSON.stringify(bossPosition)
  366. this.form.employeePosition = JSON.stringify(employeePosition)
  367. this.form.bossPage = this.imagesIndex
  368. this.form.employeePage = this.imagesIndex
  369. this.$api(this.id ? 'updateContractTemplate' :
  370. 'addContractTemplate', this.form).then(res => {
  371. if(res.code == 200){
  372. uni.navigateBack(-1)
  373. }
  374. })
  375. },
  376. // pdf转图片base64
  377. async pdf2imagebase64(){
  378. uni.showLoading({
  379. title: '解析文档中...'
  380. })
  381. let res = await this.$api('pdf2imagebase64', {
  382. pdfPath : this.form.template
  383. })
  384. this.imageArr = []
  385. for(let key in res.result){
  386. this.imageArr.push(res.result[key])
  387. }
  388. },
  389. getDetail(){
  390. if(!this.id){
  391. this.onAddImage()
  392. return
  393. }
  394. this.$api('queryContractTemplateById', {
  395. contractTemplateId : this.id
  396. }).then(async (res) => {
  397. if(res.code == 200){
  398. this.form = res.result
  399. this.imagesIndex = this.form.employeePage
  400. delete this.form.createBy
  401. delete this.form.createTime
  402. delete this.form.updateBy
  403. delete this.form.updateTime
  404. this.onAddImage()
  405. await this.pdf2imagebase64()
  406. this.changeBgImage()
  407. }
  408. })
  409. },
  410. }
  411. }
  412. </script>
  413. <style scoped lang="scss">
  414. .page {
  415. padding-bottom: 100rpx;
  416. .title{
  417. padding: 10rpx 30rpx;
  418. background-color: #fff;
  419. margin-bottom: 10rpx;
  420. input{
  421. padding: 20rpx;
  422. background-color: rgba($uni-color, 0.1);
  423. color: $uni-color;
  424. border: 1rpx solid $uni-color;
  425. border-radius: 10rpx;
  426. }
  427. }
  428. .no-template-tip {
  429. display: flex;
  430. align-items: center;
  431. justify-content: center;
  432. height: 300rpx;
  433. background-color: #f8f9fa;
  434. border: 2rpx dashed #ddd;
  435. border-radius: 10rpx;
  436. margin-bottom: 20rpx;
  437. text {
  438. color: #999;
  439. font-size: 28rpx;
  440. text-align: center;
  441. }
  442. }
  443. .btn-list {
  444. display: flex;
  445. flex-wrap: wrap;
  446. align-items: center;
  447. padding: 20rpx;
  448. gap: 30rpx;
  449. justify-content: center;
  450. .uni-color-btn {
  451. margin: 0;
  452. border-radius: 10rpx;
  453. }
  454. }
  455. }
  456. </style>