index.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. const SHARE_TO = (() => {
  2. const ShareType = {
  3. CREATE: 'create',
  4. UPDATE: 'update',
  5. CANCEL: 'cancel',
  6. };
  7. const { SharePermissionChangeType: PermissionType, PageTarget, ShareLibType } = commonConstants;
  8. const Mode = {
  9. PROJECT: 1,
  10. RATION_LIB: 2
  11. };
  12. const ModeToLibType = {
  13. [Mode.RATION_LIB]: ShareLibType.RATION_LIB
  14. };
  15. // 当前模式
  16. let curMode = Mode.PROJECT;
  17. // 当前分享的项目ID
  18. let curProjectID;
  19. // 当前项目的已分享列表
  20. let curSharedUsers = [];
  21. // 清除缓存
  22. function clearCache() {
  23. curProjectID = null;
  24. curSharedUsers = [];
  25. }
  26. // 最近联系人显示数量
  27. const rencentCount = 5;
  28. // 获取初始数据:1.最近分享人 2.联系人 3.已分享人
  29. async function getInitialData(projectID) {
  30. return await ajaxPost('/pm/api/getInitialShareData', { user_id: userID, count: rencentCount, projectID }, false);
  31. }
  32. // 获取分享库的初始数据
  33. async function getInitialLibData(libType) {
  34. return await ajaxPost('/pm/api/getInitialShareLibData', { user_id: userID, count: rencentCount, libType }, false);
  35. }
  36. // 获取头像视图html
  37. function getAvatarHTML(mobile, realName) {
  38. // 手机最后一位
  39. const lastMobileNumer = mobile.substr(-1);
  40. // 显示名称为真实名称后两位
  41. const nickName = realName.substr(-2);
  42. return `<span class="avatar bg-${lastMobileNumer}">${nickName}</span>`;
  43. }
  44. /**
  45. * 获取用户列表视图html:最近分享和联系人用
  46. * @param {Array} users - 排序过的用户数据
  47. * @param {Boolean} showAlphabet - 是否显示字母表分类
  48. * @return {HTMLString}
  49. * */
  50. function getUserHTML(users, showAlphabet) {
  51. let curLetter = '';
  52. return users.reduce((html, user) => {
  53. const mobile = user.mobile || '';
  54. const realName = user.real_name || '';
  55. const company = user.company || '';
  56. if (showAlphabet) {
  57. // 名字首个字符对应拼音
  58. const letter = pinyinUtil.getFirstLetter(realName).substr(0, 1);
  59. if (letter !== curLetter) {
  60. curLetter = letter;
  61. html += `<li class="letter">${letter}</li>`;
  62. }
  63. }
  64. const avatarHtml = getAvatarHTML(mobile, realName);
  65. return html +
  66. `<li>
  67. ${avatarHtml}
  68. <div class="book-body">
  69. <h5 class="mt-0" title="${company}">${realName}</h5>
  70. <span>${mobile}</span>
  71. </div>
  72. </li>`;
  73. }, '');
  74. }
  75. // 初始化最近分享视图
  76. function initRecentView(recentUsers) {
  77. const recentShareHTML = getUserHTML(recentUsers, false);
  78. $('#recent-share').html(recentShareHTML);
  79. // 点击最近分享列表自动添加该用户添加到搜索框中
  80. $('#recent-share li').click(function () {
  81. const mobile = $(this).find('div span')[0].textContent;
  82. $('#share-phone').val(mobile);
  83. handleSearch()
  84. })
  85. }
  86. // 初始化联系人视图
  87. function initContactsView(contacts) {
  88. // 联系人按拼英首字母降序排序
  89. contacts.sort((a, b) => {
  90. const realNameA = a.real_name || '';
  91. const realNameB = b.real_name || '';
  92. return realNameA.localeCompare(realNameB, 'zh-Hans-CN', { sensitivity: 'accent' })
  93. });
  94. const contactsHTML = getUserHTML(contacts, true);
  95. $('#contacts').html(contactsHTML);
  96. // 点击联系人自动添加该联系人添加到搜索框中
  97. $('#contacts li:not(.letter)').click(function () {
  98. const mobile = $(this).find('div span')[0].textContent;
  99. $('#share-phone').val(mobile);
  100. $('#contacts-menue').removeClass('show');
  101. handleSearch()
  102. });
  103. }
  104. // 初始化已分享视图
  105. function initSharedView(sharedUsers) {
  106. const html = sharedUsers.reduce((html, user, index) => {
  107. const mobile = user.mobile || '';
  108. const realName = user.real_name || '';
  109. const company = user.company || '';
  110. const avatarHTML = getAvatarHTML(mobile, realName);
  111. const copyLabelFor = `allowCopy${index}`;
  112. const editLabelFor = `allowEdit${index}`;
  113. return html +
  114. `<li class="card mb-1">
  115. <div class="card-body p-1 row m-0">
  116. ${avatarHTML}
  117. <div class="book-body col-auto pl-0">
  118. <h5 class="mt-0">${realName}</h5>
  119. ${mobile}
  120. </div>
  121. <div class="col-5">${company}</div>
  122. <div class="col ml-auto p-0">
  123. <div class="d-flex justify-content-end">
  124. ${curMode === Mode.PROJECT ? `<div>
  125. <div class="custom-control custom-checkbox">
  126. <input type="checkbox" class="custom-control-input allow-copy" id="${copyLabelFor}" data-user="${user._id}" ${user.allowCopy ? 'checked' : ''}>
  127. <label class="custom-control-label" for="${copyLabelFor}">允许拷贝</label>
  128. </div>
  129. <div class="custom-control custom-checkbox">
  130. <input type="checkbox" class="custom-control-input allow-edit" id="${editLabelFor}" data-user="${user._id}" ${user.allowCooperate ? 'checked' : ''}>
  131. <label class="custom-control-label" for="${editLabelFor}">允许编辑</label>
  132. </div>
  133. </div>` : ''}
  134. <div class="ml-3 d-flex align-items-center">
  135. <button class="btn btn-sm btn-outline-danger cancel-share" data-user="${user._id}">取消分享</button>
  136. </div>
  137. </div>
  138. </div>
  139. </div>
  140. </li>`;
  141. }, '');
  142. $('#shared-list').html(html);
  143. // 编辑允许拷贝
  144. $('#shared-list .allow-copy').click(function () {
  145. handleCheckBoxClick.call(this);
  146. handleShareAction.call(this, ShareType.UPDATE);
  147. });
  148. // 编辑允许编辑
  149. $('#shared-list .allow-edit').click(function () {
  150. handleCheckBoxClick.call(this);
  151. handleShareAction.call(this, ShareType.UPDATE);
  152. });
  153. // 取消分享
  154. $('#shared-list .cancel-share').click(function () {
  155. if (curMode === Mode.PROJECT) {
  156. handleShareAction.call(this, ShareType.CANCEL);
  157. } else {
  158. handleShareLibAction.call(this, ShareType.CANCEL, ModeToLibType[curMode]);
  159. }
  160. });
  161. }
  162. // 初始化搜索结果视图
  163. function initSearchResultView(user) {
  164. if (!user) {
  165. $('#share-search-result').html('')
  166. } else {
  167. const mobile = user.mobile || '';
  168. const realName = user.real_name || '';
  169. const company = user.company || '';
  170. const avatarHTML = getAvatarHTML(mobile, realName);
  171. const html =
  172. `<li class="card mb-1">
  173. <div class="card-body p-1 row m-0">
  174. ${avatarHTML}
  175. <div class="book-body col-auto pl-0">
  176. <h5 class="mt-0">${realName}</h5>
  177. ${mobile}
  178. </div>
  179. <div class="col-5">${company}</div>
  180. <div class="col ml-auto p-0">
  181. <div class="d-flex justify-content-end">
  182. ${curMode === Mode.PROJECT ? `<div>
  183. <div class="custom-control custom-checkbox">
  184. <input type="checkbox" class="custom-control-input" id="allow-copy" checked="">
  185. <label class="custom-control-label" for="allow-copy">允许拷贝</label>
  186. </div>
  187. <div class="custom-control custom-checkbox">
  188. <input type="checkbox" class="custom-control-input" id="allow-edit">
  189. <label class="custom-control-label" for="allow-edit">允许编辑</label>
  190. </div>
  191. </div>` : ''}
  192. <div class="ml-3 d-flex align-items-center"><button class="btn btn-sm btn-primary" id="share-to" data-user="${user._id}">分享给Ta</button></div>
  193. </div>
  194. </div>
  195. </div>
  196. </li>`;
  197. $('#share-search-result').html(html);
  198. // 允许拷贝
  199. $('#allow-copy').click(function () {
  200. handleCheckBoxClick.call(this);
  201. });
  202. // 允许编辑
  203. $('#allow-edit').click(function () {
  204. handleCheckBoxClick.call(this);
  205. });
  206. // 分享给事件
  207. $('#share-to').click(function () {
  208. if (curMode === Mode.PROJECT) {
  209. handleShareAction.call(this, ShareType.CREATE, user);
  210. } else {
  211. handleShareLibAction.call(this, ShareType.CREATE, ModeToLibType[curMode], user);
  212. }
  213. });
  214. }
  215. }
  216. // 复选框框的状态随点击更改,不处理的话input的checked并不会自动处理
  217. function handleCheckBoxClick() {
  218. const curChecked = !$(this).attr('checked');
  219. if (curChecked) {
  220. $(this).attr('checked', 'checked');
  221. } else {
  222. $(this).removeAttr('checked');
  223. }
  224. }
  225. async function handleShareLibAction(shareType, libType, user) {
  226. try {
  227. $.bootstrapLoading.start();
  228. const receiver = $(this).data('user');
  229. let shareData;
  230. if (shareType === ShareType.CREATE) {
  231. shareData = [{ receiver }];
  232. } else if (shareType === ShareType.CANCEL) {
  233. shareData = [{ receiver, isCancel: true }];
  234. }
  235. const postData = {
  236. type: shareType,
  237. user_id: userID,
  238. count: rencentCount,
  239. libType,
  240. shareData
  241. };
  242. const rst = await ajaxPost('/pm/api/shareLib', postData);
  243. // 请求成功后刷新视图
  244. if (shareType === ShareType.CREATE || shareType === ShareType.CANCEL) {
  245. if (shareType === ShareType.CREATE) {
  246. curSharedUsers.unshift(user);
  247. $('#share-phone').val('');
  248. initSearchResultView();
  249. } else {
  250. curSharedUsers = curSharedUsers.filter(user => user._id !== receiver);
  251. }
  252. if (Array.isArray(rst.recentUsers)) {
  253. initRecentView(rst.recentUsers);
  254. }
  255. if (Array.isArray(rst.contacts)) {
  256. initContactsView(rst.contacts)
  257. }
  258. initSharedView(curSharedUsers);
  259. refreshShareTip(curSharedUsers);
  260. refreshTreeView();
  261. }
  262. } catch (err) {
  263. console.log(err);
  264. alert(`${String(err)} 请重试。`);
  265. initSharedView(curSharedUsers);
  266. } finally {
  267. $.bootstrapLoading.end();
  268. }
  269. }
  270. // 添加分享、编辑分享、取消分享的动作
  271. async function handleShareAction(shareType, user) {
  272. try {
  273. $.bootstrapLoading.start();
  274. const receiver = $(this).data('user');
  275. let shareData;
  276. let type = ShareType.UPDATE;
  277. if (shareType === ShareType.CREATE) {
  278. const allowCopy = $('#allow-copy').prop('checked');
  279. const allowCooperate = $('#allow-edit').prop('checked');
  280. shareData = [{ userID: receiver, allowCopy, allowCooperate }];
  281. type = ShareType.CREATE; // 上传的服务器的type,删除跟更新是一样的
  282. } else if (shareType === ShareType.UPDATE) {
  283. const allowCopy = $(`[data-user=${receiver}].allow-copy`).prop('checked');
  284. const allowCooperate = $(`[data-user=${receiver}].allow-edit`).prop('checked');
  285. shareData = [{ userID: receiver, allowCopy, allowCooperate }];
  286. } else {
  287. shareData = [{ userID: receiver, isCancel: true }];
  288. }
  289. // 获取权限变更的类型
  290. const permissionType = getPermissionType(shareType, curSharedUsers, shareData[0]);
  291. const postData = {
  292. user_id: userID,
  293. type,
  294. permissionType,
  295. projectID: curProjectID,
  296. count: rencentCount,
  297. shareData
  298. };
  299. const rst = await ajaxPost('/pm/api/share', postData);
  300. // 请求成功后刷新视图
  301. if (shareType === ShareType.CREATE || shareType === ShareType.CANCEL) {
  302. if (shareType === ShareType.CREATE) {
  303. user.allowCopy = shareData[0].allowCopy;
  304. user.allowCooperate = shareData[0].allowCooperate;
  305. curSharedUsers.unshift(user);
  306. $('#share-phone').val('');
  307. initSearchResultView();
  308. } else {
  309. curSharedUsers = curSharedUsers.filter(user => user._id !== receiver);
  310. }
  311. if (Array.isArray(rst.recentUsers)) {
  312. initRecentView(rst.recentUsers);
  313. }
  314. if (Array.isArray(rst.contacts)) {
  315. initContactsView(rst.contacts)
  316. }
  317. initSharedView(curSharedUsers);
  318. refreshShareTip(curSharedUsers);
  319. refreshTreeView();
  320. } else {
  321. const matchItem = curSharedUsers.find(item => item._id === receiver);
  322. if (matchItem) {
  323. matchItem.allowCopy = shareData[0].allowCopy;
  324. matchItem.allowCooperate = shareData[0].allowCooperate;
  325. }
  326. }
  327. if (permissionType !== null) {
  328. const payload = [PermissionType.UPDATE_COOPERATE, PermissionType.UPDATE_COPY].includes(permissionType)
  329. ? { prop: { allowCopy: shareData[0].allowCopy, allowCooperate: shareData[0].allowCooperate } }
  330. : null;
  331. emitPermissionChange(permissionType, receiver, curProjectID, rst.emitTenders, payload);
  332. }
  333. } catch (err) {
  334. console.log(err);
  335. alert(`${String(err)} 请重试。`);
  336. initSharedView(curSharedUsers);
  337. } finally {
  338. $.bootstrapLoading.end();
  339. }
  340. }
  341. // 获取权限变更的类型
  342. function getPermissionType(shareType, cache, curShareData) {
  343. if (shareType === ShareType.CANCEL) {
  344. return PermissionType.CANCEL;
  345. }
  346. if (shareType === ShareType.CREATE) {
  347. return PermissionType.SHARE;
  348. }
  349. if (!cache) {
  350. return null;
  351. }
  352. const match = cache.find(item => item._id === curShareData.userID);
  353. if (!match) {
  354. return null;
  355. }
  356. if (match.allowCooperate !== curShareData.allowCooperate) {
  357. return PermissionType.UPDATE_COOPERATE;
  358. }
  359. if (match.allowCopy !== curShareData.allowCopy) {
  360. return PermissionType.UPDATE_COPY;
  361. }
  362. return null;
  363. }
  364. // 权限变更消息推送
  365. function emitPermissionChange(permissionType, userID, projectID, emitTenders, payload) {
  366. const compilationID = typeof projectObj !== 'undefined' ? projectObj.project.projectInfo.compilation : compilationData._id;
  367. socket.emit('sharePermissionChange', { permissionType, userID, compilationID, projectID, emitTenders, payload });
  368. }
  369. // 权限变更处理监听
  370. function permissionChangeListener() {
  371. socket.on('sharePermissionChange', ({ permissionType, target, payload }) => {
  372. const type = `${permissionType}-${target}`;
  373. switch (type) {
  374. case `${PermissionType.READ}-${PageTarget.PM}`:
  375. handleShareItemRead(payload);
  376. break;
  377. case `${PermissionType.UPDATE_COOPERATE}-${PageTarget.PM}`:
  378. case `${PermissionType.UPDATE_COPY}-${PageTarget.PM}`:
  379. handlePMPropChange(payload);
  380. break;
  381. case `${PermissionType.UPDATE_COOPERATE}-${PageTarget.MAIN}`:
  382. handleMainCooperateChange(payload);
  383. break;
  384. case `${PermissionType.CANCEL}-${PageTarget.PM}`:
  385. handlePMCancelPermission(payload);
  386. break;
  387. case `${PermissionType.CANCEL}-${PageTarget.MAIN}`:
  388. handleMainCancelPermission();
  389. break;
  390. case `${PermissionType.SHARE}-${PageTarget.PM}`:
  391. handlePMSharePermission(payload);
  392. break;
  393. }
  394. });
  395. }
  396. // 项目管理页面分享权限变更后相关处理函数
  397. // 已读分享项目
  398. function handleShareItemRead({ markReadProjectIDs }) {
  399. const isActive = $('#tab_pm_share').hasClass('active');
  400. if (isActive) {
  401. pmShare.handleMarkRead(unreadShareList, markReadProjectIDs);
  402. } else {
  403. markReadProjectIDs.forEach(projectID => {
  404. removeUnread(projectID, unreadShareList);
  405. });
  406. }
  407. }
  408. // 分享条数属性变更(是否可拷贝、是否可编辑)
  409. // @param {Object} prop - 属性变更对象 eg: { allowCopy: false }
  410. function handlePMPropChange({ projectID, prop }) {
  411. // 如果当前在项目管理的分享页面,需要刷新相关节点
  412. const isActive = $('#tab_pm_share').hasClass('active');
  413. if (isActive) {
  414. pmShare.handlePropChange(projectID, prop);
  415. }
  416. }
  417. // 已读某未读分享项目
  418. function removeUnread(projectID, list) {
  419. const idx = list.indexOf(projectID);
  420. if (idx >= 0) {
  421. list.splice(idx, 1);
  422. refreshUnreadCount(list.length);
  423. }
  424. }
  425. // 取消分享后项目管理页面接收到推送后到操作
  426. function handlePMCancelPermission({ projectID }) {
  427. removeUnread(projectID, unreadShareList);
  428. // 如果当前停留在分享标签界面,清楚分享项目
  429. const isActive = $('#tab_pm_share').hasClass('active');
  430. if (isActive) {
  431. pmShare.handleCancelShare(projectID);
  432. }
  433. }
  434. // 通知信息点击事件
  435. function notify() {
  436. pmShare.initShareTree();
  437. $("#notify").hide();
  438. }
  439. // 新增分享后项目管理页面接收到推送后的操作
  440. function handlePMSharePermission({ projectID }) {
  441. unreadShareList.push(projectID);
  442. unreadShareList = [...new Set(unreadShareList)];
  443. refreshUnreadCount(unreadShareList.length);
  444. // 如果当前停留在分享标签界面,需要弹出提示
  445. const isActive = $('#tab_pm_share').hasClass('active');
  446. if (isActive) {
  447. $("#message").html('您有新的分享项目,<a href="javascript:void(0);" id="load-data" onclick="SHARE_TO.notify()">点击刷新列表</a>');
  448. $("#notify").show();
  449. }
  450. }
  451. // 刷新未读分享标记
  452. function refreshUnreadCount(count) {
  453. if (count) {
  454. $('#unread-share-count').text(count);
  455. $('#unread-share-count').show();
  456. } else {
  457. $('#unread-share-count').hide();
  458. }
  459. }
  460. // 主页面的分享权限变更后相关处理函数
  461. function handleMainCooperateChange({ allowCooperate }) {
  462. if (projectObj.project.projectInfo.shareState && projectObj.project.projectInfo.shareState.allowCooperate !== allowCooperate) {
  463. setLocalCache(commonConstants.StorageKey.ONCE_MAIN_LOADED, '分享设置已被修改,当前项目已自动刷新。');
  464. window.location.reload();
  465. }
  466. }
  467. function handleMainCancelPermission() {
  468. // 定位到空白页
  469. window.location.replace(`/blank?type=${commonConstants.BlankType.SHARE_CANCEL}`);
  470. }
  471. // 刷新项目管理树视图
  472. // 如果是在项目管理页面,需要刷新树(分享图标可能需要清除)
  473. function refreshTreeView() {
  474. if (typeof projTreeObj !== 'undefined' && projTreeObj.tree.selected) {
  475. projTreeObj.tree.selected.data.shareInfo = curSharedUsers;
  476. const sheet = projTreeObj.workBook.getSheet(0);
  477. projTreeObj.renderSheetFuc(sheet, function () {
  478. sheet.invalidateLayout();
  479. sheet.repaint();
  480. });
  481. }
  482. }
  483. // 刷新造价书的分享按钮tooltip提示
  484. function refreshShareTip(sharedUsers) {
  485. const $shareTip = $('#share-tip');
  486. if (!$shareTip) {
  487. return;
  488. }
  489. const limit = 2;
  490. const count = sharedUsers.length;
  491. const users = sharedUsers.slice(0, 2);
  492. const tip = users.reduce((acc, user, index) => {
  493. if (index === 0) {
  494. acc += '已分享给';
  495. acc += user.real_name;
  496. } else {
  497. acc += ` ${user.real_name}`;
  498. }
  499. if (index === users.length - 1 && count > limit) {
  500. acc += `等${count}人`;
  501. }
  502. return acc;
  503. }, '');
  504. $shareTip.attr('data-original-title', tip);
  505. }
  506. // 初始化分享给的页面
  507. // mode: 模式,分享项目、分享库
  508. async function initModal(mode, projectID) {
  509. try {
  510. curMode = mode;
  511. $.bootstrapLoading.start();
  512. // 恢复
  513. $('#share-phone').val('');
  514. initSearchResultView();
  515. $('#share-hint').text('');
  516. let sharedUsers = [];
  517. let recentUsers = [];
  518. let contacts = [];
  519. let data;
  520. if (mode === Mode.PROJECT) {
  521. curProjectID = projectID;
  522. data = await getInitialData(projectID);
  523. if (data.isFree) {
  524. return hintBox.versionBox('此功能仅在专业版中提供,免费版可选择单位工程进行分享。');
  525. }
  526. } else {
  527. data = await getInitialLibData(ModeToLibType[curMode]);
  528. }
  529. sharedUsers = data.sharedUsers;
  530. recentUsers = data.recentUsers;
  531. contacts = data.contacts;
  532. curSharedUsers = sharedUsers;
  533. initSharedView(sharedUsers);
  534. initRecentView(recentUsers);
  535. initContactsView(contacts);
  536. setTimeout(() => $('#share-phone').focus(), 200);
  537. $('#share').modal('show');
  538. } catch (err) {
  539. console.log(err);
  540. alert(err);
  541. } finally {
  542. $.bootstrapLoading.end();
  543. }
  544. }
  545. // 退出分享给页面
  546. function exitModal() {
  547. clearCache();
  548. }
  549. // 分享给
  550. async function handleSearch() {
  551. let phone = $('#share-phone').val();
  552. phone = phone && phone.trim() || '';
  553. //$('#share-hint').text('');
  554. initSearchResultView();
  555. if (!phone) {
  556. $('#share-hint').text('请输入手机号码。');
  557. return;
  558. }
  559. // 根据手机号获取用户
  560. const user = await ajaxPost('/user/getUserByMobile', { mobile: phone });
  561. if (!user) {
  562. $('#share-hint').text('账号不存在。');
  563. return;
  564. }
  565. if (user._id === userID) {
  566. $('#share-hint').text('不可分享给自己。');
  567. return;
  568. }
  569. const matched = curSharedUsers.find(item => item._id === user._id);
  570. if (matched) {
  571. $('#share-hint').text('已与该用户分享。');
  572. return;
  573. }
  574. $('#share-hint').text('');
  575. initSearchResultView(user);
  576. }
  577. // 一些事件的监听
  578. function handleEventListener() {
  579. // 界面消失
  580. $('#share').on('hide.bs.modal', function () {
  581. exitModal();
  582. });
  583. // 联系人下拉
  584. $('#contacts-dropdown').click(function () {
  585. const $subMenu = $('#contacts-menue');
  586. const visible = $subMenu.is(':visible');
  587. if (visible) {
  588. $subMenu.removeClass('show');
  589. } else {
  590. $subMenu.addClass('show');
  591. }
  592. });
  593. // 点击body时,联系人菜单的处理
  594. $('body').click(function (e) {
  595. const body = $(this)[0];
  596. const $contactsMenu = $('#contacts-menue');
  597. const contactsMenu = $contactsMenu[0];
  598. const dropdownButton = $('#contacts-dropdown')[0]
  599. if (!$contactsMenu.is(':visible')) {
  600. return;
  601. }
  602. let target = e.target;
  603. while (target !== body) {
  604. if ([contactsMenu, dropdownButton].includes(target)) {
  605. return;
  606. }
  607. target = target.parentElement;
  608. }
  609. $(contactsMenu.parentElement).removeClass('show');
  610. $contactsMenu.removeClass('show');
  611. });
  612. // 输入手机号查找要分享给的用户
  613. let keyupTime = 0;
  614. let delayTime = 500;
  615. function delayKeyup(callback) {
  616. const nowTime = Date.now();
  617. keyupTime = nowTime;
  618. setTimeout(function () {
  619. if (nowTime - keyupTime == 0) {
  620. callback();
  621. }
  622. }, delayTime);
  623. }
  624. $('#share-phone').on('keyup', function () {
  625. delayKeyup(function () {
  626. console.log(curSharedUsers);
  627. handleSearch();
  628. });
  629. });
  630. $('#sharePhone').on('keypress', function (e) {
  631. if (e.keyCode === 13) {
  632. $(this).blur();
  633. }
  634. });
  635. }
  636. return {
  637. Mode,
  638. initModal,
  639. handleEventListener,
  640. permissionChangeListener,
  641. emitPermissionChange,
  642. getAvatarHTML,
  643. notify,
  644. removeUnread,
  645. }
  646. })();