@ajaxjs/ui 1.1.8 → 1.2.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 (50) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +1 -2
  3. package/dist/index.js.map +1 -1
  4. package/dist/util/utils.d.ts +7 -0
  5. package/dist/util/utils.js +35 -1
  6. package/dist/util/utils.js.map +1 -1
  7. package/package.json +3 -3
  8. package/src/App.vue +14 -0
  9. package/src/index.ts +50 -0
  10. package/src/main.ts +12 -0
  11. package/src/pages/calendar.vue +33 -0
  12. package/src/pages/form.vue +68 -0
  13. package/src/pages/html-editor.vue +44 -0
  14. package/src/pages/index.vue +150 -0
  15. package/src/pages/play-ground.vue +14 -0
  16. package/src/pages/widgets.vue +183 -0
  17. package/src/router/index.ts +19 -0
  18. package/src/shims-vue.d.ts +4 -0
  19. package/src/style/common-functions.less +294 -0
  20. package/src/style/reset.less +19 -0
  21. package/src/util/cookies.ts +43 -0
  22. package/src/util/dom.ts +47 -0
  23. package/src/util/utils.ts +184 -0
  24. package/src/util/xhr-config.ts +25 -0
  25. package/src/util/xhr.ts +296 -0
  26. package/src/widget/AccordionMenu.vue +140 -0
  27. package/src/widget/AdjustFontSize.vue +65 -0
  28. package/src/widget/Article.vue +59 -0
  29. package/src/widget/EmptyContent.js +4 -0
  30. package/src/widget/Expander.vue +65 -0
  31. package/src/widget/FileUploader/FileUploader.less +68 -0
  32. package/src/widget/FileUploader/FileUploader.ts +156 -0
  33. package/src/widget/FileUploader/FileUploader.vue +43 -0
  34. package/src/widget/HtmlEditor/HtmlEditor.less +345 -0
  35. package/src/widget/HtmlEditor/HtmlEditor.ts +339 -0
  36. package/src/widget/HtmlEditor/HtmlEditor.vue +70 -0
  37. package/src/widget/HtmlEditor/html-editor-HtmlSanitizer.js +103 -0
  38. package/src/widget/ImageEnlarger.vue +105 -0
  39. package/src/widget/OpacityBanner.vue +125 -0
  40. package/src/widget/ProcessLine.vue +133 -0
  41. package/src/widget/Resize.ts +152 -0
  42. package/src/widget/Resize.vue +104 -0
  43. package/src/widget/TreeSelector.vue +4 -0
  44. package/src/widget/calendar/BetweenDate.vue +63 -0
  45. package/src/widget/calendar/Calendar.less +210 -0
  46. package/src/widget/calendar/Calendar.ts +167 -0
  47. package/src/widget/calendar/Calendar.vue +52 -0
  48. package/src/widget/calendar/CalendarInput.vue +71 -0
  49. package/src/widget/form/validator.ts +289 -0
  50. package/src/widget/play-ground/sku.vue +93 -0
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <article>
3
+ <h2>{{title}}</h2>
4
+
5
+ <div class="toolbar">
6
+ <span v-if="author">作者: {{author}}</span> &nbsp;
7
+ <a :href="source" v-if="source" target="_blank">
8
+
9
+ <svg width="16px" height="16px" viewBox="0 0 24 24" style="cursor:pointer;vertical-align: middle;">
10
+ <g stroke-width="2.1" stroke="#666" fill="none" stroke-linecap="round" stroke-linejoin="round">
11
+ <polyline points="17 13.5 17 19.5 5 19.5 5 7.5 11 7.5"></polyline>
12
+ <path d="M14,4.5 L20,4.5 L20,10.5 M20,4.5 L11,13.5"></path>
13
+ </g>
14
+ </svg>
15
+ 来源</a>
16
+ <FontSize style="float:right;clear:both"></FontSize>
17
+ </div>
18
+ <slot></slot>
19
+ </article>
20
+ </template>
21
+
22
+ <script>
23
+ import FontSize from './AdjustFontSize.vue';
24
+
25
+ export default {
26
+ props: {
27
+ title: String, author: String, source: String
28
+ },
29
+ components: { FontSize }
30
+ }
31
+ </script>
32
+
33
+ <style lang="less" scoped>
34
+ @import "../style/common-functions.less";
35
+
36
+ article {
37
+ & > p {
38
+ .aj-text-function();
39
+ text-indent: 2em;
40
+ }
41
+ & > img,
42
+ & > p > img {
43
+ max-width: 80%;
44
+ margin: 0 auto;
45
+ display: block;
46
+ }
47
+
48
+ h2 {
49
+ .aj-text-title();
50
+ }
51
+
52
+ .toolbar {
53
+ height: 15px;
54
+ margin: 30px 0;
55
+ font-size: 0.8rem;
56
+ text-align: right;
57
+ }
58
+ }
59
+ </style>
@@ -0,0 +1,4 @@
1
+ export default {
2
+ empty: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwIiBoZWlnaHQ9IjEyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBzdHJva2U9IiNEQURFRTMiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0iTTUwLjU5OCAxMS4wOTNDMjUuNTU0IDE1Ljc2IDExLjcyOCAyNC41NzMgOS4xMiAzNy41MzUgNS45OSA2OC42NDQgMTI4LjA4IDcwLjIgMTEzLjIxIDEwMi44NjNjLTcuODI2IDEwLjg4Ny0yNS41NjYgMTMuMjItNTMuMjE5IDYuOTk5IiBzdHJva2UtZGFzaGFycmF5PSIzIi8+PGcgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZmlsbD0iI0ZGRiIgZD0ibTU1IDY4LjI3IDQyLjE2Mi0xMi4zMjR2NDkuNTc3TDU1IDExNy41Njh6TTU1IDY4LjEwOCAxNi4wODEgNTUuOTQ2djQ5LjU3N0w1NSAxMTcuNTY4eiIvPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik0xNi4wMTIgNTYuMDQgNTUgNjguMTA4IDQyLjUgODYuNzU3IDQuNzMgNzMuMDYzek05Ny4xNjIgNTUuOTQ2IDU1IDY4LjEwOGwxMi44MSAxOC42NDkgNDIuMzI1LTE0LjE2NnoiLz48cGF0aCBmaWxsPSIjRjZGN0Y4IiBkPSJtMTYuMDgxIDU1Ljk0NiA0My4zNDctMTIuMTYyIDM3LjczNCAxMi4xNjJMNTUgNjguMTA4eiIvPjwvZz48ZyBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBmaWxsPSIjRkZGIiBkPSJNNzguMDY4IDEwLjMxIDYwLjA0IDguOGwyLjc5LTUuMzF6Ii8+PHBhdGggZmlsbD0iI0Y2RjdGOCIgZD0iTTc4LjA2OCAxMC4zMSA1Ni40NSAxMy44OGwtMy44MzQtNS45MzR6Ii8+PC9nPjwvZz48L3N2Zz4=',
3
+ emptyDrak: 'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEyMCIgd2lkdGg9IjEyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBzdHJva2U9IiMzYTNjNDYiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0iTTUwLjU5OCAxMS4wOTNDMjUuNTU0IDE1Ljc2IDExLjcyOCAyNC41NzMgOS4xMiAzNy41MzUgNS45OSA2OC42NDQgMTI4LjA4IDcwLjIgMTEzLjIxIDEwMi44NjNjLTcuODI2IDEwLjg4Ny0yNS41NjYgMTMuMjItNTMuMjE5IDYuOTk5IiBzdHJva2UtZGFzaGFycmF5PSIzIi8+PGcgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PGcgZmlsbD0iIzFhMWIxZSI+PHBhdGggZD0ibTU1IDY4LjI3IDQyLjE2Mi0xMi4zMjR2NDkuNTc3TDU1IDExNy41Njh6TTU1IDY4LjEwOCAxNi4wODEgNTUuOTQ2djQ5LjU3N0w1NSAxMTcuNTY4eiIvPjxwYXRoIGQ9Ik0xNi4wMTIgNTYuMDQgNTUgNjguMTA4IDQyLjUgODYuNzU3IDQuNzMgNzMuMDYzek05Ny4xNjIgNTUuOTQ2IDU1IDY4LjEwOGwxMi44MSAxOC42NDkgNDIuMzI1LTE0LjE2NnoiLz48L2c+PHBhdGggZD0ibTE2LjA4MSA1NS45NDYgNDMuMzQ3LTEyLjE2MiAzNy43MzQgMTIuMTYyTDU1IDY4LjEwOHoiIGZpbGw9IiMxNDE1MTgiLz48L2c+PGcgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTc4LjA2OCAxMC4zMSA2MC4wNCA4LjhsMi43OS01LjMxeiIgZmlsbD0iIzFhMWIxZSIvPjxwYXRoIGQ9Ik03OC4wNjggMTAuMzEgNTYuNDUgMTMuODhsLTMuODM0LTUuOTM0eiIgZmlsbD0iIzE0MTUxOCIvPjwvZz48L2c+PC9zdmc+'
4
+ };
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <div class="aj-expander" :style="'height:' + (expended ? openHeight : closeHeight) + 'px;'">
3
+ <div :class="expended ? 'closeBtn' : 'openBtn'" @click="expended = !expended;"></div>
4
+ <slot></slot>
5
+ </div>
6
+ </template>
7
+
8
+ <script lang="ts">
9
+ /**
10
+ * 展开闭合器
11
+ */
12
+ export default {
13
+ props: {
14
+ openHeight: { type: Number, default: 200 },
15
+ closeHeight: { type: Number, default: 50 },
16
+ },
17
+ data(): any {
18
+ return {
19
+ expended: false,
20
+ };
21
+ },
22
+ };
23
+ </script>
24
+
25
+ <style lang="less" scoped>
26
+ .aj-expander {
27
+ overflow: hidden;
28
+ position: relative;
29
+ clear: both;
30
+ transition: height 200ms ease 0s;
31
+
32
+ .mask-layer {
33
+ position: absolute;
34
+ bottom: 0;
35
+ left: 0;
36
+ height: 23px;
37
+ width: 100%;
38
+ background: -webkit-gradient(
39
+ linear,
40
+ center top,
41
+ center bottom,
42
+ from(transparent),
43
+ to(white)
44
+ );
45
+ }
46
+
47
+ .openBtn {
48
+ background: url("https://ajaxjs.nos-eastchina1.126.net/images/openBtn.png");
49
+ }
50
+
51
+ .closeBtn {
52
+ background: url("https://ajaxjs.nos-eastchina1.126.net/images/closeBtn.png");
53
+ }
54
+
55
+ .closeBtn,
56
+ .openBtn {
57
+ width: 45px;
58
+ height: 32px;
59
+ position: absolute;
60
+ cursor: pointer;
61
+ top: 0px;
62
+ right: 0px;
63
+ }
64
+ }
65
+ </style>
@@ -0,0 +1,68 @@
1
+ .aj-file-uploader {
2
+ width: 360px;
3
+
4
+ &>* {
5
+ display: inline-block;
6
+ vertical-align: middle;
7
+ }
8
+
9
+ label {
10
+ margin-right: 2%;
11
+
12
+ &>div {
13
+ border: 1px solid lightgray;
14
+ border-radius: 5px;
15
+ text-align: center;
16
+ color: gray;
17
+ cursor: pointer;
18
+ font-size: 0.8rem;
19
+ padding: 10px;
20
+ padding-bottom: 25px;
21
+ width: 100px;
22
+ height: 70px;
23
+ transition: border-color linear 300ms, color linear 300ms;
24
+
25
+ &:hover {
26
+ border-color: gray;
27
+ color: black;
28
+ }
29
+
30
+ &>div {
31
+ font-size: 2rem;
32
+ }
33
+ }
34
+ }
35
+
36
+ button {
37
+ min-width: 110px;
38
+ }
39
+
40
+ input[type="file"] {
41
+ display: none;
42
+ }
43
+
44
+ .msg {
45
+ font-size: 0.8rem;
46
+ color: gray;
47
+ max-width: 50%;
48
+ word-break: break-word;
49
+ text-overflow: ellipsis;
50
+
51
+ &>div {
52
+ font-size: 0.75rem;
53
+ }
54
+ }
55
+
56
+ .perviewImg {
57
+ max-width: 260px;
58
+ }
59
+
60
+ .fileName {
61
+ // display: inline-block;
62
+ text-overflow: ellipsis; //溢出用省略号显示
63
+ white-space: nowrap; //溢出不换行
64
+ max-width: 120px;
65
+ max-height: 20px;
66
+ overflow: hidden;
67
+ }
68
+ }
@@ -0,0 +1,156 @@
1
+ import Empty from '../EmptyContent';
2
+
3
+ export default {
4
+ props: {
5
+ action: { type: String, required: false }, // 上传路径
6
+ limitSize: { type: Number, default: 20000 }, // 文件大小限制
7
+ limitFileType: String,
8
+ isImgUpload: Boolean,
9
+ isShowBtn: { type: Boolean, default: true },
10
+ accpectFileType: {
11
+ type: String, default() {
12
+ if (this.isImgUpload)
13
+ return 'image/*';
14
+ }
15
+ }, // 可以上传类型 如 image/*
16
+ buttonBottom: Boolean, // 上传按钮是否位于下方
17
+ radomId: {
18
+ type: Number, default() { // 不重复的 id,用关于关联 label 与 input[type=file]
19
+ return Math.round(Math.random() * 1000);
20
+ },
21
+ },
22
+ },
23
+
24
+ data() {
25
+ return {
26
+ model: { children: [] },
27
+ imgSrc: Empty.empty,
28
+ open: false,
29
+ allowAddNode: false,
30
+ // isFolder : false
31
+ fileName: '', // 获取文件名称,只能是名称,不能获取完整的文件目录
32
+ fileSize: 0, // 文件大小
33
+ progress: 0, // 上传进度百分比
34
+ errMsg: '', // 错误信息。约定:只有为空字符串,才表示允许上传。
35
+ newlyId: '', // 成功上传之后的文件 id
36
+ fileObj: null
37
+ }
38
+ },
39
+
40
+ methods: {
41
+ /**
42
+ * 选择文件后触发的事件
43
+ *
44
+ * @param ev
45
+ */
46
+ onUploadInputChange(ev: Event): void {
47
+ let fileInput: HTMLInputElement = <HTMLInputElement>ev.target;
48
+ if (!fileInput.files || !fileInput.files[0]) return;
49
+
50
+ // this.errStatus = [false, false, false];
51
+ this.onFileGet(fileInput.files);
52
+
53
+ let file: File = fileInput.files[0];
54
+ this.fileObj = file;
55
+
56
+ if (this.isImgUpload) {
57
+ let reader: FileReader = new FileReader();
58
+ reader.onload = (e) => {
59
+ let imgBase64: string = <string>e.target.result; // 得到了图片的 base64 编码
60
+ // alert(imgBase64Str);
61
+ this.imgSrc = imgBase64;
62
+ }
63
+
64
+ reader.readAsDataURL(file);
65
+ }
66
+ },
67
+
68
+ /**
69
+ * 返回 File 对象,在表单混合上传时候有用
70
+ * @returns
71
+ */
72
+ getFileObj(): File {
73
+ return this.fileObj;
74
+ },
75
+
76
+ onDrop(ev: DragEvent): void {
77
+ ev.preventDefault(); // 阻止进行拖拽时浏览器的默认行为,即自动打开图片
78
+
79
+ if (ev.dataTransfer?.files) this.onFileGet(ev.dataTransfer.files);
80
+ },
81
+
82
+ onFileGet(files: FileList): void {
83
+ let file: File = files[0],
84
+ fileType: string = file.type;
85
+
86
+ this.$fileObj = file;
87
+ this.fileName = file.name;
88
+ this.fileSize = file.size;
89
+ },
90
+ /**
91
+ * 执行上传
92
+ *
93
+ * @param this
94
+ */
95
+ doUpload(): void {
96
+ // this.$uploadOk_callback({ isOk: true, msg: "ok!", imgUrl: "fdfdf" });
97
+ // return;
98
+
99
+ let fd: FormData = new FormData();
100
+
101
+ if (this.$blob) fd.append("file", this.$blob, this.fileName);
102
+ else if (this.$fileObj) fd.append("file", this.$fileObj);
103
+
104
+ let xhr: XMLHttpRequest = new XMLHttpRequest();
105
+ //@ts-ignore
106
+ xhr.onreadystatechange = aj.xhr.requestHandler.delegate(
107
+ null,
108
+ this.$uploadOk_callback,
109
+ "json"
110
+ );
111
+ xhr.open("POST", this.action, true);
112
+ xhr.onprogress = (ev: ProgressEvent) => {
113
+ let progress: number = 0,
114
+ p: number = ~~((ev.loaded * 1000) / ev.total);
115
+ p = p / 10;
116
+
117
+ if (progress !== p) progress = p;
118
+
119
+ this.progress = progress;
120
+ };
121
+
122
+ xhr.send(fd);
123
+ },
124
+
125
+ changeByte: changeByte
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 字节 Byte 转化成 KB,MB,GB
131
+ *
132
+ * @param limit
133
+ */
134
+ function changeByte(limit: number): string {
135
+ let size: string = "";
136
+
137
+ if (limit < 0.1 * 1024)
138
+ // 小于 0.1KB,则转化成 B
139
+ size = limit.toFixed(2) + "B";
140
+ else if (limit < 0.1 * 1024 * 1024)
141
+ // 小于 0.1MB,则转化成 KB
142
+ size = (limit / 1024).toFixed(2) + "KB";
143
+ else if (limit < 0.1 * 1024 * 1024 * 1024)
144
+ // 小于 0.1GB,则转化成 MB
145
+ size = (limit / (1024 * 1024)).toFixed(2) + "MB";
146
+ // 其他转化成 GB
147
+ else size = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB";
148
+
149
+ let index = size.indexOf("."); // 获取小数点处的索引
150
+
151
+ if (size.substr(index + 1, 2) == "00")
152
+ // 获取小数点后两位的值,判断后两位是否为 00,如果是则删除 00
153
+ return size.substring(0, index) + size.substr(index + 3, 2);
154
+
155
+ return size;
156
+ }
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <div class="aj-file-uploader">
3
+ <div v-if="isImgUpload">
4
+ <img class="perviewImg" :src='imgSrc' />
5
+ <br />
6
+ </div>
7
+
8
+ <table>
9
+ <tr>
10
+ <td>
11
+ <input type="file" :id="'uploadInput_' + radomId" @change="onUploadInputChange" :accept="accpectFileType" />
12
+
13
+ <label class="pseudoFilePicker" :for="'uploadInput_' + radomId">
14
+ <div @drop="onDrop" ondragover="event.preventDefault();">
15
+ <div>+</div>点击选择文件<br />或拖放到此
16
+ </div>
17
+ </label>
18
+
19
+ </td>
20
+ <td>
21
+ <div class="msg" v-if="errMsg != ''">
22
+ 允许类型:{{limitFileType || '无限制'}}
23
+ <br />
24
+ 允许大小:{{limitSize ? changeByte(limitSize * 1024) : '无限制'}}
25
+ <span class="slot"></span>
26
+ </div>
27
+
28
+ <div class="msg" v-if="errMsg == ''">
29
+ <div class="fileName" :title="'本地文件名: ' + fileName">{{fileName}}</div>
30
+ <div v-if="fileSize">{{changeByte(fileSize)}}</div>
31
+ <button @click.prevent="doUpload" v-if="isShowBtn">{{progress && progress !== 100 ? '上传中 ' + progress + '%': '上传'}}</button>
32
+ </div>
33
+ </td>
34
+ </tr>
35
+
36
+ </table>
37
+
38
+ </div>
39
+ </template>
40
+
41
+ <script lang="ts" src="./FileUploader.ts"></script>
42
+
43
+ <style lang="less" src="./FileUploader.less"></style>