@truenewx/tnxvue3 2.6.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 (60) hide show
  1. package/README.md +3 -0
  2. package/package.json +76 -0
  3. package/sample/App.vue +19 -0
  4. package/sample/main.js +11 -0
  5. package/sample/pages/index.vue +79 -0
  6. package/sample/pages/info.vue +28 -0
  7. package/sample/tnx.js +31 -0
  8. package/src/aj-captcha/Verify/VerifyPoints.vue +258 -0
  9. package/src/aj-captcha/Verify/VerifySlide.vue +379 -0
  10. package/src/aj-captcha/Verify.vue +375 -0
  11. package/src/aj-captcha/api/index.js +19 -0
  12. package/src/aj-captcha/utils/ase.js +11 -0
  13. package/src/aj-captcha/utils/util.js +35 -0
  14. package/src/ant-design/tnxad-theme.css +5 -0
  15. package/src/ant-design/tnxad.css +8 -0
  16. package/src/ant-design/tnxad.js +23 -0
  17. package/src/element-plus/alert/Alert.vue +112 -0
  18. package/src/element-plus/avatar/Avatar.vue +124 -0
  19. package/src/element-plus/button/Button.vue +184 -0
  20. package/src/element-plus/check-icon/CheckIcon.vue +61 -0
  21. package/src/element-plus/close-error-button/CloseErrorButton.vue +45 -0
  22. package/src/element-plus/curd/Curd.vue +224 -0
  23. package/src/element-plus/date-picker/DatePicker.vue +206 -0
  24. package/src/element-plus/date-range/DateRange.vue +78 -0
  25. package/src/element-plus/datetime-picker/DateTimePicker.vue +129 -0
  26. package/src/element-plus/detail-form/DetailForm.vue +88 -0
  27. package/src/element-plus/dialog/Dialog.vue +259 -0
  28. package/src/element-plus/dialog/DialogContent.vue +13 -0
  29. package/src/element-plus/drawer/Drawer.vue +175 -0
  30. package/src/element-plus/dropdown-item/DropdownItem.vue +30 -0
  31. package/src/element-plus/enum-select/EnumSelect.vue +125 -0
  32. package/src/element-plus/fetch-cascader/FetchCascader.vue +138 -0
  33. package/src/element-plus/fetch-select/FetchSelect.vue +166 -0
  34. package/src/element-plus/fetch-tags/FetchTags.vue +122 -0
  35. package/src/element-plus/fss-upload/FssUpload.vue +306 -0
  36. package/src/element-plus/fss-view/FssView.vue +163 -0
  37. package/src/element-plus/icon/Icon.vue +221 -0
  38. package/src/element-plus/input-number/InputNumber.vue +150 -0
  39. package/src/element-plus/paged/Paged.vue +76 -0
  40. package/src/element-plus/permission-tree/PermissionTree.vue +184 -0
  41. package/src/element-plus/query-form/QueryForm.vue +138 -0
  42. package/src/element-plus/query-table/QueryTable.vue +402 -0
  43. package/src/element-plus/region-cascader/RegionCascader.vue +108 -0
  44. package/src/element-plus/select/Select.vue +446 -0
  45. package/src/element-plus/slider/Slider.vue +88 -0
  46. package/src/element-plus/steps-nav/StepsNav.vue +57 -0
  47. package/src/element-plus/submit-form/SubmitForm.vue +236 -0
  48. package/src/element-plus/table-column/TableColumn.vue +32 -0
  49. package/src/element-plus/tabs/Tabs.vue +93 -0
  50. package/src/element-plus/tnxel.css +890 -0
  51. package/src/element-plus/tnxel.js +528 -0
  52. package/src/element-plus/transfer/Transfer.vue +117 -0
  53. package/src/element-plus/upload/Upload.vue +856 -0
  54. package/src/percent/Percent.vue +12 -0
  55. package/src/text/Text.vue +33 -0
  56. package/src/tnxvue-cli.js +64 -0
  57. package/src/tnxvue-router.js +161 -0
  58. package/src/tnxvue-validator.js +365 -0
  59. package/src/tnxvue.css +12 -0
  60. package/src/tnxvue.js +343 -0
