ソースを参照

Merge branch 'master' of http://git.shengws.com/zhangbj/scrm-vue

xiaoming_global 4 年 前
コミット
5bfef25a89
共有44 個のファイルを変更した13670 個の追加144 個の削除を含む
  1. 1 1
      config/index.js
  2. 2 0
      index.html
  3. 233 4
      package-lock.json
  4. 3 0
      package.json
  5. 52 0
      src/api/activity/activity.js
  6. 8 0
      src/api/kefu/tencentim.js
  7. 9 0
      src/api/mpwechat/material.js
  8. 24 0
      src/api/mpwechat/mpmenus.js
  9. 47 0
      src/api/mpwechat/mpreply.js
  10. 1 16
      src/api/mpwechat/mpwechat.js
  11. 4 0
      src/lang/en.js
  12. 4 0
      src/lang/zh.js
  13. 7 0
      src/router/index.js
  14. 23 0
      src/router/modules/kefu.js
  15. 44 0
      src/router/modules/marketing_tool.js
  16. 1 1
      src/router/modules/member.js
  17. 13 0
      src/router/modules/system.js
  18. 932 0
      src/scrm_pages/contactBox/index.vue
  19. 965 0
      src/scrm_pages/kefu/index.vue
  20. 265 0
      src/scrm_pages/marketing_tool/activity_detail.vue
  21. 23 4
      src/scrm_pages/marketing_tool/activity_list.vue
  22. 325 0
      src/scrm_pages/marketing_tool/activity_preview.vue
  23. 227 0
      src/scrm_pages/marketing_tool/activity_share.vue
  24. 107 0
      src/scrm_pages/marketing_tool/activity_signup_users.vue
  25. 14 2
      src/scrm_pages/marketing_tool/components/drafts_cell.vue
  26. 21 5
      src/scrm_pages/marketing_tool/components/edit_activity_edit_form.vue
  27. 7 2
      src/scrm_pages/marketing_tool/components/published_cell.vue
  28. 7 2
      src/scrm_pages/marketing_tool/components/unapproved_cell.vue
  29. 286 0
      src/scrm_pages/site/components/add-contact.vue
  30. 14 0
      src/scrm_pages/site/components/contact-used.vue
  31. 312 90
      src/scrm_pages/site/components/new-feature.vue
  32. 361 0
      src/scrm_pages/site/components/used-list.vue
  33. 7 3
      src/scrm_pages/site/preview.vue
  34. 101 0
      src/scrm_pages/weixinmp/components/CreateKWReplyForm.vue
  35. 105 0
      src/scrm_pages/weixinmp/components/EditKWReplyForm.vue
  36. 193 0
      src/scrm_pages/weixinmp/components/ImageMaterialBox.vue
  37. 30 0
      src/scrm_pages/weixinmp/components/replyNav.vue
  38. 234 0
      src/scrm_pages/weixinmp/keywordreply.vue
  39. 210 12
      src/scrm_pages/weixinmp/menus.vue
  40. 117 0
      src/scrm_pages/weixinmp/subscribereply.vue
  41. 44 0
      src/styles/index.scss
  42. 4 1
      src/views/layout/Layout.vue
  43. 1 1
      src/xt_permission.js
  44. 8282 0
      static/webim.js

+ 1 - 1
config/index.js ファイルの表示

@@ -19,7 +19,7 @@ module.exports = {
19 19
 
20 20
     host: 'test1.sgjyun.com',
21 21
     port: 8090, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
22
-    host: 'test1.sgjyun.com',
22
+    // host: 'test1.sgjyun.com',
23 23
     autoOpenBrowser: true,
24 24
     errorOverlay: true,
25 25
     notifyOnErrors: false,

+ 2 - 0
index.html ファイルの表示

@@ -5,6 +5,8 @@
5 5
     <meta charset="utf-8">
6 6
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7 7
     <meta name="renderer" content="webkit">
8
+    <meta name=”referrer” content=”never”>
9
+    <meta name="referrer" content="no-referrer"/>
8 10
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
9 11
     <title>血透管理-酷医云</title>
10 12
   </head>

+ 233 - 4
package-lock.json ファイルの表示

@@ -1876,6 +1876,14 @@
1876 1876
         }
1877 1877
       }
1878 1878
     },
1879
+    "can-promise": {
1880
+      "version": "0.0.1",
1881
+      "resolved": "https://registry.npmjs.org/can-promise/-/can-promise-0.0.1.tgz",
1882
+      "integrity": "sha512-gzVrHyyrvgt0YpDm7pn04MQt8gjh0ZAhN4ZDyCRtGl6YnuuK6b4aiUTD7G52r9l4YNmxfTtEscb92vxtAlL6XQ==",
1883
+      "requires": {
1884
+        "window-or-global": "^1.0.1"
1885
+      }
1886
+    },
1879 1887
     "caniuse-api": {
1880 1888
       "version": "1.6.1",
1881 1889
       "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz",
@@ -3326,6 +3334,11 @@
3326 3334
         "randombytes": "^2.0.0"
3327 3335
       }
3328 3336
     },
3337
+    "dijkstrajs": {
3338
+      "version": "1.0.1",
3339
+      "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz",
3340
+      "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs="
3341
+    },
3329 3342
     "dir-glob": {
3330 3343
       "version": "2.2.2",
3331 3344
       "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
@@ -3537,7 +3550,6 @@
3537 3550
       "version": "1.4.1",
3538 3551
       "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
3539 3552
       "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
3540
-      "dev": true,
3541 3553
       "requires": {
3542 3554
         "once": "^1.4.0"
3543 3555
       }
@@ -7163,6 +7175,14 @@
7163 7175
         "pify": "^3.0.0"
7164 7176
       }
7165 7177
     },
7178
+    "map-age-cleaner": {
7179
+      "version": "0.1.3",
7180
+      "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
7181
+      "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
7182
+      "requires": {
7183
+        "p-defer": "^1.0.0"
7184
+      }
7185
+    },
7166 7186
     "map-cache": {
7167 7187
       "version": "0.2.2",
7168 7188
       "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -7536,6 +7556,11 @@
7536 7556
       "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
7537 7557
       "dev": true
7538 7558
     },
7559
+    "nice-try": {
7560
+      "version": "1.0.5",
7561
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
7562
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
7563
+    },
7539 7564
     "no-case": {
7540 7565
       "version": "2.3.2",
7541 7566
       "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
@@ -8003,7 +8028,6 @@
8003 8028
       "version": "1.4.0",
8004 8029
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
8005 8030
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
8006
-      "dev": true,
8007 8031
       "requires": {
8008 8032
         "wrappy": "1"
8009 8033
       }
@@ -8166,11 +8190,21 @@
8166 8190
         "os-tmpdir": "^1.0.0"
8167 8191
       }
8168 8192
     },
8193
+    "p-defer": {
8194
+      "version": "1.0.0",
8195
+      "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
8196
+      "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
8197
+    },
8169 8198
     "p-finally": {
8170 8199
       "version": "1.0.0",
8171 8200
       "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
8172 8201
       "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
8173 8202
     },
8203
+    "p-is-promise": {
8204
+      "version": "2.1.0",
8205
+      "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
8206
+      "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
8207
+    },
8174 8208
     "p-limit": {
8175 8209
       "version": "1.3.0",
8176 8210
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
@@ -8444,6 +8478,11 @@
8444 8478
       "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
8445 8479
       "dev": true
8446 8480
     },
8481
+    "pngjs": {
8482
+      "version": "3.4.0",
8483
+      "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
8484
+      "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="
8485
+    },
8447 8486
     "portfinder": {
8448 8487
       "version": "1.0.13",
8449 8488
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
@@ -11226,6 +11265,182 @@
11226 11265
       "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
11227 11266
       "dev": true
11228 11267
     },
11268
+    "qrcode": {
11269
+      "version": "1.3.3",
11270
+      "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.3.tgz",
11271
+      "integrity": "sha512-SH7V13AcJusH3GT8bMNOGz4w0L+LjcpNOU/NiOgtBhT/5DoWeZE6D5ntMJnJ84AMkoaM4kjJJoHoh9g++8lWFg==",
11272
+      "requires": {
11273
+        "can-promise": "0.0.1",
11274
+        "dijkstrajs": "^1.0.1",
11275
+        "isarray": "^2.0.1",
11276
+        "pngjs": "^3.3.0",
11277
+        "yargs": "^12.0.5"
11278
+      },
11279
+      "dependencies": {
11280
+        "camelcase": {
11281
+          "version": "5.3.1",
11282
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
11283
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
11284
+        },
11285
+        "cross-spawn": {
11286
+          "version": "6.0.5",
11287
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
11288
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
11289
+          "requires": {
11290
+            "nice-try": "^1.0.4",
11291
+            "path-key": "^2.0.1",
11292
+            "semver": "^5.5.0",
11293
+            "shebang-command": "^1.2.0",
11294
+            "which": "^1.2.9"
11295
+          }
11296
+        },
11297
+        "execa": {
11298
+          "version": "1.0.0",
11299
+          "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
11300
+          "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
11301
+          "requires": {
11302
+            "cross-spawn": "^6.0.0",
11303
+            "get-stream": "^4.0.0",
11304
+            "is-stream": "^1.1.0",
11305
+            "npm-run-path": "^2.0.0",
11306
+            "p-finally": "^1.0.0",
11307
+            "signal-exit": "^3.0.0",
11308
+            "strip-eof": "^1.0.0"
11309
+          }
11310
+        },
11311
+        "find-up": {
11312
+          "version": "3.0.0",
11313
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
11314
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
11315
+          "requires": {
11316
+            "locate-path": "^3.0.0"
11317
+          }
11318
+        },
11319
+        "get-stream": {
11320
+          "version": "4.1.0",
11321
+          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
11322
+          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
11323
+          "requires": {
11324
+            "pump": "^3.0.0"
11325
+          }
11326
+        },
11327
+        "invert-kv": {
11328
+          "version": "2.0.0",
11329
+          "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
11330
+          "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
11331
+        },
11332
+        "isarray": {
11333
+          "version": "2.0.4",
11334
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz",
11335
+          "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA=="
11336
+        },
11337
+        "lcid": {
11338
+          "version": "2.0.0",
11339
+          "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
11340
+          "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
11341
+          "requires": {
11342
+            "invert-kv": "^2.0.0"
11343
+          }
11344
+        },
11345
+        "locate-path": {
11346
+          "version": "3.0.0",
11347
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
11348
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
11349
+          "requires": {
11350
+            "p-locate": "^3.0.0",
11351
+            "path-exists": "^3.0.0"
11352
+          }
11353
+        },
11354
+        "mem": {
11355
+          "version": "4.3.0",
11356
+          "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
11357
+          "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
11358
+          "requires": {
11359
+            "map-age-cleaner": "^0.1.1",
11360
+            "mimic-fn": "^2.0.0",
11361
+            "p-is-promise": "^2.0.0"
11362
+          }
11363
+        },
11364
+        "mimic-fn": {
11365
+          "version": "2.1.0",
11366
+          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
11367
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
11368
+        },
11369
+        "os-locale": {
11370
+          "version": "3.1.0",
11371
+          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
11372
+          "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
11373
+          "requires": {
11374
+            "execa": "^1.0.0",
11375
+            "lcid": "^2.0.0",
11376
+            "mem": "^4.0.0"
11377
+          }
11378
+        },
11379
+        "p-limit": {
11380
+          "version": "2.2.0",
11381
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
11382
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
11383
+          "requires": {
11384
+            "p-try": "^2.0.0"
11385
+          }
11386
+        },
11387
+        "p-locate": {
11388
+          "version": "3.0.0",
11389
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
11390
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
11391
+          "requires": {
11392
+            "p-limit": "^2.0.0"
11393
+          }
11394
+        },
11395
+        "p-try": {
11396
+          "version": "2.2.0",
11397
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
11398
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
11399
+        },
11400
+        "pump": {
11401
+          "version": "3.0.0",
11402
+          "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
11403
+          "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
11404
+          "requires": {
11405
+            "end-of-stream": "^1.1.0",
11406
+            "once": "^1.3.1"
11407
+          }
11408
+        },
11409
+        "semver": {
11410
+          "version": "5.7.0",
11411
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
11412
+          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
11413
+        },
11414
+        "yargs": {
11415
+          "version": "12.0.5",
11416
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
11417
+          "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
11418
+          "requires": {
11419
+            "cliui": "^4.0.0",
11420
+            "decamelize": "^1.2.0",
11421
+            "find-up": "^3.0.0",
11422
+            "get-caller-file": "^1.0.1",
11423
+            "os-locale": "^3.0.0",
11424
+            "require-directory": "^2.1.1",
11425
+            "require-main-filename": "^1.0.1",
11426
+            "set-blocking": "^2.0.0",
11427
+            "string-width": "^2.0.0",
11428
+            "which-module": "^2.0.0",
11429
+            "y18n": "^3.2.1 || ^4.0.0",
11430
+            "yargs-parser": "^11.1.1"
11431
+          }
11432
+        },
11433
+        "yargs-parser": {
11434
+          "version": "11.1.1",
11435
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
11436
+          "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
11437
+          "requires": {
11438
+            "camelcase": "^5.0.0",
11439
+            "decamelize": "^1.2.0"
11440
+          }
11441
+        }
11442
+      }
11443
+    },
11229 11444
     "qrcodejs2": {
11230 11445
       "version": "0.0.2",
11231 11446
       "resolved": "https://registry.npmjs.org/qrcodejs2/-/qrcodejs2-0.0.2.tgz",
@@ -12660,6 +12875,11 @@
12660 12875
       "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
12661 12876
       "dev": true
12662 12877
     },
12878
+    "spark-md5": {
12879
+      "version": "3.0.0",
12880
+      "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.0.tgz",
12881
+      "integrity": "sha1-NyIifFTi+vJLHcbZM8wUTm9xv+8="
12882
+    },
12663 12883
     "spdx-correct": {
12664 12884
       "version": "3.1.0",
12665 12885
       "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -14096,6 +14316,11 @@
14096 14316
         "minimalistic-assert": "^1.0.0"
14097 14317
       }
14098 14318
     },
14319
+    "webim-tencent": {
14320
+      "version": "1.0.2",
14321
+      "resolved": "https://registry.npmjs.org/webim-tencent/-/webim-tencent-1.0.2.tgz",
14322
+      "integrity": "sha512-sdSRjcTsb/4t9riUpEv3+01wNMxP8hbWOllPbmkqKJ2jhXy88w57K7Ae4BnaeFH55prdcpsKwBhsX7BiJYGv/w=="
14323
+    },
14099 14324
     "webpack": {
14100 14325
       "version": "3.10.0",
14101 14326
       "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz",
@@ -14823,6 +15048,11 @@
14823 15048
         "string-width": "^1.0.2 || 2"
14824 15049
       }
14825 15050
     },
15051
+    "window-or-global": {
15052
+      "version": "1.0.1",
15053
+      "resolved": "https://registry.npmjs.org/window-or-global/-/window-or-global-1.0.1.tgz",
15054
+      "integrity": "sha1-2+RboqKRqrxW1iz2bEW3+jIpRt4="
15055
+    },
14826 15056
     "window-size": {
14827 15057
       "version": "0.1.0",
14828 15058
       "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
@@ -14889,8 +15119,7 @@
14889 15119
     "wrappy": {
14890 15120
       "version": "1.0.2",
14891 15121
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
14892
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
14893
-      "dev": true
15122
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
14894 15123
     },
14895 15124
     "write": {
14896 15125
       "version": "0.2.1",

+ 3 - 0
package.json ファイルの表示

@@ -54,12 +54,14 @@
54 54
     "normalize.css": "7.0.0",
55 55
     "nprogress": "0.2.0",
56 56
     "print-js": "^1.0.50",
57
+    "qrcode": "^1.3.3",
57 58
     "qrcodejs2": "0.0.2",
58 59
     "screenfull": "4.2.0",
59 60
     "serve-static": "1.13.2",
60 61
     "showdown": "1.8.5",
61 62
     "simplemde": "1.11.2",
62 63
     "sortablejs": "1.7.0",
64
+    "spark-md5": "^3.0.0",
63 65
     "vue": "2.5.16",
64 66
     "vue-count-to": "1.0.13",
65 67
     "vue-i18n": "7.3.2",
@@ -68,6 +70,7 @@
68 70
     "vue-splitpane": "1.0.2",
69 71
     "vuedraggable": "^2.16.0",
70 72
     "vuex": "3.0.1",
73
+    "webim-tencent": "^1.0.2",
71 74
     "xlsx": "^0.11.16"
72 75
   },
73 76
   "devDependencies": {

+ 52 - 0
src/api/activity/activity.js ファイルの表示

@@ -32,4 +32,56 @@ export function submitActivity(publish, activity) {
32 32
     },
33 33
     data: activity,
34 34
   })
35
+}
36
+
37
+export function fetchActivityDetailViewData(id) {
38
+  return request({
39
+    url: "/api/activity/detailview",
40
+    method: "get",
41
+    params: {
42
+      id: id,
43
+    }
44
+  })
45
+}
46
+
47
+export function fetchActivitySignupUsers(activity_id, keyword, page) {
48
+  return request({
49
+    url: "/api/activity/signups",
50
+    method: "get",
51
+    params: {
52
+      id: activity_id,
53
+      keyword: keyword,
54
+      page: page,
55
+    }
56
+  })
57
+}
58
+
59
+export function deleteActivity(activity_id) {
60
+  return request({
61
+    url: "/api/activity/delete",
62
+    method: "post",
63
+    params: {
64
+      id: activity_id,
65
+    }
66
+  })
67
+}
68
+
69
+export function publishActivity(activity_id) {
70
+  return request({
71
+    url: "/api/activity/publish",
72
+    method: "post",
73
+    params: {
74
+      id: activity_id,
75
+    }
76
+  })
77
+}
78
+
79
+export function getActivityShareInfo(activity_id) {
80
+  return request({
81
+    url: "/api/activity/shareinfo",
82
+    method: "get",
83
+    params: {
84
+      id: activity_id,
85
+    }
86
+  })
35 87
 }

+ 8 - 0
src/api/kefu/tencentim.js ファイルの表示

@@ -0,0 +1,8 @@
1
+import request from '@/utils/request'
2
+
3
+export function getusersig() {
4
+  return request({
5
+    url: '/api/tencent/usersig', 
6
+    method: 'get',
7
+  })
8
+}

+ 9 - 0
src/api/mpwechat/material.js ファイルの表示

@@ -0,0 +1,9 @@
1
+import request from '@/utils/request'
2
+
3
+export function GetMaterials(params) {
4
+    return request({
5
+        url: '/api/mpwechat/media/material',
6
+        method: 'get',
7
+        params:params
8
+    })
9
+}

+ 24 - 0
src/api/mpwechat/mpmenus.js ファイルの表示

@@ -0,0 +1,24 @@
1
+import request from '@/utils/request'
2
+
3
+export function GetMenus() {
4
+  return request({
5
+    url: '/api/mpwechat/menus',
6
+    method: 'get',
7
+  })
8
+}
9
+
10
+export function SaveMenus(data) {
11
+  return request({
12
+    url: '/api/mpwechat/savemenus',
13
+    method: 'put',
14
+    data:data,
15
+  })
16
+}
17
+
18
+export function DeleteMenu(data) {
19
+  return request({
20
+    url: '/api/mpwechat/deletemenus',
21
+    method: 'post',
22
+    data:data,
23
+  })
24
+}

+ 47 - 0
src/api/mpwechat/mpreply.js ファイルの表示

@@ -0,0 +1,47 @@
1
+import request from '@/utils/request'
2
+
3
+export function GetSubscribeRplay() {
4
+    return request({
5
+        url: '/api/mpwechat/reply/subscribe',
6
+        method: 'get',
7
+    })
8
+}
9
+
10
+export function SaveSubscribeRplay(data) {
11
+    return request({
12
+        url: '/api/mpwechat/reply/subscribe',
13
+        method: 'put',
14
+        data:data,
15
+    })
16
+}
17
+    
18
+export function GetKeyWordReplys(params) {
19
+    return request({
20
+        url: '/api/mpwechat/reply/kewords',
21
+        method: 'get',
22
+        params:params,
23
+    })
24
+}
25
+
26
+export function CreateKeyWordReply(data) {
27
+    return request({
28
+        url: '/api/mpwechat/reply/keword',
29
+        method: 'post',
30
+        data:data,
31
+    })
32
+}
33
+export function EditKeyWordReply(id,data) {
34
+    return request({
35
+        url: '/api/mpwechat/reply/keword?id='+id,
36
+        method: 'put',
37
+        data:data,
38
+    })
39
+}
40
+
41
+export function DeleteReplys(data) {
42
+    return request({
43
+        url: '/api/mpwechat/replys',
44
+        method: 'delete',
45
+        data:data,
46
+    })
47
+}

+ 1 - 16
src/api/mpwechat/mpwechat.js ファイルの表示

@@ -12,19 +12,4 @@ export function GetAuthUrl() {
12 12
     url: '/api/mpwechat/authurl',
13 13
     method: 'get',
14 14
   })
15
-}
16
-  
17
-export function GetMenus() {
18
-  return request({
19
-    url: '/api/mpwechat/menus',
20
-    method: 'get',
21
-  })
22
-}
23
-
24
-export function SaveMenus(data) {
25
-  return request({
26
-    url: '/api/mpwechat/savemenus',
27
-    method: 'put',
28
-    data:data,
29
-  })
30
-}
15
+}

+ 4 - 0
src/lang/en.js ファイルの表示

@@ -116,6 +116,10 @@ export default {
116 116
     activityPublish: "publish activity",
117 117
     activityModify: "edit activity",
118 118
     systemsetting:'Systemsetting',
119
+    activityDetail: "activity detail",
120
+    activityShare: "activity share",
121
+    activityPreview: "activity preview",
122
+    activitySignupList: "activity sign up list",
119 123
   },
