Commit 14571770fc947cdae489fefebcea11c578316adc

Authored by ly525
1 parent c532b500

refactor(ajax)

README.en.md
... ... @@ -36,17 +36,16 @@ English | [简体中文](./README.md)
36 36 - [ ] Photo Gallery
37 37 - [ ] Third Party uncopyrighted Image Search
38 38  
39   -4. Data Statistics
  39 +
  40 +4. back-end API
  41 + - [x] create work
  42 + - [x] save work
  43 + - [x] update work
40 44 - [ ] Form Statistics
  45 + - [x] Online Preview
  46 + - [x] QR Code Preview
41 47  
42   -5. Others
43   - - [ ] Online preview
44   - - [ ] QR Code Preview
45   -
46   -### Technology Stack (current)
47   - 1. Front end: Vue.js
48   - 2. Back End: Strapi
49   - 3. Storage: Sqlite
  48 +---
50 49  
51 50 ### Installs
52 51 > proj: project root path
... ... @@ -54,5 +53,14 @@ English | [简体中文](./README.md)
54 53 1. Front End
55 54 Editor: please refer to: [`project/front-end/h5/README.md`](https://github.com/ly525/luban-h5/blob/dev/front-end/h5/README.md)
56 55  
57   -### Front-End Component Explanation
58   -1. `lbp-`: `lu-ban-plugin-`, means `Luban H5 plugin`, location: `proj/front-end/h5/src/components/plugins`
59 56 \ No newline at end of file
  57 +
  58 +---
  59 +### More Explanation
  60 +#### Front-End Component Explanation
  61 +1. `lbp-`: `lu-ban-plugin-`, means `Luban H5 plugin`, location: `proj/front-end/h5/src/components/plugins`
  62 +
  63 +
  64 +#### Technology Stack (current)
  65 + 1. Front end: Vue.js
  66 + 2. Back End: Strapi
  67 + 3. Storage: Sqlite
60 68 \ No newline at end of file
... ...
README.md
... ... @@ -44,8 +44,8 @@
44 44 - [x] 创建、保存、更新作品
45 45 - [ ] 表单数据收集
46 46 - [ ] 表单数据展示
47   - - [ ] 在线预览
48   - - [ ] 二维码预览
  47 + - [x] 在线预览
  48 + - [x] 二维码预览
49 49  
50 50 ---
51 51  
... ...
back-end/h5-api/README.md
... ... @@ -13,3 +13,19 @@ strapi develop
13 13 # default database is sqlite3(h5-api/.tmp/data.db)
14 14 # visit http://locahost:1337/admin
15 15 ```
  16 +
  17 +
  18 +## Features(zh)
  19 + - [x] 创建、保存、更新作品
  20 + - [x] 在线预览
  21 + - [x] 二维码预览
  22 + - [ ] 表单数据收集
  23 + - [ ] 表单数据展示
  24 +
  25 +## Features(en)
  26 + - [x] create work
  27 + - [x] save work
  28 + - [x] update work
  29 + - [x] Online Preview
  30 + - [x] QR Code Preview
  31 + - [ ] Form Statistics
16 32 \ No newline at end of file
... ...
front-end/h5/src/components/core/editor/index.js
... ... @@ -43,6 +43,9 @@ export default {
43 43 editingElement: state => state.editingElement,
44 44 elements: state => state.editingPage.elements,
45 45 pages: state => state.work.pages
  46 + }),
  47 + ...mapState('loading', {
  48 + saveWork_loading: state => state.saveWork_loading
46 49 })
47 50 },
48 51 methods: {
... ... @@ -112,7 +115,7 @@ export default {
112 115 </a-button-group>
113 116 </a-menu-item>
114 117 <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small" onClick={() => { this.previewVisible = true }}>预览</a-button></a-menu-item>
115   - <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()}>保存</a-button></a-menu-item>
  118 + <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()} loading={this.saveWork_loading}>保存</a-button></a-menu-item>
116 119 <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item>
117 120 </a-menu>
118 121 </a-layout-header>
... ...
front-end/h5/src/constants/api.js
1   -export const API_HOST = 'https://radiant-depths-79548.herokuapp.com'
2   -export const API_PORT = ''
3   -export const API_ORIGIN = `${API_HOST}:${API_PORT}`
  1 +// export const API_HOST = 'https://radiant-depths-79548.herokuapp.com'
  2 +// export const API_PORT = ''
  3 +// export const API_ORIGIN = `${API_HOST}:${API_PORT}`
  4 +export const API_ORIGIN = 'http://localhost:1337'
... ...
front-end/h5/src/store/modules/loading.js
1 1 // initial state
2 2 const state = {
3   -
  3 + saveWork_loading: false
4 4 }
5 5  
6 6 // getters
... ... @@ -10,12 +10,16 @@ const getters = {
10 10  
11 11 // actions
12 12 const actions = {
13   -
  13 + update ({ commit }, payload) {
  14 + commit('update', payload)
  15 + }
14 16 }
15 17  
16 18 // mutations
17 19 const mutations = {
18   -
  20 + update (state, { type, payload }) {
  21 + state[type] = payload
  22 + }
19 23 }
20 24  
21 25 export default {
... ...
front-end/h5/src/store/modules/work.js
... ... @@ -2,6 +2,7 @@
2 2 import Element from '../../components/core/models/element'
3 3 import strapi from '../../utils/strapi'
4 4 import Page from '../../components/core/models/page'
  5 +import { AxiosWrapper } from '../../utils/http.js'
5 6  
6 7 export const actions = {
7 8 previewWork ({ commit }, payload = {}) {
... ... @@ -26,13 +27,19 @@ export const actions = {
26 27 }
27 28 commit('setWork', work)
28 29 },
29   - saveWork ({ commit, state }, payload = {}) {
  30 + saveWork ({ commit, dispatch, state }, payload = {}) {
30 31 // update work with strapi
31 32 const work = {
32 33 ...state.work,
33 34 ...payload
34 35 }
35   - strapi.updateEntry('works', state.work.id, work)
  36 +
  37 + new AxiosWrapper({
  38 + dispatch,
  39 + loading_name: 'saveWork_loading',
  40 + successMsg: '保存作品成功',
  41 + customRequest: strapi.updateEntry.bind(strapi)
  42 + }).put('works', state.work.id, work)
36 43 },
37 44 fetchWork ({ commit, state }, workId) {
38 45 strapi.getEntry('works', workId).then(entry => {
... ...
front-end/h5/src/utils/http.js 0 → 100644
  1 +import axios from 'axios'
  2 +import { message } from 'ant-design-vue'
  3 +
  4 +message.config({
  5 + maxCount: 3
  6 +})
  7 +
  8 +export const myMessage = message
  9 +
  10 +export const client = axios.create({
  11 + baseURL: '/v1',
  12 + responseType: 'json'
  13 +})
  14 +export const baseClient = axios.create({
  15 + responseType: 'json'
  16 +})
  17 +
  18 +export class AxiosWrapper {
  19 + // eslint-disable-next-line camelcase
  20 + constructor ({ name = 'default', loading_name, responseType = 'json', headers, dispatch, router, successMsg, failMsg, successCallback, failCallback, customRequest }) {
  21 + this.name = name
  22 + // eslint-disable-next-line camelcase
  23 + this.loading_name = loading_name
  24 + // eslint-disable-next-line camelcase
  25 + this.responseType = responseType
  26 + this.dispatch = dispatch
  27 + this.router = router
  28 + this.successMsg = successMsg
  29 + this.failMsg = failMsg
  30 + this.customRequest = customRequest
  31 + this.successCallback = successCallback
  32 + this.failCallback = failCallback
  33 + this.source = axios.CancelToken.source()
  34 + this.instance = axios.create({
  35 + // baseURL: '/v1',
  36 + responseType,
  37 + headers,
  38 + cancelToken: this.source.token
  39 + })
  40 + this.instance.interceptors.response.use(response => {
  41 + // Do something with response data
  42 + return Promise.resolve(response)
  43 + }, error => {
  44 + // Do something with response error
  45 + return Promise.reject(error)
  46 + })
  47 + }
  48 +
  49 + get (...args) {
  50 + this.setDefaultLoadingName(args)
  51 +
  52 + this.setLoadingValue(true)
  53 + return this.instance.get(...args).then(response => {
  54 + const handler = this.getCommonResponseHandler({ failMsg: 'Query Failed.' })
  55 + handler.call(this, response)
  56 + }).catch(error => {
  57 + // handle error
  58 + myMessage.error(error.message)
  59 + }).finally(() => this.setLoadingValue(false))
  60 + }
  61 +
  62 + post (...args) {
  63 + this.setDefaultLoadingName(args)
  64 +
  65 + this.setLoadingValue(true)
  66 + return this.instance.post(...args).then(response => {
  67 + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' })
  68 + handler.call(this, response)
  69 + }).catch(error => {
  70 + // handle error
  71 + myMessage.error(error.message)
  72 + }).finally(() => this.setLoadingValue(false))
  73 + }
  74 +
  75 + put (...args) {
  76 + this.setDefaultLoadingName(args)
  77 +
  78 + this.setLoadingValue(true)
  79 + if (this.customRequest) {
  80 + return this.customRequest(...args)
  81 + .then(data => {
  82 + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' })
  83 + handler.call(this, { data: { status: 200, data } })
  84 + })
  85 + .finally(() => this.setLoadingValue(false))
  86 + }
  87 + return this.instance.put(...args).then(response => {
  88 + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' })
  89 + // handler.call(this, response)
  90 + handler()
  91 + }).catch(error => {
  92 + // handle error
  93 + myMessage.error(error.message)
  94 + }).finally(() => this.setLoadingValue(false))
  95 + }
  96 +
  97 + delete (...args) {
  98 + this.setDefaultLoadingName(args)
  99 +
  100 + this.setLoadingValue(true)
  101 + return this.instance.delete(...args).then(response => {
  102 + const handler = this.getCommonResponseHandler({ failMsg: 'Save Failed.' })
  103 + handler.call(this, response)
  104 + }).catch(error => {
  105 + // handle error
  106 + myMessage.error(error.message)
  107 + }).finally(() => this.setLoadingValue(false))
  108 + }
  109 +
  110 + cancel (reason) {
  111 + this.source.cancel(reason)
  112 + }
  113 +
  114 + setLoadingValue (payload) {
  115 + this.dispatch('loading/update', { type: this.loading_name, payload }, { root: true })
  116 + }
  117 +
  118 + setDefaultLoadingName (...args) {
  119 + if (!this.loading_name) {
  120 + let url = args[0]
  121 + if (url.indexOf('/') !== -1) {
  122 + let us = url.split('/')
  123 + url = us[us.length - 1]
  124 + }
  125 + if (url.indexOf('?') !== -1) {
  126 + let us = url.split('?')
  127 + url = us[0]
  128 + }
  129 + this.loading_name = `${url}_loading`
  130 + }
  131 + }
  132 +
  133 + getCommonResponseHandler ({ failMsg } = {}) {
  134 + return (response) => {
  135 + if (!response.data) {
  136 + myMessage.warn(this.failMsg || failMsg)
  137 + } else if (response.data.status === 200) {
  138 + this.successMsg && myMessage.success(this.successMsg)
  139 + if (this.successCallback) {
  140 + this.successCallback(response)
  141 + } else {
  142 + // this.dispatch({ type: this.name, payload: response.data.data })
  143 + }
  144 + } else if (this.responseType === 'json') {
  145 + myMessage.error(response.data.msg)
  146 + if (response.data.status === 401) {
  147 + if (this.router) {
  148 + this.router.push('/login')
  149 + }
  150 + } else {
  151 + alert(response.data.msg)
  152 + if (this.failCallback) {
  153 + this.failCallback(response)
  154 + }
  155 + }
  156 + } else {
  157 + if (this.successCallback) {
  158 + this.successCallback(response)
  159 + }
  160 + }
  161 + }
  162 + }
  163 +}
... ...
front-end/h5/vue.config.js
1 1 const ProxyAgent = require('proxy-agent')
2 2 const isProd = process.env.NODE_ENV === 'production'
3 3  
4   -const API_ORIGIN = 'https://radiant-depths-79548.herokuapp.com'
5   -const publicPath = isProd ? '/luban-h5/' : '/'
6   -// const proxy = isProd ? API_ORIGIN : 'http://localhost:1337'
  4 +const PROD_API_ORIGIN = 'https://radiant-depths-79548.herokuapp.com'
  5 +const DEV_API_ORIGIN = 'http://localhost:1337'
7 6  
8 7 module.exports = {
9 8 runtimeCompiler: true,
10   - publicPath,
  9 + publicPath: isProd ? '/luban-h5/' : '/',
11 10 devServer: {
12 11 // proxy: API_ORIGIN
13 12 proxy: {
14 13 '/': {
15 14 agent: new ProxyAgent('socks5://127.0.0.1:1086'),
16   - target: API_ORIGIN,
  15 + target: isProd ? PROD_API_ORIGIN : DEV_API_ORIGIN,
17 16 changeOrigin: true
18 17 }
19 18 }
... ...