@@ -0,0 +1,306 @@
1
+ <template>
2
+ <tnxel-upload ref="upload"
3
+ :app-name="appName"
4
+ :action="action"
5
+ :upload-options="uploadOptions"
6
+ :file-list="fileList"
7
+ :width="width" :height="height"
8
+ :center="center"
9
+ :trigger-icon="triggerIcon" :trigger-icon-size="triggerIconSize" :trigger-text="triggerText"
10
+ :tip="tip"
11
+ :show-file-list="showFileList"
12
+ :data="params"
13
+ :before-upload="beforeUpload"
14
+ :on-upload="onUpload"
15
+ :on-progress="onProgress"
16
+ :on-success="_onSuccess"
17
+ :on-error="onError"
18
+ :on-removed="_onRemove"
19
+ :handle-errors="handleErrors"
20
+ :file-icon="fileIcon"
21
+ :disabled="disabled">
22
+ <template #trigger v-if="$slots.trigger">
23
+ <slot name="trigger"></slot>
24
+ </template>
25
+ </tnxel-upload>
26
+ </template>
27
+
28
+ <script>
29
+ import Upload from '../upload/Upload.vue';
30
+
31
+ export default {
32
+ components: {
33
+ 'tnxel-upload': Upload,
34
+ },
35
+ name: 'TnxelFssUpload',
36
+ props: {
37
+ modelValue: [String, Array],
38
+ type: {
39
+ type: String,
40
+ required: true,
41
+ },
42
+ scope: [Number, String],
43
+ width: {
44
+ type: [Number, String],
45
+ },
46
+ height: {
47
+ type: [Number, String],
48
+ },
49
+ triggerIcon: String,
50
+ triggerIconSize: Number,
51
+ triggerText: String,
52
+ center: Boolean,
53
+ tip: {
54
+ type: [Boolean, String, Function],
55
+ default() {
56
+ return true;
57
+ }
58
+ },
59
+ showFileList: {
60
+ type: Boolean,
61
+ default() {
62
+ return true;
63
+ }
64
+ },
65
+ extension: [String, Array], // 可接受的文件扩展名集合,最终实际生效的扩展名集合,是它与服务端上传配置中的扩展名限制集合的并集
66
+ beforeUpload: Function,
67
+ onUpload: Function,
68
+ onProgress: Function,
69
+ onSuccess: Function,
70
+ onError: Function,
71
+ onRemove: Function,
72
+ handleErrors: Function,
73
+ fileIcon: [String, Function],
74
+ disabled: Boolean,
75
+ },
76
+ emits: ['update:modelValue'],
77
+ data() {
78
+ const tnx = window.tnx;
79
+ return {
80
+ tnx: tnx,
81
+ appName: tnx.fss.appName,
82
+ action: tnx.fss.getUploadUrl(this.type, this.scope),
83
+ params: {},
84
+ uploadOptions: {},
85
+ fileList: [],
86
+ };
87
+ },
88
+ computed: {
89
+ uploadingFiles() {
90
+ return this.$refs.upload?.files || [];
91
+ },
92
+ },
93
+ watch: {
94
+ modelValue(newValue, oldValue) {
95
+ if (oldValue !== newValue && !this.equals(this.fileList, newValue)) {
96
+ this._initialize();
97
+ }
98
+ }
99
+ },
100
+ mounted() {
101
+ this._initialize();
102
+ },
103
+ methods: {
104
+ equals(fileList, locationUrls) {
105
+ if (!locationUrls) {
106
+ return !fileList.length;
107
+ }
108
+ if (!Array.isArray(locationUrls)) {
109
+ locationUrls = [locationUrls];
110
+ }
111
+ if (fileList.length !== locationUrls.length) {
112
+ return false;
113
+ }
114
+ // 每一个存储地址都必须在文件清单中找到对应文件
115
+ for (let locationUrl of locationUrls) {
116
+ if (!this.contains(fileList, locationUrl)) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ },
122
+ contains(fileList, locationUrl) {
123
+ for (let file of fileList) {
124
+ if (file.locationUrl === locationUrl) {
125
+ return true;
126
+ }
127
+ }
128
+ return false;
129
+ },
130
+ _initialize() {
131
+ const vm = this;
132
+ let fssConfig = vm.tnx.fss.getClientConfig();
133
+ vm.tnx.app.rpc.ensureLogined(function () {
134
+ let locationUrls;
135
+ if (vm.modelValue) {
136
+ locationUrls = Array.isArray(vm.modelValue) ? vm.modelValue : [vm.modelValue];
137
+ } else {
138
+ locationUrls = [];
139
+ }
140
+ if (locationUrls.length) {
141
+ vm.tnx.app.rpc.get(fssConfig.contextUrl + '/metas', {
142
+ locationUrls: locationUrls
143
+ }, function (metas) {
144
+ let fileList = [];
145
+ metas.forEach(meta => {
146
+ if (meta) {
147
+ fileList.push({
148
+ name: meta.name,
149
+ url: vm._getFullReadUrl(meta.thumbnailReadUrl || meta.readUrl),
150
+ previewUrl: vm._getFullReadUrl(meta.readUrl),
151
+ locationUrl: meta.locationUrl,
152
+ });
153
+ }
154
+ });
155
+ vm.fileList = fileList;
156
+ vm.$nextTick(function () {
157
+ vm._loadUploadOptions();
158
+ });
159
+ }, {
160
+ app: fssConfig.appName
161
+ });
162
+ } else {
163
+ vm.fileList = [];
164
+ vm.$nextTick(function () {
165
+ vm._loadUploadOptions();
166
+ });
167
+ }
168
+ }, {
169
+ app: fssConfig.appName,
170
+ toLogin(loginFormUrl, originalUrl, originalMethod) {
171
+ return true;
172
+ }
173
+ });
174
+ },
175
+ _loadUploadOptions() {
176
+ // 上传限制为空才执行加载,避免多次重复加载
177
+ if (Object.keys(this.uploadOptions).length === 0) {
178
+ let vm = this;
179
+ vm.tnx.fss.loadUploadOptions(this.type, function (uploadOptions) {
180
+ if (vm.extension) {
181
+ let extensions = Array.isArray(vm.extension) ? vm.extension : [vm.extension];
182
+ let acceptedExtensions = [];
183
+ if (uploadOptions.extensionsRejected) { // 服务端上传限制扩展名为排除模式
184
+ for (let extension of extensions) {
185
+ if (!uploadOptions.extensions.contains(extension)) { // 取未被排除的
186
+ acceptedExtensions.push(extension);
187
+ }
188
+ }
189
+ } else { // 服务端上传限制扩展名为包含模式
190
+ if (uploadOptions.extensions.length) {
191
+ for (let extension of extensions) {
192
+ if (uploadOptions.extensions.contains(extension)) { // 取被包含的
193
+ acceptedExtensions.push(extension);
194
+ }
195
+ }
196
+ } else { // 未限制扩展名,则直接加入
197
+ for (let extension of extensions) {
198
+ acceptedExtensions.push(extension);
199
+ }
200
+ }
201
+ }
202
+ if (acceptedExtensions.length) { // 接受的扩展名清单不为空,则替代服务端配置中的扩展名限制
203
+ uploadOptions.extensionsRejected = false;
204
+ uploadOptions.extensions = acceptedExtensions;
205
+ }
206
+ }
207
+ vm.uploadOptions = uploadOptions;
208
+ });
209
+ }
210
+ },
211
+ _getFullReadUrl(readUrl) {
212
+ if (readUrl && readUrl.startsWith('//')) {
213
+ return window.location.protocol + readUrl;
214
+ }
215
+ return readUrl;
216
+ },
217
+ _onSuccess(result, file, fileList) {
218
+ if (result) {
219
+ file.locationUrl = result.locationUrl;
220
+ file.readUrl = result.readUrl;
221
+ file.downloadUrl = result.downloadUrl;
222
+ // 构建Upload组件用到的文件字段
223
+ file.url = result.readUrl;
224
+ file.previewUrl = (process.env.VUE_APP_API_BASE_URL + result.downloadUrl) || result.readUrl;
225
+
226
+ this.fileList = fileList;
227
+ this.emitInput();
228
+ if (this.onSuccess) {
229
+ this.onSuccess(file);
230
+ }
231
+ }
232
+ },
233
+ _onRemove(file) {
234
+ for (let i = 0; i < this.fileList.length; i++) {
235
+ let _file = this.fileList[i];
236
+ if (_file.id === file.id) {
237
+ this.fileList.splice(i, 1);
238
+ break;
239
+ }
240
+ }
241
+ this.emitInput();
242
+ if (this.onRemove) {
243
+ this.onRemove(file);
244
+ }
245
+ },
246
+ emitInput() {
247
+ let locationUrls = [];
248
+ for (let file of this.fileList) {
249
+ if (file.locationUrl) {
250
+ locationUrls.push(file.locationUrl);
251
+ } else { // 存在一个未完成上传,则退出
252
+ return;
253
+ }
254
+ }
255
+ if (this.uploadOptions.number === 1) {
256
+ locationUrls = locationUrls[0];
257
+ }
258
+ this.$emit('update:modelValue', locationUrls);
259
+ },
260
+ size() {
261
+ return this.$refs.upload.size();
262
+ },
263
+ /**
264
+ * 校验上传是否已经全部完成
265
+ * @param reject 没有完成上传时的处理函数,传入文件对象参数
266
+ * @returns 文件存储路径或其数组,有上传未完成时返回false
267
+ */
268
+ validateUploaded(reject) {
269
+ if (this.uploadOptions.number > 1) {
270
+ const locationUrls = [];
271
+ for (let file of this.uploadingFiles) {
272
+ if (file.locationUrl) {
273
+ locationUrls.push(file.locationUrl);
274
+ } else {
275
+ this._doValidateUploadedReject(reject, file);
276
+ return false;
277
+ }
278
+ }
279
+ return locationUrls;
280
+ } else if (this.uploadingFiles.length) {
281
+ let file = this.uploadingFiles[0];
282
+ if (file) {
283
+ if (file.locationUrl) {
284
+ return file.locationUrl;
285
+ } else {
286
+ this._doValidateUploadedReject(reject, file);
287
+ return false;
288
+ }
289
+ }
290
+ }
291
+ return null;
292
+ },
293
+ _doValidateUploadedReject(reject, file) {
294
+ if (typeof reject === 'function') {
295
+ reject(file);
296
+ } else {
297
+ this.tnx.alert('文件"' + file.name + '"还未上传完毕,请稍候', function () {
298
+ if (reject && typeof reject.disable === 'function') {
299
+ reject.disable(false);
300
+ }
301
+ });
302
+ }
303
+ },
304
+ }
305
+ }
306
+ </script>
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <div class="tnxel-fss-view" v-if="meta.readUrl">
3
+ <span class="text-muted" v-if="denied">没有权限查看该文件</span>
4
+ <template v-else-if="thumbnailIconValue">
5
+ <tnxel-button type="primary" link :icon="thumbnailIconValue" :title="$attrs.title || meta.name"
6
+ @click="toPreview"/>
7
+ <el-image-viewer :url-list="[previewUrl]" teleported @close="imagePreviewing = false"
8
+ v-if="imagePreviewing"/>
9
+ </template>
10
+ <el-image :src="meta.thumbnailReadUrl" :preview-src-list="[meta.readUrl]" fit="contain" preview-teleported
11
+ :style="{width: imageWidth, height: imageHeight}" v-else-if="imageable">
12
+ <template #error>
13
+ <div class="text-muted h-100 flex-center">
14
+ <i class="el-icon-picture-outline"/>
15
+ </div>
16
+ </template>
17
+ </el-image>
18
+ <template v-else>
19
+ <a class="overflow-ellipsis" :href="downloadUrl" target="_blank" :title="'下载 ' + meta.name">
20
+ {{ meta.name }}
21
+ </a>
22
+ <a class="preview" :href="previewUrl" target="_blank" :title="'预览 ' + meta.name"
23
+ v-if="previewUrl">预览</a>
24
+ </template>
25
+ </div>
26
+ </template>
27
+
28
+ <script>
29
+ import Button from '../button/Button.vue';
30
+
31
+ const tnx = window.tnx;
32
+
33
+ export default {
34
+ name: 'TnxelFssView',
35
+ components: {
36
+ 'tnxel-button': Button,
37
+ },
38
+ props: {
39
+ url: String,
40
+ width: [String, Number],
41
+ height: [String, Number],
42
+ thumbnailIcon: { // 为Boolean时表示是否仅显示缩略图标,图标采用与扩展名匹配的图标,为String时仅显示指定图标
43
+ type: [Boolean, String],
44
+ default: false,
45
+ },
46
+ },
47
+ data() {
48
+ return {
49
+ meta: {
50
+ readUrl: null,
51
+ thumbnailReadUrl: null,
52
+ imageable: false,
53
+ },
54
+ denied: false,
55
+ imagePreviewing: false,
56
+ }
57
+ },
58
+ computed: {
59
+ extension() {
60
+ return tnx.util.net.getExtension(this.meta.readUrl);
61
+ },
62
+ imageable() {
63
+ return tnx.util.file.isImage(this.extension);
64
+ },
65
+ imageWidth() {
66
+ let size = this.meta.size;
67
+ let width = this.width || (size ? size.width : undefined);
68
+ if (typeof width === 'number') {
69
+ width += 'px';
70
+ }
71
+ return width;
72
+ },
73
+ imageHeight() {
74
+ let size = this.meta.size;
75
+ let height = this.height || (size ? size.height : undefined);
76
+ if (typeof height === 'number') {
77
+ height += 'px';
78
+ }
79
+ return height;
80
+ },
81
+ downloadUrl() {
82
+ return process.env.VUE_APP_API_BASE_URL + this.meta.downloadUrl;
83
+ },
84
+ previewUrl() {
85
+ if (this.imageable) {
86
+ return this.meta.readUrl; // 图片预览尽量使用第三方文件服务提供商地址
87
+ }
88
+ if (this.extension === 'pdf') { // pdf预览会打开新页面,故使用自有地址,尽量不暴露第三方文件服务提供商地址
89
+ return tnx.util.net.appendParams(this.downloadUrl, {
90
+ inline: true,
91
+ });
92
+ }
93
+ return undefined;
94
+ },
95
+ thumbnailIconValue() {
96
+ if (this.thumbnailIcon) {
97
+ if (typeof this.thumbnailIcon === 'string') {
98
+ return this.thumbnailIcon;
99
+ }
100
+ if (this.imageable) {
101
+ return 'bi bi-file-earmark-image';
102
+ }
103
+ if (this.extension === 'pdf') {
104
+ return 'bi bi-file-earmark-pdf';
105
+ }
106
+ return 'bi bi-file-earmark';
107
+ }
108
+ return undefined;
109
+ },
110
+ },
111
+ watch: {
112
+ url() {
113
+ this.load();
114
+ }
115
+ },
116
+ created() {
117
+ this.load();
118
+ },
119
+ methods: {
120
+ load() {
121
+ if (this.url && this.url.startsWith(window.tnx.fss.PROTOCOL)) {
122
+ let rpc = window.tnx.app.rpc;
123
+ let fssConfig = window.tnx.fss.getClientConfig();
124
+ let vm = this;
125
+ rpc.get(fssConfig.contextUrl + '/meta', {
126
+ locationUrl: vm.url,
127
+ }, function (meta) {
128
+ vm.meta = meta;
129
+ }, {
130
+ app: fssConfig.appName,
131
+ error(errors) {
132
+ vm.denied = true;
133
+ console.error(errors[0].message);
134
+ }
135
+ });
136
+ }
137
+ },
138
+ toPreview() {
139
+ if (this.imageable) {
140
+ this.imagePreviewing = true;
141
+ } else {
142
+ tnx.util.bom.openUniquely(this.previewUrl);
143
+ }
144
+ },
145
+ }
146
+ }
147
+ </script>
148
+
149
+ <style>
150
+ .tnxel-fss-view {
151
+ display: flex;
152
+ align-items: center;
153
+ }
154
+
155
+ .is-center .tnxel-fss-view {
156
+ justify-content: center;
157
+ }
158
+
159
+ .tnxel-fss-view .preview {
160
+ margin-left: 0.75rem;
161
+ white-space: nowrap;
162
+ }
163
+ </style>
@@ -0,0 +1,221 @@
1
+ <template>
2
+ <el-icon :class="className" :color="color" :style="style">
3
+ <Loading v-if="value === 'Loading'"/>
4
+ <ArrowDown v-else-if="value === 'ArrowDown'"/>
5
+ <ArrowLeft v-else-if="value === 'ArrowLeft'"/>
6
+ <ArrowLeftBold v-else-if="value === 'ArrowLeftBold'"/>
7
+ <ArrowRight v-else-if="value === 'ArrowRight'"/>
8
+ <ArrowRightBold v-else-if="value === 'ArrowRightBold'"/>
9
+ <Bottom v-else-if="value === 'Bottom'"/>
10
+ <CaretBottom v-else-if="value === 'CaretBottom'"/>
11
+ <CaretTop v-else-if="value === 'CaretTop'"/>
12
+ <Check v-else-if="value === 'Check'"/>
13
+ <CircleCheck v-else-if="value === 'CircleCheck'"/>
14
+ <CircleCheckFilled v-else-if="value === 'CircleCheckFilled'"/>
15
+ <CircleClose v-else-if="value === 'CircleClose'"/>
16
+ <CircleCloseFilled v-else-if="value === 'CircleCloseFilled'"/>
17
+ <Close v-else-if="value === 'Close'"/>
18
+ <CloseBold v-else-if="value === 'CloseBold'"/>
19
+ <CopyDocument v-else-if="value === 'CopyDocument'"/>
20
+ <Delete v-else-if="value === 'Delete'"/>
21
+ <DeleteFilled v-else-if="value === 'DeleteFilled'"/>
22
+ <Document v-else-if="value === 'Document'"/>
23
+ <DocumentCopy v-else-if="value === 'DocumentCopy'"/>
24
+ <Download v-else-if="value === 'Download'"/>
25
+ <Edit v-else-if="value === 'Edit'"/>
26
+ <Folder v-else-if="value === 'Folder'"/>
27
+ <HomeFilled v-else-if="value === 'HomeFilled'"/>
28
+ <InfoFilled v-else-if="value === 'InfoFilled'"/>
29
+ <MoreFilled v-else-if="value === 'MoreFilled'"/>
30
+ <OfficeBuilding v-else-if="value === 'OfficeBuilding'"/>
31
+ <Picture v-else-if="value === 'Picture'"/>
32
+ <PictureFilled v-else-if="value === 'PictureFilled'"/>
33
+ <Plus v-else-if="value === 'Plus'"/>
34
+ <Pointer v-else-if="value === 'Pointer'"/>
35
+ <QuestionFilled v-else-if="value === 'QuestionFilled'"/>
36
+ <Rank v-else-if="value === 'Rank'"/>
37
+ <Refresh v-else-if="value === 'Refresh'"/>
38
+ <Remove v-else-if="value === 'Remove'"/>
39
+ <RemoveFilled v-else-if="value === 'RemoveFilled'"/>
40
+ <Right v-else-if="value === 'Right'"/>
41
+ <Search v-else-if="value === 'Search'"/>
42
+ <Select v-else-if="value === 'Select'"/>
43
+ <Setting v-else-if="value === 'Setting'"/>
44
+ <Sort v-else-if="value === 'Sort'"/>
45
+ <SuccessFilled v-else-if="value === 'SuccessFilled'"/>
46
+ <Switch v-else-if="value === 'Switch'"/>
47
+ <Top v-else-if="value === 'Top'"/>
48
+ <UserFilled v-else-if="value === 'UserFilled'"/>
49
+ <View v-else-if="value === 'View'"/>
50
+ <WarningFilled v-else-if="value === 'WarningFilled'"/>
51
+ <ZoomIn v-else-if="value === 'ZoomIn'"/>
52
+ </el-icon>
53
+ </template>
54
+
55
+ <script>
56
+ import {
57
+ ArrowDown,
58
+ ArrowLeft,
59
+ ArrowLeftBold,
60
+ ArrowRight,
61
+ ArrowRightBold,
62
+ Bottom,
63
+ CaretBottom,
64
+ CaretTop,
65
+ Check,
66
+ CircleCheck,
67
+ CircleCheckFilled,
68
+ CircleClose,
69
+ CircleCloseFilled,
70
+ Close,
71
+ CloseBold,
72
+ CopyDocument,
73
+ Delete,
74
+ DeleteFilled,
75
+ Document,
76
+ DocumentCopy,
77
+ Download,
78
+ Edit,
79
+ Folder,
80
+ HomeFilled,
81
+ InfoFilled,
82
+ Loading,
83
+ MoreFilled,
84
+ OfficeBuilding,
85
+ Picture,
86
+ PictureFilled,
87
+ Plus,
88
+ Pointer,
89
+ QuestionFilled,
90
+ Rank,
91
+ Refresh,
92
+ Remove,
93
+ RemoveFilled,
94
+ Right,
95
+ Search,
96
+ Select,
97
+ Setting,
98
+ Sort,
99
+ SuccessFilled,
100
+ Switch,
101
+ Top,
102
+ UserFilled,
103
+ View,
104
+ WarningFilled,
105
+ ZoomIn,
106
+ } from '@element-plus/icons-vue';
107
+
108
+ const components = {
109
+ ArrowDown,
110
+ ArrowLeft,
111
+ ArrowLeftBold,
112
+ ArrowRight,
113
+ ArrowRightBold,
114
+ Bottom,
115
+ CaretBottom,
116
+ CaretTop,
117
+ Check,
118
+ CircleCheck,
119
+ CircleCheckFilled,
120
+ CircleClose,
121
+ CircleCloseFilled,
122
+ Close,
123
+ CloseBold,
124
+ CopyDocument,
125
+ Delete,
126
+ DeleteFilled,
127
+ Document,
128
+ DocumentCopy,
129
+ Download,
130
+ Edit,
131
+ Folder,
132
+ HomeFilled,
133
+ InfoFilled,
134
+ MoreFilled,
135
+ Loading,
136
+ OfficeBuilding,
137
+ Picture,
138
+ PictureFilled,
139
+ Plus,
140
+ Pointer,
141
+ QuestionFilled,
142
+ Rank,
143
+ Refresh,
144
+ Remove,
145
+ RemoveFilled,
146
+ Right,
147
+ Search,
148
+ Select,
149
+ Setting,
150
+ Sort,
151
+ SuccessFilled,
152
+ Switch,
153
+ Top,
154
+ UserFilled,
155
+ View,
156
+ WarningFilled,
157
+ ZoomIn,
158
+ };
159
+
160
+ export default {
161
+ name: 'TnxelIcon',
162
+ components: components,
163
+ props: {
164
+ value: String,
165
+ color: {},
166
+ size: Number,
167
+ width: [Number, String],
168
+ height: [Number, String],
169
+ },
170
+ computed: {
171
+ isUrlType() {
172
+ return this.value && (
173
+ this.value.startsWith('https://') || this.value.startsWith('http://')
174
+ || this.value.startsWith('../') || this.value.startsWith('./') || this.value.startsWith('/')
175
+ );
176
+ },
177
+ className() {
178
+ if (this.isUrlType) {
179
+ return undefined;
180
+ }
181
+ if (this.value && components[this.value]) {
182
+ let className = 'tnxel-icon-' + this.value;
183
+ if (this.value === 'Loading') {
184
+ className += ' is-loading';
185
+ }
186
+ return className;
187
+ } else if (this.value === 'loading') {
188
+ return 'tnxel-icon-' + this.value + ' el-icon-loading';
189
+ } else {
190
+ return this.value;
191
+ }
192
+ },
193
+ style() {
194
+ let style = {};
195
+ if (this.size) {
196
+ style['font-size'] = this.size + 'px';
197
+ }
198
+ let width = this.width || this.size;
199
+ if (width) {
200
+ style.width = width;
201
+ if (typeof style.width === 'number') {
202
+ style.width += 'px';
203
+ }
204
+ }
205
+ let height = this.height || this.size;
206
+ if (height) {
207
+ style.height = height;
208
+ if (typeof style.height === 'number') {
209
+ style.height += 'px';
210
+ }
211
+ }
212
+ if (this.isUrlType) {
213
+ style['background-repeat'] = 'no-repeat';
214
+ style['background-image'] = 'url(' + this.value + ')';
215
+ style['background-size'] = style.width + ' ' + style.height;
216
+ }
217
+ return style;
218
+ }
219
+ },
220
+ }
221
+ </script>