@reskin/core 0.0.21 → 0.1.0

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.
Files changed (45) hide show
  1. package/bundles/reskin-core-directives.umd.js +303 -163
  2. package/bundles/reskin-core-directives.umd.js.map +1 -1
  3. package/bundles/reskin-core-guards.umd.js +119 -32
  4. package/bundles/reskin-core-guards.umd.js.map +1 -1
  5. package/bundles/reskin-core-interceptors.umd.js +310 -92
  6. package/bundles/reskin-core-interceptors.umd.js.map +1 -1
  7. package/bundles/reskin-core-utils.umd.js +220 -77
  8. package/bundles/reskin-core-utils.umd.js.map +1 -1
  9. package/directives/auth.directive.d.ts +56 -9
  10. package/directives/load.styles.directive.d.ts +45 -5
  11. package/directives/string.template.outlet.directive.d.ts +68 -11
  12. package/esm2015/directives/auth.directive.js +71 -30
  13. package/esm2015/directives/load.styles.directive.js +84 -15
  14. package/esm2015/directives/string.template.outlet.directive.js +118 -60
  15. package/esm2015/guards/auth.guard.js +117 -30
  16. package/esm2015/interceptors/blob.interceptor.js +67 -28
  17. package/esm2015/interceptors/cache.interceptor.js +46 -14
  18. package/esm2015/interceptors/error.interceptor.js +104 -12
  19. package/esm2015/interceptors/public-api.js +2 -1
  20. package/esm2015/interceptors/token.interceptor.js +86 -42
  21. package/esm2015/interceptors/types.js +5 -0
  22. package/esm2015/utils/array.js +42 -22
  23. package/esm2015/utils/dom.js +29 -11
  24. package/esm2015/utils/form.js +44 -13
  25. package/esm2015/utils/store.js +101 -26
  26. package/fesm2015/reskin-core-directives.js +269 -103
  27. package/fesm2015/reskin-core-directives.js.map +1 -1
  28. package/fesm2015/reskin-core-guards.js +116 -29
  29. package/fesm2015/reskin-core-guards.js.map +1 -1
  30. package/fesm2015/reskin-core-interceptors.js +302 -91
  31. package/fesm2015/reskin-core-interceptors.js.map +1 -1
  32. package/fesm2015/reskin-core-utils.js +212 -68
  33. package/fesm2015/reskin-core-utils.js.map +1 -1
  34. package/guards/auth.guard.d.ts +85 -5
  35. package/interceptors/blob.interceptor.d.ts +30 -3
  36. package/interceptors/cache.interceptor.d.ts +28 -4
  37. package/interceptors/error.interceptor.d.ts +43 -2
  38. package/interceptors/public-api.d.ts +1 -0
  39. package/interceptors/token.interceptor.d.ts +41 -12
  40. package/interceptors/types.d.ts +68 -0
  41. package/package.json +1 -1
  42. package/utils/array.d.ts +8 -1
  43. package/utils/dom.d.ts +32 -5
  44. package/utils/form.d.ts +37 -2
  45. package/utils/store.d.ts +56 -15
@@ -6,71 +6,146 @@ let prefix = 'SK_';
6
6
  * 设置存储前缀
7
7
  *
8
8
  * 该函数用于更改全局存储前缀,影响后续所有存储操作的键名前缀。
9
- * 存储前缀的更改可能会影响已存储的数据被正确识别和访问。
9
+ * 注意:更改前缀后,之前使用旧前缀存储的数据将无法访问。
10
10
  *
11
11
  * @param newPrefix 新的存储前缀字符串
12
+ *
13
+ * @example
14
+ * setStorePrefix('MY_APP_');
12
15
  */
13
16
  export function setStorePrefix(newPrefix) {
14
17
  prefix = newPrefix;
15
18
  }
16
19
  /**
17
- * 提供了一个用于缓存值的类,值可以被存储在浏览器的localStorage或sessionStorage中。
18
- * 如果提供了过期时间,存储的值会在过期后自动移除。
20
+ * 提供了一个用于缓存值的类,值可以被存储在浏览器的 localStorage sessionStorage 中。
21
+ * 支持过期时间设置,过期后数据会自动移除。
22
+ *
23
+ * @template T 存储数据的类型
24
+ *
25
+ * @example
26
+ * // 基础用法
27
+ * const userStore = new Store<User>('user', { name: '', age: 0 });
28
+ * userStore.set({ name: '张三', age: 25 });
29
+ * console.log(userStore.get()); // { name: '张三', age: 25 }
30
+ *
31
+ * @example
32
+ * // 使用 localStorage 并设置过期时间
33
+ * const tokenStore = new Store<string>('token', '', {
34
+ * storageEngine: localStorage,
35
+ * expires: 3600000 // 1小时后过期
36
+ * });
19
37
  */
