Преглед на файлове

Merge branch 'master' of http://git.ycjcjy.com/zhiyuxing/pc-admin

张延森 преди 5 години
родител
ревизия
c2e3bd468f
променени са 100 файла, в които са добавени 17467 реда и са изтрити 262 реда
  1. 5
    0
      package.json
  2. 77
    0
      src/components/wangeditor/index.vue
  3. 95
    1
      src/config/api.js
  4. 5
    0
      src/main.js
  5. 5
    0
      src/store/index.js
  6. 132
    0
      src/store/modules/exchange.js
  7. 132
    0
      src/store/modules/goods.js
  8. 137
    0
      src/store/modules/news.js
  9. 132
    0
      src/store/modules/points.js
  10. 228
    0
      src/views/carouselFigure/advertisement.vue
  11. 454
    0
      src/views/carouselFigure/advertisementEdit.vue
  12. 459
    0
      src/views/carouselFigure/edit.vue
  13. 232
    0
      src/views/carouselFigure/list.vue
  14. 98
    93
      src/views/consultant/edit.vue
  15. 102
    44
      src/views/consultant/list.vue
  16. 235
    0
      src/views/customer/editCustomer.vue
  17. 293
    0
      src/views/customer/editRecommend.vue
  18. 145
    0
      src/views/customer/integralRecord.vue
  19. 225
    121
      src/views/customer/list.vue
  20. 274
    0
      src/views/customer/recommendCustomer.vue
  21. 268
    0
      src/views/exchange/list.vue
  22. 257
    0
      src/views/goods/edit.vue
  23. 212
    0
      src/views/goods/list.vue
  24. 262
    3
      src/views/index.js
  25. 221
    0
      src/views/news/edi/index.vue
  26. 189
    0
      src/views/news/index.vue
  27. 154
    0
      src/views/news/type/edi/index.vue
  28. 141
    0
      src/views/news/type/index.vue
  29. 211
    0
      src/views/points/edit.vue
  30. 183
    0
      src/views/points/list.vue
  31. 671
    0
      src/views/project/edit.vue
  32. 280
    0
      src/views/project/list.vue
  33. 237
    0
      src/views/systemManagement/keyWords.vue
  34. 224
    0
      src/views/systemManagement/pushMessage.vue
  35. 92
    0
      static/tinymce/jquery.tinymce.min.js
  36. 3
    0
      static/tinymce/langs/readme.md
  37. 389
    0
      static/tinymce/langs/zh_CN.js
  38. 504
    0
      static/tinymce/license.txt
  39. 9
    0
      static/tinymce/plugins/advlist/plugin.min.js
  40. 9
    0
      static/tinymce/plugins/anchor/plugin.min.js
  41. 9
    0
      static/tinymce/plugins/autolink/plugin.min.js
  42. 9
    0
      static/tinymce/plugins/autoresize/plugin.min.js
  43. 9
    0
      static/tinymce/plugins/autosave/plugin.min.js
  44. 9
    0
      static/tinymce/plugins/bbcode/plugin.min.js
  45. 9
    0
      static/tinymce/plugins/charmap/plugin.min.js
  46. 9
    0
      static/tinymce/plugins/code/plugin.min.js
  47. 9
    0
      static/tinymce/plugins/codesample/plugin.min.js
  48. 9
    0
      static/tinymce/plugins/colorpicker/plugin.min.js
  49. 9
    0
      static/tinymce/plugins/contextmenu/plugin.min.js
  50. 9
    0
      static/tinymce/plugins/directionality/plugin.min.js
  51. 9015
    0
      static/tinymce/plugins/emoticons/js/emojis.js
  52. 2
    0
      static/tinymce/plugins/emoticons/js/emojis.min.js
  53. 9
    0
      static/tinymce/plugins/emoticons/plugin.min.js
  54. 9
    0
      static/tinymce/plugins/fullpage/plugin.min.js
  55. 9
    0
      static/tinymce/plugins/fullscreen/plugin.min.js
  56. 9
    0
      static/tinymce/plugins/help/plugin.min.js
  57. 9
    0
      static/tinymce/plugins/hr/plugin.min.js
  58. 9
    0
      static/tinymce/plugins/image/plugin.min.js
  59. 9
    0
      static/tinymce/plugins/imagetools/plugin.min.js
  60. 9
    0
      static/tinymce/plugins/importcss/plugin.min.js
  61. 9
    0
      static/tinymce/plugins/insertdatetime/plugin.min.js
  62. 9
    0
      static/tinymce/plugins/legacyoutput/plugin.min.js
  63. 9
    0
      static/tinymce/plugins/link/plugin.min.js
  64. 9
    0
      static/tinymce/plugins/lists/plugin.min.js
  65. 9
    0
      static/tinymce/plugins/media/plugin.min.js
  66. 9
    0
      static/tinymce/plugins/nonbreaking/plugin.min.js
  67. 9
    0
      static/tinymce/plugins/noneditable/plugin.min.js
  68. 9
    0
      static/tinymce/plugins/pagebreak/plugin.min.js
  69. 9
    0
      static/tinymce/plugins/paste/plugin.min.js
  70. 9
    0
      static/tinymce/plugins/preview/plugin.min.js
  71. 9
    0
      static/tinymce/plugins/print/plugin.min.js
  72. 9
    0
      static/tinymce/plugins/quickbars/plugin.min.js
  73. 9
    0
      static/tinymce/plugins/save/plugin.min.js
  74. 9
    0
      static/tinymce/plugins/searchreplace/plugin.min.js
  75. 9
    0
      static/tinymce/plugins/spellchecker/plugin.min.js
  76. 9
    0
      static/tinymce/plugins/tabfocus/plugin.min.js
  77. 9
    0
      static/tinymce/plugins/table/plugin.min.js
  78. 9
    0
      static/tinymce/plugins/template/plugin.min.js
  79. 9
    0
      static/tinymce/plugins/textcolor/plugin.min.js
  80. 9
    0
      static/tinymce/plugins/textpattern/plugin.min.js
  81. 9
    0
      static/tinymce/plugins/toc/plugin.min.js
  82. 9
    0
      static/tinymce/plugins/visualblocks/plugin.min.js
  83. 9
    0
      static/tinymce/plugins/visualchars/plugin.min.js
  84. 9
    0
      static/tinymce/plugins/wordcount/plugin.min.js
  85. 7
    0
      static/tinymce/skins/content/default/content.min.css
  86. 7
    0
      static/tinymce/skins/content/document/content.min.css
  87. 7
    0
      static/tinymce/skins/content/writer/content.min.css
  88. 7
    0
      static/tinymce/skins/ui/oxide-dark/content.inline.min.css
  89. 7
    0
      static/tinymce/skins/ui/oxide-dark/content.min.css
  90. 7
    0
      static/tinymce/skins/ui/oxide-dark/content.mobile.min.css
  91. BIN
      static/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff
  92. 7
    0
      static/tinymce/skins/ui/oxide-dark/skin.min.css
  93. 7
    0
      static/tinymce/skins/ui/oxide-dark/skin.mobile.min.css
  94. 7
    0
      static/tinymce/skins/ui/oxide/content.inline.min.css
  95. 7
    0
      static/tinymce/skins/ui/oxide/content.min.css
  96. 7
    0
      static/tinymce/skins/ui/oxide/content.mobile.min.css
  97. BIN
      static/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff
  98. 7
    0
      static/tinymce/skins/ui/oxide/skin.min.css
  99. 7
    0
      static/tinymce/skins/ui/oxide/skin.mobile.min.css
  100. 0
    0
      static/tinymce/themes/mobile/theme.min.js

+ 5
- 0
package.json Целия файл

@@ -8,6 +8,10 @@
8 8
     "lint": "vue-cli-service lint"
9 9
   },
10 10
   "dependencies": {
11
+    "@ckeditor/ckeditor5-build-classic": "^12.3.1",
12
+    "@ckeditor/ckeditor5-build-decoupled-document": "^12.3.1",
13
+    "@ckeditor/ckeditor5-vue": "^1.0.0-beta.2",
14
+    "@tinymce/tinymce-vue": "^2.1.0",
11 15
     "axios": "^0.18.0",
12 16
     "blueimp-md5": "^2.10.0",
13 17
     "dayjs": "^1.8.12",
@@ -15,6 +19,7 @@
15 19
     "element-ui": "^2.6.1",
16 20
     "normalize.css": "^8.0.1",
17 21
     "nprogress": "^0.2.0",
22
+    "tinymce": "^5.0.12",
18 23
     "vue": "^2.6.6",
19 24
     "vue-amap": "^0.5.9",
20 25
     "vue-echarts": "^4.0.1",

+ 77
- 0
src/components/wangeditor/index.vue Целия файл

@@ -0,0 +1,77 @@
1
+<template>
2
+    <div id="websiteEditorElem" style="height: 400px"></div>
3
+</template>
4
+
5
+<script>
6
+    import E from 'wangeditor'
7
+    export default {
8
+        name: "index",
9
+        props:[
10
+          'content'
11
+        ],
12
+        watch: {
13
+            text(newVal, oldVal) {
14
+                console.log(newVal, oldVal)
15
+                //this.phoneEditor.txt.html(this.text)
16
+                if (!newVal && oldVal) {
17
+                    this.text = newVal
18
+                    this.intiPhoneEditor()
19
+                }
20
+                this.sendContent()
21
+            }
22
+        },
23
+        data() {
24
+          return {
25
+              text: this.content,
26
+              phoneEditor: ''
27
+          }
28
+        },
29
+        mounted() {
30
+            this.$nextTick(() => {
31
+                this.intiPhoneEditor()
32
+            })
33
+        },
34
+        methods: {
35
+            sendContent() {
36
+                this.$emit('get-content', this.text)
37
+            },
38
+            intiPhoneEditor() {
39
+                console.log('初始化值:', this.text)
40
+                const _that = this
41
+                _that.phoneEditor = new E('#websiteEditorElem')
42
+                const phoneEditor = _that.phoneEditor
43
+                phoneEditor.customConfig.zIndex = 1
44
+                phoneEditor.customConfig.onchange = function (html) {
45
+                    _that.text = html
46
+                }
47
+                // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
48
+                // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
49
+
50
+                // phoneEditor.customConfig.customUploadImg = function (files, insert) {
51
+                //     _that.uploadImg(files[0]).then(data => {
52
+                //         insert(data)
53
+                //     })
54
+                // }
55
+                phoneEditor.customConfig.menus = [
56
+                    'head',  // 标题
57
+                    'bold',  // 粗体
58
+                    'fontSize',  // 字号
59
+                    'fontName',  // 字体
60
+                    'italic',  // 斜体
61
+                    'underline',  // 下划线
62
+                    'strikeThrough',  // 删除线
63
+                    'foreColor',  // 文字颜色
64
+                    'backColor',  // 背景颜色
65
+                    'justify',  // 对齐方式
66
+                    'image',  // 插入图片
67
+                ]
68
+                phoneEditor.create()
69
+                phoneEditor.txt.html(this.text)
70
+            },
71
+        }
72
+    }
73
+</script>
74
+
75
+<style scoped>
76
+
77
+</style>

+ 95
- 1
src/config/api.js Целия файл

@@ -126,7 +126,101 @@ const apis = {
126 126
       method: 'post',
127 127
       url: `${commPrefix}/customer/add`
128 128
     }
129
-  }
129
+  },
130
+  goods:{
131
+    list:{
132
+      method:'get',
133
+      url: `${commPrefix}/taGoods`
134
+    },
135
+    detail: {
136
+      method: 'get',
137
+      url: `${commPrefix}/taGoods/:id`
138
+    },
139
+    add: {
140
+      method: 'post',
141
+      url: `${commPrefix}/taGoods/add`
142
+    },
143
+    edit: {
144
+      method: 'put',
145
+      url: `${commPrefix}/taGoods`
146
+    },
147
+    change: {
148
+      method: 'put',
149
+      url: `${commPrefix}/taGoods/change`
150
+    }
151
+  },
152
+  newsType: {
153
+    list: {
154
+      method: 'get',
155
+      url: `${commPrefix}/taNewsType`
156
+    },
157
+    add: {
158
+      method: 'post',
159
+      url: `${commPrefix}/taNewsType`
160
+    },
161
+    delete: {
162
+      method: 'delete',
163
+      url: `${commPrefix}/taNewsType/:id`
164
+    },
165
+    update: {
166
+      method: 'put',
167
+      url: `${commPrefix}/taNewsType/:id`
168
+    },
169
+    getById: {
170
+      method: 'get',
171
+      url: `${commPrefix}/taNewsType/:id`
172
+    }
173
+  },
174
+  points:{
175
+    list:{
176
+      method:'get',
177
+      url: `${commPrefix}/tdPointsRules`
178
+    },
179
+    detail: {
180
+      method: 'get',
181
+      url: `${commPrefix}/tdPointsRules/:id`
182
+    },
183
+    add: {
184
+      method: 'post',
185
+      url: `${commPrefix}/taGoods/add`
186
+    },
187
+    edit: {
188
+      method: 'put',
189
+      url: `${commPrefix}/tdPointsRules`
190
+    },
191
+    change: {
192
+      method: 'put',
193
+      url: `${commPrefix}/tdPointsRules/change`
194
+    }
195
+  },
196
+  news: {
197
+    list: {
198
+      method: 'get',
199
+      url: `${commPrefix}/taNews`
200
+    },
201
+    add: {
202
+      method: 'post',
203
+      url: `${commPrefix}/taNews`
204
+    },
205
+    delete: {
206
+      method: 'delete',
207
+      url: `${commPrefix}/taNews/:id`
208
+    },
209
+    update: {
210
+      method: 'put',
211
+      url: `${commPrefix}/taNews/:id`
212
+    },
213
+    getById: {
214
+      method: 'get',
215
+      url: `${commPrefix}/taNews/:id`
216
+    }
217
+  },
218
+  exchange:{
219
+    list:{
220
+      method:'get',
221
+      url: `${commPrefix}/taPointsExchange`
222
+    }
223
+  },
130 224
 }
131 225
 
132 226
 export default apis

+ 5
- 0
src/main.js Целия файл

@@ -12,6 +12,11 @@ import './theme.scss'
12 12
 import './assets/iconfont.css'
13 13
 import VueAMap from 'vue-amap'
14 14
 
15
+
16
+// import tinymce from 'tinymce/tinymce'
17
+// import Editor from '@tinymce/tinymce-vue'
18
+// import 'tinymce/themes/modern/theme'
19
+
15 20
 Vue.use(Element)
16 21
 
17 22
 Vue.config.productionTip = false

+ 5
- 0
src/store/index.js Целия файл

@@ -2,6 +2,7 @@ import Vue from 'vue'
2 2
 import Vuex from 'vuex'
3 3
 import system from './system'
4 4
 import apartment from './modules/apartment'
5
+import news from './modules/news'
5 6
 Vue.use(Vuex)
6 7
 
7 8
 const store = new Vuex.Store({
@@ -13,6 +14,10 @@ const store = new Vuex.Store({
13 14
     customer: require('./modules/customer').default,
14 15
     building: require('./modules/building').default,
15 16
     img: require('./modules/img').default,
17
+    goods: require('./modules/goods').default,
18
+    points: require('./modules/points').default,
19
+    exchange: require('./modules/exchange').default,
20
+    news
16 21
   }
17 22
 })
18 23
 

+ 132
- 0
src/store/modules/exchange.js Целия файл

@@ -0,0 +1,132 @@
1
+import request from '../../utils/request'
2
+import apis from '../../config/api'
3
+
4
+export default {
5
+  namespaced: true,
6
+  state: {
7
+    dynamics: {},
8
+    detail: {}
9
+  },
10
+  mutations: {
11
+    updateList (state, payload) {
12
+      state.dynamics = payload
13
+    },
14
+    updateDetail (state, payload) {
15
+      state.detail = payload
16
+    }
17
+  },
18
+  actions: {
19
+    setDetailNull ({ commit }) {
20
+      commit('updateDetail', {})
21
+    },
22
+    getExchanges ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.exchange.list,
26
+          params: payload,
27
+        }).then((data) => {
28
+          commit('updateList', data)
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+
33
+          if (typeof message === 'string') {
34
+            reject(message)
35
+          }
36
+        })
37
+      })
38
+    },
39
+    getGoodsDetail ({ commit }, payload) {
40
+      return new Promise((resolve, reject) => {
41
+        request({
42
+          ...apis.goods.detail,
43
+          urlData: payload,
44
+        }).then((data) => {
45
+          commit('updateDetail', data)
46
+          resolve(data)
47
+        }).catch((err) => {
48
+          const message = err.message || err.msg
49
+
50
+          if (typeof message === 'string') {
51
+            reject(message)
52
+          }
53
+        })
54
+      })
55
+    },
56
+    addGoods (_, payload) {
57
+      return new Promise((resolve, reject) => {
58
+        request({
59
+          ...apis.goods.add, 
60
+          data: payload,
61
+        }).then((data) => {
62
+          resolve(data)
63
+        }).catch((err) => {
64
+          const message = err.message || err.msg
65
+          if (typeof message === 'string') {
66
+            reject(message)
67
+          }
68
+        })
69
+      })
70
+    },
71
+    editGoods (_, payload) {
72
+      return new Promise((resolve, reject) => {
73
+        request({
74
+          ...apis.goods.edit,
75
+          data: payload,
76
+        }).then((data) => {
77
+          resolve(data)
78
+        }).catch((err) => {
79
+          const message = err.message || err.msg
80
+
81
+          if (typeof message === 'string') {
82
+            reject(message)
83
+          }
84
+        })
85
+      })
86
+    },
87
+    deleteDynamics (_, payload) {
88
+      return new Promise((resolve, reject) => {
89
+        request({
90
+          ...apis.dynamic.delete,
91
+          ...payload
92
+        }).then(() => {
93
+          resolve()
94
+        }).catch(() => {
95
+          reject()
96
+        })
97
+      })
98
+    },
99
+    changeGoodsStatus (_, payload) {
100
+      return new Promise((resolve, reject) => {
101
+        request({
102
+          ...apis.goods.change,
103
+          data: payload,
104
+        }).then((data) => {
105
+          resolve(data)
106
+        }).catch((err) => {
107
+          const message = err.message || err.msg
108
+
109
+          if (typeof message === 'string') {
110
+            reject(message)
111
+          }
112
+        })
113
+      })
114
+    },
115
+    cancelDynamic (_, payload) {
116
+      return new Promise((resolve, reject) => {
117
+        request({
118
+          ...apis.dynamic.cancel,
119
+          urlData: payload,
120
+        }).then((data) => {
121
+          resolve(data)
122
+        }).catch((err) => {
123
+          const message = err.message || err.msg
124
+
125
+          if (typeof message === 'string') {
126
+            reject(message)
127
+          }
128
+        })
129
+      })
130
+    }
131
+  }
132
+}

+ 132
- 0
src/store/modules/goods.js Целия файл

@@ -0,0 +1,132 @@
1
+import request from '../../utils/request'
2
+import apis from '../../config/api'
3
+
4
+export default {
5
+  namespaced: true,
6
+  state: {
7
+    dynamics: {},
8
+    detail: {}
9
+  },
10
+  mutations: {
11
+    updateList (state, payload) {
12
+      state.dynamics = payload
13
+    },
14
+    updateDetail (state, payload) {
15
+      state.detail = payload
16
+    }
17
+  },
18
+  actions: {
19
+    setDetailNull ({ commit }) {
20
+      commit('updateDetail', {})
21
+    },
22
+    getGoods ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.goods.list,
26
+          params: payload,
27
+        }).then((data) => {
28
+          commit('updateList', data)
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+
33
+          if (typeof message === 'string') {
34
+            reject(message)
35
+          }
36
+        })
37
+      })
38
+    },
39
+    getGoodsDetail ({ commit }, payload) {
40
+      return new Promise((resolve, reject) => {
41
+        request({
42
+          ...apis.goods.detail,
43
+          urlData: payload,
44
+        }).then((data) => {
45
+          commit('updateDetail', data)
46
+          resolve(data)
47
+        }).catch((err) => {
48
+          const message = err.message || err.msg
49
+
50
+          if (typeof message === 'string') {
51
+            reject(message)
52
+          }
53
+        })
54
+      })
55
+    },
56
+    addGoods (_, payload) {
57
+      return new Promise((resolve, reject) => {
58
+        request({
59
+          ...apis.goods.add, 
60
+          data: payload,
61
+        }).then((data) => {
62
+          resolve(data)
63
+        }).catch((err) => {
64
+          const message = err.message || err.msg
65
+          if (typeof message === 'string') {
66
+            reject(message)
67
+          }
68
+        })
69
+      })
70
+    },
71
+    editGoods (_, payload) {
72
+      return new Promise((resolve, reject) => {
73
+        request({
74
+          ...apis.goods.edit,
75
+          data: payload,
76
+        }).then((data) => {
77
+          resolve(data)
78
+        }).catch((err) => {
79
+          const message = err.message || err.msg
80
+
81
+          if (typeof message === 'string') {
82
+            reject(message)
83
+          }
84
+        })
85
+      })
86
+    },
87
+    deleteDynamics (_, payload) {
88
+      return new Promise((resolve, reject) => {
89
+        request({
90
+          ...apis.dynamic.delete,
91
+          ...payload
92
+        }).then(() => {
93
+          resolve()
94
+        }).catch(() => {
95
+          reject()
96
+        })
97
+      })
98
+    },
99
+    changeGoodsStatus (_, payload) {
100
+      return new Promise((resolve, reject) => {
101
+        request({
102
+          ...apis.goods.change,
103
+          data: payload,
104
+        }).then((data) => {
105
+          resolve(data)
106
+        }).catch((err) => {
107
+          const message = err.message || err.msg
108
+
109
+          if (typeof message === 'string') {
110
+            reject(message)
111
+          }
112
+        })
113
+      })
114
+    },
115
+    cancelDynamic (_, payload) {
116
+      return new Promise((resolve, reject) => {
117
+        request({
118
+          ...apis.dynamic.cancel,
119
+          urlData: payload,
120
+        }).then((data) => {
121
+          resolve(data)
122
+        }).catch((err) => {
123
+          const message = err.message || err.msg
124
+
125
+          if (typeof message === 'string') {
126
+            reject(message)
127
+          }
128
+        })
129
+      })
130
+    }
131
+  }
132
+}

+ 137
- 0
src/store/modules/news.js Целия файл

@@ -0,0 +1,137 @@
1
+import apis from '../../config/api'
2
+import request from '../../utils/request'
3
+
4
+export default {
5
+    namespaced: true,
6
+    state: {
7
+        list: [],
8
+        detail: []
9
+    },
10
+    mutations: {
11
+
12
+    },
13
+    actions: {
14
+        getTypeList({ commit }, payload) { // 查询所有资迅类型
15
+           return  new Promise((resolve, reject) => {
16
+               request({
17
+                   ...apis.newsType.list,
18
+                   params: payload,
19
+               }).then((data) => {
20
+                   resolve(data)
21
+               }).catch((err) => {
22
+                   reject(err)
23
+               })
24
+           })
25
+        },
26
+        getTypeById({ commit }, payload) { // 根据Id查询资迅类型
27
+            return  new Promise((resolve, reject) => {
28
+                request({
29
+                    ...apis.newsType.getById,
30
+                    urlData: { id: payload.newsTypeId },
31
+                }).then((data) => {
32
+                    resolve(data)
33
+                }).catch((err) => {
34
+                    reject(err)
35
+                })
36
+            })
37
+        },
38
+        addType({ commit }, payload) { // 添加类型
39
+            return  new Promise((resolve, reject) => {
40
+                request({
41
+                    ...apis.newsType.add,
42
+                    data: payload,
43
+                }).then((data) => {
44
+                    resolve(data)
45
+                }).catch((err) => {
46
+                    reject(err)
47
+                })
48
+            })
49
+        },
50
+        updateType({ commit }, payload) { // 修改类型
51
+            return  new Promise((resolve, reject) => {
52
+                request({
53
+                    ...apis.newsType.update,
54
+                    urlData:{ id: payload.newsTypeId },
55
+                    data:payload
56
+                }).then((data) => {
57
+                    resolve(data)
58
+                }).catch((err) => {
59
+                    reject(err)
60
+                })
61
+            })
62
+        },
63
+        deleteType({ commit }, payload) { // 删除类型
64
+            return  new Promise((resolve, reject) => {
65
+                request({
66
+                    ...apis.newsType.delete,
67
+                    urlData: { id: payload.newsTypeId },
68
+                }).then((data) => {
69
+                    resolve(data)
70
+                }).catch((err) => {
71
+                    reject(err)
72
+                })
73
+            })
74
+        },
75
+        getList({ commit }, payload) { // 查询所有资迅
76
+            return  new Promise((resolve, reject) => {
77
+                request({
78
+                    ...apis.news.list,
79
+                    params: payload,
80
+                }).then((data) => {
81
+                    resolve(data)
82
+                }).catch((err) => {
83
+                    reject(err)
84
+                })
85
+            })
86
+        },
87
+        getById({ commit }, payload) { // 根据Id查询资迅
88
+            return  new Promise((resolve, reject) => {
89
+                request({
90
+                    ...apis.news.getById,
91
+                    urlData: { id: payload.newsId },
92
+                }).then((data) => {
93
+                    resolve(data)
94
+                }).catch((err) => {
95
+                    reject(err)
96
+                })
97
+            })
98
+        },
99
+        add({ commit }, payload) { // 添加
100
+            return  new Promise((resolve, reject) => {
101
+                request({
102
+                    ...apis.news.add,
103
+                    data: payload,
104
+                }).then((data) => {
105
+                    resolve(data)
106
+                }).catch((err) => {
107
+                    reject(err)
108
+                })
109
+            })
110
+        },
111
+        update({ commit }, payload) { // 修改
112
+            return  new Promise((resolve, reject) => {
113
+                request({
114
+                    ...apis.news.update,
115
+                    urlData:{ id: payload.newsId },
116
+                    data:payload
117
+                }).then((data) => {
118
+                    resolve(data)
119
+                }).catch((err) => {
120
+                    reject(err)
121
+                })
122
+            })
123
+        },
124
+        delete({ commit }, payload) { // 删除
125
+            return  new Promise((resolve, reject) => {
126
+                request({
127
+                    ...apis.news.delete,
128
+                    urlData: { id: payload.newsId },
129
+                }).then((data) => {
130
+                    resolve(data)
131
+                }).catch((err) => {
132
+                    reject(err)
133
+                })
134
+            })
135
+        }
136
+    }
137
+}

+ 132
- 0
src/store/modules/points.js Целия файл

@@ -0,0 +1,132 @@
1
+import request from '../../utils/request'
2
+import apis from '../../config/api'
3
+
4
+export default {
5
+  namespaced: true,
6
+  state: {
7
+    dynamics: {},
8
+    detail: {}
9
+  },
10
+  mutations: {
11
+    updateList (state, payload) {
12
+      state.dynamics = payload
13
+    },
14
+    updateDetail (state, payload) {
15
+      state.detail = payload
16
+    }
17
+  },
18
+  actions: {
19
+    setDetailNull ({ commit }) {
20
+      commit('updateDetail', {})
21
+    },
22
+    getPointsRules ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.points.list,
26
+          params: payload,
27
+        }).then((data) => {
28
+          commit('updateList', data)
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+
33
+          if (typeof message === 'string') {
34
+            reject(message)
35
+          }
36
+        })
37
+      })
38
+    },
39
+    getPointsDetail ({ commit }, payload) {
40
+      return new Promise((resolve, reject) => {
41
+        request({
42
+          ...apis.points.detail,
43
+          urlData: payload,
44
+        }).then((data) => {
45
+          commit('updateDetail', data)
46
+          resolve(data)
47
+        }).catch((err) => {
48
+          const message = err.message || err.msg
49
+
50
+          if (typeof message === 'string') {
51
+            reject(message)
52
+          }
53
+        })
54
+      })
55
+    },
56
+    addGoods (_, payload) {
57
+      return new Promise((resolve, reject) => {
58
+        request({
59
+          ...apis.goods.add, 
60
+          data: payload,
61
+        }).then((data) => {
62
+          resolve(data)
63
+        }).catch((err) => {
64
+          const message = err.message || err.msg
65
+          if (typeof message === 'string') {
66
+            reject(message)
67
+          }
68
+        })
69
+      })
70
+    },
71
+    editPoints (_, payload) {
72
+      return new Promise((resolve, reject) => {
73
+        request({
74
+          ...apis.points.edit,
75
+          data: payload,
76
+        }).then((data) => {
77
+          resolve(data)
78
+        }).catch((err) => {
79
+          const message = err.message || err.msg
80
+
81
+          if (typeof message === 'string') {
82
+            reject(message)
83
+          }
84
+        })
85
+      })
86
+    },
87
+    deleteDynamics (_, payload) {
88
+      return new Promise((resolve, reject) => {
89
+        request({
90
+          ...apis.dynamic.delete,
91
+          ...payload
92
+        }).then(() => {
93
+          resolve()
94
+        }).catch(() => {
95
+          reject()
96
+        })
97
+      })
98
+    },
99
+    changePointsRulesStatus (_, payload) {
100
+      return new Promise((resolve, reject) => {
101
+        request({
102
+          ...apis.points.change,
103
+          data: payload,
104
+        }).then((data) => {
105
+          resolve(data)
106
+        }).catch((err) => {
107
+          const message = err.message || err.msg
108
+
109
+          if (typeof message === 'string') {
110
+            reject(message)
111
+          }
112
+        })
113
+      })
114
+    },
115
+    cancelDynamic (_, payload) {
116
+      return new Promise((resolve, reject) => {
117
+        request({
118
+          ...apis.dynamic.cancel,
119
+          urlData: payload,
120
+        }).then((data) => {
121
+          resolve(data)
122
+        }).catch((err) => {
123
+          const message = err.message || err.msg
124
+
125
+          if (typeof message === 'string') {
126
+            reject(message)
127
+          }
128
+        })
129
+      })
130
+    }
131
+  }
132
+}

+ 228
- 0
src/views/carouselFigure/advertisement.vue Целия файл

@@ -0,0 +1,228 @@
1
+<template>
2
+  <div>
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增</el-button>
7
+        </div>
8
+      </div>
9
+      <div class="moreFilter"></div>
10
+    </div>
11
+    <el-table
12
+      :data="dynamics.list || []"
13
+      >
14
+      <el-table-column
15
+        type="index">
16
+        <template slot-scope="scope">
17
+          <span>{{ GetIndex(scope.$index) }}</span>
18
+        </template>
19
+      </el-table-column>
20
+      <el-table-column
21
+        label="主图">
22
+        <template slot-scope="scope">
23
+          <div class="header">
24
+            <img :src="scope.row.imgUrl" alt="" />
25
+          </div>
26
+        </template>
27
+      </el-table-column>
28
+      <el-table-column
29
+        prop="title"
30
+        label="类型">
31
+      </el-table-column>
32
+      <el-table-column
33
+        prop="createDate"
34
+        label="发布时间">
35
+      </el-table-column>
36
+      <el-table-column
37
+        label="状态"
38
+        >
39
+        <template slot-scope="scope">
40
+          <span>{{scope.row.status == 1 ? '启用' : '停用'}}</span>
41
+        </template>
42
+      </el-table-column>
43
+      <el-table-column
44
+        fixed="right"
45
+        label="操作"
46
+        width="180">
47
+        <template slot-scope="scope">
48
+          <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status === 0" size="small">编辑</el-button>
49
+          <el-button type="text" @click="handlePulic(scope.row)" size="small" v-if="scope.row.status === 0">启用</el-button>
50
+          <el-button type="text" @click="handleUnPulic(scope.row)" size="small" v-if="scope.row.status === 1">禁用</el-button>
51
+
52
+        </template>
53
+      </el-table-column>
54
+    </el-table>
55
+    <el-pagination
56
+      small
57
+      style="margin-top:10px;"
58
+      layout="prev, pager, next"
59
+      :current-page.sync="currentPage"
60
+      :pageSize="pageSize"
61
+      :total="dynamics.total || 0"
62
+      @current-change="getList"
63
+    >
64
+    </el-pagination>
65
+  </div>
66
+</template>
67
+
68
+<script>
69
+import { createNamespacedHelpers } from 'vuex';
70
+
71
+const {mapState: mapDynamicState, mapActions: mapDynamicActions} = createNamespacedHelpers('dynamic')
72
+const {mapState: mapBuildingState, mapActions: mapBuildingActions} = createNamespacedHelpers('building')
73
+
74
+export default {
75
+  data() {
76
+    return {
77
+      pageSize: 20,
78
+      currentPage: 1,
79
+      name: '',
80
+      buildingId: '',
81
+    }
82
+  },
83
+  computed: {
84
+    ...mapDynamicState({
85
+      dynamics: x => x.dynamics
86
+    }),
87
+    ...mapBuildingState({
88
+      buildings: x => x.buildings
89
+    })
90
+  },
91
+  methods: {
92
+    ...mapDynamicActions([
93
+      'getDynamics',
94
+      'setDetailNull',
95
+      'deleteDynamics',
96
+      'publicDynamic',
97
+      'cancelDynamic'
98
+    ]),
99
+    ...mapBuildingActions([
100
+      'getBuildings',
101
+    ]),
102
+    GetIndex (inx) {
103
+      return (this.currentPage - 1) * this.pageSize + inx + 1
104
+    },
105
+    FormatDate (date) {
106
+      if (date) {
107
+        return dayjs(date).formate('yyyy-MM-DD HH:mm:ss')
108
+      } else {
109
+        return ''
110
+      }
111
+    },
112
+    getList () {
113
+      this.getDynamics({
114
+        pageNum: this.currentPage,
115
+        pageSize: this.pageSize,
116
+        name: this.name,
117
+        buildingId: this.buildingId
118
+      })
119
+    },
120
+    getBuildingName (id) {
121
+      return ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {}).buildingName || ''
122
+    },
123
+    search () {
124
+      this.currentPage = 1
125
+      this.getList()
126
+    },
127
+    handleEdit (row) {
128
+      this.setDetailNull()
129
+      this.$router.push({name: 'advertisementEdit', query: {id: row.dynamicId}})
130
+    },
131
+    handlePulic (row) {
132
+      this.$confirm('确认发布此数据?', '提示', {
133
+        confirmButtonText: '确定',
134
+        cancelButtonText: '取消',
135
+        type: 'warning'
136
+      }).then(() => {
137
+        this.publicDynamic({
138
+          id: row.dynamicId
139
+        }).then(() => {
140
+          this.getList()
141
+        })
142
+      })
143
+    },
144
+    handleUnPulic (row) {
145
+      this.$confirm('确认取消发布此数据?', '提示', {
146
+        confirmButtonText: '确定',
147
+        cancelButtonText: '取消',
148
+        type: 'warning'
149
+      }).then(() => {
150
+        this.cancelDynamic({
151
+          id: row.dynamicId}).then(() => {
152
+          this.getList()
153
+        })
154
+      })
155
+    },
156
+    handleDel (row) {
157
+      this.$confirm('确认删除此数据?', '提示', {
158
+        confirmButtonText: '确定',
159
+        cancelButtonText: '取消',
160
+        type: 'warning'
161
+      }).then(() => {
162
+        if (row.status === 1) {
163
+          this.$message.error('当前活动处于发布状态,不允许删除!')
164
+          return false
165
+        }
166
+        this.deleteDynamics({
167
+          id: row.dynamicId
168
+        }).then(() => {
169
+          this.getList()
170
+        })
171
+      })
172
+    },
173
+    addDynamic () {
174
+      this.setDetailNull()
175
+      this.$router.push({name: 'advertisementEdit'})
176
+    }
177
+  },
178
+  created () {
179
+    this.getBuildings({
180
+      pageNum: 1,
181
+      pageSize: 100,
182
+    }).then(() => {
183
+      this.getList()
184
+    })
185
+  }
186
+}
187
+</script>
188
+
189
+<style lang="scss" scoped>
190
+.header{
191
+  width: 50px;
192
+  height: 50px;
193
+  img{
194
+    width: 100%;
195
+    height: 100%;
196
+  }
197
+}
198
+
199
+.system-table-search{
200
+  width: calc(100% - 40px);
201
+  margin: 20px auto 0;
202
+}
203
+
204
+.system-table-search li{
205
+  margin-right: 20px;
206
+}
207
+
208
+.system-table-search ul{
209
+  font-size: 0;
210
+  white-space: nowrap;
211
+}
212
+
213
+.system-table-search ul>li{
214
+  display: inline-block;
215
+}
216
+
217
+.flex-h {
218
+  display: flex;
219
+  display: -webkit-flex;
220
+}
221
+
222
+.flex-item {
223
+  flex: 1;
224
+  -webkit-flex: 1;
225
+  position: relative;
226
+  overflow: hidden;
227
+}
228
+</style>

+ 454
- 0
src/views/carouselFigure/advertisementEdit.vue Целия файл

@@ -0,0 +1,454 @@
1
+<template>
2
+    <div class="edit-carousel">
3
+      <el-form ref="form" :model="building" label-width="180px">
4
+        <el-form-item label="所属项目:">
5
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
6
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
7
+          </el-select>
8
+        </el-form-item>
9
+        <el-form-item label="主图:">
10
+          <el-upload
11
+            :action="upFileUrl"
12
+            name='file'
13
+            list-type="picture-card"
14
+            :headers="uploadHeaders"
15
+            :file-list="imgList"
16
+            :show-file-list="true"
17
+            :before-upload="beforeImgUpload"
18
+            :on-success="handleAvatarSuccess"
19
+            :on-remove="handleRemove">
20
+            <i class="el-icon-plus"></i>
21
+          </el-upload>
22
+          <el-dialog :visible.sync="dialogVisible">
23
+            <img width="100%" :src="dialogImageUrl" alt="">
24
+          </el-dialog>
25
+        </el-form-item>
26
+        <el-form-item label="标题:">
27
+          <el-input v-model="building.tel"></el-input>
28
+        </el-form-item>
29
+        <el-form-item label="类型:">
30
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
31
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
32
+          </el-select>
33
+        </el-form-item>
34
+        <el-form-item label="发布内容:">
35
+          <div id="websiteEditorElem" style="height: 400px"></div>
36
+        </el-form-item>
37
+        <el-form-item label="发布内容:" class="publish">
38
+          <p>活动名称展示处<span class="choose" v-popover:popover4>{{showPlace?showPlace:'请选择'}}</span></p>
39
+          <el-popover ref="popover4"  placement="right"  width="560" v-model="popover4"  trigger="click">
40
+            <el-table :data="gridData">
41
+            <el-table-column width="360" property="name" label="标题"></el-table-column>
42
+            <el-table-column width="200" label="操作">
43
+              <template slot-scope="scope">
44
+                <el-button type="text" @click="handleEdit(scope.row)" size="small">选择</el-button>
45
+        </template>
46
+            </el-table-column>
47
+            </el-table>
48
+          </el-popover>
49
+        </el-form-item>
50
+        <el-form-item label="状态:">
51
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
52
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
53
+          </el-select>
54
+        </el-form-item>
55
+        <el-form-item>
56
+          <el-button type="primary" @click="onSubmit">保存</el-button>
57
+          <el-button @click="onCancel">取消</el-button>
58
+        </el-form-item>
59
+      </el-form>
60
+    </div>    
61
+</template>
62
+
63
+<script>
64
+import { createNamespacedHelpers } from "vuex";
65
+import apis from "../../config/api";
66
+import { mapState } from "vuex";
67
+import E from "wangeditor";
68
+
69
+const {
70
+  mapState: mapBuildingState,
71
+  mapActions: mapBuildingActions,
72
+  mapMutations: mapBuildingMutations
73
+} = createNamespacedHelpers("building");
74
+
75
+const { mapActions: mapApartmentActions } = createNamespacedHelpers(
76
+  "apartment"
77
+);
78
+
79
+const { mapActions: mapImgActions } = createNamespacedHelpers("img");
80
+
81
+export default {
82
+  data() {
83
+    var _self = this;
84
+    return {
85
+      popover4:false,//弹框
86
+      showPlace:'',//活动名称展示处
87
+      gridData: [
88
+        {
89
+          date: "2016-05-02",
90
+          name: "高奢生活,在遇到它之前你想象不到"
91
+        },
92
+        {
93
+          date: "2016-05-04",
94
+          name: "欢乐套圈圈,福利大放送"
95
+        },
96
+        {
97
+          date: "2016-05-01",
98
+          name: "上海市普陀区金沙江路 1518 弄"
99
+        }
100
+      ],
101
+      upFileUrl: apis.file.upload.url,
102
+      commPrefix: "",
103
+      imgurl: "",
104
+      loadingZm: false,
105
+      activeName: "detail",
106
+      dialogImageUrl: "",
107
+      dialogVisible: false,
108
+      dialogApartImageUrl: "",
109
+      dialogApartVisible: false,
110
+      showHx: false,
111
+      imgList: [],
112
+      tags: [],
113
+      buildingProperty: [],
114
+      aparments: [],
115
+      aparmentInfo: {},
116
+      aparmentImg: [],
117
+      saleType: [
118
+        {
119
+          id: 1,
120
+          name: "待定"
121
+        },
122
+        {
123
+          id: 2,
124
+          name: "售罄"
125
+        },
126
+        {
127
+          id: 3,
128
+          name: "在售"
129
+        }
130
+      ]
131
+    };
132
+  },
133
+  computed: {
134
+    ...mapBuildingState({
135
+      detail: x => x.detail
136
+    }),
137
+    ...mapState({
138
+      dicts: x => x.dicts
139
+    }),
140
+    building: {
141
+      get() {
142
+        return this.detail;
143
+      },
144
+      set(val) {
145
+        return this.updateDetail(val);
146
+      }
147
+    },
148
+    propertyType() {
149
+      return (this.dicts || []).filter(x => x.type === "propertyType");
150
+    },
151
+    uploadHeaders() {
152
+      const token = localStorage.getItem("x-token") || "";
153
+      return {
154
+        Authorization: `Bearer ${token}`
155
+      };
156
+    }
157
+  },
158
+  methods: {
159
+    ...mapBuildingMutations(["updateDetail"]),
160
+    ...mapBuildingActions(["getDetail", "addBuilding", "editBuilding"]),
161
+    ...mapApartmentActions([
162
+      "getApartments",
163
+      "getApartmentDetail",
164
+      "addApartment",
165
+      "editApartment",
166
+      "deleteApartment"
167
+    ]),
168
+    ...mapImgActions(["uploadImg"]),
169
+    getSaleTypeName(id) {
170
+      return (this.saleType.filter(x => x.id == id)[0] || {}).name;
171
+    },
172
+    onCancel() {
173
+      this.$router.push({ name: "buildinglist" });
174
+    },
175
+    handleRemove(file, fileList) {
176
+      this.imgList = fileList;
177
+    },
178
+    handleAparmentRemove(file, fileList) {
179
+      this.aparmentImg = fileList;
180
+    },
181
+
182
+    beforeImgUpload(file) {
183
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
184
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
185
+        return false;
186
+      }
187
+      // if (file.size / 1024 > 300) {
188
+      //   this.$message.error('图片大小不允许超过300k!')
189
+      //   return false
190
+      // }
191
+      this.loading = this.$loading({
192
+        lock: true,
193
+        text: "上传中...",
194
+        spinner: "el-icon-loading",
195
+        background: "rgba(0, 0, 0, 0.7)"
196
+      });
197
+
198
+      return true;
199
+    },
200
+    handleAvatarSuccess(res) {
201
+      this.imgList = [
202
+        ...this.imgList,
203
+        {
204
+          url: res.data
205
+        }
206
+      ];
207
+      this.loading.close();
208
+    },
209
+    handleMapImgSuccess(res) {
210
+      this.building = { ...this.building, mapImg: res.data };
211
+      this.loading.close();
212
+    },
213
+    handlePosterSuccess(res) {
214
+      this.building = { ...this.building, poster: res.data };
215
+      this.loading.close();
216
+    },
217
+    handleAparmentSuccess(res) {
218
+      this.aparmentImg = [
219
+        ...this.aparmentImg,
220
+        {
221
+          url: res.data
222
+        }
223
+      ];
224
+      this.loading.close();
225
+    },
226
+    onSubmit() {
227
+      const imgs = this.imgList.map((x, i) => {
228
+        return {
229
+          imgType: "banner",
230
+          url: x.url,
231
+          orderNo: i + 1
232
+        };
233
+      });
234
+      const tag = this.tags.map(x => {
235
+        return {
236
+          tagName: x
237
+        };
238
+      });
239
+      const building = {
240
+        ...this.building,
241
+        img: imgs,
242
+        propertyType: this.buildingProperty.join(","),
243
+        tag
244
+      };
245
+      if (!building.buildingId) {
246
+        // 新增
247
+        this.addBuilding({
248
+          onSuccess: this.onCancel,
249
+          detail: JSON.stringify(building)
250
+        });
251
+      } else {
252
+        // 修改
253
+        this.editBuilding({
254
+          onSuccess: this.onCancel,
255
+          detail: JSON.stringify(building)
256
+        });
257
+      }
258
+    },
259
+    FormatDate(date) {
260
+      return (date || "").split("T")[0] === "0001-01-01"
261
+        ? ""
262
+        : (date || "").split("T")[0];
263
+    },
264
+    saveAparment() {
265
+      const imgs = this.aparmentImg.map((x, i) => {
266
+        return {
267
+          imgType: "aparment",
268
+          url: x.url,
269
+          orderNo: i + 1
270
+        };
271
+      });
272
+      if (!this.aparmentInfo.apartmentId) {
273
+        this.addApartment(
274
+          JSON.stringify({
275
+            ...this.aparmentInfo,
276
+            img: imgs
277
+          })
278
+        ).then(() => {
279
+          this.getAparmentList();
280
+          this.showHx = false;
281
+        });
282
+      } else {
283
+        this.editApartment(
284
+          JSON.stringify({
285
+            ...this.aparmentInfo,
286
+            img: imgs
287
+          })
288
+        ).then(() => {
289
+          this.getAparmentList();
290
+          this.showHx = false;
291
+        });
292
+      }
293
+    },
294
+    addHx() {
295
+      this.aparmentImg = [];
296
+      this.aparmentInfo = { buildingId: this.building.buildingId };
297
+      this.showHx = true;
298
+    },
299
+    getAparmentList() {
300
+      this.getApartments({ buildingId: this.$route.query.id }).then(data => {
301
+        this.aparments = data;
302
+      });
303
+    },
304
+    handleEdit(row){
305
+      this.showPlace = row.name
306
+      this.popover4 = false
307
+
308
+
309
+    },
310
+    // handleEdit(row) {
311
+    //   this.aparmentImg = [];
312
+    //   this.getApartmentDetail({
313
+    //     id: row.apartmentId
314
+    //   }).then(data => {
315
+    //     console.log("...", data);
316
+    //     this.aparmentImg = data.buildingImgList.map(x => {
317
+    //       return {
318
+    //         name: x.imgId,
319
+    //         url: x.url
320
+    //       };
321
+    //     });
322
+    //     this.aparmentInfo = data;
323
+    //     this.showHx = true;
324
+    //   });
325
+    // },
326
+    handleDel(row) {
327
+      this.$confirm("确认删除此数据?", "提示", {
328
+        confirmButtonText: "确定",
329
+        cancelButtonText: "取消",
330
+        type: "warning"
331
+      }).then(() => {
332
+        if (this.building.status === 1) {
333
+          this.$message.error("当前楼盘处于发布状态,不允许删除!");
334
+          return false;
335
+        }
336
+        this.deleteApartment({
337
+          id: row.apartmentId
338
+        }).then(() => {
339
+          this.getAparmentList();
340
+        });
341
+      });
342
+    }
343
+  },
344
+  mounted() {
345
+    const _that = this;
346
+    const phoneEditor = new E("#websiteEditorElem");
347
+    phoneEditor.customConfig.onchange = function(html) {
348
+      _that.building = { ..._that.building, remark: html };
349
+    };
350
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
351
+      _that.uploadImg(files[0]).then(data => {
352
+        insert(data[0]);
353
+      });
354
+    };
355
+    phoneEditor.customConfig.menus = [
356
+      "head", // 标题
357
+      "bold", // 粗体
358
+      "fontSize", // 字号
359
+      "fontName", // 字体
360
+      "italic", // 斜体
361
+      "underline", // 下划线
362
+      "strikeThrough", // 删除线
363
+      "foreColor", // 文字颜色
364
+      "backColor", // 背景颜色
365
+      "justify", // 对齐方式
366
+      "image" // 插入图片
367
+    ];
368
+    phoneEditor.create();
369
+    if ((this.$route.query.id || "") !== "") {
370
+      this.getAparmentList();
371
+      window.console.log(this.getDetail);
372
+      this.getDetail({ id: this.$route.query.id }).then(data => {
373
+        this.buildingProperty = data.propertyType.split(",");
374
+        phoneEditor.txt.html(data.remark);
375
+        this.imgList = data.buildingImg.map(x => {
376
+          return {
377
+            name: x.imgId,
378
+            url: x.url
379
+          };
380
+        });
381
+        this.tags = data.buildingTag.map(x => x.tagName);
382
+      });
383
+    } else {
384
+      phoneEditor.txt.html("");
385
+    }
386
+  }
387
+};
388
+</script>
389
+
390
+<style lang="scss">
391
+.header {
392
+  width: 50px;
393
+  height: 50px;
394
+  img {
395
+    width: 100%;
396
+    height: 100%;
397
+  }
398
+}
399
+.avatar-uploader .el-upload {
400
+  border: 1px dashed #d9d9d9;
401
+  border-radius: 6px;
402
+  cursor: pointer;
403
+  position: relative;
404
+  overflow: hidden;
405
+}
406
+.avatar-uploader .el-upload:hover {
407
+  border-color: #409eff;
408
+}
409
+.avatar-uploader-icon {
410
+  font-size: 28px;
411
+  color: #8c939d;
412
+  width: 178px;
413
+  height: 178px;
414
+  line-height: 178px;
415
+  text-align: center;
416
+}
417
+.avatar {
418
+  width: 178px;
419
+  height: 178px;
420
+  display: block;
421
+}
422
+.edit-carousel {
423
+  .el-select {
424
+    max-width: 300px !important;
425
+  }
426
+  .el-input {
427
+    max-width: 400px;
428
+  }
429
+  .publish {
430
+    p {
431
+      margin: 0;
432
+      font-size: 15.4px;
433
+      .choose {
434
+        color: blue;
435
+        margin-left: 15px;
436
+      }
437
+    }
438
+  }
439
+}
440
+.el-popover {
441
+  z-index: 10004 !important;
442
+  .el-table .cell{
443
+    text-align: center;
444
+  }
445
+}
446
+
447
+.el-select-dropdown {
448
+  z-index: 10003 !important;
449
+}
450
+
451
+.el-date-picker {
452
+  z-index: 10002 !important;
453
+}
454
+</style>

+ 459
- 0
src/views/carouselFigure/edit.vue Целия файл

@@ -0,0 +1,459 @@
1
+<template>
2
+    <div class="edit-carousel">
3
+      <el-form ref="form" :model="building" label-width="180px">
4
+        <el-form-item label="所属项目:">
5
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
6
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
7
+          </el-select>
8
+        </el-form-item>
9
+        <el-form-item label="主图:">
10
+          <el-upload
11
+            :action="upFileUrl"
12
+            name='file'
13
+            list-type="picture-card"
14
+            :headers="uploadHeaders"
15
+            :file-list="imgList"
16
+            :show-file-list="true"
17
+            :before-upload="beforeImgUpload"
18
+            :on-success="handleAvatarSuccess"
19
+            :on-remove="handleRemove">
20
+            <i class="el-icon-plus"></i>
21
+          </el-upload>
22
+          <el-dialog :visible.sync="dialogVisible">
23
+            <img width="100%" :src="dialogImageUrl" alt="">
24
+          </el-dialog>
25
+        </el-form-item>
26
+        <el-form-item label="标题:">
27
+          <el-input v-model="building.tel"></el-input>
28
+        </el-form-item>
29
+        <el-form-item label="发布位置:">
30
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
31
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
32
+          </el-select>
33
+        </el-form-item>
34
+        <el-form-item label="类型:">
35
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
36
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
37
+          </el-select>
38
+        </el-form-item>
39
+        <el-form-item label="发布内容:">
40
+          <div id="websiteEditorElem" style="height: 400px"></div>
41
+        </el-form-item>
42
+        <el-form-item label="发布内容:" class="publish">
43
+          <p>活动名称展示处<span class="choose" v-popover:popover4>{{showPlace?showPlace:'请选择'}}</span></p>
44
+          <el-popover ref="popover4"  placement="right"  width="560" v-model="popover4"  trigger="click">
45
+            <el-table :data="gridData">
46
+            <el-table-column width="360" property="name" label="标题"></el-table-column>
47
+            <el-table-column width="200" label="操作">
48
+              <template slot-scope="scope">
49
+                <el-button type="text" @click="handleEdit(scope.row)" size="small">选择</el-button>
50
+        </template>
51
+            </el-table-column>
52
+            </el-table>
53
+          </el-popover>
54
+        </el-form-item>
55
+        <el-form-item label="状态:">
56
+          <el-select v-model="buildingProperty" multiple placeholder="请选择">
57
+            <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
58
+          </el-select>
59
+        </el-form-item>
60
+        <el-form-item>
61
+          <el-button type="primary" @click="onSubmit">保存</el-button>
62
+          <el-button @click="onCancel">取消</el-button>
63
+        </el-form-item>
64
+      </el-form>
65
+    </div>    
66
+</template>
67
+
68
+<script>
69
+import { createNamespacedHelpers } from "vuex";
70
+import apis from "../../config/api";
71
+import { mapState } from "vuex";
72
+import E from "wangeditor";
73
+
74
+const {
75
+  mapState: mapBuildingState,
76
+  mapActions: mapBuildingActions,
77
+  mapMutations: mapBuildingMutations
78
+} = createNamespacedHelpers("building");
79
+
80
+const { mapActions: mapApartmentActions } = createNamespacedHelpers(
81
+  "apartment"
82
+);
83
+
84
+const { mapActions: mapImgActions } = createNamespacedHelpers("img");
85
+
86
+export default {
87
+  data() {
88
+    var _self = this;
89
+    return {
90
+      popover4:false,//弹框
91
+      showPlace:'',//活动名称展示处
92
+      gridData: [
93
+        {
94
+          date: "2016-05-02",
95
+          name: "高奢生活,在遇到它之前你想象不到"
96
+        },
97
+        {
98
+          date: "2016-05-04",
99
+          name: "欢乐套圈圈,福利大放送"
100
+        },
101
+        {
102
+          date: "2016-05-01",
103
+          name: "上海市普陀区金沙江路 1518 弄"
104
+        }
105
+      ],
106
+      upFileUrl: apis.file.upload.url,
107
+      commPrefix: "",
108
+      imgurl: "",
109
+      loadingZm: false,
110
+      activeName: "detail",
111
+      dialogImageUrl: "",
112
+      dialogVisible: false,
113
+      dialogApartImageUrl: "",
114
+      dialogApartVisible: false,
115
+      showHx: false,
116
+      imgList: [],
117
+      tags: [],
118
+      buildingProperty: [],
119
+      aparments: [],
120
+      aparmentInfo: {},
121
+      aparmentImg: [],
122
+      saleType: [
123
+        {
124
+          id: 1,
125
+          name: "待定"
126
+        },
127
+        {
128
+          id: 2,
129
+          name: "售罄"
130
+        },
131
+        {
132
+          id: 3,
133
+          name: "在售"
134
+        }
135
+      ]
136
+    };
137
+  },
138
+  computed: {
139
+    ...mapBuildingState({
140
+      detail: x => x.detail
141
+    }),
142
+    ...mapState({
143
+      dicts: x => x.dicts
144
+    }),
145
+    building: {
146
+      get() {
147
+        return this.detail;
148
+      },
149
+      set(val) {
150
+        return this.updateDetail(val);
151
+      }
152
+    },
153
+    propertyType() {
154
+      return (this.dicts || []).filter(x => x.type === "propertyType");
155
+    },
156
+    uploadHeaders() {
157
+      const token = localStorage.getItem("x-token") || "";
158
+      return {
159
+        Authorization: `Bearer ${token}`
160
+      };
161
+    }
162
+  },
163
+  methods: {
164
+    ...mapBuildingMutations(["updateDetail"]),
165
+    ...mapBuildingActions(["getDetail", "addBuilding", "editBuilding"]),
166
+    ...mapApartmentActions([
167
+      "getApartments",
168
+      "getApartmentDetail",
169
+      "addApartment",
170
+      "editApartment",
171
+      "deleteApartment"
172
+    ]),
173
+    ...mapImgActions(["uploadImg"]),
174
+    getSaleTypeName(id) {
175
+      return (this.saleType.filter(x => x.id == id)[0] || {}).name;
176
+    },
177
+    onCancel() {
178
+      this.$router.push({ name: "buildinglist" });
179
+    },
180
+    handleRemove(file, fileList) {
181
+      this.imgList = fileList;
182
+    },
183
+    handleAparmentRemove(file, fileList) {
184
+      this.aparmentImg = fileList;
185
+    },
186
+
187
+    beforeImgUpload(file) {
188
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
189
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
190
+        return false;
191
+      }
192
+      // if (file.size / 1024 > 300) {
193
+      //   this.$message.error('图片大小不允许超过300k!')
194
+      //   return false
195
+      // }
196
+      this.loading = this.$loading({
197
+        lock: true,
198
+        text: "上传中...",
199
+        spinner: "el-icon-loading",
200
+        background: "rgba(0, 0, 0, 0.7)"
201
+      });
202
+
203
+      return true;
204
+    },
205
+    handleAvatarSuccess(res) {
206
+      this.imgList = [
207
+        ...this.imgList,
208
+        {
209
+          url: res.data
210
+        }
211
+      ];
212
+      this.loading.close();
213
+    },
214
+    handleMapImgSuccess(res) {
215
+      this.building = { ...this.building, mapImg: res.data };
216
+      this.loading.close();
217
+    },
218
+    handlePosterSuccess(res) {
219
+      this.building = { ...this.building, poster: res.data };
220
+      this.loading.close();
221
+    },
222
+    handleAparmentSuccess(res) {
223
+      this.aparmentImg = [
224
+        ...this.aparmentImg,
225
+        {
226
+          url: res.data
227
+        }
228
+      ];
229
+      this.loading.close();
230
+    },
231
+    onSubmit() {
232
+      const imgs = this.imgList.map((x, i) => {
233
+        return {
234
+          imgType: "banner",
235
+          url: x.url,
236
+          orderNo: i + 1
237
+        };
238
+      });
239
+      const tag = this.tags.map(x => {
240
+        return {
241
+          tagName: x
242
+        };
243
+      });
244
+      const building = {
245
+        ...this.building,
246
+        img: imgs,
247
+        propertyType: this.buildingProperty.join(","),
248
+        tag
249
+      };
250
+      if (!building.buildingId) {
251
+        // 新增
252
+        this.addBuilding({
253
+          onSuccess: this.onCancel,
254
+          detail: JSON.stringify(building)
255
+        });
256
+      } else {
257
+        // 修改
258
+        this.editBuilding({
259
+          onSuccess: this.onCancel,
260
+          detail: JSON.stringify(building)
261
+        });
262
+      }
263
+    },
264
+    FormatDate(date) {
265
+      return (date || "").split("T")[0] === "0001-01-01"
266
+        ? ""
267
+        : (date || "").split("T")[0];
268
+    },
269
+    saveAparment() {
270
+      const imgs = this.aparmentImg.map((x, i) => {
271
+        return {
272
+          imgType: "aparment",
273
+          url: x.url,
274
+          orderNo: i + 1
275
+        };
276
+      });
277
+      if (!this.aparmentInfo.apartmentId) {
278
+        this.addApartment(
279
+          JSON.stringify({
280
+            ...this.aparmentInfo,
281
+            img: imgs
282
+          })
283
+        ).then(() => {
284
+          this.getAparmentList();
285
+          this.showHx = false;
286
+        });
287
+      } else {
288
+        this.editApartment(
289
+          JSON.stringify({
290
+            ...this.aparmentInfo,
291
+            img: imgs
292
+          })
293
+        ).then(() => {
294
+          this.getAparmentList();
295
+          this.showHx = false;
296
+        });
297
+      }
298
+    },
299
+    addHx() {
300
+      this.aparmentImg = [];
301
+      this.aparmentInfo = { buildingId: this.building.buildingId };
302
+      this.showHx = true;
303
+    },
304
+    getAparmentList() {
305
+      this.getApartments({ buildingId: this.$route.query.id }).then(data => {
306
+        this.aparments = data;
307
+      });
308
+    },
309
+    handleEdit(row){
310
+      this.showPlace = row.name
311
+      this.popover4 = false
312
+
313
+
314
+    },
315
+    // handleEdit(row) {
316
+    //   this.aparmentImg = [];
317
+    //   this.getApartmentDetail({
318
+    //     id: row.apartmentId
319
+    //   }).then(data => {
320
+    //     console.log("...", data);
321
+    //     this.aparmentImg = data.buildingImgList.map(x => {
322
+    //       return {
323
+    //         name: x.imgId,
324
+    //         url: x.url
325
+    //       };
326
+    //     });
327
+    //     this.aparmentInfo = data;
328
+    //     this.showHx = true;
329
+    //   });
330
+    // },
331
+    handleDel(row) {
332
+      this.$confirm("确认删除此数据?", "提示", {
333
+        confirmButtonText: "确定",
334
+        cancelButtonText: "取消",
335
+        type: "warning"
336
+      }).then(() => {
337
+        if (this.building.status === 1) {
338
+          this.$message.error("当前楼盘处于发布状态,不允许删除!");
339
+          return false;
340
+        }
341
+        this.deleteApartment({
342
+          id: row.apartmentId
343
+        }).then(() => {
344
+          this.getAparmentList();
345
+        });
346
+      });
347
+    }
348
+  },
349
+  mounted() {
350
+    const _that = this;
351
+    const phoneEditor = new E("#websiteEditorElem");
352
+    phoneEditor.customConfig.onchange = function(html) {
353
+      _that.building = { ..._that.building, remark: html };
354
+    };
355
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
356
+      _that.uploadImg(files[0]).then(data => {
357
+        insert(data[0]);
358
+      });
359
+    };
360
+    phoneEditor.customConfig.menus = [
361
+      "head", // 标题
362
+      "bold", // 粗体
363
+      "fontSize", // 字号
364
+      "fontName", // 字体
365
+      "italic", // 斜体
366
+      "underline", // 下划线
367
+      "strikeThrough", // 删除线
368
+      "foreColor", // 文字颜色
369
+      "backColor", // 背景颜色
370
+      "justify", // 对齐方式
371
+      "image" // 插入图片
372
+    ];
373
+    phoneEditor.create();
374
+    if ((this.$route.query.id || "") !== "") {
375
+      this.getAparmentList();
376
+      window.console.log(this.getDetail);
377
+      this.getDetail({ id: this.$route.query.id }).then(data => {
378
+        this.buildingProperty = data.propertyType.split(",");
379
+        phoneEditor.txt.html(data.remark);
380
+        this.imgList = data.buildingImg.map(x => {
381
+          return {
382
+            name: x.imgId,
383
+            url: x.url
384
+          };
385
+        });
386
+        this.tags = data.buildingTag.map(x => x.tagName);
387
+      });
388
+    } else {
389
+      phoneEditor.txt.html("");
390
+    }
391
+  }
392
+};
393
+</script>
394
+
395
+<style lang="scss">
396
+.header {
397
+  width: 50px;
398
+  height: 50px;
399
+  img {
400
+    width: 100%;
401
+    height: 100%;
402
+  }
403
+}
404
+.avatar-uploader .el-upload {
405
+  border: 1px dashed #d9d9d9;
406
+  border-radius: 6px;
407
+  cursor: pointer;
408
+  position: relative;
409
+  overflow: hidden;
410
+}
411
+.avatar-uploader .el-upload:hover {
412
+  border-color: #409eff;
413
+}
414
+.avatar-uploader-icon {
415
+  font-size: 28px;
416
+  color: #8c939d;
417
+  width: 178px;
418
+  height: 178px;
419
+  line-height: 178px;
420
+  text-align: center;
421
+}
422
+.avatar {
423
+  width: 178px;
424
+  height: 178px;
425
+  display: block;
426
+}
427
+.edit-carousel {
428
+  .el-select {
429
+    max-width: 300px !important;
430
+  }
431
+  .el-input {
432
+    max-width: 400px;
433
+  }
434
+  .publish {
435
+    p {
436
+      margin: 0;
437
+      font-size: 15.4px;
438
+      .choose {
439
+        color: blue;
440
+        margin-left: 15px;
441
+      }
442
+    }
443
+  }
444
+}
445
+.el-popover {
446
+  z-index: 10004 !important;
447
+  .el-table .cell{
448
+    text-align: center;
449
+  }
450
+}
451
+
452
+.el-select-dropdown {
453
+  z-index: 10003 !important;
454
+}
455
+
456
+.el-date-picker {
457
+  z-index: 10002 !important;
458
+}
459
+</style>

+ 232
- 0
src/views/carouselFigure/list.vue Целия файл

@@ -0,0 +1,232 @@
1
+<template>
2
+  <div>
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增</el-button>
7
+        </div>
8
+      </div>
9
+      <div class="moreFilter"></div>
10
+    </div>
11
+    <el-table
12
+      :data="dynamics.list || []"
13
+      >
14
+      <el-table-column
15
+        type="index">
16
+        <template slot-scope="scope">
17
+          <span>{{ GetIndex(scope.$index) }}</span>
18
+        </template>
19
+      </el-table-column>
20
+      <el-table-column
21
+        label="主图">
22
+        <template slot-scope="scope">
23
+          <div class="header">
24
+            <img :src="scope.row.imgUrl" alt="" />
25
+          </div>
26
+        </template>
27
+      </el-table-column>
28
+      <el-table-column
29
+        prop="title"
30
+        label="类型">
31
+      </el-table-column>
32
+      <el-table-column
33
+        prop="desc"
34
+        label="发布位置">
35
+      </el-table-column>
36
+      <el-table-column
37
+        prop="createDate"
38
+        label="发布时间">
39
+      </el-table-column>
40
+      <el-table-column
41
+        label="状态"
42
+        >
43
+        <template slot-scope="scope">
44
+          <span>{{scope.row.status == 1 ? '启用' : '停用'}}</span>
45
+        </template>
46
+      </el-table-column>
47
+      <el-table-column
48
+        fixed="right"
49
+        label="操作"
50
+        width="180">
51
+        <template slot-scope="scope">
52
+          <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status === 0" size="small">编辑</el-button>
53
+          <el-button type="text" @click="handlePulic(scope.row)" size="small" v-if="scope.row.status === 0">启用</el-button>
54
+          <el-button type="text" @click="handleUnPulic(scope.row)" size="small" v-if="scope.row.status === 1">禁用</el-button>
55
+
56
+        </template>
57
+      </el-table-column>
58
+    </el-table>
59
+    <el-pagination
60
+      small
61
+      style="margin-top:10px;"
62
+      layout="prev, pager, next"
63
+      :current-page.sync="currentPage"
64
+      :pageSize="pageSize"
65
+      :total="dynamics.total || 0"
66
+      @current-change="getList"
67
+    >
68
+    </el-pagination>
69
+  </div>
70
+</template>
71
+
72
+<script>
73
+import { createNamespacedHelpers } from 'vuex';
74
+
75
+const {mapState: mapDynamicState, mapActions: mapDynamicActions} = createNamespacedHelpers('dynamic')
76
+const {mapState: mapBuildingState, mapActions: mapBuildingActions} = createNamespacedHelpers('building')
77
+
78
+export default {
79
+  data() {
80
+    return {
81
+      pageSize: 20,
82
+      currentPage: 1,
83
+      name: '',
84
+      buildingId: '',
85
+    }
86
+  },
87
+  computed: {
88
+    ...mapDynamicState({
89
+      dynamics: x => x.dynamics
90
+    }),
91
+    ...mapBuildingState({
92
+      buildings: x => x.buildings
93
+    })
94
+  },
95
+  methods: {
96
+    ...mapDynamicActions([
97
+      'getDynamics',
98
+      'setDetailNull',
99
+      'deleteDynamics',
100
+      'publicDynamic',
101
+      'cancelDynamic'
102
+    ]),
103
+    ...mapBuildingActions([
104
+      'getBuildings',
105
+    ]),
106
+    GetIndex (inx) {
107
+      return (this.currentPage - 1) * this.pageSize + inx + 1
108
+    },
109
+    FormatDate (date) {
110
+      if (date) {
111
+        return dayjs(date).formate('yyyy-MM-DD HH:mm:ss')
112
+      } else {
113
+        return ''
114
+      }
115
+    },
116
+    getList () {
117
+      this.getDynamics({
118
+        pageNum: this.currentPage,
119
+        pageSize: this.pageSize,
120
+        name: this.name,
121
+        buildingId: this.buildingId
122
+      })
123
+    },
124
+    getBuildingName (id) {
125
+      return ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {}).buildingName || ''
126
+    },
127
+    search () {
128
+      this.currentPage = 1
129
+      this.getList()
130
+    },
131
+    handleEdit (row) {
132
+      this.setDetailNull()
133
+      this.$router.push({name: 'editCarousel', query: {id: row.dynamicId}})
134
+    },
135
+    handlePulic (row) {
136
+      this.$confirm('确认发布此数据?', '提示', {
137
+        confirmButtonText: '确定',
138
+        cancelButtonText: '取消',
139
+        type: 'warning'
140
+      }).then(() => {
141
+        this.publicDynamic({
142
+          id: row.dynamicId
143
+        }).then(() => {
144
+          this.getList()
145
+        })
146
+      })
147
+    },
148
+    handleUnPulic (row) {
149
+      this.$confirm('确认取消发布此数据?', '提示', {
150
+        confirmButtonText: '确定',
151
+        cancelButtonText: '取消',
152
+        type: 'warning'
153
+      }).then(() => {
154
+        this.cancelDynamic({
155
+          id: row.dynamicId}).then(() => {
156
+          this.getList()
157
+        })
158
+      })
159
+    },
160
+    handleDel (row) {
161
+      this.$confirm('确认删除此数据?', '提示', {
162
+        confirmButtonText: '确定',
163
+        cancelButtonText: '取消',
164
+        type: 'warning'
165
+      }).then(() => {
166
+        if (row.status === 1) {
167
+          this.$message.error('当前活动处于发布状态,不允许删除!')
168
+          return false
169
+        }
170
+        this.deleteDynamics({
171
+          id: row.dynamicId
172
+        }).then(() => {
173
+          this.getList()
174
+        })
175
+      })
176
+    },
177
+    addDynamic () {
178
+      this.setDetailNull()
179
+      this.$router.push({name: 'editCarousel'})
180
+    }
181
+  },
182
+  created () {
183
+    this.getBuildings({
184
+      pageNum: 1,
185
+      pageSize: 100,
186
+    }).then(() => {
187
+      this.getList()
188
+    })
189
+  }
190
+}
191
+</script>
192
+
193
+<style lang="scss" scoped>
194
+.header{
195
+  width: 50px;
196
+  height: 50px;
197
+  img{
198
+    width: 100%;
199
+    height: 100%;
200
+  }
201
+}
202
+
203
+.system-table-search{
204
+  width: calc(100% - 40px);
205
+  margin: 20px auto 0;
206
+}
207
+
208
+.system-table-search li{
209
+  margin-right: 20px;
210
+}
211
+
212
+.system-table-search ul{
213
+  font-size: 0;
214
+  white-space: nowrap;
215
+}
216
+
217
+.system-table-search ul>li{
218
+  display: inline-block;
219
+}
220
+
221
+.flex-h {
222
+  display: flex;
223
+  display: -webkit-flex;
224
+}
225
+
226
+.flex-item {
227
+  flex: 1;
228
+  -webkit-flex: 1;
229
+  position: relative;
230
+  overflow: hidden;
231
+}
232
+</style>

+ 98
- 93
src/views/consultant/edit.vue Целия файл

@@ -1,37 +1,43 @@
1 1
 <template>
2 2
   <div>
3 3
     <div class="form-wrapper">
4
-      <el-form label-width="80px" :model="detail">
5
-        <el-form-item label="名称">
4
+      <el-form label-width="100px" :model="detail">
5
+        <el-form-item label="名称">
6 6
           <el-input v-model="detail.name"></el-input>
7 7
         </el-form-item>
8
-        <el-form-item label="公司">
8
+        <el-form-item label="公司">
9 9
           <el-input v-model="detail.company"></el-input>
10 10
         </el-form-item>
11
-        <el-form-item label="部门">
11
+        <el-form-item label="部门">
12 12
           <el-input v-model="detail.department"></el-input>
13 13
         </el-form-item>
14
-        <el-form-item label="职位">
14
+        <el-form-item label="职位">
15 15
           <el-input v-model="detail.post"></el-input>
16 16
         </el-form-item>
17
-        <el-form-item label="电话">
17
+        <el-form-item label="电话">
18 18
           <el-input v-model="detail.tel"></el-input>
19 19
         </el-form-item>
20
-        <el-form-item label="地址">
20
+        <el-form-item label="标签:">
21
+          <el-input v-model="detail.tag"></el-input>
22
+        </el-form-item>
23
+        <el-form-item label="地址:">
21 24
           <el-input v-model="detail.address"></el-input>
22 25
         </el-form-item>
23
-        <el-form-item label="授权项目">
26
+        <el-form-item label="授权项目">
24 27
           <el-select v-model="detail.buildings" placeholder="请选择">
25 28
             <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
26 29
           </el-select>
27 30
         </el-form-item>
28
-        <el-form-item label="图片">
31
+        <el-form-item label="图片">
29 32
           <el-upload class="avatar-uploader" :action="upFileUrl" name="file" :show-file-list="false" :before-upload="beforeImgUpload" :on-success="handleAvatarSuccess">
30 33
             <img v-if="detail.photo" :src="detail.photo" class="avatar">
31 34
             <i v-else class="el-icon-plus avatar-uploader-icon"></i>
32 35
           </el-upload>
33 36
         </el-form-item>
34
-        <el-form-item label="状态">
37
+          <el-form-item label="简介:">
38
+            <el-input type="textarea" :rows="5"  v-model="detail.introduction"></el-input>
39
+        </el-form-item>
40
+        <el-form-item label="状态:">
35 41
           <el-radio-group v-model="detail.status">
36 42
             <el-radio-button :label="0">禁用</el-radio-button>
37 43
             <el-radio-button :label="1">启用</el-radio-button>
@@ -47,15 +53,18 @@
47 53
 </template>
48 54
 
49 55
 <script>
50
-import { createNamespacedHelpers } from 'vuex'
51
-import apis from '../../config/api'
52
-import E from 'wangeditor'
56
+import { createNamespacedHelpers } from "vuex";
57
+import apis from "../../config/api";
58
+import E from "wangeditor";
53 59
 
54
-const { mapActions: mapPersonActions } = createNamespacedHelpers('persons')
55
-const { mapState: mapBuildingState, mapActions: mapBuildingActions } = createNamespacedHelpers('building')
60
+const { mapActions: mapPersonActions } = createNamespacedHelpers("persons");
61
+const {
62
+  mapState: mapBuildingState,
63
+  mapActions: mapBuildingActions
64
+} = createNamespacedHelpers("building");
56 65
 export default {
57
-  name: 'consultantEdit',
58
-  data () {
66
+  name: "consultantEdit",
67
+  data() {
59 68
     return {
60 69
       upFileUrl: apis.file.upload.url,
61 70
       detail: {
@@ -66,118 +75,114 @@ export default {
66 75
         tel: undefined,
67 76
         photo: undefined,
68 77
         status: 1,
69
-        buildings:[]
70
-      },
71
-    }
78
+        buildings: []
79
+      }
80
+    };
72 81
   },
73
-  created () {
74
-    this.init()
82
+  created() {
83
+    this.init();
75 84
   },
76
-  computed:{
85
+  computed: {
77 86
     ...mapBuildingState({
78 87
       buildings: x => x.buildings
79
-    }),
88
+    })
80 89
   },
81 90
   methods: {
82
-    
83
-    ...mapBuildingActions([
84
-      'getBuildings'
85
-    ]),
86
-    ...mapPersonActions([
87
-      'getConsultant',
88
-      'editConsultant',
89
-    ]),
90
-    init () {
91
+    ...mapBuildingActions(["getBuildings"]),
92
+    ...mapPersonActions(["getConsultant", "editConsultant"]),
93
+    init() {
91 94
       if (this.$route.params.id) {
92
-        this.getConsultant({ id: this.$route.params.id }).then((data) => {
93
-          this.detail = data
94
-        })
95
+        this.getConsultant({ id: this.$route.params.id }).then(data => {
96
+          this.detail = data;
97
+        });
95 98
       }
96 99
     },
97
-    beforeImgUpload (file) {
98
-      if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
99
-        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
100
-        return false
100
+    beforeImgUpload(file) {
101
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
102
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
103
+        return false;
101 104
       }
102 105
 
103
-      this.showLoadding('上传中...')
104
-      return true
106
+      this.showLoadding("上传中...");
107
+      return true;
105 108
     },
106 109
 
107
-    handleAvatarSuccess (res) {
108
-      this.detail.photo = res.data
109
-      this.hideLoadding()
110
+    handleAvatarSuccess(res) {
111
+      this.detail.photo = res.data;
112
+      this.hideLoadding();
110 113
     },
111 114
 
112
-    submitForm () {
113
-      this.showLoadding('保存中...')
114
-      this.editConsultant(this.detail).then((res) => {
115
-        if (res.personId) {
116
-          this.detail = res
117
-        }
115
+    submitForm() {
116
+      this.showLoadding("保存中...");
117
+      this.editConsultant(this.detail)
118
+        .then(res => {
119
+          if (res.personId) {
120
+            this.detail = res;
121
+          }
118 122
 
119
-        this.hideLoadding()
120
-        this.$notify.info('保存成功')
121
-      }).catch((err) => {
122
-        this.hideLoadding()
123
-        this.$notify.error(err.message)
124
-      })
123
+          this.hideLoadding();
124
+          this.$notify.info("保存成功");
125
+        })
126
+        .catch(err => {
127
+          this.hideLoadding();
128
+          this.$notify.error(err.message);
129
+        });
125 130
     },
126 131
 
127
-    showLoadding (text) {
132
+    showLoadding(text) {
128 133
       this.loading = this.$loading({
129 134
         text,
130 135
         lock: true,
131
-        spinner: 'el-icon-loading',
132
-        background: 'rgba(255, 255, 255, 0.7)'
133
-      })
136
+        spinner: "el-icon-loading",
137
+        background: "rgba(255, 255, 255, 0.7)"
138
+      });
134 139
     },
135 140
 
136
-    hideLoadding () {
137
-      if (this.loading) this.loading.close()
141
+    hideLoadding() {
142
+      if (this.loading) this.loading.close();
138 143
     }
139 144
   },
140
-  mounted () {
141
-    const _that = this
142
-    const phoneEditor = new E('#websiteEditorElem')
143
-    phoneEditor.customConfig.onchange = function (html) {
144
-      _that.dynamic = {..._that.dynamic, url: html}
145
-    }
145
+  mounted() {
146
+    const _that = this;
147
+    const phoneEditor = new E("#websiteEditorElem");
148
+    phoneEditor.customConfig.onchange = function(html) {
149
+      _that.dynamic = { ..._that.dynamic, url: html };
150
+    };
146 151
     // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
147 152
     // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
148 153
 
149
-    phoneEditor.customConfig.customUploadImg = function (files, insert) {
154
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
150 155
       _that.uploadImg(files[0]).then(data => {
151
-        insert(data)
152
-      })
153
-    }
156
+        insert(data);
157
+      });
158
+    };
154 159
     phoneEditor.customConfig.menus = [
155
-      'head',  // 标题
156
-      'bold',  // 粗体
157
-      'fontSize',  // 字号
158
-      'fontName',  // 字体
159
-      'italic',  // 斜体
160
-      'underline',  // 下划线
161
-      'strikeThrough',  // 删除线
162
-      'foreColor',  // 文字颜色
163
-      'backColor',  // 背景颜色
164
-      'justify',  // 对齐方式
165
-      'image',  // 插入图片
166
-    ]
160
+      "head", // 标题
161
+      "bold", // 粗体
162
+      "fontSize", // 字号
163
+      "fontName", // 字体
164
+      "italic", // 斜体
165
+      "underline", // 下划线
166
+      "strikeThrough", // 删除线
167
+      "foreColor", // 文字颜色
168
+      "backColor", // 背景颜色
169
+      "justify", // 对齐方式
170
+      "image" // 插入图片
171
+    ];
167 172
     // phoneEditor.create()
168
-    
173
+
169 174
     this.getBuildings({
170 175
       pageNum: 1,
171
-      pageSize: 100,
176
+      pageSize: 100
172 177
     }).then(() => {
173
-      if ((this.$route.query.id || '') !== '') {
174
-        this.getDetail({id: this.$route.query.id}).then((data) => {
175
-          phoneEditor.txt.html(data.url)
176
-        })
178
+      if ((this.$route.query.id || "") !== "") {
179
+        this.getDetail({ id: this.$route.query.id }).then(data => {
180
+          phoneEditor.txt.html(data.url);
181
+        });
177 182
       }
178
-    })
183
+    });
179 184
   }
180
-}
185
+};
181 186
 </script>
182 187
 
183 188
 <style lang="scss" scoped>

+ 102
- 44
src/views/consultant/list.vue Целия файл

@@ -1,15 +1,28 @@
1 1
 <template>
2 2
 <div class="list">
3
+        <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增</el-button>
7
+        </div>
8
+        <ul>
9
+          <li>
10
+            <el-input v-model="searchName" placeholder="姓名"></el-input>
11
+          </li>
12
+
13
+        </ul>
14
+        <el-button
15
+          size="mini"
16
+          type="primary" @click="search">查询</el-button>
17
+      </div>
18
+      <div class="moreFilter"></div>
19
+    </div>
3 20
   <el-table
4 21
     :data="list || []"
5 22
     style="width: 100%">
6
-    <el-table-column
7
-      prop="personId"
8
-      label="#">
9
-    </el-table-column>
10 23
     <el-table-column
11 24
       prop="name"
12
-      label="名称">
25
+      label="姓名">
13 26
     </el-table-column>
14 27
     <el-table-column
15 28
       prop="tel"
@@ -23,11 +36,17 @@
23 36
       prop="likeNum"
24 37
       label="点赞">
25 38
     </el-table-column>
39
+    <el-table-column   label="状态">
40
+      <template slot-scope="scope">
41
+        <span :style="{color:(scope.row.status == 1?'':'red')}" >{{scope.row.status == 1 ? '启用' : '禁用'}}</span>
42
+      </template>
43
+    </el-table-column>
26 44
     <el-table-column
27 45
       fixed="right"
28 46
       label="操作">
29 47
       <template slot-scope="scope">
30
-        <el-button type="text" @click="toDetail(scope.row)" size="small">详情</el-button>
48
+        <el-button type="text" @click="toDetail(scope.row)" size="small">{{scope.row.status == 1?'停用':'启用'}}</el-button>
49
+        <el-button type="text" @click="toDetail(scope.row)" size="small">编辑</el-button>
31 50
       </template>
32 51
     </el-table-column>
33 52
   </el-table>
@@ -45,70 +64,109 @@
45 64
 </template>
46 65
 
47 66
 <script>
48
-import { createNamespacedHelpers } from 'vuex'
67
+import { createNamespacedHelpers } from "vuex";
49 68
 
50
-const { mapActions: mapPersonActions } = createNamespacedHelpers('persons')
69
+const { mapActions: mapPersonActions } = createNamespacedHelpers("persons");
51 70
 
52 71
 export default {
53
-  name: 'consultant-list',
54
-  data () {
72
+  name: "consultant-list",
73
+  data() {
55 74
     return {
56 75
       filterData: {
57
-        name: '',
58
-        phone: '',
76
+        name: "",
77
+        phone: ""
59 78
       },
60 79
       list: [],
61 80
       pageNavi: {
62 81
         current: 1,
63 82
         size: 20,
64
-        total: 0,
83
+        total: 0
65 84
       },
66
-    }
67
-  },
68
-  computed: {
85
+      searchName: ""
86
+    };
69 87
   },
88
+  computed: {},
70 89
   methods: {
71
-    ...mapPersonActions([
72
-      'getConsultants',
73
-    ]),
74
-    getList () {
75
-      const pageNumber = this.pageNavi.current || 1
76
-      const pageSize = this.pageNavi.size
90
+    ...mapPersonActions(["getConsultants"]),
91
+    getList() {
92
+      const pageNumber = this.pageNavi.current || 1;
93
+      const pageSize = this.pageNavi.size;
77 94
 
78 95
       this.getConsultants({
79 96
         ...this.filterData,
80 97
         pageNumber,
81
-        pageSize,
82
-      }).then((res) => {
83
-        const { records, ...pageNavi } = res
84
-
85
-        this.list = records
86
-        this.pageNavi = pageNavi
87
-      }).catch((err) => {
88
-        this.$notify.error(err.msg || err.message)
98
+        pageSize
89 99
       })
100
+        .then(res => {
101
+          const { records, ...pageNavi } = res;
102
+
103
+          this.list = records;
104
+          this.pageNavi = pageNavi;
105
+        })
106
+        .catch(err => {
107
+          this.$notify.error(err.msg || err.message);
108
+        });
90 109
     },
91
-    toDetail (row) {
92
-      this.$router.push({ name: 'consultant.edit', params: { id: row.personId } })
110
+    addDynamic() {
111
+      this.$router.push({ name: "consultant.list" });
93 112
     },
94
-    newPage (page) {
95
-      this.$router.replace({ name: 'consultant.list', query: { page } })
113
+    toDetail(row) {
114
+      this.$router.push({
115
+        name: "consultant.edit",
116
+        params: { id: row.personId }
117
+      });
118
+    },
119
+    search() {
120
+      this.pageNavi.current = 1;
121
+      this.getList();
122
+    },
123
+    newPage(page) {
124
+      this.$router.replace({ name: "consultant.list", query: { page } });
96 125
     }
97 126
   },
98
-  created () {
99
-    this.pageNavi.current = this.$route.query.page || 1
127
+  created() {
128
+    this.pageNavi.current = this.$route.query.page || 1;
100 129
 
101
-    this.getList()
130
+    this.getList();
102 131
   }
103
-}
132
+};
104 133
 </script>
105 134
 
106 135
 <style lang="scss" scoped>
107
-  .list{
108
-    .header{
109
-      width: 50px;
110
-      height: 50px;
111
-      border-radius: 50%;
112
-    }
136
+.list {
137
+  .header {
138
+    width: 50px;
139
+    height: 50px;
140
+    border-radius: 50%;
113 141
   }
142
+}
143
+.system-table-search {
144
+  width: calc(100% - 40px);
145
+  margin: 20px auto 0;
146
+}
147
+
148
+.system-table-search li {
149
+  margin-right: 20px;
150
+}
151
+
152
+.system-table-search ul {
153
+  font-size: 0;
154
+  white-space: nowrap;
155
+}
156
+
157
+.system-table-search ul > li {
158
+  display: inline-block;
159
+}
160
+
161
+.flex-h {
162
+  display: flex;
163
+  align-items: center;
164
+}
165
+
166
+.flex-item {
167
+  flex: 1;
168
+  -webkit-flex: 1;
169
+  position: relative;
170
+  overflow: hidden;
171
+}
114 172
 </style>

+ 235
- 0
src/views/customer/editCustomer.vue Целия файл

@@ -0,0 +1,235 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="200px" :model="detail">
5
+        <el-form-item label="意向项目:">
6
+          <el-input v-model="detail.name"></el-input>
7
+        </el-form-item>
8
+        <el-form-item label="客户照片:">
9
+        <el-upload
10
+            :action="upFileUrl"
11
+            name='file'
12
+            list-type="picture-card"
13
+            :headers="uploadHeaders"
14
+            :file-list="imgList"
15
+            :show-file-list="true"
16
+            :before-upload="beforeImgUpload"
17
+            :on-success="handleAvatarSuccess"
18
+            :on-remove="handleRemove">
19
+            <i class="el-icon-plus"></i>
20
+          </el-upload>
21
+          <el-dialog :visible.sync="dialogVisible">
22
+            <img width="100%" :src="dialogImageUrl" alt="">
23
+          </el-dialog>
24
+      </el-form-item>
25
+        <el-form-item label="客户姓名:">
26
+          <el-input v-model="detail.company"></el-input>
27
+        </el-form-item>
28
+        <el-form-item label="客户电话:">
29
+          <el-input v-model="detail.department"></el-input>
30
+        </el-form-item>
31
+        <el-form-item label="客户性别:">
32
+          <el-radio-group v-model="detail.isMain">
33
+            <el-radio :label="1">男</el-radio>
34
+            <el-radio :label="0">女</el-radio>
35
+          </el-radio-group>
36
+        </el-form-item>
37
+        <el-form-item label="预约到访时间:">
38
+          <el-input v-model="detail.department"></el-input>
39
+        </el-form-item>
40
+        <el-form-item label="到访人数:">
41
+          <el-input v-model="detail.department"></el-input>
42
+        </el-form-item>
43
+        <el-form-item label="客户描述:">
44
+            <el-input type="textarea" :rows="5"  v-model="detail.introduction"></el-input>
45
+        </el-form-item>
46
+        <el-form-item label="物业类型:">
47
+          <el-input v-model="detail.department"></el-input>
48
+        </el-form-item>
49
+        <el-form-item label="需求类型:">
50
+          <el-input v-model="detail.department"></el-input>
51
+        </el-form-item>
52
+        <el-form-item label="价格区间:">
53
+          <el-input v-model="detail.department"></el-input>
54
+        </el-form-item>
55
+        <el-form-item label="状态:">
56
+          <el-select v-model="detail.buildings" placeholder="请选择">
57
+            <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
58
+          </el-select>
59
+        </el-form-item>
60
+        <el-form-item>
61
+          <el-button type="primary" @click="submitForm">保存</el-button>
62
+          <el-button @click="$router.go(-1)">返回</el-button>
63
+        </el-form-item>
64
+      </el-form>
65
+    </div>
66
+  </div>
67
+</template>
68
+
69
+<script>
70
+import { createNamespacedHelpers } from "vuex";
71
+import apis from "../../config/api";
72
+import E from "wangeditor";
73
+
74
+const { mapActions: mapPersonActions } = createNamespacedHelpers("persons");
75
+const {
76
+  mapState: mapBuildingState,
77
+  mapActions: mapBuildingActions
78
+} = createNamespacedHelpers("building");
79
+export default {
80
+  name: "consultantEdit",
81
+  data() {
82
+    return {
83
+      upFileUrl: apis.file.upload.url,
84
+      detail: {
85
+        name: undefined,
86
+        company: undefined,
87
+        department: undefined,
88
+        post: undefined,
89
+        tel: undefined,
90
+        photo: undefined,
91
+        status: 1,
92
+        buildings: []
93
+      },
94
+      imgList: [],
95
+      dialogVisible: false,
96
+      dialogImageUrl: "",
97
+      
98
+    };
99
+  },
100
+  created() {
101
+    this.init();
102
+  },
103
+  computed: {
104
+    ...mapBuildingState({
105
+      buildings: x => x.buildings
106
+    }),
107
+    uploadHeaders() {
108
+      const token = localStorage.getItem("x-token") || "";
109
+      return {
110
+        Authorization: `Bearer ${token}`
111
+      };
112
+    }
113
+  },
114
+  methods: {
115
+    ...mapBuildingActions(["getBuildings"]),
116
+    ...mapPersonActions(["getConsultant", "editConsultant"]),
117
+
118
+    init() {
119
+      if (this.$route.params.id) {
120
+        this.getConsultant({ id: this.$route.params.id }).then(data => {
121
+          this.detail = data;
122
+        });
123
+      }
124
+    },
125
+
126
+    beforeImgUpload(file) {
127
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
128
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
129
+        return false;
130
+      }
131
+      // if (file.size / 1024 > 300) {
132
+      //   this.$message.error('图片大小不允许超过300k!')
133
+      //   return false
134
+      // }
135
+      this.loading = this.$loading({
136
+        lock: true,
137
+        text: "上传中...",
138
+        spinner: "el-icon-loading",
139
+        background: "rgba(0, 0, 0, 0.7)"
140
+      });
141
+
142
+      return true;
143
+    },
144
+    handleAvatarSuccess(res) {
145
+      this.imgList = [
146
+        ...this.imgList,
147
+        {
148
+          url: res.data
149
+        }
150
+      ];
151
+      this.hideLoadding();
152
+    },
153
+    handleRemove(file, fileList) {
154
+      this.imgList = fileList;
155
+    },
156
+    submitForm() {
157
+      this.showLoadding("保存中...");
158
+      this.editConsultant(this.detail)
159
+        .then(res => {
160
+          if (res.personId) {
161
+            this.detail = res;
162
+          }
163
+
164
+          this.hideLoadding();
165
+          this.$notify.info("保存成功");
166
+        })
167
+        .catch(err => {
168
+          this.hideLoadding();
169
+          this.$notify.error(err.message);
170
+        });
171
+    },
172
+
173
+    showLoadding(text) {
174
+      this.loading = this.$loading({
175
+        text,
176
+        lock: true,
177
+        spinner: "el-icon-loading",
178
+        background: "rgba(255, 255, 255, 0.7)"
179
+      });
180
+    },
181
+
182
+    hideLoadding() {
183
+      if (this.loading) this.loading.close();
184
+    }
185
+  },
186
+  mounted() {
187
+    const _that = this;
188
+
189
+    this.getBuildings({
190
+      pageNum: 1,
191
+      pageSize: 100
192
+    }).then(() => {
193
+      if ((this.$route.query.id || "") !== "") {
194
+        this.getDetail({ id: this.$route.query.id }).then(data => {});
195
+      }
196
+    });
197
+  }
198
+};
199
+</script>
200
+
201
+<style lang="scss" scoped>
202
+.form-wrapper {
203
+  width: 60%;
204
+}
205
+</style>
206
+
207
+<style lang="scss">
208
+.avatar-uploader .el-upload {
209
+  border: 1px dashed #d9d9d9;
210
+  border-radius: 6px;
211
+  cursor: pointer;
212
+  position: relative;
213
+  overflow: hidden;
214
+}
215
+.avatar-uploader .el-upload:hover {
216
+  border-color: #409eff;
217
+}
218
+.avatar-uploader-icon {
219
+  font-size: 28px;
220
+  color: #8c939d;
221
+  width: 178px;
222
+  height: 178px;
223
+  line-height: 178px;
224
+  text-align: center;
225
+}
226
+.avatar {
227
+  width: 178px;
228
+  height: 178px;
229
+  display: block;
230
+}
231
+.choose {
232
+  color: blue;
233
+  margin-left: 15px;
234
+}
235
+</style>

+ 293
- 0
src/views/customer/editRecommend.vue Целия файл

@@ -0,0 +1,293 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="200px" :model="detail">
5
+        <el-form-item label="意向项目:">
6
+          <el-input v-model="detail.name"></el-input>
7
+        </el-form-item>
8
+        <el-form-item label="客户照片:">
9
+        <el-upload
10
+            :action="upFileUrl"
11
+            name='file'
12
+            list-type="picture-card"
13
+            :headers="uploadHeaders"
14
+            :file-list="imgList"
15
+            :show-file-list="true"
16
+            :before-upload="beforeImgUpload"
17
+            :on-success="handleAvatarSuccess"
18
+            :on-remove="handleRemove">
19
+            <i class="el-icon-plus"></i>
20
+          </el-upload>
21
+          <el-dialog :visible.sync="dialogVisible">
22
+            <img width="100%" :src="dialogImageUrl" alt="">
23
+          </el-dialog>
24
+      </el-form-item>
25
+        <el-form-item label="客户姓名:">
26
+          <el-input v-model="detail.company"></el-input>
27
+        </el-form-item>
28
+        <el-form-item label="客户电话:">
29
+          <el-input v-model="detail.department"></el-input>
30
+        </el-form-item>
31
+        <el-form-item label="客户性别:">
32
+          <el-radio-group v-model="detail.isMain">
33
+            <el-radio :label="1">男</el-radio>
34
+            <el-radio :label="0">女</el-radio>
35
+          </el-radio-group>
36
+        </el-form-item>
37
+        <el-form-item label="预约到访时间:">
38
+          <el-input v-model="detail.department"></el-input>
39
+        </el-form-item>
40
+        <el-form-item label="到访人数:">
41
+          <el-input v-model="detail.department"></el-input>
42
+        </el-form-item>
43
+        <el-form-item label="客户描述:">
44
+            <el-input type="textarea" :rows="5"  v-model="detail.introduction"></el-input>
45
+        </el-form-item>
46
+        <el-form-item label="物业类型:">
47
+          <el-input v-model="detail.department"></el-input>
48
+        </el-form-item>
49
+        <el-form-item label="需求类型:">
50
+          <el-input v-model="detail.department"></el-input>
51
+        </el-form-item>
52
+        <el-form-item label="价格区间:">
53
+          <el-input v-model="detail.department"></el-input>
54
+        </el-form-item>
55
+        <el-form-item label="报备日期:">
56
+          <el-input v-model="detail.department"></el-input>
57
+        </el-form-item>
58
+        <el-form-item label="状态:">
59
+          <el-select v-model="detail.buildings" placeholder="请选择">
60
+            <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
61
+          </el-select>
62
+        </el-form-item>
63
+        <el-form-item label="归属置业顾问:">
64
+          <p style="margin:0">{{consultant}}<span @click="dialogTableVisible=true" class="choose">请选择</span></p>
65
+        </el-form-item>
66
+        <el-form-item>
67
+          <el-button type="primary" @click="submitForm">修改并审核通过</el-button>
68
+          <el-button @click="$router.go(-1)">驳回</el-button>
69
+        </el-form-item>
70
+        <el-dialog title="选择置业顾问" :visible.sync="dialogTableVisible">
71
+      <el-table :data="gridData">
72
+        <el-table-column property="date" label="姓名"></el-table-column>
73
+        <el-table-column property="name" label="电话"></el-table-column>
74
+        <el-table-column property="name" label="部门"></el-table-column>
75
+        <el-table-column property="name" label="岗位"></el-table-column>
76
+        <el-table-column fixed="right" label="操作">
77
+          <template slot-scope="scope">
78
+            <el-button type="text" @click="handleDel(scope.row)" size="small">选择</el-button>
79
+          </template>
80
+        </el-table-column>
81
+      </el-table>
82
+    </el-dialog>
83
+      </el-form>
84
+    </div>
85
+  </div>
86
+</template>
87
+
88
+<script>
89
+import { createNamespacedHelpers } from "vuex";
90
+import apis from "../../config/api";
91
+import E from "wangeditor";
92
+
93
+const { mapActions: mapPersonActions } = createNamespacedHelpers("persons");
94
+const {
95
+  mapState: mapBuildingState,
96
+  mapActions: mapBuildingActions
97
+} = createNamespacedHelpers("building");
98
+export default {
99
+  name: "consultantEdit",
100
+  data() {
101
+    return {
102
+      upFileUrl: apis.file.upload.url,
103
+      detail: {
104
+        name: undefined,
105
+        company: undefined,
106
+        department: undefined,
107
+        post: undefined,
108
+        tel: undefined,
109
+        photo: undefined,
110
+        status: 1,
111
+        buildings: []
112
+      },
113
+      imgList: [],
114
+      dialogVisible: false,
115
+      dialogImageUrl: "",
116
+      dialogTableVisible: false, //选择置业顾问弹框
117
+      consultant:"",
118
+      gridData: [
119
+        {
120
+          date: "2016-05-02",
121
+          name: "王小虎"
122
+        },
123
+        {
124
+          date: "2016-05-04",
125
+          name: "王小虎"
126
+        },
127
+        {
128
+          date: "2016-05-01",
129
+          name: "王小虎"
130
+        },
131
+        {
132
+          date: "2016-05-03",
133
+          name: "王小虎"
134
+        }
135
+      ]
136
+    };
137
+  },
138
+  created() {
139
+    this.init();
140
+  },
141
+  computed: {
142
+    ...mapBuildingState({
143
+      buildings: x => x.buildings
144
+    }),
145
+    uploadHeaders() {
146
+      const token = localStorage.getItem("x-token") || "";
147
+      return {
148
+        Authorization: `Bearer ${token}`
149
+      };
150
+    }
151
+  },
152
+  methods: {
153
+    ...mapBuildingActions(["getBuildings"]),
154
+    ...mapPersonActions(["getConsultant", "editConsultant"]),
155
+
156
+    init() {
157
+      if (this.$route.params.id) {
158
+        this.getConsultant({ id: this.$route.params.id }).then(data => {
159
+          this.detail = data;
160
+        });
161
+      }
162
+    },
163
+    handleDel(row) {
164
+      this.$confirm("确定选择此置业顾问?", "提示", {
165
+        confirmButtonText: "确定",
166
+        cancelButtonText: "取消",
167
+        type: "warning"
168
+      })
169
+        .then(() => {
170
+          this.$message({
171
+            type: "success",
172
+            message: "选择成功!"
173
+          });
174
+          this.consultant = row.name
175
+          this.dialogTableVisible = false;
176
+        })
177
+        .catch(() => {
178
+          this.$message({
179
+            type: "info",
180
+            message: "已取消选择"
181
+          });
182
+        });
183
+    },
184
+    beforeImgUpload(file) {
185
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
186
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
187
+        return false;
188
+      }
189
+      // if (file.size / 1024 > 300) {
190
+      //   this.$message.error('图片大小不允许超过300k!')
191
+      //   return false
192
+      // }
193
+      this.loading = this.$loading({
194
+        lock: true,
195
+        text: "上传中...",
196
+        spinner: "el-icon-loading",
197
+        background: "rgba(0, 0, 0, 0.7)"
198
+      });
199
+
200
+      return true;
201
+    },
202
+    handleAvatarSuccess(res) {
203
+      this.imgList = [
204
+        ...this.imgList,
205
+        {
206
+          url: res.data
207
+        }
208
+      ];
209
+      this.hideLoadding();
210
+    },
211
+    handleRemove(file, fileList) {
212
+      this.imgList = fileList;
213
+    },
214
+    submitForm() {
215
+      this.showLoadding("保存中...");
216
+      this.editConsultant(this.detail)
217
+        .then(res => {
218
+          if (res.personId) {
219
+            this.detail = res;
220
+          }
221
+
222
+          this.hideLoadding();
223
+          this.$notify.info("保存成功");
224
+        })
225
+        .catch(err => {
226
+          this.hideLoadding();
227
+          this.$notify.error(err.message);
228
+        });
229
+    },
230
+
231
+    showLoadding(text) {
232
+      this.loading = this.$loading({
233
+        text,
234
+        lock: true,
235
+        spinner: "el-icon-loading",
236
+        background: "rgba(255, 255, 255, 0.7)"
237
+      });
238
+    },
239
+
240
+    hideLoadding() {
241
+      if (this.loading) this.loading.close();
242
+    }
243
+  },
244
+  mounted() {
245
+    const _that = this;
246
+
247
+    this.getBuildings({
248
+      pageNum: 1,
249
+      pageSize: 100
250
+    }).then(() => {
251
+      if ((this.$route.query.id || "") !== "") {
252
+        this.getDetail({ id: this.$route.query.id }).then(data => {});
253
+      }
254
+    });
255
+  }
256
+};
257
+</script>
258
+
259
+<style lang="scss" scoped>
260
+.form-wrapper {
261
+  width: 60%;
262
+}
263
+</style>
264
+
265
+<style lang="scss">
266
+.avatar-uploader .el-upload {
267
+  border: 1px dashed #d9d9d9;
268
+  border-radius: 6px;
269
+  cursor: pointer;
270
+  position: relative;
271
+  overflow: hidden;
272
+}
273
+.avatar-uploader .el-upload:hover {
274
+  border-color: #409eff;
275
+}
276
+.avatar-uploader-icon {
277
+  font-size: 28px;
278
+  color: #8c939d;
279
+  width: 178px;
280
+  height: 178px;
281
+  line-height: 178px;
282
+  text-align: center;
283
+}
284
+.avatar {
285
+  width: 178px;
286
+  height: 178px;
287
+  display: block;
288
+}
289
+.choose {
290
+  color: blue;
291
+  margin-left: 15px;
292
+}
293
+</style>

+ 145
- 0
src/views/customer/integralRecord.vue Целия файл

@@ -0,0 +1,145 @@
1
+<template>
2
+  <div>
3
+    <h5>当前可用积分:200</h5>
4
+    <el-table
5
+      :data="dynamics.list || []"
6
+      >
7
+      <el-table-column
8
+        type="index">
9
+        <template slot-scope="scope">
10
+          <span>{{ GetIndex(scope.$index) }}</span>
11
+        </template>
12
+      </el-table-column>
13
+      <el-table-column
14
+        prop="title"
15
+        label="积分类型">
16
+      </el-table-column>
17
+      <el-table-column
18
+        prop="title"
19
+        label="积分变化">
20
+      </el-table-column>
21
+      <el-table-column
22
+        prop="createDate"
23
+        label="发生时间">
24
+      </el-table-column>
25
+    </el-table>
26
+    <el-pagination
27
+      small
28
+      style="margin-top:10px;"
29
+      layout="prev, pager, next"
30
+      :current-page.sync="currentPage"
31
+      :pageSize="pageSize"
32
+      :total="dynamics.total || 0"
33
+      @current-change="getList"
34
+    >
35
+    </el-pagination>
36
+  </div>
37
+</template>
38
+
39
+<script>
40
+import { createNamespacedHelpers } from "vuex";
41
+
42
+const {
43
+  mapState: mapDynamicState,
44
+  mapActions: mapDynamicActions
45
+} = createNamespacedHelpers("dynamic");
46
+const {
47
+  mapState: mapBuildingState,
48
+  mapActions: mapBuildingActions
49
+} = createNamespacedHelpers("building");
50
+
51
+export default {
52
+  data() {
53
+    return {
54
+      pageSize: 20,
55
+      currentPage: 1,
56
+      name: "",
57
+      buildingId: "",
58
+    };
59
+  },
60
+  computed: {
61
+    ...mapDynamicState({
62
+      dynamics: x => x.dynamics
63
+    }),
64
+    ...mapBuildingState({
65
+      buildings: x => x.buildings
66
+    })
67
+  },
68
+  methods: {
69
+    ...mapDynamicActions([
70
+      "getDynamics",
71
+      "setDetailNull",
72
+      "deleteDynamics",
73
+      "publicDynamic",
74
+      "cancelDynamic"
75
+    ]),
76
+    ...mapBuildingActions(["getBuildings"]),
77
+    GetIndex(inx) {
78
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
79
+    },
80
+    FormatDate(date) {
81
+      if (date) {
82
+        return dayjs(date).formate("yyyy-MM-DD HH:mm:ss");
83
+      } else {
84
+        return "";
85
+      }
86
+    },
87
+    getList() {
88
+      this.getDynamics({
89
+        pageNum: this.currentPage,
90
+        pageSize: this.pageSize,
91
+        name: this.name,
92
+        buildingId: this.buildingId
93
+      });
94
+    },
95
+    getBuildingName(id) {
96
+      return (
97
+        ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {})
98
+          .buildingName || ""
99
+      );
100
+    },
101
+  
102
+  },
103
+  created() {
104
+    this.getBuildings({
105
+      pageNum: 1,
106
+      pageSize: 100
107
+    }).then(() => {
108
+      this.getList();
109
+    });
110
+  }
111
+};
112
+</script>
113
+
114
+<style lang="scss" scoped>
115
+.header {
116
+  width: 50px;
117
+  height: 50px;
118
+  img {
119
+    width: 100%;
120
+    height: 100%;
121
+  }
122
+}
123
+
124
+.el-dialog{
125
+  z-index: 9999!important;
126
+  .el-form-item__content{
127
+    p{
128
+      margin: 0;
129
+    }
130
+  }
131
+}
132
+
133
+
134
+.flex-h {
135
+  display: flex;
136
+  display: -webkit-flex;
137
+}
138
+
139
+.flex-item {
140
+  flex: 1;
141
+  -webkit-flex: 1;
142
+  position: relative;
143
+  overflow: hidden;
144
+}
145
+</style>

+ 225
- 121
src/views/customer/list.vue Целия файл

@@ -1,21 +1,31 @@
1 1
 <template>
2
-  <div>
2
+  <div class="list">
3 3
     <div class="system-table-search">
4 4
       <div class="flex-h">
5 5
         <ul>
6 6
           <li>
7
-            <el-input v-model="name" placeholder="客户姓名"></el-input>
7
+            <span>姓名</span>
8
+            <el-input v-model="name" ></el-input>
9
+          </li>
10
+          <li>
11
+            <span>电话</span>
12
+            <el-input v-model="name" ></el-input>
13
+          </li>
14
+          <li>
15
+            <span>置业顾问</span>
16
+            <el-input v-model="name" ></el-input>
17
+          </li>
18
+          <li>
19
+            <span>置业顾问电话</span>
20
+            <el-input v-model="name" ></el-input>
8 21
           </li>
9 22
         </ul>
10 23
         <el-button
11 24
           size="mini"
12
-          type="primary" @click="search">搜索</el-button>
25
+          type="primary" @click="search">查询</el-button>
13 26
       </div>
14
-      <div class="moreFilter"></div>
15 27
     </div>
16
-    <el-table
17
-
18
-      style="width: 100%">
28
+    <el-table :data="dynamics.list || []" style="width: 100%">
19 29
       <el-table-column
20 30
         type="index"
21 31
         width="50">
@@ -24,70 +34,65 @@
24 34
         </template>
25 35
       </el-table-column>
26 36
       <el-table-column
27
-        label="照片">
37
+        label="头像">
28 38
         <template slot-scope="scope">
29 39
           <div class="header">
30
-            <img :src="scope.row.picture" alt="" />
40
+            <img :src="scope.row.imgUrl" alt="" />
31 41
           </div>
32 42
         </template>
33 43
       </el-table-column>
34 44
       <el-table-column
35
-        prop="name"
45
+        prop="title"
36 46
         label="姓名">
37 47
       </el-table-column>
38
-      <el-table-column
39
-        prop="sex"
40
-        label="性别">
41
-      </el-table-column>
42 48
       <el-table-column
43 49
         prop="phone"
44 50
         label="电话">
45 51
       </el-table-column>
46 52
       <el-table-column
47
-        prop="describe"
48
-        label="描述">
49
-      </el-table-column>
50
-      <el-table-column
51
-        prop="appointmentTime"
52
-        label="预约时间">
53
-      </el-table-column>
54
-      <el-table-column
55
-        prop="visiteNum"
56
-        label="到访人数">
57
-      </el-table-column>
58
-      <el-table-column
59
-        prop="intention"
60
-        label="意向项目">
61
-      </el-table-column>
62
-      <el-table-column
63
-        prop="buildingId"
64
-        label="项目ID">
65
-      </el-table-column>
66
-      <el-table-column
67
-        prop="realtyManageType"
68
-        label="物业类型">
69
-      </el-table-column>
70
-      <el-table-column
71
-        prop="demandType"
72
-        label="需求类型">
73
-      </el-table-column>
74
-      <el-table-column
75
-        prop="priceRange"
76
-        label="价格区间">
77
-      </el-table-column>
78
-      <el-table-column
79
-        prop="reportDate"
80
-        label="报备日期">
53
+        prop="sex"
54
+        label="性别">
81 55
       </el-table-column>
82
-      <el-table-column
83
-        prop="status"
84
-        label="状态">
56
+      <el-table-column   label="置业顾问">
57
+        <template slot-scope="scope">
58
+          <span>{{scope.row.desc}}</span>
59
+          <p>{{scope.row.tel}}</p>
60
+        </template>
85 61
       </el-table-column>
86
-      <el-table-column
87
-        prop="personId"
88
-        label="推荐人">
62
+      <el-table-column fixed="right" width="300" label="操作">
63
+        <template slot-scope="scope">
64
+          <el-button type="text" @click="toEditCustomer(scope.row)"   size="small">编辑</el-button>
65
+          <el-button type="text" @click="adjustment(scope.row)" size="small">调整归属</el-button>
66
+          <el-button type="text" @click="toIntegralRecord(scope.row)" size="small">积分记录</el-button>
67
+          <el-button type="text" @click="recommend(scope.row)" size="small">推荐客户</el-button>
68
+          <el-button type="text" size="small" @click="toDetail(scope.row)">查看详情</el-button>
69
+        </template>
89 70
       </el-table-column>
90 71
     </el-table>
72
+    <el-dialog title="选择置业顾问" :visible.sync="dialogTableVisible">
73
+      <el-table :data="gridData">
74
+        <el-table-column property="date" label="姓名"></el-table-column>
75
+        <el-table-column property="name" label="电话"></el-table-column>
76
+        <el-table-column property="name" label="部门"></el-table-column>
77
+        <el-table-column property="name" label="岗位"></el-table-column>
78
+        <el-table-column fixed="right" label="操作">
79
+          <template slot-scope="scope">
80
+            <el-button type="text" @click="handleDel(scope.row)" size="small">选择</el-button>
81
+          </template>
82
+        </el-table-column>
83
+      </el-table>
84
+    </el-dialog>
85
+    <el-dialog title="推荐客户" :visible.sync="dialogRecommendVisible">
86
+      <el-table :data="gridData">
87
+        <el-table-column property="date" label="姓名"></el-table-column>
88
+        <el-table-column property="name" label="电话"></el-table-column>
89
+        <el-table-column property="name" label="性别"></el-table-column>
90
+        <el-table-column property="name" label="意向项目"></el-table-column>
91
+        <el-table-column property="name" label="推荐时间"></el-table-column>
92
+        <el-table-column property="name" label="状态"></el-table-column>
93
+      </el-table>
94
+       <el-button type="primary" class="close-btn"  @click="dialogRecommendVisible=false" >关闭</el-button>
95
+    </el-dialog>
91 96
     <el-pagination
92 97
       small
93 98
       style="margin-top:10px;"
@@ -100,107 +105,206 @@
100 105
   </div>
101 106
 </template>
102 107
 <script>
103
-import { createNamespacedHelpers } from 'vuex';
104
-const {mapState:mapCustomerState,mapActions:mapCustomerActions} = createNamespacedHelpers('customer');
108
+import { createNamespacedHelpers } from "vuex";
109
+const {
110
+  mapState: mapDynamicState,
111
+  mapActions: mapDynamicActions
112
+} = createNamespacedHelpers("dynamic");
113
+const {
114
+  mapState: mapCustomerState,
115
+  mapActions: mapCustomerActions
116
+} = createNamespacedHelpers("customer");
105 117
 export default {
106 118
   data() {
107
-    return{
119
+    return {
108 120
       pageSize: 20,
109 121
       currentPage: 1,
110
-      name: '',
111
-      sex:'',
112
-      phone:'',
113
-      picture:'',
114
-      describe:'',
115
-      appointmentTime:'',
116
-      visiteNum:'',
117
-      intention:'',
118
-      buildingId:'',
119
-      realtyManageType:'',
120
-      demandType:'',
121
-      priceRange:'',
122
-      reportDate:'',
123
-      status:'',
124
-      personId:''
125
-    }
122
+      name: "",
123
+      sex: "",
124
+      phone: "",
125
+      picture: "",
126
+      describe: "",
127
+      appointmentTime: "",
128
+      visiteNum: "",
129
+      intention: "",
130
+      buildingId: "",
131
+      realtyManageType: "",
132
+      demandType: "",
133
+      priceRange: "",
134
+      reportDate: "",
135
+      status: "",
136
+      personId: "",
137
+      dialogTableVisible: false, //调整归属弹框
138
+      dialogRecommendVisible: false, //推荐客户弹框
139
+      gridData: [
140
+        {
141
+          date: "2016-05-02",
142
+          name: "王小虎"
143
+        },
144
+        {
145
+          date: "2016-05-04",
146
+          name: "王小虎"
147
+        },
148
+        {
149
+          date: "2016-05-01",
150
+          name: "王小虎"
151
+        },
152
+        {
153
+          date: "2016-05-03",
154
+          name: "王小虎"
155
+        }
156
+      ]
157
+    };
126 158
   },
127
-  computed:{
159
+  computed: {
128 160
     ...mapCustomerState({
129 161
       customers: x => x.customers
130 162
     }),
163
+    ...mapDynamicState({
164
+      dynamics: x => x.dynamics
165
+    })
166
+  },
167
+  created() {
168
+    this.getList();
131 169
   },
132
-  methods:{
133
-    ...mapCustomerActions([
134
-      'getCustomers',
135
-      'getDetail'
170
+  methods: {
171
+    ...mapCustomerActions(["getCustomers", "getDetail"]),
172
+    ...mapDynamicActions([
173
+      "getDynamics",
174
+      "setDetailNull",
175
+      "deleteDynamics",
176
+      "publicDynamic",
177
+      "cancelDynamic"
136 178
     ]),
137
-    GetIndex (inx) {
138
-      return (this.currentPage - 1) * this.pageSize + inx + 1
179
+    GetIndex(inx) {
180
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
139 181
     },
140
-    getList () {
141
-      this.getCustomers({
182
+    getList() {
183
+      this.getDynamics({
142 184
         pageNum: this.currentPage,
143 185
         pageSize: this.pageSize,
144
-        name:this.name,
145
-        sex:this.sex,
146
-        phone:this.phone,
147
-        picture:this.picture,
148
-        describe:this.describe,
149
-        appointmentTime:this.appointmentTime,
150
-        visiteNum:this.visiteNum,
151
-        intention:this.intention,
152
-        buildingId:this.buildingId,
153
-        realtyManageType:this.realtyManageType,
154
-        demandType:this.demandType,
155
-        priceRange:this.priceRange,
156
-        reportDate:this.reportDate,
157
-        status:this.status,
158
-        personId:this.personId
186
+        name: this.name,
187
+        buildingId: this.buildingId
188
+      });
189
+    },
190
+    // 进入编辑页
191
+    toEditCustomer(row) {
192
+      this.$router.push({
193
+        name: "editCustomer",
194
+        params: { id: row.personId }
195
+      });
196
+    },
197
+    // 进入积分记录页
198
+    toIntegralRecord(row) {
199
+      this.$router.push({
200
+        name: "integralRecord",
201
+        params: { id: row.personId }
202
+      });
203
+    },
204
+    // 调整归属
205
+    adjustment(row) {
206
+      this.dialogTableVisible = true;
207
+    },
208
+    // 推荐客户
209
+    recommend(row) {
210
+      this.dialogRecommendVisible = true;
211
+    },
212
+    handleDel(row) {
213
+      this.$confirm("确定选择此置业顾问?", "提示", {
214
+        confirmButtonText: "确定",
215
+        cancelButtonText: "取消",
216
+        type: "warning"
159 217
       })
218
+        .then(() => {
219
+          this.$message({
220
+            type: "success",
221
+            message: "选择成功!"
222
+          });
223
+          this.dialogTableVisible = false;
224
+        })
225
+        .catch(() => {
226
+          this.$message({
227
+            type: "info",
228
+            message: "已取消选择"
229
+          });
230
+        });
160 231
     },
161
-    search () {
162
-      this.currentPage = 1
163
-      this.getList()
232
+    // getList() {
233
+    // this.getCustomers({
234
+    // pageNum: this.currentPage,
235
+    // pageSize: this.pageSize,
236
+    // name: this.name,
237
+    // sex: this.sex,
238
+    // phone: this.phone,
239
+    // picture: this.picture,
240
+    // describe: this.describe,
241
+    // appointmentTime: this.appointmentTime,
242
+    // visiteNum: this.visiteNum,
243
+    // intention: this.intention,
244
+    // buildingId: this.buildingId,
245
+    // realtyManageType: this.realtyManageType,
246
+    // demandType: this.demandType,
247
+    // priceRange: this.priceRange,
248
+    // reportDate: this.reportDate,
249
+    // status: this.status,
250
+    // personId: this.personId
251
+    // });
252
+    // },
253
+    search() {
254
+      this.currentPage = 1;
255
+      this.getList();
164 256
     },
165
-    created () {
166
-      this.getList()
257
+    toDetail(row) {
258
+      this.$router.push({
259
+        name: "consultant.edit",
260
+        params: { id: row.personId }
261
+      });
167 262
     }
168 263
   }
169
-}
264
+};
170 265
 </script>
171 266
 <style lang="scss" scoped>
172
-.list{
173
-    .header{
174
-      width: 50px;
175
-      height: 50px;
176
-      img{
177
-        width: 100%;
178
-        height: 100%;
179
-      }
267
+.list {
268
+  .header {
269
+    width: 50px;
270
+    height: 50px;
271
+    img {
272
+      width: 100%;
273
+      height: 100%;
180 274
     }
181 275
   }
276
+}
182 277
 
183
-.system-table-search{
278
+.system-table-search {
184 279
   width: calc(100% - 40px);
185
-  margin: 20px auto 0;
280
+  margin: 16px auto 0;
186 281
 }
187 282
 
188
-.system-table-search li{
283
+.system-table-search ul > li {
189 284
   margin-right: 20px;
285
+  display: flex;
286
+  float: left;
287
+  align-items: center;
288
+  span {
289
+    margin-right: 10px;
290
+  }
190 291
 }
191 292
 
192
-.system-table-search ul{
193
-  font-size: 0;
293
+.system-table-search ul {
294
+  font-size: 15px;
194 295
   white-space: nowrap;
296
+  padding: 0;
195 297
 }
196 298
 
197
-.system-table-search ul>li{
198
-  display: inline-block;
199
-}
200 299
 .flex-h {
201 300
   display: flex;
202
-  display: -webkit-flex;
203
-  justify-content:flex-end;
301
+  align-items: center;
302
+}
303
+.el-dialog__body{
304
+  text-align: center;
305
+  .close-btn{
306
+  margin:  20px auto 0 auto;
307
+}
204 308
 }
205 309
 
206 310
 .flex-item {

+ 274
- 0
src/views/customer/recommendCustomer.vue Целия файл

@@ -0,0 +1,274 @@
1
+<template>
2
+  <div class="list">
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <ul>
6
+          <li>
7
+            <span>姓名</span>
8
+            <el-input v-model="name" ></el-input>
9
+          </li>
10
+          <li>
11
+            <span>电话</span>
12
+            <el-input v-model="name" ></el-input>
13
+          </li>
14
+          <li>
15
+            <span>推荐人</span>
16
+            <el-input v-model="name" ></el-input>
17
+          </li>
18
+          <li>
19
+            <span>推荐人电话</span>
20
+            <el-input v-model="name" ></el-input>
21
+          </li>
22
+          <li>
23
+            <span>状态</span>
24
+            <el-select v-model="name" placeholder="请选择">
25
+              <el-option v-for="(item,i) in gridData || []" :key="i" :label="item.name" :value="item.id"></el-option>
26
+            </el-select>
27
+          </li>
28
+        </ul>
29
+        <el-button
30
+          size="mini"
31
+          type="primary" @click="search">查询</el-button>
32
+      </div>
33
+    </div>
34
+    <el-table :data="dynamics.list || []" style="width: 100%">
35
+      <el-table-column
36
+        type="index"
37
+        width="50">
38
+        <template slot-scope="scope">
39
+          <span>{{ GetIndex(scope.$index) }}</span>
40
+        </template>
41
+      </el-table-column>
42
+      <el-table-column
43
+        label="头像">
44
+        <template slot-scope="scope">
45
+          <div class="header">
46
+            <img :src="scope.row.imgUrl" alt="" />
47
+          </div>
48
+        </template>
49
+      </el-table-column>
50
+      <el-table-column
51
+        prop="title"
52
+        label="姓名">
53
+      </el-table-column>
54
+      <el-table-column
55
+        prop="phone"
56
+        label="电话">
57
+      </el-table-column>
58
+      <el-table-column
59
+        prop="sex"
60
+        width="100"
61
+        label="性别">
62
+      </el-table-column>
63
+      <el-table-column
64
+        prop="sex"
65
+        label="意向项目">
66
+      </el-table-column>
67
+      <el-table-column  label="推荐人">
68
+        <template slot-scope="scope">
69
+          <span>{{scope.row.name}}</span>
70
+          <p>{{scope.row.tel}}</p>
71
+        </template>
72
+      </el-table-column>
73
+      <el-table-column
74
+        prop="createDate"
75
+        label="推荐时间">
76
+      </el-table-column>
77
+      <el-table-column  label="状态">
78
+        <template slot-scope="scope">
79
+          <span>{{scope.row.status==1?'已通过':scope.row.status==0?'已驳回':'未审核'}}</span>
80
+        </template>
81
+      </el-table-column>
82
+      <el-table-column fixed="right" width="100" label="操作">
83
+        <template slot-scope="scope">
84
+          <el-button type="text" @click="toEditRecommend(scope.row)" size="small">{{scope.row.status==1?'查看详情':'审核'}}</el-button>
85
+        </template>
86
+      </el-table-column>
87
+    </el-table>
88
+    <el-pagination
89
+      small
90
+      style="margin-top:10px;"
91
+      layout="prev, pager, next"
92
+      :current-page.sync="currentPage"
93
+      :pageSize="pageSize"
94
+      @current-change="getList"
95
+    >
96
+    </el-pagination>
97
+  </div>
98
+</template>
99
+<script>
100
+import { createNamespacedHelpers } from "vuex";
101
+const {
102
+  mapState: mapDynamicState,
103
+  mapActions: mapDynamicActions
104
+} = createNamespacedHelpers("dynamic");
105
+const {
106
+  mapState: mapCustomerState,
107
+  mapActions: mapCustomerActions
108
+} = createNamespacedHelpers("customer");
109
+export default {
110
+  data() {
111
+    return {
112
+      pageSize: 20,
113
+      currentPage: 1,
114
+      name: "",
115
+      sex: "",
116
+      phone: "",
117
+      picture: "",
118
+      describe: "",
119
+      appointmentTime: "",
120
+      visiteNum: "",
121
+      intention: "",
122
+      buildingId: "",
123
+      realtyManageType: "",
124
+      demandType: "",
125
+      priceRange: "",
126
+      reportDate: "",
127
+      status: "",
128
+      personId: "",
129
+      gridData: [
130
+        {
131
+          date: "2016-05-02",
132
+          name: "王小虎",
133
+          id: "1"
134
+        },
135
+        {
136
+          date: "2016-05-04",
137
+          name: "王小虎",
138
+          id: "2"
139
+        },
140
+        {
141
+          date: "2016-05-01",
142
+          name: "王小虎",
143
+          id: "3"
144
+        },
145
+        {
146
+          date: "2016-05-03",
147
+          name: "王小虎",
148
+          id: "4"
149
+        }
150
+      ]
151
+    };
152
+  },
153
+  computed: {
154
+    ...mapCustomerState({
155
+      customers: x => x.customers
156
+    }),
157
+    ...mapDynamicState({
158
+      dynamics: x => x.dynamics
159
+    })
160
+  },
161
+  created() {
162
+    this.getList();
163
+  },
164
+  methods: {
165
+    ...mapCustomerActions(["getCustomers", "getDetail"]),
166
+    ...mapDynamicActions([
167
+      "getDynamics",
168
+      "setDetailNull",
169
+      "deleteDynamics",
170
+      "publicDynamic",
171
+      "cancelDynamic"
172
+    ]),
173
+    GetIndex(inx) {
174
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
175
+    },
176
+    getList() {
177
+      this.getDynamics({
178
+        pageNum: this.currentPage,
179
+        pageSize: this.pageSize,
180
+        name: this.name,
181
+        buildingId: this.buildingId
182
+      });
183
+    },
184
+
185
+    // 进入积分记录页
186
+    toEditRecommend(row) {
187
+      this.$router.push({
188
+        name: "editRecommend",
189
+        params: { id: row.personId }
190
+      });
191
+    },
192
+
193
+    // getList() {
194
+    // this.getCustomers({
195
+    // pageNum: this.currentPage,
196
+    // pageSize: this.pageSize,
197
+    // name: this.name,
198
+    // sex: this.sex,
199
+    // phone: this.phone,
200
+    // picture: this.picture,
201
+    // describe: this.describe,
202
+    // appointmentTime: this.appointmentTime,
203
+    // visiteNum: this.visiteNum,
204
+    // intention: this.intention,
205
+    // buildingId: this.buildingId,
206
+    // realtyManageType: this.realtyManageType,
207
+    // demandType: this.demandType,
208
+    // priceRange: this.priceRange,
209
+    // reportDate: this.reportDate,
210
+    // status: this.status,
211
+    // personId: this.personId
212
+    // });
213
+    // },
214
+    search() {
215
+      this.currentPage = 1;
216
+      this.getList();
217
+    }
218
+  }
219
+};
220
+</script>
221
+<style lang="scss" scoped>
222
+.list {
223
+  .header {
224
+    width: 50px;
225
+    height: 50px;
226
+    img {
227
+      width: 100%;
228
+      height: 100%;
229
+    }
230
+  }
231
+}
232
+
233
+.system-table-search {
234
+  width: calc(100% - 40px);
235
+  margin: 16px auto 0;
236
+}
237
+
238
+.system-table-search ul > li {
239
+  margin-right: 20px;
240
+  display: flex;
241
+  float: left;
242
+  align-items: center;
243
+  margin-bottom: 10px;
244
+  span {
245
+    margin-right: 10px;
246
+  }
247
+}
248
+
249
+.system-table-search ul {
250
+  font-size: 15px;
251
+  white-space: nowrap;
252
+  padding: 0;
253
+}
254
+
255
+.flex-h {
256
+  display: flex;
257
+  align-items: center;
258
+}
259
+.el-dialog__body {
260
+  text-align: center;
261
+  .close-btn {
262
+    margin: 20px auto 0 auto;
263
+  }
264
+}
265
+
266
+.flex-item {
267
+  flex: 1;
268
+  -webkit-flex: 1;
269
+  position: relative;
270
+  overflow: hidden;
271
+}
272
+</style>
273
+
274
+

+ 268
- 0
src/views/exchange/list.vue Целия файл

@@ -0,0 +1,268 @@
1
+<template>
2
+<div class="list">
3
+        <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addGoods'>新增</el-button>
7
+        </div>
8
+        <el-form :inline="true">
9
+          <el-form-item v-model="filterData.personName" label="用户姓名">
10
+            <el-input placeholder="用户姓名"></el-input>
11
+          </el-form-item>
12
+          <el-form-item v-model="filterData.phone" label="手机号">
13
+            <el-input placeholder="手机号"></el-input>
14
+          </el-form-item>
15
+          <el-form-item label="用户类型">
16
+            <el-select v-model="filterData.personType" placeholder="用户类型">
17
+              <el-option label="置业顾问" value="Realty Consultant"></el-option>
18
+              <el-option label="销售主管" value="Sales Executive"></el-option>
19
+              <el-option label="经纪人" value="estate agent"></el-option>
20
+            </el-select>
21
+          </el-form-item>
22
+          <el-form-item v-model="filterData.targetName" label="商品名称">
23
+            <el-input placeholder="商品名称"></el-input>
24
+          </el-form-item>
25
+          <el-form-item label="兑换时间">
26
+            <el-date-picker
27
+                      v-model="filterData.startCreateDate"
28
+                      type="date"
29
+                      placeholder="开始时间">
30
+                    </el-date-picker>
31
+                    <el-date-picker
32
+                      v-model="filterData.endCreateDate"
33
+                      type="date"
34
+                      placeholder="结束时间">
35
+                    </el-date-picker>
36
+          </el-form-item>
37
+          <el-form-item label="领取时间">
38
+          <el-date-picker
39
+                      v-model="filterData.startVerifyDate"
40
+                      type="date"
41
+                      placeholder="开始时间">
42
+                    </el-date-picker>
43
+                    <el-date-picker
44
+                      v-model="filterData.endVerifyDate"
45
+                      type="date"
46
+                      placeholder="结束时间">
47
+                    </el-date-picker>
48
+          </el-form-item>
49
+          <el-form-item label="状态">
50
+            <el-select v-model="filterData.status" placeholder="状态">
51
+              <el-option label="已领取" value="1"></el-option>
52
+              <el-option label="未领取" value="0"></el-option>
53
+            </el-select>
54
+          </el-form-item>
55
+      <el-form-item>
56
+      <el-button type="primary" @click="search">查询</el-button>
57
+  </el-form-item>
58
+</el-form>    
59
+      </div>
60
+      <div class="moreFilter"></div>
61
+    </div>
62
+  <el-table
63
+    :data="list || []"
64
+    style="width: 100%">
65
+    <el-table-column
66
+      prop="personName"
67
+      label="用户姓名">
68
+    </el-table-column>
69
+    <el-table-column
70
+      label="用户类型">
71
+      <template slot-scope="scope">
72
+          <span v-if="scope.row.personType === 'Realty Consultant'">置业顾问</span>
73
+          <span v-if="scope.row.personType === 'Sales Executive'">销售主管</span>
74
+          <span v-if="scope.row.personType === 'estate agent'">经纪人</span>
75
+      </template>
76
+    </el-table-column>
77
+    <el-table-column
78
+      prop="phone"
79
+      label="手机号">
80
+    </el-table-column>
81
+    <el-table-column
82
+      label="商品图片">
83
+      <template slot-scope="scope">
84
+          <div class="header">
85
+            <img :src="scope.row.image" alt="" />
86
+          </div>
87
+        </template>
88
+    </el-table-column>
89
+    <el-table-column
90
+      prop="targetName"
91
+      label="商品名称">
92
+    </el-table-column>
93
+    <el-table-column
94
+      label="兑换时间">
95
+      <template slot-scope="scope">
96
+          <span>{{formateDate(scope.row.createDate)}}</span>
97
+      </template>
98
+    </el-table-column>
99
+    <el-table-column
100
+      label="领取时间">
101
+      <template slot-scope="scope">
102
+          <span>{{formateDate(scope.row.verifyDate)}}</span>
103
+      </template>
104
+    </el-table-column>
105
+    <el-table-column   label="状态">
106
+      <template slot-scope="scope">
107
+        <span :style="{color:(scope.row.status == 1?'':'red')}" >{{scope.row.status == 1 ? '已领取' : '未领取'}}</span>
108
+      </template>
109
+    </el-table-column>
110
+  </el-table>
111
+  <el-pagination
112
+    small
113
+    style="margin-top:10px;"
114
+    layout="prev, pager, next"
115
+    :current-page.sync="pageNavi.current"
116
+    :pageSize="pageNavi.size"
117
+    :total="pageNavi.total || 0"
118
+    @current-change="getList"
119
+  >
120
+  </el-pagination>
121
+</div>
122
+</template>
123
+
124
+<script>
125
+import { createNamespacedHelpers } from "vuex";
126
+import dayjs from 'dayjs'
127
+
128
+const { mapActions: mapExchangeActions } = createNamespacedHelpers("exchange");
129
+
130
+export default {
131
+  name: "goods-list",
132
+  data() {
133
+    return {
134
+      filterData: {
135
+        personName: "",
136
+        phone: "",
137
+        personType: "",
138
+        targetName: "",
139
+        startCreateDate: "",
140
+        endCreateDate: "",
141
+        startVerifyDate: "",
142
+        endVerifyDate: "",
143
+        status: "",
144
+      },
145
+      list: [],
146
+      pageNavi: {
147
+        current: 1,
148
+        size: 20,
149
+        total: 0
150
+      }
151
+    };
152
+  },
153
+  computed: {},
154
+  methods: {
155
+    ...mapExchangeActions(["getExchanges"]),
156
+    getList() {
157
+      const pageNumber = this.pageNavi.current || 1;
158
+      const pageSize = this.pageNavi.size;
159
+
160
+      this.getExchanges({
161
+        ...this.filterData,
162
+        pageNumber,
163
+        pageSize
164
+      })
165
+        .then(res => {
166
+          const { records, ...pageNavi } = res;
167
+
168
+          this.list = records;
169
+          this.pageNavi = pageNavi;
170
+        })
171
+        .catch(err => {
172
+          this.$notify.error(err.msg || err.message);
173
+        });
174
+    },
175
+    addGoods() {
176
+      this.$router.push({ name: "goods.edit" });
177
+    },
178
+    toDetail(row) {
179
+      this.$router.push({
180
+        name: "goods.edit",
181
+        params: { id: row.goodsId }
182
+      });
183
+    },
184
+    changeStatus(row) {
185
+      this.showLoadding("保存中...");
186
+      this.changeGoodsStatus(row)
187
+        .then(res => {
188
+          this.hideLoadding();
189
+          this.$notify.info("保存成功");
190
+          this.search();
191
+        })
192
+        .catch(err => {
193
+          this.hideLoadding();
194
+          this.$notify.error(err.message);
195
+        });
196
+    },
197
+    showLoadding(text) {
198
+      this.loading = this.$loading({
199
+        text,
200
+        lock: true,
201
+        spinner: "el-icon-loading",
202
+        background: "rgba(255, 255, 255, 0.7)"
203
+      });
204
+    },
205
+    hideLoadding() {
206
+      if (this.loading) this.loading.close();
207
+    },
208
+    search() {
209
+      this.pageNavi.current = 1;
210
+      this.getList();
211
+    },
212
+    newPage(page) {
213
+      this.$router.replace({ name: "goods.list", query: { page } });
214
+    },
215
+    formateDate(dt) {
216
+      return !dt ? '' : dayjs(dt).format('YYYY-MM-DD HH:mm')
217
+    },
218
+  },
219
+  created() {
220
+    this.pageNavi.current = this.$route.query.page || 1;
221
+
222
+    this.getList();
223
+  }
224
+};
225
+</script>
226
+
227
+<style lang="scss" scoped>
228
+.list {
229
+  .header {
230
+    width: 50px;
231
+    height: 50px;
232
+    border-radius: 50%;
233
+  }
234
+  img {
235
+      width: 100%;
236
+      height: 100%;
237
+    }
238
+}
239
+.system-table-search {
240
+  width: calc(100% - 40px);
241
+  margin: 20px auto 0;
242
+}
243
+
244
+.system-table-search li {
245
+  margin-right: 20px;
246
+}
247
+
248
+.system-table-search ul {
249
+  font-size: 0;
250
+  white-space: nowrap;
251
+}
252
+
253
+.system-table-search ul > li {
254
+  display: inline-block;
255
+}
256
+
257
+.flex-h {
258
+  display: flex;
259
+  align-items: center;
260
+}
261
+
262
+.flex-item {
263
+  flex: 1;
264
+  -webkit-flex: 1;
265
+  position: relative;
266
+  overflow: hidden;
267
+}
268
+</style>

+ 257
- 0
src/views/goods/edit.vue Целия файл

@@ -0,0 +1,257 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="100px" :model="detail">
5
+        <el-form-item label="项目">
6
+          <el-select v-model="detail.buildingId" placeholder="请选择">
7
+            <el-option
8
+                    v-for="item in buildingList"
9
+                    :key="item.buildingId"
10
+                    :label="item.buildingName"
11
+                    :value="item.buildingId">
12
+            </el-option>
13
+          </el-select>
14
+        </el-form-item>
15
+        <el-form-item label="商品图片:">
16
+          <el-upload
17
+                  :headers="uploadHeaders"
18
+                  :action="upFileUrl"
19
+                  :show-file-list="false"
20
+                  :on-success="handleAvatarSuccess">
21
+              <img v-if="detail.imgUrl" :src="detail.imgUrl" class="avatar">
22
+              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
23
+          </el-upload>
24
+        </el-form-item>
25
+        <el-form-item label="商品名称:">
26
+          <el-input v-model="detail.goodsName"></el-input>
27
+        </el-form-item>
28
+        <el-form-item label="所需积分:">
29
+          <el-input v-model="detail.pointPrice"></el-input>
30
+        </el-form-item>
31
+        <el-form-item label="商品数量:">
32
+          <el-input v-model="detail.totalNum"></el-input>
33
+        </el-form-item>
34
+        <el-form-item label="剩余数量:">
35
+          <el-input v-model="detail.inventory"></el-input>
36
+        </el-form-item>
37
+        <el-form-item label="商品详情:">
38
+            <div id="websiteEditorElem" style="height: 400px"></div>
39
+        </el-form-item>
40
+        <el-form-item label="状态:">
41
+          <el-select v-model="detail.status" clearable placeholder="请选择">
42
+            <el-option
43
+              v-for="item in options"
44
+              :key="item.value"
45
+              :label="item.label"
46
+              :value="item.value">
47
+            </el-option>
48
+          </el-select>
49
+        </el-form-item>
50
+        <el-form-item label="领取地址:">
51
+          <el-input v-model="detail.address"></el-input>
52
+        </el-form-item>
53
+        <el-form-item>
54
+          <el-button type="primary" @click="submitForm">保存</el-button>
55
+          <el-button @click="$router.go(-1)">返回</el-button>
56
+        </el-form-item>
57
+      </el-form>
58
+    </div>
59
+  </div>
60
+</template>
61
+
62
+<script>
63
+import { createNamespacedHelpers } from "vuex";
64
+import apis from "../../config/api";
65
+import E from "wangeditor";
66
+
67
+const { mapActions: mapGoodsActions } = createNamespacedHelpers("goods");
68
+const {
69
+  mapState: mapBuildingState,
70
+  mapActions: mapBuildingActions
71
+} = createNamespacedHelpers("building");
72
+export default {
73
+  name: "goodsEdit",
74
+  data() {
75
+    return {
76
+      upFileUrl: apis.file.upload.url,
77
+      detail: {
78
+        buildingId: '',
79
+        imgUrl: '',
80
+        goodsName: '',
81
+        pointPrice: '',
82
+        totalNum: '',
83
+        inventory: '',
84
+        status: 0,
85
+        address: '',
86
+        goodsId: '',
87
+      },
88
+      options: [{
89
+          value: 1,
90
+          label: '已上架'
91
+        }, {
92
+          value: 0,
93
+          label: '已下架'
94
+        }],
95
+      buildingList: [],
96
+    };
97
+  },
98
+  created() {
99
+    this.init();
100
+  },
101
+  computed: {
102
+    ...mapBuildingState({
103
+      buildings: x => x.buildings
104
+    }),
105
+    uploadHeaders () {
106
+        const token = localStorage.getItem('x-token') || ''
107
+        return {
108
+            Authorization: `Bearer ${token}`
109
+        }
110
+    }
111
+  },
112
+  methods: {
113
+    ...mapBuildingActions(["getBuildings"]),
114
+    ...mapGoodsActions(["getGoodsDetail", "editGoods", "addGoods"]),
115
+    init() {
116
+      this.detail.goodsId = this.$route.params.id
117
+      if (this.detail.goodsId !== undefined) {
118
+        this.getGoodsDetail({ id: this.$route.params.id }).then(data => {
119
+          this.detail.buildingId = data.buildingId
120
+          this.detail.imgUrl = data.imgUrl
121
+          this.detail.goodsName = data.goodsName
122
+          this.detail.pointPrice = data.pointPrice
123
+          this.detail.totalNum = data.totalNum
124
+          this.detail.inventory = data.inventory
125
+          this.detail.status = data.status
126
+          this.detail.address = data.address
127
+          this.detail.goodsId = data.goodsId
128
+        });
129
+      }
130
+    },
131
+    beforeImgUpload(file) {
132
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
133
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
134
+        return false;
135
+      }
136
+
137
+      this.showLoadding("上传中...");
138
+      return true;
139
+    },
140
+
141
+    handleAvatarSuccess(res, file) {
142
+        this.imageUrl = URL.createObjectURL(file.raw);
143
+        // console.log(res)
144
+        this.detail.imgUrl = res.data
145
+    },
146
+
147
+    submitForm() {
148
+      this.showLoadding("保存中...");
149
+      if (this.detail.goodsId === '' || this.detail.goodsId === undefined) {
150
+        console.log('添加')
151
+        this.addGoods(this.detail)
152
+        .then(res => {
153
+          this.hideLoadding();
154
+          this.$notify.info("保存成功");
155
+           this.$router.go(-1)
156
+        })
157
+        .catch(err => {
158
+          this.hideLoadding();
159
+          this.$notify.error(err.message);
160
+        });
161
+        return;
162
+      }
163
+      this.editGoods(this.detail)
164
+        .then(res => {
165
+          this.hideLoadding();
166
+          this.$notify.info("保存成功");
167
+           this.$router.go(-1)
168
+        })
169
+        .catch(err => {
170
+          this.hideLoadding();
171
+          this.$notify.error(err.message);
172
+        });
173
+    },
174
+
175
+    showLoadding(text) {
176
+      this.loading = this.$loading({
177
+        text,
178
+        lock: true,
179
+        spinner: "el-icon-loading",
180
+        background: "rgba(255, 255, 255, 0.7)"
181
+      });
182
+    },
183
+
184
+    hideLoadding() {
185
+      if (this.loading) this.loading.close();
186
+    }
187
+  },
188
+  mounted() {
189
+    const _that = this;
190
+    const phoneEditor = new E("#websiteEditorElem");
191
+    phoneEditor.customConfig.onchange = function(html) {
192
+      _that.dynamic = { ..._that.dynamic, url: html };
193
+    };
194
+    // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
195
+    // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
196
+
197
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
198
+      _that.uploadImg(files[0]).then(data => {
199
+        insert(data);
200
+      });
201
+    };
202
+    phoneEditor.customConfig.menus = [
203
+      "head", // 标题
204
+      "bold", // 粗体
205
+      "fontSize", // 字号
206
+      "fontName", // 字体
207
+      "italic", // 斜体
208
+      "underline", // 下划线
209
+      "strikeThrough", // 删除线
210
+      "foreColor", // 文字颜色
211
+      "backColor", // 背景颜色
212
+      "justify", // 对齐方式
213
+      "image" // 插入图片
214
+    ];
215
+    phoneEditor.create()
216
+
217
+    this.getBuildings({
218
+      pageNum: 1,
219
+      pageSize: 100
220
+    }).then((data) => {
221
+      this.buildingList = data.records;
222
+    });
223
+  }
224
+};
225
+</script>
226
+
227
+<style lang="scss" scoped>
228
+.form-wrapper {
229
+  width: 60%;
230
+}
231
+</style>
232
+
233
+<style lang="scss">
234
+.avatar-uploader .el-upload {
235
+  border: 1px dashed #d9d9d9;
236
+  border-radius: 6px;
237
+  cursor: pointer;
238
+  position: relative;
239
+  overflow: hidden;
240
+}
241
+.avatar-uploader .el-upload:hover {
242
+  border-color: #409eff;
243
+}
244
+.avatar-uploader-icon {
245
+  font-size: 28px;
246
+  color: #8c939d;
247
+  width: 178px;
248
+  height: 178px;
249
+  line-height: 178px;
250
+  text-align: center;
251
+}
252
+.avatar {
253
+  width: 178px;
254
+  height: 178px;
255
+  display: block;
256
+}
257
+</style>

+ 212
- 0
src/views/goods/list.vue Целия файл

@@ -0,0 +1,212 @@
1
+<template>
2
+<div class="list">
3
+        <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addGoods'>新增</el-button>
7
+        </div>
8
+        <ul>
9
+          <li>
10
+            <el-input v-model="filterData.goodsName" placeholder="商品名称"></el-input>
11
+          </li>
12
+
13
+        </ul>
14
+        <el-button
15
+          size="mini"
16
+          type="primary" @click="search">查询</el-button>
17
+      </div>
18
+      <div class="moreFilter"></div>
19
+    </div>
20
+  <el-table
21
+    :data="list || []"
22
+    style="width: 100%">
23
+    <el-table-column
24
+      label="商品图片">
25
+      <template slot-scope="scope">
26
+          <div class="header">
27
+            <img :src="scope.row.imgUrl" alt="" />
28
+          </div>
29
+        </template>
30
+    </el-table-column>
31
+    <el-table-column
32
+      prop="goodsName"
33
+      label="商品名称">
34
+    </el-table-column>
35
+    <el-table-column
36
+      prop="pointPrice"
37
+      label="所需积分">
38
+    </el-table-column>
39
+    <el-table-column
40
+      prop="totalNum"
41
+      label="总数量">
42
+    </el-table-column>
43
+    <el-table-column
44
+      label="已经兑换数量">
45
+      <template slot-scope="scope">
46
+        <span  >{{scope.row.totalNum -scope.row.inventory }}</span>
47
+      </template>
48
+    </el-table-column>
49
+    <el-table-column
50
+      prop="inventory"
51
+      label="剩余数量">
52
+    </el-table-column>
53
+    <el-table-column   label="状态">
54
+      <template slot-scope="scope">
55
+        <span :style="{color:(scope.row.status == 1?'':'red')}" >{{scope.row.status == 1 ? '已上架' : '未上架'}}</span>
56
+      </template>
57
+    </el-table-column>
58
+    <el-table-column
59
+      fixed="right"
60
+      label="操作">
61
+      <template slot-scope="scope">
62
+        <el-button type="text" @click="changeStatus(scope.row)" size="small">{{scope.row.status == 1?'下架':'上架'}}</el-button>
63
+        <el-button type="text" @click="toDetail(scope.row)" size="small">编辑</el-button>
64
+      </template>
65
+    </el-table-column>
66
+  </el-table>
67
+  <el-pagination
68
+    small
69
+    style="margin-top:10px;"
70
+    layout="prev, pager, next"
71
+    :current-page.sync="pageNavi.current"
72
+    :pageSize="pageNavi.size"
73
+    :total="pageNavi.total || 0"
74
+    @current-change="getList"
75
+  >
76
+  </el-pagination>
77
+</div>
78
+</template>
79
+
80
+<script>
81
+import { createNamespacedHelpers } from "vuex";
82
+
83
+const { mapActions: mapGoodsActions } = createNamespacedHelpers("goods");
84
+
85
+export default {
86
+  name: "goods-list",
87
+  data() {
88
+    return {
89
+      filterData: {
90
+        goodsName: ""
91
+      },
92
+      list: [],
93
+      pageNavi: {
94
+        current: 1,
95
+        size: 20,
96
+        total: 0
97
+      }
98
+    };
99
+  },
100
+  computed: {},
101
+  methods: {
102
+    ...mapGoodsActions(["getGoods", "changeGoodsStatus"]),
103
+    getList() {
104
+      const pageNumber = this.pageNavi.current || 1;
105
+      const pageSize = this.pageNavi.size;
106
+
107
+      this.getGoods({
108
+        ...this.filterData,
109
+        pageNumber,
110
+        pageSize
111
+      })
112
+        .then(res => {
113
+          const { records, ...pageNavi } = res;
114
+
115
+          this.list = records;
116
+          this.pageNavi = pageNavi;
117
+        })
118
+        .catch(err => {
119
+          this.$notify.error(err.msg || err.message);
120
+        });
121
+    },
122
+    addGoods() {
123
+      this.$router.push({ name: "goods.edit" });
124
+    },
125
+    toDetail(row) {
126
+      this.$router.push({
127
+        name: "goods.edit",
128
+        params: { id: row.goodsId }
129
+      });
130
+    },
131
+    changeStatus(row) {
132
+      this.showLoadding("保存中...");
133
+      this.changeGoodsStatus(row)
134
+        .then(res => {
135
+          this.hideLoadding();
136
+          this.$notify.info("保存成功");
137
+          this.search();
138
+        })
139
+        .catch(err => {
140
+          this.hideLoadding();
141
+          this.$notify.error(err.message);
142
+        });
143
+    },
144
+    showLoadding(text) {
145
+      this.loading = this.$loading({
146
+        text,
147
+        lock: true,
148
+        spinner: "el-icon-loading",
149
+        background: "rgba(255, 255, 255, 0.7)"
150
+      });
151
+    },
152
+    hideLoadding() {
153
+      if (this.loading) this.loading.close();
154
+    },
155
+    search() {
156
+      this.pageNavi.current = 1;
157
+      this.getList();
158
+    },
159
+    newPage(page) {
160
+      this.$router.replace({ name: "goods.list", query: { page } });
161
+    }
162
+  },
163
+  created() {
164
+    this.pageNavi.current = this.$route.query.page || 1;
165
+
166
+    this.getList();
167
+  }
168
+};
169
+</script>
170
+
171
+<style lang="scss" scoped>
172
+.list {
173
+  .header {
174
+    width: 50px;
175
+    height: 50px;
176
+    border-radius: 50%;
177
+  }
178
+  img {
179
+      width: 100%;
180
+      height: 100%;
181
+    }
182
+}
183
+.system-table-search {
184
+  width: calc(100% - 40px);
185
+  margin: 20px auto 0;
186
+}
187
+
188
+.system-table-search li {
189
+  margin-right: 20px;
190
+}
191
+
192
+.system-table-search ul {
193
+  font-size: 0;
194
+  white-space: nowrap;
195
+}
196
+
197
+.system-table-search ul > li {
198
+  display: inline-block;
199
+}
200
+
201
+.flex-h {
202
+  display: flex;
203
+  align-items: center;
204
+}
205
+
206
+.flex-item {
207
+  flex: 1;
208
+  -webkit-flex: 1;
209
+  position: relative;
210
+  overflow: hidden;
211
+}
212
+</style>

+ 262
- 3
src/views/index.js Целия файл

@@ -1,5 +1,5 @@
1 1
 
2
-const pages = [  
2
+const pages = [
3 3
   {
4 4
     path: 'dashboard',
5 5
     name: 'dashboard',
@@ -39,6 +39,35 @@ const pages = [
39 39
       },
40 40
     ]
41 41
   },
42
+  {
43
+    path: 'project',
44
+    name: 'project',
45
+    component: () => import('./index.vue'),
46
+    meta: {
47
+      menuShow: true,
48
+      title: '项目管理',
49
+    },
50
+    children: [
51
+      {
52
+        path: 'project',
53
+        name: 'project.list',
54
+        component: () => import('./project/list.vue'),
55
+        meta: {
56
+          menuShow: true,
57
+          title: '项目列表',
58
+        },
59
+      },
60
+      {
61
+        path: 'project/edit',
62
+        name: 'projectedit',
63
+        component: () => import('./project/edit.vue'),
64
+        meta: {
65
+          menuShow: false,
66
+          title: '项目编辑',
67
+        },
68
+      },
69
+    ]
70
+  },
42 71
   {
43 72
     path: 'building',
44 73
     name: 'building',
@@ -101,17 +130,247 @@ const pages = [
101 130
         meta: {
102 131
           menuShow: true,
103 132
           title: '客户列表',
133
+        }
134
+      },
135
+      {
136
+        path: 'recommendCustomer',
137
+        name: 'recommendCustomer',
138
+        component: () => import('./customer/recommendCustomer.vue'),
139
+        meta: {
140
+          menuShow: true,
141
+          title: '推荐客户',
142
+        }
143
+      },
144
+      {
145
+        path: 'editRecommend',
146
+        name: 'editRecommend',
147
+        component: () => import('./customer/editRecommend.vue'),
148
+        meta: {
149
+          menuShow: false,
150
+          title: '编辑',
104 151
         },
105
-      }
152
+      },
153
+      {
154
+        path: 'integralRecord',
155
+        name: 'integralRecord',
156
+        component: () => import('./customer/integralRecord.vue'),
157
+        meta: {
158
+          menuShow: false,
159
+          title: '积分记录',
160
+        },
161
+      },
162
+      {
163
+        path: 'editCustomer',
164
+        name: 'editCustomer',
165
+        component: () => import('./customer/editCustomer.vue'),
166
+        meta: {
167
+          menuShow: false,
168
+          title: '编辑',
169
+        },
170
+      },
171
+    ]
172
+  },
173
+  {
174
+    path: 'carouselFigure',
175
+    name: 'carouselFigure',
176
+    component: () => import('./index.vue'),
177
+    meta: {
178
+      menuShow: true,
179
+      title: '轮播图管理',
180
+    },
181
+    children: [
182
+      {
183
+        path: 'carouselList',
184
+        name: 'carouselList',
185
+        component: () => import('./carouselFigure/list.vue'),
186
+        meta: {
187
+          menuShow: true,
188
+          title: '轮播图列表',
189
+        }
190
+      },
191
+      {
192
+        path: 'editCarousel',
193
+        name: 'editCarousel',
194
+        component: () => import('./carouselFigure/edit.vue'),
195
+        meta: {
196
+          menuShow: false,
197
+          title: '编辑轮播图',
198
+        },
199
+      },
200
+      {
201
+        path: 'advertisement',
202
+        name: 'advertisement',
203
+        component: () => import('./carouselFigure/advertisement.vue'),
204
+        meta: {
205
+          menuShow: true,
206
+          title: '开屏广告',
207
+        }
208
+      },
209
+      {
210
+        path: 'advertisementEdit',
211
+        name: 'advertisementEdit',
212
+        component: () => import('./carouselFigure/advertisementEdit.vue'),
213
+        meta: {
214
+          menuShow: false,
215
+          title: '编辑开屏广告',
216
+        },
217
+
218
+
219
+      },
220
+
221
+    ]
222
+  },
223
+  {
224
+
225
+    path: 'systemManagement',
226
+    name: 'systemManagement',
227
+    component: () => import('./index.vue'),
228
+    meta: {
229
+      menuShow: true,
230
+      title: '系统管理',
231
+    },
232
+    children: [
233
+      {
234
+        path: 'pushMessage',
235
+        name: 'pushMessage',
236
+        component: () => import('./systemManagement/pushMessage.vue'),
237
+        meta: {
238
+          menuShow: true,
239
+          title: '推送消息',
240
+        },
241
+      },
242
+      {
243
+        path: 'keyWords',
244
+        name: 'keyWords',
245
+        component: () => import('./systemManagement/keyWords.vue'),
246
+        meta: {
247
+          menuShow: true,
248
+          title: '关键字维护',
249
+        },
250
+      },
251
+    ]
252
+  },
253
+  {
254
+    path: '/news',
255
+    name: 'news',
256
+    component: () => import('./index.vue'),
257
+    meta: {
258
+      menuShow: true,
259
+      title: '资迅管理',
260
+    },
261
+    children: [
262
+      {
263
+        path: '/news/type/list',
264
+        name: 'news-type-list',
265
+        component: () => import('./news/type/index.vue'),
266
+        meta: {
267
+          menuShow: true,
268
+          title: '资迅类型',
269
+        },
270
+      },
271
+      {
272
+        path: '/news/type/edi',
273
+        name: 'news-type-edi',
274
+        component: () => import('./news/type/edi/index.vue'),
275
+        meta: {
276
+          menuShow: false,
277
+          title: '编辑资迅类型',
278
+        },
279
+      },
280
+      {
281
+        path: '/news/list',
282
+        name: 'news-list',
283
+        component: () => import('./news/index.vue'),
284
+        meta: {
285
+          menuShow: true,
286
+          title: '资迅列表',
287
+        },
288
+      },
289
+      {
290
+        path: '/news/edi',
291
+        name: 'news-edi',
292
+        component: () => import('./news/edi/index.vue'),
293
+        meta: {
294
+          menuShow: false,
295
+          title: '编辑资迅',
296
+        },
297
+      },
106 298
     ]
107 299
   },
300
+  {
301
+    path: 'pointsmall',
302
+    name: 'pointsmall',
303
+    redirect: 'pointsmall/list',
304
+    component: () => import('./index.vue'),
305
+    meta: {
306
+      menuShow: true,
307
+      title: '积分商城',
308
+    },
309
+    children: [
310
+      {
311
+        path: 'list',
312
+        name: 'goods.list',
313
+        component: () => import('./goods/list.vue'),
314
+        meta: {
315
+          menuShow: true,
316
+          title: '商品列表',
317
+        },
318
+      },
319
+      {
320
+        path: 'goods/edit',
321
+        name: 'goods.edit',
322
+        component: () => import('./goods/edit.vue'),
323
+        meta: {
324
+          menuShow: false,
325
+          title: '编辑商品',
326
+        },
327
+      },
328
+      {
329
+        path: 'points/list',
330
+        name: 'points.list',
331
+        component: () => import('./points/list.vue'),
332
+        meta: {
333
+          menuShow: true,
334
+          title: '积分获取',
335
+        },
336
+      },
337
+      {
338
+        path: 'points/edit',
339
+        name: 'points.edit',
340
+        component: () => import('./points/edit.vue'),
341
+        meta: {
342
+          menuShow: false,
343
+          title: '积分编辑',
344
+        },
345
+      },
346
+      {
347
+        path: 'edit/:id?',
348
+        name: 'consultant.edit',
349
+        component: () => import('./consultant/edit.vue'),
350
+        meta: {
351
+          menuShow: true,
352
+          title: '商品核销',
353
+        },
354
+      },
355
+      {
356
+        path: 'exchange/list',
357
+        name: 'exchange.list',
358
+        component: () => import('./exchange/list.vue'),
359
+        meta: {
360
+          menuShow: true,
361
+          title: '兑换记录',
362
+        },
363
+      },
364
+    ]
365
+  },
366
+
108 367
 ]
109 368
 
110 369
 const flatten = (rts, parents = []) => {
111 370
   return rts.reduce((acc, rt) => {
112 371
     const chs = rt.children && rt.children.length ?
113 372
       flatten(rt.children, parents.concat(rt)) : []
114
-    
373
+
115 374
     return [...acc, { ...rt, parents }, ...chs]
116 375
   }, [])
117 376
 }

+ 221
- 0
src/views/news/edi/index.vue Целия файл

@@ -0,0 +1,221 @@
1
+<template>
2
+    <div id="root">
3
+        <el-form ref="form" :model="form" label-width="80px" class="form">
4
+            <el-form-item label="所属项目">
5
+                <el-select v-model="form.buildingId" placeholder="请选择">
6
+                    <el-option
7
+                            v-for="item in buildingList"
8
+                            :key="item.buildingId"
9
+                            :label="item.buildingName"
10
+                            :value="item.buildingId">
11
+                    </el-option>
12
+                </el-select>
13
+            </el-form-item>
14
+            <el-form-item label="资讯图片">
15
+<!--                class="avatar-uploader"-->
16
+                <el-upload
17
+                        :headers="uploadHeaders"
18
+                        :action="upFileUrl"
19
+                        :show-file-list="false"
20
+                        :on-success="handleAvatarSuccess">
21
+                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
22
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
23
+                </el-upload>
24
+            </el-form-item>
25
+            <el-form-item label="资讯标题">
26
+                <el-input v-model="form.newsName"></el-input>
27
+            </el-form-item>
28
+            <el-form-item label="资讯类型">
29
+                <el-select v-model="form.newsTypeId" placeholder="请选择">
30
+                    <el-option
31
+                            v-for="item in typeList"
32
+                            :key="item.newsTypeId"
33
+                            :label="item.newsTypeName"
34
+                            :value="item.newsTypeId">
35
+                    </el-option>
36
+                </el-select>
37
+            </el-form-item>
38
+            <el-form-item label="资讯详情">
39
+                <my-wangeditor :content="form.newsDetail" @get-content="getEdiCentent"></my-wangeditor>
40
+            </el-form-item>
41
+            <el-form-item label="状态">
42
+                <el-select v-model="form.newsStatus" placeholder="请选择">
43
+                    <el-option
44
+                            v-for="item in optionNewsStatus"
45
+                            :key="item.newsStatus"
46
+                            :label="item.name"
47
+                            :value="item.newsStatus">
48
+                    </el-option>
49
+                </el-select>
50
+            </el-form-item>
51
+            <el-form-item>
52
+                <el-button type="primary" @click="submitNewsType">保存</el-button>
53
+                <el-button @click="cancel">取消</el-button>
54
+            </el-form-item>
55
+        </el-form>
56
+    </div>
57
+</template>
58
+
59
+<script>
60
+    import myWangeditor from '../../../components/wangeditor'
61
+    import apis from '../../../config/api'
62
+    export default {
63
+        name: "newsEdiIndex",
64
+        data() {
65
+            return {
66
+                upFileUrl: apis.file.upload.url,
67
+                imageUrl: '',
68
+                optionNewsStatus: [
69
+                    {
70
+                        name: '已发布',
71
+                        newsStatus: 0
72
+                    },
73
+                    {
74
+                        name: '未发布',
75
+                        newsStatus: 1
76
+                    }
77
+                ],
78
+                form: {
79
+                    newsId: '',
80
+                    newsTypeId: '',
81
+                    newsImg: '',
82
+                    newsName: '',
83
+                    buildingId: '',
84
+                    newsStatus: '',
85
+                    newsDetail: ''
86
+                },
87
+                buildingList: [],
88
+                buildingForm: {
89
+                    pageNum: 1,
90
+                    pageSize: 100
91
+                },
92
+                typeList: [],
93
+                typeForm: {
94
+                    buildingId: '',
95
+                    pageNum: 1,
96
+                    pageSize: 100
97
+                },
98
+
99
+            }
100
+        },
101
+        components: {
102
+            // eslint-disable-next-line vue/no-unused-components
103
+            'my-wangeditor': myWangeditor
104
+        },
105
+        created() {
106
+            this.getBuildList()
107
+            this.getTypeList()
108
+            this.form.newsId = this.$route.query.id
109
+            if (this.form.newsId !== undefined) {
110
+                this.getById()
111
+            }
112
+        },
113
+        mounted () {
114
+
115
+        },
116
+        computed: {
117
+            uploadHeaders () {
118
+                const token = localStorage.getItem('x-token') || ''
119
+                return {
120
+                    Authorization: `Bearer ${token}`
121
+                }
122
+            }
123
+        },
124
+        methods: {
125
+            getEdiCentent(value) {
126
+                console.log('富文本值:', value)
127
+                this.form.newsDetail = value
128
+            },
129
+            handleAvatarSuccess(res, file) {
130
+                this.imageUrl = URL.createObjectURL(file.raw);
131
+                // console.log(res)
132
+                this.form.newsImg = res.data
133
+            },
134
+            getTypeList() {
135
+                this.$store.dispatch('news/getTypeList', this.typeForm).then((res) => {
136
+                    this.typeList = res.records
137
+                }).catch(() => {
138
+                    console.log('news/getTypeList err')
139
+                })
140
+            },
141
+            getBuildList() {
142
+                this.$store.dispatch('building/getBuildings', this.buildingForm).then((res) => {
143
+                    this.buildingList = res.records
144
+                }).catch(() => {
145
+                    console.log('building/getBuildings err')
146
+                })
147
+            },
148
+            submitNewsType() {
149
+                if (this.form.newsId === '' || this.form.newsId === undefined) {
150
+                    this.$store.dispatch('news/add', this.form).then((res) => {
151
+                        this.$message.success('操作成功!')
152
+                        this.$router.go(-1)
153
+                        // console.log(res)
154
+                    }).catch(() => {
155
+                        console.log('news/add err')
156
+                    })
157
+
158
+                    return;
159
+                }
160
+
161
+                // 修改
162
+                this.$store.dispatch('news/update', this.form).then((res) => {
163
+                    this.$message.success('操作成功!')
164
+                    this.$router.go(-1)
165
+                    // console.log(res)
166
+                }).catch(() => {
167
+                    console.log('news/update err')
168
+                })
169
+
170
+            },
171
+            cancel() {
172
+                this.$router.go(-1)
173
+            },
174
+            getById() {
175
+                this.$store.dispatch('news/getById', this.form).then((res) => {
176
+                    console.log('news/getById: ', res)
177
+                    this.form.newsName = res.newsName
178
+                    this.form.newsTypeId = res.newsTypeId
179
+                    this.form.newsStatus = res.newsStatus
180
+                    this.form.newsImg = res.newsImg
181
+                    this.imageUrl = res.newsImg
182
+                    this.form.buildingId = res.buildingId
183
+                    this.form.newsDetail = res.newsDetail
184
+                }).catch(() => {
185
+                    console.log('news/getById err')
186
+                })
187
+            }
188
+        }
189
+    }
190
+</script>
191
+
192
+<style scoped>
193
+    .avatar-uploader .el-upload {
194
+        border: 1px dashed #d9d9d9;
195
+        border-radius: 6px;
196
+        cursor: pointer;
197
+        position: relative;
198
+        overflow: hidden;
199
+    }
200
+    .avatar-uploader .el-upload:hover {
201
+        border-color: #409EFF;
202
+    }
203
+    .avatar-uploader-icon {
204
+        font-size: 28px;
205
+        color: #8c939d;
206
+        width: 178px;
207
+        height: 178px;
208
+        line-height: 178px;
209
+        text-align: center;
210
+    }
211
+    .avatar {
212
+        width: 178px;
213
+        height: 178px;
214
+        display: block;
215
+    }
216
+    .form {
217
+        width: 800px;
218
+        margin-left: auto;
219
+        margin-right: auto;
220
+    }
221
+</style>

+ 189
- 0
src/views/news/index.vue Целия файл

@@ -0,0 +1,189 @@
1
+<template>
2
+    <div id="root">
3
+        <div class="operation-class">
4
+           <el-button type="primary" @click="ediNewsType">新增</el-button>
5
+            &nbsp;
6
+            <el-select v-model="form.buildingId" placeholder="项目" @change="getList">
7
+                <el-option
8
+                        v-for="item in buildingList"
9
+                        :key="item.buildingId"
10
+                        :label="item.buildingName"
11
+                        :value="item.buildingId">
12
+                </el-option>
13
+            </el-select>
14
+        </div>
15
+        <div class="body">
16
+            <el-table
17
+                    :data="list"
18
+                    border
19
+                    style="width: 100%">
20
+                <el-table-column
21
+                        prop="newsImg"
22
+                        label="资讯主图"
23
+                        align="center">
24
+                    <template slot-scope="scope">
25
+                        <img :src="scope.row.newsImg" width="50" height="50"/>
26
+                    </template>
27
+                </el-table-column>
28
+                <el-table-column
29
+                        prop="newsName"
30
+                        label="标题"
31
+                        align="center">
32
+                </el-table-column>
33
+                <el-table-column
34
+                        prop="newsType.newsTypeName"
35
+                        label="资讯类型"
36
+                        align="center">
37
+
38
+                </el-table-column>
39
+                <el-table-column
40
+                        prop="createDate"
41
+                        label="发布时间"
42
+                        align="center">
43
+                </el-table-column>
44
+                <el-table-column
45
+                        prop="pvNum"
46
+                        label="阅读量"
47
+                        align="center">
48
+                </el-table-column>
49
+                <el-table-column
50
+                        prop="newsTypeName"
51
+                        label="转发数"
52
+                        align="center">
53
+                </el-table-column>
54
+                <el-table-column
55
+                        prop="favorNum"
56
+                        label="点赞数"
57
+                        align="center">
58
+                </el-table-column>
59
+                <el-table-column
60
+                        prop="saveNum"
61
+                        label="收藏数"
62
+                        align="center">
63
+                </el-table-column>
64
+                <el-table-column
65
+                        prop="newsStatus"
66
+                        label="状态"
67
+                        align="center">
68
+                    <template slot-scope="scope">{{ scope.row.newsStatus === 0 ? '已发布' : '未发布' }}</template>
69
+                </el-table-column>
70
+                <el-table-column
71
+                        prop="newsTypeId"
72
+                        align="center"
73
+                        label="操作">
74
+                    <template slot-scope="scope">
75
+                        <router-link :to="{ name:'news-edi', query: { id: scope.row.newsId } }">编辑</router-link>
76
+                        <a href="javascript:void(0);" @click="deleteNews(scope.row.newsId)" class="delClass">删除</a>
77
+                        <a href="javascript:void(0);" @click="releaseNews(scope.row)" class="delClass">{{ scope.row.newsStatus === 0 ? '取消发布' : '发布' }}</a>
78
+                    </template>
79
+                </el-table-column>
80
+            </el-table>
81
+        </div>
82
+        <div class="block">
83
+            <el-pagination
84
+                    @size-change="handleSizeChange"
85
+                    @current-change="handleCurrentChange"
86
+                    :current-page="form.pageNum"
87
+                    :page-sizes="[1, 10, 20, 30, 40]"
88
+                    :page-size="form.pageSize"
89
+                    layout="total, sizes, prev, pager, next, jumper"
90
+                    :total="total">
91
+            </el-pagination>
92
+        </div>
93
+    </div>
94
+</template>
95
+
96
+<script>
97
+    export default {
98
+        name: "newsIndex",
99
+        data() {
100
+            return {
101
+                buildingList: [],
102
+                form: {
103
+                    buildingId: '',
104
+                    pageNum: 1,
105
+                    pageSize: 10
106
+                },
107
+                buildingForm: {
108
+                    pageNum: 1,
109
+                    pageSize: 100
110
+                },
111
+                total: 0,
112
+                list: []
113
+            }
114
+        },
115
+        created() {
116
+          this.getList()
117
+          this.getBuildList()
118
+        },
119
+        methods: {
120
+            deleteNews(id) {
121
+                // 删除操作
122
+                const data = { newsId: id }
123
+                this.$store.dispatch('news/delete', data).then((res) => {
124
+                    this.getList()
125
+                }).catch(() => {
126
+                    console.log('news/delete err');
127
+                })
128
+            },
129
+            handleSizeChange(val) {
130
+                console.log(`每页 ${val} 条`);
131
+                this.form.pageSize = val
132
+                this.form.pageNum = 1
133
+                this.getList()
134
+            },
135
+            handleCurrentChange(val) {
136
+                console.log(`当前页: ${val}`);
137
+                this.form.pageNum = val
138
+                this.getList()
139
+            },
140
+            getList() {
141
+              this.$store.dispatch('news/getList', this.form).then((res) => {
142
+                this.list = res.records
143
+                this.form.pageNum = res.current
144
+                this.form.pageSize = res.size
145
+                this.total = res.total
146
+              }).catch(() => {
147
+                  console.log('news/getList err')
148
+              })
149
+            },
150
+            getBuildList() {
151
+                this.$store.dispatch('building/getBuildings', this.buildingForm).then((res) => {
152
+                    this.buildingList = res.records
153
+                }).catch(() => {
154
+                    console.log('building/getBuildings err')
155
+                })
156
+            },
157
+            ediNewsType() {
158
+                this.$router.push({ name: 'news-edi' })
159
+            },
160
+            releaseNews(news) {
161
+                news.newsStatus = news.newsStatus === 0 ? 1 : 0
162
+                // 修改
163
+                this.$store.dispatch('news/update', news).then((res) => {
164
+                    this.$message.success('操作成功!')
165
+                    this.getList()
166
+                    // console.log(res)
167
+                }).catch(() => {
168
+                    console.log('news/updateType err')
169
+                })
170
+            }
171
+        }
172
+    }
173
+</script>
174
+
175
+<style scoped>
176
+.operation-class {
177
+    margin-left: 20px;
178
+}
179
+.body {
180
+    margin-top: 10px;
181
+}
182
+.block {
183
+    display: flex;
184
+    justify-content: flex-end;
185
+}
186
+.delClass {
187
+    padding-left: 10px;
188
+}
189
+</style>

+ 154
- 0
src/views/news/type/edi/index.vue Целия файл

@@ -0,0 +1,154 @@
1
+<template>
2
+    <div id="root">
3
+        <el-form ref="form" :model="form" label-width="80px" class="form">
4
+            <el-form-item label="所属项目">
5
+                <el-select v-model="form.buildingId" placeholder="请选择">
6
+                    <el-option
7
+                            v-for="item in buildingList"
8
+                            :key="item.buildingId"
9
+                            :label="item.buildingName"
10
+                            :value="item.buildingId">
11
+                    </el-option>
12
+                </el-select>
13
+            </el-form-item>
14
+            <el-form-item label="图片">
15
+<!--                class="avatar-uploader"-->
16
+                <el-upload
17
+                        :headers="uploadHeaders"
18
+                        :action="upFileUrl"
19
+                        :show-file-list="false"
20
+                        :on-success="handleAvatarSuccess">
21
+                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
22
+                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
23
+                </el-upload>
24
+            </el-form-item>
25
+            <el-form-item label="名称">
26
+                <el-input v-model="form.newsTypeName"></el-input>
27
+            </el-form-item>
28
+            <el-form-item>
29
+                <el-button type="primary" @click="submitNewsType">保存</el-button>
30
+                <el-button @click="cancel">取消</el-button>
31
+            </el-form-item>
32
+        </el-form>
33
+    </div>
34
+</template>
35
+
36
+<script>
37
+    import apis from '../../../../config/api'
38
+    export default {
39
+        name: "newsTypeEdiIndex",
40
+        data() {
41
+            return {
42
+                upFileUrl: apis.file.upload.url,
43
+                buildingList: [],
44
+                imageUrl: '',
45
+                form: {
46
+                    newsTypeId: '',
47
+                    newsTypeImg: '',
48
+                    newsTypeName: '',
49
+                    buildingId: ''
50
+                },
51
+                buildingForm: {
52
+                    pageNum: 1,
53
+                    pageSize: 100
54
+                },
55
+            }
56
+        },
57
+        created() {
58
+            this.getBuildList()
59
+            this.form.newsTypeId = this.$route.query.id
60
+            if (this.form.newsTypeId !== undefined) {
61
+                this.getById()
62
+            }
63
+        },
64
+        computed: {
65
+            uploadHeaders () {
66
+                const token = localStorage.getItem('x-token') || ''
67
+                return {
68
+                    Authorization: `Bearer ${token}`
69
+                }
70
+            }
71
+        },
72
+        methods: {
73
+            handleAvatarSuccess(res, file) {
74
+                this.imageUrl = URL.createObjectURL(file.raw);
75
+                // console.log(res)
76
+                this.form.newsTypeImg = res.data
77
+            },
78
+            getBuildList() {
79
+                this.$store.dispatch('building/getBuildings', this.buildingForm).then((res) => {
80
+                    this.buildingList = res.records
81
+                }).catch(() => {
82
+                    console.log('building/getBuildings err')
83
+                })
84
+            },
85
+            submitNewsType() {
86
+                if (this.form.newsTypeId === '' || this.form.newsTypeId === undefined) {
87
+                    this.$store.dispatch('news/addType', this.form).then((res) => {
88
+                        this.$message.success('操作成功!')
89
+                        this.$router.go(-1)
90
+                        // console.log(res)
91
+                    }).catch(() => {
92
+                        console.log('news/addType err')
93
+                    })
94
+
95
+                    return;
96
+                }
97
+
98
+                // 修改
99
+                this.$store.dispatch('news/updateType', this.form).then((res) => {
100
+                    this.$message.success('操作成功!')
101
+                    this.$router.go(-1)
102
+                    // console.log(res)
103
+                }).catch(() => {
104
+                    console.log('news/updateType err')
105
+                })
106
+
107
+            },
108
+            cancel() {
109
+                this.$router.go(-1)
110
+            },
111
+            getById() {
112
+                this.$store.dispatch('news/getTypeById', this.form).then((res) => {
113
+                    this.form.newsTypeName = res.newsTypeName
114
+                    this.form.newsTypeImg = res.newsTypeImg
115
+                    this.imageUrl = res.newsTypeImg
116
+                    this.form.buildingId = res.buildingId
117
+                }).catch(() => {
118
+                    console.log('news/getTypeById err')
119
+                })
120
+            }
121
+        }
122
+    }
123
+</script>
124
+
125
+<style scoped>
126
+    .avatar-uploader .el-upload {
127
+        border: 1px dashed #d9d9d9;
128
+        border-radius: 6px;
129
+        cursor: pointer;
130
+        position: relative;
131
+        overflow: hidden;
132
+    }
133
+    .avatar-uploader .el-upload:hover {
134
+        border-color: #409EFF;
135
+    }
136
+    .avatar-uploader-icon {
137
+        font-size: 28px;
138
+        color: #8c939d;
139
+        width: 178px;
140
+        height: 178px;
141
+        line-height: 178px;
142
+        text-align: center;
143
+    }
144
+    .avatar {
145
+        width: 178px;
146
+        height: 178px;
147
+        display: block;
148
+    }
149
+    .form {
150
+        width: 300px;
151
+        margin-left: auto;
152
+        margin-right: auto;
153
+    }
154
+</style>

+ 141
- 0
src/views/news/type/index.vue Целия файл

@@ -0,0 +1,141 @@
1
+<template>
2
+    <div id="root">
3
+        <div class="operation-class">
4
+           <el-button type="primary" @click="ediNewsType">新增</el-button>
5
+            &nbsp;
6
+            <el-select v-model="form.buildingId" placeholder="项目" @change="getList">
7
+                <el-option
8
+                        v-for="item in buildingList"
9
+                        :key="item.buildingId"
10
+                        :label="item.buildingName"
11
+                        :value="item.buildingId">
12
+                </el-option>
13
+            </el-select>
14
+        </div>
15
+        <div class="body">
16
+            <el-table
17
+                    :data="list"
18
+                    border
19
+                    style="width: 100%">
20
+                <el-table-column
21
+                        prop="date"
22
+                        label="类型图"
23
+                        align="center">
24
+                    <template slot-scope="scope">
25
+                        <img :src="scope.row.newsTypeImg" width="50" height="50"/>
26
+                    </template>
27
+                </el-table-column>
28
+                <el-table-column
29
+                        prop="newsTypeName"
30
+                        label="名称"
31
+                        align="center">
32
+                </el-table-column>
33
+                <el-table-column
34
+                        prop="newsTypeId"
35
+                        align="center"
36
+                        label="操作">
37
+                    <template slot-scope="scope">
38
+                        <router-link :to="{ name:'news-type-edi', query: { id: scope.row.newsTypeId } }">编辑</router-link>
39
+                        <a href="javascript:void(0);" @click="deleteNews(scope.row.newsTypeId)" class="delClass">删除</a>
40
+                    </template>
41
+                </el-table-column>
42
+            </el-table>
43
+        </div>
44
+        <div class="block">
45
+            <el-pagination
46
+                    @size-change="handleSizeChange"
47
+                    @current-change="handleCurrentChange"
48
+                    :current-page="form.pageNum"
49
+                    :page-sizes="[1, 10, 20, 30, 40]"
50
+                    :page-size="form.pageSize"
51
+                    layout="total, sizes, prev, pager, next, jumper"
52
+                    :total="total">
53
+            </el-pagination>
54
+        </div>
55
+    </div>
56
+</template>
57
+
58
+<script>
59
+    export default {
60
+        name: "newsTypeIndex",
61
+        data() {
62
+            return {
63
+                buildingList: [],
64
+                form: {
65
+                    buildingId: '',
66
+                    pageNum: 1,
67
+                    pageSize: 10
68
+                },
69
+                buildingForm: {
70
+                    pageNum: 1,
71
+                    pageSize: 100
72
+                },
73
+                total: 0,
74
+                list: []
75
+            }
76
+        },
77
+        created() {
78
+          this.getList()
79
+          this.getBuildList()
80
+        },
81
+        methods: {
82
+            deleteNews(id) {
83
+                // 删除操作
84
+                const data = { newsTypeId: id }
85
+                this.$store.dispatch('news/deleteType', data).then((res) => {
86
+                    this.getList()
87
+                }).catch(() => {
88
+                    console.log('news/deleteType err');
89
+                })
90
+            },
91
+            handleSizeChange(val) {
92
+                console.log(`每页 ${val} 条`);
93
+                this.form.pageSize = val
94
+                this.form.pageNum = 1
95
+                this.getList()
96
+            },
97
+            handleCurrentChange(val) {
98
+                console.log(`当前页: ${val}`);
99
+                this.form.pageNum = val
100
+                this.getList()
101
+            },
102
+            getList() {
103
+              this.$store.dispatch('news/getTypeList', this.form).then((res) => {
104
+                this.list = res.records
105
+                this.form.pageNum = res.current
106
+                this.form.pageSize = res.size
107
+                this.total = res.total
108
+              }).catch(() => {
109
+                  console.log('news/getTypeList err')
110
+              })
111
+            },
112
+            getBuildList() {
113
+                this.$store.dispatch('building/getBuildings', this.buildingForm).then((res) => {
114
+                    this.buildingList = res.records
115
+                }).catch(() => {
116
+                    console.log('building/getBuildings err')
117
+                })
118
+            },
119
+            ediNewsType() {
120
+                this.$router.push({ name: 'news-type-edi' })
121
+            }
122
+        }
123
+    }
124
+</script>
125
+
126
+<style scoped>
127
+.operation-class {
128
+    margin-left: 20px;
129
+}
130
+.body {
131
+    margin-top: 10px;
132
+}
133
+.block {
134
+    display: flex;
135
+    justify-content: flex-end;
136
+}
137
+.delClass {
138
+    padding-left: 10px;
139
+    padding-right: 10px;
140
+}
141
+</style>

+ 211
- 0
src/views/points/edit.vue Целия файл

@@ -0,0 +1,211 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="100px" :model="detail">
5
+        <!-- <el-form-item label="项目">
6
+          <el-select v-model="detail.buildingId" placeholder="请选择">
7
+            <el-option
8
+                    v-for="item in buildingList"
9
+                    :key="item.buildingId"
10
+                    :label="item.buildingName"
11
+                    :value="item.buildingId">
12
+            </el-option>
13
+          </el-select>
14
+        </el-form-item> -->
15
+        
16
+        <el-form-item label="获取积分:">
17
+          <el-input v-model="detail.pointsAmount"></el-input>
18
+        </el-form-item>
19
+        <el-form-item>
20
+          <el-button type="primary" @click="submitForm">保存</el-button>
21
+          <el-button @click="$router.go(-1)">返回</el-button>
22
+        </el-form-item>
23
+      </el-form>
24
+    </div>
25
+  </div>
26
+</template>
27
+
28
+<script>
29
+import { createNamespacedHelpers } from "vuex";
30
+import apis from "../../config/api";
31
+import E from "wangeditor";
32
+
33
+const { mapActions: mapPointsActions } = createNamespacedHelpers("points");
34
+const {
35
+  mapState: mapBuildingState,
36
+  mapActions: mapBuildingActions
37
+} = createNamespacedHelpers("building");
38
+export default {
39
+  name: "goodsEdit",
40
+  data() {
41
+    return {
42
+      upFileUrl: apis.file.upload.url,
43
+      detail: {
44
+        buildingId: '',
45
+        pointsAmount: '',
46
+        ruleId: '',
47
+      },
48
+      options: [{
49
+          value: '1',
50
+          label: '已上架'
51
+        }, {
52
+          value: '0',
53
+          label: '已下架'
54
+        }],
55
+      buildingList: [],
56
+    };
57
+  },
58
+  created() {
59
+    this.init();
60
+  },
61
+  computed: {
62
+    ...mapBuildingState({
63
+      buildings: x => x.buildings
64
+    }),
65
+    uploadHeaders () {
66
+        const token = localStorage.getItem('x-token') || ''
67
+        return {
68
+            Authorization: `Bearer ${token}`
69
+        }
70
+    }
71
+  },
72
+  methods: {
73
+    ...mapBuildingActions(["getBuildings"]),
74
+    ...mapPointsActions(["getPointsDetail", "editPoints", "addGoods"]),
75
+    init() {
76
+      this.detail.ruleId = this.$route.params.id
77
+      if (this.detail.ruleId !== undefined) {
78
+        this.getPointsDetail({ id: this.$route.params.id }).then(data => {
79
+          this.detail.buildingId = data.buildingId
80
+          this.detail.pointsAmount = data.pointsAmount
81
+          this.detail.goodsId = data.goodsId
82
+        });
83
+      }
84
+    },
85
+    beforeImgUpload(file) {
86
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
87
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
88
+        return false;
89
+      }
90
+
91
+      this.showLoadding("上传中...");
92
+      return true;
93
+    },
94
+
95
+    handleAvatarSuccess(res, file) {
96
+        this.imageUrl = URL.createObjectURL(file.raw);
97
+        // console.log(res)
98
+        this.detail.imgUrl = res.data
99
+    },
100
+
101
+    submitForm() {
102
+      this.showLoadding("保存中...");
103
+      // if (this.detail.goodsId === '' || this.detail.goodsId === undefined) {
104
+      //   console.log('添加')
105
+      //   this.addGoods(this.detail)
106
+      //   .then(res => {
107
+      //     this.hideLoadding();
108
+      //     this.$notify.info("保存成功");
109
+      //      this.$router.go(-1)
110
+      //   })
111
+      //   .catch(err => {
112
+      //     this.hideLoadding();
113
+      //     this.$notify.error(err.message);
114
+      //   });
115
+      //   return;
116
+      // }
117
+      this.editPoints(this.detail)
118
+        .then(res => {
119
+          this.hideLoadding();
120
+          this.$notify.info("保存成功");
121
+           this.$router.go(-1)
122
+        })
123
+        .catch(err => {
124
+          this.hideLoadding();
125
+          this.$notify.error(err.message);
126
+        });
127
+    },
128
+
129
+    showLoadding(text) {
130
+      this.loading = this.$loading({
131
+        text,
132
+        lock: true,
133
+        spinner: "el-icon-loading",
134
+        background: "rgba(255, 255, 255, 0.7)"
135
+      });
136
+    },
137
+
138
+    hideLoadding() {
139
+      if (this.loading) this.loading.close();
140
+    }
141
+  },
142
+  mounted() {
143
+    const _that = this;
144
+    const phoneEditor = new E("#websiteEditorElem");
145
+    phoneEditor.customConfig.onchange = function(html) {
146
+      _that.dynamic = { ..._that.dynamic, url: html };
147
+    };
148
+    // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
149
+    // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
150
+
151
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
152
+      _that.uploadImg(files[0]).then(data => {
153
+        insert(data);
154
+      });
155
+    };
156
+    phoneEditor.customConfig.menus = [
157
+      "head", // 标题
158
+      "bold", // 粗体
159
+      "fontSize", // 字号
160
+      "fontName", // 字体
161
+      "italic", // 斜体
162
+      "underline", // 下划线
163
+      "strikeThrough", // 删除线
164
+      "foreColor", // 文字颜色
165
+      "backColor", // 背景颜色
166
+      "justify", // 对齐方式
167
+      "image" // 插入图片
168
+    ];
169
+    phoneEditor.create()
170
+
171
+    this.getBuildings({
172
+      pageNum: 1,
173
+      pageSize: 100
174
+    }).then((data) => {
175
+      this.buildingList = data.records;
176
+    });
177
+  }
178
+};
179
+</script>
180
+
181
+<style lang="scss" scoped>
182
+.form-wrapper {
183
+  width: 60%;
184
+}
185
+</style>
186
+
187
+<style lang="scss">
188
+.avatar-uploader .el-upload {
189
+  border: 1px dashed #d9d9d9;
190
+  border-radius: 6px;
191
+  cursor: pointer;
192
+  position: relative;
193
+  overflow: hidden;
194
+}
195
+.avatar-uploader .el-upload:hover {
196
+  border-color: #409eff;
197
+}
198
+.avatar-uploader-icon {
199
+  font-size: 28px;
200
+  color: #8c939d;
201
+  width: 178px;
202
+  height: 178px;
203
+  line-height: 178px;
204
+  text-align: center;
205
+}
206
+.avatar {
207
+  width: 178px;
208
+  height: 178px;
209
+  display: block;
210
+}
211
+</style>

+ 183
- 0
src/views/points/list.vue Целия файл

@@ -0,0 +1,183 @@
1
+<template>
2
+<div class="list">
3
+        <div class="system-table-search">
4
+      <div class="moreFilter"></div>
5
+    </div>
6
+  <el-table
7
+    :data="list || []"
8
+    style="width: 100%">
9
+    <el-table-column
10
+      prop="ruleName"
11
+      label="类型">
12
+    </el-table-column>
13
+    <el-table-column
14
+      prop="pointsAmount"
15
+      label="获取积分">
16
+    </el-table-column>
17
+    <el-table-column   label="状态">
18
+      <template slot-scope="scope">
19
+        <span :style="{color:(scope.row.status == 1?'':'red')}" >{{scope.row.status == 1 ? '启用' : '停用'}}</span>
20
+      </template>
21
+    </el-table-column>
22
+    <el-table-column
23
+      label="操作时间">
24
+      <template slot-scope="scope">
25
+          <span>{{formateDate(scope.row.updateDate)}}</span>
26
+      </template>
27
+    </el-table-column>   
28
+    <el-table-column
29
+      fixed="right"
30
+      label="操作">
31
+      <template slot-scope="scope">
32
+        <el-button type="text" @click="changeStatus(scope.row)" size="small">{{scope.row.status == 1?'停用':'启用'}}</el-button>
33
+        <el-button type="text" @click="toDetail(scope.row)" size="small">编辑</el-button>
34
+      </template>
35
+    </el-table-column>
36
+  </el-table>
37
+  <el-pagination
38
+    small
39
+    style="margin-top:10px;"
40
+    layout="prev, pager, next"
41
+    :current-page.sync="pageNavi.current"
42
+    :pageSize="pageNavi.size"
43
+    :total="pageNavi.total || 0"
44
+    @current-change="getList"
45
+  >
46
+  </el-pagination>
47
+</div>
48
+</template>
49
+
50
+<script>
51
+import { createNamespacedHelpers } from "vuex";
52
+import dayjs from 'dayjs'
53
+
54
+const { mapActions: mapPointsActions } = createNamespacedHelpers("points");
55
+
56
+export default {
57
+  name: "goods-list",
58
+  data() {
59
+    return {
60
+      filterData: {
61
+        goodsName: ""
62
+      },
63
+      list: [],
64
+      pageNavi: {
65
+        current: 1,
66
+        size: 20,
67
+        total: 0
68
+      }
69
+    };
70
+  },
71
+  computed: {},
72
+  methods: {
73
+    ...mapPointsActions(["getPointsRules", "changePointsRulesStatus"]),
74
+    getList() {
75
+      const pageNumber = this.pageNavi.current || 1;
76
+      const pageSize = this.pageNavi.size;
77
+
78
+      this.getPointsRules({
79
+        ...this.filterData,
80
+        pageNumber,
81
+        pageSize
82
+      })
83
+        .then(res => {
84
+          const { records, ...pageNavi } = res;
85
+
86
+          this.list = records;
87
+          this.pageNavi = pageNavi;
88
+        })
89
+        .catch(err => {
90
+          this.$notify.error(err.msg || err.message);
91
+        });
92
+    },
93
+    toDetail(row) {
94
+      this.$router.push({
95
+        name: "points.edit",
96
+        params: { id: row.ruleId }
97
+      });
98
+    },
99
+    changeStatus(row) {
100
+      this.showLoadding("保存中...");
101
+      this.changePointsRulesStatus(row)
102
+        .then(res => {
103
+          this.hideLoadding();
104
+          this.$notify.info("保存成功");
105
+          this.search();
106
+        })
107
+        .catch(err => {
108
+          this.hideLoadding();
109
+          this.$notify.error(err.message);
110
+        });
111
+    },
112
+    showLoadding(text) {
113
+      this.loading = this.$loading({
114
+        text,
115
+        lock: true,
116
+        spinner: "el-icon-loading",
117
+        background: "rgba(255, 255, 255, 0.7)"
118
+      });
119
+    },
120
+    hideLoadding() {
121
+      if (this.loading) this.loading.close();
122
+    },
123
+    search() {
124
+      this.pageNavi.current = 1;
125
+      this.getList();
126
+    },
127
+    newPage(page) {
128
+      this.$router.replace({ name: "goods.list", query: { page } });
129
+    },
130
+    formateDate(dt) {
131
+    return !dt ? '' : dayjs(dt).format('YYYY-MM-DD HH:mm')
132
+  },
133
+  },
134
+  created() {
135
+    this.pageNavi.current = this.$route.query.page || 1;
136
+
137
+    this.getList();
138
+  },
139
+};
140
+</script>
141
+
142
+<style lang="scss" scoped>
143
+.list {
144
+  .header {
145
+    width: 50px;
146
+    height: 50px;
147
+    border-radius: 50%;
148
+  }
149
+  img {
150
+      width: 100%;
151
+      height: 100%;
152
+    }
153
+}
154
+.system-table-search {
155
+  width: calc(100% - 40px);
156
+  margin: 20px auto 0;
157
+}
158
+
159
+.system-table-search li {
160
+  margin-right: 20px;
161
+}
162
+
163
+.system-table-search ul {
164
+  font-size: 0;
165
+  white-space: nowrap;
166
+}
167
+
168
+.system-table-search ul > li {
169
+  display: inline-block;
170
+}
171
+
172
+.flex-h {
173
+  display: flex;
174
+  align-items: center;
175
+}
176
+
177
+.flex-item {
178
+  flex: 1;
179
+  -webkit-flex: 1;
180
+  position: relative;
181
+  overflow: hidden;
182
+}
183
+</style>

+ 671
- 0
src/views/project/edit.vue Целия файл

@@ -0,0 +1,671 @@
1
+<template>
2
+  <div>
3
+    <el-tabs type="border-card" >
4
+    <el-tab-pane label="基本信息">
5
+    <el-form ref="form" :model="building" label-width="160px">
6
+      <el-form-item label="项目名称:" >
7
+        <el-input v-model="building.desc"></el-input>
8
+      </el-form-item>
9
+      <el-form-item label="项目简称:">
10
+        <el-input v-model="building.desc"></el-input>
11
+      </el-form-item>
12
+      <el-form-item label="项目类型:">
13
+        <el-select v-model="building.buildingId" placeholder="请选择">
14
+          <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
15
+        </el-select>
16
+      </el-form-item>
17
+      <el-form-item label="项目编码:">
18
+        <el-input v-model="building.desc"></el-input>
19
+      </el-form-item>
20
+      <el-form-item label="项目区域:">
21
+        <el-select v-model="building.buildingId" placeholder="请选择">
22
+          <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
23
+        </el-select>
24
+      </el-form-item>
25
+      <el-form-item label="均价:">
26
+        <el-input v-model="building.desc"></el-input> &nbsp;元/m²
27
+      </el-form-item>
28
+      <el-form-item label="开盘日期:">
29
+        <el-input v-model="building.desc"></el-input>
30
+      </el-form-item>
31
+      <el-form-item label="物业类型:">
32
+        <el-input v-model="building.desc"></el-input>
33
+      </el-form-item>
34
+      <el-form-item label="项目电话:">
35
+        <el-input v-model="building.desc"></el-input>
36
+      </el-form-item>
37
+      <el-form-item label="项目联系人:">
38
+        <el-input v-model="building.desc"></el-input>
39
+      </el-form-item>
40
+      <el-form-item label="销售状态:">
41
+        <el-select v-model="building.buildingId" placeholder="请选择">
42
+          <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
43
+        </el-select>
44
+      </el-form-item>
45
+      <el-form-item label="发布时间:">
46
+        <el-input v-model="building.desc"></el-input>
47
+      </el-form-item>
48
+      <el-form-item label="项目标签:">
49
+        <el-input v-model="building.desc" placeholder="(输入标签后按回车生成)" ></el-input>
50
+      </el-form-item>
51
+      <el-form-item label="首页推荐:">
52
+        <template>
53
+          <el-radio v-model="radio" label="1">是</el-radio>
54
+          <el-radio v-model="radio" label="2">否</el-radio>
55
+        </template>
56
+      </el-form-item>   
57
+      <el-form-item label="项目状态:">
58
+        <el-select v-model="building.buildingId" placeholder="请选择">
59
+          <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
60
+        </el-select>
61
+      </el-form-item>
62
+      <el-form-item>
63
+        <el-button type="primary" @click="onSubmit">保存</el-button>
64
+        <el-button @click="onCancel">取消</el-button>
65
+      </el-form-item>
66
+    </el-form>
67
+  </el-tab-pane>
68
+
69
+  <el-tab-pane label="交通及周边设施">
70
+    <el-form ref="form" :model="building" label-width="160px">
71
+     <el-form-item label="项目地图图片:">
72
+        <el-upload
73
+            :action="upFileUrl"
74
+            name='file'
75
+            list-type="picture-card"
76
+            :headers="uploadHeaders"
77
+            :file-list="imgList1"
78
+            :show-file-list="true"
79
+            :before-upload="beforeImgUpload"
80
+            :on-success="handleAvatarSuccess1"
81
+            :on-remove="handleRemove">
82
+            <i class="el-icon-plus"></i>
83
+          </el-upload>
84
+          <el-dialog :visible.sync="dialogVisible">
85
+            <img width="100%" :src="dialogImageUrl1" alt="">
86
+          </el-dialog>
87
+      </el-form-item>
88
+      <el-form-item label="项目地址:">
89
+        <el-input v-model="building.desc" ></el-input>
90
+      </el-form-item> 
91
+      <el-form-item label="项目经纬度:">
92
+          <div class="search">
93
+            <!-- <el-amap-search-box class="search-box" :search-option="searchOption" :on-search-result="onSearchResult"></el-amap-search-box> -->
94
+           <el-input v-model="building.desc" placeholder="按关键词搜索" ></el-input>
95
+            <el-button type="primary" @click="onSubmit">搜索</el-button>
96
+           <el-input v-model="building.desc" placeholder="左击获取经纬度" ></el-input>
97
+          </div>
98
+          <div class="flex-item">
99
+            <div style="width: 100%;">
100
+              <el-amap ref="map" vid="amapDemo" :center="mapCenter" :zoom="12" :events="events" class="amap-demo">
101
+                <el-amap-marker v-for="(item,index) in markers" :key="index" :position="item" ></el-amap-marker>
102
+              </el-amap>
103
+            </div>
104
+          </div>  
105
+        </el-form-item>
106
+      <el-form-item label="周边设施:">
107
+        <div id="websiteEditorElem" style="height: 400px"></div>
108
+      </el-form-item>
109
+      <el-form-item>
110
+        <el-button type="primary" @click="onSubmit">保存</el-button>
111
+        <el-button @click="onCancel">取消</el-button>
112
+      </el-form-item>
113
+      </el-form>  
114
+  </el-tab-pane>
115
+  <el-tab-pane label="户型相册">
116
+    <el-form ref="form" :model="building" label-width="150px">
117
+      <p class="title">户型:</p>
118
+      <div v-for="(item,index) in 2" :key="index" class="apartment-box">
119
+        <el-form-item label="户型图:">
120
+          <el-upload
121
+            :action="upFileUrl"
122
+            name='file'
123
+            list-type="picture-card"
124
+            :headers="uploadHeaders"
125
+            :file-list="imgList2"
126
+            :show-file-list="true"
127
+            :before-upload="beforeImgUpload"
128
+            :on-success="handleAvatarSuccess2"
129
+            :on-remove="handleRemove">
130
+            <i class="el-icon-plus"></i>
131
+          </el-upload>
132
+          <el-dialog :visible.sync="dialogVisible">
133
+            <img width="100%" :src="dialogImageUrl2" alt="">
134
+          </el-dialog>
135
+        </el-form-item>
136
+        <el-form-item label="标题:">
137
+          <el-input v-model="building.desc" ></el-input>
138
+        </el-form-item>
139
+        <el-form-item label="面积:">
140
+          <el-input v-model="building.desc" ></el-input> &nbsp;m²
141
+        </el-form-item>
142
+        <el-form-item label="套内面积:">
143
+          <el-input v-model="building.desc" ></el-input> &nbsp;m²
144
+        </el-form-item>
145
+        <el-form-item label="销售状态:">
146
+        <el-select v-model="building.buildingId" placeholder="请选择">
147
+          <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
148
+        </el-select>
149
+        <el-button type="warning" @click="onSubmit">删除</el-button>
150
+      </el-form-item>
151
+        <el-form-item label="总价:">
152
+          <el-input v-model="building.desc" ></el-input> &nbsp;万
153
+        </el-form-item>
154
+        <el-form-item label="简介:">
155
+          <el-input type="textarea" :rows="5"  v-model="building.desc"></el-input>
156
+        </el-form-item>
157
+    </div>
158
+    <el-form-item>
159
+      <el-button type="primary" @click="onSubmit">添加户型</el-button>
160
+    </el-form-item>
161
+    <p class="title">项目相册:</p>
162
+      <el-form-item label="效果图">
163
+          <el-upload
164
+            :action="upFileUrl"
165
+            name='file'
166
+            list-type="picture-card"
167
+            :headers="uploadHeaders"
168
+            :file-list="imgList3"
169
+            :show-file-list="true"
170
+            :before-upload="beforeImgUpload"
171
+            :on-success="handleAvatarSuccess3"
172
+            :on-remove="handleRemove">
173
+            <i class="el-icon-plus"></i>
174
+          </el-upload>
175
+          <el-dialog :visible.sync="dialogVisible">
176
+            <img width="100%" :src="dialogImageUrl3" alt="">
177
+          </el-dialog>
178
+      </el-form-item>
179
+      <el-form-item label="实景图">
180
+          <el-upload
181
+            :action="upFileUrl"
182
+            name='file'
183
+            list-type="picture-card"
184
+            :headers="uploadHeaders"
185
+            :file-list="imgList4"
186
+            :show-file-list="true"
187
+            :before-upload="beforeImgUpload"
188
+            :on-success="handleAvatarSuccess4"
189
+            :on-remove="handleRemove">
190
+            <i class="el-icon-plus"></i>
191
+          </el-upload>
192
+          <el-dialog :visible.sync="dialogVisible">
193
+            <img width="100%" :src="dialogImageUrl4" alt="">
194
+          </el-dialog>
195
+      </el-form-item>
196
+      <el-form-item label="样板间">
197
+          <el-upload
198
+            :action="upFileUrl"
199
+            name='file'
200
+            list-type="picture-card"
201
+            :headers="uploadHeaders"
202
+            :file-list="imgList5"
203
+            :show-file-list="true"
204
+            :before-upload="beforeImgUpload"
205
+            :on-success="handleAvatarSuccess5"
206
+            :on-remove="handleRemove">
207
+            <i class="el-icon-plus"></i>
208
+          </el-upload>
209
+          <el-dialog :visible.sync="dialogVisible">
210
+            <img width="100%" :src="dialogImageUrl5" alt="">
211
+          </el-dialog>
212
+      </el-form-item>
213
+      <el-form-item>
214
+        <el-button type="primary" @click="onSubmit">保存</el-button>
215
+        <el-button @click="onCancel">取消</el-button>
216
+      </el-form-item>
217
+    </el-form>
218
+  </el-tab-pane>
219
+
220
+</el-tabs>
221
+  </div>
222
+
223
+</template>
224
+
225
+<script>
226
+import { createNamespacedHelpers } from "vuex";
227
+import apis from "../../config/api";
228
+import { mapState } from "vuex";
229
+import E from "wangeditor";
230
+
231
+const {
232
+  mapState: mapBuildingState,
233
+  mapActions: mapBuildingActions,
234
+  mapMutations: mapBuildingMutations
235
+} = createNamespacedHelpers("building");
236
+
237
+const { mapActions: mapApartmentActions } = createNamespacedHelpers(
238
+  "apartment"
239
+);
240
+
241
+const { mapActions: mapImgActions } = createNamespacedHelpers("img");
242
+
243
+export default {
244
+  data() {
245
+    var _self = this;
246
+    return {
247
+      upFileUrl: apis.file.upload.url,
248
+      radio: "1",
249
+      showHx: false,
250
+      dialogVisible: false,
251
+      dialogImageUrl1: "",
252
+      dialogImageUrl2: "",
253
+      dialogImageUrl3: "",
254
+      dialogImageUrl4: "",
255
+      dialogImageUrl5: "",
256
+      markers: [],
257
+      imgList1: [],
258
+      imgList2: [],
259
+      imgList3: [],
260
+      imgList4: [],
261
+      imgList5: [],
262
+      tags: [],
263
+      buildingProperty: [],
264
+      aparments: [],
265
+      aparmentInfo: {},
266
+      aparmentImg: [],
267
+      searchOption: {
268
+        city: "南京",
269
+        citylimit: false
270
+      },
271
+      saleType: [
272
+        {
273
+          id: 1,
274
+          name: "待定"
275
+        },
276
+        {
277
+          id: 2,
278
+          name: "售罄"
279
+        },
280
+        {
281
+          id: 3,
282
+          name: "在售"
283
+        }
284
+      ],
285
+      mapCenter: [118.789509, 32.019989],
286
+      events: {
287
+        click: e => {
288
+          _self.updateDetail({
289
+            ..._self.building,
290
+            coordinate: e.lnglat.lat + "," + e.lnglat.lng
291
+          });
292
+        }
293
+      }
294
+    };
295
+  },
296
+  computed: {
297
+    ...mapBuildingState({
298
+      detail: x => x.detail,
299
+      buildings: x => x.buildings
300
+    }),
301
+    ...mapState({
302
+      dicts: x => x.dicts
303
+    }),
304
+    building: {
305
+      get() {
306
+        return this.detail;
307
+      },
308
+      set(val) {
309
+        return this.updateDetail(val);
310
+      }
311
+    },
312
+    propertyType() {
313
+      return (this.dicts || []).filter(x => x.type === "propertyType");
314
+    },
315
+    uploadHeaders() {
316
+      const token = localStorage.getItem("x-token") || "";
317
+      return {
318
+        Authorization: `Bearer ${token}`
319
+      };
320
+    }
321
+  },
322
+  methods: {
323
+    ...mapBuildingMutations(["updateDetail"]),
324
+    ...mapBuildingActions([
325
+      "getDetail",
326
+      "addBuilding",
327
+      "editBuilding",
328
+      "getBuildings"
329
+    ]),
330
+    ...mapApartmentActions([
331
+      "getApartments",
332
+      "getApartmentDetail",
333
+      "addApartment",
334
+      "editApartment",
335
+      "deleteApartment"
336
+    ]),
337
+    ...mapImgActions(["uploadImg"]),
338
+
339
+    getSaleTypeName(id) {
340
+      return (this.saleType.filter(x => x.id == id)[0] || {}).name;
341
+    },
342
+    onCancel() {
343
+      this.$router.push({ name: "buildinglist" });
344
+    },
345
+    handleRemove(file, fileList) {
346
+      this.imgList = fileList;
347
+    },
348
+    handleAparmentRemove(file, fileList) {
349
+      this.aparmentImg = fileList;
350
+    },
351
+    onSearchResult(pois) {
352
+      // 搜索地图
353
+      let latSum = 0;
354
+      let lngSum = 0;
355
+      if (pois.length > 0) {
356
+        pois.forEach(poi => {
357
+          let { lng, lat } = poi;
358
+          lngSum += lng;
359
+          latSum += lat;
360
+          this.markers.push([poi.lng, poi.lat]);
361
+        });
362
+        let center = {
363
+          lng: lngSum / pois.length,
364
+          lat: latSum / pois.length
365
+        };
366
+        this.mapCenter = [center.lng, center.lat];
367
+      }
368
+    },
369
+    beforeImgUpload(file) {
370
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
371
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
372
+        return false;
373
+      }
374
+      // if (file.size / 1024 > 300) {
375
+      //   this.$message.error('图片大小不允许超过300k!')
376
+      //   return false
377
+      // }
378
+      this.loading = this.$loading({
379
+        lock: true,
380
+        text: "上传中...",
381
+        spinner: "el-icon-loading",
382
+        background: "rgba(0, 0, 0, 0.7)"
383
+      });
384
+
385
+      return true;
386
+    },
387
+    handleAvatarSuccess1(res) {
388
+      this.imgList1 = [
389
+        ...this.imgList1,
390
+        {
391
+          url: res.data
392
+        }
393
+      ];
394
+      this.loading.close();
395
+    },
396
+    handleAvatarSuccess2(res) {
397
+      this.imgList2 = [
398
+        ...this.imgList2,
399
+        {
400
+          url: res.data
401
+        }
402
+      ];
403
+      this.loading.close();
404
+    },
405
+    handleAvatarSuccess3(res) {
406
+      this.imgList3 = [
407
+        ...this.imgList3,
408
+        {
409
+          url: res.data
410
+        }
411
+      ];
412
+      this.loading.close();
413
+    },
414
+    handleAvatarSuccess4(res) {
415
+      this.imgList4 = [
416
+        ...this.imgList4,
417
+        {
418
+          url: res.data
419
+        }
420
+      ];
421
+      this.loading.close();
422
+    },
423
+    handleAvatarSuccess5(res) {
424
+      this.imgList5 = [
425
+        ...this.imgList5,
426
+        {
427
+          url: res.data
428
+        }
429
+      ];
430
+      this.loading.close();
431
+    },
432
+    handleMapImgSuccess(res) {
433
+      this.building = { ...this.building, mapImg: res.data };
434
+      this.loading.close();
435
+    },
436
+    handlePosterSuccess(res) {
437
+      this.building = { ...this.building, poster: res.data };
438
+      this.loading.close();
439
+    },
440
+    handleAparmentSuccess(res) {
441
+      this.aparmentImg = [
442
+        ...this.aparmentImg,
443
+        {
444
+          url: res.data
445
+        }
446
+      ];
447
+      this.loading.close();
448
+    },
449
+    onSubmit() {
450
+      const imgs = this.imgList.map((x, i) => {
451
+        return {
452
+          imgType: "banner",
453
+          url: x.url,
454
+          orderNo: i + 1
455
+        };
456
+      });
457
+      const tag = this.tags.map(x => {
458
+        return {
459
+          tagName: x
460
+        };
461
+      });
462
+      const building = {
463
+        ...this.building,
464
+        img: imgs,
465
+        propertyType: this.buildingProperty.join(","),
466
+        tag
467
+      };
468
+      if (!building.buildingId) {
469
+        // 新增
470
+        this.addBuilding({
471
+          onSuccess: this.onCancel,
472
+          detail: JSON.stringify(building)
473
+        });
474
+      } else {
475
+        // 修改
476
+        this.editBuilding({
477
+          onSuccess: this.onCancel,
478
+          detail: JSON.stringify(building)
479
+        });
480
+      }
481
+    },
482
+    FormatDate(date) {
483
+      return (date || "").split("T")[0] === "0001-01-01"
484
+        ? ""
485
+        : (date || "").split("T")[0];
486
+    },
487
+    saveAparment() {
488
+      const imgs = this.aparmentImg.map((x, i) => {
489
+        return {
490
+          imgType: "aparment",
491
+          url: x.url,
492
+          orderNo: i + 1
493
+        };
494
+      });
495
+      if (!this.aparmentInfo.apartmentId) {
496
+        this.addApartment(
497
+          JSON.stringify({
498
+            ...this.aparmentInfo,
499
+            img: imgs
500
+          })
501
+        ).then(() => {
502
+          this.getAparmentList();
503
+          this.showHx = false;
504
+        });
505
+      } else {
506
+        this.editApartment(
507
+          JSON.stringify({
508
+            ...this.aparmentInfo,
509
+            img: imgs
510
+          })
511
+        ).then(() => {
512
+          this.getAparmentList();
513
+          this.showHx = false;
514
+        });
515
+      }
516
+    },
517
+    addHx() {
518
+      this.aparmentImg = [];
519
+      this.aparmentInfo = { buildingId: this.building.buildingId };
520
+      this.showHx = true;
521
+    },
522
+    getAparmentList() {
523
+      this.getApartments({ buildingId: this.$route.query.id }).then(data => {
524
+        this.aparments = data;
525
+      });
526
+    },
527
+    handleEdit(row) {
528
+      this.aparmentImg = [];
529
+      this.getApartmentDetail({
530
+        id: row.apartmentId
531
+      }).then(data => {
532
+        console.log("...", data);
533
+        this.aparmentImg = data.buildingImgList.map(x => {
534
+          return {
535
+            name: x.imgId,
536
+            url: x.url
537
+          };
538
+        });
539
+        this.aparmentInfo = data;
540
+        this.showHx = true;
541
+      });
542
+    },
543
+    handleDel(row) {
544
+      this.$confirm("确认删除此数据?", "提示", {
545
+        confirmButtonText: "确定",
546
+        cancelButtonText: "取消",
547
+        type: "warning"
548
+      }).then(() => {
549
+        if (this.building.status === 1) {
550
+          this.$message.error("当前楼盘处于发布状态,不允许删除!");
551
+          return false;
552
+        }
553
+        this.deleteApartment({
554
+          id: row.apartmentId
555
+        }).then(() => {
556
+          this.getAparmentList();
557
+        });
558
+      });
559
+    }
560
+  },
561
+  mounted() {
562
+    const _that = this;
563
+    const phoneEditor = new E("#websiteEditorElem");
564
+    phoneEditor.customConfig.onchange = function(html) {
565
+      _that.dynamic = { ..._that.dynamic, url: html };
566
+    };
567
+    // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
568
+    // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
569
+
570
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
571
+      _that.uploadImg(files[0]).then(data => {
572
+        insert(data);
573
+      });
574
+    };
575
+    phoneEditor.customConfig.menus = [
576
+      "head", // 标题
577
+      "bold", // 粗体
578
+      "fontSize", // 字号
579
+      "fontName", // 字体
580
+      "italic", // 斜体
581
+      "underline", // 下划线
582
+      "strikeThrough", // 删除线
583
+      "foreColor", // 文字颜色
584
+      "backColor", // 背景颜色
585
+      "justify", // 对齐方式
586
+      "image", // 插入图片
587
+      "link", // 插入链接
588
+      "list", // 列表
589
+      "quote", // 引用
590
+      "emoticon", // 表情
591
+      "table", // 表格
592
+      "video", // 插入视频
593
+      "code", // 插入代码
594
+      "undo", // 撤销
595
+      "redo" // 重复
596
+    ];
597
+    phoneEditor.create();
598
+
599
+    this.getBuildings({
600
+      pageNum: 1,
601
+      pageSize: 100
602
+    }).then(() => {
603
+      if ((this.$route.query.id || "") !== "") {
604
+        this.getDetail({ id: this.$route.query.id }).then(data => {
605
+          phoneEditor.txt.html(data.url);
606
+        });
607
+      }
608
+    });
609
+  }
610
+};
611
+</script>
612
+
613
+<style lang="scss">
614
+.avatar-uploader .el-upload {
615
+  border: 1px dashed #d9d9d9;
616
+  border-radius: 6px;
617
+  cursor: pointer;
618
+  position: relative;
619
+  overflow: hidden;
620
+}
621
+.avatar-uploader .el-upload:hover {
622
+  border-color: #409eff;
623
+}
624
+.avatar-uploader-icon {
625
+  font-size: 28px;
626
+  color: #8c939d;
627
+  width: 160px;
628
+  height: 160px;
629
+  line-height: 160px;
630
+  text-align: center;
631
+}
632
+.avatar {
633
+  width: 160px;
634
+  height: 160px;
635
+  display: block;
636
+}
637
+.el-input {
638
+  max-width: 500px;
639
+}
640
+.search {
641
+  margin-bottom: 20px;
642
+  .el-input {
643
+    max-width: 240px;
644
+  }
645
+  .el-button {
646
+    margin: 0 20px;
647
+  }
648
+}
649
+
650
+.flex-item .amap-demo {
651
+  height: 300px;
652
+}
653
+.apartment-box {
654
+  width: 50%;
655
+  padding: 20px 0;
656
+  display: inline-block;
657
+  .el-input {
658
+    max-width: 300px;
659
+  }
660
+  .el-select {
661
+    max-width: 250px !important;
662
+    margin-right: 20px;
663
+  }
664
+}
665
+.title{
666
+  font-size: 20px;
667
+  font-weight: 600;
668
+  color: #000;
669
+  margin: 8px 20px;
670
+}
671
+</style>

+ 280
- 0
src/views/project/list.vue Целия файл

@@ -0,0 +1,280 @@
1
+<template>
2
+  <div>
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增</el-button>
7
+        </div>
8
+        <ul>
9
+          <li>
10
+            <span>项目名称</span>
11
+            <el-input v-model="name" placeholder="项目名称"></el-input>
12
+          </li>
13
+          <li>
14
+            <span>项目状态</span>
15
+            <el-select v-model="buildingId" placeholder="项目状态">
16
+              <el-option
17
+                v-for="item in buildings.list || []"
18
+                :key="item.buildingId"
19
+                :label="item.buildingName"
20
+                :value="item.buildingId">
21
+              </el-option>
22
+            </el-select>
23
+          </li>
24
+        </ul>
25
+        <el-button
26
+          size="mini"
27
+          type="primary" @click="search">查询</el-button>
28
+      </div>
29
+      <div class="moreFilter"></div>
30
+    </div>
31
+    <el-table :data="dynamics.list || []" style="width: 100%">
32
+      <!-- <el-table-column
33
+        type="index"
34
+        width="50">
35
+        <template slot-scope="scope">
36
+          <span>{{ GetIndex(scope.$index) }}</span>
37
+        </template>
38
+      </el-table-column> -->
39
+      <!-- <el-table-column
40
+        label="项目动态主图">
41
+        <template slot-scope="scope">
42
+          <div class="header">
43
+            <img :src="scope.row.imgUrl" alt="" />
44
+          </div>
45
+        </template>
46
+      </el-table-column> -->
47
+      <el-table-column
48
+        prop="title"
49
+        label="项目名称">
50
+      </el-table-column>
51
+      <el-table-column
52
+        prop="desc"
53
+        label="类型">
54
+      </el-table-column>
55
+      <el-table-column
56
+        prop="desc"
57
+        label="城市">
58
+      </el-table-column>
59
+      <el-table-column
60
+        prop="desc"
61
+        label="均价">
62
+      </el-table-column>
63
+      <el-table-column
64
+        prop="desc"
65
+        label="项目联系人">
66
+      </el-table-column>
67
+      <el-table-column
68
+        prop="desc"
69
+        label="联系电话">
70
+      </el-table-column>
71
+      <el-table-column
72
+        prop="desc"
73
+        label="地址"
74
+        width="240"
75
+        >
76
+      </el-table-column>
77
+      <el-table-column
78
+        label="项目状态"
79
+        >
80
+        <template slot-scope="scope">
81
+          <span :style="{color:(scope.row.status == 1?'':'red')}">{{scope.row.status == 1 ? '启用' : '禁用'}}</span>
82
+        </template>
83
+      </el-table-column>
84
+      <el-table-column
85
+        fixed="right"
86
+        label="操作"
87
+        width="180">
88
+        <template slot-scope="scope">
89
+          <el-button type="text" @click="handleEdit(scope.row)" size="small">{{scope.row.status == 1?'停用':'启用'}}</el-button>
90
+          <el-button type="text" @click="handleEdit(scope.row)" size="small">编辑</el-button>
91
+          <!-- <el-button type="text" @click="handlePulic(scope.row)" size="small" v-if="scope.row.status === 0">发布</el-button>
92
+          <el-button type="text" @click="handleUnPulic(scope.row)" size="small" v-if="scope.row.status === 1">取消发布</el-button>
93
+          <el-button @click="handleDel(scope.row)" type="text" size="small">删除</el-button> -->
94
+        </template>
95
+      </el-table-column>
96
+    </el-table>
97
+    <el-pagination
98
+      small
99
+      style="margin-top:10px;"
100
+      layout="prev, pager, next"
101
+      :current-page.sync="currentPage"
102
+      :pageSize="pageSize"
103
+      :total="dynamics.total || 0"
104
+      @current-change="getList"
105
+    >
106
+    </el-pagination>
107
+  </div>
108
+</template>
109
+
110
+<script>
111
+import { createNamespacedHelpers } from "vuex";
112
+
113
+const {
114
+  mapState: mapDynamicState,
115
+  mapActions: mapDynamicActions
116
+} = createNamespacedHelpers("dynamic");
117
+const {
118
+  mapState: mapBuildingState,
119
+  mapActions: mapBuildingActions
120
+} = createNamespacedHelpers("building");
121
+
122
+export default {
123
+  data() {
124
+    return {
125
+      pageSize: 20,
126
+      currentPage: 1,
127
+      name: "",
128
+      buildingId: ""
129
+    };
130
+  },
131
+  computed: {
132
+    ...mapDynamicState({
133
+      dynamics: x => x.dynamics
134
+    }),
135
+    ...mapBuildingState({
136
+      buildings: x => x.buildings
137
+    })
138
+  },
139
+  methods: {
140
+    ...mapDynamicActions([
141
+      "getDynamics",
142
+      "setDetailNull",
143
+      "deleteDynamics",
144
+      "publicDynamic",
145
+      "cancelDynamic"
146
+    ]),
147
+    ...mapBuildingActions(["getBuildings"]),
148
+    GetIndex(inx) {
149
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
150
+    },
151
+    FormatDate(date) {
152
+      if (date) {
153
+        return dayjs(date).formate("yyyy-MM-DD HH:mm:ss");
154
+      } else {
155
+        return "";
156
+      }
157
+    },
158
+    getList() {
159
+      this.getDynamics({
160
+        pageNum: this.currentPage,
161
+        pageSize: this.pageSize,
162
+        name: this.name,
163
+        buildingId: this.buildingId
164
+      });
165
+    },
166
+    getBuildingName(id) {
167
+      return (
168
+        ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {})
169
+          .buildingName || ""
170
+      );
171
+    },
172
+    search() {
173
+      this.currentPage = 1;
174
+      this.getList();
175
+    },
176
+    handleEdit(row) {
177
+      this.setDetailNull();
178
+      this.$router.push({ name: "projectedit", query: { id: row.dynamicId } });
179
+    },
180
+    handlePulic(row) {
181
+      this.$confirm("确认发布此数据?", "提示", {
182
+        confirmButtonText: "确定",
183
+        cancelButtonText: "取消",
184
+        type: "warning"
185
+      }).then(() => {
186
+        this.publicDynamic({
187
+          id: row.dynamicId
188
+        }).then(() => {
189
+          this.getList();
190
+        });
191
+      });
192
+    },
193
+    handleUnPulic(row) {
194
+      this.$confirm("确认取消发布此数据?", "提示", {
195
+        confirmButtonText: "确定",
196
+        cancelButtonText: "取消",
197
+        type: "warning"
198
+      }).then(() => {
199
+        this.cancelDynamic({
200
+          id: row.dynamicId
201
+        }).then(() => {
202
+          this.getList();
203
+        });
204
+      });
205
+    },
206
+    handleDel(row) {
207
+      this.$confirm("确认删除此数据?", "提示", {
208
+        confirmButtonText: "确定",
209
+        cancelButtonText: "取消",
210
+        type: "warning"
211
+      }).then(() => {
212
+        if (row.status === 1) {
213
+          this.$message.error("当前活动处于发布状态,不允许删除!");
214
+          return false;
215
+        }
216
+        this.deleteDynamics({
217
+          id: row.dynamicId
218
+        }).then(() => {
219
+          this.getList();
220
+        });
221
+      });
222
+    },
223
+    addDynamic() {
224
+      this.setDetailNull();
225
+      this.$router.push({ name: "projectedit" });
226
+    }
227
+  },
228
+  created() {
229
+    this.getBuildings({
230
+      pageNum: 1,
231
+      pageSize: 100
232
+    }).then(() => {
233
+      this.getList();
234
+    });
235
+  }
236
+};
237
+</script>
238
+
239
+<style lang="scss" scoped>
240
+.header {
241
+  width: 50px;
242
+  height: 50px;
243
+  img {
244
+    width: 100%;
245
+    height: 100%;
246
+  }
247
+}
248
+
249
+.system-table-search {
250
+  width: calc(100% - 40px);
251
+  margin: 20px auto 0;
252
+}
253
+
254
+.system-table-search ul > li {
255
+  margin-right: 20px;
256
+  display: flex;
257
+  float: left;
258
+  align-items: center;
259
+  span {
260
+    margin-right: 10px;
261
+  }
262
+}
263
+
264
+.system-table-search ul {
265
+  font-size: 15px;
266
+  white-space: nowrap;
267
+}
268
+
269
+.flex-h {
270
+  display: flex;
271
+  align-items: center;
272
+}
273
+
274
+.flex-item {
275
+  flex: 1;
276
+  -webkit-flex: 1;
277
+  position: relative;
278
+  overflow: hidden;
279
+}
280
+</style>

+ 237
- 0
src/views/systemManagement/keyWords.vue Целия файл

@@ -0,0 +1,237 @@
1
+<template>
2
+  <div>
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增</el-button>
7
+        </div>
8
+      </div>
9
+    </div>
10
+    <el-table :data="dynamics.list || []" >
11
+      <el-table-column
12
+        type="index">
13
+        <template slot-scope="scope">
14
+          <span>{{ GetIndex(scope.$index) }}</span>
15
+        </template>
16
+      </el-table-column>
17
+      <el-table-column
18
+        prop="title"
19
+        label="关键字">
20
+      </el-table-column>
21
+      <el-table-column
22
+        prop="createDate"
23
+        label="操作时间">
24
+      </el-table-column>
25
+      <el-table-column
26
+        fixed="right"
27
+        label="操作">
28
+        <template slot-scope="scope">
29
+          <el-button type="text" @click="handleDel(scope.row)" size="small">删除</el-button>
30
+        </template>
31
+      </el-table-column>
32
+    </el-table>
33
+      <el-dialog title="新增" :modal-append-to-body='false' :visible.sync="dialogFormVisible">
34
+          <el-form :model="form"  >
35
+              <el-form-item label="所属项目:" :label-width="formLabelWidth">
36
+                <el-select v-model="form.region" placeholder="请选择所属项目">
37
+                  <el-option label="区域一" value="shanghai"></el-option>
38
+                  <el-option label="区域二" value="beijing"></el-option>
39
+                </el-select>
40
+            </el-form-item>
41
+            <el-form-item label="关键字:" :label-width="formLabelWidth">
42
+                <el-input v-model="form.name" auto-complete="off"></el-input>
43
+              </el-form-item>
44
+          </el-form>
45
+          <div slot="footer" class="dialog-footer">
46
+            <el-button type="primary" @click="dialogFormVisible = false">保 存</el-button>
47
+            <el-button @click="dialogFormVisible = false">取 消</el-button>
48
+          </div>
49
+      </el-dialog>
50
+    <el-pagination
51
+      small
52
+      style="margin-top:10px;"
53
+      layout="prev, pager, next"
54
+      :current-page.sync="currentPage"
55
+      :pageSize="pageSize"
56
+      :total="dynamics.total || 0"
57
+      @current-change="getList"
58
+    >
59
+    </el-pagination>
60
+  </div>
61
+</template>
62
+
63
+<script>
64
+import { createNamespacedHelpers } from "vuex";
65
+
66
+const {
67
+  mapState: mapDynamicState,
68
+  mapActions: mapDynamicActions
69
+} = createNamespacedHelpers("dynamic");
70
+const {
71
+  mapState: mapBuildingState,
72
+  mapActions: mapBuildingActions
73
+} = createNamespacedHelpers("building");
74
+
75
+export default {
76
+  data() {
77
+    return {
78
+      dialogFormVisible: false, //新增弹框
79
+      pageSize: 20,
80
+      currentPage: 1,
81
+      name: "",
82
+      buildingId: "",
83
+      form: {
84
+        name: "",
85
+        region: ""
86
+      },
87
+      formLabelWidth: "150px"
88
+    };
89
+  },
90
+  computed: {
91
+    ...mapDynamicState({
92
+      dynamics: x => x.dynamics
93
+    }),
94
+    ...mapBuildingState({
95
+      buildings: x => x.buildings
96
+    })
97
+  },
98
+  methods: {
99
+    ...mapDynamicActions([
100
+      "getDynamics",
101
+      "setDetailNull",
102
+      "deleteDynamics",
103
+      "publicDynamic",
104
+      "cancelDynamic"
105
+    ]),
106
+    ...mapBuildingActions(["getBuildings"]),
107
+    GetIndex(inx) {
108
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
109
+    },
110
+    FormatDate(date) {
111
+      if (date) {
112
+        return dayjs(date).formate("yyyy-MM-DD HH:mm:ss");
113
+      } else {
114
+        return "";
115
+      }
116
+    },
117
+    getList() {
118
+      this.getDynamics({
119
+        pageNum: this.currentPage,
120
+        pageSize: this.pageSize,
121
+        name: this.name,
122
+        buildingId: this.buildingId
123
+      });
124
+    },
125
+    getBuildingName(id) {
126
+      return (
127
+        ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {})
128
+          .buildingName || ""
129
+      );
130
+    },
131
+    search() {
132
+      this.currentPage = 1;
133
+      this.getList();
134
+    },
135
+    handleDel(row) {
136
+      this.setDetailNull();
137
+       this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
138
+          confirmButtonText: '确定',
139
+          cancelButtonText: '取消',
140
+          type: 'warning'
141
+        }).then(() => {
142
+          this.$message({
143
+            type: 'success',
144
+            message: '删除成功!'
145
+          });
146
+        }).catch(() => {
147
+          this.$message({
148
+            type: 'info',
149
+            message: '已取消删除'
150
+          });          
151
+        });
152
+    },
153
+    handlePulic(row) {
154
+      this.$confirm("确认发布此数据?", "提示", {
155
+        confirmButtonText: "确定",
156
+        cancelButtonText: "取消",
157
+        type: "warning"
158
+      }).then(() => {
159
+        this.publicDynamic({
160
+          id: row.dynamicId
161
+        }).then(() => {
162
+          this.getList();
163
+        });
164
+      });
165
+    },
166
+    handleUnPulic(row) {
167
+      this.$confirm("确认取消发布此数据?", "提示", {
168
+        confirmButtonText: "确定",
169
+        cancelButtonText: "取消",
170
+        type: "warning"
171
+      }).then(() => {
172
+        this.cancelDynamic({
173
+          id: row.dynamicId
174
+        }).then(() => {
175
+          this.getList();
176
+        });
177
+      });
178
+    },
179
+    // handleDel(row) {
180
+    //   this.$confirm("确认删除此数据?", "提示", {
181
+    //     confirmButtonText: "确定",
182
+    //     cancelButtonText: "取消",
183
+    //     type: "warning"
184
+    //   }).then(() => {
185
+    //     if (row.status === 1) {
186
+    //       this.$message.error("当前活动处于发布状态,不允许删除!");
187
+    //       return false;
188
+    //     }
189
+    //     this.deleteDynamics({
190
+    //       id: row.dynamicId
191
+    //     }).then(() => {
192
+    //       this.getList();
193
+    //     });
194
+    //   });
195
+    // },
196
+    addDynamic() {
197
+      this.dialogFormVisible = true;
198
+    }
199
+  },
200
+  created() {
201
+    this.getBuildings({
202
+      pageNum: 1,
203
+      pageSize: 100
204
+    }).then(() => {
205
+      this.getList();
206
+    });
207
+  }
208
+};
209
+</script>
210
+
211
+<style lang="scss" scoped>
212
+.header {
213
+  width: 50px;
214
+  height: 50px;
215
+  img {
216
+    width: 100%;
217
+    height: 100%;
218
+  }
219
+}
220
+
221
+.system-table-search {
222
+  width: calc(100% - 40px);
223
+  margin: 20px auto 0;
224
+}
225
+
226
+.flex-h {
227
+  display: flex;
228
+  display: -webkit-flex;
229
+}
230
+
231
+.flex-item {
232
+  flex: 1;
233
+  -webkit-flex: 1;
234
+  position: relative;
235
+  overflow: hidden;
236
+}
237
+</style>

+ 224
- 0
src/views/systemManagement/pushMessage.vue Целия файл

@@ -0,0 +1,224 @@
1
+<template>
2
+  <div>
3
+    <el-table
4
+      :data="dynamics.list || []"
5
+      >
6
+      <el-table-column
7
+        type="index">
8
+        <template slot-scope="scope">
9
+          <span>{{ GetIndex(scope.$index) }}</span>
10
+        </template>
11
+      </el-table-column>
12
+      <el-table-column
13
+        prop="title"
14
+        label="标题">
15
+      </el-table-column>
16
+      <el-table-column
17
+        prop="createDate"
18
+        label="提示内容">
19
+      </el-table-column>
20
+      <el-table-column
21
+        fixed="right"
22
+        label="操作"
23
+        width="180">
24
+        <template slot-scope="scope">
25
+          <el-button type="text" @click="handleEdit(scope.row)" size="small">编辑</el-button>
26
+        </template>
27
+      </el-table-column>
28
+    </el-table>
29
+    <el-pagination
30
+      small
31
+      style="margin-top:10px;"
32
+      layout="prev, pager, next"
33
+      :current-page.sync="currentPage"
34
+      :pageSize="pageSize"
35
+      :total="dynamics.total || 0"
36
+      @current-change="getList"
37
+    >
38
+    </el-pagination>
39
+    <el-dialog title="编辑" :modal-append-to-body='false' :visible.sync="dialogFormVisible">
40
+          <el-form :model="form"  >
41
+              <el-form-item label="所属项目:" :label-width="formLabelWidth">
42
+                <el-select v-model="form.region" placeholder="请选择所属项目">
43
+                  <el-option label="区域一" value="shanghai"></el-option>
44
+                  <el-option label="区域二" value="beijing"></el-option>
45
+                </el-select>
46
+            </el-form-item>
47
+            <el-form-item label="标题:" :label-width="formLabelWidth">
48
+                <p>用户来访提醒</p>
49
+              </el-form-item>
50
+            <el-form-item label="提示内容:" :label-width="formLabelWidth">
51
+                <el-input v-model="form.name" auto-complete="off"></el-input>
52
+              </el-form-item>
53
+          </el-form>
54
+          <div slot="footer" class="dialog-footer">
55
+            <el-button type="primary" @click="dialogFormVisible = false">保 存</el-button>
56
+            <el-button @click="dialogFormVisible = false">取 消</el-button>
57
+          </div>
58
+      </el-dialog>
59
+  </div>
60
+</template>
61
+
62
+<script>
63
+import { createNamespacedHelpers } from "vuex";
64
+
65
+const {
66
+  mapState: mapDynamicState,
67
+  mapActions: mapDynamicActions
68
+} = createNamespacedHelpers("dynamic");
69
+const {
70
+  mapState: mapBuildingState,
71
+  mapActions: mapBuildingActions
72
+} = createNamespacedHelpers("building");
73
+
74
+export default {
75
+  data() {
76
+    return {
77
+      pageSize: 20,
78
+      currentPage: 1,
79
+      name: "",
80
+      buildingId: "",
81
+      dialogFormVisible:false,//编辑弹框
82
+      form: {
83
+          name: '',
84
+          region: ''
85
+        },
86
+        formLabelWidth: '150px'
87
+    };
88
+  },
89
+  computed: {
90
+    ...mapDynamicState({
91
+      dynamics: x => x.dynamics
92
+    }),
93
+    ...mapBuildingState({
94
+      buildings: x => x.buildings
95
+    })
96
+  },
97
+  methods: {
98
+    ...mapDynamicActions([
99
+      "getDynamics",
100
+      "setDetailNull",
101
+      "deleteDynamics",
102
+      "publicDynamic",
103
+      "cancelDynamic"
104
+    ]),
105
+    ...mapBuildingActions(["getBuildings"]),
106
+    GetIndex(inx) {
107
+      return (this.currentPage - 1) * this.pageSize + inx + 1;
108
+    },
109
+    FormatDate(date) {
110
+      if (date) {
111
+        return dayjs(date).formate("yyyy-MM-DD HH:mm:ss");
112
+      } else {
113
+        return "";
114
+      }
115
+    },
116
+    getList() {
117
+      this.getDynamics({
118
+        pageNum: this.currentPage,
119
+        pageSize: this.pageSize,
120
+        name: this.name,
121
+        buildingId: this.buildingId
122
+      });
123
+    },
124
+    getBuildingName(id) {
125
+      return (
126
+        ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {})
127
+          .buildingName || ""
128
+      );
129
+    },
130
+    search() {
131
+      this.currentPage = 1;
132
+      this.getList();
133
+    },
134
+    handleEdit(row) {
135
+      this.setDetailNull();
136
+      this.dialogFormVisible = true;
137
+    },
138
+    handlePulic(row) {
139
+      this.$confirm("确认发布此数据?", "提示", {
140
+        confirmButtonText: "确定",
141
+        cancelButtonText: "取消",
142
+        type: "warning"
143
+      }).then(() => {
144
+        this.publicDynamic({
145
+          id: row.dynamicId
146
+        }).then(() => {
147
+          this.getList();
148
+        });
149
+      });
150
+    },
151
+    handleUnPulic(row) {
152
+      this.$confirm("确认取消发布此数据?", "提示", {
153
+        confirmButtonText: "确定",
154
+        cancelButtonText: "取消",
155
+        type: "warning"
156
+      }).then(() => {
157
+        this.cancelDynamic({
158
+          id: row.dynamicId
159
+        }).then(() => {
160
+          this.getList();
161
+        });
162
+      });
163
+    },
164
+    handleDel(row) {
165
+      this.$confirm("确认删除此数据?", "提示", {
166
+        confirmButtonText: "确定",
167
+        cancelButtonText: "取消",
168
+        type: "warning"
169
+      }).then(() => {
170
+        if (row.status === 1) {
171
+          this.$message.error("当前活动处于发布状态,不允许删除!");
172
+          return false;
173
+        }
174
+        this.deleteDynamics({
175
+          id: row.dynamicId
176
+        }).then(() => {
177
+          this.getList();
178
+        });
179
+      });
180
+    }
181
+  },
182
+  created() {
183
+    this.getBuildings({
184
+      pageNum: 1,
185
+      pageSize: 100
186
+    }).then(() => {
187
+      this.getList();
188
+    });
189
+  }
190
+};
191
+</script>
192
+
193
+<style lang="scss" scoped>
194
+.header {
195
+  width: 50px;
196
+  height: 50px;
197
+  img {
198
+    width: 100%;
199
+    height: 100%;
200
+  }
201
+}
202
+
203
+.el-dialog{
204
+  z-index: 9999!important;
205
+  .el-form-item__content{
206
+    p{
207
+      margin: 0;
208
+    }
209
+  }
210
+}
211
+
212
+
213
+.flex-h {
214
+  display: flex;
215
+  display: -webkit-flex;
216
+}
217
+
218
+.flex-item {
219
+  flex: 1;
220
+  -webkit-flex: 1;
221
+  position: relative;
222
+  overflow: hidden;
223
+}
224
+</style>

+ 92
- 0
static/tinymce/jquery.tinymce.min.js Целия файл

@@ -0,0 +1,92 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+/**
8
+ * Jquery integration plugin.
9
+ *
10
+ * @class tinymce.core.JqueryIntegration
11
+ * @private
12
+ */
13
+!function(){var f,c,u,p,d,s=[];d="undefined"!=typeof global?global:window,p=d.jQuery;var v=function(){
14
+// Reference to tinymce needs to be lazily evaluated since tinymce
15
+// might be loaded through the compressor or other means
16
+return d.tinymce};p.fn.tinymce=function(o){var e,t,i,l=this,r="";
17
+// No match then just ignore the call
18
+if(!l.length)return l;
19
+// Get editor instance
20
+if(!o)return v()?v().get(l[0].id):null;l.css("visibility","hidden");// Hide textarea to avoid flicker
21
+var n=function(){var a=[],c=0;
22
+// Apply patches to the jQuery object, only once
23
+u||(m(),u=!0),
24
+// Create an editor instance for each matched node
25
+l.each(function(e,t){var n,i=t.id,r=o.oninit;
26
+// Generate unique id for target element if needed
27
+i||(t.id=i=v().DOM.uniqueId()),
28
+// Only init the editor once
29
+v().get(i)||(
30
+// Create editor instance and render it
31
+n=v().createEditor(i,o),a.push(n),n.on("init",function(){var e,t=r;l.css("visibility",""),
32
+// Run this if the oninit setting is defined
33
+// this logic will fire the oninit callback ones each
34
+// matched editor instance is initialized
35
+r&&++c==a.length&&("string"==typeof t&&(e=-1===t.indexOf(".")?null:v().resolve(t.replace(/\.\w+$/,"")),t=v().resolve(t)),
36
+// Call the oninit function with the object
37
+t.apply(e||v(),a))}))}),
38
+// Render the editor instances in a separate loop since we
39
+// need to have the full editors array used in the onInit calls
40
+p.each(a,function(e,t){t.render()})};
41
+// Load TinyMCE on demand, if we need to
42
+if(d.tinymce||c||!(e=o.script_url))
43
+// Delay the init call until tinymce is loaded
44
+1===c?s.push(n):n();else{c=1,t=e.substring(0,e.lastIndexOf("/")),
45
+// Check if it's a dev/src version they want to load then
46
+// make sure that all plugins, themes etc are loaded in source mode as well
47
+-1!=e.indexOf(".min")&&(r=".min"),
48
+// Setup tinyMCEPreInit object this will later be used by the TinyMCE
49
+// core script to locate other resources like CSS files, dialogs etc
50
+// You can also predefined a tinyMCEPreInit object and then it will use that instead
51
+d.tinymce=d.tinyMCEPreInit||{base:t,suffix:r},
52
+// url contains gzip then we assume it's a compressor
53
+-1!=e.indexOf("gzip")&&(i=o.language||"en",e=e+(/\?/.test(e)?"&":"?")+"js=true&core=true&suffix="+escape(r)+"&themes="+escape(o.theme||"modern")+"&plugins="+escape(o.plugins||"")+"&languages="+(i||""),
54
+// Check if compressor script is already loaded otherwise setup a basic one
55
+d.tinyMCE_GZ||(d.tinyMCE_GZ={start:function(){var n=function(e){v().ScriptLoader.markDone(v().baseURI.toAbsolute(e))};
56
+// Add core languages
57
+n("langs/"+i+".js"),
58
+// Add themes with languages
59
+n("themes/"+o.theme+"/theme"+r+".js"),n("themes/"+o.theme+"/langs/"+i+".js"),
60
+// Add plugins with languages
61
+p.each(o.plugins.split(","),function(e,t){t&&(n("plugins/"+t+"/plugin"+r+".js"),n("plugins/"+t+"/langs/"+i+".js"))})},end:function(){}}));var a=document.createElement("script");a.type="text/javascript",a.onload=a.onreadystatechange=function(e){e=e||window.event,2===c||"load"!=e.type&&!/complete|loaded/.test(a.readyState)||(v().dom.Event.domLoaded=1,c=2,
62
+// Execute callback after mainscript has been loaded and before the initialization occurs
63
+o.script_loaded&&o.script_loaded(),n(),p.each(s,function(e,t){t()}))},a.src=e,document.body.appendChild(a)}return l},
64
+// Add :tinymce pseudo selector this will select elements that has been converted into editor instances
65
+// it's now possible to use things like $('*:tinymce') to get all TinyMCE bound elements.
66
+p.extend(p.expr[":"],{tinymce:function(e){var t;return!!(e.id&&"tinymce"in d&&(t=v().get(e.id))&&t.editorManager===v())}});
67
+// This function patches internal jQuery functions so that if
68
+// you for example remove an div element containing an editor it's
69
+// automatically destroyed by the TinyMCE API
70
+var m=function(){
71
+// Removes any child editor instances by looking for editor wrapper elements
72
+var r=function(e){
73
+// If the function is remove
74
+"remove"===e&&this.each(function(e,t){var n=l(t);n&&n.remove()}),this.find("span.mceEditor,div.mceEditor").each(function(e,t){var n=v().get(t.id.replace(/_parent$/,""));n&&n.remove()})},o=function(i){var e,t=this;
75
+// Handle set value
76
+/*jshint eqnull:true */if(null!=i)r.call(t),
77
+// Saves the contents before get/set value of textarea/div
78
+t.each(function(e,t){var n;(n=v().get(t.id))&&n.setContent(i)});else if(0<t.length&&(e=v().get(t[0].id)))return e.getContent()},l=function(e){var t=null;return e&&e.id&&d.tinymce&&(t=v().get(e.id)),t},u=function(e){return!!(e&&e.length&&d.tinymce&&e.is(":tinymce"))},s={};
79
+// Loads or saves contents from/to textarea if the value
80
+// argument is defined it will set the TinyMCE internal contents
81
+// Patch some setter/getter functions these will
82
+// now be able to set/get the contents of editor instances for
83
+// example $('#editorid').html('Content'); will update the TinyMCE iframe instance
84
+p.each(["text","html","val"],function(e,t){var a=s[t]=p.fn[t],c="text"===t;p.fn[t]=function(e){var t=this;if(!u(t))return a.apply(t,arguments);if(e!==f)return o.call(t.filter(":tinymce"),e),a.apply(t.not(":tinymce"),arguments),t;// return original set for chaining
85
+var i="",r=arguments;return(c?t:t.eq(0)).each(function(e,t){var n=l(t);i+=n?c?n.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g,""):n.getContent({save:!0}):a.apply(p(t),r)}),i}}),
86
+// Makes it possible to use $('#id').append("content"); to append contents to the TinyMCE editor iframe
87
+p.each(["append","prepend"],function(e,t){var n=s[t]=p.fn[t],r="prepend"===t;p.fn[t]=function(i){var e=this;return u(e)?i!==f?("string"==typeof i&&e.filter(":tinymce").each(function(e,t){var n=l(t);n&&n.setContent(r?i+n.getContent():n.getContent()+i)}),n.apply(e.not(":tinymce"),arguments),e):void 0:n.apply(e,arguments)}}),
88
+// Makes sure that the editor instance gets properly destroyed when the parent element is removed
89
+p.each(["remove","replaceWith","replaceAll","empty"],function(e,t){var n=s[t]=p.fn[t];p.fn[t]=function(){return r.call(this,t),n.apply(this,arguments)}}),s.attr=p.fn.attr,
90
+// Makes sure that $('#tinymce_id').attr('value') gets the editors current HTML contents
91
+p.fn.attr=function(e,t){var n=this,i=arguments;if(!e||"value"!==e||!u(n))return s.attr.apply(n,i);if(t!==f)return o.call(n.filter(":tinymce"),t),s.attr.apply(n.not(":tinymce"),i),n;// return original set for chaining
92
+var r=n[0],a=l(r);return a?a.getContent({save:!0}):s.attr.apply(p(r),i)}}}();

+ 3
- 0
static/tinymce/langs/readme.md Целия файл

@@ -0,0 +1,3 @@
1
+This is where language files should be placed.
2
+
3
+Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/

+ 389
- 0
static/tinymce/langs/zh_CN.js Целия файл

@@ -0,0 +1,389 @@
1
+tinymce.addI18n('zh_CN',{
2
+"Redo": "\u91cd\u505a",
3
+"Undo": "\u64a4\u9500",
4
+"Cut": "\u526a\u5207",
5
+"Copy": "\u590d\u5236",
6
+"Paste": "\u7c98\u8d34",
7
+"Select all": "\u5168\u9009",
8
+"New document": "\u65b0\u6587\u4ef6",
9
+"Ok": "\u786e\u5b9a",
10
+"Cancel": "\u53d6\u6d88",
11
+"Visual aids": "\u7f51\u683c\u7ebf",
12
+"Bold": "\u7c97\u4f53",
13
+"Italic": "\u659c\u4f53",
14
+"Underline": "\u4e0b\u5212\u7ebf",
15
+"Strikethrough": "\u5220\u9664\u7ebf",
16
+"Superscript": "\u4e0a\u6807",
17
+"Subscript": "\u4e0b\u6807",
18
+"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
19
+"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
20
+"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
21
+"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
22
+"Justify": "\u4e24\u7aef\u5bf9\u9f50",
23
+"Bullet list": "\u9879\u76ee\u7b26\u53f7",
24
+"Numbered list": "\u7f16\u53f7\u5217\u8868",
25
+"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
26
+"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
27
+"Close": "\u5173\u95ed",
28
+"Formats": "\u683c\u5f0f",
29
+"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
30
+"Headers": "\u6807\u9898",
31
+"Header 1": "\u6807\u98981",
32
+"Header 2": "\u6807\u98982",
33
+"Header 3": "\u6807\u98983",
34
+"Header 4": "\u6807\u98984",
35
+"Header 5": "\u6807\u98985",
36
+"Header 6": "\u6807\u98986",
37
+"Headings": "\u6807\u9898",
38
+"Heading 1": "\u6807\u98981",
39
+"Heading 2": "\u6807\u98982",
40
+"Heading 3": "\u6807\u98983",
41
+"Heading 4": "\u6807\u98984",
42
+"Heading 5": "\u6807\u98985",
43
+"Heading 6": "\u6807\u98986",
44
+"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
45
+"Div": "Div",
46
+"Pre": "Pre",
47
+"Code": "\u4ee3\u7801",
48
+"Paragraph": "\u6bb5\u843d",
49
+"Blockquote": "\u5f15\u6587\u533a\u5757",
50
+"Inline": "\u6587\u672c",
51
+"Blocks": "\u57fa\u5757",
52
+"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
53
+"Fonts": "\u5b57\u4f53",
54
+"Font Sizes": "\u5b57\u53f7",
55
+"Class": "\u7c7b\u578b",
56
+"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
57
+"OR": "\u6216",
58
+"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
59
+"Upload": "\u4e0a\u4f20",
60
+"Block": "\u5757",
61
+"Align": "\u5bf9\u9f50",
62
+"Default": "\u9ed8\u8ba4",
63
+"Circle": "\u7a7a\u5fc3\u5706",
64
+"Disc": "\u5b9e\u5fc3\u5706",
65
+"Square": "\u65b9\u5757",
66
+"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
67
+"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
68
+"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
69
+"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
70
+"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
71
+"Anchor...": "\u951a\u70b9...",
72
+"Name": "\u540d\u79f0",
73
+"Id": "\u6807\u8bc6\u7b26",
74
+"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
75
+"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
76
+"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
77
+"Special characters...": "\u7279\u6b8a\u5b57\u7b26...",
78
+"Source code": "\u6e90\u4ee3\u7801",
79
+"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
80
+"Language": "\u8bed\u8a00",
81
+"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
82
+"Color Picker": "\u9009\u8272\u5668",
83
+"R": "R",
84
+"G": "G",
85
+"B": "B",
86
+"Left to right": "\u4ece\u5de6\u5230\u53f3",
87
+"Right to left": "\u4ece\u53f3\u5230\u5de6",
88
+"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
89
+"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
90
+"Title": "\u6807\u9898",
91
+"Keywords": "\u5173\u952e\u8bcd",
92
+"Description": "\u63cf\u8ff0",
93
+"Robots": "\u673a\u5668\u4eba",
94
+"Author": "\u4f5c\u8005",
95
+"Encoding": "\u7f16\u7801",
96
+"Fullscreen": "\u5168\u5c4f",
97
+"Action": "\u64cd\u4f5c",
98
+"Shortcut": "\u5feb\u6377\u952e",
99
+"Help": "\u5e2e\u52a9",
100
+"Address": "\u5730\u5740",
101
+"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
102
+"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
103
+"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
104
+"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
105
+"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
106
+"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
107
+"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
108
+"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
109
+"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
110
+"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
111
+"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
112
+"Plugins": "\u63d2\u4ef6",
113
+"Handy Shortcuts": "\u5feb\u6377\u952e",
114
+"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
115
+"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
116
+"Image description": "\u56fe\u7247\u63cf\u8ff0",
117
+"Source": "\u5730\u5740",
118
+"Dimensions": "\u5927\u5c0f",
119
+"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
120
+"General": "\u666e\u901a",
121
+"Advanced": "\u9ad8\u7ea7",
122
+"Style": "\u6837\u5f0f",
123
+"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
124
+"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
125
+"Border": "\u8fb9\u6846",
126
+"Insert image": "\u63d2\u5165\u56fe\u7247",
127
+"Image...": "\u56fe\u7247...",
128
+"Image list": "\u56fe\u7247\u5217\u8868",
129
+"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
130
+"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
131
+"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
132
+"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
133
+"Edit image": "\u7f16\u8f91\u56fe\u7247",
134
+"Image options": "\u56fe\u7247\u9009\u9879",
135
+"Zoom in": "\u653e\u5927",
136
+"Zoom out": "\u7f29\u5c0f",
137
+"Crop": "\u88c1\u526a",
138
+"Resize": "\u8c03\u6574\u5927\u5c0f",
139
+"Orientation": "\u65b9\u5411",
140
+"Brightness": "\u4eae\u5ea6",
141
+"Sharpen": "\u9510\u5316",
142
+"Contrast": "\u5bf9\u6bd4\u5ea6",
143
+"Color levels": "\u989c\u8272\u5c42\u6b21",
144
+"Gamma": "\u4f3d\u9a6c\u503c",
145
+"Invert": "\u53cd\u8f6c",
146
+"Apply": "\u5e94\u7528",
147
+"Back": "\u540e\u9000",
148
+"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
149
+"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
150
+"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
151
+"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
152
+"Text to display": "\u663e\u793a\u6587\u5b57",
153
+"Url": "\u5730\u5740",
154
+"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
155
+"Current window": "\u5f53\u524d\u7a97\u53e3",
156
+"None": "\u65e0",
157
+"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
158
+"Remove link": "\u5220\u9664\u94fe\u63a5",
159
+"Anchors": "\u951a\u70b9",
160
+"Link...": "\u94fe\u63a5...",
161
+"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
162
+"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
163
+"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
164
+"Link list": "\u94fe\u63a5\u5217\u8868",
165
+"Insert video": "\u63d2\u5165\u89c6\u9891",
166
+"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
167
+"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
168
+"Alternative source": "\u955c\u50cf",
169
+"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
170
+"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
171
+"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
172
+"Embed": "\u5185\u5d4c",
173
+"Media...": "\u591a\u5a92\u4f53...",
174
+"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
175
+"Page break": "\u5206\u9875\u7b26",
176
+"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
177
+"Preview": "\u9884\u89c8",
178
+"Print...": "\u6253\u5370...",
179
+"Save": "\u4fdd\u5b58",
180
+"Find": "\u67e5\u627e",
181
+"Replace with": "\u66ff\u6362\u4e3a",
182
+"Replace": "\u66ff\u6362",
183
+"Replace all": "\u5168\u90e8\u66ff\u6362",
184
+"Previous": "\u4e0a\u4e00\u4e2a",
185
+"Next": "\u4e0b\u4e00\u4e2a",
186
+"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
187
+"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
188
+"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
189
+"Find whole words only": "\u5168\u5b57\u5339\u914d",
190
+"Spell check": "\u62fc\u5199\u68c0\u67e5",
191
+"Ignore": "\u5ffd\u7565",
192
+"Ignore all": "\u5168\u90e8\u5ffd\u7565",
193
+"Finish": "\u5b8c\u6210",
194
+"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
195
+"Insert table": "\u63d2\u5165\u8868\u683c",
196
+"Table properties": "\u8868\u683c\u5c5e\u6027",
197
+"Delete table": "\u5220\u9664\u8868\u683c",
198
+"Cell": "\u5355\u5143\u683c",
199
+"Row": "\u884c",
200
+"Column": "\u5217",
201
+"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
202
+"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
203
+"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
204
+"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
205
+"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
206
+"Delete row": "\u5220\u9664\u884c",
207
+"Row properties": "\u884c\u5c5e\u6027",
208
+"Cut row": "\u526a\u5207\u884c",
209
+"Copy row": "\u590d\u5236\u884c",
210
+"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
211
+"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
212
+"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
213
+"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
214
+"Delete column": "\u5220\u9664\u5217",
215
+"Cols": "\u5217",
216
+"Rows": "\u884c",
217
+"Width": "\u5bbd",
218
+"Height": "\u9ad8",
219
+"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
220
+"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
221
+"Show caption": "\u663e\u793a\u6807\u9898",
222
+"Left": "\u5de6\u5bf9\u9f50",
223
+"Center": "\u5c45\u4e2d",
224
+"Right": "\u53f3\u5bf9\u9f50",
225
+"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
226
+"Scope": "\u8303\u56f4",
227
+"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
228
+"H Align": "\u6c34\u5e73\u5bf9\u9f50",
229
+"V Align": "\u5782\u76f4\u5bf9\u9f50",
230
+"Top": "\u9876\u90e8\u5bf9\u9f50",
231
+"Middle": "\u5782\u76f4\u5c45\u4e2d",
232
+"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
233
+"Header cell": "\u8868\u5934\u5355\u5143\u683c",
234
+"Row group": "\u884c\u7ec4",
235
+"Column group": "\u5217\u7ec4",
236
+"Row type": "\u884c\u7c7b\u578b",
237
+"Header": "\u8868\u5934",
238
+"Body": "\u8868\u4f53",
239
+"Footer": "\u8868\u5c3e",
240
+"Border color": "\u8fb9\u6846\u989c\u8272",
241
+"Insert template...": "\u63d2\u5165\u6a21\u677f...",
242
+"Templates": "\u6a21\u677f",
243
+"Template": "\u6a21\u677f",
244
+"Text color": "\u6587\u5b57\u989c\u8272",
245
+"Background color": "\u80cc\u666f\u8272",
246
+"Custom...": "\u81ea\u5b9a\u4e49...",
247
+"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
248
+"No color": "\u65e0",
249
+"Remove color": "\u79fb\u9664\u989c\u8272",
250
+"Table of Contents": "\u5185\u5bb9\u5217\u8868",
251
+"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
252
+"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
253
+"Word count": "\u5b57\u6570",
254
+"Words: {0}": "\u5b57\u6570\uff1a{0}",
255
+"{0} words": "{0} \u5b57",
256
+"File": "\u6587\u4ef6",
257
+"Edit": "\u7f16\u8f91",
258
+"Insert": "\u63d2\u5165",
259
+"View": "\u89c6\u56fe",
260
+"Format": "\u683c\u5f0f",
261
+"Table": "\u8868\u683c",
262
+"Tools": "\u5de5\u5177",
263
+"Powered by {0}": "\u7531{0}\u9a71\u52a8",
264
+"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
265
+"Image title": "\u56fe\u7247\u6807\u9898",
266
+"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
267
+"Border style": "\u8fb9\u6846\u6837\u5f0f",
268
+"Error": "\u9519\u8bef",
269
+"Warn": "\u8b66\u544a",
270
+"Valid": "\u6709\u6548",
271
+"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
272
+"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
273
+"System Font": "\u7cfb\u7edf\u5b57\u4f53",
274
+"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
275
+"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
276
+"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
277
+"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
278
+"example": "\u793a\u4f8b",
279
+"Search": "\u641c\u7d22",
280
+"All": "\u5168\u90e8",
281
+"Currency": "\u8d27\u5e01",
282
+"Text": "\u6587\u5b57",
283
+"Quotations": "\u5f15\u7528",
284
+"Mathematical": "\u6570\u5b66",
285
+"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
286
+"Symbols": "\u7b26\u53f7",
287
+"Arrows": "\u7bad\u5934",
288
+"User Defined": "\u81ea\u5b9a\u4e49",
289
+"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
290
+"currency sign": "\u8d27\u5e01\u7b26\u53f7",
291
+"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
292
+"colon sign": "\u5192\u53f7",
293
+"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
294
+"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
295
+"lira sign": "\u91cc\u62c9\u7b26\u53f7",
296
+"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
297
+"naira sign": "\u5948\u62c9\u7b26\u53f7",
298
+"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
299
+"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
300
+"won sign": "\u97e9\u5143\u7b26\u53f7",
301
+"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
302
+"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
303
+"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
304
+"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
305
+"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
306
+"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
307
+"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
308
+"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
309
+"austral sign": "\u6fb3\u5143\u7b26\u53f7",
310
+"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
311
+"cedi sign": "\u585e\u5730\u7b26\u53f7",
312
+"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
313
+"spesmilo sign": "spesmilo\u7b26\u53f7",
314
+"tenge sign": "\u575a\u6208\u7b26\u53f7",
315
+"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
316
+"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
317
+"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
318
+"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
319
+"ruble sign": "\u5362\u5e03\u7b26\u53f7",
320
+"yen character": "\u65e5\u5143\u5b57\u6837",
321
+"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
322
+"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
323
+"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
324
+"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
325
+"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
326
+"People": "\u4eba\u7c7b",
327
+"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
328
+"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
329
+"Activity": "\u6d3b\u52a8",
330
+"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
331
+"Objects": "\u7269\u4ef6",
332
+"Flags": "\u65d7\u5e1c",
333
+"Characters": "\u5b57\u7b26",
334
+"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
335
+"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
336
+"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
337
+"Update": "\u66f4\u65b0",
338
+"Color swatch": "\u989c\u8272\u6837\u672c",
339
+"Turquoise": "\u9752\u7eff\u8272",
340
+"Green": "\u7eff\u8272",
341
+"Blue": "\u84dd\u8272",
342
+"Purple": "\u7d2b\u8272",
343
+"Navy Blue": "\u6d77\u519b\u84dd",
344
+"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
345
+"Dark Green": "\u6df1\u7eff\u8272",
346
+"Medium Blue": "\u4e2d\u84dd\u8272",
347
+"Medium Purple": "\u4e2d\u7d2b\u8272",
348
+"Midnight Blue": "\u6df1\u84dd\u8272",
349
+"Yellow": "\u9ec4\u8272",
350
+"Orange": "\u6a59\u8272",
351
+"Red": "\u7ea2\u8272",
352
+"Light Gray": "\u6d45\u7070\u8272",
353
+"Gray": "\u7070\u8272",
354
+"Dark Yellow": "\u6697\u9ec4\u8272",
355
+"Dark Orange": "\u6df1\u6a59\u8272",
356
+"Dark Red": "\u6df1\u7ea2\u8272",
357
+"Medium Gray": "\u4e2d\u7070\u8272",
358
+"Dark Gray": "\u6df1\u7070\u8272",
359
+"Black": "\u9ed1\u8272",
360
+"White": "\u767d\u8272",
361
+"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
362
+"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
363
+"history": "\u5386\u53f2",
364
+"styles": "\u6837\u5f0f",
365
+"formatting": "\u683c\u5f0f\u5316",
366
+"alignment": "\u5bf9\u9f50",
367
+"indentation": "\u7f29\u8fdb",
368
+"permanent pen": "\u8bb0\u53f7\u7b14",
369
+"comments": "\u5907\u6ce8",
370
+"Anchor": "\u951a\u70b9",
371
+"Special character": "\u7279\u6b8a\u7b26\u53f7",
372
+"Code sample": "\u4ee3\u7801\u793a\u4f8b",
373
+"Color": "\u989c\u8272",
374
+"Emoticons": "\u8868\u60c5",
375
+"Document properties": "\u6587\u6863\u5c5e\u6027",
376
+"Image": "\u56fe\u7247",
377
+"Insert link": "\u63d2\u5165\u94fe\u63a5",
378
+"Target": "\u6253\u5f00\u65b9\u5f0f",
379
+"Link": "\u94fe\u63a5",
380
+"Poster": "\u5c01\u9762",
381
+"Media": "\u5a92\u4f53",
382
+"Print": "\u6253\u5370",
383
+"Prev": "\u4e0a\u4e00\u4e2a",
384
+"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
385
+"Whole words": "\u5168\u5b57\u5339\u914d",
386
+"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
387
+"Caption": "\u6807\u9898",
388
+"Insert template": "\u63d2\u5165\u6a21\u677f"
389
+});

+ 504
- 0
static/tinymce/license.txt Целия файл

@@ -0,0 +1,504 @@
1
+      GNU LESSER GENERAL PUBLIC LICENSE
2
+           Version 2.1, February 1999
3
+
4
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+[This is the first released version of the Lesser GPL.  It also counts
10
+ as the successor of the GNU Library Public License, version 2, hence
11
+ the version number 2.1.]
12
+
13
+          Preamble
14
+
15
+  The licenses for most software are designed to take away your
16
+freedom to share and change it.  By contrast, the GNU General Public
17
+Licenses are intended to guarantee your freedom to share and change
18
+free software--to make sure the software is free for all its users.
19
+
20
+  This license, the Lesser General Public License, applies to some
21
+specially designated software packages--typically libraries--of the
22
+Free Software Foundation and other authors who decide to use it.  You
23
+can use it too, but we suggest you first think carefully about whether
24
+this license or the ordinary General Public License is the better
25
+strategy to use in any particular case, based on the explanations below.
26
+
27
+  When we speak of free software, we are referring to freedom of use,
28
+not price.  Our General Public Licenses are designed to make sure that
29
+you have the freedom to distribute copies of free software (and charge
30
+for this service if you wish); that you receive source code or can get
31
+it if you want it; that you can change the software and use pieces of
32
+it in new free programs; and that you are informed that you can do
33
+these things.
34
+
35
+  To protect your rights, we need to make restrictions that forbid
36
+distributors to deny you these rights or to ask you to surrender these
37
+rights.  These restrictions translate to certain responsibilities for
38
+you if you distribute copies of the library or if you modify it.
39
+
40
+  For example, if you distribute copies of the library, whether gratis
41
+or for a fee, you must give the recipients all the rights that we gave
42
+you.  You must make sure that they, too, receive or can get the source
43
+code.  If you link other code with the library, you must provide
44
+complete object files to the recipients, so that they can relink them
45
+with the library after making changes to the library and recompiling
46
+it.  And you must show them these terms so they know their rights.
47
+
48
+  We protect your rights with a two-step method: (1) we copyright the
49
+library, and (2) we offer you this license, which gives you legal
50
+permission to copy, distribute and/or modify the library.
51
+
52
+  To protect each distributor, we want to make it very clear that
53
+there is no warranty for the free library.  Also, if the library is
54
+modified by someone else and passed on, the recipients should know
55
+that what they have is not the original version, so that the original
56
+author's reputation will not be affected by problems that might be
57
+introduced by others.
58
+
59
+  Finally, software patents pose a constant threat to the existence of
60
+any free program.  We wish to make sure that a company cannot
61
+effectively restrict the users of a free program by obtaining a
62
+restrictive license from a patent holder.  Therefore, we insist that
63
+any patent license obtained for a version of the library must be
64
+consistent with the full freedom of use specified in this license.
65
+
66
+  Most GNU software, including some libraries, is covered by the
67
+ordinary GNU General Public License.  This license, the GNU Lesser
68
+General Public License, applies to certain designated libraries, and
69
+is quite different from the ordinary General Public License.  We use
70
+this license for certain libraries in order to permit linking those
71
+libraries into non-free programs.
72
+
73
+  When a program is linked with a library, whether statically or using
74
+a shared library, the combination of the two is legally speaking a
75
+combined work, a derivative of the original library.  The ordinary
76
+General Public License therefore permits such linking only if the
77
+entire combination fits its criteria of freedom.  The Lesser General
78
+Public License permits more lax criteria for linking other code with
79
+the library.
80
+
81
+  We call this license the "Lesser" General Public License because it
82
+does Less to protect the user's freedom than the ordinary General
83
+Public License.  It also provides other free software developers Less
84
+of an advantage over competing non-free programs.  These disadvantages
85
+are the reason we use the ordinary General Public License for many
86
+libraries.  However, the Lesser license provides advantages in certain
87
+special circumstances.
88
+
89
+  For example, on rare occasions, there may be a special need to
90
+encourage the widest possible use of a certain library, so that it becomes
91
+a de-facto standard.  To achieve this, non-free programs must be
92
+allowed to use the library.  A more frequent case is that a free
93
+library does the same job as widely used non-free libraries.  In this
94
+case, there is little to gain by limiting the free library to free
95
+software only, so we use the Lesser General Public License.
96
+
97
+  In other cases, permission to use a particular library in non-free
98
+programs enables a greater number of people to use a large body of
99
+free software.  For example, permission to use the GNU C Library in
100
+non-free programs enables many more people to use the whole GNU
101
+operating system, as well as its variant, the GNU/Linux operating
102
+system.
103
+
104
+  Although the Lesser General Public License is Less protective of the
105
+users' freedom, it does ensure that the user of a program that is
106
+linked with the Library has the freedom and the wherewithal to run
107
+that program using a modified version of the Library.
108
+
109
+  The precise terms and conditions for copying, distribution and
110
+modification follow.  Pay close attention to the difference between a
111
+"work based on the library" and a "work that uses the library".  The
112
+former contains code derived from the library, whereas the latter must
113
+be combined with the library in order to run.
114
+
115
+      GNU LESSER GENERAL PUBLIC LICENSE
116
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117
+
118
+  0. This License Agreement applies to any software library or other
119
+program which contains a notice placed by the copyright holder or
120
+other authorized party saying it may be distributed under the terms of
121
+this Lesser General Public License (also called "this License").
122
+Each licensee is addressed as "you".
123
+
124
+  A "library" means a collection of software functions and/or data
125
+prepared so as to be conveniently linked with application programs
126
+(which use some of those functions and data) to form executables.
127
+
128
+  The "Library", below, refers to any such software library or work
129
+which has been distributed under these terms.  A "work based on the
130
+Library" means either the Library or any derivative work under
131
+copyright law: that is to say, a work containing the Library or a
132
+portion of it, either verbatim or with modifications and/or translated
133
+straightforwardly into another language.  (Hereinafter, translation is
134
+included without limitation in the term "modification".)
135
+
136
+  "Source code" for a work means the preferred form of the work for
137
+making modifications to it.  For a library, complete source code means
138
+all the source code for all modules it contains, plus any associated
139
+interface definition files, plus the scripts used to control compilation
140
+and installation of the library.
141
+
142
+  Activities other than copying, distribution and modification are not
143
+covered by this License; they are outside its scope.  The act of
144
+running a program using the Library is not restricted, and output from
145
+such a program is covered only if its contents constitute a work based
146
+on the Library (independent of the use of the Library in a tool for
147
+writing it).  Whether that is true depends on what the Library does
148
+and what the program that uses the Library does.
149
+  
150
+  1. You may copy and distribute verbatim copies of the Library's
151
+complete source code as you receive it, in any medium, provided that
152
+you conspicuously and appropriately publish on each copy an
153
+appropriate copyright notice and disclaimer of warranty; keep intact
154
+all the notices that refer to this License and to the absence of any
155
+warranty; and distribute a copy of this License along with the
156
+Library.
157
+
158
+  You may charge a fee for the physical act of transferring a copy,
159
+and you may at your option offer warranty protection in exchange for a
160
+fee.
161
+
162
+  2. You may modify your copy or copies of the Library or any portion
163
+of it, thus forming a work based on the Library, and copy and
164
+distribute such modifications or work under the terms of Section 1
165
+above, provided that you also meet all of these conditions:
166
+
167
+    a) The modified work must itself be a software library.
168
+
169
+    b) You must cause the files modified to carry prominent notices
170
+    stating that you changed the files and the date of any change.
171
+
172
+    c) You must cause the whole of the work to be licensed at no
173
+    charge to all third parties under the terms of this License.
174
+
175
+    d) If a facility in the modified Library refers to a function or a
176
+    table of data to be supplied by an application program that uses
177
+    the facility, other than as an argument passed when the facility
178
+    is invoked, then you must make a good faith effort to ensure that,
179
+    in the event an application does not supply such function or
180
+    table, the facility still operates, and performs whatever part of
181
+    its purpose remains meaningful.
182
+
183
+    (For example, a function in a library to compute square roots has
184
+    a purpose that is entirely well-defined independent of the
185
+    application.  Therefore, Subsection 2d requires that any
186
+    application-supplied function or table used by this function must
187
+    be optional: if the application does not supply it, the square
188
+    root function must still compute square roots.)
189
+
190
+These requirements apply to the modified work as a whole.  If
191
+identifiable sections of that work are not derived from the Library,
192
+and can be reasonably considered independent and separate works in
193
+themselves, then this License, and its terms, do not apply to those
194
+sections when you distribute them as separate works.  But when you
195
+distribute the same sections as part of a whole which is a work based
196
+on the Library, the distribution of the whole must be on the terms of
197
+this License, whose permissions for other licensees extend to the
198
+entire whole, and thus to each and every part regardless of who wrote
199
+it.
200
+
201
+Thus, it is not the intent of this section to claim rights or contest
202
+your rights to work written entirely by you; rather, the intent is to
203
+exercise the right to control the distribution of derivative or
204
+collective works based on the Library.
205
+
206
+In addition, mere aggregation of another work not based on the Library
207
+with the Library (or with a work based on the Library) on a volume of
208
+a storage or distribution medium does not bring the other work under
209
+the scope of this License.
210
+
211
+  3. You may opt to apply the terms of the ordinary GNU General Public
212
+License instead of this License to a given copy of the Library.  To do
213
+this, you must alter all the notices that refer to this License, so
214
+that they refer to the ordinary GNU General Public License, version 2,
215
+instead of to this License.  (If a newer version than version 2 of the
216
+ordinary GNU General Public License has appeared, then you can specify
217
+that version instead if you wish.)  Do not make any other change in
218
+these notices.
219
+
220
+  Once this change is made in a given copy, it is irreversible for
221
+that copy, so the ordinary GNU General Public License applies to all
222
+subsequent copies and derivative works made from that copy.
223
+
224
+  This option is useful when you wish to copy part of the code of
225
+the Library into a program that is not a library.
226
+
227
+  4. You may copy and distribute the Library (or a portion or
228
+derivative of it, under Section 2) in object code or executable form
229
+under the terms of Sections 1 and 2 above provided that you accompany
230
+it with the complete corresponding machine-readable source code, which
231
+must be distributed under the terms of Sections 1 and 2 above on a
232
+medium customarily used for software interchange.
233
+
234
+  If distribution of object code is made by offering access to copy
235
+from a designated place, then offering equivalent access to copy the
236
+source code from the same place satisfies the requirement to
237
+distribute the source code, even though third parties are not
238
+compelled to copy the source along with the object code.
239
+
240
+  5. A program that contains no derivative of any portion of the
241
+Library, but is designed to work with the Library by being compiled or
242
+linked with it, is called a "work that uses the Library".  Such a
243
+work, in isolation, is not a derivative work of the Library, and
244
+therefore falls outside the scope of this License.
245
+
246
+  However, linking a "work that uses the Library" with the Library
247
+creates an executable that is a derivative of the Library (because it
248
+contains portions of the Library), rather than a "work that uses the
249
+library".  The executable is therefore covered by this License.
250
+Section 6 states terms for distribution of such executables.
251
+
252
+  When a "work that uses the Library" uses material from a header file
253
+that is part of the Library, the object code for the work may be a
254
+derivative work of the Library even though the source code is not.
255
+Whether this is true is especially significant if the work can be
256
+linked without the Library, or if the work is itself a library.  The
257
+threshold for this to be true is not precisely defined by law.
258
+
259
+  If such an object file uses only numerical parameters, data
260
+structure layouts and accessors, and small macros and small inline
261
+functions (ten lines or less in length), then the use of the object
262
+file is unrestricted, regardless of whether it is legally a derivative
263
+work.  (Executables containing this object code plus portions of the
264
+Library will still fall under Section 6.)
265
+
266
+  Otherwise, if the work is a derivative of the Library, you may
267
+distribute the object code for the work under the terms of Section 6.
268
+Any executables containing that work also fall under Section 6,
269
+whether or not they are linked directly with the Library itself.
270
+
271
+  6. As an exception to the Sections above, you may also combine or
272
+link a "work that uses the Library" with the Library to produce a
273
+work containing portions of the Library, and distribute that work
274
+under terms of your choice, provided that the terms permit
275
+modification of the work for the customer's own use and reverse
276
+engineering for debugging such modifications.
277
+
278
+  You must give prominent notice with each copy of the work that the
279
+Library is used in it and that the Library and its use are covered by
280
+this License.  You must supply a copy of this License.  If the work
281
+during execution displays copyright notices, you must include the
282
+copyright notice for the Library among them, as well as a reference
283
+directing the user to the copy of this License.  Also, you must do one
284
+of these things:
285
+
286
+    a) Accompany the work with the complete corresponding
287
+    machine-readable source code for the Library including whatever
288
+    changes were used in the work (which must be distributed under
289
+    Sections 1 and 2 above); and, if the work is an executable linked
290
+    with the Library, with the complete machine-readable "work that
291
+    uses the Library", as object code and/or source code, so that the
292
+    user can modify the Library and then relink to produce a modified
293
+    executable containing the modified Library.  (It is understood
294
+    that the user who changes the contents of definitions files in the
295
+    Library will not necessarily be able to recompile the application
296
+    to use the modified definitions.)
297
+
298
+    b) Use a suitable shared library mechanism for linking with the
299
+    Library.  A suitable mechanism is one that (1) uses at run time a
300
+    copy of the library already present on the user's computer system,
301
+    rather than copying library functions into the executable, and (2)
302
+    will operate properly with a modified version of the library, if
303
+    the user installs one, as long as the modified version is
304
+    interface-compatible with the version that the work was made with.
305
+
306
+    c) Accompany the work with a written offer, valid for at
307
+    least three years, to give the same user the materials
308
+    specified in Subsection 6a, above, for a charge no more
309
+    than the cost of performing this distribution.
310
+
311
+    d) If distribution of the work is made by offering access to copy
312
+    from a designated place, offer equivalent access to copy the above
313
+    specified materials from the same place.
314
+
315
+    e) Verify that the user has already received a copy of these
316
+    materials or that you have already sent this user a copy.
317
+
318
+  For an executable, the required form of the "work that uses the
319
+Library" must include any data and utility programs needed for
320
+reproducing the executable from it.  However, as a special exception,
321
+the materials to be distributed need not include anything that is
322
+normally distributed (in either source or binary form) with the major
323
+components (compiler, kernel, and so on) of the operating system on
324
+which the executable runs, unless that component itself accompanies
325
+the executable.
326
+
327
+  It may happen that this requirement contradicts the license
328
+restrictions of other proprietary libraries that do not normally
329
+accompany the operating system.  Such a contradiction means you cannot
330
+use both them and the Library together in an executable that you
331
+distribute.
332
+
333
+  7. You may place library facilities that are a work based on the
334
+Library side-by-side in a single library together with other library
335
+facilities not covered by this License, and distribute such a combined
336
+library, provided that the separate distribution of the work based on
337
+the Library and of the other library facilities is otherwise
338
+permitted, and provided that you do these two things:
339
+
340
+    a) Accompany the combined library with a copy of the same work
341
+    based on the Library, uncombined with any other library
342
+    facilities.  This must be distributed under the terms of the
343
+    Sections above.
344
+
345
+    b) Give prominent notice with the combined library of the fact
346
+    that part of it is a work based on the Library, and explaining
347
+    where to find the accompanying uncombined form of the same work.
348
+
349
+  8. You may not copy, modify, sublicense, link with, or distribute
350
+the Library except as expressly provided under this License.  Any
351
+attempt otherwise to copy, modify, sublicense, link with, or
352
+distribute the Library is void, and will automatically terminate your
353
+rights under this License.  However, parties who have received copies,
354
+or rights, from you under this License will not have their licenses
355
+terminated so long as such parties remain in full compliance.
356
+
357
+  9. You are not required to accept this License, since you have not
358
+signed it.  However, nothing else grants you permission to modify or
359
+distribute the Library or its derivative works.  These actions are
360
+prohibited by law if you do not accept this License.  Therefore, by
361
+modifying or distributing the Library (or any work based on the
362
+Library), you indicate your acceptance of this License to do so, and
363
+all its terms and conditions for copying, distributing or modifying
364
+the Library or works based on it.
365
+
366
+  10. Each time you redistribute the Library (or any work based on the
367
+Library), the recipient automatically receives a license from the
368
+original licensor to copy, distribute, link with or modify the Library
369
+subject to these terms and conditions.  You may not impose any further
370
+restrictions on the recipients' exercise of the rights granted herein.
371
+You are not responsible for enforcing compliance by third parties with
372
+this License.
373
+
374
+  11. If, as a consequence of a court judgment or allegation of patent
375
+infringement or for any other reason (not limited to patent issues),
376
+conditions are imposed on you (whether by court order, agreement or
377
+otherwise) that contradict the conditions of this License, they do not
378
+excuse you from the conditions of this License.  If you cannot
379
+distribute so as to satisfy simultaneously your obligations under this
380
+License and any other pertinent obligations, then as a consequence you
381
+may not distribute the Library at all.  For example, if a patent
382
+license would not permit royalty-free redistribution of the Library by
383
+all those who receive copies directly or indirectly through you, then
384
+the only way you could satisfy both it and this License would be to
385
+refrain entirely from distribution of the Library.
386
+
387
+If any portion of this section is held invalid or unenforceable under any
388
+particular circumstance, the balance of the section is intended to apply,
389
+and the section as a whole is intended to apply in other circumstances.
390
+
391
+It is not the purpose of this section to induce you to infringe any
392
+patents or other property right claims or to contest validity of any
393
+such claims; this section has the sole purpose of protecting the
394
+integrity of the free software distribution system which is
395
+implemented by public license practices.  Many people have made
396
+generous contributions to the wide range of software distributed
397
+through that system in reliance on consistent application of that
398
+system; it is up to the author/donor to decide if he or she is willing
399
+to distribute software through any other system and a licensee cannot
400
+impose that choice.
401
+
402
+This section is intended to make thoroughly clear what is believed to
403
+be a consequence of the rest of this License.
404
+
405
+  12. If the distribution and/or use of the Library is restricted in
406
+certain countries either by patents or by copyrighted interfaces, the
407
+original copyright holder who places the Library under this License may add
408
+an explicit geographical distribution limitation excluding those countries,
409
+so that distribution is permitted only in or among countries not thus
410
+excluded.  In such case, this License incorporates the limitation as if
411
+written in the body of this License.
412
+
413
+  13. The Free Software Foundation may publish revised and/or new
414
+versions of the Lesser General Public License from time to time.
415
+Such new versions will be similar in spirit to the present version,
416
+but may differ in detail to address new problems or concerns.
417
+
418
+Each version is given a distinguishing version number.  If the Library
419
+specifies a version number of this License which applies to it and
420
+"any later version", you have the option of following the terms and
421
+conditions either of that version or of any later version published by
422
+the Free Software Foundation.  If the Library does not specify a
423
+license version number, you may choose any version ever published by
424
+the Free Software Foundation.
425
+
426
+  14. If you wish to incorporate parts of the Library into other free
427
+programs whose distribution conditions are incompatible with these,
428
+write to the author to ask for permission.  For software which is
429
+copyrighted by the Free Software Foundation, write to the Free
430
+Software Foundation; we sometimes make exceptions for this.  Our
431
+decision will be guided by the two goals of preserving the free status
432
+of all derivatives of our free software and of promoting the sharing
433
+and reuse of software generally.
434
+
435
+          NO WARRANTY
436
+
437
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446
+
447
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456
+DAMAGES.
457
+
458
+         END OF TERMS AND CONDITIONS
459
+
460
+           How to Apply These Terms to Your New Libraries
461
+
462
+  If you develop a new library, and you want it to be of the greatest
463
+possible use to the public, we recommend making it free software that
464
+everyone can redistribute and change.  You can do so by permitting
465
+redistribution under these terms (or, alternatively, under the terms of the
466
+ordinary General Public License).
467
+
468
+  To apply these terms, attach the following notices to the library.  It is
469
+safest to attach them to the start of each source file to most effectively
470
+convey the exclusion of warranty; and each file should have at least the
471
+"copyright" line and a pointer to where the full notice is found.
472
+
473
+    <one line to give the library's name and a brief idea of what it does.>
474
+    Copyright (C) <year>  <name of author>
475
+
476
+    This library is free software; you can redistribute it and/or
477
+    modify it under the terms of the GNU Lesser General Public
478
+    License as published by the Free Software Foundation; either
479
+    version 2.1 of the License, or (at your option) any later version.
480
+
481
+    This library is distributed in the hope that it will be useful,
482
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
483
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
484
+    Lesser General Public License for more details.
485
+
486
+    You should have received a copy of the GNU Lesser General Public
487
+    License along with this library; if not, write to the Free Software
488
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
489
+
490
+Also add information on how to contact you by electronic and paper mail.
491
+
492
+You should also get your employer (if you work as a programmer) or your
493
+school, if any, to sign a "copyright disclaimer" for the library, if
494
+necessary.  Here is a sample; alter the names:
495
+
496
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
497
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
498
+
499
+  <signature of Ty Coon>, 1 April 1990
500
+  Ty Coon, President of Vice
501
+
502
+That's all there is to it!
503
+
504
+

+ 9
- 0
static/tinymce/plugins/advlist/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var n,t,e,r,u=tinymce.util.Tools.resolve("tinymce.PluginManager"),v=tinymce.util.Tools.resolve("tinymce.util.Tools"),O=function(n,t,e){var r="UL"===t?"InsertUnorderedList":"InsertOrderedList";n.execCommand(r,!1,!1===e?null:{"list-style-type":e})},o=function(e){e.addCommand("ApplyUnorderedListStyle",function(n,t){O(e,"UL",t["list-style-type"])}),e.addCommand("ApplyOrderedListStyle",function(n,t){O(e,"OL",t["list-style-type"])})},i=function(n){var t=n.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman");return t?t.split(/[ ,]/):[]},l=function(n){var t=n.getParam("advlist_bullet_styles","default,circle,square");return t?t.split(/[ ,]/):[]},c=function(n){return function(){return n}},s=c(!1),f=c(!0),a=s,d=f,g=function(){return p},p=(r={fold:function(n,t){return n()},is:a,isSome:a,isNone:d,getOr:e=function(n){return n},getOrThunk:t=function(n){return n()},getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:function(){return null},getOrUndefined:function(){return undefined},or:e,orThunk:t,map:g,ap:g,each:function(){},bind:g,flatten:g,exists:a,forall:d,filter:g,equals:n=function(n){return n.isNone()},equals_:n,toArray:function(){return[]},toString:c("none()")},Object.freeze&&Object.freeze(r),r),m=function(e){var n=function(){return e},t=function(){return u},r=function(n){return n(e)},u={fold:function(n,t){return t(e)},is:function(n){return e===n},isSome:d,isNone:a,getOr:n,getOrThunk:n,getOrDie:n,getOrNull:n,getOrUndefined:n,or:t,orThunk:t,map:function(n){return m(n(e))},ap:function(n){return n.fold(g,function(n){return m(n(e))})},each:function(n){n(e)},bind:r,flatten:n,exists:r,forall:r,filter:function(n){return n(e)?u:p},equals:function(n){return n.is(e)},equals_:function(n,t){return n.fold(a,function(n){return t(e,n)})},toArray:function(){return[e]},toString:function(){return"some("+e+")"}};return u},y=function(n){return null===n||n===undefined?p:m(n)},h=function(n){return n&&/^(TH|TD)$/.test(n.nodeName)},L=function(r){return function(n){return n&&/^(OL|UL|DL)$/.test(n.nodeName)&&(e=n,(t=r).$.contains(t.getBody(),e));var t,e}},N=function(n){var t=n.dom.getParent(n.selection.getNode(),"ol,ul"),e=n.dom.getStyle(t,"listStyleType");return y(e)},S=function(n,t,e){var r=function(n,t){for(var e=0;e<n.length;e++)if(t(n[e]))return e;return-1}(t.parents,h),u=-1!==r?t.parents.slice(0,r):t.parents,o=v.grep(u,L(n));return 0<o.length&&o[0].nodeName===e},T=function(n,t,e,r,u,o){var i,l,c,s,f,a,d,g,p,m,y;0<o.length?(d=t,g=e,p=r,m=u,y=o,(a=n).ui.registry.addSplitButton(d,{tooltip:g,icon:"OL"===m?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:function(n){n(v.map(y,function(n){return{type:"choiceitem",value:"default"===n?"":n,icon:"list-"+("OL"===m?"num":"bull")+"-"+("disc"===n||"decimal"===n?"default":n),text:n.replace(/\-/g," ").replace(/\b\w/g,function(n){return n.toUpperCase()})}}))},onAction:function(){return a.execCommand(p)},onItemAction:function(n,t){O(a,m,t)},select:function(t){return N(a).map(function(n){return t===n}).getOr(!1)},onSetup:function(t){var n=function(n){t.setActive(S(a,n,m))};return a.on("NodeChange",n),function(){return a.off("NodeChange",n)}}})):(l=t,c=e,s=r,f=u,(i=n).ui.registry.addToggleButton(l,{active:!1,tooltip:c,icon:"OL"===f?"ordered-list":"unordered-list",onSetup:function(t){var n=function(n){t.setActive(S(i,n,f))};return i.on("NodeChange",n),function(){return i.off("NodeChange",n)}},onAction:function(){return i.execCommand(s)}}))},b=function(n){T(n,"numlist","Numbered list","InsertOrderedList","OL",i(n)),T(n,"bullist","Bullet list","InsertUnorderedList","UL",l(n))};!function A(){u.add("advlist",function(n){var t,e,r;e="lists",r=(t=n).settings.plugins?t.settings.plugins:"",-1!==v.inArray(r.split(/[ ,]/),e)&&(b(n),o(n))})}()}();

+ 9
- 0
static/tinymce/plugins/anchor/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(e){return/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(e)},t=function(e){var t=e.selection.getNode();return"A"===t.tagName&&""===e.dom.getAttrib(t,"href")?t.getAttribute("id")||t.getAttribute("name"):""},r=function(e,t){var n=e.selection.getNode();"A"===n.tagName&&""===e.dom.getAttrib(n,"href")?(n.removeAttribute("name"),n.id=t,e.undoManager.add()):(e.focus(),e.selection.collapse(!0),e.execCommand("mceInsertContent",!1,e.dom.createHTML("a",{id:t})))},n=function(o){var e=t(o);o.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:e},onSubmit:function(e){var t,n;t=o,n=e.getData().id,(a(n)?(r(t,n),0):(t.windowManager.alert("Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),1))||e.close()}})},o=function(e){e.addCommand("mceAnchor",function(){n(e)})},i=function(o){return function(e){for(var t=0;t<e.length;t++)(n=e[t]).attr("href")||!n.attr("id")&&!n.attr("name")||n.firstChild||e[t].attr("contenteditable",o);var n}},c=function(e){e.on("PreInit",function(){e.parser.addNodeFilter("a",i("false")),e.serializer.addNodeFilter("a",i(null))})},d=function(t){t.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:function(){return t.execCommand("mceAnchor")},onSetup:function(e){return t.selection.selectorChangedWithUnbind("a:not([href])",e.setActive).unbind}}),t.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:function(){return t.execCommand("mceAnchor")}})};!function u(){e.add("anchor",function(e){c(e),o(e),d(e)})}()}();

+ 9
- 0
static/tinymce/plugins/autolink/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=tinymce.util.Tools.resolve("tinymce.Env"),m=function(e){return e.getParam("autolink_pattern",/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i)},y=function(e){return e.getParam("default_link_target","")},o=function(e,t){if(t<0&&(t=0),3===e.nodeType){var n=e.data.length;n<t&&(t=n)}return t},k=function(e,t,n){1!==t.nodeType||t.hasChildNodes()?e.setStart(t,o(t,n)):e.setStartBefore(t)},p=function(e,t,n){1!==t.nodeType||t.hasChildNodes()?e.setEnd(t,o(t,n)):e.setEndAfter(t)},r=function(e,t,n){var i,o,r,a,f,s,d,l,c,u,g=m(e),h=y(e);if("A"!==e.selection.getNode().tagName){if((i=e.selection.getRng(!0).cloneRange()).startOffset<5){if(!(l=i.endContainer.previousSibling)){if(!i.endContainer.firstChild||!i.endContainer.firstChild.nextSibling)return;l=i.endContainer.firstChild.nextSibling}if(c=l.length,k(i,l,c),p(i,l,c),i.endOffset<5)return;o=i.endOffset,a=l}else{if(3!==(a=i.endContainer).nodeType&&a.firstChild){for(;3!==a.nodeType&&a.firstChild;)a=a.firstChild;3===a.nodeType&&(k(i,a,0),p(i,a,a.nodeValue.length))}o=1===i.endOffset?2:i.endOffset-1-t}for(r=o;k(i,a,2<=o?o-2:0),p(i,a,1<=o?o-1:0),o-=1," "!==(u=i.toString())&&""!==u&&160!==u.charCodeAt(0)&&0<=o-2&&u!==n;);var C;(C=i.toString())===n||" "===C||160===C.charCodeAt(0)?(k(i,a,o),p(i,a,r),o+=1):(0===i.startOffset?k(i,a,0):k(i,a,o),p(i,a,r)),"."===(s=i.toString()).charAt(s.length-1)&&p(i,a,r-1),(d=(s=i.toString().trim()).match(g))&&("www."===d[1]?d[1]="http://www.":/@$/.test(d[1])&&!/^mailto:/.test(d[1])&&(d[1]="mailto:"+d[1]),f=e.selection.getBookmark(),e.selection.setRng(i),e.execCommand("createlink",!1,d[1]+d[2]),h&&e.dom.setAttrib(e.selection.getNode(),"target",h),e.selection.moveToBookmark(f),e.nodeChanged())}},t=function(t){var n;t.on("keydown",function(e){13!==e.keyCode||r(t,-1,"")}),i.ie&&i.ie<=11?t.on("focus",function(){if(!n){n=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(e){}}}):(t.on("keypress",function(e){41!==e.keyCode||r(t,-1,"(")}),t.on("keyup",function(e){32!==e.keyCode||r(t,0,"")}))};!function n(){e.add("autolink",function(e){t(e)})}()}();

+ 9
- 0
static/tinymce/plugins/autoresize/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var i=function(e){var t=e,n=function(){return t};return{get:n,set:function(e){t=e},clone:function(){return i(n())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),h=function(e){return e.fire("ResizeEditor")},v=function(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")},y=function(e){return e.getParam("max_height",0,"number")},o=function(e){return e.getParam("autoresize_overflow_padding",1,"number")},p=function(e){return e.getParam("autoresize_bottom_margin",50,"number")},u=function(e){return e.getParam("autoresize_on_init",!0,"boolean")},a=function(e,t,n,i,o){r.setEditorTimeout(e,function(){b(e,t),n--?a(e,t,n,i,o):o&&o()},i)},z=function(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))},C=function(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o},b=function(e,t){var n,i,o,r=e.dom,u=e.getDoc();if(u)if((a=e).plugins.fullscreen&&a.plugins.fullscreen.isFullscreen())z(e,!0);else{var a,s=u.documentElement,f=p(e);i=v(e);var c=C(r,s,"margin-top",!0),g=C(r,s,"margin-bottom",!0);(o=s.offsetHeight+c+g+f)<0&&(o=0);var l=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;o+l>v(e)&&(i=o+l);var m=y(e);m&&m<i?(i=m,z(e,!0)):z(e,!1),i!==t.get()&&(n=i-t.get(),r.setStyle(e.getContainer(),"height",i+"px"),t.set(i),h(e),d.webkit&&n<0&&b(e,t))}},n={setup:function(t,n){t.on("init",function(){var e=o(t);t.dom.setStyles(t.getBody(),{paddingLeft:e,paddingRight:e,"min-height":0})}),t.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",function(e){b(t,n)}),u(t)&&t.on("init",function(){a(t,n,20,100,function(){a(t,n,5,1e3)})})},resize:b},s=function(e,t){e.addCommand("mceAutoResize",function(){n.resize(e,t)})};!function t(){e.add("autoresize",function(e){if(e.settings.hasOwnProperty("resize")||(e.settings.resize=!1),!e.inline){var t=i(0);s(e,t),n.setup(e,t)}})}()}();

+ 9
- 0
static/tinymce/plugins/autosave/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(r){"use strict";var o=function(t){var e=t,r=function(){return e};return{get:r,set:function(t){e=t},clone:function(){return o(r())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),i=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=function(t,e){var r=t||e,n=/^(\d+)([ms]?)$/.exec(""+r);return(n[2]?{s:1e3,m:6e4}[n[2]]:1)*parseInt(r,10)},s=function(t){var e=t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-");return e=(e=(e=(e=e.replace(/\{path\}/g,r.document.location.pathname)).replace(/\{query\}/g,r.document.location.search)).replace(/\{hash\}/g,r.document.location.hash)).replace(/\{id\}/g,t.id)},c=function(t,e){var r=t.settings.forced_root_block;return""===(e=i.trim(void 0===e?t.getBody().innerHTML:e))||new RegExp("^<"+r+"[^>]*>((\xa0|&nbsp;|[ \t]|<br[^>]*>)+?|)</"+r+">|<br>$","i").test(e)},f=function(t){var e=parseInt(a.getItem(s(t)+"time"),10)||0;return!((new Date).getTime()-e>u(t.settings.autosave_retention,"20m"))||(l(t,!1),!1)},l=function(t,e){var r=s(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&t.fire("RemoveDraft")},m=function(t){var e=s(t);!c(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))},v=function(t){var e=s(t);f(t)&&(t.setContent(a.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))},d=function(t,e){var r=u(t.settings.autosave_interval,"30s");e.get()||(n.setInterval(function(){t.removed||m(t)},r),e.set(!0))},g=function(t){t.undoManager.transact(function(){v(t),l(t)}),t.focus()};function y(n){for(var o=[],t=1;t<arguments.length;t++)o[t-1]=arguments[t];return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var r=o.concat(t);return n.apply(null,r)}}var p=tinymce.util.Tools.resolve("tinymce.EditorManager"),D=function(r,t){return function(t){t.setDisabled(!f(r));var e=function(){return t.setDisabled(!f(r))};return r.on("StoreDraft RestoreDraft RemoveDraft",e),function(){return r.off("StoreDraft RestoreDraft RemoveDraft",e)}}};!function e(){t.add("autosave",function(t){var e,r,n=o(!1);return t.editorManager.on("BeforeUnload",function(t){var e;i.each(p.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e&&(t.preventDefault(),t.returnValue=e)}),d(e=t,n),e.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:function(){g(e)},onSetup:D(e)}),e.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:function(){g(e)},onSetup:D(e)}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&v(t)}),{hasDraft:y(f,r=t),storeDraft:y(m,r),restoreDraft:y(v,r),removeDraft:y(l,r),isEmpty:y(c,r)}})}()}(window);

+ 9
- 0
static/tinymce/plugins/bbcode/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),e=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=function(t){t=e.trim(t);var o=function(o,e){t=t.replace(o,e)};return o(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),o(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),o(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),o(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),o(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),o(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),o(/<font>(.*?)<\/font>/gi,"$1"),o(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),o(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),o(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),o(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),o(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),o(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),o(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),o(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),o(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),o(/<\/(strong|b)>/gi,"[/b]"),o(/<(strong|b)>/gi,"[b]"),o(/<\/(em|i)>/gi,"[/i]"),o(/<(em|i)>/gi,"[i]"),o(/<\/u>/gi,"[/u]"),o(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),o(/<u>/gi,"[u]"),o(/<blockquote[^>]*>/gi,"[quote]"),o(/<\/blockquote>/gi,"[/quote]"),o(/<br \/>/gi,"\n"),o(/<br\/>/gi,"\n"),o(/<br>/gi,"\n"),o(/<p>/gi,""),o(/<\/p>/gi,"\n"),o(/&nbsp;|\u00a0/gi," "),o(/&quot;/gi,'"'),o(/&lt;/gi,"<"),o(/&gt;/gi,">"),o(/&amp;/gi,"&"),t},i=function(t){t=e.trim(t);var o=function(o,e){t=t.replace(o,e)};return o(/\n/gi,"<br />"),o(/\[b\]/gi,"<strong>"),o(/\[\/b\]/gi,"</strong>"),o(/\[i\]/gi,"<em>"),o(/\[\/i\]/gi,"</em>"),o(/\[u\]/gi,"<u>"),o(/\[\/u\]/gi,"</u>"),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),o(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),o(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),o(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span>&nbsp;'),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span>&nbsp;'),t};!function n(){o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=i(o.content)}),o.on("PostProcess",function(o){o.set&&(o.content=i(o.content)),o.get&&(o.content=t(o.content))})})}()}();

+ 9
- 0
static/tinymce/plugins/charmap/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/code/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e,n){e.focus(),e.undoManager.transact(function(){e.setContent(n)}),e.selection.setCursorLocation(),e.nodeChanged()},o=function(e){return e.getContent({source_view:!0})},n=function(n){var e=o(n);n.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:e},onSubmit:function(e){t(n,e.getData().code),e.close()}})},c=function(e){e.addCommand("mceCodeEditor",function(){n(e)})},i=function(e){e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:function(){return n(e)}}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:function(){return n(e)}})};!function u(){e.add("code",function(e){return c(e),i(e),{}})}()}();

+ 9
- 0
static/tinymce/plugins/codesample/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/colorpicker/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(o){"use strict";var i=tinymce.util.Tools.resolve("tinymce.PluginManager");!function n(){i.add("colorpicker",function(){o.console.warn("Color picker plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

+ 9
- 0
static/tinymce/plugins/contextmenu/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(n){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager");!function e(){o.add("contextmenu",function(){n.console.warn("Context menu plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

+ 9
- 0
static/tinymce/plugins/directionality/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(c){"use strict";var n,t,e,r,o,u,i=tinymce.util.Tools.resolve("tinymce.PluginManager"),f=tinymce.util.Tools.resolve("tinymce.util.Tools"),d=function(n,t){var e,r=n.dom,o=n.selection.getSelectedBlocks();o.length&&(e=r.getAttrib(o[0],"dir"),f.each(o,function(n){r.getParent(n.parentNode,'*[dir="'+t+'"]',r.getRoot())||r.setAttrib(n,"dir",e!==t?t:null)}),n.nodeChanged())},l=function(n){n.addCommand("mceDirectionLTR",function(){d(n,"ltr")}),n.addCommand("mceDirectionRTL",function(){d(n,"rtl")})},a=function(n){return function(){return n}},m=a(!1),N=a(!0),s=m,g=N,T=function(){return E},E=(r={fold:function(n,t){return n()},is:s,isSome:s,isNone:g,getOr:e=function(n){return n},getOrThunk:t=function(n){return n()},getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:function(){return null},getOrUndefined:function(){return undefined},or:e,orThunk:t,map:T,ap:T,each:function(){},bind:T,flatten:T,exists:s,forall:g,filter:T,equals:n=function(n){return n.isNone()},equals_:n,toArray:function(){return[]},toString:a("none()")},Object.freeze&&Object.freeze(r),r),O=function(e){var n=function(){return e},t=function(){return o},r=function(n){return n(e)},o={fold:function(n,t){return t(e)},is:function(n){return e===n},isSome:g,isNone:s,getOr:n,getOrThunk:n,getOrDie:n,getOrNull:n,getOrUndefined:n,or:t,orThunk:t,map:function(n){return O(n(e))},ap:function(n){return n.fold(T,function(n){return O(n(e))})},each:function(n){n(e)},bind:r,flatten:n,exists:r,forall:r,filter:function(n){return n(e)?o:E},equals:function(n){return n.is(e)},equals_:function(n,t){return n.fold(s,function(n){return t(e,n)})},toArray:function(){return[e]},toString:function(){return"some("+e+")"}};return o},y=function(n){return null===n||n===undefined?E:O(n)},D=function(n){if(null===n||n===undefined)throw new Error("Node cannot be null or undefined");return{dom:a(n)}},p={fromHtml:function(n,t){var e=(t||c.document).createElement("div");if(e.innerHTML=n,!e.hasChildNodes()||1<e.childNodes.length)throw c.console.error("HTML does not have a single root node",n),new Error("HTML must have a single root node");return D(e.childNodes[0])},fromTag:function(n,t){var e=(t||c.document).createElement(n);return D(e)},fromText:function(n,t){var e=(t||c.document).createTextNode(n);return D(e)},fromDom:D,fromPoint:function(n,t,e){var r=n.dom();return y(r.elementFromPoint(t,e)).map(D)}},h=(o="function",function(n){return function(n){if(null===n)return"null";var t=typeof n;return"object"===t&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"===t&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":t}(n)===o}),_=Array.prototype.slice,v=(h(Array.from)&&Array.from,c.Node.ATTRIBUTE_NODE,c.Node.CDATA_SECTION_NODE,c.Node.COMMENT_NODE,c.Node.DOCUMENT_NODE,c.Node.DOCUMENT_TYPE_NODE,c.Node.DOCUMENT_FRAGMENT_NODE,c.Node.ELEMENT_NODE,c.Node.TEXT_NODE),C=(c.Node.PROCESSING_INSTRUCTION_NODE,c.Node.ENTITY_REFERENCE_NODE,c.Node.ENTITY_NODE,c.Node.NOTATION_NODE,u=v,function(n){return n.dom().nodeType===u}),A=function(n,t){var e,r,o=n.dom(),u=c.window.getComputedStyle(o).getPropertyValue(t),i=""!==u||(r=C(e=n)?e.dom().parentNode:e.dom())!==undefined&&null!==r&&r.ownerDocument.body.contains(r)?u:S(o,t);return null===i?undefined:i},S=function(n,t){return(e=n).style!==undefined&&h(e.style.getPropertyValue)?n.style.getPropertyValue(t):"";var e},R=function(t,r){return function(e){var n=function(n){var t=p.fromDom(n.element);e.setActive(("rtl"===A(t,"direction")?"rtl":"ltr")===r)};return t.on("NodeChange",n),function(){return t.off("NodeChange",n)}}},w=function(n){n.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:function(){return n.execCommand("mceDirectionLTR")},onSetup:R(n,"ltr")}),n.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:function(){return n.execCommand("mceDirectionRTL")},onSetup:R(n,"rtl")})};!function M(){i.add("directionality",function(n){l(n),w(n)})}()}(window);

+ 9015
- 0
static/tinymce/plugins/emoticons/js/emojis.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 2
- 0
static/tinymce/plugins/emoticons/js/emojis.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/emoticons/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/fullpage/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/fullscreen/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/help/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/hr/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),o=function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"<hr />")})},t=function(n){n.ui.registry.addButton("hr",{icon:"horizontal-rule",tooltip:"Horizontal line",onAction:function(){return n.execCommand("InsertHorizontalRule")}}),n.ui.registry.addMenuItem("hr",{icon:"horizontal-rule",text:"Horizontal line",onAction:function(){return n.execCommand("InsertHorizontalRule")}})};!function e(){n.add("hr",function(n){o(n),t(n)})}()}();

+ 9
- 0
static/tinymce/plugins/image/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/imagetools/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/importcss/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var t,e,n,r,o=tinymce.util.Tools.resolve("tinymce.PluginManager"),v=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),f=tinymce.util.Tools.resolve("tinymce.EditorManager"),m=tinymce.util.Tools.resolve("tinymce.Env"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),c=function(t){return t.getParam("importcss_merge_classes")},i=function(t){return t.getParam("importcss_exclusive")},h=function(t){return t.getParam("importcss_selector_converter")},l=function(t){return t.getParam("importcss_selector_filter")},p=function(t){return t.getParam("importcss_groups")},_=function(t){return t.getParam("importcss_append")},x=function(t){return t.getParam("importcss_file_filter")},u=function(t){return function(){return t}},s=u(!1),a=u(!0),g=function(){return y},y=(r={fold:function(t,e){return t()},is:s,isSome:s,isNone:a,getOr:n=function(t){return t},getOrThunk:e=function(t){return t()},getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:function(){return null},getOrUndefined:function(){return undefined},or:n,orThunk:e,map:g,ap:g,each:function(){},bind:g,flatten:g,exists:s,forall:a,filter:g,equals:t=function(t){return t.isNone()},equals_:t,toArray:function(){return[]},toString:u("none()")},Object.freeze&&Object.freeze(r),r),O=function(e){return function(t){return function(t){if(null===t)return"null";var e=typeof t;return"object"===e&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"===e&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":e}(t)===e}},T=O("array"),b=O("function"),k=Array.prototype.slice,S=Array.prototype.push,A=function(t,e){return function(t){for(var e=[],n=0,r=t.length;n<r;++n){if(!T(t[n]))throw new Error("Arr.flatten item "+n+" was not an array, input: "+t);S.apply(e,t[n])}return e}(function(t,e){for(var n=t.length,r=new Array(n),o=0;o<n;o++){var i=t[o];r[o]=e(i,o,t)}return r}(t,e))},P=(b(Array.from)&&Array.from,function(e){return"string"==typeof e?function(t){return-1!==t.indexOf(e)}:e instanceof RegExp?function(t){return e.test(t)}:e}),w=function(c,t,s){var a=[],n={};function l(t,e){var n,r,o,i=t.href;if(r=i,o=m.cacheSuffix,"string"==typeof r&&(r=r.replace("?"+o,"").replace("&"+o,"")),(i=r)&&s(i,e)&&!function(t,e){var n=t.settings,r=!1!==n.skin&&(n.skin||"oxide");if(r){var o=n.skin_url?t.documentBaseURI.toAbsolute(n.skin_url):f.baseURL+"/skins/ui/"+r,i=f.baseURL+"/skins/content/";return e===o+"/content"+(t.inline?".inline":"")+".min.css"||-1!==e.indexOf(i)}return!1}(c,i)){d.each(t.imports,function(t){l(t,!0)});try{n=t.cssRules||t.rules}catch(u){}d.each(n,function(t){t.styleSheet?l(t.styleSheet,!0):t.selectorText&&d.each(t.selectorText.split(","),function(t){a.push(d.trim(t))})})}}d.each(c.contentCSS,function(t){n[t]=!0}),s||(s=function(t,e){return e||n[t]});try{d.each(t.styleSheets,function(t){l(t)})}catch(e){}return a},E=function(t,e){var n,r=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(e);if(r){var o=r[1],i=r[2].substr(1).split(".").join(" "),u=d.makeMap("a,img");return r[1]?(n={title:e},t.schema.getTextBlockElements()[o]?n.block=o:t.schema.getBlockElements()[o]||u[o.toLowerCase()]?n.selector=o:n.inline=o):r[2]&&(n={inline:"span",title:e.substr(1),classes:i}),!1!==c(t)?n.classes=i:n.attributes={"class":i},n}},I=function(t,e){return null===e||!1!==i(t)},M=E,j=function(y){y.on("init",function(t){var e,n,r,o,i=(e=[],n=[],r={},{addItemToGroup:function(t,e){r[t]?r[t].push(e):(n.push(t),r[t]=[e])},addItem:function(t){e.push(t)},toFormats:function(){return A(n,function(t){var e=r[t];return 0===e.length?[]:[{title:t,items:e}]}).concat(e)}}),g={},u=P(l(y)),c=(o=p(y),d.map(o,function(t){return d.extend({},t,{original:t,selectors:{},filter:P(t.filter),item:{text:t.title,menu:[]}})})),s=function(t,e){if(f=t,p=g,!(I(y,m=e)?f in p:f in m.selectors)){s=t,l=g,I(y,a=e)?l[s]=!0:a.selectors[s]=!0;var n=(i=(o=y).plugins.importcss,u=t,((c=e)&&c.selector_converter?c.selector_converter:h(o)?h(o):function(){return E(o,u)}).call(i,u,c));if(n){var r=n.name||v.DOM.uniqueId();return y.formatter.register(r,n),d.extend({},{title:n.title,format:r})}}var o,i,u,c,s,a,l,f,m,p;return null};d.each(w(y,y.getDoc(),P(x(y))),function(n){if(-1===n.indexOf(".mce-")&&(!u||u(n))){var t=(r=c,o=n,d.grep(r,function(t){return!t.filter||t.filter(o)}));if(0<t.length)d.each(t,function(t){var e=s(n,t);e&&i.addItemToGroup(t.title,e)});else{var e=s(n,null);e&&i.addItem(e)}}var r,o});var a=i.toFormats();y.fire("addStyleModifications",{items:a,replace:!_(y)})})},D=function(e){return{convertSelectorToFormat:function(t){return M(e,t)}}};!function R(){o.add("importcss",function(t){return j(t),D(t)})}()}();

+ 9
- 0
static/tinymce/plugins/insertdatetime/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=function(e){return e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S"))},r=function(e){return e.getParam("insertdatetime_formats",["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"])},t=function(e){return e.getParam("insertdatetime_dateformat",e.translate("%Y-%m-%d"))},a=n,i=r,o=function(e){var t=r(e);return 0<t.length?t[0]:n(e)},l=function(e){return e.getParam("insertdatetime_element",!1)},u="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),c="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),m="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),s="January February March April May June July August September October November December".split(" "),d=function(e,t){if((e=""+e).length<t)for(var n=0;n<t-e.length;n++)e="0"+e;return e},f=function(e,t,n){return n=n||new Date,t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace("%D","%m/%d/%Y")).replace("%r","%I:%M:%S %p")).replace("%Y",""+n.getFullYear())).replace("%y",""+n.getYear())).replace("%m",d(n.getMonth()+1,2))).replace("%d",d(n.getDate(),2))).replace("%H",""+d(n.getHours(),2))).replace("%M",""+d(n.getMinutes(),2))).replace("%S",""+d(n.getSeconds(),2))).replace("%I",""+((n.getHours()+11)%12+1))).replace("%p",n.getHours()<12?"AM":"PM")).replace("%B",""+e.translate(s[n.getMonth()]))).replace("%b",""+e.translate(m[n.getMonth()]))).replace("%A",""+e.translate(c[n.getDay()]))).replace("%a",""+e.translate(u[n.getDay()]))).replace("%%","%")},p=function(e,t){if(l(e)){var n=f(e,t),r=void 0;r=/%[HMSIp]/.test(t)?f(e,"%Y-%m-%dT%H:%M"):f(e,"%Y-%m-%d");var a=e.dom.getParent(e.selection.getStart(),"time");a?(o=a,u=r,c=n,m=(i=e).dom.create("time",{datetime:u},c),o.parentNode.insertBefore(m,o),i.dom.remove(o),i.selection.select(m,!0),i.selection.collapse(!1)):e.insertContent('<time datetime="'+r+'">'+n+"</time>")}else e.insertContent(f(e,t));var i,o,u,c,m},g=f,y=function(e){e.addCommand("mceInsertDate",function(){p(e,t(e))}),e.addCommand("mceInsertTime",function(){p(e,a(e))})},M=tinymce.util.Tools.resolve("tinymce.util.Tools"),S=function(e){var t=e,n=function(){return t};return{get:n,set:function(e){t=e},clone:function(){return S(n())}}},v=function(n){var t=i(n),r=S(o(n));n.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:function(e){return e===r.get()},fetch:function(e){e(M.map(t,function(e){return{type:"choiceitem",text:g(n,e),value:e}}))},onAction:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];p(n,r.get())},onItemAction:function(e,t){r.set(t),p(n,t)}});n.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:function(){return M.map(t,function(e){return{type:"menuitem",text:g(n,e),onAction:(t=e,function(){r.set(t),p(n,t)})};var t})}})};!function h(){e.add("insertdatetime",function(e){y(e),v(e)})}()}();

+ 9
- 0
static/tinymce/plugins/legacyoutput/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools"),t=function(e){return e.getParam("font_formats")},i=function(e){return e.getParam("fontsize_formats")},n=function(e,t){e.settings.fontsize_formats=t},s=function(e,t){e.settings.font_formats=t},r=function(e){return e.getParam("font_size_style_values","xx-small,x-small,small,medium,large,x-large,xx-large")},o=function(e,t){e.settings.inline_styles=t},a=function(a){var e;o(e=a,!1),i(e)||n(e,"8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7"),t(e)||s(e,"Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats"),a.on("init",function(){return e=a,t="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table",i=l.explode(r(e)),n=e.schema,e.formatter.register({alignleft:{selector:t,attributes:{align:"left"}},aligncenter:{selector:t,attributes:{align:"center"}},alignright:{selector:t,attributes:{align:"right"}},alignjustify:{selector:t,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",toggle:!1,attributes:{face:"%value"}},fontsize:{inline:"font",toggle:!1,attributes:{size:function(e){return l.inArray(i,e.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0}}),l.each("b,i,u,strike".split(","),function(e){n.addValidElements(e+"[*]")}),n.getElementRule("font")||n.addValidElements("font[face|size|color|style]"),void l.each(t.split(","),function(e){var t=n.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))});var e,t,i,n})};!function c(){e.add("legacyoutput",function(e){a(e)})}()}();

+ 9
- 0
static/tinymce/plugins/link/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/lists/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/media/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/nonbreaking/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(n,e){var o,t=(o=n).plugins.visualchars&&o.plugins.visualchars.isEnabled()?'<span class="mce-nbsp">&nbsp;</span>':"&nbsp;";n.insertContent(function(n,e){for(var o="",t=0;t<e;t++)o+=n;return o}(t,e)),n.dom.setAttrib(n.dom.select("span.mce-nbsp"),"data-mce-bogus","1")},e=function(n){n.addCommand("mceNonBreaking",function(){t(n,1)})},i=tinymce.util.Tools.resolve("tinymce.util.VK"),a=function(n){var e=n.getParam("nonbreaking_force_tab",0);return"boolean"==typeof e?!0===e?3:0:e},o=function(e){var o=a(e);0<o&&e.on("keydown",function(n){if(n.keyCode===i.TAB&&!n.isDefaultPrevented()){if(n.shiftKey)return;n.preventDefault(),n.stopImmediatePropagation(),t(e,o)}})},r=function(n){n.ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:function(){return n.execCommand("mceNonBreaking")}}),n.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:function(){return n.execCommand("mceNonBreaking")}})};!function c(){n.add("nonbreaking",function(n){e(n),r(n),o(n)})}()}();

+ 9
- 0
static/tinymce/plugins/noneditable/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.util.Tools"),l=function(t){return t.getParam("noneditable_noneditable_class","mceNonEditable")},u=function(t){return t.getParam("noneditable_editable_class","mceEditable")},f=function(t){var n=t.getParam("noneditable_regexp",[]);return n&&n.constructor===RegExp?[n]:n},s=function(n){return function(t){return-1!==(" "+t.attr("class")+" ").indexOf(n)}},d=function(i,o,c){return function(t){var n=arguments,e=n[n.length-2],r=0<e?o.charAt(e-1):"";if('"'===r)return t;if(">"===r){var a=o.lastIndexOf("<",e);if(-1!==a)if(-1!==o.substring(a,e).indexOf('contenteditable="false"'))return t}return'<span class="'+c+'" data-mce-content="'+i.dom.encode(n[0])+'">'+i.dom.encode("string"==typeof n[1]?n[1]:n[0])+"</span>"}},n=function(n){var t,e,r="contenteditable";t=" "+c.trim(u(n))+" ",e=" "+c.trim(l(n))+" ";var a=s(t),i=s(e),o=f(n);n.on("PreInit",function(){0<o.length&&n.on("BeforeSetContent",function(t){!function(t,n,e){var r=n.length,a=e.content;if("raw"!==e.format){for(;r--;)a=a.replace(n[r],d(t,a,l(t)));e.content=a}}(n,o,t)}),n.parser.addAttributeFilter("class",function(t){for(var n,e=t.length;e--;)n=t[e],a(n)?n.attr(r,"true"):i(n)&&n.attr(r,"false")}),n.serializer.addAttributeFilter(r,function(t){for(var n,e=t.length;e--;)n=t[e],(a(n)||i(n))&&(0<o.length&&n.attr("data-mce-content")?(n.name="#text",n.type=3,n.raw=!0,n.value=n.attr("data-mce-content")):n.attr(r,null))})})};!function e(){t.add("noneditable",function(t){n(t)})}()}();

+ 9
- 0
static/tinymce/plugins/pagebreak/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.Env"),a=function(e){return e.getParam("pagebreak_separator","\x3c!-- pagebreak --\x3e")},i=function(e){return e.getParam("pagebreak_split_block",!1)},t=function(){return"mce-pagebreak"},r=function(){return'<img src="'+n.transparentSrc+'" class="mce-pagebreak" data-mce-resize="false" data-mce-placeholder />'},o=function(o){var c=a(o),n=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi");o.on("BeforeSetContent",function(e){e.content=e.content.replace(n,r())}),o.on("PreInit",function(){o.serializer.addNodeFilter("img",function(e){for(var n,a,t=e.length;t--;)if((a=(n=e[t]).attr("class"))&&-1!==a.indexOf("mce-pagebreak")){var r=n.parent;if(o.schema.getBlockElements()[r.name]&&i(o)){r.type=3,r.value=c,r.raw=!0,n.remove();continue}n.type=3,n.value=c,n.raw=!0}})})},c=r,u=t,g=function(e){e.addCommand("mcePageBreak",function(){e.settings.pagebreak_split_block?e.insertContent("<p>"+c()+"</p>"):e.insertContent(c())})},m=function(n){n.on("ResolveName",function(e){"IMG"===e.target.nodeName&&n.dom.hasClass(e.target,u())&&(e.name="pagebreak")})},s=function(e){e.ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:function(){return e.execCommand("mcePageBreak")}}),e.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:function(){return e.execCommand("mcePageBreak")}})};!function l(){e.add("pagebreak",function(e){g(e),s(e),o(e),m(e)})}()}();

+ 9
- 0
static/tinymce/plugins/paste/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/preview/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),l=function(e){return e.getParam("content_style","")},m=function(e){return e.getParam("content_css_cors",!1,"boolean")},i=function(t){var n="",i=t.dom.encode,e=l(t);n+='<base href="'+i(t.documentBaseURI.getURI())+'">',e&&(n+='<style type="text/css">'+e+"</style>");var o=m(t)?' crossorigin="anonymous"':"";d.each(t.contentCSS,function(e){n+='<link type="text/css" rel="stylesheet" href="'+i(t.documentBaseURI.toAbsolute(e))+'"'+o+">"});var r=t.settings.body_id||"tinymce";-1!==r.indexOf("=")&&(r=(r=t.getParam("body_id","","hash"))[t.id]||r);var a=t.settings.body_class||"";-1!==a.indexOf("=")&&(a=(a=t.getParam("body_class","","hash"))[t.id]||"");var c=t.getBody().dir,s=c?' dir="'+i(c)+'"':"";return"<!DOCTYPE html><html><head>"+n+'</head><body id="'+i(r)+'" class="mce-content-body '+i(a)+'"'+s+">"+t.getContent()+'<script>document.addEventListener && document.addEventListener("click", function(e) {for (var elm = e.target; elm; elm = elm.parentNode) {if (elm.nodeName === "A") {e.preventDefault();}}}, false);<\/script> </body></html>'},t=function(n){n.addCommand("mcePreview",function(){var e,t;t=i(e=n),e.windowManager.open({title:"Preview",size:"large",body:{type:"panel",items:[{name:"preview",type:"iframe",sandboxed:!0}]},buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{preview:t}}).focus("close")})},n=function(e){e.ui.registry.addButton("preview",{icon:"preview",tooltip:"Preview",onAction:function(){return e.execCommand("mcePreview")}}),e.ui.registry.addMenuItem("preview",{icon:"preview",text:"Preview",onAction:function(){return e.execCommand("mcePreview")}})};!function o(){e.add("preview",function(e){t(e),n(e)})}()}();

+ 9
- 0
static/tinymce/plugins/print/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env"),i=function(n){n.addCommand("mcePrint",function(){t.ie&&t.ie<=11?n.getDoc().execCommand("print",!1,null):n.getWin().print()})},e=function(n){n.ui.registry.addButton("print",{icon:"print",tooltip:"Print",onAction:function(){return n.execCommand("mcePrint")}}),n.ui.registry.addMenuItem("print",{text:"Print...",icon:"print",onAction:function(){return n.execCommand("mcePrint")}})};!function o(){n.add("print",function(n){i(n),e(n),n.addShortcut("Meta+P","","mcePrint")})}()}();

+ 9
- 0
static/tinymce/plugins/quickbars/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/save/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools"),a=function(n){return n.getParam("save_enablewhendirty",!0)},i=function(n){return!!n.getParam("save_onsavecallback")},c=function(n){return!!n.getParam("save_oncancelcallback")},r=function(n,e){n.notificationManager.open({text:e,type:"error"})},e=function(n){var e;if(e=t.DOM.getParent(n.id,"form"),!a(n)||n.isDirty()){if(n.save(),i(n))return n.execCallback("save_onsavecallback",n),void n.nodeChanged();e?(n.setDirty(!1),e.onsubmit&&!e.onsubmit()||("function"==typeof e.submit?e.submit():r(n,"Error: Form submit field collision.")),n.nodeChanged()):r(n,"Error: No form element found.")}},u=function(n){var e=o.trim(n.startContent);c(n)?n.execCallback("save_oncancelcallback",n):n.resetContent(e)},l=function(n){n.addCommand("mceSave",function(){e(n)}),n.addCommand("mceCancel",function(){u(n)})},s=function(t){return function(n){var e=function(){n.setDisabled(a(t)&&!t.isDirty())};return t.on("NodeChange dirty",e),function(){return t.off("NodeChange dirty",e)}}},d=function(n){n.ui.registry.addButton("save",{icon:"save",tooltip:"Save",disabled:!0,onAction:function(){return n.execCommand("mceSave")},onSetup:s(n)}),n.ui.registry.addButton("cancel",{icon:"cancel",tooltip:"Cancel",disabled:!0,onAction:function(){return n.execCommand("mceCancel")},onSetup:s(n)}),n.addShortcut("Meta+S","","mceSave")};!function m(){n.add("save",function(n){d(n),l(n)})}()}();

+ 9
- 0
static/tinymce/plugins/searchreplace/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/spellchecker/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/tabfocus/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(c){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=tinymce.util.Tools.resolve("tinymce.EditorManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),y=tinymce.util.Tools.resolve("tinymce.util.Delay"),f=tinymce.util.Tools.resolve("tinymce.util.Tools"),d=tinymce.util.Tools.resolve("tinymce.util.VK"),m=function(e){return e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))},v=t.DOM,n=function(e){e.keyCode!==d.TAB||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()},i=function(r){function e(n){var i,o,e,l;if(!(n.keyCode!==d.TAB||n.ctrlKey||n.altKey||n.metaKey||n.isDefaultPrevented())&&(1===(e=f.explode(m(r))).length&&(e[1]=e[0],e[0]=":prev"),o=n.shiftKey?":prev"===e[0]?u(-1):v.get(e[0]):":next"===e[1]?u(1):v.get(e[1]))){var t=s.get(o.id||o.name);o.id&&t?t.focus():y.setTimeout(function(){a.webkit||c.window.focus(),o.focus()},10),n.preventDefault()}function u(e){function t(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&s.get(n.id)&&-1!==e.tabIndex&&function t(e){return"BODY"===e.nodeName||"hidden"!==e.type&&"none"!==e.style.display&&"hidden"!==e.style.visibility&&t(e.parentNode)}(e)}if(o=v.select(":input:enabled,*[tabindex]:not(iframe)"),f.each(o,function(e,t){if(e.id===r.id)return i=t,!1}),0<e){for(l=i+1;l<o.length;l++)if(t(o[l]))return o[l]}else for(l=i-1;0<=l;l--)if(t(o[l]))return o[l];return null}}r.on("init",function(){r.inline&&v.setAttrib(r.getBody(),"tabIndex",null),r.on("keyup",n),a.gecko?r.on("keypress keydown",e):r.on("keydown",e)})};!function o(){e.add("tabfocus",function(e){i(e)})}()}(window);

+ 9
- 0
static/tinymce/plugins/table/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/template/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/textcolor/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(o){"use strict";var i=tinymce.util.Tools.resolve("tinymce.PluginManager");!function n(){i.add("textcolor",function(){o.console.warn("Text color plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

+ 9
- 0
static/tinymce/plugins/textpattern/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/toc/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),s=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),f=tinymce.util.Tools.resolve("tinymce.util.I18n"),i=tinymce.util.Tools.resolve("tinymce.util.Tools"),a=function(t){return t.getParam("toc_class","mce-toc")},m=function(t){var e=t.getParam("toc_header","h2");return/^h[1-6]$/.test(e)?e:"h2"},c=function(t){var e=parseInt(t.getParam("toc_depth","3"),10);return 1<=e&&e<=9?e:3},l=function(e){var n=0;return function(){var t=(new Date).getTime().toString(32);return e+t+(n++).toString(32)}}("mcetoc_"),u=function u(t){var e,n=[];for(e=1;e<=t;e++)n.push("h"+e);return n.join(",")},v=function(n){var o=a(n),t=m(n),e=u(c(n)),r=n.$(e);return r.length&&/^h[1-9]$/i.test(t)&&(r=r.filter(function(t,e){return!n.dom.hasClass(e.parentNode,o)})),i.map(r,function(t){return{id:t.id?t.id:l(),level:parseInt(t.nodeName.replace(/^H/i,""),10),title:n.$.text(t),element:t}})},d=function(t){var e,n,o,r,i,c,a,l="",u=v(t),d=function(t){var e,n=9;for(e=0;e<t.length;e++)if(t[e].level<n&&(n=t[e].level),1===n)return n;return n}(u)-1;if(!u.length)return"";for(l+=(i=m(t),c=f.translate("Table of Contents"),a="</"+i+">","<"+i+' contenteditable="true">'+s.DOM.encode(c)+a),e=0;e<u.length;e++){if((o=u[e]).element.id=o.id,r=u[e+1]&&u[e+1].level,d===o.level)l+="<li>";else for(n=d;n<o.level;n++)l+="<ul><li>";if(l+='<a href="#'+o.id+'">'+o.title+"</a>",r!==o.level&&r)for(n=o.level;r<n;n--)l+="</li></ul><li>";else l+="</li>",r||(l+="</ul>");d=o.level}return l},g=function(t){var e=a(t),n=t.$("."+e);n.length&&t.undoManager.transact(function(){n.html(d(t))})},o={hasHeaders:function(t){return 0<v(t).length},insertToc:function(t){var e,n,o,r,i=a(t),c=t.$("."+i);o=t,!(r=c).length||0<o.dom.getParents(r[0],".mce-offscreen-selection").length?t.insertContent((n=d(e=t),'<div class="'+e.dom.encode(a(e))+'" contenteditable="false">'+n+"</div>")):g(t)},updateToc:g},e=function(t){t.addCommand("mceInsertToc",function(){o.insertToc(t)}),t.addCommand("mceUpdateToc",function(){o.updateToc(t)})},n=function(t){var n=t.$,o=a(t);t.on("PreProcess",function(t){var e=n("."+o,t.node);e.length&&(e.removeAttr("contentEditable"),e.find("[contenteditable]").removeAttr("contentEditable"))}),t.on("SetContent",function(){var t=n("."+o);t.length&&(t.attr("contentEditable",!1),t.children(":first-child").attr("contentEditable",!0))})},r=function(n){return function(t){var e=function(){return t.setDisabled(n.readonly||!o.hasHeaders(n))};return e(),n.on("LoadContent SetContent change",e),function(){return n.on("LoadContent SetContent change",e)}}},h=function(t){var e;t.ui.registry.addButton("toc",{icon:"toc",tooltip:"Table of contents",onAction:function(){return t.execCommand("mceInsertToc")},onSetup:r(t)}),t.ui.registry.addButton("tocupdate",{icon:"reload",tooltip:"Update",onAction:function(){return t.execCommand("mceUpdateToc")}}),t.ui.registry.addMenuItem("toc",{icon:"toc",text:"Table of contents",onAction:function(){return t.execCommand("mceInsertToc")},onSetup:r(t)}),t.ui.registry.addContextToolbar("toc",{items:"tocupdate",predicate:(e=t,function(t){return t&&e.dom.is(t,"."+a(e))&&e.getBody().contains(t)}),scope:"node",position:"node"})};!function p(){t.add("toc",function(t){e(t),h(t),n(t)})}()}();

+ 9
- 0
static/tinymce/plugins/visualblocks/plugin.min.js Целия файл

@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ *
7
+ * Version: 5.0.12 (2019-07-18)
8
+ */
9
+!function(){"use strict";var e=function(t){var n=t,o=function(){return n};return{get:o,set:function(t){n=t},clone:function(){return e(o())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(t,n){t.fire("VisualBlocks",{state:n})},u=function(t,n,o){t.dom.toggleClass(t.getBody(),"mce-visualblocks"),o.set(!o.get()),i(t,o.get())},c=function(t,n,o){t.addCommand("mceVisualBlocks",function(){u(t,n,o)})},s=function(t){return t.getParam("visualblocks_default_state",!1,"boolean")},r=function(n,t,o){n.on("PreviewFormats AfterPreviewFormats",function(t){o.get()&&n.dom.toggleClass(n.getBody(),"mce-visualblocks","afterpreviewformats"===t.type)}),n.on("init",function(){s(n)&&u(n,t,o)}),n.on("remove",function(){n.dom.removeClass(n.getBody(),"mce-visualblocks")})},o=function(o,e){return function(n){n.setActive(e.get());var t=function(t){return n.setActive(t.state)};return o.on("VisualBlocks",t),function(){return o.off("VisualBlocks",t)}}},a=function(t,n){t.ui.registry.addToggleButton("visualblocks",{icon:"paragraph",tooltip:"Show blocks",onAction:function(){return t.execCommand("mceVisualBlocks")},onSetup:o(t,n)}),t.ui.registry.addToggleMenuItem("visualblocks",{text:"Show blocks",onAction:function(){return t.execCommand("mceVisualBlocks")},onSetup:o(t,n)})};!function n(){t.add("visualblocks",function(t,n){var o=e(!1);c(t,n,o),a(t,o),r(t,n,o)})}()}();

+ 9
- 0
static/tinymce/plugins/visualchars/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 9
- 0
static/tinymce/plugins/wordcount/plugin.min.js
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/content/default/content.min.css Целия файл

@@ -0,0 +1,7 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table td,table th{border:1px solid #ccc;padding:.4rem}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

+ 7
- 0
static/tinymce/skins/content/document/content.min.css Целия файл

@@ -0,0 +1,7 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+@media screen{html{background:#f4f4f4}}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif}@media screen{body{background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.15);box-sizing:border-box;margin:1rem auto 0;max-width:820px;min-height:calc(100vh - 1rem);padding:4rem 6rem 6rem 6rem}}table{border-collapse:collapse}table td,table th{border:1px solid #ccc;padding:.4rem}figure figcaption{color:#999;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

+ 7
- 0
static/tinymce/skins/content/writer/content.min.css Целия файл

@@ -0,0 +1,7 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem auto;max-width:900px}table{border-collapse:collapse}table td,table th{border:1px solid #ccc;padding:.4rem}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

+ 7
- 0
static/tinymce/skins/ui/oxide-dark/content.inline.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide-dark/content.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide-dark/content.mobile.min.css Целия файл

@@ -0,0 +1,7 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}

BIN
static/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide-dark/skin.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide-dark/skin.mobile.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide/content.inline.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide/content.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide/content.mobile.min.css Целия файл

@@ -0,0 +1,7 @@
1
+/**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}

BIN
static/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide/skin.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
static/tinymce/skins/ui/oxide/skin.mobile.min.css
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 0
- 0
static/tinymce/themes/mobile/theme.min.js Целия файл


Някои файлове не бяха показани, защото твърде много файлове са промени