efront 3.7.3 → 3.7.8

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.
package/apps/kugou/api.js CHANGED
@@ -12,7 +12,7 @@
12
12
  "singer-list": "get:[].singer-img-list>li singer/list/:id#href=a!href&=a!href\\singer-info&imgurl=img!_src&name=p|innerText",
13
13
  "singer-info": "mget:[].singer-songs-list>li singer/info/:id#hash=!id&singer=.singer-name|innerText&name=.song-name|innerText&data=em/innerText"
14
14
  },
15
- "https://mobilecdn.kugou.com/": {
15
+ "http://mobilecdn.kugou.com/": {
16
16
  "search?keyword": "get:data.info api/v3/search/song?format=json&page=1&pagesize=30&showtype=1"
17
17
  }
18
18
  })
@@ -17,6 +17,9 @@
17
17
  <script>
18
18
  cross_host = 'efront.cc';
19
19
  </script>
20
+ <script deleteoncompile>
21
+ cross_host = '';
22
+ </script>
20
23
  <style>
21
24
  *,
22
25
  ::before,
@@ -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");
@@ -79,7 +79,7 @@ Object.assign(encode62, {
79
79
  for (var cx = 0, dx = data.length; cx < dx; cx++) {
80
80
  if (result[cx] < 128) result[cx] = result[cx] ^ sign[cx % sign.length];
81
81
  else if (result[cx] < 192) {
82
- var c = c << 8 | sign[(delta += 6) / 8 | 0];
82
+ var c = c << 8 | sign[(delta += 6) / 8 % sign.length | 0];
83
83
  result[cx] = result[cx] ^ (c >> 8 - delta % 8 & 0x3f);
84
84
  }
85
85
  }
@@ -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
  }
@@ -7,6 +7,9 @@
7
7
  top: 0;
8
8
  height: auto;
9
9
  }
10
+ &+.titlebar>back{
11
+ height: 44px;
12
+ }
10
13
 
11
14
  >png {
12
15
  width: 100%;
@@ -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
+ };
@@ -155,6 +155,7 @@ function getUrlParamsForApi(api, url) {
155
155
  cap.push(a.slice(1));
156
156
  return r;
157
157
  });
158
+ if (api.base) base = api.base + base;
158
159
  var params = {};
159
160
  url = url.replace(/[\?#]*$/g, function (match) {
160
161
  match.split(/[&#\?]+/).forEach(function (s) {
@@ -402,6 +403,12 @@ function createApiMap(data) {
402
403
  }
403
404
  var _configfileurl;
404
405
  var configPormise;
406
+ function LoadingArray_then(ok, oh) {
407
+ if (this.loading_promise) this.loading_promise.then(ok, oh);
408
+ else if (this.is_errored) oh(this.error_message);
409
+ else ok();
410
+ }
411
+
405
412
  var privates = {
406
413
  loadAfterConfig(serviceId, params) {
407
414
  var promise = this.getApi(serviceId).then((api) => {
@@ -622,6 +629,7 @@ var data = {
622
629
  if (isObject(response)) {
623
630
  response.is_loaded = true;
624
631
  response.is_loading = false;
632
+ if (response.then === LoadingArray_then) delete response.then;
625
633
  }
626
634
  this.loading_count--;
627
635
  },
@@ -630,6 +638,7 @@ var data = {
630
638
  if (isObject(response)) {
631
639
  response.is_loaded = false;
632
640
  response.is_loading = true;
641
+ response.then = LoadingArray_then;
633
642
  }
634
643
  this.loading_count++;
635
644
  },
@@ -836,7 +845,10 @@ var data = {
836
845
  this.responseLoading(instance);
837
846
  var params = privates.pack(sid, params1);
838
847
  if (!privates.validApi(api, params)) throw aborted;
839
- var { method, uri, params, selector } = privates.prepare(api.method, api.url, params);
848
+ let url = api.url;
849
+ var base = api.base;
850
+ if (base) url = base + api.path;
851
+ var { method, uri, params, selector } = privates.prepare(api.method, url, params);
840
852
  var promise = new Promise(function (ok, oh) {
841
853
  var headers = api.headers;
842
854
  if (headers) {
@@ -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
  })