使用屬性規則限制編輯內容始終在邊界內

如何限制編輯范圍?如何將編輯限制在某些邊界?如何將用戶限制為僅在分配給他們的工作訂單邊界內進行編輯?是否可以限制用戶在某些邊界中進行編輯,而不能在其他邊界中進行編輯?我們經常遇到這些問題,在本博客中,我將說明如何使用屬性規則來做到這一點。

一、限制邊界區域內的編輯內容

在本例中,我們希望創建一個邊界要素類,該要素類將表示限制區域或區域。我們還將創建另一個表示數據的要素類;最后,我們將向要素類添加一個屬性規則,用于檢查正在創建或更新的要素是否在邊界內。

注意: 此示例可在裝有 ArcGIS Pro 2.4 或 GeoScene Pro任意版本的產品 以及更高版本的文件地理數據庫中完成。但是,我使用的是企業級地理數據庫。因為后續想要發布可編輯的要素服務。當數據源為文件型地理數據庫時,無法發布可編輯的要素服務。

在企業級地理數據庫中,使用如圖所示的字段創建以下兩個要素類。

目錄
boundaryClass 數據設計-字段


pointClass 數據設計 - 字段

右鍵pointClass 數據設計 - 屬性規則,在約束屬性規則中,添加一條約束屬性規則,填寫名稱描述和表達式,還有編寫錯誤提示,勾選使其在插入、更新和刪除時執行,然后單擊保存。?

也可以在字段選項卡打開它的屬性規則

使用以下腳本

//僅允許在邊界內進行編輯

var fsBoundary = FeatureSetByName($datastore, "boundaryClass", ["globalId"], false);

return Count(Intersects(fsBoundary, Geometry($feature))) > 0

添加屬性規則

讓我們測試一下它出來,在boundaryClass中創建面,然后嘗試在邊界外部和內部創建點要素。

僅允許在邊界內進行編輯 實現效果

二、將編輯限制為用戶分配的邊界

所以上面的例子非常簡單明了。有一個或多個邊界,你希望所有用戶確保在邊界內進行編輯。如果更進一步考慮,是否可以使用屬性規則允許某些用戶僅在管理者為其分配的邊界內進行編輯?在上面的例子的基礎上,我們將找出如何做到這一點。請注意,您還可以將相同的想法應用于外業工作和上門工作的訂單。

此示例可通過 ArcGIS Pro 2.5或GeoScene任意版本的產品 和與企業級地理數據庫(Enterprise Geodatabase)的客戶端/服務器連接來完成,該數據庫已注冊到服務器。我正在通過服務使用 ArcGIS Enterprise 11.1,用GeoScene Enterprise也能完成。

首先,我們需要一個額外的表,其中為用戶分配了邊界。創建一個 usersBoundary 表,其中包含一個用戶名的文本字段和一個boundaryGuid 字段表示外鍵到 boundaryClass globalId。我們還將在 boundaryClass usersBoundary 表之間創建一個關系類。您不必創建關系,但它將允許我們將多個用戶分配到邊界,并簡化在 Pro 中編輯表格的過程。

usersBoundary數據結構
創建關系類
本示例用到4個要素類

我們在 pointClass 上需要的最后一件事是啟用編輯器跟蹤。 這就是我們如何通過查看 $feature.last_edited_user 來判斷哪個用戶實際上正在對屬性規則進行編輯。右鍵要素類,管理,開啟編輯者追蹤。

右鍵要素類-管理-啟用編輯者追蹤

好的,目前已經萬事俱備,讓我們將用戶分配到邊界,如下所示:

許工(xugong)只能在邊界'金泰大廈區域'中編輯

張工(zhanggong)僅在邊界'老國展區域'中編輯

謝工(xiegong)只能在邊界'和平里區域' 中編輯


查看屬性表usersBoundary記錄用戶所屬邊界,用戶名應當是拼音,而不是中文
查看工作區分配,用戶名應當為拼音而不是中文

讓我們將 pointClass 上的屬性規則表達式編輯為以下腳本。

//獲得當前用戶

var user = $feature.last_edited_user;

//獲取創建/更新要素的當前邊界

var fsBoundary = FeatureSetByName($datastore, "boundaryClass", ["globalId", "name"], false);

var fsIntersectedBoundaries = Intersects(fsBoundary, Geometry($feature))

//如果不在任何工作區內則報錯

if (Count(fsIntersectedBoundaries) == 0)

? return {"errorMessage": "要素必須創建在工作區內"}

//我們只對第一個相交的工作區感興趣

//我們可以增強這個腳本去遍歷所有工作區

var boundary = First(fsIntersectedBoundaries);

var boundaryGlobalId = boundary.globalId;

//查詢usersBoundary類(表)

var usersBoundary = FeatureSetByName($datastore, "usersBoundary");

//用戶被允許在當前工作區嗎?

var usercanEdit = Count(Filter(usersBoundary, "username = @user AND boundaryGuid = @boundaryGlobalId")) > 0

var bid = boundary.boundaryId

//返回一個友好的提示

if (usercanEdit == false)

? return {"errorMessage": "用戶" + user + " 未被授權編輯區域 " + bid }

return usercanEdit;

