index.js 27 KB

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