Plan.cshtml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. @using WePlatform.Configuration
  2. @using WePlatform.Authorization
  3. @using WePlatform.Views.Shared.Modals
  4. @{
  5. ViewBag.Title = "应急预案管理";
  6. string activeMenu = PermissionNames.PagesResourceMgGuideMgPlanMg; //The menu item will be active for this page.
  7. ViewBag.ActiveMenu = activeMenu;
  8. }
  9. @section css{
  10. <link href="~/Content/Libs/jstree/themes/proton/style.min.css" rel="stylesheet" />
  11. <style>
  12. .vakata-context, .vakata-context ul {
  13. z-index: 1;
  14. }
  15. #plan-tree {
  16. min-height: calc(100vh - 110px);
  17. background: #000000;
  18. background: rgba(0,0,0,.02);
  19. }
  20. .search-icon .input-group-text {
  21. background: #007bff;
  22. color: #eee;
  23. cursor: pointer;
  24. }
  25. .search-icon .input-group-text:hover {
  26. color: #fff;
  27. }
  28. .tool-more {
  29. width: 100%;
  30. height: 150px;
  31. background: linear-gradient(rgba(255, 255, 255, .8), rgba(255, 255, 255, 1));
  32. position: absolute;
  33. bottom: 0;
  34. display: flex;
  35. justify-content: center;
  36. align-items: center;
  37. }
  38. .plan-no-content {
  39. margin-top: 50px;
  40. text-align: center;
  41. }
  42. .plan-no-content span {
  43. margin: 20px auto;
  44. font-size: 24px;
  45. font-weight: 600;
  46. display: inline-block;
  47. }
  48. .content-info {
  49. --mainColor: #007bff;
  50. border: 2px solid var(--mainColor);
  51. margin: 15px 0;
  52. border-radius: 5px;
  53. position: relative;
  54. }
  55. .content-info .title {
  56. border-bottom: 1px solid var(--mainColor);
  57. color: var(--mainColor);
  58. padding: 5px 10px;
  59. font-weight: 600;
  60. display: flex;
  61. align-items: center;
  62. justify-content: center;
  63. }
  64. .content-info .text {
  65. padding: 5px 10px;
  66. word-break: break-all;
  67. min-height: 60px;
  68. display: flex;
  69. /*align-items: center;*/
  70. flex-direction: column;
  71. }
  72. .content-info .tool {
  73. border-top: 1px solid var(--mainColor);
  74. padding: 5px 10px;
  75. display: flex;
  76. align-items: center;
  77. justify-content: space-between;
  78. }
  79. .content-info .tool:not(:last-child) {
  80. border-bottom: 1px solid var(--mainColor);
  81. }
  82. .content-info .tool .version-box {
  83. font-weight: 600;
  84. min-width: 100px;
  85. }
  86. .content-info .tool .word-box {
  87. font-weight: 600;
  88. min-width: 300px;
  89. text-align: center;
  90. }
  91. .content-info .tool .btn-box {
  92. min-width: 280px;
  93. text-align: right;
  94. }
  95. .content-info .tool .btn {
  96. margin: 0 8px;
  97. }
  98. </style>
  99. }
  100. <div class="row">
  101. <div class="col-sm-3" style="overflow-x: hidden; padding-right: 0;">
  102. <div class="scroll">
  103. <div id="plan-tree"></div>
  104. </div>
  105. </div>
  106. <div class="col-sm-9">
  107. <div class="tool-box">
  108. <div class="row">
  109. <div class="col-sm-6">
  110. <div class="input-group ">
  111. <input type="text" id="keywords-search" class="form-control" value="" placeholder="根据关键字查询,多个关键字以空格分隔"/>
  112. <div class="input-group-append search-icon" style="cursor: pointer;" onclick="RefreshContent()">
  113. <span class="input-group-text" style=""><i class="fa fa-search"></i>&nbsp;查询</span>
  114. </div>
  115. </div>
  116. </div>
  117. </div>
  118. </div>
  119. <div class="scroll" style="height: calc(100vh - 150px)">
  120. <div id="plan-content" style="position: relative;">
  121. </div>
  122. </div>
  123. </div>
  124. </div>
  125. @*@Html.Partial("Table/_Table", table)*@
  126. @section modal{
  127. <!--Main Modal-->
  128. @{
  129. var modal = new ModalViewModel("预案", new ModalBodyViewModel(new List<Input>()
  130. {
  131. new InputHide("id"),
  132. new InputHide("parentNo"),
  133. new InputHide("path"),
  134. new Input("parentName", "父预案").SetDisabled(),
  135. new Input("name", "名称"),
  136. new InputTextarea("description", "描述").SetNotRequired(),
  137. }));
  138. var modalContent = new ModalViewModel("预案内容", new ModalBodyViewModel(new List<Input>()
  139. {
  140. new InputHide("id"),
  141. new InputHide("planNo"),
  142. new Input("planName", "预案名称").SetDisabled(),
  143. new Input("keyWord", "关键字").SetHelp("多个关键字以“,”分隔!"),
  144. //new Input("version", "预案版本"),
  145. new InputKindeditor("planContent", "内容"),
  146. }, "content-form"), "content-modal");
  147. }
  148. @Html.Partial("Modals/_Modal", modal)
  149. @Html.Partial("Modals/_Modal", modalContent)
  150. }
  151. @section scripts
  152. {
  153. <script src="~/Content/Libs/jstree/jstree.min.js"></script>
  154. <script type="text/javascript">
  155. var curPlanNo = '', curPlanName = '';
  156. $(function() {
  157. OverlayScrollbar($('.scroll'));
  158. $('#plan-tree')
  159. .jstree({
  160. 'core': {
  161. 'data': GetNode,
  162. 'strings': {
  163. 'Loading ...': '请稍后...'
  164. },
  165. 'force_text': true,
  166. 'check_callback': true,
  167. 'themes': {
  168. 'name': 'proton',
  169. 'responsive': true,
  170. 'variant': 'large'
  171. }
  172. },
  173. contextmenu: {
  174. items: Actions
  175. },
  176. 'plugins': ['contextmenu', 'wholerow'] // 'state',
  177. })
  178. .on('ready.jstree',
  179. function(e, data) {
  180. //console.log('000', e, data);
  181. var inst = data.instance,
  182. obj = inst.get_node('@(IwbConsts.EmergencyPlanRootNo)');
  183. inst.open_node(obj);
  184. inst.select_node(obj);
  185. curPlanNo = '';
  186. curPlanName = '';
  187. RefreshContent(true);
  188. })
  189. //.on('create_node.jstree', function (e, data) {console.log(1);}).on('rename_node.jstree', function (e, data) {console.log(2);}).on('delete_node.jstree', function (e, data){console.log(3);}).on('changed.jstree', function (e, data) {console.log('222');})
  190. .on('activate_node.jstree',
  191. function(e, data) {
  192. //console.log('111',data);
  193. curPlanNo = data.node.id == '@(IwbConsts.EmergencyPlanRootNo)' ? "" : data.node.id;
  194. curPlanName = data.node.text;
  195. RefreshContent(true);
  196. });
  197. });
  198. function GetNode(node, callback) {
  199. $.iwbAjax4({
  200. url: abp.appUrl + 'EmergencyPlan/GetChildPlan',
  201. data: { id: node.id },
  202. success: function(res) {
  203. if (callback) {
  204. callback.call(this, res);
  205. } else {
  206. $("#plan-tree").html("暂无数据!");
  207. }
  208. }
  209. });
  210. }
  211. function Actions(o, cb) {
  212. console.log(o.id);
  213. if (cb) {
  214. // cb.call(this, o);
  215. }
  216. var actions = {};
  217. actions.create = {
  218. "separator_before": false,
  219. "separator_after": true,
  220. "_disabled": @(IsGranted(PermissionNames.PagesResourceMgGuideMgPlanMgCreate) ? "false" : "true"), //(this.check("create_node", data.reference, {}, "last")),
  221. "label": "添加子预案",
  222. // "title": "添加子预案",
  223. "icon": "far fa-plus-square",
  224. "action": function(data) {
  225. var inst = $.jstree.reference(data.reference),
  226. obj = inst.get_node(data.reference);
  227. console.log('CREATE');
  228. OpenModal({
  229. modal: 'modal',
  230. url: abp.appUrl + 'EmergencyPlan/create',
  231. data: { id: "", parentNo: obj.id, parentName: obj.text },
  232. success: function() {
  233. inst.refresh_node(obj);
  234. inst.open_node(obj);
  235. }
  236. });
  237. }
  238. };
  239. actions.rename = {
  240. "separator_before": false,
  241. "separator_after": false,
  242. "_disabled": @(IsGranted(PermissionNames.PagesResourceMgGuideMgPlanMgUpdate) ? "false" : "true"), //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")),
  243. "label": "修改预案",
  244. //"title": "修改预案",
  245. /*!
  246. "shortcut" : 113,
  247. "shortcut_label" : 'F2',
  248. "icon" : "far fa-plus-square",
  249. */
  250. "icon": "far fa-edit",
  251. "action": function(data) {
  252. var inst = $.jstree.reference(data.reference),
  253. obj = inst.get_node(data.reference);
  254. console.log('UPDATE');
  255. $.iwbAjax4({
  256. url: abp.appUrl + 'EmergencyPlan/getDtoById?id=' + obj.id,
  257. success: function(res) {
  258. if (res) {
  259. var parent = inst.get_node(obj.parent);
  260. OpenModal({
  261. modal: 'modal',
  262. url: abp.appUrl + 'EmergencyPlan/update',
  263. data: {
  264. id: res.id,
  265. path: res.path,
  266. parentNo: res.parentNo,
  267. parentName: parent.text,
  268. name: res.name,
  269. description: res.description
  270. },
  271. success: function() {
  272. inst.refresh_node(parent);
  273. }
  274. });
  275. }
  276. }
  277. });
  278. }
  279. };
  280. actions.remove = {
  281. "separator_before": false,
  282. "separator_after": false,
  283. "_disabled": @(IsGranted(PermissionNames.PagesResourceMgGuideMgPlanMgDelete) ? "false" : "true"), //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")),
  284. "label": "删除预案",
  285. "title": "删除预案",
  286. "icon": "far fa-minus-square",
  287. "action": function(data) {
  288. var inst = $.jstree.reference(data.reference),
  289. obj = inst.get_node(data.reference);
  290. var parent = inst.get_node(obj.parent);
  291. console.log('DELETER');
  292. MsgConfirm("您确认删除此预案吗?",
  293. "确认删除",
  294. function() {
  295. $.iwbAjax1({
  296. url: abp.appUrl + 'EmergencyPlan/delete',
  297. data: { id: obj.id },
  298. success: function() {
  299. inst.refresh_node(parent);
  300. RefreshContent();
  301. }
  302. });
  303. });
  304. //if (inst.is_selected(obj)) {
  305. // inst.delete_node(inst.get_selected());
  306. //} else {
  307. // inst.delete_node(obj);
  308. //}
  309. }
  310. };
  311. actions.planContent = {
  312. "separator_before": false,
  313. "separator_after": false,
  314. "_disabled": @(IsGranted(PermissionNames.PagesResourceMgGuideMgPlanMgUpdate) ? "false" : "true"), //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")),
  315. "label": "增加内容",
  316. //"title": "增加内容",
  317. "icon": "far fa-plus-square",
  318. "action": function(data) {
  319. var inst = $.jstree.reference(data.reference),
  320. obj = inst.get_node(data.reference);
  321. curPlanNo = obj.id;
  322. curPlanName = obj.text;
  323. AddPlanContent();
  324. }
  325. };
  326. return actions;
  327. }
  328. function AddPlanContent(data) {
  329. console.log('CONTENT');
  330. data = data || { id: '', planContent: '', keyWord: '', planNo: curPlanNo, planName: curPlanName };
  331. if (!data.planNo) {
  332. abp.message.warn('请在在左边选择(激活)一个预案,再添加内容!', "添加失败");
  333. return;
  334. }
  335. OpenModal({
  336. modal: 'content-modal',
  337. modaltitle: data.id ? '修订' : '增加',
  338. url: abp.appUrl + 'EmergencyPlan/UpdatePlanContent',
  339. data:data,
  340. success: function() {
  341. RefreshContent();
  342. }
  343. });
  344. }
  345. function UpdatePlanContent(that) {
  346. var $that = $(that).closest('.content-info');
  347. var data = { id: $that.data('id'), planContent: $that.find('.text').html(), keyWord: $that.find('.keyword').text(), planNo: $that.data('plan-no'), planName : $that.data('plan-name')}
  348. AddPlanContent(data);
  349. }
  350. function DeleteContent(that) {
  351. var $that = $(that).closest('.content-info');
  352. $.iwbAjax1({
  353. url: abp.appUrl + 'EmergencyPlan/DeletePlanContent',
  354. data: {
  355. id: $that.data('id')
  356. },
  357. success: function () {
  358. RefreshContent();
  359. }
  360. });
  361. }
  362. function SetUse(that) {
  363. var $that = $(that).closest('.content-info');
  364. $.iwbAjax1({
  365. url: abp.appUrl + 'EmergencyPlan/SetUse',
  366. data: {
  367. id: $that.data('id')
  368. },
  369. success: function () {
  370. RefreshContent();
  371. }
  372. });
  373. }
  374. </script>
  375. <script>
  376. var take = @(IwbConsts.TakeCount) ;
  377. function RefreshContent() {
  378. $('#plan-content').empty();
  379. GetPlanContent(true);
  380. }
  381. function GetPlanContent(isNew) {
  382. console.log('curPlanNo', curPlanNo);
  383. var skip = $('#plan-content .content-info').length, keyWords = [], isGlobal = false;
  384. if (!isNew) {
  385. isGlobal = $('#global-search').is(':checked');
  386. }
  387. var keyStr = $('#keywords-search').val();
  388. if (keyStr) {
  389. keyWords = keyStr.split(' ');
  390. }
  391. $.iwbAjax4({
  392. url: abp.appUrl + 'EmergencyPlan/GetPlanContent',
  393. data: {
  394. planNo: curPlanNo,
  395. keyWords: keyWords,
  396. skip: skip,
  397. take: take,
  398. isGlobal: isGlobal
  399. },
  400. success: function (res) {
  401. PlanContentsFormatter(res, isNew);
  402. }
  403. });
  404. }
  405. function PlanContentsFormatter(data, isNew) {
  406. var str = '', more = ' <div class="tool-more"><button class="btn btn-danger" style="width: 120px;" onclick="GetPlanContent()">查看更多...</button></div>';
  407. $('.plan-no-content').remove();
  408. if (data && data.length) {
  409. data.forEach(function (v) {
  410. str += PlanContentFormatter(v);
  411. });
  412. $('#plan-content').append(str);
  413. if (data.length < take) {
  414. $('.tool-more').remove();
  415. } else {
  416. $('#plan-content').append(more);
  417. }
  418. } else if (isNew) {
  419. $('#plan-content')
  420. .html(
  421. '<div class="plan-no-content"><span>预案暂无内容</span><br/> <button class="btn btn-success" style="width: 120px;" onclick=" AddPlanContent()">新增内容</button></div>');
  422. $('.tool-more').remove();
  423. } else {
  424. $('.tool-more').remove();
  425. }
  426. }
  427. function PlanContentFormatter(data) {
  428. var str = '';
  429. if (data) {
  430. var isUse = data.isUse ? "use" : "";
  431. str += '<div class="content-info {0}" data-id="{1}" data-plan-no="{2}" data-plan-name="{3}">'.format(isUse, data.id, data.planNo, data.planName);
  432. str += '<div class="title">{0}</div>'.format(data.planName);
  433. str += '<div class="text">{0}</div>'.format(data.planContent);
  434. str += '<div class="tool">';
  435. str += '<div class="version-box">版本:V<span class="version">{0}</span></div>'.format(data.version);
  436. str += '<div class="">关键字:<span class="keyword">{0}</span></div>'.format(data.keyWord);
  437. str += '<div class="btn-box">';
  438. str += data.isUse ? '<button class="btn btn-sm btn-success" disabled type="button">正在使用</button>' : '<button class="btn btn-sm btn-danger" onclick="DeleteContent(this)" type="button">删除版本</button><button class="btn btn-sm btn-warning" onclick="SetUse(this)" type="button">使用版本</button>';
  439. str += '<button class="btn btn-sm btn-primary" onclick="UpdatePlanContent(this)" type="button">修订版本</button>';
  440. str += '</div>';
  441. str += '</div>';
  442. str += '</div>';
  443. }
  444. return str;
  445. }
  446. </script>
  447. <!--格式化-->
  448. <script id="formatter-script" type="text/javascript">
  449. function TypeFormatter(v) {
  450. var name = $('#hid-type option[value="' + v + '"]').text();
  451. switch (v) {
  452. case 0:
  453. return '<span class="label label-danger">' + name + '</span>';
  454. default:
  455. return '<span class="label label-info">' + name + '</span>';
  456. }
  457. }
  458. </script>
  459. }
  460. <section style="display: none">
  461. <select id="hid-type">
  462. <option value=""></option>
  463. </select>
  464. @*@Html.DropDownList("hid-type", type)*@
  465. </section>