浏览代码

聊天界面优化

wangwei 4 年之前
父节点
当前提交
2ab50e35e2
共有 9 个文件被更改,包括 1014 次插入50 次删除
  1. 11 0
      .env.dev
  2. 4 0
      build/webpack.base.conf.js
  3. 571 2
      package-lock.json
  4. 4 0
      package.json
  5. 97 48
      src/components/ChatFrame.vue
  6. 131 0
      src/components/Emoji.vue
  7. 143 0
      src/components/Entry.vue
  8. 42 0
      src/styles/index.scss
  9. 11 0
      src/styles/theme.scss

+ 11 - 0
.env.dev

@@ -0,0 +1,11 @@
+#本地开发环境
+NODE_ENV=development
+
+#公共组件使用cdn加速
+VUE_APP_CDN=false
+
+#后台地址
+VUE_APP_API_URL=http://localhost:3000
+
+#第三方组织架构地址
+VUE_APP_ORG_URL=

+ 4 - 0
build/webpack.base.conf.js

@@ -64,6 +64,10 @@ module.exports = {
           limit: 10000,
           name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
         }
+      },
+      {
+        test: /\.scss$/,
+        loader: 'sass-loader!style-loader!css-loader',
       }
     ]
   },

+ 571 - 2
package-lock.json

@@ -180,6 +180,12 @@
       "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
       "dev": true
     },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true
+    },
     "ansi-escapes": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
@@ -468,6 +474,16 @@
       "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
       "dev": true
     },
+    "are-we-there-yet": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+      "dev": true,
+      "requires": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^2.0.6"
+      }
+    },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -665,6 +681,12 @@
       "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
       "dev": true
     },
+    "async-foreach": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+      "dev": true
+    },
     "async-limiter": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
@@ -1826,6 +1848,15 @@
       "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
       "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
     },
+    "block-stream": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+      "dev": true,
+      "requires": {
+        "inherits": "~2.0.0"
+      }
+    },
     "bluebird": {
       "version": "3.7.2",
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -2495,12 +2526,81 @@
       "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==",
       "dev": true
     },
+    "cliui": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^3.1.0",
+        "strip-ansi": "^5.2.0",
+        "wrap-ansi": "^5.1.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        },
+        "wrap-ansi": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+          "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.0",
+            "string-width": "^3.0.0",
+            "strip-ansi": "^5.0.0"
+          }
+        }
+      }
+    },
     "clone": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
       "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
       "dev": true
     },
+    "clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "dev": true,
+      "requires": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+          "dev": true
+        }
+      }
+    },
     "co": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -2736,6 +2836,12 @@
       "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
       "dev": true
     },
+    "console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+      "dev": true
+    },
     "consolidate": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz",
@@ -3542,6 +3648,12 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
+    "delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+      "dev": true
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -3825,6 +3937,12 @@
         }
       }
     },
+    "emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
     "emojis-list": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
@@ -4766,6 +4884,18 @@
         "nan": "^2.12.1"
       }
     },
+    "fstream": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "inherits": "~2.0.0",
+        "mkdirp": ">=0.5 0",
+        "rimraf": "2"
+      }
+    },
     "ftp": {
       "version": "0.3.10",
       "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz",
@@ -4808,6 +4938,53 @@
       "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
       "dev": true
     },
+    "gauge": {
+      "version": "2.7.4",
+      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+      "dev": true,
+      "requires": {
+        "aproba": "^1.0.3",
+        "console-control-strings": "^1.0.0",
+        "has-unicode": "^2.0.0",
+        "object-assign": "^4.1.0",
+        "signal-exit": "^3.0.0",
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1",
+        "wide-align": "^1.1.0"
+      },
+      "dependencies": {
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        }
+      }
+    },
+    "gaze": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+      "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+      "dev": true,
+      "requires": {
+        "globule": "^1.0.0"
+      }
+    },
     "get-caller-file": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
@@ -4948,6 +5125,17 @@
         }
       }
     },
+    "globule": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
+      "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+      "dev": true,
+      "requires": {
+        "glob": "~7.1.1",
+        "lodash": "~4.17.10",
+        "minimatch": "~3.0.2"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.6",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@@ -5102,6 +5290,12 @@
       "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
       "dev": true
     },
+    "has-unicode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+      "dev": true
+    },
     "has-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -5771,6 +5965,12 @@
       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
       "dev": true
     },