120 124
   navbar: {
121 125
     logOut: 'Log Out',

+ 4 - 0
src/lang/zh.js ファイルの表示

@@ -167,6 +167,10 @@ export default {
167 167
     activityModify: "编辑活动",
168 168
     systemsetting:'系统设置',
169 169
     staffmanagement:'员工管理',
170
+    activityDetail: "活动详情",
171
+    activityShare: "活动分享",
172
+    activityPreview: "活动预览",
173
+    activitySignupList: "报名列表",
170 174
   },
171 175
   navbar: {
172 176
     logOut: '退出登录',

+ 7 - 0
src/router/index.js ファイルの表示

@@ -13,6 +13,7 @@ import org from './modules/org'
13 13
 import marketing_tool from './modules/marketing_tool'
14 14
 import system from './modules/system'
15 15
 import site from './modules/site'
16
+import kefu from './modules/kefu'
16 17
 
17 18
 /** note: submenu only apppear when children.length>=1
18 19
  *   detail see  https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
@@ -68,12 +69,18 @@ var _constant_router_map = [{
68 69
       noCache: true
69 70
     }
70 71
   }]
72
+},
73
+{
74
+  path: '/activity/preview',
75
+  component: () => import('@/scrm_pages/marketing_tool/activity_preview'),
76
+  hidden: true
71 77
 }
72 78
   // service
73 79
 ]
74 80
 
75 81
 var _asy_router_map = [
76 82
   member,
83
+  kefu,
77 84
   article,
78 85
   marketing_tool,
79 86
   org,

+ 23 - 0
src/router/modules/kefu.js ファイルの表示

@@ -0,0 +1,23 @@
1
+import Layout from '@/views/layout/Layout'
2
+//客服管理模块
3
+
4
+
5
+export default {
6
+    alwaysShow: true,
7
+    path: '/kefu',
8
+    component: Layout,
9
+    redirect: 'noredirect',
10
+    name: 'kefu',
11
+    meta: {
12
+      title: '客服管理',
13
+      icon: 'message'
14
+    },
15
+    children: [
16
+      {
17
+        path: '/kefu',
18
+        component: () => import('@/scrm_pages/kefu'),
19
+        name: 'kefuBox',
20
+        meta: { title: '咨询管理', noCache: true }
21
+      },
22
+    ]
23
+  }

+ 44 - 0
src/router/modules/marketing_tool.js ファイルの表示

@@ -39,5 +39,49 @@ export default {
39 39
         noCache: true
40 40
       }
41 41
     },
42
+    {
43
+      path: "/activity",
44
+      hidden: true,
45
+      is_menu: false,
46
+      component: () => import("@/scrm_pages/marketing_tool/activity_detail"),
47
+      name: "activityDetail",
48
+      meta: {
49
+        title: "activityDetail",
50
+        noCache: true,
51
+      }
52
+    },
53
+    {
54
+      path: "/activity/share",
55
+      hidden: true,
56
+      is_menu: false,
57
+      component: () => import("@/scrm_pages/marketing_tool/activity_share"),
58
+      name: "activityShare",
59
+      meta: {
60
+        title: "activityShare",
61
+        noCache: true,
62
+      }
63
+    },
64
+    // {
65
+    //   path: "/activity/preview",
66
+    //   hidden: true,
67
+    //   is_menu: false,
68
+    //   component: () => import("@/scrm_pages/marketing_tool/activity_preview"),
69
+    //   name: "activityPreview",
70
+    //   meta: {
71
+    //     title: "activityPreview",
72
+    //     noCache: true,
73
+    //   }
74
+    // },
75
+    {
76
+      path: "/activity/signupusers",
77
+      hidden: true,
78
+      is_menu: false,
79
+      component: () => import("@/scrm_pages/marketing_tool/activity_signup_users"),
80
+      name: "activitySignupList",
81
+      meta: {
82
+        title: "activitySignupList",
83
+        noCache: true,
84
+      }
85
+    },
42 86
   ]
43 87
 }

+ 1 - 1
src/router/modules/member.js ファイルの表示

@@ -15,7 +15,7 @@ export default {
15 15
     {
16 16
       path: '/member/members',
17 17
       component: () => import('@/scrm_pages/members/members'),
18
-      name: 'memberslist',
18
+      name: 'memberslists',
19 19
       meta: { title: '会员管理', noCache: true }
20 20
     },
21 21
     {

+ 13 - 0
src/router/modules/system.js ファイルの表示

@@ -23,6 +23,19 @@ export default {
23 23
       name: 'weixinMpMenus',
24 24
       meta: { title: '公众号菜单', noCache: true }
25 25
     },
26
+    {
27
+      path: '/weixinmp/reply/subscribe',
28
+      component: () => import('@/scrm_pages/weixinmp/subscribereply'),
29
+      name: 'weixinAutoReply',
30
+      meta: { title: '自动回复', noCache: true }
31
+    },
32
+    {
33
+      path: '/weixinmp/reply/keyword',
34
+      component: () => import('@/scrm_pages/weixinmp/keywordreply'),
35
+      name: 'weixinKeywordReply',
36
+      hidden: true,
37
+      meta: { title: '关键词回复', noCache: true }
38
+    },
26 39
     {
27 40
       path: '/Systemsetting/staffmanagement',
28 41
       component: () => import('@/scrm_pages/Systemsetting/staffmanagement'),

+ 932 - 0
src/scrm_pages/contactBox/index.vue ファイルの表示

@@ -0,0 +1,932 @@
1
+<template>
2
+    <div class="contact-box" id="contact-box">
3
+        <div class="contact-box-item msg-box" >
4
+            <div class="box-btn " @click="toggleMsgBox">
5
+                <i class="el-icon-service"></i>
6
+                <span>在线客服</span>
7
+            </div>
8
+            <div class="contact-msg-box" v-show="showMsgBox">
9
+                <div class="msg-box-panel">
10
+                    <div class="panel-header">
11
+                        <i class="el-icon-close kf-close" @click="showMsgBox=false"></i>
12
+                        <p class="kf-h-line">酷医云在线客服</p>
13
+                        <div class="clearfix"></div>
14
+                    </div>
15
+                    <div class="panel-body">
16
+                        <ul class="msg-inner scroll-y">
17
+                            <li v-for="(messageitem, key) in messageBox" :key="key" :id="'id_'+messageitem.id" class="cell clearfix" :class="messageitem.float=='right'?'cell_right':''">
18
+                                <template v-if="messageitem.float=='right'">
19
+                                    <div class="msg_body fl">
20
+                                        <div class="inner" v-html="messageitem.message"></div>
21
+                                    </div>
22
+                                    <div class="cell_pic fl">
23
+                                        <div class="pic">
24
+                                            <img :src="messageitem.avatar" alt="">
25
+                                        </div>
26
+                                    </div>
27
+                                </template>
28
+                                <template v-else>
29
+                                    <div class="cell_pic fl">
30
+                                        <div class="pic">
31
+                                            <img :src="messageitem.avatar" alt="">
32
+                                        </div>
33
+                                    </div>
34
+                                    <div class="msg_body fl">
35
+                                        <div class="inner" v-html="messageitem.message"></div>
36
+                                    </div>
37
+                                </template>
38
+                            </li>
39
+                        </ul>
40
+                    </div>
41
+                    <div class="panel-tool">
42
+                        <i class="icon-face" title="表情" @click="showEmotion"></i>
43
+                        <el-upload
44
+                        class="avatar-uploader"
45
+                        action="https://jsonplaceholder.typicode.com/posts/"
46
+                        :show-file-list="false"
47
+                        :http-request='handleIMPicUload'
48
+                        :on-success="handleIMPicSuccess"
49
+                        :before-upload="beforeIMPicUpload">
50
+                        <i class="el-icon-picture" title="图片"></i>
51
+                        </el-upload>
52
+                        <div class="face-box" v-show="showFace">
53
+                            <div class="face-box-title">
54
+                                <span>表情</span>
55
+                                <i class="el-icon-close " @click="showFace=false" style="float:right" ></i>
56
+                            </div>
57
+                            <ul class="face-box-list clearfix">
58
+                                <li v-for="(faceitem, index) in facelist" :key="index" @click="selectEmotion(faceitem)" >
59
+                                    <img :src="faceitem[1]" :id="faceitem[0]"  alt="">
60
+                                </li>
61
+                            </ul>
62
+                        </div>
63
+
64
+                    </div>
65
+                    <div class="panel-booter">
66
+                        <div class="msg-input-box">
67
+                            <textarea class="textarea scroll-y message-textarea"  v-model="message" placeholder="请输入"></textarea>
68
+                        </div>
69
+                        <div class="msg-send-btn-box">
70
+                            <span class="time fl">服务时间:工作时间:9:00-22:00 节假日:9:00-18:00</span>
71
+                            <el-button type="primary" icon="el-icon-edit" class="fr" size="mini" @click="sendMessage">发送</el-button>
72
+                            <!-- <button type="submit" id="sendadminkfmsg" class="send_btn fr">发送</button> -->
73
+                        </div>
74
+                    </div>
75
+                </div>
76
+            </div>
77
+        </div>
78
+        <div class="contact-box-item phone-box">
79
+            <div class="box-btn" @click="togglePhoneBox">
80
+                <i class="el-icon-phone-outline"></i>
81
+                <span>客服电话</span>
82
+            </div>
83
+            <div class="contact-phone-box" v-show="showPhoneBox">
84
+                <i class="el-icon-phone-outline" ></i>
85
+                <span>0755-86526342</span>
86
+            </div>
87
+        </div>
88
+    </div>
89
+</template>
90
+<script>
91
+import {getusersig} from "@/api/kefu/tencentim";
92
+import webim from 'webim-tencent';
93
+let selType =  webim.SESSION_TYPE.C2C;
94
+let reqMsgCount = 15; //每次请求的历史消息(c2c获取群)条数
95
+var msgList = [];
96
+var getPrePageC2CHistroyMsgInfoMap = {};
97
+export default {
98
+    name:'contactBox',
99
+    data(){
100
+        return{
101
+            showMsgBox:false,
102
+            showPhoneBox:false,
103
+            selToID:'',
104
+            loginInfo: {
105
+                sdkAppID: '', //用户所属应用id,必填
106
+                appIDAt3rd: '',
107
+                identifier: '', //当前用户ID,必须是否字符串类型,必填
108
+                accountType: '', //用户所属应用帐号类型,必填
109
+                userSig: '', //当前用户身份凭证,必须是字符串类型,必填
110
+                identifierNick: '', //当前用户昵称,不用填写,登录接口会返回用户的昵称,如果没有设置,则返回用户的id
111
+                headurl: '', //当前用户默认头像,选填,如果设置过头像,则可以通过拉取个人资料接口来得到头像信息
112
+            },
113
+            useradmin:{
114
+                usersig: '',
115
+                Indentifier: '',
116
+                appIDAt3rd:'',
117
+                IdentifierNick:'',
118
+                HeadURL:'',
119
+            },
120
+            kefuUrl:'https://images.shengws.com/ico_gjh.png',
121
+            userSigFlag:false,
122
+            imloginFlag:false,
123
+            message:'',
124
+            messageBox:[],
125
+            facelist:[],
126
+            showFace:false,
127
+        }
128
+    },
129
+    created(){
130
+        
131
+        this.getusersig();
132
+    },
133
+    methods:{
134
+        getusersig() {
135
+            getusersig().then(response => {
136
+                if (response.data.state == 0) {
137
+                    this.$message.error(response.data.msg);
138
+                    return false;
139
+                } else {
140
+                    this.useradmin = {
141
+                        usersig: response.data.data.sig,
142
+                        Indentifier: response.data.data.Indentifier,
143
+                        appIDAt3rd:response.data.data.appIDAt3rd,
144
+                        IdentifierNick:response.data.data.IdentifierNick,
145
+                        HeadURL:response.data.data.HeadURL,
146
+                    } 
147
+                    
148
+                    this.loginInfo.appIDAt3rd = this.useradmin.appIDAt3rd
149
+                    this.loginInfo.identifier = this.useradmin.Indentifier
150
+                    this.loginInfo.userSig = this.useradmin.usersig
151
+                    this.loginInfo.identifierNick = this.useradmin.IdentifierNick
152
+                    this.loginInfo.headurl = this.useradmin.HeadURL
153
+                    this.loginInfo.sdkAppID = response.data.data.sdkAppID
154
+                    this.loginInfo.accountType = response.data.data.accountType
155
+                    this.selToID = response.data.data.selToAdmin;
156
+                    this.userSigFlag = true;
157
+                }
158
+            });
159
+        },
160
+        showEmotion:function(){
161
+            this.facelist = [];
162
+            for (const index in webim.Emotions) {
163
+                this.facelist.push(webim.Emotions[index]);
164
+            }
165
+            this.showFace = true;
166
+        },
167
+        selectEmotion:function(face){
168
+            this.message += face[0];
169
+            this.showFace = false;
170
+        },
171
+        sendMessage:function(){
172
+            var message = this.message.trim();
173
+            var msgLen = webim.Tool.getStrBytes(message);
174
+            if(message == '') {
175
+                this.$message.error('不能发送空消息');
176
+                return false;
177
+            }
178
+            var maxLen, errInfo;
179
+            if (selType == webim.SESSION_TYPE.C2C) {
180
+                maxLen = webim.MSG_MAX_LENGTH.C2C;
181
+                errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";
182
+            } else {
183
+                maxLen = webim.MSG_MAX_LENGTH.GROUP;
184
+                errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";
185
+            }
186
+            if (msgLen > maxLen) {
187
+                this.$message.error(errInfo);
188
+                return false;
189
+            }
190
+            this.handleMsgSend(message);
191
+        },
192
+        handleMsgSend(msgContent) {
193
+            var selSess = new webim.Session(selType, this.selToID, this.selToID, this.kefuUrl, Math.round(new Date().getTime() / 1000));
194
+            var isSend = true; //是否为自己发送
195
+            var seq = -1; //消息序列,-1表示sdk自动生成,用于去重
196
+            var random = Math.round(Math.random() * 4294967296); //消息随机数,用于去重
197
+            var msgTime = Math.round(new Date().getTime() / 1000); //消息时间戳
198
+            var subType; //消息子类型
199
+            if (selType == webim.SESSION_TYPE.C2C) {
200
+                subType = webim.C2C_MSG_SUB_TYPE.COMMON;
201
+            } else {
202
+                subType = webim.GROUP_MSG_SUB_TYPE.COMMON;
203
+            }
204
+            var msg = new webim.Msg(selSess, isSend, seq, random, msgTime, this.loginInfo.identifier, subType, this.loginInfo.identifierNick);
205
+
206
+            var text_obj, face_obj, tmsg, emotionIndex, emotion, restMsgIndex;
207
+            //解析文本和表情
208
+            var expr = /\[[^[\]]{1,3}\]/mg;
209
+            var emotions = msgContent.match(expr);
210
+            if (!emotions || emotions.length < 1) {
211
+                text_obj = new webim.Msg.Elem.Text(msgContent);
212
+                msg.addText(text_obj);
213
+            } else {
214
+                for (var i = 0; i < emotions.length; i++) {
215
+                    tmsg = msgContent.substring(0, msgContent.indexOf(emotions[i]));
216
+                    if (tmsg) {
217
+                        text_obj = new webim.Msg.Elem.Text(tmsg);
218
+                        msg.addText(text_obj);
219
+                    }
220
+                    emotionIndex = webim.EmotionDataIndexs[emotions[i]];
221
+                    emotion = webim.Emotions[emotionIndex];
222
+
223
+                    if (emotion) {
224
+                        face_obj = new webim.Msg.Elem.Face(emotionIndex, emotions[i]);
225
+                        msg.addFace(face_obj);
226
+                    } else {
227
+                        text_obj = new webim.Msg.Elem.Text(emotions[i]);
228
+                        msg.addText(text_obj);
229
+                    }
230
+                    restMsgIndex = msgContent.indexOf(emotions[i]) + emotions[i].length;
231
+                    msgContent = msgContent.substring(restMsgIndex);
232
+                }
233
+                if (msgContent) {
234
+                    text_obj = new webim.Msg.Elem.Text(msgContent);
235
+                    msg.addText(text_obj);
236
+                }
237
+            }
238
+
239
+            msg.PushInfo = {
240
+                "PushFlag": 0,
241
+                "Desc": '测试离线推送内容', //离线推送内容
242
+                "Ext": '测试离线推送透传内容', //离线推送透传内容
243
+                "AndroidInfo": {
244
+                    "Sound": "android.mp3" //离线推送声音文件路径。
245
+                },
246
+                "ApnsInfo": {
247
+                    "Sound": "apns.mp3", //离线推送声音文件路径。
248
+                    "BadgeMode": 1
249
+                }
250
+            };
251
+
252
+            msg.PushInfoBoolean = true; //是否开启离线推送push同步
253
+            msg.sending = 1;
254
+            msg.originContent = msgContent;
255
+            // turnoffFaces_box();
256
+            var _this = this;
257
+
258
+            webim.sendMsg(msg, function (resp) {
259
+                _this.addMsg(msg);
260
+                _this.message = '';
261
+            }, function (err) {
262
+                console.log(err)
263
+            });
264
+        },
265
+        addMsg(msg, prepage) {
266
+            var messageitem = {
267
+                id:'',
268
+                message:'',
269
+                avatar:'',
270
+                time:'',
271
+                float:''
272
+            };
273
+            var isSelfSend, fromAccount, fromAccountNick, fromAccountImage, sessType, subType;
274
+
275
+            //webim.SESSION_TYPE.GROUP-群聊,
276
+            //webim.SESSION_TYPE.C2C-私聊,
277
+            sessType = msg.getSession().type();
278
+            isSelfSend = msg.getIsSend();//消息是否为自己发的
279
+            fromAccount = msg.getFromAccount();
280
+            if (!fromAccount) {
281
+                return;
282
+            }
283
+            if (isSelfSend) {//如果是自己发的消息
284
+                messageitem.avatar = this.loginInfo.headurl;
285
+                messageitem.float = "right";
286
+            } else {
287
+                messageitem.avatar = this.kefuUrl;
288
+                messageitem.float = "left";
289
+            }
290
+            messageitem.id = msg.random;
291
+            messageitem.time = webim.Tool.formatText2Html(webim.Tool.formatTimeStamp(msg.getTime()));
292
+            messageitem.message = this.convertMsgtoHtml(msg)
293
+            this.messageBox.push(messageitem);
294
+
295
+            var msgflow = document.getElementsByClassName("msg-inner")[0];
296
+            if (prepage) {
297
+                //300ms后,等待图片加载完,滚动条自动滚动到底部
298
+                if (msgflow.scrollTop == 0) {
299
+                    setTimeout(function () {
300
+                        msgflow.scrollTop = 0;
301
+                    }, 300);
302
+                }
303
+            } else {
304
+                //300ms后,等待图片加载完,滚动条自动滚动到底部
305
+                setTimeout(function () {
306
+                    msgflow.scrollTop = msgflow.scrollHeight;
307
+                }, 300);
308
+            }
309
+        },
310
+        sendPic(images, imgName) {
311
+            var _this = this;
312
+            if (!this.selToID) {
313
+                alert("请先选择对话用户");
314
+                return;
315
+            }
316
+
317
+            if (!this.selSess) {
318
+                this.selSess = new webim.Session(selType, this.selToID, this.selToID, this.kefuUrl, Math.round(new Date().getTime() / 1000));
319
+            }
320
+            var msg = new webim.Msg(this.selSess, true, -1, -1, -1, this.loginInfo.identifier, 0, this.loginInfo.identifierNick);
321
+            var images_obj = new webim.Msg.Elem.Images(images.File_UUID);
322
+            for (var i in images.URL_INFO) {
323
+                var img = images.URL_INFO[i];
324
+                var newImg;
325
+                var type;
326
+                switch (img.PIC_TYPE) {
327
+                    case 1://原图
328
+                        type = 1;//原图
329
+                        break;
330
+                    case 2://小图(缩略图)
331
+                        type = 3;//小图
332
+                        break;
333
+                    case 4://大图
334
+                        type = 2;//大图
335
+                        break;
336
+                }
337
+                newImg = new webim.Msg.Elem.Images.Image(type, img.PIC_Size, img.PIC_Width, img.PIC_Height, img.DownUrl);
338
+                images_obj.addImage(newImg);
339
+            }
340
+            msg.addImage(images_obj);
341
+            //if(imgName){
342
+            //    var data=imgName;//通过自定义消息中的data字段保存图片名称
343
+            //    var custom_obj = new webim.Msg.Elem.Custom(data, '', '');
344
+            //    msg.addCustom(custom_obj);
345
+            //}
346
+            //调用发送图片消息接口
347
+            webim.sendMsg(msg, function (resp) {
348
+                if (selType == webim.SESSION_TYPE.C2C) {//私聊时,在聊天窗口手动添加一条发的消息,群聊时,长轮询接口会返回自己发的消息
349
+                    _this.addMsg(msg);
350
+                }
351
+            }, function (err) {
352
+                alert(err.ErrorInfo);
353
+            });
354
+        },
355
+        bindScrollHistoryEvent(axtion){
356
+            var msgflow = document.getElementsByClassName("msg-inner")[0];
357
+            var _this = this;
358
+            if (axtion=='init') {
359
+                msgflow.onscroll = function () {
360
+                    if (msgflow.scrollTop == 0) {
361
+                        msgflow.scrollTop = 10;
362
+                        if (selType == webim.SESSION_TYPE.C2C) {
363
+                            _this.getPrePageC2CHistoryMsgs();
364
+                        } 
365
+                    }
366
+                }
367
+            }else {
368
+                msgflow.onscroll = null;
369
+            }
370
+        },
371
+        getPrePageC2CHistoryMsgs  (cbOk, cbError) {
372
+            var _this = this;
373
+            if (selType == webim.SESSION_TYPE.GROUP) {
374
+                _this.$message.error("当前的聊天类型为群聊天,不能进行拉取好友历史消息操作");
375
+                return;
376
+            }
377
+            var tempInfo = getPrePageC2CHistroyMsgInfoMap[_this.selToID];//获取下一次拉取的c2c消息时间和消息Key
378
+            var lastMsgTime;
379
+            var msgKey;
380
+            if (tempInfo) {
381
+                lastMsgTime = tempInfo.LastMsgTime;
382
+                msgKey = tempInfo.MsgKey;
383
+            } else {
384
+                _this.$message.error("获取下一次拉取的c2c消息时间和消息Key为空");
385
+                return;
386
+            }
387
+            var options = {
388
+                'Peer_Account': _this.selToID, //好友帐号
389
+                'MaxCnt': reqMsgCount, //拉取消息条数
390
+                'LastMsgTime': lastMsgTime, //最近的消息时间,即从这个时间点向前拉取历史消息
391
+                'MsgKey': msgKey
392
+            };
393
+            webim.getC2CHistoryMsgs(
394
+                options,
395
+                function (resp) {
396
+                    var complete = resp.Complete;//是否还有历史消息可以拉取,1-表示没有,0-表示有
397
+                    if (resp.MsgList.length == 0) {
398
+                        webim.Log.warn("没有历史消息了:data=" + JSON.stringify(options));
399
+                        return;
400
+                    }
401
+                    getPrePageC2CHistroyMsgInfoMap[_this.selToID] = {//保留服务器返回的最近消息时间和消息Key,用于下次向前拉取历史消息
402
+                        'LastMsgTime': resp.LastMsgTime,
403
+                        'MsgKey': resp.MsgKey
404
+                    };
405
+                    if (cbOk) {
406
+                        cbOk(resp.MsgList);
407
+                    } else {
408
+                        _this.getHistoryMsgCallback(resp.MsgList, true);
409
+                    }
410
+                },
411
+                cbError
412
+            );
413
+        },
414
+        getLastC2CHistoryMsgs (cbOk, cbError) {
415
+            var _this = this;
416
+            var lastMsgTime = 0;//第一次拉取好友历史消息时,必须传0
417
+            var msgKey = '';
418
+            var options = {
419
+                'Peer_Account': this.selToID, //好友帐号
420
+                'MaxCnt': reqMsgCount, //拉取消息条数
421
+                'LastMsgTime': lastMsgTime, //最近的消息时间,即从这个时间点向前拉取历史消息
422
+                'MsgKey': msgKey
423
+            };
424
+            this.selSess = null;
425
+            webim.MsgStore.delSessByTypeId(selType, this.selToID);
426
+
427
+            webim.getC2CHistoryMsgs(
428
+                options,
429
+                function (resp) {
430
+                    var complete = resp.Complete;//是否还有历史消息可以拉取,1-表示没有,0-表示有
431
+
432
+                    if (resp.MsgList.length == 0) {
433
+                        webim.Log.warn("没有历史消息了:data=" + JSON.stringify(options));
434
+                        return;
435
+                    }
436
+                    getPrePageC2CHistroyMsgInfoMap[_this.selToID] = {//保留服务器返回的最近消息时间和消息Key,用于下次向前拉取历史消息
437
+                        'LastMsgTime': resp.LastMsgTime,
438
+                        'MsgKey': resp.MsgKey
439
+                    };
440
+                    
441
+                    if (cbOk)
442
+                        cbOk(resp.MsgList);
443
+                },
444
+                cbError
445
+            );
446
+        },
447
+        getHistoryMsgCallback(msgList, prepage) {
448
+            var msg;
449
+            var prepage = prepage || false;
450
+
451
+            //如果是加载前几页的消息,消息体需要prepend,所以先倒排一下
452
+            if (prepage) {
453
+                msgList.reverse();
454
+            }
455
+
456
+            for (var j in msgList) {//遍历新消息
457
+                msg = msgList[j];
458
+                if (msg.getSession().id() == this.selToID) {//为当前聊天对象的消息
459
+                    this.selSess = msg.getSession();
460
+                    //在聊天窗体中新增一条消息
461
+                    this.addMsg(msg, prepage);
462
+                }
463
+            }
464
+            //消息已读上报,并将当前会话的消息设置成自动已读
465
+            webim.setAutoRead(this.selSess, true, true);
466
+        },
467
+        convertMsgtoHtml(msg) {
468
+            var html = "",
469
+                elems, elem, type, content;
470
+            elems = msg.getElems(); //获取消息包含的元素数组
471
+            var count = elems.length;
472
+            for (var i = 0; i < count; i++) {
473
+                elem = elems[i];
474
+                type = elem.getType();//获取元素类型
475
+                content = elem.getContent();//获取元素对象
476
+                switch (type) {
477
+                    case webim.MSG_ELEMENT_TYPE.TEXT:
478
+                        var eleHtml = this.convertTextMsgToHtml(content);
479
+                        //转义,防XSS
480
+                        html += webim.Tool.formatText2Html(eleHtml);
481
+                        break;
482
+                    case webim.MSG_ELEMENT_TYPE.FACE:
483
+                        html += this.convertFaceMsgToHtml(content);
484
+                        break;
485
+                    case webim.MSG_ELEMENT_TYPE.IMAGE:
486
+                        if (i <= count - 2) {
487
+                            var customMsgElem = elems[i + 1];//获取保存图片名称的自定义消息elem
488
+                            var imgName = customMsgElem.getContent().getData();//业务可以自定义保存字段,demo中采用data字段保存图片文件名
489
+                            html += this.convertImageMsgToHtml(content, imgName);
490
+                            i++;//下标向后移一位
491
+                        } else {
492
+                            html += this.convertImageMsgToHtml(content);
493
+                        }
494
+                        break;
495
+                    case webim.MSG_ELEMENT_TYPE.SOUND:
496
+                        html += this.convertSoundMsgToHtml(content);
497
+                        break;
498
+                    case webim.MSG_ELEMENT_TYPE.FILE:
499
+                        html += this.convertFileMsgToHtml(content);
500
+                        break;
501
+                    case webim.MSG_ELEMENT_TYPE.LOCATION:
502
+                        html += this.convertLocationMsgToHtml(content);
503
+                        break;
504
+                    case webim.MSG_ELEMENT_TYPE.CUSTOM:
505
+                        var eleHtml = this.convertCustomMsgToHtml(content);
506
+                        //转义,防XSS
507
+                        html += webim.Tool.formatText2Html(eleHtml);
508
+                        break;
509
+                    case webim.MSG_ELEMENT_TYPE.GROUP_TIP:
510
+                        var eleHtml = this.convertGroupTipMsgToHtml(content);
511
+                        //转义,防XSS
512
+                        html += webim.Tool.formatText2Html(eleHtml);
513
+                        break;
514
+                    default:
515
+                        webim.Log.error('未知消息元素类型: elemType=' + type);
516
+                        break;
517
+                }
518
+            }
519
+            return html;
520
+        },
521
+        convertTextMsgToHtml(content) {
522
+            return content.getText();
523
+        },
524
+        //解析表情消息元素
525
+        convertFaceMsgToHtml(content) {
526
+            var faceUrl = null;
527
+            var data = content.getData();
528
+            var index = webim.EmotionDataIndexs[data];
529
+
530
+            var emotion = webim.Emotions[index];
531
+            if (emotion && emotion[1]) {
532
+                faceUrl = emotion[1];
533
+            }
534
+            if (faceUrl) {
535
+                return "<img src='" + faceUrl + "'/>";
536
+            } else {
537
+                return data;
538
+            }
539
+        },
540
+        //解析图片消息元素
541
+        convertImageMsgToHtml(content, imageName) {
542
+            var smallImage = content.getImage(webim.IMAGE_TYPE.SMALL);//小图
543
+            var bigImage = content.getImage(webim.IMAGE_TYPE.LARGE);//大图
544
+            var oriImage = content.getImage(webim.IMAGE_TYPE.ORIGIN);//原图
545
+            if (!bigImage) {
546
+                bigImage = smallImage;
547
+            }
548
+            if (!oriImage) {
549
+                oriImage = smallImage;
550
+            }
551
+            return "<img name='" + imageName + "' src='" + smallImage.getUrl() + "#" + bigImage.getUrl() + "#" + oriImage.getUrl() + "' style='CURSOR: hand' id='" + content.getImageId() + "' bigImgUrl='" + bigImage.getUrl() + "'/>";
552
+        }, 
553
+        handleIMPicUload:function(fileobj){
554
+            var file = fileobj.file
555
+            console.log("file", file);
556
+            var _this = this;
557
+            var businessType;//业务类型,1-发群图片,2-向好友发图片
558
+            if (selType != webim.SESSION_TYPE.C2C) {//向好友发图片
559
+                this.$message.error('不支持群聊');
560
+                return; 
561
+            } 
562
+            businessType = webim.UPLOAD_PIC_BUSSINESS_TYPE.C2C_MSG;
563
+            //封装上传图片请求
564
+            var opt = {
565
+                'file': file, //图片对象
566
+                'onProgressCallBack': this.onProgressCallBack, //上传图片进度条回调函数
567
+                //'abortButton': document.getElementById('upd_abort'), //停止上传图片按钮
568
+                'To_Account': this.selToID, //接收者
569
+                'businessType': businessType//业务类型
570
+            };
571
+            //上传图片
572
+            webim.uploadPic(opt,
573
+                function (resp) {
574
+                    //上传成功发送图片
575
+                    _this.sendPic(resp, file.name);
576
+                    
577
+                },
578
+                function (err) {
579
+                    alert(err.ErrorInfo);
580
+                }
581
+            );
582
+        },
583
+        handleIMPicSuccess:function(){},
584
+        beforeIMPicUpload:function(file){
585
+            var fileType = file.type;
586
+            const isJPG = fileType.indexOf("image") > -1;
587
+            if (!isJPG) {
588
+                this.$message.error('只能上传图片');
589
+            }
590
+            return isJPG;
591
+        },
592
+        togglePhoneBox:function(){
593
+            if (this.showPhoneBox) {
594
+                this.showPhoneBox = false;
595
+            }else {
596
+                this.showPhoneBox = true;
597
+            }
598
+            this.showMsgBox = false;
599
+        },
600
+        toggleMsgBox:function(){
601
+            if (this.showMsgBox) {
602
+                this.showMsgBox = false;
603
+            }else {
604
+                this.showMsgBox = true;
605
+            }
606
+            this.showPhoneBox = false;
607
+        },
608
+        webimlogin(){
609
+            let _this = this;
610
+            let listeners = {
611
+                "onConnNotify": this.onConnNotify //监听连接状态回调变化事件,必填
612
+                , "jsonpCallback": this.jsonpCallback //IE9(含)以下浏览器用到的jsonp回调函数,
613
+                , "onMsgNotify": this.onMsgNotify //监听新消息(私聊,普通群(非直播聊天室)消息,全员推送消息)事件,必填
614
+                , "onProfileSystemNotifys": this.onProfileSystemNotifys //监听资料系统(自己或好友)通知事件,选填
615
+                , "onKickedEventCall": this.onKickedEventCall //被其他登录实例踢下线
616
+                , "onC2cEventNotifys": this.onC2cEventNotifys //监听C2C系统消息通道
617
+            };
618
+            webim.login(this.loginInfo, listeners, this.loginOptions, 
619
+                function(resp){
620
+                    _this.$message.success('webim登录成功');
621
+                    _this.imloginFlag = true;
622
+                },
623
+                function(err) {
624
+                    _this.$message.error('webim登录错误');
625
+                }
626
+            );
627
+        },
628
+        onConnNotify(){},
629
+        jsonpCallback(){},
630
+        onMsgNotify(newMsgList){
631
+            //监听新消息事件
632
+            var msgList = [];
633
+            var dateStart = null;
634
+            var dateEnd = null;
635
+
636
+            //console.warn(newMsgList);
637
+            var sess, newMsg, formId;
638
+            //获取所有聊天会话
639
+            var sessMap = webim.MsgStore.sessMap();
640
+
641
+            for (var j in newMsgList) {//遍历新消息
642
+
643
+                newMsg = newMsgList[j];
644
+                formId = newMsg.getSession().id();
645
+                if (formId.indexOf("AdminKeFu")<0) {
646
+                    continue;
647
+                }else {
648
+                    if (newMsg.getSession().id() == this.selToID) {//为当前聊天对象的消息
649
+                        this.addMsg(newMsg);
650
+                    }
651
+                    msgList.push(newMsg.elems[0].content.text);
652
+                }
653
+                
654
+            }
655
+        },
656
+        onProfileSystemNotifys(){},
657
+        onKickedEventCall(){},
658
+        onC2cEventNotifys(){},
659
+    },
660
+    watch:{
661
+        'userSigFlag':function(value){
662
+            if(this.userSigFlag) {
663
+                this.webimlogin();
664
+            }
665
+        },
666
+        'imloginFlag':function(value) {
667
+            var _this = this;
668
+            if (this.imloginFlag) {
669
+                this.bindScrollHistoryEvent('reset');
670
+                this.getLastC2CHistoryMsgs(function (msgList) {
671
+                    _this.getHistoryMsgCallback(msgList);
672
+                    _this.bindScrollHistoryEvent('init');
673
+                    //绑定滚动操作
674
+                }, function (err) {
675
+                    alert(err.ErrorInfo);
676
+                });
677
+            }
678
+        }
679
+    },
680
+
681
+}
682
+</script>
683
+
684
+<style scoped>
685
+.contact-box {
686
+    position: fixed;
687
+    right: 12px;
688
+    bottom: 10%;
689
+    margin-top: -100px;
690
+    z-index: 9999;
691
+}
692
+    
693
+.contact-box .contact-box-item{
694
+    position: relative;
695
+    margin-bottom: 6px;
696
+    border: 1px solid #999;
697
+}
698
+
699
+.contact-box .contact-box-item .box-btn {
700
+    width: 48px;
701
+    height: 48px;
702
+    text-align: center;
703
+    display: block;
704
+    position: relative;
705
+    background: #fff;
706
+    cursor: pointer;
707
+}
708
+.contact-box .contact-box-item .box-btn i{
709
+    font-size:30px; 
710
+    margin: 9px;
711
+    color: #59a3ec;
712
+    display: inline-block;
713
+}
714
+/* .contact-box .contact-box-item .box-btn:hover {
715
+} */
716
+.contact-box .box-btn span{
717
+    display: none;
718
+    color:#fff;
719
+    padding: 8px;
720
+    font-size: 14px;
721
+    background: #5aa6f1;
722
+}
723
+.contact-box .box-btn:hover span{
724
+    display: block;
725
+}
726
+.contact-box .box-btn:hover i{
727
+    display: none;
728
+}
729
+.contact-box .contact-phone-box {
730
+    border: 1px solid #999;
731
+    position: absolute;
732
+    bottom: 0px;
733
+    right: 56px;
734
+    height: 48px;
735
+    display:flex;
736
+    background: #fff;
737
+    width: 230px;
738
+    align-items: center;
739
+}
740
+.contact-box .contact-phone-box i {
741
+    color: #59a3ec;
742
+    font-size:30px; 
743
+    margin: 9px;
744
+}
745
+.contact-box .contact-phone-box span {
746
+    font-size:20px; 
747
+    margin-left: 15px;
748
+    color: #485b6d;
749
+}
750
+
751
+.contact-box .contact-info-box {
752
+    border: 1px #e5e5e5 solid;
753
+    position: absolute;
754
+    bottom: 0px;
755
+    right: 56px;
756
+    display: none;
757
+    background: #fff;
758
+    width: 175px;
759
+    z-index: 10000;
760
+}
761
+.contact-box .msg-box:hover .contact-info-box{
762
+    display:block;
763
+    color: #485b6d;
764
+    font-size:20px; 
765
+    padding: 5px;
766
+}
767
+
768
+.contact-box .contact-msg-box {
769
+    border: 1px #e5e5e5 solid;
770
+    position: absolute;
771
+    bottom: 0px;
772
+    right: 56px;
773
+    background: #fff;
774
+}
775
+.contact-box .msg-box-panel {
776
+    width: 408px;
777
+    background-color: #fff;
778
+    position: relative;
779
+}
780
+.contact-box .panel-header {
781
+    border-bottom: 1px #e5e5e5 solid;
782
+}
783
+.contact-box .panel-header .kf-close {
784
+    width: 30px;
785
+    height: 20px;
786
+    float: right;
787
+    cursor: pointer;
788
+    margin: 12px 0 0 0;
789
+}
790
+.contact-box .panel-header .kf-h-line {
791
+    float: left;
792
+    color: #485b6d;
793
+    font-size: 16px;
794
+    line-height: 40px;
795
+    height: 40px;
796
+    padding-left: 10px;
797
+}
798
+.contact-box .panel-body {
799
+    overflow-x: visible;
800
+    overflow-y: auto;
801
+    height: 182px;
802
+}
803
+
804
+.contact-box .msg-inner {
805
+    overflow-y: auto;
806
+    overflow-x: hidden;
807
+    height: 100%;
808
+    border-bottom: 1px #e5e5e5 solid;
809
+}
810
+.contact-box .scroll-y::-webkit-scrollbar {
811
+    width: 6px;
812
+    height: 3px;
813
+}
814
+.contact-box .scroll-y::-webkit-scrollbar-thumb {
815
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.1);
816
+    box-shadow: inset 0 0 6px rgba(0,0,0,.1);
817
+    border-radius: 2px;
818
+}
819
+.contact-box .scroll-y::-webkit-scrollbar-track {
820
+    border-radius: 2px;
821
+}
822
+.contact-box .msg-inner .cell {
823
+    margin-bottom: 15px;
824
+}
825
+.contact-box .cell_right {
826
+    float: right;
827
+}
828
+
829
+.contact-box .clearfix {
830
+    clear: both;
831
+}
832
+.contact-box .msg-inner .msg_body {
833
+    border: 1px #e5e5e5 solid;
834
+    line-height: 22px;
835
+    display: inline-block;
836
+    padding: 6px;
837
+    max-width: 292px;
838
+}
839
+.contact-box .fl {
840
+    float: left;
841
+}
842
+.contact-box .msg-inner .msg_body .inner {
843
+    color: #465b6e;
844
+}
845
+.contact-box .msg-inner .cell_pic {
846
+    width: 40px;
847
+    height: 40px;
848
+    display: inline-block;
849
+    margin: 0 20px;
850
+}
851
+.contact-box .msg-inner .cell_pic .pic {
852
+    width: 40px;
853
+    height: 40px;
854
+    display: flex;
855
+}
856
+.contact-box .msg-inner .cell_pic .pic img {
857
+    width: 40px;
858
+    height: 40px;
859
+    border-radius: 50%;
860
+    object-fit: cover;
861
+    object-position: center;
862
+}
863
+
864
+.contact-box .msg-box-panel .panel-booter .textarea {
865
+    border: 1px #fff solid;
866
+    padding: 10px 20px;
867
+    color: #465b6e;
868
+    height: 100px;
869
+    resize: none;
870
+    width: 100%;
871
+}
872
+.contact-box .msg-box-panel .panel-booter .msg-send-btn-box {
873
+    padding: 0 20px 10px 20px;
874
+    float: left;
875
+    background: #fff;
876
+    width: 408px;
877
+}
878
+.contact-box .msg-box-panel .panel-booter .time {
879
+    font-size: 12px;
880
+    color: #bebebe;
881
+    height: 26px;
882
+    line-height: 26px;
883
+}
884
+.contact-box .msg-box-panel .panel-booter .msg-send-btn-box .send_btn {
885
+    color: #fff;
886
+    padding: 6px 20px;
887
+    border-radius: 4px;
888
+    font-size: 12px;
889
+    background: #58a1ed;
890
+    border: none;
891
+}
892
+
893
+.contact-box  .panel-tool {
894
+    color: #465b6e;
895
+    height: 30px;
896
+    border-bottom: 1px #e5e5e5 solid;
897
+    display:flex;
898
+    align-items: center;
899
+}
900
+
901
+.contact-box  .panel-tool i {
902
+    font-size: 20px;
903
+    padding: 0 5px;
904
+    margin: 0 5px;
905
+    cursor: pointer;
906
+}
907
+
908
+.contact-box  .panel-tool .icon-face::before {
909
+    content: '\1F642';
910
+    font-size: 15px;
911
+}
912
+.contact-box .face-box {
913
+    width: 304px;
914
+    z-index: 10001;
915
+    background: #fff;
916
+    position: relative;
917
+    bottom: 70px;
918
+    left: -100px;
919
+    border: 2px #e5e5e5 solid;
920
+}
921
+.contact-box .face-box-list li {
922
+    display: inline-block;
923
+    
924
+    border-right: 1px #CCC solid;
925
+    border-bottom: 1px #CCC solid;
926
+    cursor: pointer;
927
+}
928
+.contact-box .face-box-title {
929
+    border-bottom: 1px #e5e5e5 solid;
930
+    margin: 2px 0;
931
+}
932
+</style>

+ 965 - 0
src/scrm_pages/kefu/index.vue ファイルの表示

@@ -0,0 +1,965 @@
1
+<template>
2
+  <div class="main-contain">
3
+    <div class="position">
4
+      <bread-crumb :crumbs='crumbs'></bread-crumb>
5
+    </div>
6
+    <div class="app-container">
7
+        <div class="customer_plate white-bg">
8
+            <div class="aside">
9
+                <div class="customer_search clearfix">
10
+                <div class="super_searchbox">
11
+                    <span class="search_icon"></span>
12
+                    <input type="text" class="cus_search_input" v-model="searchname" placeholder="请输入客户名称">
13
+                </div>
14
+                </div>
15
+                <div class="client_list_box">
16
+                <div class="client_list">
17
+                    <ul class="users-list">
18
+                    <li v-for="(patient, key) in patientsMap" v-show="searchname == '' || (patient.name.indexOf(searchname)>=0)" :class="thisPatient && patient.user_id==thisPatient.user_id?'Active':''" :key="key" :id="'sessDiv_User_'+patient.user_id" class="item" :data-username="patient.name" @click="chooseThisUser(patient)">
19
+                        <span :id="'badgeDiv_User_'+patient.user_id" class="circle-count" style="" v-show="patient.unread_msg_count"><i class="count">{{patient.unread_msg_count}}</i></span>
20
+                        <figure :id="'faceImg_User_'+patient.user_id" class="session-pic"><img :src="patient.avatar"></figure>
21
+                        <h3 :id="'nameDiv_User_'+patient.user_id" class="nick">{{patient.name}}</h3>
22
+                        <!-- <span class="square-close" title="退出接待" :data-toid="'User_'+patient.user_id">×</span> -->
23
+                    </li>
24
+                    </ul>
25
+                </div>
26
+                </div>
27
+            </div>
28
+
29
+            <div class="left_content">
30
+                <div class="conversation-admin">
31
+                <span class="nickname">
32
+                    <span></span>
33
+                </span>
34
+                </div>
35
+                <div class="message-list-wrap">
36
+                <div class="message-list-item">
37
+                    <ul class="message-list">
38
+                    
39
+                    <li v-for="(messageitem, key) in messageBox" :key="key" :id="'id_'+messageitem.id" class="message-item clearfix">
40
+                        <div class="time"><span v-html="messageitem.time"></span></div>
41
+                        <div class="user " :class="messageitem.float">
42
+                            <figure class="bg-pic circle-bg-pic">
43
+                            <div class="bg-pic-content">
44
+                                <img :src="messageitem.avatar">
45
+                            </div>
46
+                            </figure>
47
+                        </div>
48
+                        <div class="message-body " :class="messageitem.float"><div class="inner" v-html="messageitem.message"></div></div>
49
+                    </li>
50
+
51
+                    </ul>
52
+                </div>
53
+                <div class="no_session">
54
+                    <span class="no_session_pic"></span>
55
+                    <p class="no_session_txt">没有选中会话哦!</p>
56
+                </div>
57
+                </div>
58
+                <div class="send_box" v-loading="loadingbox" :element-loading-text="loadingboxtext">
59
+                <div class="inputer_actions">
60
+                    <!-- <div class="face">
61
+                    <span class="face_icon" @click="showEmotionDialog"></span>
62
+                    </div> -->
63
+                    <div class="picture">
64
+                    <span class="picture_icon" @click="selectPicClick"></span>
65
+                    </div>
66
+                </div>
67
+                <div id="wl_faces_box" class="wl_faces_box" v-bind:style="{left:'0px', display:facesBoxDisplay}">
68
+                    <div class="wl_faces_content">
69
+                    <div class="title">
70
+                        <ul>
71
+                        <li class="title_name">常用表情</li>
72
+                        <li class="wl_faces_close">
73
+                            <span @click="facesBoxDisplay='none'">&nbsp;</span>
74
+                        </li>
75
+                        </ul>
76
+                    </div>
77
+                    <div id="wl_faces_main" class="wl_faces_main">
78
+                        <ul id="emotionUL">
79
+                        <li v-for="(emotion, key) in emotionList" :key="key" @click="chooseThisFace(emotion)">
80
+                            <img :src="emotion.src" :id="emotion.id" alt="" style="cursor:pointer;">
81
+                        </li>
82
+                        </ul>
83
+                    </div>
84
+                    </div>
85
+                    <div class="wlf_icon"></div>
86
+                </div>
87
+                <div class="inputer-area">
88
+                    <textarea
89
+                    maxlength="500" v-model="message"
90
+                    class="message-textarea transparent-txta"
91
+                    placeholder
92
+                    id="message"
93
+                    ></textarea>
94
+                </div>
95
+                <div class="send_box_btn">
96
+                    <button class="send_btn" id="sendMessaeg" @click="sendMessage">发送</button>
97
+                </div>
98
+                </div>
99
+            </div>
100
+        </div>
101
+    </div>
102
+  </div>
103
+</template>
104
+
105
+<script>
106
+  import BreadCrumb from '../components/bread-crumb'
107
+  export default {
108
+    name: 'commentList',
109
+    components:{
110
+      BreadCrumb,
111
+    },
112
+    data(){
113
+      return{
114
+        crumbs: [
115
+          { path: false, name: '客服管理' },
116
+          { path: false, name: '咨询管理' }
117
+        ],
118
+        searchname:'',
119
+        patientsMap:{},
120
+        thisPatient:null,
121
+        messageBox:[],
122
+      }
123
+    },
124
+    methods:{},
125
+    created(){
126
+    }
127
+  }
128
+</script>
129
+
130
+<style scoped>
131
+  /*.app-container .cell.clearfix .time ul li {*/
132
+    /*float: left;*/
133
+    /*list-style: none;*/
134
+    /*cursor: pointer;*/
135
+    /*padding: 6px 20px;*/
136
+    /*color: #606266;*/
137
+    /*border-radius: 4px;*/
138
+    /*margin: 0 8px 0 0;*/
139
+    /*font-size: 14px;*/
140
+    /*text-align: center;*/
141
+  /*}*/
142
+
143
+  
144
+.app-container{
145
+  height: 750px;  
146
+}
147
+.customer_plate {
148
+  width: 100%;
149
+  display: -webkit-box;
150
+  display: -webkit-flex;
151
+  display: -moz-box;
152
+  display: -ms-flexbox;
153
+  display: flex;
154
+  -webkit-box-flex: 1;
155
+  -webkit-flex: 1;
156
+  -moz-box-flex: 1;
157
+  -ms-flex: 1;
158
+  flex: 1;
159
+  height:100%;
160
+}
161
+.customer_plate .aside {
162
+  width: 282px;
163
+  -webkit-flex-shrink: 0;
164
+  -ms-flex-negative: 0;
165
+  flex-shrink: 0;
166
+  position: relative;
167
+  border-right: 1px solid #e5e8ea;
168
+}
169
+.customer_plate .aside .client_list_box {
170
+  position: absolute;
171
+  width: 100%;
172
+  top: 50px;
173
+  left: 0;
174
+  bottom: 0;
175
+  overflow-x: visible;
176
+  overflow-y: auto;
177
+}
178
+.channelswitch-wrap {
179
+  position: absolute;
180
+  top: 0;
181
+  left: 0;
182
+  right: 0;
183
+  bottom: 0;
184
+}
185
+.customer_plate .aside .client_list_box .client_list {
186
+  height: 100%;
187
+  overflow: hidden;
188
+  overflow-y: auto;
189
+}
190
+.customer_plate .aside .customer_search {
191
+  margin: 0 10px;
192
+  height: 34px;
193
+}
194
+.customer_plate .aside .super_searchbox {
195
+  padding: 0 8px;
196
+  background-color: #f4f7fa;
197
+  border-radius: 30px;
198
+  margin-top: 15px;
199
+  font-size: 12px;
200
+}
201
+.customer_plate .aside .super_searchbox .cus_search_input {
202
+  border: none;
203
+  background: none;
204
+  width: 224px;
205
+  height: 22px;
206
+  line-height: 22px;
207
+}
208
+.customer_plate .aside .super_searchbox .search_icon {
209
+  display: inline-block;
210
+  width: 12px;
211
+  height: 12px;
212
+  background: url(http://jk.kuyicloud.com/static/images/ico.png) no-repeat;
213
+  float: left;
214
+  background-position: -460px -314px;
215
+  margin: 4px 5px 0 0;
216
+}
217
+.left_content {
218
+  -webkit-box-flex: 1;
219
+  -webkit-flex: 1;
220
+  -moz-box-flex: 1;
221
+  -ms-flex: 1;
222
+  flex: 1;
223
+  display: -webkit-box;
224
+  display: -webkit-flex;
225
+  display: -moz-box;
226
+  display: -ms-flexbox;
227
+  display: flex;
228
+  position: relative;
229
+  width: 100%;
230
+  justify-content: flex-start;
231
+  flex-direction: column;
232
+}
233
+.left_content .message-list-wrap {
234
+  position: absolute;
235
+  top: 50px;
236
+  overflow: hidden;
237
+  left: 0;
238
+  right: 0;
239
+  border-bottom: 1px #e5e8ea solid;
240
+  bottom: 210px;
241
+}
242
+.left_content .message-list-wrap .message-list-item {
243
+  height: 100%;
244
+  overflow-x: hidden;
245
+  overflow-y: auto;
246
+}
247
+.left_content .message-list-wrap .message-list {
248
+  padding: 0 12px 20px;
249
+}
250
+.left_content .conversation-admin {
251
+  height: 48px;
252
+  line-height: 48px;
253
+  border-bottom: 1px #e5e8ea solid;
254
+  margin-left: 2px;
255
+  width: 100%;
256
+}
257
+.left_content .conversation-admin .nickname {
258
+  padding-left: 22px;
259
+}
260
+.client_list ul {
261
+  list-style: none;
262
+}
263
+.client_list ul .item {
264
+  padding: 17px 12px 17px 62px;
265
+  min-height: 36px;
266
+  cursor: pointer;
267
+  font-size: 12px;
268
+  transition: background-color 0.2s linear;
269
+  -webkit-transition: background-color 0.2s linear;
270
+  -moz-transition: background-color 0.2s linear;
271
+  position: relative;
272
+}
273
+.client_list ul .Active {
274
+  background: #f4f7fa;
275
+}
276
+.client_list ul .item .nick {
277
+  font-size: 14px;
278
+  color: #485b6d;
279
+  margin-bottom: 7px;
280
+}
281
+.client_list ul .item:hover {
282
+  background: #dfedfb;
283
+}
284
+.client_list ul .item .time {
285
+  position: absolute;
286
+  top: 14px;
287
+  right: 12px;
288
+  color: #a8b3ba;
289
+}
290
+.client_list ul .item .circle-count {
291
+  padding: 2px;
292
+  background-color: #ff7979;
293
+  text-align: center;
294
+  left: 8px;
295
+  z-index: 2;
296
+  min-width: 17px;
297
+  min-height: 15px;
298
+  line-height: 12px;
299
+  border-radius: 10px;
300
+  position: absolute;
301
+  top: 12px;
302
+  display: inline-block;
303
+}
304
+.client_list ul .item .circle-count .count {
305
+  color: #fff;
306
+  display: inline-block;
307
+  -webkit-transform: scale(0.83);
308
+  -moz-transform: scale(0.83);
309
+  -ms-transform: scale(0.83);
310
+  transform: scale(0.83);
311
+}
312
+.client_list ul .item .session-pic {
313
+  position: absolute;
314
+  top: 17px;
315
+  left: 13px;
316
+  width: 40px;
317
+  height: 40px;
318
+  border-radius: 50%;
319
+  overflow: hidden;
320
+  display: inline-block;
321
+}
322
+.client_list ul .item .session-pic img {
323
+  width: 40px;
324
+  height: 40px;
325
+}
326
+.client_list ul .item .square-close {
327
+  color: #fff;
328
+  background-color: #d2d2d5;
329
+  display: none;
330
+  width: 14px;
331
+  height: 14px;
332
+  line-height: 12px;
333
+  text-align: center;
334
+  position: absolute;
335
+  top: 0;
336
+  right: 0;
337
+}
338
+.client_list ul .item:hover .square-close {
339
+  display: block;
340
+}
341
+.client_list ul .item .desc {
342
+  color: #a8b3ba;
343
+  text-overflow: ellipsis;
344
+  white-space: nowrap;
345
+  overflow: hidden;
346
+  width: 150px;
347
+}
348
+.service_fixed {
349
+  position: fixed;
350
+}
351
+.message-list-wrap ul li {
352
+  padding: 12px;
353
+}
354
+.message-list-wrap .message-item .time {
355
+  text-align: center;
356
+  margin: 20px 0 6px 0;
357
+}
358
+.message-list-wrap .message-item .time span {
359
+  font-size: 12px;
360
+  color: #a8b3ba;
361
+}
362
+.message-list .message-item .user .bg-pic {
363
+  display: inline-block;
364
+  margin-right: 20px;
365
+}
366
+.message-list .message-item .message-body {
367
+  background: #e5e8ea;
368
+  padding: 16px 12px 12px 12px;
369
+  border-radius: 4px;
370
+  color: #485b6d;
371
+  max-width: 520px;
372
+}
373
+.message-list .message-item .user .bg-pic .bg-pic-content {
374
+  border-radius: 50%;
375
+  display: inline-block;
376
+  width: 40px;
377
+  height: 40px;
378
+}
379
+.message-list .message-item .user .bg-pic img {
380
+  width: 40px;
381
+  height: 40px;
382
+  border-radius: 50%;
383
+  display: inline-block;
384
+}
385
+.no_session {
386
+  text-align: center;
387
+}
388
+.send_box {
389
+  position: absolute;
390
+  font-size: 13px;
391
+  bottom: 0;
392
+  height: 210px;
393
+  left: 0;
394
+  right: 0;
395
+  display: -webkit-box;
396
+  display: -webkit-flex;
397
+  display: -moz-box;
398
+  display: -ms-flexbox;
399
+  display: flex;
400
+  -webkit-box-orient: vertical;
401
+  -webkit-box-direction: normal;
402
+  -webkit-flex-direction: column;
403
+  -moz-box-orient: vertical;
404
+  -moz-box-direction: normal;
405
+  -ms-flex-direction: column;
406
+  flex-direction: column;
407
+}
408
+.send_box .inputer_actions {
409
+  padding: 10px;
410
+  background: #f5f5f5;
411
+}
412
+
413
+.send_box .inputer_actions .face {
414
+  float: left;
415
+  margin: 0;
416
+  height: auto;
417
+}
418
+.send_box .inputer_actions .face_icon {
419
+  width: 24px;
420
+  height: 22px;
421
+  background: url(http://jk.kuyicloud.com/static/images/ico.png) no-repeat -478px -314px;
422
+  display: inline-block;
423
+  margin-right: 22px;
424
+  cursor: pointer;
425
+}
426
+.send_box .inputer_actions .picture_icon {
427
+  width: 28px;
428
+  height: 24px;
429
+  background: url(http://jk.kuyicloud.com/static/images/ico.png) no-repeat -508px -314px;
430
+  display: inline-block;
431
+  margin-right: 22px;
432
+  cursor: pointer;
433
+}
434
+.inputer-area {
435
+  -webkit-box-flex: 1;
436
+  -webkit-flex: 1;
437
+  -moz-box-flex: 1;
438
+  -moz-flex: 1;
439
+  -ms-flex: 1;
440
+  flex: 1;
441
+  margin: 2px;
442
+  overflow: hidden;
443
+  display: -webkit-box;
444
+  display: -webkit-flex;
445
+  display: -moz-flex;
446
+  display: -ms-flexbox;
447
+  display: -moz-box;
448
+  display: flex;
449
+  -webkit-box-direction: normal;
450
+  -webkit-box-orient: vertical;
451
+  -webkit-flex-direction: column;
452
+  -moz-flex-direction: column;
453
+  -ms-flex-direction: column;
454
+  flex-direction: column;
455
+}
456
+.inputer-area .message-textarea {
457
+  display: -webkit-box;
458
+  display: -webkit-flex;
459
+  display: -moz-flex;
460
+  display: -ms-flexbox;
461
+  display: -moz-box;
462
+  display: flex;
463
+  -webkit-box-flex: 1;
464
+  -webkit-flex: 1;
465
+  -moz-box-flex: 1;
466
+  -moz-flex: 1;
467
+  -ms-flex: 1;
468
+  flex: 1;
469
+  width: auto;
470
+  height: 100%;
471
+  resize: none;
472
+  margin: 0;
473
+  padding: 9px 4px;
474
+  font-size: 14px;
475
+  line-height: 1.5em;
476
+  border: none;
477
+  overflow-x: hidden;
478
+  overflow-y: auto;
479
+  border-radius: 0;
480
+  -webkit-box-shadow: none;
481
+  box-shadow: none;
482
+  padding: 0 9px 4px;
483
+}
484
+.send_box .send_box_btn {
485
+  position: absolute;
486
+  bottom: 26px;
487
+  right: 40px;
488
+}
489
+.send_box .send_box_btn .send_btn {
490
+  background: #58a2ec;
491
+  color: #fff;
492
+  padding: 12px 55px;
493
+  border-radius: 4px;
494
+  border: none;
495
+  font-size: 14px;
496
+}
497
+/*
498
+To change this license header, choose License Headers in Project Properties.
499
+To change this template file, choose Tools | Templates
500
+and open the template in the editor.
501
+*/
502
+/*
503
+    Created on : 2015-7-6, 15:55:30
504
+    Author     : peakerdong
505
+*/
506
+
507
+#login {
508
+    display: block;
509
+    margin: 150px auto;
510
+    text-align: center;
511
+}
512
+
513
+.aio {
514
+    display: none;
515
+    width: 734px;
516
+    border: 1px black solid;
517
+    padding: 0px;
518
+    background: white;
519
+    margin: 20px auto;
520
+    font: 10px/1.5 "微软雅黑";
521
+}
522
+
523
+.titlebar {
524
+    height: 82px;
525
+    background: #5c95b3;
526
+}
527
+
528
+.titlebar #p_my_face {
529
+    position: relative;
530
+    width: 60px;
531
+    height: 60px;
532
+    border: 1px white solid;
533
+    margin: 10px;
534
+    float: left;
535
+}
536
+
537
+.titlebar #t_my_name {
538
+    position: relative;
539
+    top: 10px;
540
+    left: 10px;
541
+    float: left;
542
+    font-size: 20px;
543
+    color: white;
544
+}
545
+
546
+.titlebar #t_my_menu {
547
+    width: 150px;
548
+    position: relative;
549
+    top: 5px;
550
+    right: 5px;
551
+    float: right;
552
+
553
+}
554
+
555
+.sesspart {
556
+    clear: both;
557
+    float: left;
558
+    width: 208px;
559
+    height: 535px;
560
+    background: #d7eaf3;
561
+}
562
+
563
+.accordion {
564
+    margin-bottom: 18px;
565
+}
566
+
567
+.accordion-group {
568
+    margin-bottom: 2px;
569
+    border: 1px solid #e5e5e5;
570
+    -webkit-border-radius: 4px;
571
+    -moz-border-radius: 4px;
572
+    border-radius: 4px;
573
+}
574
+
575
+.accordion-heading {
576
+    border-bottom: 0;
577
+    background-color: bisque;
578
+}
579
+
580
+.accordion-heading .accordion-toggle {
581
+    display: block;
582
+    padding: 8px 15px;
583
+    font-size: medium;
584
+}
585
+
586
+.accordion-inner {
587
+    padding: 9px 15px;
588
+    border-top: 1px solid #e5e5e5;
589
+}
590
+.sesslist-recent {
591
+    height: 450px;
592
+    background: #f5f5f5;
593
+    border-width: 0px 1px 0px 0px;
594
+    border-color: #d5d6d7;
595
+    border-style: solid;
596
+}
597
+
598
+
599
+.sesslist {
600
+    /* height: 400px; */
601
+    height: 450px;
602
+    background: #f5f5f5;
603
+    border-width: 0px 1px 0px 0px;
604
+    border-color: #d5d6d7;
605
+    border-style: solid;
606
+    overflow: auto;
607
+}
608
+
609
+.sesslist-group {
610
+    /* height: 400px; */
611
+    height: 450px;
612
+    background: #f5f5f5;
613
+    border-width: 0px 1px 0px 0px;
614
+    border-color: #d5d6d7;
615
+    border-style: solid;
616
+    overflow: auto;
617
+}
618
+
619
+.sessinfo {
620
+    clear: both;
621
+    height: 50px;
622
+    border-width: 0px 0px 1px 0px;
623
+    border-color: #d5d6d7;
624
+    border-style: solid;
625
+}
626
+
627
+.sessinfo-sel {
628
+    clear: both;
629
+    height: 50px;
630
+    border-width: 0px 0px 1px 0px;
631
+    border-color: #d5d6d7;
632
+    border-style: solid;
633
+    background: #d7eaf3;
634
+}
635
+
636
+.face {
637
+    float: left;
638
+    width: 40px;
639
+    height: 40px;
640
+    margin: 5px 5px 5px 10px;
641
+}
642
+
643
+.name {
644
+    float: left;
645
+    height: 20px;
646
+    text-indent: 2px;
647
+    font-size: 12px;
648
+    color: #1f1f1f;
649
+    margin: 15px 0 0 0;
650
+}
651
+
652
+.badge {
653
+    display: none;
654
+    float: right;
655
+    margin: 18px 0 0 0;
656
+    width: 32px;
657
+    height: 20px;
658
+    background: #f00000;
659
+    color: white;
660
+    text-align: center;
661
+    -webkit-border-radius: 10px;
662
+    -moz-border-radius: 10px;
663
+    border-radius: 10px;
664
+}
665
+
666
+.badge span {
667
+    position: relative;
668
+    top: 1px;
669
+    font-size: 10px;
670
+}
671
+
672
+.chatpart {
673
+    float: right;
674
+    width: 526px;
675
+    border: 0px red solid;
676
+    background: #d7eaf3;
677
+    margin-top: -535px;
678
+}
679
+
680
+.msgflow {
681
+    width: 525px;
682
+    height: 380px;
683
+    border: 1px rgb(181, 178, 178) solid;
684
+    padding: 20px 6px 0 6px;
685
+    background: #f5f5f5;
686
+    overflow: auto;
687
+}
688
+.msgflow .onemsg{position:relative;}
689
+.msgflow .onemsg .msghead {
690
+    color: green;
691
+    line-height: 12px;
692
+    font-size: 12px;
693
+}
694
+
695
+.msgflow .onemsg .msgbody {
696
+    margin: 0 0 0 18px;
697
+    line-height: 13px;
698
+    font-size: 14px;
699
+}
700
+
701
+.msgflow .msgbody img {
702
+    max-width: 500px;
703
+}
704
+
705
+.editbar {
706
+    width: 526px;
707
+    height: 25px;
708
+}
709
+
710
+.chat02_title_btn {
711
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/icon.png') no-repeat 0 0;
712
+    cursor: pointer;
713
+    float: left;
714
+    display: block;
715
+    width: 15px;
716
+    height: 15px;
717
+    margin: 5px 6px;
718
+}
719
+
720
+.ctb01 {
721
+    background-position: 0 -90px;
722
+    margin-left: 18px;
723
+    _margin-left: 8px;
724
+}
725
+
726
+.ctb03 {
727
+    background-position: 0 -152px;
728
+}
729
+
730
+.ctb02 {
731
+    background-position: 0 -457px;
732
+}
733
+
734
+.ctb05 {
735
+    background-position: 0 -217px;
736
+}
737
+
738
+.ctb04 {
739
+    background-position: 0 -543px;
740
+}
741
+
742
+.wl_faces_box {
743
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/wlf_bg.png') repeat 0 0;
744
+    position: relative;
745
+    /*position: absolute;*/
746
+    width: 428px;
747
+    height: 225px;
748
+    bottom: 290px;
749
+    left: -42px;
750
+    display: none;
751
+}
752
+
753
+.wl_faces_content {
754
+    background: #fff;
755
+    border: 1px #ccc solid;
756
+    width: 417px;
757
+    height: 216px;
758
+    margin: 3px 4px;
759
+}
760
+
761
+.wl_faces_content .title {
762
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/wlf_title_bg.jpg') repeat-x 0 0;
763
+    height: 40px;
764
+    position: relative;
765
+}
766
+
767
+.wl_faces_content .title ul {
768
+
769
+}
770
+
771
+.wl_faces_content .title ul li {
772
+    position: absolute;
773
+    display: block;
774
+}
775
+
776
+.wl_faces_content .title ul li.title_name {
777
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/wlf_title_btn.jpg') no-repeat 0 0;
778
+    width: 82px;
779
+    height: 30px;
780
+    bottom: 0;
781
+    _bottom: -2px;
782
+    left: 15px;
783
+    text-align: center;
784
+    line-height: 32px;
785
+    font-weight: bold;
786
+    color: #333;
787
+}
788
+
789
+.wl_faces_content .title ul li.wl_faces_close {
790
+    right: 8px;
791
+    top: 15px;
792
+}
793
+
794
+.wl_faces_content .title ul li.wl_faces_close span {
795
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/icon.png') repeat-x 0 0;
796
+    cursor: pointer;
797
+    display: block;
798
+    width: 15px;
799
+    height: 15px;
800
+}
801
+
802
+.wl_faces_main {
803
+
804
+}
805
+
806
+.wl_faces_main ul {
807
+    margin: 12px 12px;
808
+    padding: 0px;
809
+    overflow: hidden;
810
+    border-top: 1px #CCC solid;
811
+    border-left: 1px #CCC solid;
812
+    list-style: none;
813
+    width: 393px;
814
+}
815
+
816
+.wl_faces_main ul li {
817
+    float: left;
818
+    border-right: 1px #CCC solid;
819
+    border-bottom: 1px #CCC solid;
820
+    height: 28px;
821
+    width: 28px;
822
+    margin: 0px 0px 0px 0px;
823
+    padding: 4px 2px;
824
+    text-align: center;
825
+}
826
+
827
+.wl_faces_main ul li img {
828
+    width: 24px;
829
+    height: 24px;
830
+}
831
+
832
+.wlf_icon {
833
+    background: url('http://jk.kuyicloud.com/static/plugins/tencentim/IMSDK_V1.7/img/layer_arrow.png') no-repeat 0 0;
834
+    position: absolute;
835
+    width: 22px;
836
+    height: 9px;
837
+    bottom: -4px;
838
+    _bottom: -11px;
839
+    left: 61px;
840
+}
841
+
842
+.msgedit {
843
+    width: 525px;
844
+    height: 100px;
845
+    border: 1px rgb(181, 178, 178) solid;
846
+    background: #f5f5f5;
847
+    padding: 6px 6px;
848
+    line-height: 1.5;
849
+}
850
+
851
+.sendbar {
852
+    width: 526px;
853
+    height: 30px;
854
+}
855
+
856
+.sendbtn {
857
+    float: right;
858
+    width: 80px;
859
+    margin-right: 10px;
860
+    font: 10px/1.5 "微软雅黑";
861
+}
862
+
863
+.closebtn {
864
+    float: right;
865
+    width: 80px;
866
+    margin-right: 10px;
867
+    font: 10px/1.5 "微软雅黑";
868
+}
869
+
870
+.bottom {
871
+    clear: both;
872
+    height: 3px;
873
+    background: #d7eaf3;
874
+}
875
+
876
+#demo_type_desc {
877
+    color: red;
878
+}
879
+
880
+#myself_type_desc {
881
+    display: none;
882
+    color: red;
883
+}
884
+
885
+#qcloudLink {
886
+    color: blue;
887
+}
888
+
889
+#sdkAppIdDiv {
890
+    display: none;
891
+}
892
+
893
+#accountTypeDiv {
894
+    display: none;
895
+}
896
+
897
+.pic_thumb {
898
+    width: 200px;
899
+    height: 200px;
900
+}
901
+
902
+
903
+
904
+.spinner {
905
+    width: 60px;
906
+    text-align: center;
907
+    position: absolute;
908
+    right: 10px;
909
+    top: 32px;
910
+    text-align: right;
911
+}
912
+
913
+.spinner > div {
914
+  width: 6px;
915
+  height: 6px;
916
+  background-color: #333;
917
+
918
+  border-radius: 100%;
919
+  display: inline-block;
920
+  -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
921
+  animation: sk-bouncedelay 1.4s infinite ease-in-out both;
922
+}
923
+
924
+.spinner .bounce1 {
925
+  -webkit-animation-delay: -0.32s;
926
+  animation-delay: -0.32s;
927
+}
928
+
929
+.spinner .bounce2 {
930
+  -webkit-animation-delay: -0.16s;
931
+  animation-delay: -0.16s;
932
+}
933
+
934
+@-webkit-keyframes sk-bouncedelay {
935
+  0%, 80%, 100% { -webkit-transform: scale(0) }
936
+  40% { -webkit-transform: scale(1.0) }
937
+}
938
+
939
+@keyframes sk-bouncedelay {
940
+  0%, 80%, 100% {
941
+    -webkit-transform: scale(0);
942
+    transform: scale(0);
943
+  } 40% {
944
+    -webkit-transform: scale(1.0);
945
+    transform: scale(1.0);
946
+  }
947
+}
948
+
949
+.headurlClass{
950
+    height: 30px;
951
+    width: 30px;
952
+    border-radius: 50%;
953
+}
954
+
955
+.delChat{
956
+    color: red;
957
+    width: 50px;
958
+    padding: 16px 0;
959
+    float: right;
960
+    margin-right: 5px;
961
+}
962
+figure {
963
+  margin: 0;
964
+}
965
+</style>