20
38
  export class Store {
21
39
  /**
22
- * 初始化Store类的实例。
23
- * @param key 缓存值的键名。
24
- * @param defaultValue 初始值,默认值会被存储并返回直到设置新的值。
25
- * @param options 配置选项,包括存储引擎和过期时间。
40
+ * 初始化 Store 类的实例
41
+ * @param key 缓存值的键名
42
+ * @param defaultValue 初始值,默认值会被存储并返回直到设置新的值
43
+ * @param options 配置选项,包括存储引擎和过期时间
26
44
  */
27
45
  constructor(key, defaultValue, options) {
46
+ this.key = key;
28
47
  this.value = defaultValue;
29
- // 进行初始设置
30
- this.storageKey = () => `@${prefix}_${key}`.toLocaleUpperCase();
31
48
  const { storageEngine = sessionStorage, expires } = options !== null && options !== void 0 ? options : {};
32
49
  this.storage = storageEngine;
33
50
  this.expires = expires;
34
- const storedValue = this.storage.getItem(this.storageKey());
35
- if (storedValue) {
51
+ // 尝试从存储中读取数据
52
+ this.loadFromStorage();
53
+ }
54
+ /**
55
+ * 生成存储键名
56
+ */
57
+ getStorageKey() {
58
+ return `@${prefix}_${this.key}`.toLocaleUpperCase();
59
+ }
60
+ /**
61
+ * 从存储中加载数据
62
+ */
63
+ loadFromStorage() {
64
+ try {
65
+ const storedValue = this.storage.getItem(this.getStorageKey());
66
+ if (!storedValue) {
67
+ return;
68
+ }
36
69
  const { data, expiry } = JSON.parse(storedValue);
37
- // 判断是否过期,过期后删除key
70
+ // 检查是否过期
38
71
  if (!expiry || expiry > Date.now()) {
39
72
  this.value = data;
40
73
  }
41
74
  else {
42
- this.storage.removeItem(this.storageKey());
75
+ // 过期则删除
76
+ this.clear();
43
77
  }
44
78
  }
79
+ catch (error) {
80
+ console.error(`从存储中读取数据失败 (key: ${this.getStorageKey()}):`, error);
81
+ // 数据损坏时清除
82
+ this.clear();
83
+ }
45
84
  }
46
85
  /**
47
- * 获取当前缓存的值。
48
- * @returns 缓存的值。
86
+ * 获取当前缓存的值
87
+ * @returns 缓存的值
49
88
  */
50
89
  get() {
51
90
  return this.value;
52
91
  }
53
92
  /**
54
- * 设置新的缓存值。
55
- * @param newValue 新的值。
93
+ * 设置新的缓存值
94
+ * @param newValue 新的值
56
95
  */
57
96
  set(newValue) {
58
97
  this.value = newValue;
59
- // 设置值时进行Storage设置
60
- const value = JSON.stringify({
61
- data: newValue,
62
- expiry: this.expires ? Date.now() + this.expires : null,
63
- });
64
- this.storage.setItem(this.storageKey(), value);
98
+ try {
99
+ const storageData = {
100
+ data: newValue,
101
+ expiry: this.expires ? Date.now() + this.expires : null,
102
+ };
103
+ this.storage.setItem(this.getStorageKey(), JSON.stringify(storageData));
104
+ }
105
+ catch (error) {
106
+ console.error(`存储数据失败 (key: ${this.getStorageKey()}):`, error);
107
+ }
65
108
  }
66
109
  /**
67
- * 使用提供的函数更新缓存的值。
68
- * @param updateFn 一个接受当前值并返回新值的函数。
110
+ * 使用提供的函数更新缓存的值
111
+ * @param updateFn 一个接受当前值并返回新值的函数
112
+ *
113
+ * @example
114
+ * const countStore = new Store<number>('count', 0);
115
+ * countStore.update(count => count + 1);
69
116
  */
70
117
  update(updateFn) {
71
118
  if (typeof updateFn === 'function') {
72
119
  this.set(updateFn(this.value));
73
120
  }
74
121
  }
122
+ /**
123
+ * 清除缓存数据
124
+ */
125
+ clear() {
126
+ try {
127
+ this.storage.removeItem(this.getStorageKey());
128
+ }
129
+ catch (error) {
130
+ console.error(`清除存储数据失败 (key: ${this.getStorageKey()}):`, error);
131
+ }
132
+ }
133
+ /**
134
+ * 检查缓存是否存在且未过期
135
+ * @returns 如果缓存存在且未过期返回 true,否则返回 false
136
+ */
137
+ has() {
138
+ try {
139
+ const storedValue = this.storage.getItem(this.getStorageKey());
140
+ if (!storedValue) {
141
+ return false;
142
+ }
143
+ const { expiry } = JSON.parse(storedValue);
144
+ return !expiry || expiry > Date.now();
145
+ }
146
+ catch (_a) {
147
+ return false;
148
+ }
149
+ }
75
150
  }
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJyYXJ5L2NvcmUvdXRpbHMvc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBY0E7O0dBRUc7QUFDSCxJQUFJLE1BQU0sR0FBVyxLQUFLLENBQUM7QUFFM0I7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsU0FBaUI7SUFDNUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztBQUN2QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLEtBQUs7SUFNZDs7Ozs7T0FLRztJQUNILFlBQVksR0FBVyxFQUFFLFlBQWUsRUFBRSxPQUFzQjtRQUM1RCxJQUFJLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztRQUUxQixTQUFTO1FBQ1QsSUFBSSxDQUFDLFVBQVUsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ2hFLE1BQU0sRUFBRSxhQUFhLEdBQUcsY0FBYyxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sYUFBUCxPQUFPLGNBQVAsT0FBTyxHQUFJLEVBQUUsQ0FBQztRQUNsRSxJQUFJLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQztRQUM3QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2QixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUM1RCxJQUFJLFdBQVcsRUFBRTtZQUNiLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNqRCxrQkFBa0I7WUFDbEIsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNoQyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQzthQUNyQjtpQkFBTTtnQkFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQzthQUM5QztTQUNKO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUc7UUFDQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUcsQ0FBQyxRQUFXO1FBQ1gsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFFdEIsa0JBQWtCO1FBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDekIsSUFBSSxFQUFFLFFBQVE7WUFDZCxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUk7U0FDMUQsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsUUFBZ0M7UUFDbkMsSUFBSSxPQUFPLFFBQVEsS0FBSyxVQUFVLEVBQUU7WUFDaEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDbEM7SUFDTCxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICog57yT5a2Y6YWN572u5L+h5oGvXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIFN0b3JlT3B0aW9ucyB7XHJcbiAgICAvKipcclxuICAgICAqIOe8k+WtmOWtmOWCqOaWueW8j1xyXG4gICAgICovXHJcbiAgICBzdG9yYWdlRW5naW5lPzogU3RvcmFnZTtcclxuICAgIC8qKlxyXG4gICAgICog6L+H5pyf5pe26Ze0KOavq+enkilcclxuICAgICAqL1xyXG4gICAgZXhwaXJlcz86IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIOm7mOiupOWJjee8gFxyXG4gKi9cclxubGV0IHByZWZpeDogc3RyaW5nID0gJ1NLXyc7XHJcblxyXG4vKipcclxuICog6K6+572u5a2Y5YKo5YmN57yAXHJcbiAqXHJcbiAqIOivpeWHveaVsOeUqOS6juabtOaUueWFqOWxgOWtmOWCqOWJjee8gO+8jOW9seWTjeWQjue7reaJgOacieWtmOWCqOaTjeS9nOeahOmUruWQjeWJjee8gOOAglxyXG4gKiDlrZjlgqjliY3nvIDnmoTmm7TmlLnlj6/og73kvJrlvbHlk43lt7LlrZjlgqjnmoTmlbDmja7ooqvmraPnoa7or4bliKvlkozorr/pl67jgIJcclxuICpcclxuICogQHBhcmFtIG5ld1ByZWZpeCDmlrDnmoTlrZjlgqjliY3nvIDlrZfnrKbkuLJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBzZXRTdG9yZVByZWZpeChuZXdQcmVmaXg6IHN0cmluZykge1xyXG4gICAgcHJlZml4ID0gbmV3UHJlZml4O1xyXG59XHJcblxyXG4vKipcclxuICog5o+Q5L6b5LqG5LiA5Liq55So5LqO57yT5a2Y5YC855qE57G777yM5YC85Y+v5Lul6KKr5a2Y5YKo5Zyo5rWP6KeI5Zmo55qEbG9jYWxTdG9yYWdl5oiWc2Vzc2lvblN0b3JhZ2XkuK3jgIJcclxuICog5aaC5p6c5o+Q5L6b5LqG6L+H5pyf5pe26Ze077yM5a2Y5YKo55qE5YC85Lya5Zyo6L+H5pyf5ZCO6Ieq5Yqo56e76Zmk44CCXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgU3RvcmU8VD4ge1xyXG4gICAgcHJpdmF0ZSB2YWx1ZTogVDtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgc3RvcmFnZTogU3RvcmFnZTtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXhwaXJlcz86IG51bWJlcjtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgc3RvcmFnZUtleTogKCkgPT4gc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICog5Yid5aeL5YyWU3RvcmXnsbvnmoTlrp7kvovjgIJcclxuICAgICAqIEBwYXJhbSBrZXkg57yT5a2Y5YC855qE6ZSu5ZCN44CCXHJcbiAgICAgKiBAcGFyYW0gZGVmYXVsdFZhbHVlIOWIneWni+WAvO+8jOm7mOiupOWAvOS8muiiq+WtmOWCqOW5tui/lOWbnuebtOWIsOiuvue9ruaWsOeahOWAvOOAglxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMg6YWN572u6YCJ6aG577yM5YyF5ous5a2Y5YKo5byV5pOO5ZKM6L+H5pyf5pe26Ze044CCXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU6IFQsIG9wdGlvbnM/OiBTdG9yZU9wdGlvbnMpIHtcclxuICAgICAgICB0aGlzLnZhbHVlID0gZGVmYXVsdFZhbHVlO1xyXG5cclxuICAgICAgICAvLyDov5vooYzliJ3lp4vorr7nva5cclxuICAgICAgICB0aGlzLnN0b3JhZ2VLZXkgPSAoKSA9PiBgQCR7cHJlZml4fV8ke2tleX1gLnRvTG9jYWxlVXBwZXJDYXNlKCk7XHJcbiAgICAgICAgY29uc3QgeyBzdG9yYWdlRW5naW5lID0gc2Vzc2lvblN0b3JhZ2UsIGV4cGlyZXMgfSA9IG9wdGlvbnMgPz8ge307XHJcbiAgICAgICAgdGhpcy5zdG9yYWdlID0gc3RvcmFnZUVuZ2luZTtcclxuICAgICAgICB0aGlzLmV4cGlyZXMgPSBleHBpcmVzO1xyXG5cclxuICAgICAgICBjb25zdCBzdG9yZWRWYWx1ZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHRoaXMuc3RvcmFnZUtleSgpKTtcclxuICAgICAgICBpZiAoc3RvcmVkVmFsdWUpIHtcclxuICAgICAgICAgICAgY29uc3QgeyBkYXRhLCBleHBpcnkgfSA9IEpTT04ucGFyc2Uoc3RvcmVkVmFsdWUpO1xyXG4gICAgICAgICAgICAvLyDliKTmlq3mmK/lkKbov4fmnJ/vvIzov4fmnJ/lkI7liKDpmaRrZXlcclxuICAgICAgICAgICAgaWYgKCFleHBpcnkgfHwgZXhwaXJ5ID4gRGF0ZS5ub3coKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IGRhdGE7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlSXRlbSh0aGlzLnN0b3JhZ2VLZXkoKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDojrflj5blvZPliY3nvJPlrZjnmoTlgLzjgIJcclxuICAgICAqIEByZXR1cm5zIOe8k+WtmOeahOWAvOOAglxyXG4gICAgICovXHJcbiAgICBnZXQoKTogVCB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDorr7nva7mlrDnmoTnvJPlrZjlgLzjgIJcclxuICAgICAqIEBwYXJhbSBuZXdWYWx1ZSDmlrDnmoTlgLzjgIJcclxuICAgICAqL1xyXG4gICAgc2V0KG5ld1ZhbHVlOiBUKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IG5ld1ZhbHVlO1xyXG5cclxuICAgICAgICAvLyDorr7nva7lgLzml7bov5vooYxTdG9yYWdl6K6+572uXHJcbiAgICAgICAgY29uc3QgdmFsdWUgPSBKU09OLnN0cmluZ2lmeSh7XHJcbiAgICAgICAgICAgIGRhdGE6IG5ld1ZhbHVlLFxyXG4gICAgICAgICAgICBleHBpcnk6IHRoaXMuZXhwaXJlcyA/IERhdGUubm93KCkgKyB0aGlzLmV4cGlyZXMgOiBudWxsLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXRJdGVtKHRoaXMuc3RvcmFnZUtleSgpLCB2YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDkvb/nlKjmj5DkvpvnmoTlh73mlbDmm7TmlrDnvJPlrZjnmoTlgLzjgIJcclxuICAgICAqIEBwYXJhbSB1cGRhdGVGbiDkuIDkuKrmjqXlj5flvZPliY3lgLzlubbov5Tlm57mlrDlgLznmoTlh73mlbDjgIJcclxuICAgICAqL1xyXG4gICAgdXBkYXRlKHVwZGF0ZUZuOiAoY3VycmVudFZhbHVlOiBUKSA9PiBUKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB1cGRhdGVGbiA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICB0aGlzLnNldCh1cGRhdGVGbih0aGlzLnZhbHVlKSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiJdfQ==
151
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJyYXJ5L2NvcmUvdXRpbHMvc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBOEJBOztHQUVHO0FBQ0gsSUFBSSxNQUFNLEdBQVcsS0FBSyxDQUFDO0FBRTNCOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLFNBQWlCO0lBQzVDLE1BQU0sR0FBRyxTQUFTLENBQUM7QUFDdkIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLE9BQU8sS0FBSztJQU1kOzs7OztPQUtHO0lBQ0gsWUFBWSxHQUFXLEVBQUUsWUFBZSxFQUFFLE9BQXNCO1FBQzVELElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ2YsSUFBSSxDQUFDLEtBQUssR0FBRyxZQUFZLENBQUM7UUFFMUIsTUFBTSxFQUFFLGFBQWEsR0FBRyxjQUFjLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxhQUFQLE9BQU8sY0FBUCxPQUFPLEdBQUksRUFBRSxDQUFDO1FBQ2xFLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDO1FBQzdCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBRXZCLGFBQWE7UUFDYixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ssYUFBYTtRQUNqQixPQUFPLElBQUksTUFBTSxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQ3hELENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWU7UUFDbkIsSUFBSTtZQUNBLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1lBQy9ELElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ2QsT0FBTzthQUNWO1lBRUQsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBbUIsQ0FBQztZQUVuRSxTQUFTO1lBQ1QsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNoQyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQzthQUNyQjtpQkFBTTtnQkFDSCxRQUFRO2dCQUNSLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNoQjtTQUNKO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLG9CQUFvQixJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNuRSxVQUFVO1lBQ1YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2hCO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUc7UUFDQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDdEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUcsQ0FBQyxRQUFXO1FBQ1gsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFFdEIsSUFBSTtZQUNBLE1BQU0sV0FBVyxHQUFtQjtnQkFDaEMsSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJO2FBQzFELENBQUM7WUFDRixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1NBQzNFO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNsRTtJQUNMLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsTUFBTSxDQUFDLFFBQWdDO1FBQ25DLElBQUksT0FBTyxRQUFRLEtBQUssVUFBVSxFQUFFO1lBQ2hDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ2xDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNELElBQUk7WUFDQSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztTQUNqRDtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDcEU7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsR0FBRztRQUNDLElBQUk7WUFDQSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMsV0FBVyxFQUFFO2dCQUNkLE9BQU8sS0FBSyxDQUFDO2FBQ2hCO1lBRUQsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFtQixDQUFDO1lBQzdELE9BQU8sQ0FBQyxNQUFNLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUN6QztRQUFDLFdBQU07WUFDSixPQUFPLEtBQUssQ0FBQztTQUNoQjtJQUNMLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxyXG4gKiDnvJPlrZjphY3nva7kv6Hmga9cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVPcHRpb25zIHtcclxuICAgIC8qKlxyXG4gICAgICog57yT5a2Y5a2Y5YKo5pa55byPXHJcbiAgICAgKiBAZGVmYXVsdCBzZXNzaW9uU3RvcmFnZVxyXG4gICAgICovXHJcbiAgICBzdG9yYWdlRW5naW5lPzogU3RvcmFnZTtcclxuICAgIC8qKlxyXG4gICAgICog6L+H5pyf5pe26Ze077yI5q+r56eS77yJXHJcbiAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQgKOawuOS4jei/h+acnylcclxuICAgICAqL1xyXG4gICAgZXhwaXJlcz86IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIOWtmOWCqOaVsOaNrue7k+aehFxyXG4gKi9cclxuaW50ZXJmYWNlIFN0b3JhZ2VEYXRhPFQ+IHtcclxuICAgIC8qKlxyXG4gICAgICog5a6e6ZmF5a2Y5YKo55qE5pWw5o2uXHJcbiAgICAgKi9cclxuICAgIGRhdGE6IFQ7XHJcbiAgICAvKipcclxuICAgICAqIOi/h+acn+aXtumXtOaIs++8iOavq+enku+8iVxyXG4gICAgICovXHJcbiAgICBleHBpcnk6IG51bWJlciB8IG51bGw7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiDpu5jorqTliY3nvIBcclxuICovXHJcbmxldCBwcmVmaXg6IHN0cmluZyA9ICdTS18nO1xyXG5cclxuLyoqXHJcbiAqIOiuvue9ruWtmOWCqOWJjee8gFxyXG4gKlxyXG4gKiDor6Xlh73mlbDnlKjkuo7mm7TmlLnlhajlsYDlrZjlgqjliY3nvIDvvIzlvbHlk43lkI7nu63miYDmnInlrZjlgqjmk43kvZznmoTplK7lkI3liY3nvIDjgIJcclxuICog5rOo5oSP77ya5pu05pS55YmN57yA5ZCO77yM5LmL5YmN5L2/55So5pen5YmN57yA5a2Y5YKo55qE5pWw5o2u5bCG5peg5rOV6K6/6Zeu44CCXHJcbiAqXHJcbiAqIEBwYXJhbSBuZXdQcmVmaXgg5paw55qE5a2Y5YKo5YmN57yA5a2X56ym5LiyXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIHNldFN0b3JlUHJlZml4KCdNWV9BUFBfJyk7XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gc2V0U3RvcmVQcmVmaXgobmV3UHJlZml4OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHByZWZpeCA9IG5ld1ByZWZpeDtcclxufVxyXG5cclxuLyoqXHJcbiAqIOaPkOS+m+S6huS4gOS4queUqOS6jue8k+WtmOWAvOeahOexu++8jOWAvOWPr+S7peiiq+WtmOWCqOWcqOa1j+iniOWZqOeahCBsb2NhbFN0b3JhZ2Ug5oiWIHNlc3Npb25TdG9yYWdlIOS4reOAglxyXG4gKiDmlK/mjIHov4fmnJ/ml7bpl7Torr7nva7vvIzov4fmnJ/lkI7mlbDmja7kvJroh6rliqjnp7vpmaTjgIJcclxuICpcclxuICogQHRlbXBsYXRlIFQg5a2Y5YKo5pWw5o2u55qE57G75Z6LXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIC8vIOWfuuehgOeUqOazlVxyXG4gKiBjb25zdCB1c2VyU3RvcmUgPSBuZXcgU3RvcmU8VXNlcj4oJ3VzZXInLCB7IG5hbWU6ICcnLCBhZ2U6IDAgfSk7XHJcbiAqIHVzZXJTdG9yZS5zZXQoeyBuYW1lOiAn5byg5LiJJywgYWdlOiAyNSB9KTtcclxuICogY29uc29sZS5sb2codXNlclN0b3JlLmdldCgpKTsgLy8geyBuYW1lOiAn5byg5LiJJywgYWdlOiAyNSB9XHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIC8vIOS9v+eUqCBsb2NhbFN0b3JhZ2Ug5bm26K6+572u6L+H5pyf5pe26Ze0XHJcbiAqIGNvbnN0IHRva2VuU3RvcmUgPSBuZXcgU3RvcmU8c3RyaW5nPigndG9rZW4nLCAnJywge1xyXG4gKiAgIHN0b3JhZ2VFbmdpbmU6IGxvY2FsU3RvcmFnZSxcclxuICogICBleHBpcmVzOiAzNjAwMDAwIC8vIDHlsI/ml7blkI7ov4fmnJ9cclxuICogfSk7XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgU3RvcmU8VD4ge1xyXG4gICAgcHJpdmF0ZSB2YWx1ZTogVDtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgc3RvcmFnZTogU3RvcmFnZTtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXhwaXJlcz86IG51bWJlcjtcclxuICAgIHByaXZhdGUgcmVhZG9ubHkga2V5OiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDliJ3lp4vljJYgU3RvcmUg57G755qE5a6e5L6LXHJcbiAgICAgKiBAcGFyYW0ga2V5IOe8k+WtmOWAvOeahOmUruWQjVxyXG4gICAgICogQHBhcmFtIGRlZmF1bHRWYWx1ZSDliJ3lp4vlgLzvvIzpu5jorqTlgLzkvJrooqvlrZjlgqjlubbov5Tlm57nm7TliLDorr7nva7mlrDnmoTlgLxcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIOmFjee9rumAiemhue+8jOWMheaLrOWtmOWCqOW8leaTjuWSjOi/h+acn+aXtumXtFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihrZXk6IHN0cmluZywgZGVmYXVsdFZhbHVlOiBULCBvcHRpb25zPzogU3RvcmVPcHRpb25zKSB7XHJcbiAgICAgICAgdGhpcy5rZXkgPSBrZXk7XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IGRlZmF1bHRWYWx1ZTtcclxuXHJcbiAgICAgICAgY29uc3QgeyBzdG9yYWdlRW5naW5lID0gc2Vzc2lvblN0b3JhZ2UsIGV4cGlyZXMgfSA9IG9wdGlvbnMgPz8ge307XHJcbiAgICAgICAgdGhpcy5zdG9yYWdlID0gc3RvcmFnZUVuZ2luZTtcclxuICAgICAgICB0aGlzLmV4cGlyZXMgPSBleHBpcmVzO1xyXG5cclxuICAgICAgICAvLyDlsJ3or5Xku47lrZjlgqjkuK3or7vlj5bmlbDmja5cclxuICAgICAgICB0aGlzLmxvYWRGcm9tU3RvcmFnZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog55Sf5oiQ5a2Y5YKo6ZSu5ZCNXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0U3RvcmFnZUtleSgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBgQCR7cHJlZml4fV8ke3RoaXMua2V5fWAudG9Mb2NhbGVVcHBlckNhc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIOS7juWtmOWCqOS4reWKoOi9veaVsOaNrlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGxvYWRGcm9tU3RvcmFnZSgpOiB2b2lkIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCBzdG9yZWRWYWx1ZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKHRoaXMuZ2V0U3RvcmFnZUtleSgpKTtcclxuICAgICAgICAgICAgaWYgKCFzdG9yZWRWYWx1ZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCB7IGRhdGEsIGV4cGlyeSB9ID0gSlNPTi5wYXJzZShzdG9yZWRWYWx1ZSkgYXMgU3RvcmFnZURhdGE8VD47XHJcblxyXG4gICAgICAgICAgICAvLyDmo4Dmn6XmmK/lkKbov4fmnJ9cclxuICAgICAgICAgICAgaWYgKCFleHBpcnkgfHwgZXhwaXJ5ID4gRGF0ZS5ub3coKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IGRhdGE7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyDov4fmnJ/liJnliKDpmaRcclxuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYOS7juWtmOWCqOS4reivu+WPluaVsOaNruWksei0pSAoa2V5OiAke3RoaXMuZ2V0U3RvcmFnZUtleSgpfSk6YCwgZXJyb3IpO1xyXG4gICAgICAgICAgICAvLyDmlbDmja7mjZ/lnY/ml7bmuIXpmaRcclxuICAgICAgICAgICAgdGhpcy5jbGVhcigpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIOiOt+WPluW9k+WJjee8k+WtmOeahOWAvFxyXG4gICAgICogQHJldHVybnMg57yT5a2Y55qE5YC8XHJcbiAgICAgKi9cclxuICAgIGdldCgpOiBUIHtcclxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIOiuvue9ruaWsOeahOe8k+WtmOWAvFxyXG4gICAgICogQHBhcmFtIG5ld1ZhbHVlIOaWsOeahOWAvFxyXG4gICAgICovXHJcbiAgICBzZXQobmV3VmFsdWU6IFQpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnZhbHVlID0gbmV3VmFsdWU7XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHN0b3JhZ2VEYXRhOiBTdG9yYWdlRGF0YTxUPiA9IHtcclxuICAgICAgICAgICAgICAgIGRhdGE6IG5ld1ZhbHVlLFxyXG4gICAgICAgICAgICAgICAgZXhwaXJ5OiB0aGlzLmV4cGlyZXMgPyBEYXRlLm5vdygpICsgdGhpcy5leHBpcmVzIDogbnVsbCxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnNldEl0ZW0odGhpcy5nZXRTdG9yYWdlS2V5KCksIEpTT04uc3RyaW5naWZ5KHN0b3JhZ2VEYXRhKSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihg5a2Y5YKo5pWw5o2u5aSx6LSlIChrZXk6ICR7dGhpcy5nZXRTdG9yYWdlS2V5KCl9KTpgLCBlcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog5L2/55So5o+Q5L6b55qE5Ye95pWw5pu05paw57yT5a2Y55qE5YC8XHJcbiAgICAgKiBAcGFyYW0gdXBkYXRlRm4g5LiA5Liq5o6l5Y+X5b2T5YmN5YC85bm26L+U5Zue5paw5YC855qE5Ye95pWwXHJcbiAgICAgKlxyXG4gICAgICogQGV4YW1wbGVcclxuICAgICAqIGNvbnN0IGNvdW50U3RvcmUgPSBuZXcgU3RvcmU8bnVtYmVyPignY291bnQnLCAwKTtcclxuICAgICAqIGNvdW50U3RvcmUudXBkYXRlKGNvdW50ID0+IGNvdW50ICsgMSk7XHJcbiAgICAgKi9cclxuICAgIHVwZGF0ZSh1cGRhdGVGbjogKGN1cnJlbnRWYWx1ZTogVCkgPT4gVCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0eXBlb2YgdXBkYXRlRm4gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXQodXBkYXRlRm4odGhpcy52YWx1ZSkpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIOa4hemZpOe8k+WtmOaVsOaNrlxyXG4gICAgICovXHJcbiAgICBjbGVhcigpOiB2b2lkIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlSXRlbSh0aGlzLmdldFN0b3JhZ2VLZXkoKSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihg5riF6Zmk5a2Y5YKo5pWw5o2u5aSx6LSlIChrZXk6ICR7dGhpcy5nZXRTdG9yYWdlS2V5KCl9KTpgLCBlcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog5qOA5p+l57yT5a2Y5piv5ZCm5a2Y5Zyo5LiU5pyq6L+H5pyfXHJcbiAgICAgKiBAcmV0dXJucyDlpoLmnpznvJPlrZjlrZjlnKjkuJTmnKrov4fmnJ/ov5Tlm54gdHJ1Ze+8jOWQpuWImei/lOWbniBmYWxzZVxyXG4gICAgICovXHJcbiAgICBoYXMoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3Qgc3RvcmVkVmFsdWUgPSB0aGlzLnN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmdldFN0b3JhZ2VLZXkoKSk7XHJcbiAgICAgICAgICAgIGlmICghc3RvcmVkVmFsdWUpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgeyBleHBpcnkgfSA9IEpTT04ucGFyc2Uoc3RvcmVkVmFsdWUpIGFzIFN0b3JhZ2VEYXRhPFQ+O1xyXG4gICAgICAgICAgICByZXR1cm4gIWV4cGlyeSB8fCBleHBpcnkgPiBEYXRlLm5vdygpO1xyXG4gICAgICAgIH0gY2F0Y2gge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiJdfQ==
@@ -1,63 +1,104 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Directive, Input, TemplateRef, EventEmitter, Output, NgModule } from '@angular/core';
3
- import { map } from 'rxjs/operators';
3
+ import { Subject } from 'rxjs';
4
+ import { takeUntil, map } from 'rxjs/operators';
4
5
  import * as i1 from '@reskin/core/services';
