oipage 1.5.0-alpha.0 → 1.5.0-alpha.2

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 (48) hide show
  1. package/CHANGELOG +4 -1
  2. package/README.md +14 -0
  3. package/bin/serve.js +3 -3
  4. package/bin/tools/resolve404.js +2 -2
  5. package/bin/website-htmls/components/ui-select-file/index.html +8 -0
  6. package/bin/website-htmls/components/ui-select-file/index.js +38 -0
  7. package/bin/website-htmls/components/ui-select-file/index.scss +45 -0
  8. package/bin/website-htmls/dialogs/imageSize/index.html +55 -0
  9. package/bin/website-htmls/dialogs/imageSize/index.js +53 -0
  10. package/bin/website-htmls/dialogs/imageSize/index.scss +139 -0
  11. package/bin/website-htmls/dialogs/index.js +29 -19
  12. package/bin/website-htmls/images/addFile.svg +1 -0
  13. package/bin/website-htmls/images/img-to-pdf.svg +1 -0
  14. package/bin/website-htmls/images/lock.png +0 -0
  15. package/bin/website-htmls/images/size.png +0 -0
  16. package/bin/website-htmls/main.js +2 -0
  17. package/bin/website-htmls/pages/appStore/index.html +6 -0
  18. package/bin/website-htmls/pages/chart/index.js +1 -1
  19. package/bin/website-htmls/pages/image-editor/index.html +14 -5
  20. package/bin/website-htmls/pages/image-editor/index.js +92 -5
  21. package/bin/website-htmls/pages/image-editor/index.scss +19 -5
  22. package/bin/website-htmls/pages/img-to-pdf/index.html +4 -0
  23. package/bin/website-htmls/pages/img-to-pdf/index.js +45 -0
  24. package/bin/website-htmls/pages/img-to-pdf/index.scss +5 -0
  25. package/bin/website-htmls/router.config.js +3 -0
  26. package/bin/website-plugins/intercept/index.js +2 -0
  27. package/bin/website-plugins/intercept/oipage-vislite-intercept.js +34 -0
  28. package/bin/website-plugins/intercept/oipage-zipaper-intercept.js +2 -2
  29. package/nodejs/animation/index.js +1 -1
  30. package/nodejs/cmdlog/index.js +1 -1
  31. package/nodejs/disk/index.js +1 -1
  32. package/nodejs/format/index.js +3 -3
  33. package/nodejs/json/index.js +1 -1
  34. package/nodejs/logform/index.js +1 -1
  35. package/nodejs/reader/index.js +1 -1
  36. package/nodejs/throttle/index.js +1 -1
  37. package/package.json +2 -2
  38. package/snipping/chart.png +0 -0
  39. package/snipping/image-editor.png +0 -0
  40. package/web/XMLHttpRequest/index.js +1 -1
  41. package/web/animation/index.js +1 -1
  42. package/web/format/index.js +3 -3
  43. package/web/json/index.js +1 -1
  44. package/web/onReady/index.js +1 -1
  45. package/web/performChunk/index.js +1 -1
  46. package/web/reader/index.js +1 -1
  47. package/web/style/index.js +1 -1
  48. package/web/throttle/index.js +1 -1
package/CHANGELOG CHANGED
@@ -103,7 +103,10 @@ v1.5.0:
103
103
  - 修复bug
104
104
  1、修复404网站在手机浏览器显示高问题
105
105
  2、服务器响应类型由 Content-type 改为 Content-Type
106
+ 3、修复dateFormat第二个参数无法缺省报错
107
+ 4、修复numberFormat不支持负数问题
106
108
  - 新增功能
107
109
  1、开发服务器 / 应用市场
108
110
  * 聊天工具
109
- * 图片编辑器
111
+ * 图片编辑器
112
+ * 图片转PDF
package/README.md CHANGED
@@ -74,6 +74,20 @@ oipage-cli serve -p 8080
74
74
 
