Commit bc747db80900204f58827a0f577d801a912e339e

Authored by ly525
1 parent d6787783

feat: set up cover when saving work

front-end/h5/package.json
... ... @@ -15,6 +15,7 @@
15 15 "core-js": "^2.6.5",
16 16 "element-ui": "^2.9.1",
17 17 "font-awesome": "4.7.0",
  18 + "html2canvas": "^1.0.0-rc.3",
18 19 "node-sass": "^4.12.0",
19 20 "proxy-agent": "^3.1.0",
20 21 "qrcode": "^1.4.1",
... ...
front-end/h5/src/components/core/editor/index.js
... ... @@ -99,10 +99,7 @@ export default {
99 99 pages: state => state.work.pages,
100 100 work: state => state.work
101 101 }),
102   - ...mapState('loading', {
103   - saveWork_loading: state => state.saveWork_loading,
104   - setWorkAsTemplate_loading: state => state.setWorkAsTemplate_loading
105   - })
  102 + ...mapState('loading', ['saveWork_loading', 'setWorkAsTemplate_loading', 'uploadWorkCover_loading'])
106 103 },
107 104 methods: {
108 105 ...mapActions('editor', [
... ... @@ -170,7 +167,7 @@ export default {
170 167 style={{ lineHeight: '64px', float: 'right', background: 'transparent' }}
171 168 >
172 169 <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small" onClick={() => { this.previewVisible = true }}>预览</a-button></a-menu-item>
173   - <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()} loading={this.saveWork_loading}>保存</a-button></a-menu-item>
  170 + <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork({ isSaveCover: true })} loading={this.saveWork_loading || this.uploadWorkCover_loading}>保存</a-button></a-menu-item>
174 171 {/* <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> */}
175 172 <a-menu-item key="3" class="transparent-bg">
176 173 <a-dropdown-button onClick={() => {}} size="small">
... ...
front-end/h5/src/store/modules/loading.js
... ... @@ -4,7 +4,8 @@ const state = {
4 4 fetchWorks_loading: false,
5 5 setWorkAsTemplate_loading: false,
6 6 fetchWorkTemplates_loading: false,
7   - useTemplate_loading: false
  7 + useTemplate_loading: false,
  8 + uploadWorkCover_loading: false
8 9 }
9 10  
10 11 // getters
... ...
front-end/h5/src/store/modules/work.js
... ... @@ -4,6 +4,7 @@ import Page from &#39;../../components/core/models/page&#39;
4 4 import Work from '../../components/core/models/work'
5 5 import { AxiosWrapper } from '../../utils/http.js'
6 6 import router from '@/router.js'
  7 +import { takeScreenshot } from '../../utils/helper.js'
7 8  
8 9 export const actions = {
9 10 previewWork ({ commit }, payload = {}) {
... ... @@ -30,20 +31,30 @@ export const actions = {
30 31 }
31 32 commit('setWork', work)
32 33 },
33   - saveWork ({ commit, dispatch, state }, payload = {}) {
34   - // update work with strapi
35   - const work = {
36   - ...state.work,
37   - ...payload
  34 + /**
  35 + * isSaveCover {Boolean} 保存作品时,是否保存封面图
  36 + */
  37 + saveWork ({ commit, dispatch, state }, { isSaveCover = false } = {}) {
  38 + const fn = (callback) => {
  39 + new AxiosWrapper({
  40 + dispatch,
  41 + commit,
  42 + loading_name: 'saveWork_loading',
  43 + successMsg: '保存作品成功',
  44 + customRequest: strapi.updateEntry.bind(strapi)
  45 + }).put('works', state.work.id, state.work).then(callback)
38 46 }
39   -
40   - return new AxiosWrapper({
41   - dispatch,
42   - commit,
43   - loading_name: 'saveWork_loading',
44   - successMsg: '保存作品成功',
45   - customRequest: strapi.updateEntry.bind(strapi)
46   - }).put('works', state.work.id, work)
  47 + return new Promise((resolve, reject) => {
  48 + if (isSaveCover) {
  49 + takeScreenshot().then(file => {
  50 + dispatch('uploadCover', { file }).then(() => {
  51 + fn(resolve)
  52 + }) // uploadCover
  53 + }) // takeScreenshot
  54 + } else {
  55 + fn(resolve)
  56 + }
  57 + })
47 58 },
48 59 fetchWork ({ commit, state }, workId) {
49 60 strapi.getEntry('works', workId).then(entry => {
... ... @@ -158,12 +169,52 @@ export const actions = {
158 169 loading_name: 'useTemplate_loading',
159 170 successMsg: '使用模板成功'
160 171 }).post(`/works/use-template/${workId}`)
  172 + },
  173 + uploadCover ({ commit, state, dispatch }, { file } = {}) {
  174 + const formData = new FormData()
  175 + formData.append('files', file, `${+new Date()}.png`)
  176 + formData.append('workId', state.work.id)
  177 + return new AxiosWrapper({
  178 + dispatch,
  179 + commit,
  180 + name: 'editor/setWorkCover',
  181 + loading_name: 'uploadWorkCover_loading',
  182 + successMsg: '上传封面图成功!'
  183 + // }).post(`/works/uploadCover/${state.work.id}`, formData)
  184 + }).post(`/upload/`, formData)
161 185 }
162 186 }
163 187  
164 188 // mutations
165 189 export const mutations = {
166 190 /**
  191 + *
  192 + * @param {*} state
  193 + * @param {Object} payload
  194 + *
  195 + value example: [
  196 + {
  197 + "id": 1,
  198 + "name": "1567769149231.png",
  199 + "hash": "1660b11229e7473b90f99a9f9afe7675",
  200 + "sha256": "lKl7f_csUAgOjf0VRYkBZ64EcTjvt4Dt4beNIhELpTU",
  201 + "ext": ".png",
  202 + "mime": "image/png",
  203 + "size": "6.57",
  204 + "url": "/uploads/1660b11229e7473b90f99a9f9afe7675.png",
  205 + "provider": "local",
  206 + "public_id": null,
  207 + "created_at": "2019-09-06T11:25:49.255Z",
  208 + "updated_at": "2019-09-06T11:25:49.261Z",
  209 + "related": []
  210 + }
  211 + ]
  212 + */
  213 + setWorkCover (state, { type, value }) {
  214 + const [cover] = value
  215 + state.work.cover_image_url = cover.url
  216 + },
  217 + /**
167 218 * payload: {
168 219 * type: @params {String} "editor/setWorks",
169 220 * value: @params {Array} work list
... ...
front-end/h5/src/utils/helper.js 0 → 100644
  1 +import html2canvas from 'html2canvas'
  2 +
  3 +/**
  4 + * 生成作品封面图(截图)
  5 + * @param {String} selector
  6 + * @param {文件名} fileName
  7 + */
  8 +export function takeScreenshot (selector = '.canvas-wrapper', fileName = `${+new Date()}`) {
  9 + const el = document.querySelector(selector)
  10 + return new Promise((resolve, reject) => {
  11 + // html2canvas document: https://html2canvas.hertzen.com/configuration
  12 + // allowTaint: Whether to allow cross-origin images to taint the canvas
  13 + // if you use allowTaint: true, the cors image will taint the canvas, and canvas.toDataURL won't work
  14 + // 会对canvas造成污染,导致 canvas.toDataURL 无效
  15 + html2canvas(el, { allowTaint: true }).then(canvas => {
  16 + // document.body.appendChild(canvas) use this line to test the generated canvas
  17 + canvas.toBlob(blob => {
  18 + const file = new window.File([blob], fileName, { type: 'image/png' })
  19 + resolve(file)
  20 + })
  21 + })
  22 + })
  23 +}
... ...
front-end/h5/vue.config.js
1   -// const ProxyAgent = require('proxy-agent')
2 1 const isProd = process.env.NODE_ENV === 'production'
3   -
4   -const PROD_API_ORIGIN = 'https://luban-h5-api.herokuapp.com'
5   -const DEV_API_ORIGIN = 'http://localhost:1337'
6   -// const DEV_API_ORIGIN = 'https://luban-h5-api.herokuapp.com'
7   -
  2 +const target = 'http://localhost:1337'
8 3 module.exports = {
9 4 runtimeCompiler: true,
10 5 // 因为需要部署到 github pages,所以需要将 publicPath 设为 "/< GitHub Repo Name>/"
... ... @@ -14,8 +9,12 @@ module.exports = {
14 9 // proxy: API_ORIGIN
15 10 proxy: {
16 11 '/works': {
17   - // agent: new ProxyAgent('socks5://127.0.0.1:1086'),
18   - target: isProd ? PROD_API_ORIGIN : DEV_API_ORIGIN,
  12 + target,
  13 + changeOrigin: true,
  14 + ws: false
  15 + },
  16 + '/upload': {
  17 + target,
19 18 changeOrigin: true,
20 19 ws: false
21 20 }
... ...
front-end/h5/yarn.lock
... ... @@ -1974,6 +1974,11 @@ balanced-match@^1.0.0:
1974 1974 resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
1975 1975 integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
1976 1976  
  1977 +base64-arraybuffer@^0.2.0:
  1978 + version "0.2.0"
  1979 + resolved "https://registry.npm.taobao.org/base64-arraybuffer/download/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45"
  1980 + integrity sha1-S5RPrAGRqlkHr+LYyZnMxXzoD0U=
  1981 +
1977 1982 base64-js@^1.0.2:
1978 1983 version "1.3.0"
1979 1984 resolved "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
... ... @@ -3027,6 +3032,13 @@ css-declaration-sorter@^4.0.1:
3027 3032 postcss "^7.0.1"
3028 3033 timsort "^0.3.0"
3029 3034  
  3035 +css-line-break@1.1.1:
  3036 + version "1.1.1"
  3037 + resolved "https://registry.npm.taobao.org/css-line-break/download/css-line-break-1.1.1.tgz#d5e9bdd297840099eb0503c7310fd34927a026ef"
  3038 + integrity sha1-1em90peEAJnrBQPHMQ/TSSegJu8=
  3039 + dependencies:
  3040 + base64-arraybuffer "^0.2.0"
  3041 +
3030 3042 css-loader@^1.0.1:
3031 3043 version "1.0.1"
3032 3044 resolved "https://registry.npm.taobao.org/css-loader/download/css-loader-1.0.1.tgz#6885bb5233b35ec47b006057da01cc640b6b79fe"
... ... @@ -5286,6 +5298,13 @@ html-webpack-plugin@^3.2.0:
5286 5298 toposort "^1.0.0"
5287 5299 util.promisify "1.0.0"
5288 5300  
  5301 +html2canvas@^1.0.0-rc.3:
  5302 + version "1.0.0-rc.3"
  5303 + resolved "https://registry.npm.taobao.org/html2canvas/download/html2canvas-1.0.0-rc.3.tgz#1de88b073f6bcaa6954ca1edfb46da13b258b038"
  5304 + integrity sha1-HeiLBz9ryqaVTKHt+0baE7JYsDg=
  5305 + dependencies:
  5306 + css-line-break "1.1.1"
  5307 +
5289 5308 htmlparser2@^3.3.0:
5290 5309 version "3.10.1"
5291 5310 resolved "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
... ...