From 529c60970749537d6b42797b700588b08512e4dc Mon Sep 17 00:00:00 2001 From: CW Deng Date: Thu, 26 Apr 2018 04:40:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20html=20loader=EF=BC=8C?= =?UTF-8?q?=E9=80=82=E9=85=8D=20Tpl.html=20=E5=90=8E=E7=BC=80=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20alias=20=E4=BD=9C=E4=B8=BA=20require=20=E6=A0=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=20=E6=96=B0=E5=A2=9E=20getArticleJson=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20=E6=96=B0=E5=A2=9E=20popupList=20=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20utils.sameProtocol=20=E5=85=BC=E5=AE=B9=E5=8F=AA?= =?UTF-8?q?=E6=9C=89=E6=A0=B9=E8=B7=AF=E5=BE=84=E7=9A=84=E6=83=85=E5=86=B5?= =?UTF-8?q?=20css=20=E5=85=BC=E5=AE=B9=E6=96=B0=E6=97=A7=E4=B8=A4=E7=89=88?= =?UTF-8?q?=20tenantInfo=20=E6=96=B0=E7=89=88=20tenantInfo=20=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/js/app/modules/apiHelper.js | 43 ++-- src/js/app/modules/chat.js | 31 ++- src/js/app/modules/tenantInfo/index.js | 195 ++++++++++++++++++ .../modules/tenantInfo/template/indexTpl.html | 6 + src/js/app/modules/uikit/popupList.js | 50 +++++ .../modules/uikit/template/popupListTpl.html | 7 + src/js/common/utils.js | 5 +- src/js/transfer/api.js | 15 +- src/scss/body.scss | 70 ++++++- src/scss/global.scss | 7 + webpack.config.js | 10 + 11 files changed, 410 insertions(+), 29 deletions(-) create mode 100644 src/js/app/modules/tenantInfo/index.js create mode 100644 src/js/app/modules/tenantInfo/template/indexTpl.html create mode 100644 src/js/app/modules/uikit/popupList.js create mode 100644 src/js/app/modules/uikit/template/popupListTpl.html diff --git a/src/js/app/modules/apiHelper.js b/src/js/app/modules/apiHelper.js index e7fcd508d..b20a8dbf7 100644 --- a/src/js/app/modules/apiHelper.js +++ b/src/js/app/modules/apiHelper.js @@ -175,8 +175,6 @@ function getConfig(configId){ }, function(err){ reject(err); }); - - }); } function getProjectId(){ @@ -1112,12 +1110,12 @@ function createWechatImUser(openId){ emajax({ url: "/v1/webimplugin/visitors/wechat/" + [ - config.tenantId, - config.orgName, - config.appName, - config.toUser, - openId, - ].join("_") + config.tenantId, + config.orgName, + config.appName, + config.toUser, + openId, + ].join("_") + "?tenantId=" + config.tenantId, data: { orgName: config.orgName, @@ -1204,12 +1202,12 @@ function updateCustomerInfo(data){ ]).then(function(result){ var visitorId = result[0]; var token = result[1]; - data["visitorId"] = visitorId; - data["tenantId"] = config.tenantId; - data["orgName"] = config.orgName; - data["appName"] = config.appName; - data["userName"] = config.user.username; - data["token"] = token; + data.visitorId = visitorId; + data.tenantId = config.tenantId; + data.orgName = config.orgName; + data.appName = config.appName; + data.userName = config.user.username; + data.token = token; api("updateCustomerInfo", data, function(msg){ // resolve(msg.data); }, function(err){ @@ -1219,6 +1217,22 @@ function updateCustomerInfo(data){ }); } +function getArticleJson(data){ + return new Promise(function(resolve, reject){ + api("getArticleJson", { + media_id: data.media_id, + tenantId: config.tenantId, + userId: config.user.userName, + orgName: config.orgName, + appName: config.appName, + token: 0, + }, function(ret){ + var articles = utils.getDataByPath(ret, "data.entity.articles"); + resolve(articles); + }); + }); +} + module.exports = { getCurrentServiceSession: getCurrentServiceSession, getToken: getToken, @@ -1267,6 +1281,7 @@ module.exports = { getCustomEmojiFiles: getCustomEmojiFiles, getSatisfactionTipWord: getSatisfactionTipWord, updateCustomerInfo: updateCustomerInfo, + getArticleJson: getArticleJson, initApiTransfer: initApiTransfer, api: api, diff --git a/src/js/app/modules/chat.js b/src/js/app/modules/chat.js index f1fde238b..8490b257a 100644 --- a/src/js/app/modules/chat.js +++ b/src/js/app/modules/chat.js @@ -21,6 +21,8 @@ var initGetGreetings = require("./chat/initGetGreetings"); var initAgentNicknameUpdate = require("./chat/initAgentNicknameUpdate"); var emojiPanel = require("./chat/emojiPanel"); var extendMessageSender = require("./chat/extendMessageSender"); +var TenantInfo = require("@/app/modules/tenantInfo/index"); +var tenantInfo; var isMessageChannelReady; var config; @@ -165,21 +167,28 @@ function _setLogo(){ function _setNotice(){ var noticeContent = document.querySelector(".em-widget-tip .content"); var noticeCloseBtn = document.querySelector(".em-widget-tip .tip-close"); - apiHelper.getNotice().then(function(notice){ - if(!notice.enabled) return; var slogan = notice.content; + if(!notice.enabled) return; - // 设置信息栏内容 - noticeContent.innerHTML = WebIM.utils.parseLink(slogan); // 显示信息栏 utils.addClass(doms.imChat, "has-tip"); - // 隐藏信息栏按钮 - utils.on(noticeCloseBtn, utils.click, function(){ - // 隐藏信息栏 - utils.removeClass(doms.imChat, "has-tip"); - }); + // 新配置就走新 tenantInfo + if(config.isWebChannelConfig){ + tenantInfo = new TenantInfo(); + } + else{ + (function(){ + // 设置信息栏内容 + noticeContent.innerHTML = WebIM.utils.parseLink(slogan); + // 隐藏信息栏按钮 + utils.on(noticeCloseBtn, utils.click, function(){ + // 隐藏信息栏 + utils.removeClass(doms.imChat, "has-tip"); + }); + })(); + } }); } @@ -423,6 +432,7 @@ function _bindEvents(){ var iframe = articleContainer.querySelector("iframe"); iframe && utils.removeDom(iframe); articleContainer.style.display = "none"; + tenantInfo && tenantInfo.show(); }); utils.live(".article-link", "click", function(e){ @@ -444,6 +454,9 @@ function _bindEvents(){ else{ window.open(url); } + + // 隐藏整个 tenantInfo + tenantInfo && tenantInfo.hide(); }); var messagePredict = _.throttle(function(msg){ diff --git a/src/js/app/modules/tenantInfo/index.js b/src/js/app/modules/tenantInfo/index.js new file mode 100644 index 000000000..de2277cf0 --- /dev/null +++ b/src/js/app/modules/tenantInfo/index.js @@ -0,0 +1,195 @@ +var apiHelper = require("@/app/modules/apiHelper"); +var PopupList = require("@/app/modules/uikit/popupList"); +var utils = require("@/common/utils"); +var channel = require("@/app/modules/channel"); +var tpl = require("./template/indexTpl.html"); + +module.exports = function(){ + // 二级菜单实例 + var menuInsArr = []; + var menuArr = []; + var container = document.querySelector(".em-widget-tip"); + container.innerHTML = ""; + utils.addClass(container, "new"); + + apiHelper.getNotice() + .then(function(notice){ + if(!notice.enabled) return; + + + + // test + // notice.content = [ + // { + // name: "菜单", + // sub_button: [ + // { + // type: "view", + // name: "搜索2666", + // url: "http://www.soso.com/" + // } + // ] + // }, + // { + // name: "222", + // sub_button: [ + // { + // type: "media_id", + // name: "111", + // media_id: "75cffa4b-e462-40e8-a517-0ff807db29a6" + // }, + // { + // type: "media_id", + // name: "香格里拉", + // media_id: "4150c891-9917-4482-909c-ab7c9954110a" + // } + // ] + // }, + // { + // type: "media_id", + // name: "333", + // media_id: "75cffa4b-e462-40e8-a517-0ff807db29a6" + // } + // ]; + + + + + menuArr = notice.content; + container.innerHTML = _.template(tpl)({ + menu: menuArr, + }); + createMenu(); + utils.live(".tip-btn", "click", onMenuClick, container); + }); + + // 菜单点击 + function onMenuClick(e){ + var menuId; + var menuDat; + var target = e.srcElement || e.target; + var targetBounding; + if(utils.hasClass(target.parentNode, "tip-btn")){ + target = target.parentNode; + } + menuId = target.getAttribute("menuId"); + menuDat = menuArr[menuId]; + + targetBounding = target.getBoundingClientRect(); + handleMenuClick(menuDat, menuId, { + top: targetBounding.top + 48, + left: targetBounding.left + (target.clientWidth * 0.1), + width: target.clientWidth * 0.8, + }); + // ie8 + // 使得 popupList 可以自动关闭 + e.stopPropagation(); + return false; + } + + function handleMenuClick(menuDat, menuId, pos){ + // 有子菜单 + if(menuDat.sub_button){ + popupList(menuId, pos || { + left: 0, + top: 0, + width: 0, + }); + } + // 无子菜单 + else{ + hideAllSubMenu(); + fireMsg(menuDat); + } + } + + function fireMsg(dat){ + switch(dat.type){ + // 发送 article + case "media_id": + fireArticle(dat); + break; + // 发送 url + case "view": + fireUrl(dat); + break; + // 发送 text + case "txt": + fireText(dat); + break; + default: + break; + } + } + + function fireArticle(menuDat){ + apiHelper.getArticleJson({ + media_id: menuDat.media_id + }).then(function(articles){ + articles = _.map(articles, function(article){ + return { + title: article.title, + digest: article.digest, + description: article.digest, + // url: "/v1/webimplugin/tenants/" + article.tenantId + "/robot/article/html/" + article.articleId, + url: "/v1/Tenants/" + article.tenantId + "/robot/article/html/" + article.articleId, + thumbUrl: "/v1/Tenant/" + article.tenantId + "/MediaFiles/" + article.thumb_media_id, + picurl: "/v1/Tenant/" + article.tenantId + "/MediaFiles/" + article.thumb_media_id, + prop: article.prop, + }; + }); + channel.handleMessage( + { + ext: { + msgtype: { + articles: articles, + } + }, + }, + { + type: "article", + noPrompt: true + } + ); + }); + } + + function fireText(menuDat){ + + } + + function fireUrl(menuDat){ + + } + + // 每个 btn 创建一个菜单 + function createMenu(){ + _.each(menuArr, function(menuDat, menuId){ + menuInsArr[menuId] = new PopupList({ + items: menuDat.sub_button, + reportClick: handleMenuClick, + }); + }); + } + + // 弹出菜单 + function popupList(menuId, pos){ + hideAllSubMenu(); + menuInsArr[menuId].show(pos); + } + + function hideAllSubMenu(){ + _.each(menuInsArr, function(menuIns){ + menuIns.hide(); + }); + } + + return { + show: function(){ + container.style.display = "block"; + }, + hide: function(){ + container.style.display = "none"; + } + }; +}; diff --git a/src/js/app/modules/tenantInfo/template/indexTpl.html b/src/js/app/modules/tenantInfo/template/indexTpl.html new file mode 100644 index 000000000..05b7e0c0c --- /dev/null +++ b/src/js/app/modules/tenantInfo/template/indexTpl.html @@ -0,0 +1,6 @@ +<% _.each(menu, function(itm, menuId){ %> +
+ + <%= itm.name %> +
+<% }) %> diff --git a/src/js/app/modules/uikit/popupList.js b/src/js/app/modules/uikit/popupList.js new file mode 100644 index 000000000..c230869cb --- /dev/null +++ b/src/js/app/modules/uikit/popupList.js @@ -0,0 +1,50 @@ +var utils = require("@/common/utils"); +var tpl = require("./template/popupListTpl.html"); + +module.exports = function(opt){ + var items = opt.items; + var reportClick = opt.reportClick || utils.noop; + + var dom = utils.createElementFromHTML(_.template(tpl)({ + items: items + })); + document.body.appendChild(dom); + utils.on(window, "resize", function(){ + hide(); + }); + utils.on(document, "click", function(e){ + var target = e.srcElement || e.target; + if(!dom.contains(target)){ + hide(); + } + }); + + // 菜单点击 + utils.live("li", "click", function(e){ + var menuId; + var target = e.srcElement || e.target; + if(utils.hasClass(target.parentNode, "popup-item")){ + target = target.parentNode; + } + menuId = target.getAttribute("menuId"); + // 上报点击项 + reportClick(items[menuId], menuId); + hide(); + }, dom); + + function show(pos){ + utils.removeClass(dom, "hide"); + dom.style.left = pos.left + "px"; + dom.style.top = pos.top + "px"; + pos.width && (dom.style.width = pos.width + "px"); + } + + function hide(){ + utils.addClass(dom, "hide"); + } + + return { + show: show, + hide: hide, + }; +}; diff --git a/src/js/app/modules/uikit/template/popupListTpl.html b/src/js/app/modules/uikit/template/popupListTpl.html new file mode 100644 index 000000000..c540dbe8a --- /dev/null +++ b/src/js/app/modules/uikit/template/popupListTpl.html @@ -0,0 +1,7 @@ + diff --git a/src/js/common/utils.js b/src/js/common/utils.js index fce9142c2..a557aaa23 100644 --- a/src/js/common/utils.js +++ b/src/js/common/utils.js @@ -107,6 +107,7 @@ module.exports = { isIOS: /(iPad|iPhone|iPod)/i.test(navigator.userAgent), isSafari: /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent), isMobile: _isMobile, + noop: function(){}, click: _isMobile && ("ontouchstart" in window) ? "touchstart" : "click", isBrowserMinimized: function(){ return document.visibilityState === "hidden" || document.hidden; @@ -293,7 +294,9 @@ module.exports = { // 全清理 url = url.replace(/^http[s]?:/, ""); url = url.replace(/^\/\//, ""); - url = "//" + url; + if(!/^\//.test(url)){ + url = "//" + url; + } return url; }, setStore: function(key, value){ diff --git a/src/js/transfer/api.js b/src/js/transfer/api.js index cd04e01d0..a7a5b429c 100644 --- a/src/js/transfer/api.js +++ b/src/js/transfer/api.js @@ -102,7 +102,7 @@ getData.listen(function(msg){ }); break; case "getSession": - // DEPRECATED!!! + // DEPRECATED!!! emitAjax({ url: "/v1/webimplugin/visitors/" + params.id + "/schedule-data?techChannelInfo=" + techChannelInfo @@ -132,7 +132,7 @@ getData.listen(function(msg){ }); break; case "getGroup": - // DEPRECATED!!! + // DEPRECATED!!! emitAjax({ url: "/v1/webimplugin/visitors/" + params.id + "/ChatGroupId?techChannelInfo=" + techChannelInfo @@ -143,7 +143,7 @@ getData.listen(function(msg){ }); break; case "getGroupNew": - // DEPRECATED!!! + // DEPRECATED!!! emitAjax({ url: "/v1/webimplugin/tenant/" + tenantId + "/visitors/" + params.id + @@ -155,7 +155,7 @@ getData.listen(function(msg){ }); break; case "getHistory": - // DEPRECATED!!! + // DEPRECATED!!! emitAjax({ url: "/v1/webimplugin/visitors/msgHistory", type: "GET", @@ -730,6 +730,13 @@ getData.listen(function(msg){ type: "put" }); break; + case "getArticleJson": + emitAjax({ + url: "/v1/webimplugin/tenants/" + tenantId + "/robot/news/" + params.media_id, + type: "GET", + msg: msg, + }); + break; default: console.error("unexpect api name: " + apiName); break; diff --git a/src/scss/body.scss b/src/scss/body.scss index 7e31804a8..f4cc11f32 100644 --- a/src/scss/body.scss +++ b/src/scss/body.scss @@ -183,9 +183,43 @@ } } +// +.em-info-popup-tip { + position: absolute; + z-index: 10; + top: 30px; + left: 0; -/* 信息栏 */ + background-color: #fff; + color: #535252; + max-width: 30%; + min-width: 132px; + padding: 0 8px; + box-shadow: 0 0 5px rgba(102, 102, 102, 0.3); + li { + @extend %em-mix-ellipsis; + position: relative; + text-align: center; + line-height: 32px; + width: 100%; + border-top: 1px solid #ccc; + // 这里应该继承 theme 色,但是没设计好,再说 + a { + cursor: pointer; + color: #535252; + } + &:hover { + a { + color: #009eec; + } + } + } + li:nth-child(1) { + border-top: 0; + } +} +/* 信息栏 */ .em-widget-tip { display: none; position: absolute; @@ -213,6 +247,40 @@ height: 30px; color: #EBCFB3; } + + // 以下是新版信息栏 + &.new { + z-index: 1; + background-color: #fff; + box-shadow: 0 2px 2px rgba(102, 102, 102, 0.3); + // border-bottom: 1px solid #ccc; + font-size: 0; + box-sizing: border-box; + // 刚好 1 个 child,选中所有 + .tip-btn:first-child:nth-last-child(1), + .tip-btn:first-child:nth-last-child(1) ~ .tip-btn { + width: 100%; + } + .tip-btn:first-child:nth-last-child(2), + .tip-btn:first-child:nth-last-child(2) ~ .tip-btn { + width: 50%; + } + .tip-btn:first-child:nth-last-child(3), + .tip-btn:first-child:nth-last-child(3) ~ .tip-btn { + width: 33%; + } + .tip-btn { + @extend %em-mix-ellipsis; + cursor: pointer; + text-align: center; + font-size: 13px; + display: inline-block; + line-height: 48px; + span { + font-size: 15px; + } + } + } } .em-widget-wrapper.has-tip { diff --git a/src/scss/global.scss b/src/scss/global.scss index 1e598b9c1..841e1d39a 100644 --- a/src/scss/global.scss +++ b/src/scss/global.scss @@ -72,3 +72,10 @@ body { .hide { display: none!important; } + +// +%em-mix-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} diff --git a/webpack.config.js b/webpack.config.js index 5ff95497c..56fbf63b7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -44,6 +44,11 @@ i18next.init({ }); conmmonConfig = { + resolve: { + alias: { + "@": path.resolve("./src/js") + }, + }, plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { @@ -60,6 +65,11 @@ conmmonConfig = { devtool: "eval", module: { loaders: [ + // HtmlWebpackPlugin 需要此 loader + { + test: /Tpl.html$/, + loaders: [ "html-loader" ] + }, { test: /easemob\.scss$/, loaders: [