+    "in-publish": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz",
+      "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==",
+      "dev": true
+    },
     "indent-string": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
@@ -6792,6 +6992,11 @@
         "nopt": "^5.0.0"
       }
     },
+    "js-cookie": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.0.tgz",
+      "integrity": "sha512-oUbbplKuH07/XX2YD2+Q+GMiPpnVXaRz8npE7suhBH9QEkJe2W7mQ6rwuMXHue3fpfcftQwzgyvGzIHyfCSngQ=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7742,8 +7947,7 @@
       "version": "2.14.2",
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
       "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "nanomatch": {
       "version": "1.2.13",
@@ -7874,6 +8078,43 @@
       "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
       "dev": true
     },
+    "node-gyp": {
+      "version": "3.8.0",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+      "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+      "dev": true,
+      "requires": {
+        "fstream": "^1.0.0",
+        "glob": "^7.0.3",
+        "graceful-fs": "^4.1.2",
+        "mkdirp": "^0.5.0",
+        "nopt": "2 || 3",
+        "npmlog": "0 || 1 || 2 || 3 || 4",
+        "osenv": "0",
+        "request": "^2.87.0",
+        "rimraf": "2",
+        "semver": "~5.3.0",
+        "tar": "^2.0.0",
+        "which": "1"
+      },
+      "dependencies": {
+        "nopt": {
+          "version": "3.0.6",
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+          "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+          "dev": true,
+          "requires": {
+            "abbrev": "1"
+          }
+        },
+        "semver": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+          "dev": true
+        }
+      }
+    },
     "node-int64": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -7938,6 +8179,68 @@
       "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
       "dev": true
     },
+    "node-sass": {
+      "version": "4.14.1",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
+      "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
+      "dev": true,
+      "requires": {
+        "async-foreach": "^0.1.3",
+        "chalk": "^1.1.1",
+        "cross-spawn": "^3.0.0",
+        "gaze": "^1.0.0",
+        "get-stdin": "^4.0.1",
+        "glob": "^7.0.3",
+        "in-publish": "^2.0.0",
+        "lodash": "^4.17.15",
+        "meow": "^3.7.0",
+        "mkdirp": "^0.5.1",
+        "nan": "^2.13.2",
+        "node-gyp": "^3.8.0",
+        "npmlog": "^4.0.0",
+        "request": "^2.88.0",
+        "sass-graph": "2.2.5",
+        "stdout-stream": "^1.4.0",
+        "true-case-path": "^1.0.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+          "dev": true
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "cross-spawn": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+          "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^4.0.1",
+            "which": "^1.2.9"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+          "dev": true
+        }
+      }
+    },
     "nopt": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -7997,6 +8300,18 @@
         "path-key": "^2.0.0"
       }
     },
+    "npmlog": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+      "dev": true,
+      "requires": {
+        "are-we-there-yet": "~1.1.2",
+        "console-control-strings": "~1.1.0",
+        "gauge": "~2.7.3",
+        "set-blocking": "~2.0.0"
+      }
+    },
     "nth-check": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
@@ -8924,6 +9239,16 @@
       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
       "dev": true
     },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.0.0"
+      }
+    },
     "p-finally": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -12286,6 +12611,168 @@
         }
       }
     },
+    "sass-graph": {
+      "version": "2.2.5",
+      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz",
+      "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.0.0",
+        "lodash": "^4.0.0",
+        "scss-tokenizer": "^0.2.3",
+        "yargs": "^13.3.2"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
+        },
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "^3.0.0"
+          }
+        },
+        "get-caller-file": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+          "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+          "dev": true
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "^3.0.0",
+            "path-exists": "^3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "^2.0.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        },
+        "y18n": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+          "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+          "dev": true
+        },
+        "yargs": {
+          "version": "13.3.2",
+          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+          "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+          "dev": true,
+          "requires": {
+            "cliui": "^5.0.0",
+            "find-up": "^3.0.0",
+            "get-caller-file": "^2.0.1",
+            "require-directory": "^2.1.1",
+            "require-main-filename": "^2.0.0",
+            "set-blocking": "^2.0.0",
+            "string-width": "^3.0.0",
+            "which-module": "^2.0.0",
+            "y18n": "^4.0.0",
+            "yargs-parser": "^13.1.2"
+          }
+        },
+        "yargs-parser": {
+          "version": "13.1.2",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+          "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
+        }
+      }
+    },
+    "sass-loader": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.3.1.tgz",
+      "integrity": "sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA==",
+      "dev": true,
+      "requires": {
+        "clone-deep": "^4.0.1",
+        "loader-utils": "^1.0.1",
+        "neo-async": "^2.5.0",
+        "pify": "^4.0.1",
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "4.0.1",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+          "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+          "dev": true
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
     "sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@@ -12302,6 +12789,27 @@
         "ajv-keywords": "^3.1.0"
       }
     },