+ 265 - 0
src/scrm_pages/marketing_tool/activity_detail.vue ファイルの表示

@@ -0,0 +1,265 @@
1
+<template>
2
+    <div class="main-contain">
3
+        <div class="position">
4
+            <bread-crumb :crumbs="crumbs"></bread-crumb>
5
+        </div>
6
+        <div class="app-container" style="padding-top: 0; background-color: #f6f8f9;">
7
+            <div class="base-info">
8
+                <div class="poster-photo">
9
+                    <img :src="poster_photo" />
10
+                </div>
11
+                <div class="title-panel">
12
+                    <p class="title">
13
+                        <!-- <router-link v-if="activity != null && activity.status == 4" :to="activity_url" target="_blank">{{ title }}</router-link>
14
+                        <router-link v-else :to="activity_url">{{ title }}</router-link> -->
15
+                        <router-link :to="activity_url" target="_blank">{{ title }}</router-link>
16
+                    </p>
17
+                    <p class="date">活动日期:{{ activity_time }}</p>
18
+                </div>
19
+                <div class="action-panel">
20
+                    <el-button type="primary" v-if="show_share_btn" @click="$router.push({ path: '/activity/share', query: { id: activity_id } })">再次分享</el-button>
21
+                    <el-button type="primary" v-if="show_publish_btn" @click="publishActivity" :loading="publishing">发布</el-button>
22
+                </div>
23
+            </div>
24
+            <div class="times-statistics">
25
+                <el-row :gutter="20">
26
+                    <el-col :span="12">
27
+                        <div class="item">
28
+                            <span class="count">{{ read_times }}</span>
29
+                            <p class="desc">展示次数</p>
30
+                        </div>
31
+                    </el-col>
32
+                    <el-col :span="12">
33
+                        <div class="item">
34
+                            <span class="count">{{ join_count }}</span>
35
+                            <p class="desc">参与人数</p>
36
+                        </div>
37
+                    </el-col>
38
+                </el-row>
39
+            </div>
40
+            <div class="signup-header">
41
+                <div class="input">
42
+                    <el-input v-model="signup_keyword" placeholder="搜索报名人" style="width: 330px;"></el-input>
43
+                    <el-button type="primary" icon="el-icon-search" :loading="loading_search" @click="fetchSignupUsers">搜索</el-button>
44
+                </div>
45
+                <div class="all-btn">
46
+                    <el-button type="primary" @click="$router.push({ path: '/activity/signupusers', query: { id: activity_id } })">查看全部</el-button>
47
+                </div>
48
+            </div>
49
+            <div class="signup-table-panel">
50
+                <el-table :data="signup_users" empty-text="暂无人报名">
51
+                    <el-table-column label="报名号" align="center" prop="id"></el-table-column>
52
+                    <el-table-column label="手机号" align="center" prop="mobile"></el-table-column>
53
+                    <el-table-column label="客户姓名" align="center" prop="real_name"></el-table-column>
54
+                    <el-table-column label="报名时间" align="center">
55
+                        <template slot-scope="scope">
56
+                            <span>{{ parseTime(scope.row.ctime, "{y}-{m}-{d} {h}:{i}") }}</span>
57
+                        </template>
58
+                    </el-table-column>
59
+                </el-table>
60
+            </div>
61
+        </div>
62
+    </div>
63
+</template>
64
+
65
+<script>
66
+import BreadCrumb from "@/scrm_pages/components/bread-crumb"
67
+import { fetchActivityDetailViewData, fetchActivitySignupUsers, publishActivity } from "@/api/activity/activity"
68
+import { parseTime } from "@/utils"
69
+
70
+export default {
71
+    name: "ActivityDetail",
72
+    components: {
73
+        BreadCrumb,
74
+    },
75
+    data() {
76
+        return {
77
+            crumbs: [
78
+                { path: false, name: "营销工具" },
79
+                { path: false, name: "活动详情" },
80
+            ],
81
+
82
+            activity_id: 0,
83
+            activity: null,
84
+
85
+            signup_keyword: "",
86
+            signup_users: [],
87
+
88
+            loading_search: false,
89
+            publishing: false,
90
+        }
91
+    },
92
+    computed: {
93
+        title: function() {
94
+            return this.activity == null ? "" : this.activity.title
95
+        },
96
+        poster_photo: function() {
97
+            return this.activity == null ? "/" : this.activity.poster_photo
98
+        },
99
+        activity_url: function() {
100
+            if (this.activity != null) {
101
+                return "/activity/preview?id=" + this.activity_id
102
+            }
103
+            return ""
104
+        },
105
+        activity_time: function() {
106
+            return this.activity == null ? "" : parseTime(this.activity.start_time, "{y}-{m}-{d} {h}:{i}")
107
+        },
108
+        show_share_btn: function() {
109
+            return this.activity == null ? false : (this.activity.status == 1)
110
+        },
111
+        show_publish_btn: function() {
112
+            return this.activity == null ? false : (this.activity.status == 4)
113
+        },
114
+        read_times: function() {
115
+            return this.activity == null ? 0 : this.activity.read_num
116
+        },
117
+        join_count: function() {
118
+            return this.activity == null ? 0 : this.activity.join_num
119
+        }
120
+    },
121
+    mounted() {
122
+        this.activity_id = this.$route.query.id
123
+
124
+        fetchActivityDetailViewData(this.activity_id).then(rs => {
125
+            var resp = rs.data
126
+            if (resp.state == 1) {
127
+                this.activity = resp.data.activity
128
+                this.signup_users = resp.data.users
129
+            } else {
130
+                this.$message.error(resp.msg)
131
+            }
132
+
133
+        }).catch(err => {
134
+            this.$message.error(err)
135
+        })
136
+    },
137
+    methods: {
138
+        parseTime,
139
+        fetchSignupUsers: function() {
140
+            this.loading_search = true
141
+            fetchActivitySignupUsers(this.activity_id, this.signup_keyword, 1).then(rs => {
142
+                this.loading_search = false
143
+                var resp = rs.data
144
+                if (resp.state == 1) {
145
+                    this.signup_users = resp.data.users
146
+                } else {
147
+                    this.$message.error(resp.msg)
148
+                }
149
+            }).catch(err => {
150
+                this.loading_search = false
151
+                this.$message.error(err)
152
+            })
153
+        },
154
+        publishActivity: function() {
155
+            this.publishing = true
156
+            publishActivity(this.activity_id).then(rs => {
157
+                this.publishing = false
158
+                var resp = rs.data
159
+                if (resp.state == 1) {
160
+                    this.activity.status = 1
161
+                } else {
162
+                    this.$message.error(resp.msg)
163
+                } 
164
+
165
+            }).catch(rs => {
166
+                this.publishing = false
167
+                this.$message.error(err)
168
+            })
169
+        }
170
+    },
171
+}
172
+</script>
173
+
174
+<style lang="scss" scoped>
175
+.base-info {
176
+    padding: 20px 25px;
177
+    display: flex;
178
+    justify-content: flex-end;
179
+    flex-wrap: nowrap;
180
+    align-items: center;
181
+    background-color: white;
182
+    box-shadow: 0 0 1px #dee2e5;
183
+
184
+    .poster-photo {
185
+        width: 120px;
186
+        height: 96px;
187
+        display: flex;
188
+        justify-content: center;
189
+        margin-right: 22px;
190
+
191
+        img {
192
+            width: 100%;
193
+            height: auto;
194
+            border-radius: 4px;
195
+            object-fit: cover;
196
+            object-position: center;
197
+        }
198
+    }
199
+    .title-panel {
200
+        flex: 3;
201
+        padding-right: 20px;
202
+
203
+        .title {
204
+            font-size: 18px;
205
+            color: #485b6d;
206
+            font-weight: 700;
207
+            word-break: break-all;
208
+            overflow: hidden;
209
+            text-overflow: ellipsis;
210
+            display: -webkit-box;
211
+            -webkit-line-clamp: 2;
212
+            -webkit-box-orient: vertical;
213
+            height: 70px;
214
+            line-height: 34px;
215
+        }
216
+        .date {
217
+            color: #7b8a97;
218
+            line-height: 20px;
219
+            font-size: 14px;
220
+        }
221
+    }
222
+    .action-panel {
223
+        flex: 1;
224
+        text-align: right;
225
+    }
226
+}
227
+.times-statistics {
228
+    margin-top: 20px;
229
+
230
+    .item {
231
+        padding: 40px 0 30px 0;
232
+        box-shadow: 0 0 1px #dee2e5;
233
+        background-color: white;
234
+        text-align: center;
235
+
236
+        .count {
237
+            font-size: 36px;
238
+            color: #58a2ec;
239
+        }
240
+        .desc {
241
+            margin-top: 5px;
242
+            font-size: 14px;
243
+            color: #485b6d;
244
+        }
245
+    }
246
+}
247
+.signup-header {
248
+    margin-top: 20px;
249
+    display: flex;
250
+    justify-content: space-between;
251
+
252
+    .input {
253
+        width: 500px;
254
+        display: block;
255
+    }
256
+    .all-btn {
257
+        display: block;
258
+    }
259
+}
260
+.signup-table-panel {
261
+    margin-top: 10px;
262
+}
263
+</style>
264
+
265
+