5
6
 
7
+ /**
8
+ * 权限指令
9
+ * 根据权限标识符控制模板的显示与隐藏
10
+ *
11
+ * @example
12
+ * ```html
13
+ * <!-- 基础用法 -->
14
+ * <div *rkAuth="'user:edit'">有编辑权限才显示</div>
15
+ *
16
+ * <!-- 多个权限(或关系) -->
17
+ * <div *rkAuth="['user:edit', 'user:delete']">有任一权限即显示</div>
18
+ *
19
+ * <!-- 使用 then/else 模板 -->
20
+ * <ng-container *rkAuth="'user:edit'; then hasAuth; else noAuth"></ng-container>
21
+ * <ng-template #hasAuth let-menu>
22
+ * <p>有权限,菜单信息:{{ menu | json }}</p>
23
+ * </ng-template>
24
+ * <ng-template #noAuth>
25
+ * <p>无权限</p>
26
+ * </ng-template>
27
+ * ```
28
+ */
6
29
  class RkAuthDirective {
7
- constructor(menu, viewContainerRef, templateRef) {
8
- this.menu = menu;
30
+ constructor(menuService, viewContainerRef, templateRef) {
31
+ this.menuService = menuService;
9
32
  this.viewContainerRef = viewContainerRef;
10
33
  this.templateRef = templateRef;
11
34
  this.condition = '';
35
+ this.destroy$ = new Subject();
12
36
  this.thenTemplateRef = templateRef;
13
37
  }
14
38
  /**
15
- * 传递多个标识符时,逗号分隔,匹配按"或者"运算
16
- * @param condition
39
+ * 权限标识符
40
+ * 传递多个标识符时,匹配按"或"运算
17
41
  */
18
42
  set rkAuth(condition) {
19
43
  this.condition = condition;
20
44
  this.updateView();
21
45
  }
46
+ /**
47
+ * 有权限时显示的模板
48
+ */
22
49
  set rkAuthThen(templateRef) {
23
50
  this.thenTemplateRef = templateRef;
24
51
  this.updateView();
25
52
  }
53
+ /**
54
+ * 无权限时显示的模板
55
+ */
26
56
  set rkAuthElse(templateRef) {
27
57
  this.elseTemplateRef = templateRef;
28
58
  this.updateView();
29
59
  }
30
60
  ngOnDestroy() {
31
- var _a;
32
- (_a = this.authSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
61
+ this.destroy$.next();
62
+ this.destroy$.complete();
33
63
  }
64
+ /**
65
+ * 更新视图显示
66
+ */
34
67
  updateView() {
35
- var _a;
36
- (_a = this.authSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
37
- this.authSubscription = this.hasAuth(this.condition).subscribe((context) => {
68
+ if (!this.condition) {
38
69
  this.viewContainerRef.clear();
39
- if (context.status) {
40
- if (this.thenTemplateRef) {
41
- this.viewContainerRef.createEmbeddedView(this.thenTemplateRef, context);
42
- }
43
- }
44
- else {
45
- if (this.elseTemplateRef) {
46
- this.viewContainerRef.createEmbeddedView(this.elseTemplateRef, context);
47
- }
48
- }
70
+ return;
71
+ }
72
+ this.checkAuth(this.condition)
73
+ .pipe(takeUntil(this.destroy$))
74
+ .subscribe((context) => {
75
+ this.renderView(context);
49
76
  });
50
77
  }
51
- hasAuth(tags) {
52
- const tagList = typeof tags === 'string' ? [tags] : tags;
53
- return this.menu.requestData().pipe(map((json) => {
54
- const menus = json.data.filter((menu) => tagList.includes(menu.SYSTEM_RESOURCE_GUARD_ID));
55
- if (!menus.length)
56
- return { $implicit: [], status: false };
57
- return {
58
- $implicit: typeof tags === 'string' ? menus[0] : menus,
59
- status: !!menus.length,
78
+ /**
79
+ * 渲染视图
80
+ */
81
+ renderView(context) {
82
+ this.viewContainerRef.clear();
83
+ if (context.status && this.thenTemplateRef) {
84
+ this.viewContainerRef.createEmbeddedView(this.thenTemplateRef, context);
85
+ }
86
+ else if (!context.status && this.elseTemplateRef) {
87
+ this.viewContainerRef.createEmbeddedView(this.elseTemplateRef, context);
88
+ }
89
+ }
90
+ /**
91
+ * 检查权限
92
+ */
93
+ checkAuth(tags) {
94
+ const tagList = Array.isArray(tags) ? tags : [tags];
95
+ return this.menuService.requestData().pipe(map((response) => {
96
+ const matchedMenus = response.data.filter((menu) => tagList.includes(menu.SYSTEM_RESOURCE_GUARD_ID));
97
+ const context = {
98
+ $implicit: Array.isArray(tags) ? matchedMenus : matchedMenus[0] || null,
99
+ status: matchedMenus.length > 0,
60
100
  };
101
+ return context;
61
102
  }));
62
103
  }
63
104
  }
@@ -76,120 +117,245 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImpo
76
117
  type: Input
77
118
  }] } });
78
119
 
120
+ /**
121
+ * 字符串模板输出上下文
122
+ */
123
+ class RkStringTemplateOutletContext {
124
+ constructor() {
125
+ /** 隐式上下文值 */
126
+ this.$implicit = null;
127
+ }
128
+ }
129
+ /**
130
+ * 字符串模板输出指令
131
+ * 支持动态渲染字符串或 TemplateRef
132
+ *
133
+ * @example
134
+ * ```html
135
+ * <!-- 渲染字符串 -->
136
+ * <ng-container *rkStringTemplateOutlet="'Hello World'">
137
+ * <ng-template>默认模板</ng-template>
138
+ * </ng-container>
139
+ *
140
+ * <!-- 渲染 TemplateRef -->
141
+ * <ng-container *rkStringTemplateOutlet="customTemplate; context: { $implicit: data }">
142
+ * </ng-container>
143
+ * <ng-template #customTemplate let-item>
144
+ * <div>{{ item }}</div>
145
+ * </ng-template>
146
+ *
147
+ * <!-- 动态切换 -->
148
+ * <ng-container *rkStringTemplateOutlet="isTemplate ? templateRef : 'Static Text'">
149
+ * </ng-container>
150
+ * ```
151
+ */
79
152
  class RkStringTemplateOutletDirective {
80
- constructor(viewContainer, templateRef) {
81
- this.viewContainer = viewContainer;
153
+ constructor(viewContainerRef, templateRef) {
154
+ this.viewContainerRef = viewContainerRef;
82
155
  this.templateRef = templateRef;
83
156
  this.embeddedViewRef = null;
84
157
  this.context = new RkStringTemplateOutletContext();
85
- this.rkStringTemplateOutletContext = null;
158
+ /**
159
+ * 输出内容
160
+ * 可以是字符串或 TemplateRef
161
+ */
86
162
  this.rkStringTemplateOutlet = null;
163
+ /**
164
+ * 模板上下文
165
+ * 当 rkStringTemplateOutlet 是 TemplateRef 时使用
166
+ */
167
+ this.rkStringTemplateOutletContext = null;
87
168
  }
169
+ /**
170
+ * 类型守卫
171
+ * 用于 Angular 模板类型检查
172
+ */
88
173
  static rkTemplateContextGuard(_dir, _ctx) {
89
174
  return true;
90
175
  }
91
- recreateView() {
92
- this.viewContainer.clear();
93
- const isTemplateRef = this.rkStringTemplateOutlet instanceof TemplateRef;
94
- const templateRef = (isTemplateRef ? this.rkStringTemplateOutlet : this.templateRef);
95
- this.embeddedViewRef = this.viewContainer.createEmbeddedView(templateRef, isTemplateRef ? this.rkStringTemplateOutletContext : this.context);
96
- }
97
- updateContext() {
98
- const isTemplateRef = this.rkStringTemplateOutlet instanceof TemplateRef;
99
- const newCtx = isTemplateRef ? this.rkStringTemplateOutletContext : this.context;
100
- const oldCtx = this.embeddedViewRef.context;
101
- if (newCtx) {
102
- for (const propName of Object.keys(newCtx)) {
103
- oldCtx[propName] = newCtx[propName];
104
- }
105
- }
106
- }
107
176
  ngOnChanges(changes) {
108
- const { rkStringTemplateOutletContext, rkStringTemplateOutlet } = changes;
109
- const shouldRecreateView = () => {
110
- let shouldOutletRecreate = false;
111
- if (rkStringTemplateOutlet) {
112
- if (rkStringTemplateOutlet.firstChange) {
113
- shouldOutletRecreate = true;
114
- }
115
- else {
116
- const isPreviousOutletTemplate = rkStringTemplateOutlet.previousValue instanceof TemplateRef;
117
- const isCurrentOutletTemplate = rkStringTemplateOutlet.currentValue instanceof TemplateRef;
118
- shouldOutletRecreate = isPreviousOutletTemplate || isCurrentOutletTemplate;
119
- }
120
- }
121
- const hasContextShapeChanged = (ctxChange) => {
122
- const prevCtxKeys = Object.keys(ctxChange.previousValue || {});
123
- const currCtxKeys = Object.keys(ctxChange.currentValue || {});
124
- if (prevCtxKeys.length === currCtxKeys.length) {
125
- for (const propName of currCtxKeys) {
126
- if (prevCtxKeys.indexOf(propName) === -1) {
127
- return true;
128
- }
129
- }
130
- return false;
131
- }
132
- else {
133
- return true;
134
- }
135
- };
136
- const shouldContextRecreate = rkStringTemplateOutletContext && hasContextShapeChanged(rkStringTemplateOutletContext);
137
- return shouldContextRecreate || shouldOutletRecreate;
138
- };
177
+ const { rkStringTemplateOutlet, rkStringTemplateOutletContext } = changes;
178
+ // 更新隐式上下文
139
179
  if (rkStringTemplateOutlet) {
140
180
  this.context.$implicit = rkStringTemplateOutlet.currentValue;
141
181
  }
142
- const recreateView = shouldRecreateView();
143
- if (recreateView) {
144
- /** recreate view when context shape or outlet change **/
182
+ // 判断是否需要重建视图
183
+ if (this.shouldRecreateView(rkStringTemplateOutlet, rkStringTemplateOutletContext)) {
145
184
  this.recreateView();
146
185
  }
147
186
  else {
148
- /** update context **/
149
187
  this.updateContext();
150
188
  }
151
189
  }
190
+ /**
191
+ * 判断是否需要重建视图
192
+ */
193
+ shouldRecreateView(outletChange, contextChange) {
194
+ // 首次变更需要创建视图
195
+ if (outletChange === null || outletChange === void 0 ? void 0 : outletChange.firstChange) {
196
+ return true;
197
+ }
198
+ // outlet 在 TemplateRef 和非 TemplateRef 之间切换时需要重建
199
+ if (outletChange && this.isOutletTypeChanged(outletChange)) {
200
+ return true;
201
+ }
202
+ // 上下文结构变化时需要重建
203
+ if (contextChange && this.isContextShapeChanged(contextChange)) {
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ /**
209
+ * 检查 outlet 类型是否变化
210
+ */
211
+ isOutletTypeChanged(change) {
212
+ const isPreviousTemplate = change.previousValue instanceof TemplateRef;
213
+ const isCurrentTemplate = change.currentValue instanceof TemplateRef;
214
+ return isPreviousTemplate !== isCurrentTemplate;
215
+ }
216
+ /**
217
+ * 检查上下文结构是否变化
218
+ */
219
+ isContextShapeChanged(change) {
220
+ const prevKeys = Object.keys(change.previousValue || {});
221
+ const currKeys = Object.keys(change.currentValue || {});
222
+ if (prevKeys.length !== currKeys.length) {
223
+ return true;
224
+ }
225
+ return currKeys.some((key) => !prevKeys.includes(key));
226
+ }
227
+ /**
228
+ * 重建视图
229
+ */
230
+ recreateView() {
231
+ this.viewContainerRef.clear();
232
+ const isTemplateRef = this.rkStringTemplateOutlet instanceof TemplateRef;
233
+ const templateRef = isTemplateRef ? this.rkStringTemplateOutlet : this.templateRef;
234
+ const context = isTemplateRef ? this.rkStringTemplateOutletContext : this.context;
235
+ this.embeddedViewRef = this.viewContainerRef.createEmbeddedView(templateRef, context || this.context);
236
+ }
237
+ /**
238
+ * 更新视图上下文
239
+ */
240
+ updateContext() {
241
+ if (!this.embeddedViewRef) {
242
+ return;
243
+ }
244
+ const isTemplateRef = this.rkStringTemplateOutlet instanceof TemplateRef;
245
+ const newContext = isTemplateRef ? this.rkStringTemplateOutletContext : this.context;
246
+ const viewContext = this.embeddedViewRef.context;
247
+ if (newContext) {
248
+ Object.keys(newContext).forEach((key) => {
249
+ viewContext[key] = newContext[key];
250
+ });
251
+ }
252
+ }
152
253
  }
153
254
  RkStringTemplateOutletDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: RkStringTemplateOutletDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
154
- RkStringTemplateOutletDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.17", type: RkStringTemplateOutletDirective, selector: "[rkStringTemplateOutlet]", inputs: { rkStringTemplateOutletContext: "rkStringTemplateOutletContext", rkStringTemplateOutlet: "rkStringTemplateOutlet" }, usesOnChanges: true, ngImport: i0 });
255
+ RkStringTemplateOutletDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.17", type: RkStringTemplateOutletDirective, selector: "[rkStringTemplateOutlet]", inputs: { rkStringTemplateOutlet: "rkStringTemplateOutlet", rkStringTemplateOutletContext: "rkStringTemplateOutletContext" }, usesOnChanges: true, ngImport: i0 });
155
256
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: RkStringTemplateOutletDirective, decorators: [{
156
257
  type: Directive,
157
258
  args: [{
158
259
  selector: '[rkStringTemplateOutlet]',
159
260
  }]
160
- }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.TemplateRef }]; }, propDecorators: { rkStringTemplateOutletContext: [{
261
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.TemplateRef }]; }, propDecorators: { rkStringTemplateOutlet: [{
161
262
  type: Input
162
- }], rkStringTemplateOutlet: [{
263
+ }], rkStringTemplateOutletContext: [{
163
264
  type: Input
164
- }] } });
165
- class RkStringTemplateOutletContext {
166
- }
265
+ }] } });
167
266
 
