makePoster.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. <template>
  2. <view>
  3. <view class="head">
  4. <view class="left">海报预览
  5. <text class="text">
  6. (请拖动到下方编辑、保存海报)
  7. </text>
  8. </view>
  9. <My_upload @uploadCallback="handleFileLink">
  10. <view class="right">
  11. 更换背景图
  12. </view>
  13. </My_upload>
  14. </view>
  15. <view class="painter-box">
  16. <view>
  17. <l-painter ref="painter" css="position: relative;">
  18. <!-- 背景图片 -->
  19. <l-painter-image :src="file.url" css="width: 280px; height: 500px" object-fit="fill" />
  20. <!-- 模板1 底部背景图 -->
  21. <l-painter-image v-if="mode == 'model1'"
  22. src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712714733820B3d50bdd4.png"
  23. css="width: 280px; height: 130px;position: absolute;bottom: 0;z-index: 1;" object-fit="fill" />
  24. <block v-if="mode == 'model1' || mode == 'model2'">
  25. <!-- 站点logo -->
  26. <l-painter-image :src="siteLogo"
  27. css="width: 60px; height:60px;position: absolute;bottom: 0px;left:10px;z-index: 2;"
  28. object-fit="cover" />
  29. <!-- 文字描述 -->
  30. <l-painter-text :text="painterText"
  31. :css="'width: 190px; line-height:20px;position: absolute;bottom: 62px;left:10px;z-index: 2;font-size: 14px;color: #333333;line-clamp:2;' + 'color:' + textColor" />
  32. </block>
  33. <!-- 二维码 -->
  34. <l-painter-qrcode v-if="mode != 'default' && detail.isqrcode" :text="detail.qrcodecontent"
  35. css="width: 64px; height: 64px;position: absolute;bottom: 22px;right:10px;z-index: 2;" />
  36. </l-painter>
  37. </view>
  38. </view>
  39. <view class="custom">
  40. <view class="models">
  41. <view class="group">
  42. <view class="title">海报样式</view>
  43. <view class="options">
  44. <view class="option" v-for="option in ops.painter" hover-class="navigator-hover" :key="option.mode"
  45. @click="mode = option.mode">
  46. <image v-if="option.imgUrl" class="image" :src="option.imgUrl" />
  47. <image class="current" v-if="option.mode == mode"
  48. src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712715614059B373541f3.png" />
  49. </view>
  50. </view>
  51. </view>
  52. <view class="group">
  53. <view class="title">文字色彩</view>
  54. <view class="options">
  55. <view class="option" v-for="option in ops.text" hover-class="navigator-hover" :key="option.name"
  56. @click="textColor = option.color">
  57. <view class="text" :style="option.style">
  58. {{ option.name }}
  59. </view>
  60. <image class="current" v-if="option.color == textColor"
  61. src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712715614059B373541f3.png" />
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. <view class="text-box">
  67. <view class="title">
  68. 海报文案
  69. </view>
  70. <view class="input-box">
  71. <input class="input" maxlength="16" type="text" v-model="painterText">
  72. <icon v-if="painterText" class="icon" type="clear" size="3.733vw" @click="painterText = ''" />
  73. </view>
  74. </view>
  75. <view class="but" @click="loading ? '' : saveTheImage()" hover-class="navigator-hover">
  76. <u-loading-icon v-if="loading" color="#fff" />
  77. <text v-else>
  78. 保存
  79. </text>
  80. </view>
  81. </view>
  82. <view class="tips">
  83. *自定义海报区域可以选择海报样式、文字色彩等,文案部分最多可输入16个字,若留空,则不显示自定义文案。
  84. </view>
  85. <view style="height: 20px;" />
  86. </view>
  87. </template>
  88. <script>
  89. import lPainter from "../../uni_modules/lime-painter/components/l-painter/l-painter.vue"
  90. import lPainterView from "../../uni_modules/lime-painter/components/l-painter-view/l-painter-view.vue"
  91. import lPainterText from "../../uni_modules/lime-painter/components/l-painter-text/l-painter-text.vue"
  92. import lPainterImage from "../../uni_modules/lime-painter/components/l-painter-image/l-painter-image.vue"
  93. import lPainterQrcode from "../../uni_modules/lime-painter/components/l-painter-qrcode/l-painter-qrcode.vue"
  94. export default {
  95. components: { lPainter, lPainterView, lPainterText, lPainterImage, lPainterQrcode },
  96. data() {
  97. return {
  98. detail: {},
  99. file: {},
  100. siteLogo: uni.getStorageSync('site').attinfos[0].url || '',
  101. painterText: '自定义海报区域可以选择海报样式',
  102. mode: "model1",
  103. textColor: '#000000',
  104. ops: {
  105. painter: [{
  106. mode: "model1",
  107. imgUrl: "https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712714638752Bc18af43.png"
  108. }, {
  109. mode: "model2",
  110. imgUrl: "https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712714646946B480ca84d.png"
  111. }, {
  112. mode: "model3",
  113. imgUrl: "https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404101712714656283B28c9d1df.png"
  114. }, {
  115. mode: "default"
  116. }],
  117. text: [{
  118. name: "灰色",
  119. color: '#999999',
  120. style: "color: #999999; background: #FFFFFF;border: 1px solid #DDDDDD;"
  121. }, {
  122. name: "黑色",
  123. color: '#000000',
  124. style: 'color: #000000; background: #FFFFFF; border: 1px solid #DDDDDD;'
  125. }, {
  126. name: "白色",
  127. color: '#FFFFFF',
  128. style: "color: #FFFFFF;background: #CCCCCC;"
  129. },]
  130. },
  131. loading: false
  132. }
  133. },
  134. onLoad() {
  135. try {
  136. this.detail = this.$Http.data.detail;
  137. this.file = this.$Http.data.file;
  138. delete (this.$Http.data)
  139. } catch (error) {
  140. }
  141. },
  142. beforeDestroy() {
  143. this.deteleFiles()
  144. },
  145. methods: {
  146. saveTheImage() {
  147. let that = this;
  148. this.loading = true;
  149. this.$refs.painter.canvasToTempFilePathSync({
  150. fileType: "jpg",
  151. // 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
  152. pathType: 'url',
  153. quality: 1,
  154. success: (res) => {
  155. // 非H5 保存到相册
  156. // H5 提示用户长按图另存
  157. uni.saveImageToPhotosAlbum({
  158. filePath: res.tempFilePath,
  159. success: function (e) {
  160. uni.showModal({
  161. title: '提示',
  162. content: '图片已保存到系统相册',
  163. showCancel: false
  164. })
  165. that.loading = false;
  166. that.$Http.basic({
  167. "id": 20240319142702,
  168. "content": {
  169. sat_sharematerialid: that.detail.sat_sharematerialid, type: 1
  170. }
  171. }).then(res => {
  172. console.log(type, '记录', res)
  173. })
  174. },
  175. fail: ({ errMsg }) => {
  176. if (errMsg == 'saveImageToPhotosAlbum:fail auth deny') {
  177. uni.showModal({
  178. title: '提示',
  179. content: '请授权添加到相册权限后再试!',
  180. showCancel: false,
  181. complete: (complete) => {
  182. uni.openSetting({
  183. success: res => {
  184. that.loading = false;
  185. if (res.authSetting['scope.writePhotosAlbum']) {
  186. this.saveTheImage()
  187. } else {
  188. uni.showModal({
  189. title: '提示',
  190. content: '未获取授权!已取消保存',
  191. showCancel: false,
  192. })
  193. }
  194. }
  195. })
  196. },
  197. })
  198. } else {
  199. that.loading = false;
  200. uni.showModal({
  201. title: '提示',
  202. content: '已取消保存',
  203. showCancel: false,
  204. })
  205. }
  206. },
  207. });
  208. },
  209. });
  210. },
  211. handleFileLink(attachmentids, ownertable = "temporary", ownerid = 1, data) {
  212. this.deteleFiles()
  213. this.$Http.basic({
  214. "classname": "system.attachment.Attachment",
  215. "method": "createFileLink",
  216. "content": {
  217. ownertable,
  218. ownerid,
  219. usetype: 'painter',
  220. attachmentids
  221. }
  222. }).then(res => {
  223. console.log('绑定附件', res)
  224. if (this.cutoff(res.msg)) return;
  225. this.file = res.data[0];
  226. })
  227. },
  228. //删除附件
  229. deteleFiles() {
  230. if (this.file.ownertable == "temporary") this.$Http.basic({
  231. "classname": "system.attachment.Attachment",
  232. "method": "deleteFileLink",
  233. "content": {
  234. linksids: [this.file.linksid]
  235. }
  236. }).then(res => {
  237. console.log("处理删除附件", res)
  238. if (this.cutoff(res.msg)) return;
  239. });
  240. },
  241. },
  242. }
  243. </script>
  244. <style lang="scss">
  245. .head {
  246. display: flex;
  247. align-items: center;
  248. justify-content: space-between;
  249. padding: 10px;
  250. .left {
  251. line-height: 20px;
  252. font-family: Source Han Sans SC, Source Han Sans SC;
  253. font-size: 14px;
  254. color: #333333;
  255. .text {
  256. color: #666666;
  257. }
  258. }
  259. .right {
  260. color: #C30D23;
  261. font-size: 12px;
  262. }
  263. }
  264. .custom {
  265. width: 355px;
  266. background: #FFFFFF;
  267. border-radius: 8px;
  268. padding: 10px;
  269. box-sizing: border-box;
  270. margin: 10px auto;
  271. .models {
  272. display: flex;
  273. justify-content: space-between;
  274. .group {
  275. .title {
  276. line-height: 20px;
  277. font-family: Source Han Sans SC, Source Han Sans SC;
  278. font-size: 14px;
  279. color: #333333;
  280. margin-bottom: 10px;
  281. }
  282. .options {
  283. display: flex;
  284. .option {
  285. position: relative;
  286. width: 40px;
  287. height: 40px;
  288. background: #CCCCCC;
  289. border-radius: 5px;
  290. margin-right: 5px;
  291. overflow: hidden;
  292. box-sizing: border-box;
  293. .image,
  294. .text {
  295. display: flex;
  296. align-items: center;
  297. justify-content: center;
  298. width: 100%;
  299. height: 100%;
  300. font-family: Source Han Sans SC, Source Han Sans SC;
  301. font-size: 12px;
  302. box-sizing: border-box;
  303. border-radius: 5px;
  304. }
  305. .current {
  306. position: absolute;
  307. height: 14px;
  308. width: 14px;
  309. top: 0;
  310. right: 0;
  311. }
  312. }
  313. .option:last-child {
  314. margin-right: 0;
  315. }
  316. }
  317. }
  318. }
  319. .text-box {
  320. margin-top: 20px;
  321. .title {
  322. line-height: 20px;
  323. font-family: Source Han Sans SC, Source Han Sans SC;
  324. font-size: 14px;
  325. color: #333333;
  326. }
  327. .input-box {
  328. display: flex;
  329. align-items: center;
  330. width: 335px;
  331. height: 50px;
  332. background: #FFFFFF;
  333. border-radius: 8px;
  334. border: 1px solid #CCCCCC;
  335. margin-top: 10px;
  336. padding: 10px;
  337. box-sizing: border-box;
  338. .input {
  339. flex: 1;
  340. }
  341. }
  342. }
  343. .but {
  344. display: flex;
  345. align-items: center;
  346. justify-content: center;
  347. width: 333px;
  348. height: 45px;
  349. background: #C30D23;
  350. border-radius: 5px;
  351. margin-top: 20px;
  352. font-family: PingFang SC, PingFang SC;
  353. font-weight: bold;
  354. font-size: 16px;
  355. color: #FFFFFF;
  356. }
  357. }
  358. .tips {
  359. width: 355px;
  360. height: 34px;
  361. font-family: Source Han Sans SC, Source Han Sans SC;
  362. font-size: 12px;
  363. color: #666666;
  364. margin: 10px auto;
  365. }
  366. .painter-box {
  367. display: flex;
  368. justify-content: center;
  369. }
  370. </style>