+ 23 - 4
src/scrm_pages/marketing_tool/activity_list.vue ファイルの表示

@@ -34,8 +34,10 @@
34 34
       <div>
35 35
         <template v-for="(activity, index) in activities">
36 36
           <published-cell v-if="activity.status == 1 || activity.status == 4" :key="index" :activity="activity"></published-cell>
37
-          <unapproved-cell v-else-if="activity.status == 3" :key="index" :activity="activity"></unapproved-cell>
38
-          <drafts-cell v-else-if="activity.status == 2" :key="index" :activity="activity"></drafts-cell>
37
+
38
+          <unapproved-cell v-else-if="activity.status == 3" :key="index" :activity="activity" @delete="deleteActivity(activity.id, index)"></unapproved-cell>
39
+
40
+          <drafts-cell v-else-if="activity.status == 2" :key="index" :activity="activity" @delete="deleteActivity(activity.id, index)"></drafts-cell>
39 41
         </template>
40 42
       </div>
41 43
       <div class="cell clearfix" style="padding-top: 15px;">
@@ -46,11 +48,11 @@
46 48
 </template>
47 49
 
48 50
 <script>
49
-import BreadCrumb from "@/scrm_pages/components/bread-crumb";
51
+import BreadCrumb from "@/scrm_pages/components/bread-crumb"
50 52
 import PublishedCell from "@/scrm_pages/marketing_tool/components/published_cell"
51 53
 import UnapprovedCell from "@/scrm_pages/marketing_tool/components/unapproved_cell"
52 54
 import DraftsCell from "@/scrm_pages/marketing_tool/components/drafts_cell"
53
-import { fetchActivities } from "@/api/activity/activity"
55
+import { fetchActivities, deleteActivity } from "@/api/activity/activity"
54 56
 
55 57
 export default {
56 58
   name: "ActivityList",
@@ -102,6 +104,23 @@ export default {
102 104
         this.$message.error(err)
103 105
       })
104 106
     },
107
+
108
+    deleteActivity(id, index) {
109
+      this.loading_activities = true
110
+      deleteActivity(id).then(rs => {
111
+        this.loading_activities = false
112
+        var resp = rs.data
113
+        if (resp.state == 1) {
114
+          this.activities.splice(index, 1)
115
+        } else {
116
+          this.$message.error(resp.msg)
117
+        }
118
+      }).catch(err => {
119
+        this.loading_activities = false
120
+        this.$message.error(err)
121
+        return err
122
+      })
123
+    }
105 124
   },
106 125
 };
107 126
 </script>

+ 325 - 0
src/scrm_pages/marketing_tool/activity_preview.vue ファイルの表示

@@ -0,0 +1,325 @@
1
+<template>
2
+<div style="background-color: #f6f8f9;">
3
+    <div class="main">
4
+        <div class="border title-panel">
5
+            <img :src="activity.poster_photo"/>
6
+            <div class="text">
7
+                <p class="title">{{ activity.title }}</p>
8
+                <p class="subtitle">{{ activity.subtitle }}</p>
9
+            </div>
10
+        </div>
11
+        <div class="org-info border">
12
+            <div class="logo">
13
+                <img :src="org.logo" />
14
+            </div>
15
+            <div class="info">
16
+                <p class="name">{{ org.name }}</p>
17
+                <p class="address">{{ activity.address }}</p>
18
+            </div>
19
+            <div class="arrow">
20
+                <img src="@/assets/img/sa_52.png" />
21
+            </div>
22
+        </div>
23
+        <div class="simple-cell border">
24
+            <div class="icon">
25
+                <img src="@/assets/img/sa_21.png" />
26
+            </div>
27
+            <div class="text">
28
+                <p>{{ parseTime(activity.start_time, "{y}-{m}-{d} {h}:{i}") }}</p>
29
+            </div>
30
+            <div class="arrow-panel">
31
+                <img src="@/assets/img/sa_52.png" />
32
+            </div>
33
+        </div>
34
+        <div class="simple-cell border" v-if="activity.phone_number.length > 0">
35
+            <div class="icon">
36
+                <img src="@/assets/img/sa_24.png" />
37
+            </div>
38
+            <div class="text">
39
+                <p>{{ activity.phone_number }}</p>
40
+            </div>
41
+            <div class="arrow-panel">
42
+                <img src="@/assets/img/sa_52.png" />
43
+            </div>
44
+        </div>
45
+        <div class="simple-cell border" v-if="activity.limit_num > 0">
46
+            <div class="title">
47
+                <p>活动名额</p>
48
+            </div>
49
+            <div class="detail">
50
+                <p>{{ activity.limit_num + "人" }}</p>
51
+            </div>
52
+        </div>
53
+
54
+        <div class="large-text-cell border" v-if="sign_up_notice.length > 0">
55
+            <div class="title">
56
+                <img src="@/assets/img/sa_25.png" />
57
+                <span>报名须知</span>
58
+            </div>
59
+            <p class="content" v-html="sign_up_notice">
60
+            </p>
61
+        </div>
62
+
63
+        <div class="large-text-cell border" v-if="activity_paragraph.title.length > 0">
64
+            <div class="title">
65
+                <img src="@/assets/img/sa_26.png" />
66
+                <span>{{ activity_paragraph.title }}</span>
67
+            </div>
68
+            <p class="content" v-html="activity_paragraph.content">
69
+            </p>
70
+        </div>
71
+
72
+        <div class="signup-fake-btn">
73
+            立即报名
74
+        </div>
75
+    </div>
76
+</div> 
77
+</template>
78
+
79
+<script>
80
+import { fetchActivity } from "@/api/activity/activity"
81
+import { parseTime } from "@/utils"
82
+
83
+export default {
84
+    name: "ActivityPreview",
85
+    data() {
86
+        return {
87
+            activity_id: 0,
88
+
89
+            activity: {
90
+                id: 0,
91
+                poster_photo: "",
92
+                title: "",
93
+                subtitle: "",
94
+                address: "",
95
+                limit_num: 0,
96
+                sign_up_deadline: 0,
97
+                start_time: 0,
98
+                phone_number: "",
99
+                sign_up_notice: "",
100
+            },
101
+            activity_paragraph: {
102
+                title: "",
103
+                content: "",
104
+            },
105
+            org: {
106
+                name: "",
107
+                logo: "",
108
+            }
109
+        }
110
+    },
111
+    computed: {
112
+        sign_up_notice: function() {
113
+            return this.activity.sign_up_notice.replace(/\n/g, "<br/>")
114
+        }
115
+    },
116
+    mounted() {
117
+        this.activity_id = this.$route.query.id
118
+
119
+        fetchActivity(this.activity_id).then(rs => {
120
+            var resp = rs.data
121
+            if (resp.state == 1) {
122
+                // console.log(resp.data)
123
+                var activity = resp.data.activity
124
+                this.activity.id = activity.id
125
+                this.activity.poster_photo = activity.poster_photo
126
+                this.activity.title = activity.title
127
+                this.activity.subtitle = activity.subtitle
128
+                this.activity.address = activity.address
129
+                this.activity.limit_num = activity.limit_num
130
+                this.activity.sign_up_deadline = activity.sign_up_deadline * 1000
131
+                this.activity.start_time = activity.start_time * 1000
132
+                this.activity.phone_number = activity.phone_number
133
+                this.activity.sign_up_notice = activity.sign_up_notice
134
+
135
+                var paragraph = resp.data.paragraph
136
+                this.activity_paragraph.title = paragraph.title
137
+                this.activity_paragraph.content = paragraph.content
138
+
139
+                this.org.name = resp.data.org.name
140
+                this.org.logo = resp.data.org.logo
141
+
142
+            } else {
143
+                this.$message.error(resp.msg)
144
+            }
145
+
146
+        }).catch(err => {
147
+            this.$message.error(err)
148
+        })
149
+    },
150
+    methods: {
151
+        parseTime,
152
+    }
153
+}
154
+</script>
155
+
156
+<style lang="scss" scoped>
157
+.main {
158
+    width: 750px;
159
+    margin: 0 auto;
160
+    padding: 14px 30px 0 30px;
161
+
162
+    .title-panel {
163
+        background-color: white;
164
+
165
+        img {
166
+            width: 100%;
167
+            height: auto;
168
+        }
169
+        .text {
170
+            padding: 12px 15px 16px 20px;
171
+
172
+            .title {
173
+                font-size: 18px;
174
+                color: #485b6d;
175
+                font-weight: bold;
176
+                line-height: 32px;
177
+            }
178
+            .subtitle {
179
+                margin-top: 4px;
180
+                color: #a6a6a6;
181
+                font-size: 14px;
182
+            }
183
+        }
184
+    }
185
+
186
+    .org-info {
187
+        padding: 26px 20px;
188
+        position: relative;
189
+        display: flex;
190
+        -webkit-box-align: center;
191
+        align-items: center;
192
+        margin-top: 15px;
193
+        background-color: white;
194
+
195
+        .logo {
196
+            img {
197
+                width: 40px;
198
+                height: 40px;
199
+                border-radius: 20px;
200
+                object-fit: cover;
201
+                object-position: center;
202
+            }
203
+        }
204
+
205
+        .info {
206
+            flex: 1;
207
+            padding-left: 23px;
208
+            color: #485b6d;
209
+
210
+            .name {
211
+                font-size: 16px;
212
+                line-height: 22px;
213
+            }
214
+            .address {
215
+                font-size: 14px;
216
+                line-height: 20px;
217
+            }
218
+        }
219
+        
220
+        .arrow {
221
+            width: 20px;
222
+            position: relative;
223
+            img {
224
+                width: 8px;
225
+                float: right;
226
+            }
227
+        }
228
+    }
229
+
230
+    .simple-cell {
231
+        background-color: white;
232
+        padding: 20px 20px;
233
+        margin-top: 15px;
234
+        position: relative;
235
+        display: flex;
236
+        -webkit-box-align: center;
237
+        align-items: center;
238
+
239
+        .icon {
240
+            img {
241
+                width: 20px;
242
+                height: auto;//20px;
243
+                vertical-align: middle;
244
+            }
245
+        }
246
+        .text {
247
+            flex: 1;
248
+            padding-left: 17px;
249
+            color: #485b6d;
250
+            line-height: 20px;
251
+        }
252
+        .arrow-panel {
253
+            width: 20px;
254
+            position: relative;
255
+
256
+            img {
257
+                width: 8px;
258
+                float: right;
259
+                vertical-align: middle;
260
+            }
261
+        }
262
+
263
+        .title {
264
+            p {
265
+                color: #485b6d;
266
+            }
267
+        }
268
+        .detail {
269
+            flex: 1;
270
+            padding-left: 23px;
271
+            color: #485b6d;
272
+
273
+            p {
274
+                color: #485b6d;
275
+                float: right;
276
+                text-align: right;
277
+            }
278
+        }
279
+    }
280
+
281
+    .large-text-cell {
282
+        background-color: white;
283
+        padding: 20px 20px;
284
+        position: relative;
285
+        -webkit-box-align: center;
286
+        align-items: center;
287
+        margin-top: 15px;
288
+
289
+        .title {
290
+            color: #485b6d;
291
+            line-height: 18px;
292
+            height: 18px;
293
+
294
+            img {
295
+                margin-right: 11px;
296
+                float: left;
297
+            }
298
+        }
299
+        .content {
300
+            color: #a8b3ba;
301
+            margin: 10px 0 0 0;
302
+            font-size: 14px;
303
+            line-height: 20px;
304
+        }
305
+    }
306
+
307
+    .signup-fake-btn {
308
+        background: #58a1ed;
309
+        color: #fff;
310
+        height: 50px;
311
+        line-height: 50px;
312
+        text-align: center;
313
+        width: 100%;
314
+        margin-top: 100px;
315
+        font-size: 16px;
316
+    }
317
+}
318
+</style>
319
+
320
+<style scoped>
321
+.border {
322
+    border: solid 1px #dee2e5;
323
+    border-radius: 4px;
324
+}
325
+</style>