+    "scss-tokenizer": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+      "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+      "dev": true,
+      "requires": {
+        "js-base64": "^2.1.8",
+        "source-map": "^0.4.2"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
     "select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -12468,6 +12976,23 @@
         "safe-buffer": "^5.0.1"
       }
     },
+    "shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "dev": true,
+      "requires": {
+        "kind-of": "^6.0.2"
+      },
+      "dependencies": {
+        "kind-of": {
+          "version": "6.0.3",
+          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+          "dev": true
+        }
+      }
+    },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -12986,6 +13511,15 @@
       "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
       "dev": true
     },
+    "stdout-stream": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
+      "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
+      "dev": true,
+      "requires": {
+        "readable-stream": "^2.0.1"
+      }
+    },
     "stealthy-require": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
@@ -13156,6 +13690,12 @@
       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
       "dev": true
     },
+    "style-loader": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.2.1.tgz",
+      "integrity": "sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg==",
+      "dev": true
+    },
     "stylehacks": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
@@ -13248,6 +13788,17 @@
       "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==",
       "dev": true
     },
+    "tar": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+      "dev": true,
+      "requires": {
+        "block-stream": "*",
+        "fstream": "^1.0.12",
+        "inherits": "2"
+      }
+    },
     "tcp-port-used": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz",
@@ -13433,6 +13984,15 @@
       "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
       "dev": true
     },
+    "true-case-path": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
+      "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.2"
+      }
+    },
     "tryer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
@@ -15308,6 +15868,15 @@
       "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
       "dev": true
     },
+    "wide-align": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.2 || 2"
+      }
+    },
     "word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",

+ 4 - 0
package.json