75
75
  如果你需要在项目中使用,我们也提供了一些有用的API,具体可以访问[ 在线文档 ](https://oi-contrib.github.io/OIPage)进行了解。
76
76
 
77
+ ## 应用市场
78
+
79
+ 为了方便日常使用,内置了一个应用市场网站,比如有如下功能:
80
+
81
+ ### 群聊贴
82
+
83
+ <img src="./snipping/chart.png" />
84
+
85
+ ### 图片编辑器
86
+
87
+ <img src="./snipping/image-editor.png" />
88
+
89
+ 已有功能或更多功能我们将根据实际情况逐步完善和维护,当然,你可以通过 [issue](https://github.com/oi-contrib/VISLite/issues) 给我们留言,告诉我们你的改进意见。
90
+
77
91
  ## 版权
78
92
 
79
93
  MIT License
package/bin/serve.js CHANGED
@@ -18,13 +18,13 @@ module.exports = function (config) {
18
18
  let startTime = new Date().valueOf();
19
19
 
20
20
  const cache = "cache" in config.devServer ? config.devServer.cache : true;
21
- const port = config.devServer.port; // 端口号
21
+ const port = +config.devServer.port; // 端口号
22
22
  const basePath = (/^\./.test(config.devServer.baseUrl)) ? join(process.cwd(), config.devServer.baseUrl) : config.devServer.baseUrl; // 服务器根路径
23
23
 
24
- const name = (config.name || "OIPage") + "-dev-server";
24
+ const name = (config.name || "OIPage") + "-http-server";
25
25
  const version = config.version || packageValue.version;
26
26
 
27
- const wsHandler = WebSocketClass(port + 1, (config.name || "OIPage") + "-dev-websocket", version);
27
+ const wsHandler = WebSocketClass(port + 1, (config.name || "OIPage") + "-ws-server", version);
28
28
 
29
29
  let Server = createServer(function (request, response) {
30
30
  let headers = request.headers;
@@ -18,9 +18,9 @@ module.exports = function (filePath, url) {
18
18
 
19
19
  try {
20
20
  subItems = readdirSync(filePath);
21
- console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] Read Folder: " + url + '\x1b[0m ' + new Date().toLocaleString());
21
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read Folder: " + url + '\x1b[0m ' + new Date().toLocaleString());
22
22
  } catch (e) {
23
- console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] Read " + (/\/$/.test(url) ? "Folder" : "File") + ": \x1b[35m" + url + ' 404 Not Found\x1b[0m ' + new Date().toLocaleString());
23
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Read " + (/\/$/.test(url) ? "Folder" : "File") + ": \x1b[35m" + url + ' 404 Not Found\x1b[0m ' + new Date().toLocaleString());
24
24
  try {
25
25
  if (!/\/$/.test(url) || url === "/") {
26
26
  filePath = join(filePath, "../");
@@ -0,0 +1,8 @@
1
+ <div class="ui-select-file-view">
2
+ <h2 class="title" z-bind="_props.title"></h2>
3
+ <div class="tips" z-bind="_props.tips"></div>
4
+ <div class="file">
5
+ <input type="file" multiple id="input" z-on:change.stop="doChange" z-bind:accept="accept" />
6
+ <label for="input" z-bind="'选择'+_props.type+'文件'"></label>
7
+ </div>
8
+ </div>
@@ -0,0 +1,38 @@
1
+ import { defineElement } from "zipaper";
2
+ import template from "./index.html";
3
+ import style from "./index.scss";
4
+
5
+ export default defineElement({
6
+ template,
7
+ emits: ["change"],
8
+ props: {
9
+ title: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ tips: {
14
+ type: String,
15
+ required: true,
16
+ },
17
+ type: {
18
+ type: String,
19
+ required: true,
20
+ },
21
+ },
22
+ data() {
23
+ return {
24
+ accept: {
25
+ pdf: "application/pdf",
26
+ image: "image/*"
27
+ }[this._props.type]
28
+ };
29
+ },
30
+ methods: {
31
+ doChange(event, target) {
32
+ this.$emit("change", target.files);
33
+ }
34
+ },
35
+ style: {
36
+ content: style
37
+ }
38
+ });
@@ -0,0 +1,45 @@
1
+ .ui-select-file-view{
2
+ &>.title {
3
+ text-align: center;
4
+ font-weight: 700;
5
+ color: rgb(26, 26, 26);
6
+ font-size: 36px;
7
+ line-height: 48px;
8
+ padding-top: 30px;
9
+ }
10
+
11
+ &>.tips {
12
+ text-align: center;
13
+ line-height: 30px;
14
+ font-size: 22px;
15
+ color: rgb(26, 26, 26);
16
+ font-weight: 300;
17
+ }
18
+
19
+ &>.file {
20
+ text-align: center;
21
+ margin-top: 30px;
22
+
23
+ input {
24
+ display: none;
25
+ }
26
+
27
+ label {
28
+ line-height: 50px;
29
+ display: inline-block;
30
+ border: 1px solid gray;
31
+ background-image: url("./images/addFile.svg");
32
+ background-repeat: no-repeat;
33
+ background-position: 5px center;
34
+ background-size: auto 70%;
35
+ padding-left: 40px;
36
+ padding-right: 10px;
37
+ border-radius: 5px;
38
+
39
+ &:hover {
40
+ text-decoration: underline;
41
+ cursor: pointer;
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,55 @@
1
+ <h2 z-bind="title"></h2>
2
+ <div class="right-btn">
3
+ <div>
4
+ <fieldset>
5
+ <legend>
6
+ 当前大小
7
+ </legend>
8
+ <ul z-bind:lock="title=='图像大小'?'yes':'no'">
9
+ <li>
10
+ <label>宽度:</label>
11
+ <span z-bind="width"></span>px
12
+ </li>
13
+ <li>
14
+ <label>宽度:</label>
15
+ <span z-bind="height"></span>px
16
+ </li>
17
+ </ul>
18
+ </fieldset>
19
+ <fieldset>
20
+ <legend>
21
+ 新建大小
22
+ </legend>
23
+ <ul z-bind:lock="title=='图像大小'?'yes':'no'">
24
+ <li>
25
+ <label>宽度(W):</label>
26
+ <input type="text" z-model="newWidth" z-on:input="calcHeight">
27
+ px
28
+ </li>
29
+ <li>
30
+ <label>高度(H):</label>
31
+ <input type="text" z-model="newHeight" z-on:input="calcWidth">
32
+ px
33
+ </li>
34
+ <li z-bind:active="title=='画布大小'?'yes':'no'">
35
+ <label>定位:</label>
36
+ <div class="change-type" z-bind:type="changeType">
37
+ <span z-on:click="doChangeType" val="left-top"></span>
38
+ <span z-on:click="doChangeType" val="center-top"></span>
39
+ <span z-on:click="doChangeType" val="right-top"></span>
40
+ <span z-on:click="doChangeType" val="left-middle"></span>
41
+ <span z-on:click="doChangeType" val="center-middle"></span>
42
+ <span z-on:click="doChangeType" val="right-middle"></span>
43
+ <span z-on:click="doChangeType" val="left-bottom"></span>
44
+ <span z-on:click="doChangeType" val="center-bottom"></span>
45
+ <span z-on:click="doChangeType" val="right-bottom"></span>
46
+ </div>
47
+ </li>
48
+ </ul>
49
+ </fieldset>
50
+ </div>
51
+ <div>
52
+ <button z-on:click="doSubmit">确定</button>
53
+ <button z-on:click="doClose">取消</button>
54
+ </div>
55
+ </div>
@@ -0,0 +1,53 @@
1
+ import { defineElement, ref } from "zipaper"
2
+ import template from "./index.html"
3
+ import style from "./index.scss";
4
+
5
+ export default defineElement({
6
+ template,
7
+ data() {
8
+ return {
9
+ title: this._props.title,
10
+ width: this._props.width,
11
+ height: this._props.height,
12
+
13
+ newWidth: ref(this._props.width),
14
+ newHeight: ref(this._props.height),
15
+
16
+ changeType: ref('center-middle')
17
+ }
18
+ },
19
+ methods: {
20
+ calcHeight() {
21
+ if (this.title == '图像大小') {
22
+ this.newHeight = +(this.newWidth * this.height / this.width).toFixed(0);
23
+ }
24
+ },
25
+
26
+ calcWidth() {
27
+ if (this.title == '图像大小') {
28
+ this.newWidth = +(this.newHeight * this.width / this.height).toFixed(0);
29
+ }
30
+ },
31
+
32
+ doChangeType: function (event, target) {
33
+ this.changeType = target.getAttribute('val');
34
+ },
35
+
36
+ // 确定
37
+ doSubmit: function () {
38
+ this.$closeDialog({
39
+ width: +this.newWidth,
40
+ height: +this.newHeight,
41
+ changeType: this.changeType
42
+ });
43
+ },
44
+
45
+ // 取消
46
+ doClose: function () {
47
+ this.$closeDialog();
48
+ }
49
+ },
50
+ style: {
51
+ content: style
52
+ }
53
+ })
@@ -0,0 +1,139 @@
1
+ #dialog-root>.content.imageSize {
2
+ border: 1px solid gray;
3
+ min-height: 300px;
4
+ width: 300px;
5
+ background-color: white;
6
+
7
+ &>h2 {
8
+ font-size: 12px;
9
+ padding-left: 30px;
10
+ background-image: url('./images/image-editor.png');
11
+ background-size: auto 80%;
12
+ background-repeat: no-repeat;
13
+ background-position: 3px center;
14
+ border-bottom: 1px solid gray;
15
+ line-height: 30px;
16
+ height: 30px;
17
+ user-select: none;
18
+ }
19
+
20
+ &>div.right-btn {
21
+ display: flex;
22
+
23
+ &>div {
24
+ &:first-child {
25
+ flex-grow: 1;
26
+ padding: 10px 0 10px 10px;
27
+ }
28
+
29
+ &:last-child {
30
+ text-align: center;
31
+ flex-grow: 0;
32
+ flex-shrink: 0;
33
+ flex-basis: 70px;
34
+
35
+ &>button {
36
+ height: 30px;
37
+ border-radius: 15px;
38
+ width: 50px;
39
+ margin-top: 10px;
40
+
41
+ &:hover {
42
+ background-color: rgb(127, 131, 131);
43
+ cursor: pointer;
44
+ }
45
+ }
46
+
47
+ }
48
+ }
49
+ }
50
+
51
+ fieldset {
52
+ margin-top: 10px;
53
+ font-size: 12px;
54
+ }
55
+
56
+ ul {
57
+
58
+ &[lock='yes'] {
59
+ background-image: url('./images/lock.png');
60
+ background-repeat: no-repeat;
61
+ background-position: right;
62
+ }
63
+
64
+ &>li {
65
+ line-height: 2em;
66
+ margin-top: 5px;
67
+
68
+ &[active='no'] {
69
+ display: none;
70
+ }
71
+
72
+ &>label {
73
+ width: 70px;
74
+ display: inline-block;
75
+ text-align: right;
76
+ }
77
+
78
+ &>input {
79
+ width: 50px;
80
+ margin-right: 5px;
81
+ }
82
+
83
+ .change-type {
84
+ font-size: 0;
85
+ width: 90px;
86
+ display: inline-block;
87
+ line-height: 0;
88
+ vertical-align: top;
89
+ background-image: url('./images/size.png');
90
+ background-size: 100% auto;
91
+ background-repeat: no-repeat;
92
+
93
+ &>span {
94
+ display: inline-block;
95
+ width: 30px;
96
+ height: 30px;
97
+ cursor: pointer;
98
+ outline: 1px solid #dedede;
99
+ }
100
+
101
+ &[type='left-top'] {
102
+ background-position: -29px -32px;
103
+ }
104
+
105
+ &[type='center-top'] {
106
+ background-position: 1px -32px;
107
+ }
108
+
109
+ &[type='right-top'] {
110
+ background-position: 30px -32px;
111
+ }
112
+
113
+ &[type='left-middle'] {
114
+ background-position: -29px -1px;
115
+ }
116
+
117
+ &[type='center-middle'] {
118
+ background-position: 1px -1px;
119
+ }
120
+
121
+ &[type='right-middle'] {
122
+ background-position: 30px -1px;
123
+ }
124
+
125
+ &[type='left-bottom'] {
126
+ background-position: -29px 30px;
127
+ }
128
+
129
+ &[type='center-bottom'] {
130
+ background-position: 1px 30px;
131
+ }
132
+
133
+ &[type='right-bottom'] {
134
+ background-position: 30px 30px;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
@@ -1,43 +1,53 @@
1
- import { createApp } from "zipaper"
1
+ import { createApp } from "zipaper";
2
2
 
3
3
  const dialogs = {
4
+ imageSize: () => import("./imageSize/index.js")
5
+ };
4
6
 
5
- // xxx
6
- xxx: () => import("./xxx/index.js")
7
- }
8
-
9
- let dialogsResolve = []
7
+ let dialogsResolve = [];
10
8
  export default {
11
9
  install(Zipaper) {
12
10
 
13
11
  // 打开弹框
14
- Zipaper.prototype.$openDialog = function (dialogName, callback) {
15
- let el = document.createElement("div")
12
+ Zipaper.prototype.$openDialog = function (dialogName, data) {
13
+ let el = document.createElement("div");
16
14
 
17
15
  dialogs[dialogName]().then(App => {
18
16
 
19
17
  // 准备好挂载点
20
- el.setAttribute("class", "content " + dialogName)
18
+ el.setAttribute("class", "content " + dialogName);
21
19
 
22
20
  // 创建并挂载
23
- document.getElementById("dialog-root").appendChild(el)
24
- createApp(App.default).mount(el)
25
- if (callback) callback()
26
- })
21
+ document.getElementById("dialog-root").appendChild(el);
22
+
23
+ if (data) {
24
+ let props = {};
25
+ for (let key in data) {
26
+ props[key] = {
27
+ default: data[key]
28
+ };
29
+ }
30
+ App.default.props = props;
31
+ } else {
32
+ App.default.props = {};
33
+ }
34
+
35
+ createApp(App.default).mount(el);
36
+ });
27
37
 
28
38
  return new Promise((resolve) => {
29
39
  dialogsResolve.push({
30
40
  resolve,
31
41
  el
32
- })
33
- })
34
- }
42
+ });
43
+ });
44
+ };
35
45
 
36
46
  // 关闭弹框
37
47
  Zipaper.prototype.$closeDialog = function (data) {
38
- let dialog = dialogsResolve.pop()
48
+ let dialog = dialogsResolve.pop();
39
49
  dialog.el.parentNode.removeChild(dialog.el);
40
- dialog.resolve(data)
41
- }
50
+ dialog.resolve(data);
51
+ };
42
52
  }
43
53
  }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 12v-2h1v2h2v1h-2v2h-1v-2h-2v-1h2zm5 8H6V4H5v17h13v-1zm1 0v2H4V3h2V1h10l5 5v14h-2zM7 2v17h13V6l-4-4H7zm9 0l4 4h-4V2z"></path></svg>
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 4C0 1.79086 1.79086 0 4 0H20C22.2091 0 24 1.79086 24 4V20C24 22.2091 22.2091 24 20 24H4C1.79086 24 0 22.2091 0 20V4Z" fill="#FFB700"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M6.99992 8L13.9999 14.5625L16.9544 11.7927L24 17.5625V20L17.0455 14.3589L13.9999 17.2141L6.99992 10.6517L0 17.1875V14.5625L6.99992 8Z" fill="white"></path><circle cx="18" cy="6" r="3" fill="white"></circle></svg>
@@ -3,10 +3,12 @@ import { createApp } from "zipaper"
3
3
  import App from "./pages/App/index.js"
4
4
  import router from "./router.config.js"
5
5
  import dialogs from "./dialogs/index.js"
6
+ import uiSelectFile from "./components/ui-select-file/index.js"
6
7
 
7
8
  // https://oi-contrib.github.io/Zipaper/index.html
8
9
 
9
10
  createApp(App)
10
11
  .use(router) // 路由
11
12
  .use(dialogs) // 弹框
13
+ .component("ui-select-file", uiSelectFile)
12
14
  .mount(document.getElementById("root")) // 挂载到页面
@@ -15,5 +15,11 @@
15
15
  图片编辑器
16
16
  </h2>
17
17
  </li>
18
+ <li z-on:click="goto" tag="img-to-pdf">
19
+ <img src="./images/img-to-pdf.svg" />
20
+ <h2>
21
+ 图片转PDF
22
+ </h2>
23
+ </li>
18
24
  </ul>
19
25
  </div>
@@ -12,7 +12,7 @@ export default defineElement({
12
12
  },
13
13
  created() {
14
14
 
15
- var ws = new WebSocket('ws://' + window.location.hostname + ':' + (+window.location.port + 1) + '/');
15
+ let ws = new WebSocket('ws://' + window.location.hostname + ':' + (+window.location.port + 1) + '/');
16
16
 
17
17
  // 连接成功
18
18
  ws.addEventListener('open', () => {
@@ -1,19 +1,28 @@
1
1
  <div class="image-editor-view">
2
2
  <ul class="menu">
3
3
  <li>
4
- 打开
4
+ <label for="openImage">打开</label>
5
5
  </li>
6
6
  <li>
7
- 画布大小
7
+ <label z-on:click="changeSize">画布大小</label>
8
8
  </li>
9
9
  <li>
10
- 图像大小
10
+ <label z-on:click="changeSize">图像大小</label>
11
11
  </li>
12
12
  <li>
13
- 保存
13
+ <label z-on:click="download" type="jpeg">下载JPEG</label>
14
+ </li>
15
+ <li>
16
+ <label z-on:click="download" type="png">下载PNG</label>
14
17
  </li>
15
18
  </ul>
16
19
  <div class="content">
17
- <canvas style="width:700px;height:400px"></canvas>
20
+ <div id="drawId"></div>
21
+ </div>
22
+ <div class="no-view">
23
+
24
+ <!-- 选择图片 -->
25
+ <input type="file" id="openImage" z-on:change="openImage" accept="image/*" />
26
+
18
27
  </div>
19
28
  </div>
@@ -1,18 +1,105 @@
1
- import { defineElement } from "zipaper"
2
- import template from "./index.html"
3
- import style from "./index.scss"
1
+ import { defineElement } from "zipaper";
2
+ import template from "./index.html";
3
+ import style from "./index.scss";
4
+ import { Canvas } from "vislite";
4
5
 
5
6
  export default defineElement({
6
7
  template,
7
8
  data() {
8
9
  return {
9
-
10
+ painter: null,
11
+ drawEl: null
10
12
  }
11
13
  },
14
+ created() {
15
+ this.drawEl = document.getElementById("drawId");
16
+ this.painter = new Canvas(this.drawEl, {
17
+ scale: 1
18
+ }, 700, 400);
19
+ },
12
20
  methods: {
21
+ openImage(event, target) {
22
+ let file = target.files[0];
23
+ if (file) {
24
+ let reader = new FileReader();
25
+
26
+ reader.onload = () => {
27
+ let image = new Image();
28
+
29
+ image.onload = () => {
30
+
31
+ // 调整画布大小
32
+ this.painter = new Canvas(this.drawEl, {
33
+ scale: 1
34
+ }, image.width, image.height);
35
+
36
+ // 绘制图片
37
+ this.painter.clearRect(0, 0, image.width, image.height).drawImage(image, 0, 0, image.width, image.height);
38
+ }
39
+
40
+ image.src = reader.result;
41
+ }
42
+ reader.readAsDataURL(file);
43
+ }
44
+ },
45
+ download(event, target) {
46
+ let btn = document.createElement('a');
47
+ btn.href = this.painter.__canvas.toDataURL("image/" + target.getAttribute("type"));
48
+ btn.download = "图片." + target.getAttribute("type");
49
+ btn.click();
50
+ },
51
+ changeSize(event, target) {
52
+ let canvasInfo = this.painter.getInfo();
53
+ this.$openDialog("imageSize", {
54
+ title: target.innerText.trim(),
55
+ width: canvasInfo.width,
56
+ height: canvasInfo.height
57
+ }).then(data => {
58
+ if (data) {
59
+ let base64 = this.painter.__canvas.toDataURL();
13
60
 
14
-
61
+ // 调整画布大小
62
+ this.painter = new Canvas(this.drawEl, {
63
+ scale: 1
64
+ }, data.width, data.height).clearRect(0, 0, data.width, data.height);
15
65
 
66
+ if (target.innerText.trim() === "画布大小") {
67
+
68
+ // 计算图片的对齐方式
69
+
70
+ let _left, _top;
71
+ let changeType = data.changeType.split('-');
72
+
73
+ // 水平方向
74
+ if (changeType[0] == 'left') {
75
+ _left = 0;
76
+ } else if (changeType[0] == 'right') {
77
+ _left = data.width - canvasInfo.width;
78
+ } else {
79
+ _left = (data.width - canvasInfo.width) * 0.5;
80
+ }
81
+
82
+ // 垂直方向
83
+ if (changeType[1] == 'top') {
84
+ _top = 0;
85
+ } else if (changeType[1] == 'bottom') {
86
+ _top = data.height - canvasInfo.height;
87
+ } else {
88
+ _top = (data.height - canvasInfo.height) * 0.5;
89
+ }
90
+
91
+ const img = new Image();
92
+ img.onload = () => {
93
+ this.painter.getContext().drawImage(img, 0, 0, canvasInfo.width, canvasInfo.height, _left, _top, canvasInfo.width, canvasInfo.height);
94
+ };
95
+ img.src = base64;
96
+
97
+ } else {
98
+ this.painter.drawImage(base64, 0, 0, data.width, data.height);
99
+ }
100
+ }
101
+ });
102
+ }
16
103
  },
17
104
  style: {
18
105
  content: style
@@ -4,16 +4,22 @@
4
4
  left: 50%;
5
5
  top: 5px;
6
6
  transform: translateX(-50%);
7
+ white-space: nowrap;
7
8
 
8
9
  &>li {
9
10
  display: inline-block;
10
- padding: 5px 10px;
11
- cursor: pointer;
12
11
  background-color: #FF5722;
13
12
  color: white;
14
13
  margin: 0 5px;
15
14
  border-radius: 5px;
16
15
 
16
+ &>label {
17
+ line-height: 30px;
18
+ padding: 0 5px;
19
+ display: inline-block;
20
+ cursor: pointer;
21
+ }
22
+
17
23
  &:hover {
18
24
  text-decoration: underline;
19
25
  }
@@ -24,9 +30,17 @@
24
30
  text-align: center;
25
31
  margin-top: 100px;
26
32
 
27
- canvas {
28
- background-image: url("./images/mosaic.png");
29
- outline: 2px solid #CDDC39;
33
+ #drawId {
34
+ display: inline-block;
35
+
36
+ &>canvas {
37
+ background-image: url("./images/mosaic.png");
38
+ outline: 2px solid #CDDC39;
39
+ }
30
40
  }
31
41
  }
42
+
43
+ &>.no-view {
44
+ display: none;
45
+ }
32
46
  }
@@ -0,0 +1,4 @@
1
+ <div class="img-to-pdf-view">
2
+ <ui-select-file z-on:change="doChange" title="图片转PDF" tips="选择一张或多张图片后,可以把这些图片拼接成一个PDF文件" type="image"></ui-select-file>
3
+ <iframe id="iframe"></iframe>
4
+ </div>
@@ -0,0 +1,45 @@
1
+ import { defineElement, ref } from "zipaper"
2
+ import template from "./index.html"
3
+ import style from "./index.scss"
4
+
5
+ export default defineElement({
6
+ template,
7
+ methods: {
8
+ doChange(event) {
9
+ let files = event.data, promises = [], iframeEl = document.getElementById("iframe");
10
+
11
+ let template = "";
12
+ for (let index = 0; index < files.length; index++) {
13
+ let file = files[index];
14
+
15
+ promises.push(new Promise(function (resolve) {
16
+
17
+ let reader = new FileReader();
18
+
19
+ reader.onload = function () {
20
+
21
+ template += '<div style="display: flex;justify-content: center;align-items: center;height: 100vh;width: 100vw;"><img src="' + reader.result + '" style="max-width: 100vw;max-height: 100vh;"></img></div>';
22
+ resolve("");
23
+ }
24
+ reader.readAsDataURL(file);
25
+ }));
26
+ }
27
+
28
+ Promise.all(promises).then(function () {
29
+ let iframeWindow = iframeEl.contentWindow;
30
+ let iframeDocument = iframeEl.contentWindow?.document;
31
+
32
+ iframeDocument.open();
33
+ iframeDocument.write(`<style>body{margin:0px;}</style>` + template);
34
+ iframeDocument.close();
35
+
36
+ setTimeout(function () {
37
+ iframeWindow.print();
38
+ }, 500);
39
+ });
40
+ }
41
+ },
42
+ style: {
43
+ content: style
44
+ }
45
+ })
@@ -0,0 +1,5 @@
1
+ .img-to-pdf-view {
2
+ iframe {
3
+ display: none;
4
+ }
5
+ }
@@ -13,5 +13,8 @@ export default defineRouter({
13
13
  }, {
14
14
  path: "/image-editor",
15
15
  component: () => import("./pages/image-editor/index.js"),
16
+ }, {
17
+ path: "/img-to-pdf",
18
+ component: () => import("./pages/img-to-pdf/index.js"),
16
19
  }]
17
20
  })
@@ -1,7 +1,9 @@
1
1
  const OIPageZipaperIntercept = require("./oipage-zipaper-intercept.js");
2
+ const OIPageVISLiteIntercept = require("./oipage-vislite-intercept.js");
2
3
  const ChartIntercept = require("./chart.js");
3
4
 
4
5
  module.exports = [
5
6
  OIPageZipaperIntercept,
7
+ OIPageVISLiteIntercept,
6
8
  ChartIntercept
7
9
  ];
@@ -0,0 +1,34 @@
1
+ const { readFileSync } = require("fs");
2
+ const { join } = require("path");
3
+ const headFactory = require("./head.js");
4
+
5
+ const head = headFactory();
6
+
7
+ // VISLite库
8
+ module.exports = {
9
+ test: /^vislite$/,
10
+ handler(request, response) {
11
+ head["Content-Type"] = "application/javascript;charset=utf-8";
12
+ head["ETag"] = "VISLite@v" + require("vislite/package.json").version;
13
+
14
+ if (request.headers["if-none-match"] === head["ETag"]) {
15
+ response.writeHead('304', head);
16
+ response.end();
17
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Cache File: VISLite\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");;
18
+ return;
19
+ }
20
+
21
+ response.writeHead(200, head);
22
+
23
+ let source = readFileSync(join(__dirname, "../../../node_modules/vislite/lib/index.umd.min.js"), {
24
+ encoding: "utf8"
25
+ });
26
+
27
+ response.write(`let module = { exports: {} };
28
+ let exports = module.exports;
29
+ ${source}
30
+ export let Canvas = module.exports.Canvas;
31
+ `);
32
+ response.end();
33
+ }
34
+ };
@@ -14,7 +14,7 @@ module.exports = {
14
14
  if (request.headers["if-none-match"] === head["ETag"]) {
15
15
  response.writeHead('304', head);
16
16
  response.end();
17
- console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] Cache File: Zipaper\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");;
17
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-http-server] Cache File: Zipaper\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");;
18
18
  return;
19
19
  }
20
20
 
@@ -24,7 +24,7 @@ module.exports = {
24
24
  encoding: "utf8"
25
25
  });
26
26
 
27
- response.write(`let module = { exports: {}};
27
+ response.write(`let module = { exports: {} };
28
28
  let exports = module.exports;
29
29
  ${source}
30
30
  export let createApp = exports.createApp;
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * animation of OIPage v1.5.0-alpha.0
2
+ * animation of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * cmdlog of OIPage v1.5.0-alpha.0
2
+ * cmdlog of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * disk of OIPage v1.5.0-alpha.0
2
+ * disk of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * format of OIPage v1.5.0-alpha.0
2
+ * format of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -26,12 +26,12 @@ function numberFormat(input) {
26
26
  integerArray.unshift(integerValue.substring(index > 2 ? index - 3 : 0, index));
27
27
  }
28
28
 
29
- return integerArray.join(",") + decimalValue;
29
+ return integerArray.join(",").replace(/^\-,/, "-") + decimalValue;
30
30
  }
31
31
  }
32
32
 
33
33
  function dateFormat(input, option) {
34
- option = option || option;
34
+ option = option || {};
35
35
  var dateObj;
36
36
 
37
37
  // 如果无值,就用当前日期
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * json of OIPage v1.5.0-alpha.0
2
+ * json of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
  const {reader} = require("../reader/index.js");
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * logform of OIPage v1.5.0-alpha.0
2
+ * logform of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
  const {linelog} = require("../cmdlog/index.js");
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * reader of OIPage v1.5.0-alpha.0
2
+ * reader of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * throttle of OIPage v1.5.0-alpha.0
2
+ * throttle of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oipage",
3
- "version": "1.5.0-alpha.0",
3
+ "version": "1.5.0-alpha.2",
4
4
  "description": "前端网页或应用快速开发助手,包括开发服务器、辅助命令、实用API等",
5
5
  "sideEffects": false,
6
6
  "scripts": {
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "homepage": "https://oi-contrib.github.io/OIPage",
37
37
  "dependencies": {
38
- "vislite": "^1.4.0",
38
+ "vislite": "^1.5.0",
39
39
  "xhtml-to-json": "^0.1.0",
40
40
  "zipaper": "^0.2.0"
41
41
  }
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * XMLHttpRequest of OIPage v1.5.0-alpha.0
2
+ * XMLHttpRequest of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * animation of OIPage v1.5.0-alpha.0
2
+ * animation of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * format of OIPage v1.5.0-alpha.0
2
+ * format of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -26,12 +26,12 @@ export function numberFormat(input) {
26
26
  integerArray.unshift(integerValue.substring(index > 2 ? index - 3 : 0, index));
27
27
  }
28
28
 
29
- return integerArray.join(",") + decimalValue;
29
+ return integerArray.join(",").replace(/^\-,/, "-") + decimalValue;
30
30
  }
31
31
  }
32
32
 
33
33
  export function dateFormat(input, option) {
34
- option = option || option;
34
+ option = option || {};
35
35
  var dateObj;
36
36
 
37
37
  // 如果无值,就用当前日期
package/web/json/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * json of OIPage v1.5.0-alpha.0
2
+ * json of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
  import {reader} from "../reader/index.js";
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * onReady of OIPage v1.5.0-alpha.0
2
+ * onReady of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * performChunk of OIPage v1.5.0-alpha.0
2
+ * performChunk of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * reader of OIPage v1.5.0-alpha.0
2
+ * reader of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * style of OIPage v1.5.0-alpha.0
2
+ * style of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * throttle of OIPage v1.5.0-alpha.0
2
+ * throttle of OIPage v1.5.0-alpha.2
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5