+ 227 - 0
src/scrm_pages/marketing_tool/activity_share.vue ファイルの表示

@@ -0,0 +1,227 @@
1
+<template>
2
+    <div class="main-contain">
3
+        <div class="position">
4
+            <bread-crumb :crumbs="crumbs"></bread-crumb>
5
+        </div>
6
+        <div class="app-container" style="padding: 0 6px 20px; background-color: #f6f8f9;">
7
+            <div class="wx-share-panel">
8
+                <div class="text-panel">
9
+                    <p class="title">微信分享</p>
10
+                    <p class="desc">以微信方式推送给客户,该方式可以监测活动的展现及参与次数</p>
11
+                </div>
12
+                <div class="qrcode-panel">
13
+                    <div class="qrcode">
14
+                        <img :src="qr_img" :style="{ opacity: qr_img.length > 0 ? 1 : 0 }" />
15
+                    </div>
16
+                    <div class="btn">
17
+                        <el-button type="primary" @click="previewAction">新窗口预览</el-button>
18
+                    </div>
19
+                </div>
20
+            </div>
21
+            <div class="sms-share-panel">
22
+                <div class="text-panel">
23
+                    <p class="title">短信分享</p>
24
+                    <p class="desc">以短信方式推送给客户</p>
25
+                </div>
26
+                <div class="btn-panel">
27
+                    <el-button type="primary">短信推送</el-button>
28
+                </div>
29
+            </div>
30
+            <div class="link-share-panel">
31
+                <div>
32
+                    <p class="title">网页链接</p>
33
+                    <p class="desc">可以直接分享以下链接到相应媒体(邮件、QQ、微博等),或者嵌入到微信公众号菜单</p>
34
+                </div>
35
+                <div class="input-line">
36
+                    <div class="input">
37
+                        <el-input readonly v-model="short_url"></el-input>
38
+                    </div>
39
+                    <el-button type="primary" @click="copyAction">复制链接</el-button>
40
+                </div>
41
+            </div>
42
+        </div>
43
+    </div>
44
+</template>
45
+
46
+<script>
47
+import BreadCrumb from "@/scrm_pages/components/bread-crumb"
48
+import QRCode from "qrcode"
49
+import { getActivityShareInfo } from "@/api/activity/activity"
50
+
51
+export default {
52
+    name: "ActivityShare",
53
+    components: {
54
+        BreadCrumb,
55
+    },
56
+    data() {
57
+        return {
58
+            crumbs: [
59
+                { path: false, name: "活动详情" },
60
+                { path: false, name: "活动分享" },
61
+            ],
62
+
63
+            activity_id: 0,
64
+            short_url: "",
65
+            qr_img: "",
66
+        }
67
+    },
68
+    mounted() {
69
+        this.activity_id = this.$route.query.id
70
+
71
+        getActivityShareInfo(this.activity_id).then(rs => {
72
+            var resp = rs.data
73
+            if (resp.state == 1) {
74
+                this.short_url = resp.data.url
75
+
76
+                var opts = {
77
+                    errorCorrectionLevel: "H",
78
+                    type: "image/png"
79
+                };
80
+                var that = this;
81
+                QRCode.toDataURL(this.short_url, opts, function(err, qr_url) {
82
+                    if (err) {
83
+                        console.log(err);
84
+                    } else {
85
+                        that.qr_img = qr_url;
86
+                    }
87
+                });
88
+
89
+            } else {
90
+                this.$message.error(resp.msg)
91
+            }
92
+        }).catch(err => {
93
+            this.$message.error(err)
94
+        })
95
+
96
+    },
97
+    methods: {
98
+        previewAction: function () {
99
+            // var new_page = this.$router.resolve({ 
100
+            //     path: '/activity/preview',
101
+            //     query: {
102
+            //         id: this.activity_id,
103
+            //     }   
104
+            // })
105
+            // window.open(new_page.href, '_blank');
106
+            window.open(this.short_url, "_blank")
107
+        },
108
+        copyAction: function() {
109
+            var input = document.createElement("input");
110
+            input.value = this.short_url;
111
+            document.body.appendChild(input);
112
+            input.select();
113
+            document.execCommand("Copy");
114
+            document.body.removeChild(input);
115
+
116
+            this.$message.success("已复制链接")
117
+        }
118
+    },
119
+}
120
+</script>
121
+
122
+<style lang="scss" scoped>
123
+.wx-share-panel {
124
+    box-shadow: 0 0 1px #dee2e5;
125
+    padding: 25px 35px;
126
+    display: flex;
127
+    background-color: white;
128
+
129
+    .text-panel {
130
+        flex: 1;
131
+
132
+        .title {
133
+            font-size: 16px;
134
+            color: #485b6d;
135
+            font-weight: bold;
136
+            height: 40px;
137
+            display: -webkit-box;
138
+            -webkit-box-orient: vertical;
139
+            -webkit-line-clamp: 2;
140
+            overflow: hidden;
141
+        }
142
+        .desc {
143
+            color: #7b8a97;
144
+            font-size: 14px;
145
+        }
146
+    }
147
+    .qrcode-panel {
148
+        text-align: right;
149
+
150
+        .qrcode {
151
+            text-align: center;
152
+
153
+            img {
154
+                width: 120px;
155
+                height: 120px;
156
+            }
157
+        }
158
+
159
+        .btn {
160
+            text-align: center;
161
+        }
162
+    }
163
+}
164
+
165
+.sms-share-panel {
166
+    box-shadow: 0 0 1px #dee2e5;
167
+    padding: 25px 35px;
168
+    display: flex;
169
+    margin-top: 20px;
170
+    background-color: white;
171
+
172
+    .text-panel {
173
+        flex: 1;
174
+
175
+        .title {
176
+            font-size: 16px;
177
+            color: #485b6d;
178
+            font-weight: bold;
179
+            height: 40px;
180
+            display: -webkit-box;
181
+            -webkit-box-orient: vertical;
182
+            -webkit-line-clamp: 2;
183
+            overflow: hidden;
184
+        }
185
+        .desc {
186
+            color: #7b8a97;
187
+            font-size: 14px;
188
+        }
189
+    }
190
+    .btn-panel {
191
+        text-align: right;
192
+        padding-right: 4px;
193
+    }
194
+}
195
+
196
+.link-share-panel {
197
+    box-shadow: 0 0 1px #dee2e5;
198
+    padding: 25px 35px;
199
+    // display: flex;
200
+    margin-top: 20px;
201
+    background-color: white;
202
+
203
+    .title {
204
+        font-size: 16px;
205
+        color: #485b6d;
206
+        font-weight: bold;
207
+        height: 40px;
208
+        display: -webkit-box;
209
+        -webkit-box-orient: vertical;
210
+        -webkit-line-clamp: 2;
211
+        overflow: hidden;
212
+    }
213
+    .desc {
214
+        color: #7b8a97;
215
+        font-size: 14px;
216
+    }
217
+    .input-line {
218
+        margin-top: 20px;
219
+
220
+        .input {
221
+            display: inline-block;
222
+            width: 400px;
223
+        }
224
+    }
225
+}
226
+</style>
227
+

+ 107 - 0
src/scrm_pages/marketing_tool/activity_signup_users.vue ファイルの表示

@@ -0,0 +1,107 @@
1
+<template>
2
+    <div class="main-contain">
3
+        <div class="position">
4
+            <bread-crumb :crumbs="crumbs"></bread-crumb>
5
+        </div>
6
+        <div class="app-container" style="padding-top: 0; background-color: #f6f8f9;">
7
+            <div style="display: flex;">
8
+                <div style="flex: 1;">
9
+                    <router-link to="/activity/list">
10
+                        <el-button type="primary">返回列表</el-button>
11
+                    </router-link>
12
+                </div>
13
+                <el-button type="primary" @click="printAction">导出</el-button>
14
+            </div>
15
+            <div style="margin-top: 10px;" id="table-panel">
16
+                <el-table id="table" border :data="signup_users" empty-text="暂无人报名">
17
+                    <el-table-column label="报名号" align="center" prop="id"></el-table-column>
18
+                    <el-table-column label="手机号" align="center" prop="mobile"></el-table-column>
19
+                    <el-table-column label="客户姓名" align="center" prop="real_name"></el-table-column>
20
+                    <el-table-column label="报名时间" align="center">
21
+                        <template slot-scope="scope">
22
+                            <span>{{ parseTime(scope.row.ctime, "{y}-{m}-{d} {h}:{i}") }}</span>
23
+                        </template>
24
+                    </el-table-column>
25
+                </el-table>
26
+            </div>
27
+            <div style="margin-top: 10px;">
28
+                <el-pagination :total="total" :current-page.sync="current_page" :page-size="10" layout="total, prev, pager, next" @current-change="getActivities()"></el-pagination>
29
+            </div>
30
+            <div id="print-table" style="width:960px; display: none;">
31
+                <el-table border :data="signup_users" empty-text="暂无人报名">
32
+                    <el-table-column label="报名号" align="center" prop="id"></el-table-column>
33
+                    <el-table-column label="手机号" align="center" prop="mobile"></el-table-column>
34
+                    <el-table-column label="客户姓名" align="center" prop="real_name"></el-table-column>
35
+                    <el-table-column label="报名时间" align="center">
36
+                        <template slot-scope="scope">
37
+                            <span>{{ parseTime(scope.row.ctime, "{y}-{m}-{d} {h}:{i}") }}</span>
38
+                        </template>
39
+                    </el-table-column>
40
+                </el-table>
41
+            </div>
42
+        </div>
43
+    </div>
44
+</template>
45
+
46
+<script>
47
+import BreadCrumb from "@/scrm_pages/components/bread-crumb"
48
+import { fetchActivitySignupUsers } from "@/api/activity/activity"
49
+import { parseTime } from "@/utils"
50
+import printJS from "print-js"
51
+
52
+export default {
53
+    name: "ActivitySignupUsers",
54
+    components: {
55
+        BreadCrumb,
56
+    },
57
+    data() {
58
+        return {
59
+            crumbs: [
60
+                { path: false, name: "活动详情" },
61
+                { path: false, name: "报名列表" },
62
+            ],
63
+
64
+            activity_id: 0,
65
+
66
+            signup_users: [],
67
+            loading_search: false,
68
+            total: 0,
69
+            current_page: 1,
70
+        }
71
+    },
72
+    mounted() {
73
+        this.activity_id = this.$route.query.id
74
+
75
+        this.fetchSignupUsers()
76
+    },
77
+    methods: {
78
+        parseTime,
79
+        fetchSignupUsers: function() {
80
+            this.loading_search = true
81
+            fetchActivitySignupUsers(this.activity_id, "", this.current_page).then(rs => {
82
+                this.loading_search = false
83
+                var resp = rs.data
84
+                if (resp.state == 1) {
85
+                    this.signup_users = resp.data.users
86
+                    this.total = resp.data.total
87
+                } else {
88
+                    this.$message.error(resp.msg)
89
+                }
90
+            }).catch(err => {
91
+                this.loading_search = false
92
+                this.$message.error(err)
93
+            })
94
+        },
95
+        printAction: function() {
96
+            printJS({
97
+                printable: 'table',
98
+                type: "html",
99
+                scanStyles: false,
100
+                css: ['https://unpkg.com/element-ui/lib/theme-chalk/index.css'],
101
+                // maxWidth: 960,
102
+            })
103
+        },
104
+    },
105
+}
106
+</script>
107
+

+ 14 - 2
src/scrm_pages/marketing_tool/components/drafts_cell.vue ファイルの表示

@@ -7,11 +7,13 @@
7 7
         </div>
8 8
         <div class="activity-info-panel">
9 9
             <h3 class="title">
10
-                <a href="/">{{ activity.title }}</a>
10
+                <router-link :to="activityUrl">
11
+                    <a>{{ activity.title }}</a>
12
+                </router-link>
11 13
             </h3>
12 14
             <div class="operation">
13 15
                 <el-button type="primary" size="small" icon="el-icon-edit-outline" @click="$router.push({ path: '/activity/modify', query: {id: activity.id} })">编辑</el-button>
14
-                <el-button type="danger" size="small" icon="el-icon-delete">删除</el-button>
16
+                <el-button type="danger" size="small" icon="el-icon-delete" @click="deleteActivity">删除</el-button>
15 17
             </div>
16 18
         </div>
17 19
     </div>
@@ -32,6 +34,16 @@ export default {
32 34
             
33 35
         }
34 36
     },
37
+    computed: {
38
+        activityUrl: function() {
39
+            return "/activity?id=" + this.activity.id
40
+        }
41
+    },
42
+    methods: {
43
+        deleteActivity() {
44
+            this.$emit("delete")
45
+        }
46
+    }
35 47
 }
36 48
 </script>
37 49
 

+ 21 - 5
src/scrm_pages/marketing_tool/components/edit_activity_edit_form.vue ファイルの表示

@@ -95,7 +95,7 @@
95 95
             <div class="submit-button-panel">
96 96
                 <el-button style="padding: 10px 30px;" type="primary" @click="publishAction" :loading="publishing_activity" :disabled="saving_activity || saving_before_preview_activity">发 布</el-button>
97 97
                 <el-button style="color: #409eff; border-color: #409eff; padding: 10px 30px;" @click="saveAction" :loading="saving_activity" :disabled="publishing_activity || saving_before_preview_activity">保存草稿</el-button>
98
-                <el-button style="color: #409eff; border-color: #409eff; padding: 10px 30px;" :loading="saving_before_preview_activity" :disabled="publishing_activity || saving_activity">预 览</el-button>
98
+                <el-button style="color: #409eff; border-color: #409eff; padding: 10px 30px;" @click="previewAction" :loading="saving_before_preview_activity" :disabled="publishing_activity || saving_activity">预 览</el-button>
99 99
             </div>
100 100
         </div>
101 101
     </div>
@@ -222,18 +222,27 @@ export default {
222 222
 
223 223
         saveAction: function() {
224 224
             this.saving_activity = true
225
-            this.submitActivity(false)
225
+            this.submitActivity(false, function() {
226
+                // 弹框 => 再发一条/前往列表
227
+            })
226 228
         },
227 229
         publishAction: function() {
228 230
             this.publishing_activity = true
229 231
             this.submitActivity(true, function() {
230
-                // 前往活动详情页
232
+                this.$router.push({ path: "/activity", query: { id: this.activity.id } })
231 233
             })
232 234
         },
233 235
         previewAction: function() {
234 236
             this.saving_before_preview_activity = true
237
+            var t = this
235 238
             this.submitActivity(false, function() {
236
-                // 前往活动预览页
239
+                var new_page = t.$router.resolve({ 
240
+                    path: '/activity/preview',
241
+                    query: {
242
+                        id: t.activity.id,
243
+                    }   
244
+                })
245
+                window.open(new_page.href, '_blank');
237 246
             })
238 247
         },
239 248
         submitActivity: function(is_publish, successCallBack) {
@@ -272,6 +281,7 @@ export default {
272 281
                     this.saving_before_preview_activity = false
273 282
 
274 283
                 }).catch(err => {
284
+                    console.log('------  ' + err)
275 285
                     this.$message.error(err)
276 286
                     this.saving_activity = false
277 287
                     this.publishing_activity = false
@@ -279,27 +289,33 @@ export default {
279 289
                 })
280 290
 
281 291
             }).catch(err => {
292
+                console.log('asdada  ' + err)
282 293
                 this.$message.error(err)
283 294
                 this.saving_activity = false
284 295
                 this.publishing_activity = false
285 296
                 this.saving_before_preview_activity = false
286 297
             })
287
-            
288 298
         },