在正式使用之前。我們還要引用注冊的數據源,發布要素服務到GeoScene Enterprise 或 ArcGIS Enterprise。以便使用許工、張工這樣的用戶在web端的身份信息,而不是使用連接sde的數據庫的用戶。數據庫用戶往往數量很少且機密較高,不是Web端的最終用戶。

注意:要將pointClass、boundaryClass、usersBoundary 三個要素類一起發布。可以按Ctrl鍵選中多個圖層發布。

引用注冊數據 發布要素圖層

發布成功后,添加被編輯的要素圖層到當前地圖。

添加到當前地圖

讓我們測試一下屬性規則,限制編輯區域的功能。如果我們以 許工 身份登錄,我們將只能在金泰大廈區域內創建要素。嘗試在和平里或老國展邊界內創建要素將失敗,并出現不同的錯誤提示。

許工只能編輯金泰大廈區域

類似地,張工只能編輯老國展區域。

張工只能編輯老國展區域

最后,謝工只能編輯和平里區域。

謝工只能編輯和平里區域

讓我們在瀏覽器端查看在線編輯功能的邊界限制屬性規則依然生效。

網頁端在線編輯,屬性規則依然生效

注意:發布后的屬性規則表達式發生了變化,且為只讀的。所以想要修改屬性規則,需要重新發布。

發布后的屬性規則表達式發生了變化

不過,刪除和更新功能是棘手的。使用我們現在擁有的腳本,謝工可以將要素從任何邊界移動到他的邊界,這是因為我們只檢查幾何 ($feature),這是要素更新后的狀態。因此,如果謝工將老國展區域的要素移動到和平里區域,當前規則會允許這個操作,但其實這個操作是不符合業務邏輯的!

謝工移動其他區域的點到和平里區域

為了實現這一目標,我們需要在ArcGIS Pro 2.5 / 10.8中引入一個名為$originalFeature的新Arcade全局變量。可以在此博客中閱讀有關此內容的更多信息https://www.esri.com/arcgis-blog/products/arcgis-pro/data-management/originalfeature-new-attribute-rules-arcade-global/。

我們希望確保允許 謝工 將要素從其原始幾何中移動,并且還允許他將要素移動到其新位置。我們將使用 Arcade 函數簡化代碼,讓我們將所有代碼放在 canEdit 中,獲取用戶和特征幾何體,我們將基本上執行相同的代碼。

最終腳本https://github.com/hussein-nasser/arcade-scripts/blob/master/restrictBoundaryEditing.js

//function that tells whether the user can edit

function canEdit(user, featureGeo) {

? ? //get the current Boundary the feature is created/updated on.

? ? var fsBoundary = FeatureSetByName($datastore, "restrictedits.owner.boundaryClass", ["globalId", "boundaryId"], false);

? ? var fsIntersectedBoundaries = Intersects(fsBoundary, featureGeo )

? ? //if no boundary error

? ? if (Count(fsIntersectedBoundaries) == 0)

? ? return {"errorMessage": "要素必須創建在工作區內"}


? ? //we are interested in the first boundary

? ? //we can enhnace the script to look for all boundaries

? ? var boundary = First(fsIntersectedBoundaries);

? ? var boundaryGlobalId = boundary.globalId;


? ? //query the usersBoundary class

? ? var usersBoundary = FeatureSetByName($datastore, "restrictedits.owner.usersBoundary");

? ? //is the user allowed to edit this boundary?

? ? var usercanEdit = Count(Filter(usersBoundary, "username = @user AND boundaryGuid = @boundaryGlobalId")) > 0

? ? var boundaryId =? boundary.boundaryId

? ? //return a good error message

? ? return {

? ? "errorMessage": "用戶 @user 未被授權編輯區域 @boundaryId",

? ? "success": usercanEdit

? ? }


}

//code starts here

//get the current user

var user = $feature.last_edited_user;

//get the feature geometry

var featureGeo = Geometry($feature)

//if this was an update get the original geometry (user might have moved the feature)

//$originalFeature geometry is empty when creating new features

if (!isEmpty(Geometry($originalFeature)))

{

? ? //user is moving a feature, this is the original geometry

? ? var originalGeo? = Geometry($originalFeature)

? ? //is she allowed to do so?

? ? var result = canEdit(user,originalGeo);

? ? if (result.success == false)

? ? ? ? return {"errorMessage": result.errorMessage}? ? ?

}

//is the user allowed to create/delete feature (or move a feature_

var result = canEdit(user,featureGeo);

if (result.success == false)

return {"errorMessage": result.errorMessage}? ? ?

//if we reach here we are good.

return true;

//update

使用屬性規則執行此操作的好處是,使用要素服務的任何客戶端都將獲得此行為,無論是通過 Pro、Web 編輯器還是Collector(已連接)。 您也可以編寫服務器端代碼(如 SOE 或 SOI)來實現類似的方案。

請注意,上面的代碼僅用于演示目的,將許多用戶單獨分配到邊界變得難以管理。因此,我們正在考慮解決此問題的更好方法,例如通過在 Arcade 中引入門戶訪問控制,以便我們可以以群組作為單位做記錄級權限控制而不僅是對個人用戶的編輯操作做記錄級權限控制。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容