267
+ /**
268
+ * 样式按需加载指令
269
+ * 在指令初始化时加载指定的样式文件,销毁时自动卸载
270
+ *
271
+ * @example
272
+ * ```html
273
+ * <!-- 加载单个样式 -->
274
+ * <div [rkLoadStyles]="'assets/styles/theme.css'">内容</div>
275
+ *
276
+ * <!-- 加载多个样式 -->
277
+ * <div [rkLoadStyles]="['assets/styles/theme.css', 'assets/styles/components.css']">内容</div>
278
+ *
279
+ * <!-- 监听加载完成事件 -->
280
+ * <div [rkLoadStyles]="styleUrls" (stylesLoaded)="onLoaded($event)">内容</div>
281
+ * ```
282
+ */
168
283
  class RkLoadStylesDirective {
169
- constructor(styleLoader) {
170
- this.styleLoader = styleLoader;
284
+ constructor(styleLoaderService) {
285
+ this.styleLoaderService = styleLoaderService;
286
+ this.destroy$ = new Subject();
287
+ this.styleUrls = [];
288
+ /**
289
+ * 样式文件路径
290
+ * 可以是单个路径字符串或路径数组
291
+ */
171
292
  this.hrefs = [];
172
- // (可选) 输出加载完成事件,以便父组件可以响应
293
+ /**
294
+ * 样式加载完成事件
295
+ * 返回每个样式文件的加载结果
296
+ */
173
297
  this.stylesLoaded = new EventEmitter();
174
- this.styleUrls = [];
175
298
  }
176
299
  ngOnInit() {
177
- this.styleUrls = Array.isArray(this.hrefs) ? this.hrefs : [this.hrefs];
178
- if (this.styleUrls.length > 0) {
179
- this.subscription = this.styleLoader.load(...this.styleUrls).subscribe((results) => {
180
- this.stylesLoaded.emit(results);
181
- });
182
- }
300
+ this.loadStyles();
183
301
  }
184
302
  ngOnDestroy() {
185
- if (this.subscription) {
186
- this.subscription.unsubscribe();
303
+ this.destroy$.next();
304
+ this.destroy$.complete();
305
+ this.unloadStyles();
306
+ }
307
+ /**
308
+ * 加载样式文件
309
+ */
310
+ loadStyles() {
311
+ this.styleUrls = this.normalizeHrefs(this.hrefs);
312
+ if (this.styleUrls.length === 0) {
313
+ return;
187
314
  }
188
- // 指令销毁时,自动调用 unload,服务内部会处理引用计数
315
+ this.styleLoaderService
316
+ .load(...this.styleUrls)
317
+ .pipe(takeUntil(this.destroy$))
318
+ .subscribe({
319
+ next: (results) => {
320
+ this.stylesLoaded.emit(results);
321
+ this.logLoadResults(results);
322
+ },
323
+ error: (error) => {
324
+ console.error('[RkLoadStyles] 样式加载失败:', error);
325
+ },
326
+ });
327
+ }
328
+ /**
329
+ * 卸载样式文件
330
+ */
331
+ unloadStyles() {
189
332
  if (this.styleUrls.length > 0) {
190
- this.styleLoader.unload(...this.styleUrls);
333
+ this.styleLoaderService.unload(...this.styleUrls);
191
334
  }
192
335
  }
336
+ /**
337
+ * 标准化 hrefs 输入为数组
338
+ */
339
+ normalizeHrefs(hrefs) {
340
+ if (!hrefs) {
341
+ return [];
342
+ }
343
+ return Array.isArray(hrefs) ? hrefs : [hrefs];
344
+ }
345
+ /**
346
+ * 记录加载结果(仅在开发模式)
347
+ */
348
+ logLoadResults(results) {
349
+ // 开发模式下记录加载结果
350
+ results.forEach((result) => {
351
+ if (result.success) {
352
+ console.log(`[RkLoadStyles] 样式加载成功: ${result.href}`);
353
+ }
354
+ else {
355
+ console.error(`[RkLoadStyles] 样式加载失败: ${result.href}`, result.error);
356
+ }
357
+ });
358
+ }
193
359
  }
194
360
  RkLoadStylesDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: RkLoadStylesDirective, deps: [{ token: i1.RkStyleLoaderService }], target: i0.ɵɵFactoryTarget.Directive });
195
361
  RkLoadStylesDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.17", type: RkLoadStylesDirective, selector: "[rkLoadStyles]", inputs: { hrefs: ["rkLoadStyles", "hrefs"] }, outputs: { stylesLoaded: "stylesLoaded" }, ngImport: i0 });