289 299
         validActivityInfo: function() {
290 300
             return new Promise((resolve, reject) => {
291 301
                 if (this.activity.poster_photo.length == 0) {
292 302
                     reject("海报不能为空")
303
+                    return
293 304
                 } else if (this.activity.title.length == 0) {
294 305
                     reject("标题不能为空")
306
+                    return
295 307
                 } else if (this.activity.subtitle.length == 0) {
296 308
                     reject("副标题不能为空")
309
+                    return
297 310
                 } else if (this.activity.address.length == 0) {
298 311
                     reject("活动地址不能为空")
312
+                    return
299 313
                 } else if (this.activity.sign_up_deadline == 0) {
300 314
                     reject("活动报名时间不能为空")
315
+                    return
301 316
                 } else if (this.activity.start == 0) {
302 317
                     reject("活动时间不能为空")
318
+                    return
303 319
                 } else {
304 320
                     if (this.activity.phone_number.length > 0) {
305 321
                         if (/^1\d{10}$/.test(this.activity.phone_number) == false && /^(0\d{2,3}-?\d{7,8}$)/.test(this.activity.phone_number) == false) {

+ 7 - 2
src/scrm_pages/marketing_tool/components/published_cell.vue ファイルの表示

@@ -7,7 +7,9 @@
7 7
         </div>
8 8
         <div class="activity-info-panel">
9 9
             <h3 class="title">
10
-                <a href="">{{ activity.title }}</a>
10
+                <router-link :to="activityUrl">
11
+                    <a>{{ activity.title }}</a>
12
+                </router-link>
11 13
             </h3>
12 14
             <div class="statistics">
13 15
                 阅读:{{ activity.read_num }} 丨 评论:{{ activity.comment_num }} 丨 点赞:{{ activity.star_num }}
@@ -52,6 +54,9 @@ export default {
52 54
                 return "已发布"
53 55
             }
54 56
         },
57
+        activityUrl: function() {
58
+            return "/activity?id=" + this.activity.id
59
+        },
55 60
         progress_percent: function() {
56 61
             if (this.activity.limit_num > 0) {
57 62
                 return (this.activity.join_num / this.activity.limit_num) * 100
@@ -71,7 +76,7 @@ export default {
71 76
             }
72 77
         },
73 78
         start_time: function() {
74
-            return parseTime(this.activity.start_time, "{y}-{m}-{d}")
79
+            return parseTime(this.activity.start_time, "{y}-{m}-{d} {h}-{i}")
75 80
         },
76 81
     },
77 82
 }

+ 7 - 2
src/scrm_pages/marketing_tool/components/unapproved_cell.vue ファイルの表示

@@ -14,7 +14,7 @@
14 14
             </div>
15 15
             <div class="operation">
16 16
                 <el-button type="primary" size="small" icon="el-icon-edit-outline" @click="$router.push({ path: '/activity/modify', query: {id: activity.id} })">编辑</el-button>
17
-                <el-button type="danger" size="small" icon="el-icon-delete">删除</el-button>
17
+                <el-button type="danger" size="small" icon="el-icon-delete" @click="deleteActivity">删除</el-button>
18 18
             </div>
19 19
         </div>
20 20
         <div class="activity-time-panel">
@@ -42,9 +42,14 @@ export default {
42 42
     },
43 43
     computed: {
44 44
         start_time: function() {
45
-            return parseTime(this.activity.start_time, "{y}-{m}-{d}")
45
+            return parseTime(this.activity.start_time, "{y}-{m}-{d} {h}:{i}")
46 46
         },
47 47
     },
48
+    methods: {
49
+        deleteActivity() {
50
+            this.$emit("delete")
51
+        }
52
+    }
48 53
 }
49 54
 </script>
50 55
 

+ 286 - 0
src/scrm_pages/site/components/add-contact.vue ファイルの表示

@@ -0,0 +1,286 @@
1
+<template>
2
+    <div>
3
+         <div class="feature ">
4
+            <ul >
5
+                <li @click="slideshow = true">
6
+                    <span>
7
+                        <img :src="new1" alt="">
8
+                        <p>轮播图</p>  
9
+                    </span>
10
+                </li>
11
+                <li @click="address = true">
12
+                    <span>
13
+                        <img :src="new1" alt="">
14
+                        <p>医院地址</p>  
15
+                    </span>
16
+                </li>
17
+                <li @click="contact = true">
18
+                    <span>
19
+                        <img :src="new1" alt="">
20
+                        <p>联系方式</p>  
21
+                    </span>
22
+                </li>
23
+                <li @click="time = true">
24
+                    <span>
25
+                        <img :src="new1" alt="">
26
+                        <p>工作时间</p>  
27
+                    </span>
28
+                </li>
29
+                <li @click="type = true">
30
+                    <span>
31
+                        <img :src="new1" alt="">
32
+                        <p>乘车方式</p>  
33
+                    </span>
34
+                </li>
35
+            </ul>
36
+         </div>
37
+<!-- 轮播图 -->
38
+<el-dialog
39
+    title="新增轮播图"
40
+    :visible.sync="slideshow"
41
+    width="550px"
42
+    :before-close="handleClose">
43
+    <el-form ref="form" :model="form" label-width="80px">
44
+      <el-form-item label="模块标题: ">
45
+        <el-input v-model="form.name"></el-input>
46
+      </el-form-item>
47
+      <el-form-item label="排序值: ">
48
+        <el-input v-model="form.name"></el-input>
49
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
50
+      </el-form-item>
51
+      <el-form-item label="添加图片: ">
52
+        <el-upload
53
+          action="https://jsonplaceholder.typicode.com/posts/"
54
+          list-type="picture-card"
55
+          :on-preview="handlePictureCardPreview"
56
+          :on-remove="handleRemove">
57
+          <i class="el-icon-plus"></i>
58
+        </el-upload>
59
+      </el-form-item>
60
+    </el-form>
61
+    <span slot="footer" class="dialog-footer">
62
+      <el-button @click="slideshow = false">取 消</el-button>
63
+      <el-button type="primary" @click="slideshow = false">确 定</el-button>
64
+    </span>
65
+  </el-dialog>
66
+
67
+  <!-- 医院地址 -->
68
+  <el-dialog
69
+    title="新增轮播图"
70
+    :visible.sync="address"
71
+    width="550px"
72
+    :before-close="handleClose">
73
+    <el-form ref="form" :model="form" label-width="80px">
74
+      <el-form-item label="模块标题: ">
75
+        <el-input v-model="form.name"></el-input>
76
+      </el-form-item>
77
+      <el-form-item label="排序值: ">
78
+        <el-input v-model="form.name"></el-input>
79
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
80
+      </el-form-item>
81
+      <el-form-item label="医院地址: ">
82
+        <el-input v-model="form.name"></el-input>
83
+      </el-form-item>
84
+      <el-form-item label="医院地图: ">
85
+
86
+      </el-form-item>
87
+    </el-form>
88
+    <span slot="footer" class="dialog-footer">
89
+      <el-button @click="address = false">取 消</el-button>
90
+      <el-button type="primary" @click="address = false">确 定</el-button>
91
+    </span>
92
+  </el-dialog>
93
+
94
+<!-- 新增联系方式 -->
95
+<el-dialog
96
+    title="新增联系方式"
97
+    :visible.sync="contact"
98
+    width="550px"
99
+    :before-close="handleClose">
100
+    <el-form ref="form" :model="form" label-width="80px">
101
+      <el-form-item label="模块标题: ">
102
+        <el-input v-model="form.name"></el-input>
103
+      </el-form-item>
104
+      <el-form-item label="排序值: ">
105
+        <el-input v-model="form.name"></el-input>
106
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
107
+      </el-form-item>
108
+      <el-form-item label="联系方式: ">
109
+        <div class="used">
110
+             <ul>
111
+                 <li>
112
+                    <span class="name">医院电话</span>
113
+                    <span class="icon"> 
114
+                        <i class="el-icon-edit-outline" @click="addLink = true"></i>
115
+                        <i class="el-icon-delete" @click="deleteList = true"></i>
116
+                    </span>
117
+                 </li>
118
+                 <li>
119
+                    <span class="name">微信号</span>
120
+                    <span class="icon"> 
121
+                        <i class="el-icon-edit-outline" @click="addLink = true"></i>
122
+                        <i class="el-icon-delete" @click="deleteList = true"></i>
123
+                    </span>
124
+                 </li>
125
+             </ul>
126
+        </div>
127
+      </el-form-item>
128
+    </el-form>
129
+    <span slot="footer" class="dialog-footer">
130
+      <el-button @click="addLink = true">添加联系方式</el-button>      
131
+      <el-button @click="contact = false">取 消</el-button>
132
+      <el-button type="primary" @click="contact = false">确 定</el-button>
133
+    </span>
134
+  </el-dialog>
135
+
136
+
137
+  <!-- 确定删除组件 -->
138
+    <el-dialog
139
+        title="删除提示"
140
+        :visible.sync="deleteList"
141
+        width="550px"
142
+        :before-close="handleClose">
143
+        <span>确认要删除该组件吗?删除后,该组件将无法恢复</span>
144
+        <span slot="footer" class="dialog-footer">
145
+            <el-button @click="deleteList = false">取 消</el-button>
146
+            <el-button type="primary" @click="deleteList = false">确 定</el-button>
147
+        </span>
148
+    </el-dialog>
149
+  <!-- 新增联系方式 -->
150
+  <el-dialog
151
+    title="新增联系方式"
152
+    :visible.sync="addLink"
153
+    width="550px"
154
+    :before-close="handleClose">
155
+    <el-form ref="form" :model="form" label-width="80px">
156
+        <el-form-item label="标题:">
157
+            <el-input v-model="form.name"></el-input>
158
+        </el-form-item>
159
+        <el-form-item label="联系方式:">
160
+            <el-radio-group v-model="form.resource">
161
+            <el-radio label="电话"></el-radio>
162
+            <el-radio label="非电话"></el-radio>
163
+            </el-radio-group>
164
+        </el-form-item>
165
+        <el-form-item label="内容:">
166
+            <el-input v-model="form.name"></el-input>
167
+        </el-form-item>
168
+    </el-form>
169
+    <span slot="footer" class="dialog-footer">
170
+        <el-button @click="addLink = false">取 消</el-button>
171
+        <el-button type="primary" @click="addLink = false">确 定</el-button>
172
+    </span>
173
+  </el-dialog>
174
+
175
+ <!-- 工作时间 -->
176
+ <el-dialog
177
+    title="新增工作时间"
178
+    :visible.sync="time"
179
+    width="550px"
180
+    :before-close="handleClose">
181
+    <el-form ref="form" :model="form" label-width="80px">
182
+      <el-form-item label="模块标题: ">
183
+        <el-input v-model="form.name"></el-input>
184
+      </el-form-item>
185
+      <el-form-item label="排序值: ">
186
+        <el-input v-model="form.name"></el-input>
187
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
188
+      </el-form-item>
189
+      <el-form-item label="工作时间: ">
190
+        <el-input
191
+          type="textarea"
192
+          :rows="6"
193
+          placeholder="请输入内容"
194
+          v-model="textarea">
195
+        </el-input>
196
+      </el-form-item>
197
+    </el-form>
198
+    <span slot="footer" class="dialog-footer">
199
+      <el-button @click="time = false">取 消</el-button>
200
+      <el-button type="primary" @click="time = false">确 定</el-button>
201
+    </span>
202
+  </el-dialog>
203
+
204
+  <!-- 新增乘车方式 -->
205
+ <el-dialog
206
+    title="新增乘车方式"
207
+    :visible.sync="type"
208
+    width="550px"
209
+    :before-close="handleClose">
210
+    <el-form ref="form" :model="form" label-width="80px">
211
+      <el-form-item label="模块标题: ">
212
+        <el-input v-model="form.name"></el-input>
213
+      </el-form-item>
214
+      <el-form-item label="排序值: ">
215
+        <el-input v-model="form.name"></el-input>
216
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
217
+      </el-form-item>
218
+      <el-form-item label="乘车方式: ">
219
+        <el-input
220
+          type="textarea"
221
+          :rows="6"
222
+          placeholder="请输入内容"
223
+          v-model="textarea">
224
+        </el-input>
225
+      </el-form-item>
226
+    </el-form>
227
+    <span slot="footer" class="dialog-footer">
228
+      <el-button @click="type = false">取 消</el-button>
229
+      <el-button type="primary" @click="type = false">确 定</el-button>
230
+    </span>
231
+  </el-dialog>
232
+
233
+
234
+    </div>
235
+</template>
236
+
237
+
238
+<script>
239
+export default {
240
+  name: "addcontact",
241
+  data() {
242
+    return {
243
+      slideshow:false,
244
+      address:false,
245
+      contact:false,
246
+      addLink:false,
247
+      time:false,
248
+      type:false,
249
+      new1: require("../../../assets/preview/new-1.png"),
250
+      form: {
251
+        name: ""
252
+      }
253
+    };
254
+  }
255
+};
256
+</script>
257
+
258
+<style rel="stylesheet/scss" lang="scss" scoped>
259
+
260
+.tips {
261
+  font-size: 12px;
262
+  line-height: 18px;
263
+}
264
+.used {
265
+  ul {
266
+    li {
267
+      height: 44px;
268
+      line-height: 44px;
269
+      font-size: 14px;
270
+      display: flex;
271
+      color: #606266;      
272
+      align-items: center;
273
+      justify-content: space-between;
274
+      border: 1px solid #e4e7ed;
275
+      padding: 0 10px;
276
+      margin-bottom: 10px;
277
+      border-radius: 4px;
278
+      i {
279
+        font-size: 19px;
280
+        margin: 0 6px;
281
+        cursor: pointer;
282
+      }
283
+    }
284
+  }
285
+}
286
+</style>

+ 14 - 0
src/scrm_pages/site/components/contact-used.vue ファイルの表示

@@ -0,0 +1,14 @@
1
+<template>
2
+    
3
+</template>
4
+
5
+
6
+<script>
7
+export default {
8
+    name:'contactused'
9
+}
10
+</script>
11
+
12
+<style rel="stylesheet/scss" lang="scss" scoped>
13
+
14
+</style>

+ 312 - 90
src/scrm_pages/site/components/new-feature.vue ファイルの表示

@@ -1,107 +1,329 @@
1 1
 <template>
2
-<div class="feature">
3
-    <ul >
4
-        <li>
2
+<div class="feature-box">
3
+  <div class="feature ">
4
+      <ul >
5
+          <li @click="dialogVisible = true">
6
+              <span>
7
+                <img :src="new1" alt="">
8
+                <p>轮播图</p>  
9
+              </span>
10
+          </li>
11
+          <li @click="two = true">
5 12
             <span>
6
-              <img :src="new1" alt="">
7
-              <p>轮播图</p>  
8
-            </span>
9
-        </li>
10
-         <li>
11
-           <span>
12
-              <img :src="new1" alt="">
13
-              <p>轮播图</p>  
14
-            </span>  
15
-        </li>
16
-         <li>
17
-           <span>
18
-              <img :src="new1" alt="">
19
-              <p>轮播图</p>  
20
-            </span>  
21
-        </li>
22
-         <li>
23
-           <span>
24
-              <img :src="new1" alt="">
25
-              <p>轮播图</p>  
26
-            </span>  
27
-        </li>
28
-         <li>
29
-           <span>
30
-              <img :src="new1" alt="">
31
-              <p class="title">轮播图</p>  
32
-            </span>  
33
-        </li>
34
-    </ul>
35
-    <!-- <el-row :gutter="21" type="flex"  justify="space-around">
36
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>轮播图</p></div></el-col>
37
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>医院介绍</p></div></el-col>
38
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>科室介绍</p></div></el-col>
39
-    </el-row>
40
-    <el-row :gutter="21" type="flex"  justify="space-around">
41
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>轮播图</p></div></el-col>
42
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>医院介绍</p></div></el-col>
43
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>科室介绍</p></div></el-col>
44
-    </el-row>
45
-    <el-row :gutter="21" type="flex"  justify="space-around">
46
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>轮播图</p></div></el-col>
47
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>医院介绍</p></div></el-col>
48
-        <el-col :span="5"><div class="grid-content "><img :src="new1" alt=""><p>科室介绍</p></div></el-col>
49
-    </el-row> -->
50
-</div>    
51
-</template>
13
+                <img :src="new1" alt="">
14
+                <p>医院介绍</p>  
15
+              </span>  
16
+          </li>
17
+          <li @click="three = true">
18
+            <span>
19
+                <img :src="new1" alt="">
20
+                <p>科室介绍</p>  
21
+              </span>  
22
+          </li>
23
+          <li @click="four = true">
24
+            <span>
25
+                <img :src="new1" alt="">
26
+                <p>名医介绍</p>  
27
+              </span>  
28
+          </li>
29
+          <li @click="five = true">
30
+            <span>
31
+                <img :src="new1" alt="">
32
+                <p class="title">科室环境</p>  
33
+              </span>  
34
+          </li>
35
+          <li @click="six = true">
36
+            <span>
37
+                <img :src="new1" alt="">
38
+                <p class="title">文章列表</p>  
39
+              </span>  
40
+          </li>
41
+          <li @click="seven = true">
42
+            <span>
43
+                <img :src="new1" alt="">
44
+                <p class="title">活动列表</p>  
45
+              </span>  
46
+          </li>
47
+          <li @click="eight = true">
48
+            <span>
49
+                <img :src="new1" alt="">
50
+                <p class="title">魔方导航</p>  
51
+              </span>  
52
+          </li>
53
+      </ul>
54
+  </div>    
55
+  <div class="clear"></div>
56
+
57
+  <!-- 新增轮播图 -->
58
+  <el-dialog
59
+    title="新增轮播图"
60
+    :visible.sync="dialogVisible"
61
+    width="550px"
62
+    :before-close="handleClose">
63
+    <el-form ref="form" :model="form" label-width="80px">
64
+      <el-form-item label="模块标题: ">
65
+        <el-input v-model="form.name"></el-input>
66
+      </el-form-item>
67
+      <el-form-item label="排序值: ">
68
+        <el-input v-model="form.name"></el-input>
69
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
70
+      </el-form-item>
71
+      <el-form-item label="添加图片: ">
72
+        <el-upload
73
+          action="https://jsonplaceholder.typicode.com/posts/"
74
+          list-type="picture-card"
75
+          :on-preview="handlePictureCardPreview"
76
+          :on-remove="handleRemove">
77
+          <i class="el-icon-plus"></i>
78
+        </el-upload>
79
+      </el-form-item>
80
+    </el-form>
81
+    <span slot="footer" class="dialog-footer">
82
+      <el-button @click="dialogVisible = false">取 消</el-button>
83
+      <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
84
+    </span>
85
+  </el-dialog>
86
+  <!-- 新增医院介绍 -->
87
+  <el-dialog
88
+    title="新增医院介绍"
89
+    :visible.sync="two"
90
+    width="550px"
91
+    :before-close="handleClose">
92
+    <el-form ref="form" :model="form" label-width="80px">
93
+      <el-form-item label="模块标题: ">
94
+        <el-input v-model="form.name"></el-input>
95
+      </el-form-item>
96
+      <el-form-item label="排序值: ">
97
+        <el-input v-model="form.name"></el-input>
98
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
99
+      </el-form-item>
100
+      <el-form-item label="医院介绍: ">
101
+        <el-input
102
+          type="textarea"
103
+          :rows="6"
104
+          placeholder="请输入内容"
105
+          v-model="textarea">
106
+        </el-input>
107
+      </el-form-item>
108
+    </el-form>
109
+    <span slot="footer" class="dialog-footer">
110
+      <el-button @click="two = false">取 消</el-button>
111
+      <el-button type="primary" @click="two = false">确 定</el-button>
112
+    </span>
113
+  </el-dialog>
114
+  <!-- 新增科室介绍 -->
115
+  <el-dialog
116
+    title="新增科室介绍"
117
+    :visible.sync="three"
118
+    width="550px"
119
+    :before-close="handleClose">
120
+    <el-form ref="form" :model="form" label-width="80px">
121
+      <el-form-item label="模块标题: ">
122
+        <el-input v-model="form.name"></el-input>
123
+      </el-form-item>
124
+      <el-form-item label="排序值: ">
125
+        <el-input v-model="form.name"></el-input>
126
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
127
+      </el-form-item>
128
+      <el-form-item label="科室介绍: ">
129
+        <el-input
130
+          type="textarea"
131
+          :rows="6"
132
+          placeholder="请输入内容"
133
+          v-model="textarea">
134
+        </el-input>
135
+      </el-form-item>
136
+    </el-form>
137
+    <span slot="footer" class="dialog-footer">
138
+      <el-button @click="three = false">取 消</el-button>
139
+      <el-button type="primary" @click="three = false">确 定</el-button>
140
+    </span>
141
+  </el-dialog>
142
+
143
+  <!-- 新增名医介绍 -->
144
+  <el-dialog
145
+    title="新增名医介绍"
146
+    :visible.sync="four"
147
+    width="550px"
148
+    :before-close="handleClose">
149
+    <el-form ref="form" :model="form" label-width="80px">
150
+      <el-form-item label="模块标题: ">
151
+        <el-input v-model="form.name"></el-input>
152
+      </el-form-item>
153
+      <el-form-item label="排序值: ">
154
+        <el-input v-model="form.name"></el-input>
155
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
156
+      </el-form-item>
157
+      <el-form-item label="新增名医: ">
158
+        <el-upload
159
+          action="https://jsonplaceholder.typicode.com/posts/"
160
+          list-type="picture-card"
161
+          :on-preview="handlePictureCardPreview"
162
+          :on-remove="handleRemove">
163
+          <i class="el-icon-plus"></i>
164
+        </el-upload>
165
+      </el-form-item>
166
+    </el-form>
167
+    <span slot="footer" class="dialog-footer">
168
+      <el-button @click="four = false">取 消</el-button>
169
+      <el-button type="primary" @click="four = false">确 定</el-button>
170
+    </span>
171
+  </el-dialog>
172
+  <!-- 新增科室环境 -->
173
+   <el-dialog
174
+    title="新增科室环境"
175
+    :visible.sync="five"
176
+    width="550px"
177
+    :before-close="handleClose">
178
+    <el-form ref="form" :model="form" label-width="100px">
179
+      <el-form-item label="模块标题: ">
180
+        <el-input v-model="form.name"></el-input>
181
+      </el-form-item>
182
+      <el-form-item label="排序值: ">
183
+        <el-input v-model="form.name"></el-input>
184
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
185
+      </el-form-item>
186
+      <el-form-item label="新增科室环境: ">
187
+        <el-upload
188
+          action="https://jsonplaceholder.typicode.com/posts/"
189
+          list-type="picture-card"
190
+          :on-preview="handlePictureCardPreview"
191
+          :on-remove="handleRemove">
192
+          <i class="el-icon-plus"></i>
193
+        </el-upload>
194
+      </el-form-item>
195
+    </el-form>
196
+    <span slot="footer" class="dialog-footer">
197
+      <el-button @click="five = false">取 消</el-button>
198
+      <el-button type="primary" @click="five = false">确 定</el-button>
199
+    </span>
200
+  </el-dialog>
201
+  <!-- 新增文章列表 -->
202
+  <el-dialog
203
+    title="新增文章列表"
204
+    :visible.sync="six"
205
+    width="550px"
206
+    :before-close="handleClose">
207
+    <el-form ref="form" :model="form" label-width="100px">
208
+      <el-form-item label="模块标题: ">
209
+        <el-input v-model="form.name"></el-input>
210
+      </el-form-item>
211
+      <el-form-item label="排序值: ">
212
+        <el-input v-model="form.name"></el-input>
213
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
214
+      </el-form-item>
215
+      <el-form-item label="文章分类: ">
216
+        <el-select v-model="form.region" placeholder="请选择活动区域" style="width:49%;float:left;">
217
+          <el-option label="区域一" value="shanghai"></el-option>
218
+          <el-option label="区域二" value="beijing"></el-option>
219
+        </el-select>
220
+        <el-select v-model="form.region" placeholder="请选择活动区域" style="width:49%;float:right;">
221
+          <el-option label="区域一" value="shanghai"></el-option>
222
+          <el-option label="区域二" value="beijing"></el-option>
223
+        </el-select>
224
+      </el-form-item>
225
+      <el-form-item label="首页展示条数: ">
226
+        <el-input v-model="form.name"></el-input>
227
+      </el-form-item>
228
+    </el-form>
229
+    <span slot="footer" class="dialog-footer">
230
+      <el-button @click="six = false">取 消</el-button>
231
+      <el-button type="primary" @click="six = false">确 定</el-button>
232
+    </span>
233
+  </el-dialog>
234
+  <!-- 新增活动列表 -->
235
+   <el-dialog
236
+    title="新增活动列表"
237
+    :visible.sync="seven"
238
+    width="550px"
239
+    :before-close="handleClose">
240
+    <el-form ref="form" :model="form" label-width="100px">
241
+      <el-form-item label="模块标题: ">
242
+        <el-input v-model="form.name"></el-input>
243
+      </el-form-item>
244
+      <el-form-item label="排序值: ">
245
+        <el-input v-model="form.name"></el-input>
246
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
247
+      </el-form-item>
248
+     
249
+      <el-form-item label="首页展示条数: ">
250
+        <el-input v-model="form.name"></el-input>
251
+      </el-form-item>
252
+    </el-form>
253
+    <span slot="footer" class="dialog-footer">
254
+      <el-button @click="seven = false">取 消</el-button>
255
+      <el-button type="primary" @click="seven = false">确 定</el-button>
256
+    </span>
257
+  </el-dialog>
258
+  <!-- 新增魔方导航 -->
259
+  <el-dialog
260
+    title="新增魔方导航"
261
+    :visible.sync="eight"
262
+    width="550px"
263
+    :before-close="handleClose">
264
+    <el-form ref="form" :model="form" label-width="100px">
265
+      <el-form-item label="模块标题: ">
266
+        <el-input v-model="form.name"></el-input>
267
+      </el-form-item>
268
+      <el-form-item label="排序值: ">
269
+        <el-input v-model="form.name"></el-input>
270
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
271
+      </el-form-item>
272
+      <el-form-item label="新增科室环境: ">
273
+        <el-upload
274
+          action="https://jsonplaceholder.typicode.com/posts/"
275
+          list-type="picture-card"
276
+          :on-preview="handlePictureCardPreview"
277
+          :on-remove="handleRemove">
278
+          <i class="el-icon-plus"></i>
279
+        </el-upload>
280
+      </el-form-item>
281
+    </el-form>
282
+    <span slot="footer" class="dialog-footer">
283
+      <el-button @click="eight = false">取 消</el-button>
284
+      <el-button type="primary" @click="eight = false">确 定</el-button>
285
+    </span>
286
+  </el-dialog>
52 287
 
53 288
 
289
+</div>
290
+</template>
291
+
54 292
 <script>
55 293
 export default {
56 294
   name: "newfeature",
57 295
   data() {
58 296
     return {
59
-      new1: require("../../../assets/preview/new-1.png")
297
+      new1: require("../../../assets/preview/new-1.png"),
298
+      dialogVisible: false,
299
+      two: false,
300
+      three: false,
301
+      four: false,
302
+      five: false,
303
+      six: false,
304
+      seven: false,
305
+      eight: false,
306
+      form: {
307
+        name: ""
308
+      }
60 309
     };
61 310
   }
62 311
 };
63 312
 </script>
64 313
 
65 314
 <style rel="stylesheet/scss" lang="scss" scoped>
66
-.feature {
67
-  ul {
68
-    border: 1px solid #eaeefb;
69
-    float: left;
70
-    width: 100%;
71
-    li {
72
-      width: 33.3%;
73
-      float: left;
74
-      text-align: center;
75
-      height: 120px;
76
-      color: #666;
77
-      font-size: 13px;
78
-      border-right: 1px solid #eee;
79
-      border-bottom: 1px solid #eee;
80
-      margin-right: -1px;
81
-      margin-bottom: -1px;
82
-      span {
83
-        vertical-align: middle;
84
-        display: flex;
85
-        flex-direction: column;
86
-        align-items: center;
87
-        justify-content: center;
88
-        height: 120px;
89
-        img {
90
-          display: inline-block;
91
-          font-size: 32px;
92
-          margin-bottom: 15px;
93
-          color: #606266;
94
-          transition: color 0.15s linear;
95
-          vertical-align: middle;
96
-        }
97
-        .title {
98
-          display: inline-block;
99
-          padding: 0 3px;
100
-          height: 30px;
101
-          vertical-align: middle;
102
-        }
103
-      }
104
-    }
105
-  }
315
+
316
+.clearfix {
317
+  clear: both;
318
+}
319
+
320
+.el-upload--picture-card {
321
+  width: 80px !important;
322
+  height: 80px !important;
323
+  line-height: 80px !important;
324
+}
325
+.tips {
326
+  font-size: 12px;
327
+  line-height: 18px;
106 328
 }
107 329
 </style>

+ 361 - 0
src/scrm_pages/site/components/used-list.vue ファイルの表示

@@ -0,0 +1,361 @@
1
+<template>
2
+<div>
3
+    <div class="used">
4
+        <ul>
5
+            <li>
6
+                <span class="name">轮播图</span>
7
+                <span class="icon"> 
8
+                    <i class="el-icon-edit-outline" @click="dialogVisible = true"></i>
9
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
10
+                </span>
11
+            </li>
12
+            <li>
13
+                <span class="name">魔方导航</span>
14
+                <span class="icon"> 
15
+                    <i class="el-icon-edit-outline" @click="eight = true"></i>
16
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
17
+                </span>
18
+            </li>
19
+            <li>
20
+                <span class="name">医院介绍</span>
21
+                <span class="icon"> 
22
+                    <i class="el-icon-edit-outline" @click="two = true"></i>
23
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
24
+                </span>
25
+            </li>
26
+            <li>
27
+                <span class="name">科室介绍</span>
28
+                <span class="icon"> 
29
+                    <i class="el-icon-edit-outline" @click="three = true"></i>
30
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
31
+                </span>
32
+            </li>
33
+            <li>
34
+                <span class="name">名医介绍</span>
35
+                <span class="icon"> 
36
+                    <i class="el-icon-edit-outline" @click="four = true"></i>
37
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
38
+                </span>
39
+            </li>
40
+            <li>
41
+                <span class="name">科室环境</span>
42
+                <span class="icon"> 
43
+                    <i class="el-icon-edit-outline" @click="five = true"></i>
44
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
45
+                </span>
46
+            </li>
47
+            <li>
48
+                <span class="name">文章列表</span>
49
+                <span class="icon"> 
50
+                    <i class="el-icon-edit-outline" @click="six = true"></i>
51
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
52
+                </span>
53
+            </li>
54
+            <li>
55
+                <span class="name">活动列表</span> 
56
+                <span class="icon"> 
57
+                    <i class="el-icon-edit-outline" @click="seven = true"></i>
58
+                    <i class="el-icon-delete" @click="deleteList = true"></i>
59
+                </span>
60
+            </li>
61
+        </ul>
62
+    </div>
63
+
64
+<!-- 确定删除组件 -->
65
+    <el-dialog
66
+        title="删除提示"
67
+        :visible.sync="deleteList"
68
+        width="550px"
69
+        :before-close="handleClose">
70
+        <span>确认要删除该组件吗?删除后,该组件将无法恢复</span>
71
+        <span slot="footer" class="dialog-footer">
72
+            <el-button @click="deleteList = false">取 消</el-button>
73
+            <el-button type="primary" @click="deleteList = false">确 定</el-button>
74
+        </span>
75
+    </el-dialog>
76
+
77
+
78
+  <!-- 新增轮播图 -->
79
+  <el-dialog
80
+    title="新增轮播图"
81
+    :visible.sync="dialogVisible"
82
+    width="550px"
83
+    :before-close="handleClose">
84
+    <el-form ref="form" :model="form" label-width="80px">
85
+      <el-form-item label="模块标题: ">
86
+        <el-input v-model="form.name"></el-input>
87
+      </el-form-item>
88
+      <el-form-item label="排序值: ">
89
+        <el-input v-model="form.name"></el-input>
90
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
91
+      </el-form-item>
92
+      <el-form-item label="添加图片: ">
93
+        <el-upload
94
+          action="https://jsonplaceholder.typicode.com/posts/"
95
+          list-type="picture-card"
96
+          :on-preview="handlePictureCardPreview"
97
+          :on-remove="handleRemove">
98
+          <i class="el-icon-plus"></i>
99
+        </el-upload>
100
+      </el-form-item>
101
+    </el-form>
102
+    <span slot="footer" class="dialog-footer">
103
+      <el-button @click="dialogVisible = false">取 消</el-button>
104
+      <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
105
+    </span>
106
+  </el-dialog>
107
+  <!-- 新增医院介绍 -->
108
+  <el-dialog
109
+    title="新增医院介绍"
110
+    :visible.sync="two"
111
+    width="550px"
112
+    :before-close="handleClose">
113
+    <el-form ref="form" :model="form" label-width="80px">
114
+      <el-form-item label="模块标题: ">
115
+        <el-input v-model="form.name"></el-input>
116
+      </el-form-item>
117
+      <el-form-item label="排序值: ">
118
+        <el-input v-model="form.name"></el-input>
119
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
120
+      </el-form-item>
121
+      <el-form-item label="医院介绍: ">
122
+          <el-input
123
+          type="textarea"
124
+          :rows="6"
125
+          placeholder="请输入内容"
126
+          v-model="textarea">
127
+        </el-input>
128
+      </el-form-item>
129
+    </el-form>
130
+    <span slot="footer" class="dialog-footer">
131
+      <el-button @click="two = false">取 消</el-button>
132
+      <el-button type="primary" @click="two = false">确 定</el-button>
133
+    </span>
134
+  </el-dialog>
135
+  <!-- 新增科室介绍 -->
136
+  <el-dialog
137
+    title="新增科室介绍"
138
+    :visible.sync="three"
139
+    width="550px"
140
+    :before-close="handleClose">
141
+    <el-form ref="form" :model="form" label-width="80px">
142
+      <el-form-item label="模块标题: ">
143
+        <el-input v-model="form.name"></el-input>
144
+      </el-form-item>
145
+      <el-form-item label="排序值: ">
146
+        <el-input v-model="form.name"></el-input>
147
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
148
+      </el-form-item>
149
+      <el-form-item label="科室介绍: ">
150
+           <el-input
151
+          type="textarea"
152
+          :rows="6"
153
+          placeholder="请输入内容"
154
+          v-model="textarea">
155
+        </el-input>
156
+      </el-form-item>
157
+    </el-form>
158
+    <span slot="footer" class="dialog-footer">
159
+      <el-button @click="three = false">取 消</el-button>
160
+      <el-button type="primary" @click="three = false">确 定</el-button>
161
+    </span>
162
+  </el-dialog>
163
+
164
+  <!-- 新增名医介绍 -->
165
+  <el-dialog
166
+    title="新增名医介绍"
167
+    :visible.sync="four"
168
+    width="550px"
169
+    :before-close="handleClose">
170
+    <el-form ref="form" :model="form" label-width="80px">
171
+      <el-form-item label="模块标题: ">
172
+        <el-input v-model="form.name"></el-input>
173
+      </el-form-item>
174
+      <el-form-item label="排序值: ">
175
+        <el-input v-model="form.name"></el-input>
176
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
177
+      </el-form-item>
178
+      <el-form-item label="新增名医: ">
179
+        <el-upload
180
+          action="https://jsonplaceholder.typicode.com/posts/"
181
+          list-type="picture-card"
182
+          :on-preview="handlePictureCardPreview"
183
+          :on-remove="handleRemove">
184
+          <i class="el-icon-plus"></i>
185
+        </el-upload>
186
+      </el-form-item>
187
+    </el-form>
188
+    <span slot="footer" class="dialog-footer">
189
+      <el-button @click="four = false">取 消</el-button>
190
+      <el-button type="primary" @click="four = false">确 定</el-button>
191
+    </span>
192
+  </el-dialog>
193
+
194
+  <!-- 新增科室环境 -->
195
+   <el-dialog
196
+    title="新增科室环境"
197
+    :visible.sync="five"
198
+    width="550px"
199
+    :before-close="handleClose">
200
+    <el-form ref="form" :model="form" label-width="100px">
201
+      <el-form-item label="模块标题: ">
202
+        <el-input v-model="form.name"></el-input>
203
+      </el-form-item>
204
+      <el-form-item label="排序值: ">
205
+        <el-input v-model="form.name"></el-input>
206
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
207
+      </el-form-item>
208
+      <el-form-item label="新增科室环境: ">
209
+        <el-upload
210
+          action="https://jsonplaceholder.typicode.com/posts/"
211
+          list-type="picture-card"
212
+          :on-preview="handlePictureCardPreview"
213
+          :on-remove="handleRemove">
214
+          <i class="el-icon-plus"></i>
215
+        </el-upload>
216
+      </el-form-item>
217
+    </el-form>
218
+    <span slot="footer" class="dialog-footer">
219
+      <el-button @click="five = false">取 消</el-button>
220
+      <el-button type="primary" @click="five = false">确 定</el-button>
221
+    </span>
222
+  </el-dialog>
223
+
224
+  <!-- 新增文章列表 -->
225
+  <el-dialog
226
+    title="新增文章列表"
227
+    :visible.sync="six"
228
+    width="550px"
229
+    :before-close="handleClose">
230
+    <el-form ref="form" :model="form" label-width="100px">
231
+      <el-form-item label="模块标题: ">
232
+        <el-input v-model="form.name"></el-input>
233
+      </el-form-item>
234
+      <el-form-item label="排序值: ">
235
+        <el-input v-model="form.name"></el-input>
236
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
237
+      </el-form-item>
238
+      <el-form-item label="文章分类: ">
239
+        <el-select v-model="form.region" placeholder="请选择活动区域" style="width:49%;float:left;">
240
+          <el-option label="区域一" value="shanghai"></el-option>
241
+          <el-option label="区域二" value="beijing"></el-option>
242
+        </el-select>
243
+        <el-select v-model="form.region" placeholder="请选择活动区域" style="width:49%;float:right;">
244
+          <el-option label="区域一" value="shanghai"></el-option>
245
+          <el-option label="区域二" value="beijing"></el-option>
246
+        </el-select>
247
+      </el-form-item>
248
+      <el-form-item label="首页展示条数: ">
249
+        <el-input v-model="form.name"></el-input>
250
+      </el-form-item>
251
+    </el-form>
252
+    <span slot="footer" class="dialog-footer">
253
+      <el-button @click="six = false">取 消</el-button>
254
+      <el-button type="primary" @click="six = false">确 定</el-button>
255
+    </span>
256
+  </el-dialog>
257
+
258
+  <!-- 新增活动列表 -->
259
+   <el-dialog
260
+    title="新增活动列表"
261
+    :visible.sync="seven"
262
+    width="550px"
263
+    :before-close="handleClose">
264
+    <el-form ref="form" :model="form" label-width="100px">
265
+      <el-form-item label="模块标题: ">
266
+        <el-input v-model="form.name"></el-input>
267
+      </el-form-item>
268
+      <el-form-item label="排序值: ">
269
+        <el-input v-model="form.name"></el-input>
270
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
271
+      </el-form-item>
272
+     
273
+      <el-form-item label="首页展示条数: ">
274
+        <el-input v-model="form.name"></el-input>
275
+      </el-form-item>
276
+    </el-form>
277
+    <span slot="footer" class="dialog-footer">
278
+      <el-button @click="seven = false">取 消</el-button>
279
+      <el-button type="primary" @click="seven = false">确 定</el-button>
280
+    </span>
281
+  </el-dialog>
282
+
283
+  <!-- 新增魔方导航 -->
284
+  <el-dialog
285
+    title="新增魔方导航"
286
+    :visible.sync="eight"
287
+    width="550px"
288
+    :before-close="handleClose">
289
+    <el-form ref="form" :model="form" label-width="100px">
290
+      <el-form-item label="模块标题: ">
291
+        <el-input v-model="form.name"></el-input>
292
+      </el-form-item>
293
+      <el-form-item label="排序值: ">
294
+        <el-input v-model="form.name"></el-input>
295
+        <p class="tips">请输入1-99的整数,数值越小,模块排序越靠前</p>
296
+      </el-form-item>
297
+      <el-form-item label="新增科室环境: ">
298
+        <el-upload
299
+          action="https://jsonplaceholder.typicode.com/posts/"
300
+          list-type="picture-card"
301
+          :on-preview="handlePictureCardPreview"
302
+          :on-remove="handleRemove">
303
+          <i class="el-icon-plus"></i>
304
+        </el-upload>
305
+      </el-form-item>
306
+    </el-form>
307
+    <span slot="footer" class="dialog-footer">
308
+      <el-button @click="eight = false">取 消</el-button>
309
+      <el-button type="primary" @click="eight = false">确 定</el-button>
310
+    </span>
311
+  </el-dialog>
312
+
313
+
314
+</div>
315
+
316
+</template>
317
+
318
+
319
+<script>
320
+export default {
321
+  name: "usedlist",
322
+  data() {
323
+    return {
324
+      deleteList: false,
325
+      two: false,
326
+      three: false,
327
+      four: false,
328
+      five: false,
329
+      six: false,
330
+      seven: false,
331
+      eight: false,
332
+      dialogVisible: false,      
333
+      form: {
334
+        name: ""
335
+      }
336
+    };
337
+  }
338
+};
339
+</script>
340
+
341
+<style rel="stylesheet/scss" lang="scss" scoped>
342
+.used {
343
+  ul {
344
+    li {
345
+      height: 44px;
346
+      line-height: 44px;
347
+      font-size: 14px;
348
+      display: flex;
349
+      color: #606266;      
350
+      align-items: center;
351
+      justify-content: space-between;
352
+      border-bottom: 1px solid #e4e7ed;
353
+      i {
354
+        font-size: 19px;
355
+        margin: 0 6px;
356
+        cursor: pointer;
357
+      }
358
+    }
359
+  }
360
+}
361
+</style>

+ 7 - 3
src/scrm_pages/site/preview.vue ファイルの表示

@@ -12,14 +12,14 @@
12 12
                                  <new-feature> </new-feature>
13 13
                             </el-tab-pane>
14 14
                             <el-tab-pane label="已使用" name="second">
15
-
15
+                                 <used-list></used-list>
16 16
                             </el-tab-pane>
17 17
                         </el-tabs>
18 18
                     </el-tab-pane>
19 19
                     <el-tab-pane label="联系我们">
20 20
                         <el-tabs v-model="activeName" @tab-click="handleClick">
21 21
                             <el-tab-pane label="新增模块" name="three">
22
-
22
+                                <add-contact></add-contact>
23 23
                             </el-tab-pane>
24 24
                             <el-tab-pane label="已使用" name="four">
25 25
                                 
@@ -36,11 +36,15 @@
36 36
 <script> 
37 37
 import BreadCrumb from "../components/bread-crumb";
38 38
 import NewFeature from "./components/new-feature";
39
+import UsedList from "./components/used-list";
40
+import AddContact from "./components/add-contact";
39 41
 export default {
40 42
   name: "preview",
41 43
   components: {
42 44
     BreadCrumb,
43
-    NewFeature
45
+    NewFeature,
46
+    UsedList,
47
+    AddContact
44 48
   },
45 49
   data() {
46 50
     return {

+ 101 - 0
src/scrm_pages/weixinmp/components/CreateKWReplyForm.vue ファイルの表示

@@ -0,0 +1,101 @@
1
+<template>
2
+    <div id="create-kw-reply-form-box">
3
+        <el-dialog title="添加关键词回复" :visible.sync="createKWReplyFormVisible" width="700px" >
4
+            <el-form ref="replyForm" :rules="replyRules" :model="form" label-width="90px">
5
+                <el-form-item label="规则名称:" required prop="message_regular_name">
6
+                    <el-input v-model="form.message_regular_name"></el-input>
7
+                </el-form-item>
8
+                <el-form-item label="模式:" required prop="message_key_type">
9
+                    <el-radio-group v-model="form.message_key_type">
10
+                        <el-radio :label="item.id" :value="item.id" v-for="(item, index) in keyTypeOptions" :key="index" >{{item.name}}</el-radio>
11
+                    </el-radio-group>
12
+                </el-form-item>
13
+                <el-form-item label="关键字:" required prop="message_key_name">
14
+                    <el-input v-model="form.message_key_name"></el-input>
15
+                </el-form-item>
16
+                <el-form-item label="回复内容:" required prop="message_content">
17
+                    <el-input v-model="form.message_content" type="textarea" rows="4"></el-input>
18
+                </el-form-item>
19
+            </el-form>
20
+            <div slot="footer" class="dialog-footer">
21
+                <el-button @click="createKWReplyFormVisible = false">取消</el-button>
22
+                <el-button
23
+                type="primary"
24
+                @click="submitForm('replyForm')"
25
+                >保 存
26
+                </el-button>
27
+            </div>
28
+        </el-dialog>  
29
+    </div>
30
+</template>
31
+
32
+<script>
33
+import {CreateKeyWordReply} from "@/api/mpwechat/mpreply";
34
+
35
+export default {
36
+    name:'CreateReplyForm',
37
+    props:{
38
+        replysData:{
39
+            type: Array,
40
+            default: function () {
41
+                return [];
42
+            }
43
+        },
44
+    },
45
+    data(){
46
+        return {
47
+            createKWReplyFormVisible:false,
48
+            keyTypeOptions:[
49
+                {id:1, name:'半匹配'},
50
+                {id:2, name:'全匹配'},
51
+            ],
52
+            replyRules: {
53
+                message_regular_name: [{required: true, message: "请填写规则名称",},],
54
+                message_key_type: [{required: true, message: "请选择模式",},],
55
+                message_key_name: [{required: true, message: "请填写关键字",},],
56
+                message_content: [{required: true, message: "请填写回复内容",},],
57
+            },
58
+            form:{
59
+                message_regular_name:'',
60
+                message_key_type:1,
61
+                message_key_name:'',
62
+                message_content:'',
63
+            },
64
+            
65
+        }
66
+    },
67
+    methods:{
68
+        open:function(){
69
+            this.resetForm("replyForm");
70
+            this.createKWReplyFormVisible = true;
71
+        },
72
+        resetForm(formName) {
73
+            if (typeof(this.$refs[formName]) !='undefined') {
74
+                this.$refs[formName].resetFields();
75
+            }
76
+        },
77
+        submitForm(formName){
78
+            this.$refs[formName].validate((valid) => {
79
+                if (valid) {
80
+                    CreateKeyWordReply(this.form).then(response=>{
81
+                        var res = response.data;
82
+                        if(res.state === 1) {
83
+                            var message = res.data.message;
84
+                            this.replysData.unshift(message);
85
+                            this.resetForm("replyForm");
86
+                            this.createKWReplyFormVisible = false;
87
+                            this.$message.success("添加成功");
88
+                        }else {
89
+                            this.$message.error(res.msg);
90
+                        }
91
+                    }).catch(e=>{});
92
+
93
+                } else {
94
+                    return false;
95
+                }
96
+            });
97
+        },
98
+    }
99
+}
100
+</script>
101
+

+ 105 - 0
src/scrm_pages/weixinmp/components/EditKWReplyForm.vue ファイルの表示

@@ -0,0 +1,105 @@
1
+<template>
2
+    <div id="edit-kw-reply-form-box">
3
+        <el-dialog title="编辑关键词回复" :visible.sync="editKWReplyFormVisible" width="700px" >
4
+            <el-form ref="replyForm" :rules="replyRules" :model="form" label-width="90px">
5
+                <el-form-item label="规则名称:" required prop="message_regular_name">
6
+                    <el-input v-model="form.message_regular_name"></el-input>
7
+                </el-form-item>
8
+                <el-form-item label="模式:" required prop="message_key_type">
9
+                    <el-radio-group v-model="form.message_key_type">
10
+                        <el-radio :label="item.id" :value="item.id" v-for="(item, index) in keyTypeOptions" :key="index" >{{item.name}}</el-radio>
11
+                    </el-radio-group>
12
+                </el-form-item>
13
+                <el-form-item label="关键字:" required prop="message_key_name">
14
+                    <el-input v-model="form.message_key_name"></el-input>
15
+                </el-form-item>
16
+                <el-form-item label="回复内容:" required prop="message_content">
17
+                    <el-input v-model="form.message_content" type="textarea" rows="4"></el-input>
18
+                </el-form-item>
19
+            </el-form>
20
+            <div slot="footer" class="dialog-footer">
21
+                <el-button @click="editKWReplyFormVisible = false">取消</el-button>
22
+                <el-button
23
+                type="primary"
24
+                @click="submitForm('replyForm')"
25
+                >保 存
26
+                </el-button>
27
+            </div>
28
+        </el-dialog>  
29
+    </div>
30
+</template>
31
+
32
+<script>
33
+import {EditKeyWordReply} from "@/api/mpwechat/mpreply";
34
+
35
+export default {
36
+    name:'EditReplyForm',
37
+    props:{
38
+        replysData:{
39
+            type: Array,
40
+            default: function () {
41
+                return [];
42
+            }
43
+        },
44
+        replyIndex:{
45
+            type:Number,
46
+            default:-1,
47
+        },
48
+        form:{
49
+            id:0,
50
+            message_regular_name:'',
51
+            message_key_type:1,
52
+            message_key_name:'',
53
+            message_content:'',
54
+        },
55
+    },
56
+    data(){
57
+        return {
58
+            editKWReplyFormVisible:false,
59
+            keyTypeOptions:[
60
+                {id:1, name:'半匹配'},
61
+                {id:2, name:'全匹配'},
62
+            ],
63
+            replyRules: {
64
+                message_regular_name: [{required: true, message: "请填写规则名称",},],
65
+                message_key_type: [{required: true, message: "请选择模式",},],
66
+                message_key_name: [{required: true, message: "请填写关键字",},],
67
+                message_content: [{required: true, message: "请填写回复内容",},],
68
+            },
69
+            
70
+        }
71
+    },
72
+    methods:{
73
+        open:function(){
74
+            this.editKWReplyFormVisible = true;
75
+        },
76
+        resetForm(formName) {
77
+            if (typeof(this.$refs[formName]) !='undefined') {
78
+                this.$refs[formName].resetFields();
79
+            }
80
+        },
81
+        submitForm(formName){
82
+            this.$refs[formName].validate((valid) => {
83
+                if (valid) {
84
+                    EditKeyWordReply(this.form.id, this.form).then(response=>{
85
+                        var res = response.data;
86
+                        if(res.state === 1) {
87
+                            var message = res.data.message;
88
+                            this.replysData.splice(this.replyIndex, 1, message);
89
+                            this.resetForm("replyForm");
90
+                            this.editKWReplyFormVisible = false;
91
+                            this.$message.success("编辑成功");
92
+                        }else {
93
+                            this.$message.error(res.msg);
94
+                        }
95
+                    }).catch(e=>{});
96
+
97
+                } else {
98
+                    return false;
99
+                }
100
+            });
101
+        },
102
+    }
103
+}
104
+</script>
105
+

+ 193 - 0
src/scrm_pages/weixinmp/components/ImageMaterialBox.vue ファイルの表示

@@ -0,0 +1,193 @@
1
+<template>
2
+    <div id="image-material-box">
3
+        <el-dialog title="选择图片" :visible.sync="ImageMaterialBoxVisible" width="900px" >
4
+            <el-row>
5
+                <el-col :span="24" style="text-align: right;" >
6
+                    <el-upload
7
+                        class="media-uploader"
8
+                        :action="addMaterialUrl"
9
+                        :show-file-list="false"
10
+                        :with-credentials='true'
11
+                        :on-success="handleMediaSuccess"
12
+                        :before-upload="beforeMediaUpload"
13
+                        >
14
+                        <el-button type="primary" size="small" icon="el-icon-upload" >上传图片</el-button>
15
+                    </el-upload>
16
+                </el-col>
17
+            </el-row>
18
+            <div class="material-box">
19
+                <div class="mateial-item" v-for="(media, index) in medias" :key="index" @click="selectThis(media.media_id, media.media_url)">
20
+                    <div class="mateial-item-image" :class="selectId==media.media_id?'active':''">
21
+                        <img :src="'http://img01.store.sogou.com/net/a/04/link?appid=100520029&url='+media.media_url" alt="" srcset="">
22
+                    </div>
23
+                </div>
24
+            </div>
25
+            <el-row style="clear:both">
26
+                <el-pagination
27
+                    @size-change="handleSizeChange"
28
+                    @current-change="handleCurrentChange"
29
+                    :page-sizes="[20,50,100]"
30
+                    :page-size="20"
31
+                    :current-page="pageParams.page"
32
+                    background
33
+                    style="margin-top:20px;"
34
+                    align="right"
35
+                    layout="total, sizes, prev, pager, next, jumper"
36
+                    :total="total">
37
+                </el-pagination>
38
+            </el-row>
39
+            <div slot="footer" class="dialog-footer">
40
+                <el-button @click="ImageMaterialBoxVisible = false">取消</el-button>
41
+                <el-button
42
+                type="primary"
43
+                @click="submitSelect"
44
+                >保 存
45
+                </el-button>
46
+            </div>
47
+        </el-dialog>  
48
+    </div>
49
+</template>
50
+
51
+<script>
52
+
53
+import {GetMaterials} from "@/api/mpwechat/material";
54
+
55
+export default {
56
+    name:'imageMaterialBox',
57
+    props:{
58
+        currentMenu:{
59
+            big_type:0,
60
+            type:'',
61
+            name:'',
62
+            url:'',
63
+            appid:'',
64
+            pagepath:'',
65
+            key:'',//key规则:V_[number]_click;VC_[number]_click
66
+            message:'',
67
+            sub_button:[],
68
+            media_id:'',
69
+            media_url:'',
70
+        },
71
+    },
72
+    data(){
73
+        return {
74
+            addMaterialUrl: process.env.BASE_API + '/api/mpwechat/media/add_material',
75
+            ImageMaterialBoxVisible:false,
76
+            medias:[],
77
+            selectId:'',
78
+            selectUrl:'',
79
+            total:0,
80
+            pageParams:{
81
+                page:1,
82
+                limit:20,
83
+                media_type:'image',
84
+            },
85
+        }
86
+    },
87
+    methods:{
88
+        open:function(){
89
+            
90
+            this.pageParams={
91
+                page:1,
92
+                limit:20,
93
+                media_type:'image',
94
+            },
95
+            
96
+            this.selectId='',
97
+            this.selectUrl='',
98
+            this.GetMaterials();
99
+            this.ImageMaterialBoxVisible = true;
100
+        },
101
+        submitSelect:function(){
102
+            if (this.selectId.length==0) {
103
+                this.$message.error('未选择图片');
104
+                return false;
105
+            }
106
+            this.currentMenu.media_id = this.selectId;
107
+            this.currentMenu.media_url = 'http://img01.store.sogou.com/net/a/04/link?appid=100520029&url=' +  this.selectUrl;
108
+            this.ImageMaterialBoxVisible = false;
109
+        },
110
+        selectThis(id, url) {
111
+            this.selectId = id;
112
+            this.selectUrl = url;
113
+        },
114
+        handleSizeChange(limit) {
115
+            this.pageParams.limit = limit;
116
+            this.GetMaterials();
117
+        },
118
+        handleCurrentChange(page) {
119
+            this.pageParams.page = page;
120
+            this.GetMaterials();
121
+        },
122
+        handleMediaSuccess:function(res, file) {
123
+            if (res.state==1) {
124
+                this.$message.success('上传成功');
125
+                this.currentMenu.media_url = 'http://img01.store.sogou.com/net/a/04/link?appid=100520029&url=' + res.data.media.media_url;
126
+                this.currentMenu.media_id =  res.data.media.media_id;
127
+                this.pageParams.page = 1;
128
+                
129
+                this.selectId='',
130
+                this.selectUrl='',
131
+                this.GetMaterials();
132
+            }else {
133
+                this.$message.error(res.msg);
134
+            }
135
+        },
136
+        beforeMediaUpload:function(file) {
137
+            var allow = {"image/bmp":1,"image/png":1,"image/jpeg":1,"image/jpg":1,"image/gif":1};
138
+            // const isJPG = file.type === 'image/jpeg';
139
+            const isImg = file.type in allow;
140
+            const isLt2M = file.size / 1024 / 1024 < 2;
141
+
142
+            if (!isImg) {
143
+                this.$message.error('上传图片只能是 bmp/png/jpeg/jpg/gif 格式!');
144
+            }
145
+            if (!isLt2M) {
146
+                this.$message.error('上传图片大小不能超过 2MB!');
147
+            }
148
+            return isImg && isLt2M;
149
+        },
150
+        GetMaterials:function(){
151
+            GetMaterials(this.pageParams).then(response=>{
152
+                var res = response.data;
153
+                if (res.state==1) {
154
+                    this.medias = res.data.medias;
155
+                    this.total = res.data.total;
156
+                }
157
+            }).catch(e=>{});
158
+        }
159
+    }
160
+}
161
+</script>
162
+
163
+<style >
164
+#image-material-box .mateial-item {
165
+    float: left;
166
+    margin: 6px;
167
+}
168
+
169
+#image-material-box  .mateial-item-image {
170
+    width: 199px;
171
+    height: 90px;
172
+    position: relative;
173
+    border: none;
174
+    background: #dde1e4;
175
+    color: #58a2ec;
176
+    display: block;
177
+    padding: 4px;
178
+    line-height: 1.42857143;
179
+    background-color: #fff;
180
+    -webkit-transition: border .2s ease-in-out;
181
+    transition: border .2s ease-in-out;
182
+}
183
+
184
+#image-material-box  .mateial-item .active {
185
+    border: 1px solid rgb(68, 181, 73);
186
+}
187
+#image-material-box  .mateial-item-image img {
188
+    width: 100%;
189
+    height: 100%;
190
+    position: relative;
191
+}
192
+</style>
193
+

+ 30 - 0
src/scrm_pages/weixinmp/components/replyNav.vue ファイルの表示

@@ -0,0 +1,30 @@
1
+<template>
2
+    <el-tabs v-model="tabActiveName" @tab-click="handleTabClick" style="margin-bottom:10px">
3
+        <el-tab-pane label="关键词回复" name="keyword"></el-tab-pane>
4
+        <el-tab-pane label="关注后回复" name="subscribe"></el-tab-pane>
5
+    </el-tabs>
6
+</template>
7
+<script>
8
+export default {
9
+    props:{
10
+        activeName:{
11
+            type:String,
12
+            default: 'subscribe'
13
+        }
14
+    },
15
+    data(){
16
+        return{
17
+            tabActiveName:'subscribe',
18
+        }
19
+    }, 
20
+    methods:{
21
+        handleTabClick(tab, event) {
22
+            this.$router.push({ path: "/weixinmp/reply/"+this.tabActiveName });
23
+        }
24
+    },
25
+    created(){
26
+        this.tabActiveName = this.activeName
27
+    },
28
+}
29
+</script>
30
+

+ 234 - 0
src/scrm_pages/weixinmp/keywordreply.vue ファイルの表示

@@ -0,0 +1,234 @@
1
+<template>
2
+  <div class="main-contain">
3
+    <div class="position">
4
+      <bread-crumb :crumbs='crumbs'></bread-crumb>
5
+      <el-button  style="float:right;" type="primary" size="small" icon="el-icon-circle-plus-outline" @click="openCreate">添加回复</el-button>
6
+    </div>
7
+    <div class="app-container">
8
+        <reply-nav activeName="keyword"></reply-nav>
9
+        <div style="margin-bottom: 10px">
10
+            <el-row :gutter="24">
11
+                <el-col :span="8">
12
+                    <el-input style="width: 300px" v-model="listQuery.search" placeholder="请输入您需要搜索的内容"></el-input>
13
+                    <el-button type="primary"  icon="el-icon-search" @click="changeKey">搜索</el-button>
14
+                </el-col>
15
+            </el-row>
16
+        </div>
17
+        <div class="filter-container" style="margin-top: 10px;margin-left: 5px">
18
+            <el-checkbox style="width: 30px" @change="changeCheck" v-model="checkAllStatus">全选</el-checkbox>
19
+            <el-button size="small" icon="el-icon-delete" @click="openDeleteReplys">批量删除</el-button>
20
+        </div>
21
+        <el-table ref="multipleTable"  @selection-change="handleSelectionChange"  :header-cell-style="{ backgroundColor: 'rgb(245, 247, 250)'}" :data="messagesData" border fit highlight-current-row  style="width: 100%;margin-top: 10px;">
22
+            <el-table-column
23
+                align="center"
24
+                type="selection"
25
+                width="55">
26
+             </el-table-column>
27
+            <el-table-column label="关键词" align="center">
28
+                <template slot-scope="scope">
29
+                    {{scope.row.message_key_name}}
30
+                </template>
31
+            </el-table-column>
32
+            <el-table-column label="回复内容" align="center">
33
+                <template slot-scope="scope">
34
+                <span>{{scope.row.message_content}}</span>
35
+                </template>
36
+            </el-table-column>
37
+            <el-table-column label="模式" align="center">
38
+                <template slot-scope="scope">
39
+                <span>{{keyTypeName(scope.row.message_key_type)}}</span>
40
+                </template>
41
+            </el-table-column>
42
+            <el-table-column label="操作" align="center">
43
+                <template slot-scope="scope">
44
+                    <el-tooltip class="item" effect="dark" content="编辑" placement="top">
45
+                        <el-button size="mini" type="primary" icon="el-icon-edit-outline" @click="openEdit(scope.row, scope.$index)" ></el-button>
46
+                    </el-tooltip>
47
+                    <el-tooltip class="item" effect="dark" content="删除" placement="top">
48
+                        <el-button size="mini" type="danger" icon="el-icon-delete" @click="openDelete(scope.row, scope.$index)" ></el-button>
49
+                    </el-tooltip>
50
+                </template>
51
+            </el-table-column>
52
+        </el-table>
53
+        <el-pagination
54
+            @size-change="handleSizeChange"
55
+            @current-change="handleCurrentChange"
56
+            :page-sizes="[10,20,50,100]"
57
+            :page-size="10"
58
+            background
59
+            style="margin-top:20px;"
60
+            align="right"
61
+            layout="total, sizes, prev, pager, next, jumper"
62
+            :total="total">
63
+        </el-pagination>
64
+        <!--添加-->
65
+        <create-k-w-reply-form ref="createKWReplyForm" :replysData="messagesData" ></create-k-w-reply-form>
66
+        <!--编辑-->
67
+        <edit-k-w-reply-form ref="editKWReplyForm" :replysData="messagesData" :replyIndex="replyIndex" :form="editForm"></edit-k-w-reply-form>
68
+    </div>
69
+  </div>
70
+</template>
71
+
72
+<script>
73
+  import {GetKeyWordReplys,DeleteReplys} from "@/api/mpwechat/mpreply";
74
+  import BreadCrumb from '../components/bread-crumb';
75
+  import CreateKWReplyForm from './components/CreateKWReplyForm';
76
+  import EditKWReplyForm from './components/EditKWReplyForm';
77
+import replyNav from "./components/replyNav";
78
+
79
+  export default {
80
+    name: 'keywordreply',
81
+    components:{
82
+      BreadCrumb,
83
+      replyNav,
84
+      CreateKWReplyForm,
85
+      EditKWReplyForm,
86
+    },
87
+    data(){
88
+      return{
89
+        crumbs: [
90
+        { path: false, name: "系统设置" },
91
+        { path: false, name: "关键词回复" }
92
+        ],
93
+        total:0,
94
+        listQuery:{
95
+            page:1,
96
+            limit:10,
97
+            search:'',
98
+        },
99
+        checkAllStatus:false,
100
+        selectedReplys:[],
101
+        messagesData:[],
102
+        replyIndex:-1,
103
+        editForm:{
104
+            id:0,
105
+            message_regular_name:'',
106
+            message_key_type:1,
107
+            message_key_name:'',
108
+            message_content:'',
109
+        },
110
+      }
111
+    },
112
+    methods:{
113
+        openCreate:function(){
114
+          this.$refs.createKWReplyForm.open();
115
+        },
116
+        openEdit:function(row,index){
117
+            this.replyIndex = index;
118
+            for (const key in this.editForm) {
119
+              this.editForm[key] = row[key];
120
+            }
121
+            this.$refs.editKWReplyForm.open();
122
+        },
123
+        openDeleteReplys:function(){
124
+          if (this.selectedReplys.length==0) {
125
+            this.$message.error("请选择要删除的回复");
126
+            return false;
127
+          }
128
+
129
+          this.$confirm('确认要删除所选的回复吗?<br>删除后,回复将无法恢复', '删除提示', {
130
+            dangerouslyUseHTMLString:true,
131
+            confirmButtonText: '确定',
132
+            cancelButtonText: '取消',
133
+            type: 'warning'
134
+          }).then(() => {
135
+            var ids = [];
136
+            var idMap = {};
137
+            for (const index in this.selectedReplys) {
138
+              ids.push(this.selectedReplys[index].id);
139
+              idMap[this.selectedReplys[index].id] = this.selectedReplys[index].id;
140
+            }
141
+            DeleteReplys({ids:ids}).then(response=>{
142
+              var res = response.data;
143
+              if (res.state === 1) {
144
+                var dataLength = this.messagesData.length;
145
+                for (let index = dataLength-1; index >= 0; index--) {
146
+                  if(this.messagesData[index].id in idMap) {
147
+                    this.messagesData.splice(index, 1);
148
+                  }                  
149
+                }
150
+                this.$message.success("删除成功");
151
+              }else {
152
+                this.$message.error(res.msg);
153
+              }
154
+            }).catch(e=>{});
155
+          }).catch(() => {
156
+            return false        
157
+          });
158
+        },
159
+        openDelete:function(row,index){
160
+          this.$confirm('确认要删除该回复吗?<br>删除后,该回复将无法恢复', '删除提示', {
161
+            dangerouslyUseHTMLString:true,
162
+            confirmButtonText: '确定',
163
+            cancelButtonText: '取消',
164
+            type: 'warning'
165
+          }).then(() => {
166
+            var ids = [];
167
+            ids.push(row.id);
168
+            DeleteReplys({ids:ids}).then(response=>{
169
+              var res = response.data;
170
+              if (res.state === 1) {
171
+                this.messagesData.splice(index, 1);
172
+                this.$message.success("删除成功");
173
+              }else {
174
+                this.$message.error(res.msg);
175
+              }
176
+            }).catch(e=>{});
177
+          }).catch(() => {
178
+            return false        
179
+          });
180
+        },
181
+        changeCheck:function(){
182
+          this.$refs.multipleTable.clearSelection();
183
+          if (this.checkAllStatus) {
184
+            this.$refs.multipleTable.toggleAllSelection();
185
+          }
186
+        },
187
+        handleSelectionChange:function (val) {
188
+          this.selectedReplys = val;
189
+        },
190
+        handleSizeChange(limit) {
191
+            this.listQuery.limit = limit;
192
+            this.GetKeyWordReplys();
193
+        },
194
+        handleCurrentChange(page) {
195
+            this.listQuery.page = page;
196
+            this.GetKeyWordReplys();
197
+        },
198
+        changeKey(){
199
+            this.GetKeyWordReplys();
200
+        },
201
+        keyTypeName:function(type){
202
+          return type == 1?'半匹配':'全匹配';
203
+        },
204
+        GetKeyWordReplys(){
205
+            GetKeyWordReplys(this.listQuery).then(response=>{
206
+                var res = response.data;
207
+                if(res.state===1) {
208
+                    this.messagesData = res.data.messages;
209
+                    this.total = res.data.total;
210
+                }
211
+            }).catch(e=>{})
212
+        }
213
+    },
214
+    computed:{
215
+    },
216
+    created(){
217
+        this.GetKeyWordReplys();
218
+    }
219
+  }
220
+</script>
221
+
222
+<style scoped>
223
+  /*.app-container .cell.clearfix .time ul li {*/
224
+    /*float: left;*/
225
+    /*list-style: none;*/
226
+    /*cursor: pointer;*/
227
+    /*padding: 6px 20px;*/
228
+    /*color: #606266;*/
229
+    /*border-radius: 4px;*/
230
+    /*margin: 0 8px 0 0;*/
231
+    /*font-size: 14px;*/
232
+    /*text-align: center;*/
233
+  /*}*/
234
+</style>

+ 210 - 12
src/scrm_pages/weixinmp/menus.vue ファイルの表示

@@ -4,7 +4,7 @@
4 4
       <bread-crumb :crumbs="crumbs"></bread-crumb>
5 5
       <el-col :span="5" style="text-align: right;" v-show="initButtons">
6 6
         <el-button type="primary" size="small" :disabled="subload" icon="el-icon-upload" @click="submitSave">保存并发布</el-button>
7
-        <el-button  type="danger" size="small" :disabled="subload" icon="el-icon-delete" >停用菜单</el-button>
7
+        <el-button  type="danger" size="small" :disabled="subload" icon="el-icon-delete" @click="deleteMenus">停用菜单</el-button>
8 8
       </el-col>
9 9
     </div>
10 10
     <div class="app-container" id="winxin-menus-box">
@@ -41,7 +41,7 @@
41 41
                             </div> 
42 42
                         </li>
43 43
 
44
-                          <li class="jsAddMenu pre_menu_li" v-show="menus.button.length<3">
44
+                          <li class="jsAddMenu pre_menu_li" v-show="!menus.button||menus.button.length<3">
45 45
                               <a href="javascript:void(0);" class="pre_menu_link" @click="addItem(-1)">
46 46
                                   <i class="icon_menu_dot "></i>
47 47
                                   <span class="js_l1Title_">
@@ -84,7 +84,7 @@
84 84
                   <div class="menu_form_item menu_more_info" v-show="typeof(currentMenu.sub_button) == 'undefined' || !currentMenu.sub_button || currentMenu.sub_button.length==0">
85 85
                       <div class="menu_form__nav clearfix">
86 86
                           <label for="" class="tit">菜单内容</label>
87
-                          <el-radio-group v-model="menuType" class="radio_item" @change="changeMenuType">
87
+                          <el-radio-group v-model="menuType" class="radio_item" @change="changeBigType">
88 88
                             <el-radio v-for="(menu, index) in menuTypeOptions" :key="index" :label="menu.id" :value="menu.id">{{menu.name}}</el-radio>
89 89
                           </el-radio-group>
90 90
                       </div>
@@ -92,13 +92,44 @@
92 92
                         <div class="inner send_message " v-show="menuType==1">
93 93
                             <div class="send_message_tit">
94 94
                                 <div class="send_nav">
95
-                                    <i class="ico_size"></i>
96
-                                    文字
95
+                                    <el-button type="text" icon="el-icon-edit-outline" style="padding:0" :disabled="currentMenu.type=='click'" @click="selectMenuType(1)">文字</el-button>
97 96
                                 </div>
97
+                                <div class="send_nav">
98
+                                    <el-button type="text" icon="el-icon-picture-outline" style="padding:0" :disabled="currentMenu.type=='media_id'" @click="selectMenuType(2)">图片</el-button>
99
+                                </div>
100
+                            </div>
101
+                            <textarea v-show="currentMenu.type=='click'" class="send_message_edit" id="click_menu_act" v-model="currentMenu.message" placeholder="请输入你需要的文字"></textarea>
102
+                            <span v-show="currentMenu.type=='click'" class="tips" id="acterrinfo" v-if="!messageError" >&nbsp;&nbsp;{{menuMessageTip}}</span>
103
+                            <span v-show="currentMenu.type=='click'" class="tips" id="acterrinfo" v-if="messageError"  style="color: #f00;">&nbsp;&nbsp;{{menuMessageTip}}</span>
104
+                            <div v-show="currentMenu.type=='media_id'" class="mediaID-box">
105
+                              <el-row>
106
+                                <el-col :span="12" >
107
+                                  <div class="mediaID-item">
108
+                                    <i class="el-icon-news" @click="openMediaBox"></i>
109
+                                    <span class="icon-name">从素材库选择</span>
110
+                                  </div>
111
+                                </el-col>
112
+                                <el-col :span="12" >
113
+                                  <div class="mediaID-item">
114
+                                    <el-upload
115
+                                      class="media-uploader"
116
+                                      :action="addMaterialUrl"
117
+                                      :show-file-list="false"
118
+                                      :with-credentials='true'
119
+                                      :on-success="handleMediaSuccess"
120
+                                      :before-upload="beforeMediaUpload"
121
+                                      >
122
+                                      <img v-if="currentMenu.media_url" :src="currentMenu.media_url" class="media">
123
+                                      <i v-else class="el-icon-plus media-uploader-icon"></i>
124
+                                    </el-upload>
125
+                                    <span class="icon-name">上传图片</span>
126
+                                  </div>
127
+                                </el-col>
128
+                              </el-row>
129
+                              
130
+                            <span class="tips" id="acterrinfo"  >&nbsp;&nbsp;如果出现:此图片来自微信公众平台,未经允许不可引用!是正常情况</span>
131
+                              
98 132
                             </div>
99
-                            <textarea class="send_message_edit" id="click_menu_act" v-model="currentMenu.message" placeholder="请输入你需要的文字"></textarea>
100
-                            <span class="tips" id="acterrinfo" v-if="!messageError" >&nbsp;&nbsp;{{menuMessageTip}}</span>
101
-                            <span class="tips" id="acterrinfo" v-if="messageError"  style="color: #f00;">&nbsp;&nbsp;{{menuMessageTip}}</span>
102 133
                         </div>
103 134
                         <div class="inner  jump_page" v-show="menuType==2">
104 135
                             <span class="tips_size">订阅者点击该子菜单会跳到以下链接</span>
@@ -137,16 +168,22 @@
137 168
           </div>
138 169
       </div>
139 170
     </div>
171
+    <!--选择图片-->
172
+    <image-material-box ref="imageMaterialBox" :currentMenu="currentMenu"></image-material-box>
140 173
   </div>
141 174
 </template>
142 175
 
143 176
 <script>
144 177
 import BreadCrumb from "../components/bread-crumb";
145
-import {GetAuthorizationInfo,GetMenus,SaveMenus} from "@/api/mpwechat/mpwechat";
178
+import ImageMaterialBox from "./components/ImageMaterialBox";
179
+import {GetAuthorizationInfo} from "@/api/mpwechat/mpwechat";
180
+import {GetMenus,SaveMenus,DeleteMenu} from "@/api/mpwechat/mpmenus";
181
+
146 182
 export default {
147 183
   name: "menus",
148 184
   components: {
149 185
     BreadCrumb,
186
+    ImageMaterialBox,
150 187
   },
151 188
   data() {
152 189
     return {
@@ -159,10 +196,12 @@ export default {
159 196
         {id:2, name:' 跳转网页'},
160 197
         {id:3, name:' 跳转小程序'},
161 198
       ],
199
+      addMaterialUrl: process.env.BASE_API + '/api/mpwechat/media/add_material',
162 200
       initButtons:false,
163 201
       subload:false,
164 202
       menus:{button:[]},
165 203
       currentMenu:{
204
+        big_type:0,
166 205
         type:'',
167 206
         name:'',
168 207
         url:'',
@@ -172,6 +211,7 @@ export default {
172 211
         message:'',
173 212
         sub_button:[],
174 213
         media_id:'',
214
+        media_url:'',
175 215
       },
176 216
       menuType:0,
177 217
       currentPatient:-1,
@@ -229,6 +269,66 @@ export default {
229 269
         }
230 270
       }).catch(e=>{});
231 271
     },
272
+    openMediaBox:function(){
273
+      this.$refs.imageMaterialBox.open();
274
+    },
275
+    handleMediaSuccess:function(res, file) {
276
+      if (res.state==1) {
277
+        this.$message.success('上传成功');
278
+        this.currentMenu.media_url = 'http://img01.store.sogou.com/net/a/04/link?appid=100520029&url=' + res.data.media.media_url;
279
+        this.currentMenu.media_id =  res.data.media.media_id;
280
+      }else {
281
+        this.$message.error(res.msg);
282
+      }
283
+    },
284
+    beforeMediaUpload:function(file) {
285
+      var allow = {"image/bmp":1,"image/png":1,"image/jpeg":1,"image/jpg":1,"image/gif":1};
286
+      // const isJPG = file.type === 'image/jpeg';
287
+      const isImg = file.type in allow;
288
+      const isLt2M = file.size / 1024 / 1024 < 2;
289
+
290
+      if (!isImg) {
291
+        this.$message.error('上传图片只能是 bmp/png/jpeg/jpg/gif 格式!');
292
+      }
293
+      if (!isLt2M) {
294
+        this.$message.error('上传图片大小不能超过 2MB!');
295
+      }
296
+      return isImg && isLt2M;
297
+    },
298
+    deleteMenus:function(){
299
+      this.$confirm('删除后,公众号的菜单也将被删除', '删除提示', {
300
+        dangerouslyUseHTMLString:true,
301
+        confirmButtonText: '确定',
302
+        cancelButtonText: '取消',
303
+        type: 'warning'
304
+      }).then(() => {
305
+        DeleteMenu().then(response=>{
306
+          var res = response.data;
307
+          if (res.state==1) {
308
+            this.$message.success('删除成功');
309
+            this.currentMenu = {
310
+              type:'',
311
+              name:'',
312
+              url:'',
313
+              appid:'',
314
+              pagepath:'',
315
+              key:'',//key规则:V_[number]_click;VC_[number]_click
316
+              message:'',
317
+              sub_button:[],
318
+              media_id:'',
319
+              media_url:'',
320
+              big_type:0
321
+            };
322
+            this.currentPatient = -1;
323
+            this.currentChild = -1;
324
+            this.menus = {button:[]};
325
+          }else {
326
+            this.$message.error(res.msg);
327
+          }
328
+        }).catch(e=>{});
329
+      }).catch(() => {
330
+      });
331
+    },
232 332
     submitSave:function () {
233 333
         this.subload = true;
234 334
         var res = this.checkMenus();
@@ -309,6 +409,8 @@ export default {
309 409
               message:'',
310 410
               sub_button:[],
311 411
               media_id:'',
412
+              media_url:'',
413
+              big_type:0
312 414
             };
313 415
           }
314 416
         }
@@ -323,6 +425,7 @@ export default {
323 425
             this.menus = res.data.menus;
324 426
             for (const index in this.menus.button) {
325 427
               var button = this.menus.button[index];
428
+              this.menus.button[index]['big_type'] = typeof(button.type) !='undefined' && button.type ? this.setBigType(button.type):0;
326 429
               if(typeof(button.key) !='undefined' && button.key) {
327 430
                 var keys = button.key.split("_")
328 431
                 if (typeof(keys[1]) !='undefined') {
@@ -333,6 +436,7 @@ export default {
333 436
               if(typeof(button.sub_button) !='undefined' && button.sub_button) {
334 437
                 for (const chilid in button.sub_button) {
335 438
                   var cbutton = button.sub_button[chilid];
439
+                  this.menus.button[index].sub_button[chilid]['big_type'] = typeof(cbutton.type) !='undefined' && cbutton.type ? this.setBigType(cbutton.type):0;
336 440
                   if(typeof(cbutton.key) !='undefined' && cbutton.key) {
337 441
                     var keys = cbutton.key.split("_")
338 442
                     if (typeof(keys[1]) !='undefined') {
@@ -367,10 +471,29 @@ export default {
367 471
           break;
368 472
       }
369 473
     },
370
-    changeMenuType:function(value){
474
+    setBigType(type) {
475
+       var bitType = 0;
476
+       switch (this.currentMenu.type) {
477
+        case 'click':
478
+          bitType = 1;
479
+          break;
480
+        case 'media_id':
481
+          bitTypee = 2;
482
+          break;
483
+      }
484
+      return bitType;
485
+    },
486
+    changeBigType:function(value){
487
+      // this.currentMenu.big_type = value;
371 488
       switch (value) {
372 489
         case 1:
373
-          this.currentMenu.type = 'click';
490
+          if (this.currentMenu.big_type == 1 ) {
491
+            this.currentMenu.type = 'click';
492
+          } else if (this.currentMenu.big_type == 2) {
493
+            this.currentMenu.type = 'media_id';
494
+          } else {
495
+            this.currentMenu.type = 'click';
496
+          }
374 497
           break;
375 498
         case 2:
376 499
           this.currentMenu.type = 'view';
@@ -382,6 +505,14 @@ export default {
382 505
           break;
383 506
       }
384 507
     },
508
+    selectMenuType:function(type){
509
+      this.currentMenu.big_type = type;
510
+      if(type==1) {
511
+        this.currentMenu.type = 'click';
512
+      }else if(type==2) {
513
+        this.currentMenu.type = 'media_id';
514
+      }
515
+    },
385 516
     selectItem:function(mi, ni, node){
386 517
       this.currentPatient = mi;
387 518
       this.currentChild = ni;
@@ -395,6 +526,8 @@ export default {
395 526
         message:'',
396 527
         sub_button:[],
397 528
         media_id:'',
529
+        media_url:'',
530
+        big_type:0,
398 531
       };
399 532
       for (const key in node) {
400 533
         this.currentMenu[key] = node[key]; 
@@ -567,8 +700,10 @@ export default {
567 700
       }
568 701
     },  
569 702
     'currentMenu.type':function(){
703
+
570 704
       if (this.currentPatient>=0&&this.currentChild>=0) {
571 705
         this.menus.button[this.currentPatient].sub_button[this.currentChild].type = this.currentMenu.type;
706
+        this.menus.button[this.currentPatient].sub_button[this.currentChild].big_type = this.currentMenu.big_type;
572 707
         if (this.currentMenu.type == 'click' && this.currentMenu.key.length==0) {
573 708
           this.cclick += 1;
574 709
           var key = 'VC_' + this.cclick + "_click";
@@ -577,6 +712,7 @@ export default {
577 712
         }
578 713
       } else if (this.currentPatient>=0){
579 714
         this.menus.button[this.currentPatient].type = this.currentMenu.type;
715
+        this.menus.button[this.currentPatient].big_type = this.currentMenu.big_type;
580 716
         if (this.currentMenu.type == 'click' && this.currentMenu.key.length==0) {
581 717
           this.pclick += 1;
582 718
           var key = 'V_' + this.cclick + "_click";
@@ -609,6 +745,20 @@ export default {
609 745
       }
610 746
       this.CheckPagePathError();
611 747
     },  
748
+    'currentMenu.media_id':function(){
749
+      if (this.currentPatient>=0&&this.currentChild>=0) {
750
+        this.menus.button[this.currentPatient].sub_button[this.currentChild].media_id = this.currentMenu.media_id;
751
+      } else if (this.currentPatient>=0){
752
+        this.menus.button[this.currentPatient].media_id = this.currentMenu.media_id;
753
+      }
754
+    },
755
+    'currentMenu.media_url':function(){
756
+      if (this.currentPatient>=0&&this.currentChild>=0) {
757
+        this.menus.button[this.currentPatient].sub_button[this.currentChild].media_url = this.currentMenu.media_url;
758
+      } else if (this.currentPatient>=0){
759
+        this.menus.button[this.currentPatient].media_url = this.currentMenu.media_url;
760
+      }
761
+    },
612 762
     'currentMenu.message':function(){
613 763
       var len = $.trim(this.currentMenu.message+'').length; 
614 764
       var mt = 600-len;
@@ -630,7 +780,7 @@ export default {
630 780
 };
631 781
 </script>
632 782
 
633
-<style scoped>
783
+<style >
634 784
 #winxin-menus-box {
635 785
   font-size: 14px;
636 786
   color: #485b6d;
@@ -929,6 +1079,7 @@ export default {
929 1079
 }
930 1080
 #winxin-menus-box .menu_form_item .send_message_tit .send_nav {
931 1081
     width: 80px;
1082
+    display: inline-block;
932 1083
 }
933 1084
 #winxin-menus-box .menu_form_item .send_message_tit .ico_size {
934 1085
     width: 14px;
@@ -984,6 +1135,53 @@ export default {
984 1135
 #winxin-menus-box .menu_form__con .mitips {
985 1136
   display:block;left:84px;position:relative;margin-top:10px;color: #c0c8d4;
986 1137
 }
1138
+#winxin-menus-box .mediaID-item {
1139
+    text-align: center;
1140
+    padding: 10px;
1141
+    /* cursor: pointer; */
1142
+}
1143
+
1144
+#winxin-menus-box .mediaID-item .el-icon-news{
1145
+  
1146
+    cursor: pointer;
1147
+}
1148
+
1149
+/* #winxin-menus-box .mediaID-item:hover {
1150
+  background:#c0c8d4;
1151
+}  */
1152
+#winxin-menus-box .mediaID-item i {
1153
+  display: block;
1154
+    width: 80px;
1155
+    margin: 0 auto;
1156
+}
1157
+#winxin-menus-box .mediaID-item .el-icon-news {
1158
+  font-size: 80px;
1159
+}
1160
+#winxin-menus-box .mediaID-item .media-uploader .el-upload {
1161
+  border: 1px dashed #d9d9d9 !important;
1162
+  border-radius: 6px;
1163
+  cursor: pointer;
1164
+  position: relative;
1165
+  overflow: hidden;
1166
+  margin: 10px;
1167
+}
1168
+#winxin-menus-box .mediaID-item  .media-uploader .el-upload:hover {
1169
+  border-color: #409EFF;
1170
+}
1171
+#winxin-menus-box .mediaID-item .media-uploader-icon {
1172
+  font-size: 28px;
1173
+  color: #8c939d;
1174
+  width: 155px;
1175
+  height: 70px;
1176
+  line-height: 70px;
1177
+  text-align: center;
1178
+}
1179
+#winxin-menus-box .mediaID-item  .media {
1180
+  width: 155px;
1181
+  height: 70px;
1182
+  display: block;
1183
+}
1184
+
987 1185
 /*.app-container .cell.clearfix .time ul li {*/
988 1186
 /*float: left;*/
989 1187
 /*list-style: none;*/

+ 117 - 0
src/scrm_pages/weixinmp/subscribereply.vue ファイルの表示

@@ -0,0 +1,117 @@
1
+<template>
2
+  <div class="main-contain">
3
+    <div class="position">
4
+      <bread-crumb :crumbs="crumbs"></bread-crumb>
5
+    </div>
6
+    <div class="app-container" id="winxin-subscribe-replu-box">
7
+      <reply-nav activeName="subscribe"></reply-nav>
8
+      <el-form ref="form" :model="form" >
9
+        <el-form-item label="">
10
+          <el-input type="textarea" v-model="form.message_content" rows='5'></el-input>
11
+        </el-form-item>
12
+        <el-form-item>
13
+          <!-- <el-col :span="24" style="text-align: right;"> -->
14
+            <el-button type="primary" align="right" @click="saveReply">保存</el-button>
15
+          <!-- </el-col> -->
16
+        </el-form-item>
17
+      </el-form>
18
+    </div>
19
+  </div>
20
+</template>
21
+
22
+<script>
23
+import BreadCrumb from "../components/bread-crumb";
24
+import replyNav from "./components/replyNav";
25
+import {GetAuthorizationInfo} from "@/api/mpwechat/mpwechat";
26
+import {GetSubscribeRplay,SaveSubscribeRplay} from "@/api/mpwechat/mpreply";
27
+
28
+export default {
29
+  name: "subscribereply",
30
+  components: {
31
+    BreadCrumb,
32
+    replyNav,
33
+  },
34
+  data() {
35
+    return {
36
+      crumbs: [
37
+        { path: false, name: "系统设置" },
38
+        { path: false, name: "关注后回复" }
39
+      ],
40
+      initReply:false,
41
+      form:{
42
+        'message_content':'',
43
+      },
44
+    };
45
+  },
46
+  methods: {
47
+    GetAuthorizationInfo:function(){
48
+      GetAuthorizationInfo().then(response=>{
49
+        var res =  response.data;
50
+        if(res.state===1) {
51
+          if(res.data.authorization) {
52
+            this.authData = res.data.authorization;
53
+            if (this.authData.authorizer_status != 1) {
54
+              this.$message.error("公众号未授权");
55
+              this.$router.push({path:"/weixinmp/authorization"})
56
+              return false;
57
+            }else if (this.authData.authorizer_verify_type_info>=0 || this.authData.authorizer_service_type_info==2) {
58
+              this.initReply = true;
59
+            }
60
+          }else {
61
+              this.$message.error("公众号未授权");
62
+              this.$router.push({path:"/weixinmp/authorization"})
63
+          }
64
+        }else {
65
+          this.$message.error(res.msg);
66
+        }
67
+      }).catch(e=>{});
68
+    },
69
+    GetSubscribeRplay:function(){
70
+      GetSubscribeRplay().then(response=>{
71
+        var res = response.data;
72
+        if (res.state==1) {
73
+          if (res.data.message) {
74
+            this.form.message_content = res.data.message.message_content;
75
+          }
76
+        }else {
77
+          this.$message.error(res.msg);
78
+        }
79
+      }).catch(e=>{});
80
+    },
81
+    saveReply:function(){
82
+      SaveSubscribeRplay(this.form).then(response=>{
83
+        var res = response.data;
84
+        if (res.state === 1) {
85
+          this.$message.success('保存成功');
86
+        }else {
87
+          this.$message.error(res.msg);
88
+        }
89
+      }).catch(e=>{});
90
+    }
91
+  },
92
+  created() {
93
+    this.GetAuthorizationInfo();
94
+  },
95
+  computed:{
96
+  },
97
+  watch:{
98
+    'initReply':function(){
99
+      this.GetSubscribeRplay();
100
+    }
101
+  },
102
+};
103
+</script>
104
+
105
+<style scoped>
106
+/*.app-container .cell.clearfix .time ul li {*/
107
+/*float: left;*/
108
+/*list-style: none;*/
109
+/*cursor: pointer;*/
110
+/*padding: 6px 20px;*/
111
+/*color: #606266;*/
112
+/*border-radius: 4px;*/
113
+/*margin: 0 8px 0 0;*/
114
+/*font-size: 14px;*/
115
+/*text-align: center;*/
116
+/*}*/
117
+</style>

+ 44 - 0
src/styles/index.scss ファイルの表示

@@ -499,3 +499,47 @@ code {
499 499
   color: #C0C4CC;
500 500
   padding: 0 3px;
501 501
 }
502
+
503
+// 微网站-新增模块
504
+.feature {
505
+  ul {
506
+    border: 1px solid #eaeefb;
507
+    float: left;
508
+    width: 100%;
509
+    li {
510
+      width: 33.3%;
511
+      float: left;
512
+      text-align: center;
513
+      height: 120px;
514
+      color: #666;
515
+      font-size: 13px;
516
+      border-right: 1px solid #eee;
517
+      border-bottom: 1px solid #eee;
518
+      margin-right: -1px;
519
+      margin-bottom: -1px;
520
+      span {
521
+        vertical-align: middle;
522
+        display: flex;
523
+        flex-direction: column;
524
+        align-items: center;
525
+        justify-content: center;
526
+        height: 120px;
527
+        cursor: pointer;
528
+        img {
529
+          display: inline-block;
530
+          font-size: 32px;
531
+          margin-bottom: 15px;
532
+          color: #606266;
533
+          transition: color 0.15s linear;
534
+          vertical-align: middle;
535
+        }
536
+        .title {
537
+          display: inline-block;
538
+          padding: 0 3px;
539
+          height: 30px;
540
+          vertical-align: middle;
541
+        }
542
+      }
543
+    }
544
+  }
545
+}

+ 4 - 1
src/views/layout/Layout.vue ファイルの表示

@@ -8,6 +8,7 @@
8 8
     <div class="main-container">
9 9
       <tags-view></tags-view>
10 10
       <app-main></app-main>
11
+      <contact-box></contact-box>
11 12
     </div>
12 13
    </div>
13 14
   </div>
@@ -15,6 +16,7 @@
15 16
 
16 17
 <script>
17 18
 import { Navbar, Sidebar, AppMain, TagsView } from './components'
19
+import ContactBox from '@/scrm_pages/contactBox';
18 20
 import ResizeMixin from './mixin/ResizeHandler'
19 21
 
20 22
 export default {
@@ -23,7 +25,8 @@ export default {
23 25
     Navbar,
24 26
     Sidebar,
25 27
     AppMain,
26
-    TagsView
28
+    TagsView,
29
+    ContactBox,
27 30
   },
28 31
   mixins: [ResizeMixin],
29 32
   computed: {

+ 1 - 1
src/xt_permission.js ファイルの表示

@@ -5,7 +5,7 @@ import 'nprogress/nprogress.css'// progress bar style
5 5
 
6 6
 NProgress.configure({ showSpinner: false })// NProgress Configuration
7 7
 
8
-const loginWhiteList = ['/token/verify', '/401', '/404'] // 登录验证白名单
8
+const loginWhiteList = ['/token/verify', '/401', '/404', "/activity/preview"] // 登录验证白名单
9 9
 const permissionWhiteList = loginWhiteList.concat(['/']) // 权限验证白名单
10 10
 
11 11
 router.beforeEach((to, from, next) => {

File diff suppressed because it is too large
+ 8282 - 0
static/webim.js