@@ -15,6 +15,7 @@
   "dependencies": {
     "axios": "^0.21.1",
     "element-ui": "^2.15.3",
+    "js-cookie": "^3.0.0",
     "socket.io-client": "^4.1.3",
     "socketio-file-upload": "^0.7.3",
     "v-contextmenu": "^3.0.0",
@@ -51,6 +52,7 @@
     "jest-serializer-vue": "^0.3.0",
     "nightwatch": "^0.9.12",
     "node-notifier": "^5.1.2",
+    "node-sass": "^4.14.1",
     "optimize-css-assets-webpack-plugin": "^3.2.0",
     "ora": "^1.2.0",
     "portfinder": "^1.0.13",
@@ -58,9 +60,11 @@
     "postcss-loader": "^2.0.8",
     "postcss-url": "^7.2.1",
     "rimraf": "^2.6.0",
+    "sass-loader": "^7.3.1",
     "selenium-server": "^3.0.1",
     "semver": "^5.3.0",
     "shelljs": "^0.7.6",
+    "style-loader": "^3.2.1",
     "uglifyjs-webpack-plugin": "^1.1.1",
     "url-loader": "^0.5.8",
     "vue-jest": "^1.0.2",

+ 97 - 48
src/components/ChatFrame.vue

@@ -60,20 +60,32 @@
               </div>
             </div>
             <div v-if="item.id === self.id" class="record-item send-record">
-              <!-- <div class="user">5asfdasdf</div> -->
-              <!-- <span>{{ item.msg }}</span> -->
               <!-- 链接 -->
-              <!-- <a class="message-content-text" href="https://img2.baidu.com/it/u=1605987499,4009355285&fm=26&fmt=auto&gp=0.jpg" target="_blank">https://img2.baidu.com/it/u=1605987499,4009355285&fm=26&fmt=auto&gp=0.jpg</a> -->
+              <a class="message-content-text" v-if="_isUrl(item.msg)" :href="item.msg" target="_blank">
+                {{ item.msg }}
+              </a>
               <!-- 文本 -->
-              <!-- <div class="message-content-text" v-text="_parseText(item.msg)"></div> -->
+              <div class="message-content-text" v-if="item.messageType === 'text'" v-text="_parseText(item.msg)"></div>
               <!-- 图片 -->
-              <!-- <div class="message-content-image" :style="getImageStyle('https://img2.baidu.com/it/u=1605987499,4009355285&fm=26&fmt=auto&gp=0.jpg')">
+              <div class="message-content-image" v-if="item.messageType === 'image'" :style="getImageStyle(item.msg)">
                 <viewer style="display: flex; align-items: center">
-                  <img src="https://img2.baidu.com/it/u=1605987499,4009355285&fm=26&fmt=auto&gp=0.jpg" alt="" />
+                  <img :src="baseUrl + item.msg" alt="" />
                 </viewer>
+              </div>
+              <!-- 附件类型消息 -->
+              <!-- <div class="message-content-file" v-else-if="item.messageType === 'file'" @click="download(item)">
+                <img class="message-content-icon" :src="getFileIcon(item)" alt="" />
+                <div class="message-content-detail">
+                  <div class="file-name">
+                    {{ getFileName(item).name }}
+                  </div>
+                  <div class="file-size">
+                    {{ getFileName(item).size }}
+                  </div>
+                </div>
               </div> -->
               <!-- 视频格式文件 -->
-              <div class="message-content-image">
+              <div class="message-content-image" v-if="item.messageType === 'video'">
                 <video style="width: 255px" src="https://media.w3.org/2010/05/sintel/trailer.mp4" controls="controls">您的浏览器不支持 video 标签。</video>
               </div>
               <!-- <div class="avatar">
@@ -89,6 +101,14 @@
       <div class="send-msg-wrap">
         <div class="send-header">
           <div class="tools" style="margin:10px">
+            <el-popover
+              placement="bottom"
+              width="200"
+              trigger="click">
+                <Emoji @addEmoji="addEmoji" />
+             <i slot="reference">😃</i>
+
+            </el-popover>
             <el-upload
               ref="upload"
               class="file-uploader"
@@ -136,17 +156,23 @@
 <script>
 import { addCookie, getCookie } from "@/utils/setCookie.js";
 import { isUrl, parseText, processReturn } from "@/utils/common";
+import Emoji from './Emoji.vue';
 export default {
   name: "ChatFrame",
   props: ["selected", "tab"],
+  components: {
+    Emoji,
+  },
   data() {
     return {
-      msg: "",
+      baseUrl: 'http://192.168.100.8:3000/',
+      msg: '',
       friend_record: [],
       friend_record_list: [],
       room_record: {},
       room_record_list: [],
       self: null,
+      messageType: '',
       uploadProgress: false
     };
   },
@@ -173,16 +199,7 @@ export default {
     },
     beforeUpload(file) {
       console.log(`file`, file);
-      // const isJPG = file.type === "image/jpeg";
-      // const isLt2M = file.size / 1024 / 1024 < 2;
-
-      // if (!isJPG) {
-      //   this.$message.error("上传头像图片只能是 JPG 格式!");
-      // }
-      // if (!isLt2M) {
-      //   this.$message.error("上传头像图片大小不能超过 2MB!");
-      // }
-      // return isJPG && isLt2M;
+      console.log(`file.type`, file.type)
       this.uploadProgress = true;
       this.fileData = file;
       //  调用函数分割文件 我这里是分割成不超过20M的文件快
@@ -193,16 +210,22 @@ export default {
       // })
       let fd = new FormData();
       fd.append("filename", file);
-      // fd.append('project_id', this.project_id)
-      // fd.append('version_id', this.version_id)
-      console.log(`fd`, fd);
       this.$http.post("/api/upload/", fd).then(
         res => {
+          if (file.type === "image/jpeg"|| file.type === "image/png" || file.type === "image/gif") {
+            this.messageType = 'image'
+            this.sendMsg(null, res.data.data)
+            console.log('========is image =====')
+          } else {
+            this.messageType = 'file'
+            console.log('=========not image=========')
+          }
           // this.importDataBtnText='导入成功';
           console.log(`res1111`, res);
           console.log("======success====");
         },
         res => {
+          this.$message.error('文件发送失败')
           console.log("===========shibai====");
           //  this.importDataBtnText='导入失败';
           console.log(res);
@@ -264,41 +287,54 @@ export default {
       }
       return fileChunkList;
     },
-    /**
-   * 根据图片url设置图片框宽高, 注意是图片框
-   */
-  getImageStyle(src) {
-    const arr = src.split('$');
-    let width = Number(arr[2]);
-    let height = Number(arr[3]);
-    if (this.mobile) {
-      // 如果是移动端,图片最大宽度138, 返回值加12是因为设置的是图片框的宽高要加入padding值
-      if (width > 138) {
-        height = (height * 138) / width;
-        width = 138;
-        return {
-          width: `${width + 12}px`,
-          height: `${height + 12}px`,
-        };
+      /**
+     * 根据图片url设置图片框宽高, 注意是图片框
+     */
+    getImageStyle(src) {
+      const arr = src.split('$');
+      let width = Number(arr[2]);
+      let height = Number(arr[3]);
+      if (this.mobile) {
+        // 如果是移动端,图片最大宽度138, 返回值加12是因为设置的是图片框的宽高要加入padding值
+        if (width > 138) {
+          height = (height * 138) / width;
+          width = 138;
+          return {
+            width: `${width + 12}px`,
+            height: `${height + 12}px`,
+          };
+        }
       }
-    }
-    return {
-      width: `${width + 12}px`,
-      height: `${height + 12}px`,
-    };
-  },
+      return {
+        width: `${width + 12}px`,
+        height: `${height + 12}px`,
+      };
+    },
+
+      /**
+     * 是否URL
+     * @params text
+     */
+    _isUrl(text) {
+      return isUrl(text);
+    },
 
     upload() {},
 
-    sendMsg(e) {
-      if (e.which === 13) {
+    // 添加表情
+    addEmoji(emoji) {
+      console.log(`emoji`, emoji)
+      this.msg = this.msg + emoji
+    },
+    sendMsg(e, fileurl) {
+      if (e&&e.which === 13) {
         console.log(`e.which`, e.which);
         e.cancelBubble = true;
         e.preventDefault();
         e.stopPropagation();
       }
 
-      if (this.msg.trim() === "") {
+      if (this.msg.trim() === "" && !fileurl) {
         this.msg = "";
         return;
       }
@@ -306,12 +342,25 @@ export default {
         this.self = JSON.parse(localStorage.getItem("self"));
       }
       console.log(`this.self`, this.self);
+      if (!this.messageType) {
+        this.messageType = 'text';
+      }
       const msgInfo = {
-        id: this.$socket.id,
+        ...this.self,
         msg: this.msg,
-        nickname: this.self.nickname
+        messageType: this.messageType,
       };
+      if (fileurl) {
+        msgInfo.msg = fileurl
+      }
+      console.log(`msgInfo`, msgInfo)
+      console.log(`this.selected.id`, this.selected)
+      if (!this.selected) {
+        this.$message.error('请先选择聊天对象')
+        return;
+      }
       this.msg = ""; // 输入enter后置空
+      this.messageType = '';
       if (this.tab === "friends") {
         msgInfo.toid = this.selected.id;
         this.$socket.emit("private message", this.selected.id, msgInfo);

+ 131 - 0
src/components/Emoji.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="emoji-content">
+    <div class="emoji-content-item">
+      <span @click="addEmoji('😃')">😃</span>
+      <span @click="addEmoji('😁')">😁</span>
+      <span @click="addEmoji('😂')">😂</span>
+      <span @click="addEmoji('😄')">😄</span>
+      <span @click="addEmoji('😅')">😅</span>
+      <span @click="addEmoji('😆')">😆</span>
+      <span @click="addEmoji('😇')">😇</span>
+      <span @click="addEmoji('😈')">😈</span>
+      <span @click="addEmoji('😉')">😉</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('😊')">😊</span>
+      <span @click="addEmoji('😋')">😋</span>
+      <span @click="addEmoji('😌')">😌</span>
+      <span @click="addEmoji('😍')">😍</span>
+      <span @click="addEmoji('😎')">😎</span>
+      <span @click="addEmoji('😏')">😏</span>
+      <span @click="addEmoji('😐')">😐</span>
+      <span @click="addEmoji('😒')">😒</span>
+      <span @click="addEmoji('😓')">😓</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('❓')">❓</span>
+      <span @click="addEmoji('😕')">😕</span>
+      <span @click="addEmoji('😖')">😖</span>
+      <span @click="addEmoji('😗')">😗</span>
+      <span @click="addEmoji('😘')">😘</span>
+      <span @click="addEmoji('😙')">😙</span>
+      <span @click="addEmoji('😚')">😚</span>
+      <span @click="addEmoji('😜')">😜</span>
+      <span @click="addEmoji('😝')">😝</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('😞')">😞</span>
+      <span @click="addEmoji('😟')">😟</span>
+      <span @click="addEmoji('😠')">😠</span>
+      <span @click="addEmoji('😡')">😡</span>
+      <span @click="addEmoji('😢')">😢</span>
+      <span @click="addEmoji('😣')">😣</span>
+      <span @click="addEmoji('😤')">😤</span>
+      <span @click="addEmoji('😥')">😥</span>
+      <span @click="addEmoji('😦')">😦</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('😨')">😨</span>
+      <span @click="addEmoji('😩')">😩</span>
+      <span @click="addEmoji('😪')">😪</span>
+      <span @click="addEmoji('😫')">😫</span>
+      <span @click="addEmoji('😬')">😬</span>
+      <span @click="addEmoji('😭')">😭</span>
+      <span @click="addEmoji('😮')">😮</span>
+      <span @click="addEmoji('😯')">😯</span>
+      <span @click="addEmoji('😰')">😰</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('😲')">😲</span>
+      <span @click="addEmoji('😳')">😳</span>
+      <span @click="addEmoji('😴')">😴</span>
+      <span @click="addEmoji('😵')">😵</span>
+      <span @click="addEmoji('🧐')">🧐</span>
+      <span @click="addEmoji('😷')">😷</span>
+      <span @click="addEmoji('🙁')">🙁</span>
+      <span @click="addEmoji('🙂')">🙂</span>
+      <span @click="addEmoji('🙃')">🙃</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('🤐')">🤐</span>
+      <span @click="addEmoji('🤑')">🤑</span>
+      <span @click="addEmoji('🤒')">🤒</span>
+      <span @click="addEmoji('🤓')">🤓</span>
+      <span @click="addEmoji('🤔')">🤔</span>
+      <span @click="addEmoji('🤕')">🤕</span>
+      <span @click="addEmoji('🤠')">🤠</span>
+      <span @click="addEmoji('🤡')">🤡</span>
+      <span @click="addEmoji('🤢')">🤢</span>
+    </div>
+    <div class="emoji-content-item">
+      <span @click="addEmoji('🤤')">🤤</span>
+      <span @click="addEmoji('🤥')">🤥</span>
+      <span @click="addEmoji('🤧')">🤧</span>
+      <span @click="addEmoji('🤨')">🤨</span>
+      <span @click="addEmoji('🤩')">🤩</span>
+      <span @click="addEmoji('🤪')">🤪</span>
+      <span @click="addEmoji('🤫')">🤫</span>
+      <span @click="addEmoji('🤬')">🤬</span>
+      <span @click="addEmoji('🤭')">🤭</span>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Emoji',
+  data() {
+    return {};
+  },
+  methods: {
+    addEmoji(emoji) {
+      this.$emit('addEmoji', emoji);
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.emoji-content {
+  color: #000;
+  font-size: 20px;
+  width: 250px;
+  /* 禁止文字被鼠标选中 */
+  moz-user-select: -moz-none;
+  -moz-user-select: none;
+  -o-user-select: none;
+  -khtml-user-select: none;
+  -webkit-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+  
+  .emoji-content-item {
+    display: flex;
+    justify-content: space-evenly;
+    flex-wrap: nowrap;
+  }
+  .emoji-content-item span {
+      cursor: pointer;
+  }
+</style>

+ 143 - 0
src/components/Entry.vue

@@ -0,0 +1,143 @@
+<template>
+  <div class="message-input" v-if="activeRoom">
+    <div class="message-tool">
+      <a-popover placement="topLeft" trigger="click" class="message-popver">
+        <template slot="content">
+          <emoji @addEmoji="addEmoji"></emoji>
+        </template>
+        <div class="message-tool-item">
+          <div class="messagte-tool-icon" v-if="mobile">😃</div>
+          <a-icon v-else type="smile" />
+        </div>
+      </a-popover>
+      <div class="message-tool-item" v-if="!mobile">
+        <a-upload :show-upload-list="false" :before-upload="beforeFileUpload">
+          <a-icon type="folder-open" />
+        </a-upload>
+      </div>
+    </div>
+
+    <a-input
+      v-if="mobile"
+      autocomplete="off"
+      type="text"
+      autoFocus
+      placeholder="say hello..."
+      v-model="text"
+      ref="input"
+      style="color: #000"
+      @pressEnter="throttle(preSendMessage)"
+    />
+    <a-textarea
+      v-else
+      autocomplete="off"
+      v-model="text"
+      ref="input"
+      autoFocus
+      style="color: #000"
+      @pressEnter="
+        (e) => {
+          // 此处拦截enter后光标换行
+          e.preventDefault();
+          throttle(preSendMessage);
+        }
+      "
+    />
+    <img class="message-input-button" v-if="mobile" @click="throttle(preSendMessage)" src="~@/assets/send.png" alt="" />
+  </div>
+</template>
+
+<script>
+import Emoji from './Emoji.vue';
+export default {
+  name: 'Entry',
+  components: {
+    Emoji,
+  },
+  data() {
+    return {
+    };
+  },
+  computed: {
+  },
+  watch: {
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@import '@/styles/theme';
+
+.message-input {
+  display: flex;
+  // border-top: 1px solid #d1d1d1;
+  background: $message-bg-color;
+  flex-wrap: nowrap;
+  width: 100%;
+  textarea {
+    border-left: none !important;
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+    border-bottom-left-radius: 0;
+  }
+  .message-input-button {
+    width: 30px;
+    cursor: pointer;
+    position: absolute;
+    right: 10px;
+    top: 4px;
+  }
+}
+//输入框样式
+.ant-input {
+  padding: 50px 10px 0 20px !important;
+  height: 180px;
+  border-top: 1px solid #d6d6d6;
+  background: $message-bg-color;
+  border-left: none;
+  border-right: none;
+  border-bottom: none;
+  border-radius: 0;
+  &:focus {
+    box-shadow: none !important;
+  }
+}
+
+// 移动端样式
+@media screen and (max-width: 768px) {
+  .ant-input {
+    padding: 0 50px 0 35px !important;
+    height: 40px;
+  }
+  .message-tool {
+    right: unset !important;
+    padding: 0 0 0 10px !important;
+    .message-tool-item {
+      .anticon {
+        margin-right: 0 !important;
+      }
+    }
+  }
+}
+
+// 消息工具样式
+.message-tool {
+  position: absolute;
+  left: 0;
+  right: 0;
+  display: flex;
+  align-items: center;
+  height: 50px;
+  line-height: 42px;
+  font-size: 22px;
+  padding: 0 20px;
+  z-index: 99;
+  color: #828282;
+  .message-tool-item {
+    .anticon {
+      margin-right: 25px;
+    }
+  }
+}
+</style>

+ 42 - 0
src/styles/index.scss

@@ -0,0 +1,42 @@
+@import './coverAntd.scss';
+
+.message {
+  // 滚动条样式
+  ::-webkit-scrollbar-track-piece {
+    background-color: rgba(54, 50, 50, 0.4);
+  }
+  ::-webkit-scrollbar {
+    width: 5px;
+    height: 10px;
+    display: block;
+  }
+  ::-webkit-scrollbar-thumb {
+    height: 50px;
+    background-color: rgba(9, 185, 85, 0.3);
+    outline-offset: -2px;
+    filter: alpha(opacity = 50);
+    -moz-opacity: 0.5;
+    opacity: 0.5;
+    border-radius: 4px;
+  }
+  ::-webkit-scrollbar-thumb:hover {
+    background-color: rgba(9, 185, 85, 0.5);
+  }
+}  
+::-webkit-scrollbar {
+  display: none;
+}
+
+// * {
+//   // 禁止文字被鼠标选中
+//   moz-user-select: -moz-none;
+//   -moz-user-select: none;
+//   -o-user-select:none;
+//   -webkit-user-select:none;
+//   -ms-user-select:none;
+//   user-select:none;
+// }
+
+.viewer-button {
+  background-color: rgba(231, 226, 226, 0.6)!important;
+}

+ 11 - 0
src/styles/theme.scss

@@ -0,0 +1,11 @@
+/*
+ * @file: 主题配色
+ * @author: BoBo
+ * @copyright: BoBo
+ * @Date: 2020-11-26 14:21:25
+ */
+
+// 主题色
+$primary-color: #09b955;
+$room-bg-color: #fbfbfb;
+$message-bg-color:#f1f1f1;