Browse Source

打开他人分享的项目后,如果分享人修改了“可编辑”、取消了分享,应刷新并提示。(TASK #3068)

vian 5 years ago
parent
commit
385a35c993

+ 32 - 0
modules/blank/routes/index.js

@@ -0,0 +1,32 @@
+const { BlankType } = require('../../../public/common_constants');
+
+function getCardHtml(info, btn) {
+    return `<div class="row">
+    <div class="col-lg-8 mx-auto mt-5">
+        <div class="card newuser-input">
+            <div class="card-body">
+                <h4 class="mt-2 mb-5 text-center">${info}</h4>
+                ${btn ? `<div class="form-group text-center"><a class="btn btn-primary" href="${btn.href}">${btn.title}</a></div>` : ''}
+            </div>
+        </div>
+    </div>
+</div>`;
+}
+
+module.exports = function (app) {
+    app.get('/blank', function (req, res) {
+        const { type } = req.query;
+        let html = '';
+        switch (+type) {
+            case BlankType.SHARE_CANCEL:
+                html = getCardHtml('分享设置已被修改,当前项目无权查看。', { href: '/pm', title: '返回项目管理' });
+                break;
+            case BlankType.NOT_FOUND:
+            default:
+                html = getCardHtml('很抱歉,您要访问的页面不存在。');
+                break;
+
+        }
+        res.render('common/components/blank/index.html', { html });
+    });
+}

+ 13 - 0
public/common_constants.js

@@ -147,6 +147,17 @@
     // 费用定额
     const COMPILATION = 'compilation';
 
+    // 缓存key
+    const StorageKey = {
+        // 主界面一旦出现这个缓存,马上提示
+        ONCE_MAIN_LOADED: 'onceMainLoaded'
+    };
+
+    const BlankType = {
+        NOT_FOUND: 1,
+        SHARE_CANCEL: 2,
+    };
+
     return {
         fixedFlag,
         billType,
@@ -159,5 +170,7 @@
         DEFAULT_REGION,
         COMPILATION,
         COMPLEMENTARY_LIB,
+        StorageKey,
+        BlankType
     };
 });

+ 3 - 2
public/web/socket/connection.js

