efront 3.7.1 → 3.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,5 +4,5 @@
4
4
  share: options ::share-:opt?:path
5
5
  folder: options ::file-:opt:::path?:to
6
6
  cluster: options ::cluster-:opt?:id
7
- private-list: options ::private
8
- private-edit: options ::private-:key?:value
7
+ list: options :::type
8
+ edit: options :::type-:key?:value
@@ -4,7 +4,6 @@ var fields = refilm`
4
4
  服务器地址/host* select?a ${hosts}
5
5
  密码/password* password
6
6
  `;
7
- console.log(fields)
8
7
  function main() {
9
8
  var page = view();
10
9
  page.innerHTML = login;
@@ -1,5 +1,5 @@
1
1
  <div class="clusters">
2
- <a -repeat="(c,i) in clusters" @click="active(i)">
2
+ <a -repeat="(c,i) in clusters" ng-class="{current:i===index}" @click="active(i,c)">
3
3
  <span -text="c"></span>
4
4
  </a>
5
5
  </div>
@@ -7,6 +7,6 @@
7
7
  <padding>
8
8
  <span -text=c.id></span>
9
9
  <span class="time" -text=filterTime(c.optime)></span>
10
-
10
+
11
11
  </padding>
12
12
  </lattice>
@@ -3,21 +3,21 @@ function main() {
3
3
  page.innerHTML = template;
4
4
  renderWithDefaults(page, {
5
5
  async load() {
6
- var cs = this.clusters = data.from("cluster", { opt: "list" });
7
- await cs.loading_promise;
6
+ this.clusters = data.from("cluster", { opt: "list" });
7
+ await this.clusters;
8
8
  this.active();
9
9
  },
10
- index: 0,
10
+ index: data.getInstance("index").index || 0,
11
11
  clusters: [],
12
12
  filterTime(d) {
13
13
  return ((new Date - d) / 1000 | 0) + "秒";
14
14
  },
15
15
  clients: [],
16
- async active() {
17
- var index = this.index;
16
+ active(index = this.index) {
17
+ data.setInstance('index', { index });
18
18
  var clusters = this.clusters;
19
19
  if (index >= clusters.length) index = clusters.length - 1;
20
- this.clients = data.lazyInstance("cluster", { opt: "list", id: clusters[index] });
20
+ this.clients = data.from("cluster", { opt: "list", id: clusters[index] });
21
21
  },
22
22
  });
23
23
  page.$scope.load();
@@ -6,4 +6,9 @@
6
6
 
7
7
  .time {
8
8
  color: #bbb;
9
+ }
10
+
11
+ .button.current {
12
+ background: #28c;
13
+ color: #fff;
9
14
  }
@@ -1,7 +1,11 @@
1
1
  首页: /home/welcome
2
- 共享目录管理: /share/list
3
- 短链接: /home/short
4
- WEB文件管理: /wow/root
5
- 长连接管理: /link/list
6
- 密钥管理: /token/list
2
+ WEB:
3
+ 共享目录: /share/list
4
+ 短链接: /home/short
5
+ 文件管理: /wow/root
6
+ 长连接管理: /link/list
7
+ 任务:
8
+ 密钥管理: /token/list
9
+ 任务建立: /task/list
10
+ 定期执行: /tick/list
7
11
  # 用户列表: /user/list
@@ -0,0 +1 @@
1
+ pedit.bind(null, "任务", "task");
@@ -0,0 +1,6 @@
1
+ plist.bind(null, '任务管理', "task", refilm`
2
+ *任务ID/key 100
3
+ *任务名/name 100
4
+ *启用/status swap [关闭,开启]
5
+ 任务代码/code text
6
+ `, '/task/edit');
@@ -0,0 +1,5 @@
1
+ function main() {
2
+ var a = div();
3
+ a.innerHTML = "定时任务管理,敬请期待";
4
+ return a;
5
+ }
@@ -1,9 +1 @@
1
- frame$edit.bind(null, "密钥", {
2
- submit(a) {
3
- return data.from("private-edit", {
4
- key: encode62.timeencode(a.key),
5
- value: encode62.timeencode(JSON.stringify(a)),
6
- }).loading_promise;
7
- },
8
-
9
- });
1
+ pedit.bind(null, "密钥", "private");
@@ -1,13 +1,6 @@
1
- frame$list.bind(null, "密钥管理", {
2
- load() {
3
- return data.from("private-list", a => JSAM.parse(encode62.timedecode(a)));
4
- },
5
- remove(o) {
6
- return data.from("private-edit", { key: encode62.timeencode(o.key), value: encode62.timeencode("") }).loading_promise;
7
- },
8
- fields: refilm`
9
- 显示名/name input
10
- *键名/key
11
- 密钥/value
12
- 备注/comment
13
- `}, "/token/edit");
1
+ plist.bind(null, '密钥管理', "private", refilm`
2
+ *键名/key 100
3
+ 显示名/name input/300
4
+ 密钥/value text/100
5
+ 备注/comment text/200
6
+ `, "/token/edit");
@@ -1,6 +1,6 @@
1
1
  var d = 0b10000000, s = 0b00111111;
2
2
  function numberUTF8(t, dist = []) {
3
- if (t < 127) {//0b0xxxxxxx - 0b10xxxxxx
3
+ if (t < 128) {//0b0xxxxxxx - 0b10xxxxxx
4
4
  dist.push(0b00000000 | t)
5
5
  }
6
6
  else if (t < 2048) {// 0b110xxxxx 10xxxxxx
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  module.exports = encode62;
3
+ var encodeUTF8 = require("../basic/encodeUTF8");
4
+ var decodeUTF8 = require("../basic/decodeUTF8");
3
5
  var src = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4
6
  var map = {};
5
7
  src.split("").forEach((s, i) => map[s] = i);
@@ -69,6 +71,20 @@ Object.assign(encode62, {
69
71
  });
70
72
  return result;
71
73
  },
74
+ encodestr(data, sign) {
75
+ if (!sign) return data;
76
+ var result = encodeUTF8(data);
77
+ sign = Buffer.from(sign);
78
+ var delta = 0, c = 0;
79
+ for (var cx = 0, dx = data.length; cx < dx; cx++) {
80
+ if (result[cx] < 128) result[cx] = result[cx] ^ sign[cx % sign.length];
81
+ else if (result[cx] < 192) {
82
+ var c = c << 8 | sign[(delta += 6) / 8 % sign.length | 0];
83
+ result[cx] = result[cx] ^ (c >> 8 - delta % 8 & 0x3f);
84
+ }
85
+ }
86
+ return decodeUTF8(result);
87
+ },
72
88
  decode(data, sign) {
73
89
  if (!sign) return data;
74
90
  var result = Buffer.from(data);
@@ -101,5 +117,6 @@ Object.assign(encode62, {
101
117
  encode62.ab2c = encode62.ba2d = encode62.huan;
102
118
  encode62.db2a = encode62.ca2b = encode62.yuan;
103
119
  encode62.da2b = encode62.cb2a = encode62.suan;
120
+ encode62.decodestr = encode62.encodestr;
104
121
  encode62.encode = encode62.decode;
105
122
  encode62.decode62 = encode62.encode62;
@@ -18,7 +18,7 @@ function main(title, { submit }, { data: origin, fields, }) {
18
18
  });
19
19
  on('submit')(page, async function (e) {
20
20
  e.preventDefault();
21
- await submit(item);
21
+ await submit(item, fields);
22
22
  dispatch(this, 'submited');
23
23
  remove(this);
24
24
  });
@@ -0,0 +1,3 @@
1
+ &{
2
+ width: 600px;
3
+ }
@@ -1,4 +1,4 @@
1
- function main(title, { fields, load, remove }, edit_ref) {
1
+ function main(title, { fields, options: options0, load, remove }, edit_ref) {
2
2
  prepare(edit_ref);
3
3
  var page = document.createElement("div");
4
4
  var edit = function (o) {
@@ -11,6 +11,40 @@ function main(title, { fields, load, remove }, edit_ref) {
11
11
  })
12
12
  };
13
13
  page.innerHTML = template;
14
+ var options = [
15
+ {
16
+ name: "修改",
17
+ do(o) {
18
+ edit(o);
19
+ },
20
+ },
21
+ {
22
+ type: "danger",
23
+ name(o) {
24
+ return this.confirm === o ? "确认删除" : "删除";
25
+ },
26
+ type(o) {
27
+ return this.confirm === o ? "dark" : "danger";
28
+ },
29
+ confirm: false,
30
+ timer: 0,
31
+ async do(o) {
32
+ if (this.confirm !== o) {
33
+ this.confirm = o;
34
+ clearTimeout(this.timer);
35
+ var that = this;
36
+ this.timer = setTimeout(function () {
37
+ that.confirm = null;
38
+ render.refresh();
39
+ }, 2000);
40
+ return;
41
+ }
42
+ await remove(o);
43
+ page.$scope.load();
44
+ }
45
+ }
46
+ ];
47
+ if (options0) options = options.concat(options0);
14
48
  renderWithDefaults(page, {
15
49
  title,
16
50
  load() {
@@ -18,39 +52,7 @@ function main(title, { fields, load, remove }, edit_ref) {
18
52
  },
19
53
  fields: fields.concat({
20
54
  name: "操作",
21
- options: [
22
- {
23
- name: "修改",
24
- do(o) {
25
- edit(o);
26
- },
27
- },
28
- {
29
- type: "danger",
30
- name(o) {
31
- return this.confirm === o ? "确认删除" : "删除";
32
- },
33
- type(o) {
34
- return this.confirm === o ? "dark" : "danger";
35
- },
36
- confirm: false,
37
- timer: 0,
38
- async do(o) {
39
- if (this.confirm !== o) {
40
- this.confirm = o;
41
- clearTimeout(this.timer);
42
- var that = this;
43
- this.timer = setTimeout(function () {
44
- that.confirm = null;
45
- render.refresh();
46
- }, 2000);
47
- return;
48
- }
49
- await remove(o);
50
- page.$scope.load();
51
- }
52
- }
53
- ]
55
+ options
54
56
  }),
55
57
  data: [],
56
58
  add() {
@@ -1,3 +1,25 @@
1
- btn{
1
+ btn {
2
2
  padding: 0 16px;
3
+ }
4
+
5
+ & {
6
+ height: 100%;
7
+ overflow: auto;
8
+ }
9
+
10
+ table {
11
+
12
+ td {
13
+
14
+ >span,
15
+ >model {
16
+ white-space: normal;
17
+ word-break: break-all;
18
+ overflow: hidden;
19
+ display: -webkit-box;
20
+ -webkit-line-clamp: 2;
21
+ -webkit-box-orient: vertical;
22
+ text-overflow: ellipsis;
23
+ }
24
+ }
3
25
  }
@@ -1,4 +1,5 @@
1
1
  & {
2
2
  border-top-width: 0;
3
3
  width: 100%;
4
+ overflow: auto;
4
5
  }
@@ -0,0 +1,13 @@
1
+ function main(title, type, params) {
2
+ return frame$edit(title, {
3
+ submit(a, fields) {
4
+ a = submit(fields, a);
5
+ return data.from("edit", {
6
+ type,
7
+ key: encode62.timeencode(a.key),
8
+ value: encode62.timeencode(JSON.stringify(a)),
9
+ }).loading_promise;
10
+ },
11
+
12
+ }, params);
13
+ }
@@ -0,0 +1,13 @@
1
+
2
+ function main(title, type, fields, edit_ref, options) {
3
+ return frame$list(title, {
4
+ load() {
5
+ return data.from("list", { type }, a => JSAM.parse(encode62.timedecode(a)));
6
+ },
7
+ remove(o) {
8
+ return data.from("edit", { type, key: encode62.timeencode(o.key), value: encode62.timeencode("") }).loading_promise;
9
+ },
10
+ fields,
11
+ options,
12
+ }, edit_ref);
13
+ }
@@ -0,0 +1,27 @@
1
+ // class LoadingArray extends Array {
2
+ // totalCount = 0;
3
+ // data = [];
4
+ // is_errored = null;
5
+ // error_message = null;
6
+ // is_loading = true;
7
+ // is_loaded = false;
8
+ // is_readonly = null;
9
+ // loading = null;
10
+ // loading_promise = null;
11
+ // then (ok, oh) {
12
+ // if (this.loading_promise) this.loading_promise.then(ok, oh);
13
+ // }
14
+ // }
15
+ function LoadingArray() {
16
+ var this0 = [];
17
+ this0.totalCount = 0;
18
+ this0.data = [];
19
+ this0.is_errored = null;
20
+ this0.error_message = null;
21
+ this0.is_loading = true;
22
+ this0.is_loaded = false;
23
+ this0.is_readonly = null;
24
+ this0.loading = null;
25
+ this0.loading_promise = null;
26
+ return this0;
27
+ };
@@ -402,6 +402,12 @@ function createApiMap(data) {
402
402
  }
403
403
  var _configfileurl;
404
404
  var configPormise;
405
+ function LoadingArray_then(ok, oh) {
406
+ if (this.loading_promise) this.loading_promise.then(ok, oh);
407
+ else if (this.is_errored) oh(this.error_message);
408
+ else ok();
409
+ }
410
+
405
411
  var privates = {
406
412
  loadAfterConfig(serviceId, params) {
407
413
  var promise = this.getApi(serviceId).then((api) => {
@@ -622,6 +628,7 @@ var data = {
622
628
  if (isObject(response)) {
623
629
  response.is_loaded = true;
624
630
  response.is_loading = false;
631
+ if (response.then === LoadingArray_then) delete response.then;
625
632
  }
626
633
  this.loading_count--;
627
634
  },
@@ -630,6 +637,7 @@ var data = {
630
637
  if (isObject(response)) {
631
638
  response.is_loaded = false;
632
639
  response.is_loading = true;
640
+ response.then = LoadingArray_then;
633
641
  }
634
642
  this.loading_count++;
635
643
  },
@@ -37,6 +37,17 @@ var renderModel = function (field, data) {
37
37
  var constructors = {
38
38
  input,
39
39
  raw: input,
40
+ swap(e) {
41
+ var { field } = e;
42
+ e = swap(e);
43
+ if (field.options) {
44
+ e.getValue = function () {
45
+ return field.options[+this.checked].value;
46
+ };
47
+ }
48
+ return e;
49
+ },
50
+ switch: swap,
40
51
  row: textarea,
41
52
  password,
42
53
  text: textarea,
@@ -134,8 +145,18 @@ var readonly_types = {
134
145
  "size"({ field }, data) {
135
146
  var f = data[field.key];
136
147
  return size(f);
137
- }
148
+ },
149
+ swap(e, data) {
150
+ var { field } = e;
151
+ var v = data[field.key];
152
+ if (field.options) {
153
+ var o = field.options[v];
154
+ if (o) return o.name;
155
+ }
156
+ return v;
157
+ },
138
158
  };
159
+ readonly_types.select = readonly_types.swap;
139
160
  function main(elem) {
140
161
  var build = function () {
141
162
  var { data, readonly, field } = elem;
@@ -222,7 +243,6 @@ function main(elem) {
222
243
  }
223
244
  };
224
245
  on("changes")(elem, function ({ changes }) {
225
-
226
246
  if (changes.data || changes.field || changes.readonly) {
227
247
  build();
228
248
  }
@@ -90,7 +90,7 @@ var initialComment = function (renders, type, expression) {
90
90
  var parseRepeat = function (expression) {
91
91
  var reg =
92
92
  // /////////////////////////////////////////// i // r ///////////////////////// o ///// a ///////////////////// t /////
93
- /^(?:let\b|var\b|const\b)?\s*(?:[\(\{\[]\s*)?(.+?)((?:\s*,\s*.+?)*)?(?:\s*[\)\}\]]\s*|\s+)(in|of)\s+(.+?)(\s+?:track\s*by\s+(.+?))?$/i;
93
+ /^(?:let\b|var\b|const\b)?\s*(?:[\(\{\[]\s*)?(.+?)((?:\s*,\s*.+?)*)?(?:\s*[\)\}\]]\s*|\s+)(in|of)\s+(.+?)(?:\s+track\s*by\s+(.+?))?$/i;
94
94
  var res = reg.exec(expression);
95
95
  if (!res) return res;
96
96
  var [_, i, k, r, s, t] = res;
@@ -125,7 +125,7 @@ var createRepeat = function (search, id = 0) {
125
125
  var [context, expression] = search;
126
126
  var res = parseRepeat(expression);
127
127
  if (!res) throw new Error(`不能识别循环表达式: ${expression} `);
128
- var { keyName, itemName, indexName, srcName } = res;
128
+ var { keyName, itemName, indexName, srcName, trackBy } = res;
129
129
  // 懒渲染
130
130
  var getter = createGetter([context, srcName]).bind(this);
131
131
  var element = this, clonedElements = [], savedValue, savedOrigin;
@@ -151,17 +151,26 @@ var createRepeat = function (search, id = 0) {
151
151
  var clonedElements1 = Object.create(null);
152
152
  var cloned = keys.map(function (key, cx) {
153
153
  var k = isArrayResult ? cx : key;
154
- var c = changes[k];
155
- if (clonedElements[k]) if (!c || !isObject(c.previous) && !isObject(c.current)) return clonedElements1[k] = clonedElements[k];
156
- var clone = element.cloneNode();
157
- clone.innerHTML = element.innerHTML;
158
- clone.renderid = id;
159
- clone.$parentScopes = $parentScopes;
160
154
  var $scope = {
161
155
  [keyName || '$key']: k,
162
156
  [itemName || '$item']: result[k],
163
157
  [indexName || '$index']: cx
164
158
  };
159
+ if (trackBy) {
160
+ k = seek($scope, trackBy);
161
+ if (clonedElements[k]) {
162
+ clonedElements[k].$scope = $scope;
163
+ return clonedElements1[k] = clonedElements[k];
164
+ }
165
+ }
166
+ else {
167
+ var c = changes[k];
168
+ if (clonedElements[k]) if (!c || !isObject(c.previous) && !isObject(c.current)) return clonedElements1[k] = clonedElements[k];
169
+ }
170
+ var clone = element.cloneNode();
171
+ clone.innerHTML = element.innerHTML;
172
+ clone.renderid = id;
173
+ clone.$parentScopes = $parentScopes;
165
174
  clone.$scope = $scope;
166
175
  clone.$parentScopes = $parentScopes;
167
176
  clone.$struct = $struct;
@@ -556,7 +565,8 @@ function getFromScopes(key, scope, parentScopes) {
556
565
  if (key in scope) {
557
566
  return scope[key];
558
567
  }
559
- if (parentScopes) for (var o of parentScopes) {
568
+ if (parentScopes) for (var cx = parentScopes.length - 1; cx >= 0; cx--) {
569
+ var o = parentScopes[cx];
560
570
  if (key in o) {
561
571
  return o[key];
562
572
  }
@@ -30,7 +30,7 @@
30
30
  -o-appearance: none;
31
31
  appearance: none;
32
32
  &:before {
33
- background-color: #26f;
33
+ background-color: #28c;
34
34
  transition: all .1s ease-out;
35
35
  left: 50%;
36
36
  top: 50%;
@@ -1,14 +1,15 @@
1
1
  <thead>
2
2
  <tr>
3
- <td -repeat="f in fields"><i -if="f.icon" -class="f.icon"></i></span><span -if="f.name" -html="f.name"></span>
3
+ <td -repeat="f in fields track by f.id" :style="{width:f.width}"><i -if="f.icon"
4
+ -class="f.icon"></i></span><span -if="f.name" -html="f.name"></span>
4
5
  </td>
5
6
  </tr>
6
7
  </thead>
7
8
  <tbody -src="d in data">
8
9
  <tr>
9
10
  <td -repeat="f in fields">
10
- <span -if="f.key" -text="d[f.key]"></span>
11
- <a on-click="o.do(d)" -if="f.options" _type="o.type instanceof Function?o.type(d):o.type"
11
+ <model -if="f.key" :field=f :data=d readonly ></model>
12
+ <a on-click="o.do(d)" -if="!f.key&&f.options" _type="o.type instanceof Function?o.type(d):o.type"
12
13
  -repeat="o in f.options">
13
14
  <span -text="o.name instanceof Function?o.name(d):o.name"></span>
14
15
  </a>
@@ -95,7 +95,7 @@ var adaptTarget = function (event) {
95
95
  target = this;
96
96
  return;
97
97
  }
98
- css(this, { 'cursor': 'e-resize' });
98
+ css(document.body, { 'cursor': 'col-resize' });
99
99
  result = {
100
100
  target,
101
101
  restX: event.clientX - target.offsetWidth
@@ -106,18 +106,66 @@ var adaptTarget = function (event) {
106
106
  }
107
107
  if (!result) {
108
108
  this.resizing = false;
109
- css(this, { 'cursor': 'default' });
109
+ css(document.body, { 'cursor': '' });
110
110
  }
111
111
  };
112
112
  var tdElementReg = /^t[hd]$/i;
113
113
  var trElementReg = /^tr$/i;
114
+ var id = 0;
115
+ function enrichField(f) {
116
+ if (!f.id) f.id = ++id;
117
+ if (f.width) return;
118
+ var width;
119
+ if (f.size) {
120
+ width = f.size;
121
+ if (width < 40) width = width * 16;
122
+ }
123
+ else switch (f.type) {
124
+ case "text":
125
+ width = 30;
126
+ break;
127
+ case "input":
128
+ width = 200;
129
+ break;
130
+ case "date":
131
+ width = 180;
132
+ case "datetime":
133
+ width = 200;
134
+ break;
135
+ case "time":
136
+ width = 120;
137
+ break;
138
+ default:
139
+ if (f.options) {
140
+ width = f.options.map(o => o.name instanceof Function ? o.name() : o.name).join(" ").length * 20;
141
+ } else {
142
+ width = String(f.name || f.key).length * 16;
143
+ }
144
+ }
145
+ if (width > 600) width = 600;
146
+ f.width = width + 60;
147
+ }
148
+
114
149
 
115
150
  function table(elem) {
116
151
  var tableElement = isElement(elem) ? elem : document.createElement("table");
117
152
  var activeCols = [];
118
- onmousemove(tableElement, adaptTarget);
153
+ var adaptCursor = adaptTarget.bind(tableElement);
154
+ var off;
155
+ tableElement.init = function () {
156
+ off = on("mousemove")(window, adaptCursor);
157
+ };
158
+ tableElement.dispose = tableElement.destroy = function () {
159
+ off();
160
+ };
161
+ on("append")(tableElement, tableElement.init);
162
+ on("remove")(tableElement, tableElement.destroy);
163
+ if (isMounted(tableElement)) tableElement.init();
164
+
119
165
  moveupon(tableElement, {
120
- start() { },
166
+ start(event) {
167
+ if (this.resizing) event.preventDefault();
168
+ },
121
169
  move: resizeTarget,
122
170
  });
123
171
  onmousemove(tableElement, function (event) {
@@ -142,7 +190,7 @@ function table(elem) {
142
190
  removeClass(td, "y-ing");
143
191
  });
144
192
  });
145
- var table = tableElement.hasAttribute("ng-src") || tableElement.hasAttribute("src") ? list(tableElement) : tableElement;
193
+ var table = tableElement;
146
194
  var thead;
147
195
  var cellMatchManager = function (element) {
148
196
  if (!thead) [thead] = table.getElementsByTagName("thead");
@@ -162,10 +210,15 @@ function table(elem) {
162
210
  care(table, function ([fields, data]) {
163
211
  thead = null;
164
212
  this.innerHTML = template;
213
+ fields.forEach(enrichField);
165
214
  render(this, {
166
215
  fields,
167
216
  tbody: list,
168
217
  data,
218
+ model,
219
+ setWidth(target, f) {
220
+ css(target, { width: f.width });
221
+ },
169
222
  a: button,
170
223
  }, this.$parentScopes.concat(this.$scope));
171
224
  })
@@ -1,4 +1,5 @@
1
1
  &[dragchildren] {
2
+
2
3
  >thead,
3
4
  >tbody,
4
5
  & {
@@ -74,8 +75,9 @@ table,
74
75
  line-height: 32px;
75
76
  height: 100%;
76
77
  min-height: 30px;
77
-
78
+ user-select: auto;
78
79
  display: table-row-group;
80
+ overflow: auto;
79
81
 
80
82
  >tr {
81
83