@@ -22,7 +22,8 @@ socketObject = {
         } else {
             me.roomInfo={
                 feeRate:me.getFeeRateRoomID(),
-                unitFile:me.getUnitFileRoomID()
+                unitFile:me.getUnitFileRoomID(),
+                userIDProjectID: `${userID}@${projectObj.project.ID()}`
             };
               if (payload && payload.projectReadOnly === false) {
                   me.roomInfo.projectID = `projectID${projectObj.project.ID()}`;
@@ -75,7 +76,7 @@ socketObject = {
       socket.on('handleAvatarList', function ({ editingUsers }) {
           projectInfoObj.handleAvatarList(editingUsers);
       });
-
+      SHARE_TO.permissionChangeListener();
 
       //=============================================================================================
       //项目管理页面接收消息部分

+ 5 - 0
socket.js

@@ -6,6 +6,7 @@
  * @version
  */
 import socket from "socket.io";
+const { SharePermissionType } = require('./public/common_constants');
 
 const socketIO = socket(3300);
 
@@ -100,6 +101,10 @@ socketIO.on('connection', function(socket) {
         }
     });
 
+    // 分享权限变更
+    socket.on('sharePermissionChange', function ({ permissionType, roomID }) {
+        socket.broadcast.to(roomID).emit('sharePermissionChange', { permissionType });
+    });
 
     socket.on('disconnect', function () {
         // 由于用户可以重复打开项目,因此不做唯一性处理,只删除一个数据,不删除所有的同用户数据

+ 1 - 0
web/building_saas/complementary_ration_lib/js/gljSelect.js

@@ -117,6 +117,7 @@ let gljSelOprObj = {
         const html = libData.reduce((acc, lib) => acc += `<option ${lib.isDefault ? 'selected="selected"' : ''} value="${lib.gljLibId}">${lib.name}</option>`, '');
         $('#glj-lib-select').html(html);
     },
+    // TODO 改成分页的形式
     // 初始化选择页面
     initView: async function (gljLibId, isInitial) {
         try {

+ 14 - 2
web/building_saas/js/global.js

@@ -99,13 +99,25 @@ $(function () {
  * @param {String|Number} value
  * @return {void}
  */
+let storageErrCount = 0;
 function setLocalCache(key, value) {
     const storage = window.localStorage;
     if (!storage || key === '' || value === '') {
         return;
     }
-
-    storage.setItem(key, value);
+    try {
+        storage.setItem(key, value);
+        storageErrCount = 0;
+    } catch (err) {
+        storageErrCount++;
+        if (storageErrCount > 1) {
+            alert(`字段“${key}”数据过大,存入本地缓存失败。`)
+            storageErrCount = 0;
+            return;
+        }
+        storage.clear();
+        setLocalCache(key, value);
+    }
 }
 
 /**

+ 5 - 0
web/building_saas/main/js/views/project_view.js

@@ -1042,6 +1042,11 @@ var projectObj = {
             else {
 
             }
+            const onceAlert = getLocalCache(commonConstants.StorageKey.ONCE_MAIN_LOADED);
+            if (onceAlert) {
+                alert(onceAlert);
+                removeLocalCache(commonConstants.StorageKey.ONCE_MAIN_LOADED);
+            }
         });
 
     },

+ 32 - 0
web/common/components/blank/index.html

@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>大司空云计价</title>
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/building_saas/css/main.css">
+    <link rel="shortcut icon" href="/web/building_saas/css/favicon.ico">
+    <link rel="icon" type="image/gif" href="/web/building_saas/css/animated_favicon1.gif">
+</head>
+
+<body>
+    <div class="header">
+        <nav class="navbar navbar-expand-lg p-0 d-flex">
+            <div class="header-logo">
+            </div>
+        </nav>
+    </div>
+    <div class="container mt-3">
+        <%- html %>
+    </div>
+    <!-- JS. -->
+    <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
+    <script src="/lib/popper/popper.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/web/building_saas/js/global.js"></script>
+</body>
+
+</html>

+ 66 - 4
web/common/components/share/index.js

@@ -6,6 +6,11 @@ const SHARE_TO = (() => {
         CANCEL: 'cancel',
     };
 
+    const PermissionType = {
+        UPDATE_COOPERATE: 1,
+        CANCEL: 2,
+    };
+
     // 当前分享的项目ID
     let curProjectID;
 
@@ -224,13 +229,13 @@ const SHARE_TO = (() => {
             let shareData;
             let type = ShareType.UPDATE;
             if (shareType === ShareType.CREATE) {
-                const allowCopy = !!$('#allow-copy').attr('checked');
-                const allowCooperate = !!$('#allow-edit').attr('checked');
+                const allowCopy = $('#allow-copy').prop('checked');
+                const allowCooperate = $('#allow-edit').prop('checked');
                 shareData = [{ userID: receiver, allowCopy, allowCooperate }];
                 type = ShareType.CREATE; // 上传的服务器的type,删除跟更新是一样的
             } else if (shareType === ShareType.UPDATE) {
-                const allowCopy = !!$(`[data-user=${receiver}].allow-copy`).attr('checked');
-                const allowCooperate = !!$(`[data-user=${receiver}].allow-edit`).attr('checked');
+                const allowCopy = $(`[data-user=${receiver}].allow-copy`).prop('checked');
+                const allowCooperate = $(`[data-user=${receiver}].allow-edit`).prop('checked');
                 shareData = [{ userID: receiver, allowCopy, allowCooperate }];
             } else {
                 shareData = [{ userID: receiver, isCancel: true }];
@@ -243,6 +248,8 @@ const SHARE_TO = (() => {
                 shareData
             };
             const rst = await ajaxPost('/pm/api/share', postData);
+            // 获取权限变更的类型
+            const permissionType = getPermissionType(shareType, curSharedUsers, shareData[0]);
             // 请求成功后刷新视图
             if (shareType === ShareType.CREATE || shareType === ShareType.CANCEL) {
                 if (shareType === ShareType.CREATE) {
@@ -263,6 +270,15 @@ const SHARE_TO = (() => {
                 initSharedView(curSharedUsers);
                 refreshShareTip(curSharedUsers);
                 refreshTreeView();
+            } else {
+                const matchItem = curSharedUsers.find(item => item._id === receiver);
+                if (matchItem) {
+                    matchItem.allowCopy = shareData[0].allowCopy;
+                    matchItem.allowCooperate = shareData[0].allowCooperate;
+                }
+            }
+            if (permissionType !== null) {
+                emitPermissionChange(permissionType, receiver, curProjectID);
             }
         } catch (err) {
             console.log(err);
@@ -273,6 +289,50 @@ const SHARE_TO = (() => {
         }
     }
 
+    // 获取权限变更的类型
+    function getPermissionType(shareType, cache, curShareData) {
+        if (shareType === ShareType.CANCEL) {
+            return PermissionType.CANCEL;
+        }
+        if (!cache) {
+            return null;
+        }
+        const match = cache.find(item => item._id === curShareData.userID);
+        if (!match) {
+            return null;
+        }
+        if (match.allowCooperate !== curShareData.allowCooperate) {
+            return PermissionType.UPDATE_COOPERATE;
+        }
+        return null;
+    }
+
+    // 权限变更消息推送
+    function emitPermissionChange(permissionType, userID, projectID) {
+        socket.emit('sharePermissionChange', { permissionType, roomID: `${userID}@${projectID}` });
+    }
+
+    // 权限变更处理监听
+    function permissionChangeListener() {
+        socket.on('sharePermissionChange', ({ permissionType }) => {
+            if (permissionType === PermissionType.CANCEL) {
+                handleCancelPermission();
+            } else if (permissionType === PermissionType.UPDATE_COOPERATE) {
+                handleCooperateChange();
+            }
+        });
+    }
+
+    function handleCancelPermission() {
+        // 定位到空白页
+        window.location.replace(`/blank?type=${commonConstants.BlankType.SHARE_CANCEL}`);
+    }
+
+    function handleCooperateChange() {
+        setLocalCache(commonConstants.StorageKey.ONCE_MAIN_LOADED, '分享设置已被修改,当前项目已自动刷新。');
+        window.location.reload();
+    }
+
     // 刷新项目管理树视图
     // 如果是在项目管理页面,需要刷新树(分享图标可能需要清除)
     function refreshTreeView() {
@@ -424,6 +484,7 @@ const SHARE_TO = (() => {
         }
         $('#share-phone').on('keyup', function () {
             delayKeyup(function () {
+                console.log(curSharedUsers);
                 handleSearch();
             });
         });
@@ -437,6 +498,7 @@ const SHARE_TO = (() => {
     return {
         initModal,
         handleEventListener,
+        permissionChangeListener,
         getAvatarHTML,
     }
 })();