This commit is contained in:
lq 2024-06-27 16:23:31 +08:00
commit 0f6644557b
87 changed files with 6974 additions and 0 deletions

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# wps
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

8
jsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

1318
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "wps",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@hufe921/canvas-editor": "^0.9.81",
"axios": "^1.7.2",
"element-plus": "^2.7.5",
"vue": "^3.4.21",
"vue-axios": "^3.5.2",
"vue-router": "^4.3.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"vite": "^5.2.8"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

1012
src/App.vue Normal file

File diff suppressed because it is too large Load Diff

2197
src/Appaaa.vue Normal file

File diff suppressed because it is too large Load Diff

86
src/assets/base.css Normal file
View File

@ -0,0 +1,86 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M2 13h12v1H2v-1zm0-3h12v1H2v-1zm0-3h12v1H2V7zm0-6h12v1H2V1zm0 3h12v1H2V4z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 209 B

View File

@ -0,0 +1 @@
<svg width="4" height="7" xmlns="http://www.w3.org/2000/svg"><path fill="#6F6F6F" d="M0 3.5L4 0v7z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 127 B

View File

@ -0,0 +1 @@
<svg width="4" height="7" xmlns="http://www.w3.org/2000/svg"><path fill="#6F6F6F" d="M4 3.5L0 0v7z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 127 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757"><path d="M8.923 11v1h-2A2 2 0 015 10.55c.328-.15.638-.335.923-.55a1 1 0 001 1h2zm0-6h-2a1 1 0 00-1 1A4.997 4.997 0 005 5.45 2 2 0 016.923 4h2v1z"/><path d="M4 10a2 2 0 100-4 2 2 0 000 4zm0 1a3 3 0 110-6 3 3 0 010 6zm6-9a1 1 0 00-1 1v3a1 1 0 001 1h3a1 1 0 001-1V3a1 1 0 00-1-1h-3zm0-1h3a2 2 0 012 2v3a2 2 0 01-2 2h-3a2 2 0 01-2-2V3a2 2 0 012-2zm0 10a1 1 0 00-1 1v1a1 1 0 001 1h3a1 1 0 001-1v-1a1 1 0 00-1-1h-3zm0-1h3a2 2 0 012 2v1a2 2 0 01-2 2h-3a2 2 0 01-2-2v-1a2 2 0 012-2z"/></g></svg>

After

Width:  |  Height:  |  Size: 568 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M8.131 6.9c2.035 0 2.569-.9 2.569-1.869 0-.968-.64-1.831-2.623-1.831H5.2v3.7h2.931zm.524 5.9c2.045 0 2.545-1.305 2.545-2.3 0-.985-.506-2.4-2.81-2.4H5.2v4.7h3.455zM4 2h4.71c2.367 0 3.19 1.583 3.19 3s-.325 1.852-1.1 2.5c1.2.5 1.569 1.379 1.6 3 .03 1.606-.586 3.5-3.769 3.5H4V2z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 411 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757"><path d="M13 0c.552 0 1 .48 1 1.071V13.93c0 .59-.448 1.07-1 1.07H3c-.552 0-1-.48-1-1.071V1.07C2 .48 2.448 0 3 0h10zm0 1H3v13h10V1z"/><path d="M5 10v1H4v-1h1zm6 0v1H6v-1h5zM5 7v1H4V7h1zm6 0v1H6V7h5zM5 4v1H4V4h1zm6 0v1H6V4h5z"/></g></svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M2 13h12v1H2v-1zm2-3h8v1H4v-1zM2 7h12v1H2V7zm0-6h12v1H2V1zm2 3h8v1H4V4z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 207 B

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:#3d4757}</style><g id="_x30_1-文字_x2F_01开始_x2F_任务列表-16px"><path id="合并形状" class="st0" d="M10.1 2H2v11h11V8.7l1-1V13c0 .6-.4 1-1 1H2c-.6 0-1-.4-1-1V2c0-.6.4-1 1-1h9.1l-1 1z"/><path id="路径" class="st0" d="M7.7 8.5l5.7-5.8.9.8-6.1 5.9-.5.5-3.9-3.4.8-.7z"/></g></svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M8.9 8.192l4.242 4.243-.707.707L8.192 8.9 3.95 13.142l-.707-.707 4.242-4.243L3.243 3.95l.707-.707 4.242 4.242 4.243-4.242.707.707L8.9 8.192z" fill="#6A6A6A" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1 @@
<svg width="14" height="14" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path stroke="#525C6F" stroke-linejoin="round" d="M4 4.5L1.5 7 4 9.5M10 4.5L12.5 7 10 9.5"></path><rect fill="#525C6F" transform="scale(1 -1) rotate(70 16.711 0)" x="2.671" y="6.53" width="8" height="1" rx=".2"></rect></g></svg>

After

Width:  |  Height:  |  Size: 326 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M7.997 3.429L6.398 8h3.2L7.997 3.429zM8.497 2L12 12h-1L9.949 9h-3.9L5 12H4L7.496 2h1z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 221 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M9.793 1.5H3a.5.5 0 00-.5.5v12a.5.5 0 00.5.5h9a.5.5 0 00.5-.5V4.207L9.793 1.5z" stroke="#3D4757"/><g fill="#3D4757"><path d="M7 7h1v5H7z"/><path d="M5 7h5v1H5z"/></g><path fill="#3D4757" fill-rule="nonzero" d="M9 2h1v3H9z"/><path fill="#3D4757" fill-rule="nonzero" d="M9 4h3v1H9z"/></g></svg>

After

Width:  |  Height:  |  Size: 399 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M7.5 14.154a5.654 5.654 0 100-11.308 5.654 5.654 0 000 11.308zm0 .846a6.5 6.5 0 110-13 6.5 6.5 0 010 13z" fill-rule="nonzero"/><path d="M8 8h4v1H7V4h1v4z"/></g></svg>

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M9 9h1v4H9z"/><path d="M9 9h4v1H9zM7 7H6V3h1z"/><path d="M7 7H3V6h4z"/></g></svg>

After

Width:  |  Height:  |  Size: 191 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M8.213 13H6.8l6.636-6.636-4.243-4.243-7.07 7.071L5.928 13H4.515L1.06 9.546a.5.5 0 010-.707L8.839 1.06a.5.5 0 01.707 0l4.95 4.95a.5.5 0 010 .707L8.213 13z" fill-rule="nonzero"/><path d="M4.536 6.364l4.95 4.95-.707.707-4.95-4.95zM4.521 13h10.03v1H5.496z"/></g></svg>

After

Width:  |  Height:  |  Size: 394 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M13.31 5h-1.92a2.203 2.203 0 00-.39-.034c-.135 0-.27.012-.402.034H10v.18c-.578.256-1 .714-1 1.214v1.928c0 .196.117.43.3.658v1.23a3.543 3.543 0 01-.3-.4V11H8V1h1v4.265C9 4.763 10 4 10.942 4c1.19 0 1.92.422 2.367 1zM2 6c-.03-.498-.175-2 2.5-2C7.11 4 7 5 7 6.902V11H5.984v-.993c.38.662-.115.993-1.484.993C2.708 11 2 9.931 2 9c0-1.428.447-2 2.5-2h1.484c0-1 .031-2-1.484-2-1.533 0-1.577.485-1.577 1H2zm2.5 2C3.601 8 3 7.768 3 9c0 1.31.438 1 1.5 1 .617 0 1.484-.665 1.484-1.847V8H4.5z"/><path d="M13.085 6.316l-2.814 3a1 1 0 101.458 1.368l2.815-3a1 1 0 00-1.459-1.368z" fill-rule="nonzero"/></g></svg>

After

Width:  |  Height:  |  Size: 725 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g transform="rotate(45 5.5 13.328)" fill="#3D4757" fill-rule="evenodd"><path d="M7 6H6V3.515a2.5 2.5 0 10-5 0V6H0V3.515a3.5 3.5 0 117 0V6zm0 4v2.5a3.5 3.5 0 01-7 0V10h1v2.5a2.5 2.5 0 105 0V10h1z" fill-rule="nonzero"/><rect x="3.062" y="5.209" width="1" height="5.5" rx=".5"/></g></svg>

After

Width:  |  Height:  |  Size: 349 B

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:#3d4757}</style><g id="_x30_0-公共_x2F_02工具栏_x2F_插入图片-16px-"><g id="Group-19" transform="translate(1 1)"><path id="Combined-Shape" class="st0" d="M1 0h12c.6 0 1 .4 1 1v11c0 .6-.4 1-1 1H1c-.6 0-1-.4-1-1V1c0-.6.4-1 1-1zm0 1v11h12V1H1z"/><circle id="椭圆形" class="st0" cx="10" cy="4" r="1"/><path id="Path" class="st0" d="M8.5 11.2l-4-4.1L1 10.7V9.2c1.7-1.6 2.7-2.5 3-2.8.4-.5.7-.4 1 0L8.5 10 11 7.3c.4-.5.6-.5 1-.1l2 2.8v1.5l-2.5-3.4-3 3.1z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 613 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.017 3L8.08 13H9v1H6v-1h1.182L9 3H8V2h3v1h-.983z" fill="#3D4757"/></svg>

After

Width:  |  Height:  |  Size: 167 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M9 13.5H2.982a.5.5 0 01-.404-.794l3.208-4.412a.5.5 0 000-.588L2.578 3.294a.5.5 0 01.404-.794H9" stroke="#3D4757"/><path d="M14.447 7l.809.588-2.139 2.942 2.139 2.942-.81.588-1.946-2.68-1.947 2.68-.809-.588 2.138-2.942-2.138-2.942.81-.588L12.5 9.679 14.447 7z" fill="#3D4757"/></g></svg>

After

Width:  |  Height:  |  Size: 393 B

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 13h12v1H2zm0-3h8v1H2zm0-3h12v1H2zm0-6h12v1H2zm0 3h8v1H2z" fill="#3d4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 195 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4 10h5v1H4zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2zm4 0h5v1h-5zm7 0h2v1h-2zm4 0h2v1h-2z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4 10h6v1H4zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3zm6 0h6v1h-6zm9 0h3v1h-3z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 294 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M5 10h4v1H5zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4zm8 0h4v1h-4z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4 10h4v1H4zm5 0h4v1H9zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h4v1h-4zm5 0h3v1h-3z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 389 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4 10h1v1H4zm12 0h1v1h-1zM6 10h1v1H6zm12 0h1v1h-1zM8 10h1v1H8zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm2 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm2 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm2 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm2 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1zm12 0h1v1h-1zm-10 0h1v1h-1z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 885 B

View File

@ -0,0 +1 @@
<svg width="126" height="20" xmlns="http://www.w3.org/2000/svg"><path d="M4 10h118v1H4z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 116 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#3D4757" d="M7 12h7v1H7zm0-5h7v1H7zm0-5h7v1H7zM3 4V2H2V1h2v3h1v1H2V4h1z"/><path d="M2 6h3v1H2V6zm0 3h3v1H2V9z" fill="#4F4F4F"/><path fill="#3D4757" fill-rule="nonzero" d="M4.5 6L5 7l-2.5 3L2 9z"/><path d="M4 14l-1-2H2v-1h3v1H4l1 2v1H2v-1h2z" fill="#3D4757"/></g></svg>

After

Width:  |  Height:  |  Size: 398 B

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:none;stroke:#3d4757}.st1{fill:#3d4757}</style><g id="_x30_1-文字_x2F_02插入_x2F_分页-16px"><path id="矩形" class="st0" d="M5.5 2.5h7c.6 0 1 .4 1 1v3c0 .6-.4 1-1 1h-7c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1z"/><path id="三角形" class="st1" d="M4 8.5L1 6v5z"/><path id="合并形状" class="st0" d="M10.8 9.5H5c-.3 0-.5.2-.5.5v4c0 .3.2.5.5.5h8c.3 0 .5-.2.5-.5v-1.8l-2.7-2.7z"/><path id="矩形_1_" class="st1" d="M10 10h1v3h-1z"/><path id="矩形-copy-2" class="st1" d="M10 12h3v1h-3z"/></g></svg>

After

Width:  |  Height:  |  Size: 635 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g transform="translate(2 1)"><rect stroke="#3D4757" x=".5" y=".5" width="11" height="8" rx="1"/><path fill="#3D4757" fill-rule="nonzero" d="M2 3h4v1H2zm0 2h8v1H2z"/></g><g fill="#3D4757" fill-rule="nonzero"><path d="M14 15h-1v-5H3v5H2V9h12v6z"/><path d="M4 12h4v1H4zm0 2h8v1H4z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 413 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M7 7V3h2v4h4v2H9v4H7V9H3V7h4z" fill="#636363" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 165 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3 7h10v2H3z" fill="#636363" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 148 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M7.5 2v2.5H4a.5.5 0 00-.5.5v2a.5.5 0 00.5.5h9a.5.5 0 00.5-.5V5a.5.5 0 00-.5-.5H9.5V2a.5.5 0 00-.5-.5H8a.5.5 0 00-.5.5z" stroke="#3D4757"/><path fill="#3D4757" d="M13 7h1v4h-1z"/><path d="M11 13a2 2 0 002-2V8.764A3 3 0 118.764 13H11z" fill="#3D4757"/><path fill="#3D4757" d="M1 13h10v1H1z"/><path d="M1 13a2 2 0 002-2V8.764A3 3 0 011 14v-1z" fill="#3D4757"/><path fill="#3D4757" d="M3 7h1v4H3z"/></g></svg>

After

Width:  |  Height:  |  Size: 532 B

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:#3d4757}</style><g id="_x30_1-文字_x2F_04页面_x2F_纸张方向-16px"><g id="编组" transform="translate(1 1)"><path id="合并形状" class="st0" d="M14 6v7c0 .6-.4 1-1 1H4c-.6 0-1-.4-1-1V6c0-.6.4-1 1-1h9c.6 0 1 .4 1 1zm-1 0H4v7h9V6z"/><path id="路径" class="st0" d="M9 4H8V1H1v9h1v1H1c-.6 0-1-.4-1-1V1c0-.6.4-1 1-1h7c.6 0 1 .4 1 1v3z"/><path id="矩形" class="st0" d="M11 7h1v5h-1z"/><path id="矩形-copy-2" class="st0" d="M2 2h5v1H2z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 599 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect stroke="#3D4757" x="2.5" y="1.5" width="11" height="13" rx="1"/><path fill="#3D4757" fill-rule="nonzero" d="M3 4h10v1H3zm0 7h10v1H3z"/><path fill="#3D4757" fill-rule="nonzero" d="M5 14V2h1v12zm5 0V2h1v12z"/></g></svg>

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g fill-rule="nonzero"><path d="M10.793 1.5L13.5 4.207V14L3 14.5 2.5 2l8.293-.5z" stroke="#3D4757"/><path fill="#3D4757" d="M10 2h1v3h-1z"/><path fill="#3D4757" d="M10 4h3v1h-3z"/></g><path d="M7 3v1H5v2H4V3h3z" fill="#3D4757"/><path fill="#3D4757" d="M5.169 3.43l6.62 8.784-.799.602-6.62-8.785z"/><path d="M9 13v-1h2v-2h1v3H9z" fill="#3D4757"/></g></svg>

After

Width:  |  Height:  |  Size: 453 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M12 4h-1V2H5v2H4V2a1 1 0 011-1h6a1 1 0 011 1v2zm0 5v4a1 1 0 01-1 1H5a1 1 0 01-1-1V9h1v4h6V9h1z"/><path d="M12 12v-1h2V5H2v6h2v1H2a1 1 0 01-1-1V5a1 1 0 011-1h12a1 1 0 011 1v6a1 1 0 01-1 1h-2z"/><path d="M3 8h10v1H3zm8-2h2v1h-2z"/></g></svg>

After

Width:  |  Height:  |  Size: 369 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3 14v-3a4 4 0 014-4h3V6H7a5 5 0 00-5 5v3h1zm7.016-11.282v7.543l4.29-3.73z" fill="#3D4757"/></svg>

After

Width:  |  Height:  |  Size: 190 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M3 3h1v4H3z"/><path d="M3 3h4v1H3zm10 10h-1V9h1z"/><path d="M13 13H9v-1h4z"/></g></svg>

After

Width:  |  Height:  |  Size: 217 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M2 13h12v1H2v-1zm4-3h8v1H6v-1zM2 7h12v1H2V7zm0-6h12v1H2V1zm4 3h8v1H6V4z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 207 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M2 14h12v1H2v-1zm7-5h5v1H9V9zm0-3h5v1H9V6zM2 1h12v1H2V1zm2.5 3L7 7H2zm0 8L7 9H2z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><circle stroke="#3D4757" cx="6" cy="6" r="4.5"/><path d="M10.061 10.968L8.707 9.414l.707-.707 1.514 1.457.435-.404 2.632 2.462a1.154 1.154 0 01.05 1.635 1.184 1.184 0 01-1.655.064l-2.788-2.527.46-.426z" fill="#3D4757" fill-rule="nonzero"/></g></svg>

After

Width:  |  Height:  |  Size: 367 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M3.9 2.8l2.01 2.506c.2.25.58.25.78 0L8.7 2.799l2.01 2.507c.2.25.58.25.78 0l2.4-2.993-.78-.626-2.01 2.507-2.01-2.507a.5.5 0 00-.78 0L6.3 4.194 4.29 1.687a.5.5 0 00-.78 0l-2.4 3 .78.625L3.9 2.8zM1 8h13v1H1zm0 4h3v1H1zm5 0h3v1H6zm5 0h3v1h-3z" fill="#3D4757"/></svg>

After

Width:  |  Height:  |  Size: 334 B

View File

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><path d="M8 6h5.5a7 7 0 010 14v-2a5 5 0 000-10H8v3L4 7l4-4v3z" fill="#3d4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 168 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#3D4757" d="M2 13h12v1H2z"/><path fill="#4B5463" fill-rule="nonzero" d="M5.26 8.458l2.23 1.28L6 12H3z"/><path d="M5.666 6.149L4.31 8.168l4.045 2.48 1.503-2.159-4.192-2.34zm1.106-4.156l-1.986 3.44 6.3 3.648 2.037-2.943-6.351-4.145z" stroke="#4B5463"/></g></svg>

After

Width:  |  Height:  |  Size: 370 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M6.215 3.29H7.64L11.855 14H10.52l-1.14-3H4.46l-1.14 3H2L6.215 3.29zM4.85 9.965h4.14L6.965 4.61h-.06L4.85 9.965z"/><path d="M12 4V2h1v2h2v1h-2v2h-1V5h-2V4h2z" fill-rule="nonzero"/></g></svg>

After

Width:  |  Height:  |  Size: 319 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path fill-rule="nonzero" d="M11 4h4v1h-4z"/><path d="M6.215 3.29H7.64L11.855 14H10.52l-1.14-3H4.46l-1.14 3H2L6.215 3.29zM4.85 9.965h4.14L6.965 4.61h-.06L4.85 9.965z"/></g></svg>

After

Width:  |  Height:  |  Size: 299 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M10.42 7.903H6.692a9.182 9.182 0 01-.41-.172 5.54 5.54 0 01-.814-.447 2.955 2.955 0 01-.655-.595 2.728 2.728 0 01-.44-.777 2.877 2.877 0 01-.162-1.006c0-.472.094-.888.282-1.25.188-.36.453-.663.793-.907s.747-.43 1.22-.558A5.97 5.97 0 018.063 2c.504 0 .95.049 1.337.147.387.097.725.23 1.013.398.287.169.53.365.73.59a3.337 3.337 0 01.772 1.486c.03.13.054.255.073.379h-1.276a2.393 2.393 0 00-.22-.615 2.315 2.315 0 00-.59-.724 2.467 2.467 0 00-.834-.44 3.376 3.376 0 00-1.005-.146 4.69 4.69 0 00-.958.097 2.77 2.77 0 00-.839.314 1.765 1.765 0 00-.597.566c-.152.233-.229.518-.229.854 0 .348.086.642.258.884.171.241.401.449.689.622.287.174.615.323.983.448s.749.247 1.142.367c.31.097.62.196.934.297a8.439 8.439 0 01.973.38zm1.376 1c.175.217.315.466.418.746.105.285.158.612.158.98 0 .554-.104 1.041-.312 1.462-.207.42-.496.772-.867 1.054-.37.282-.81.495-1.32.64A6.12 6.12 0 018.205 14c-.543 0-1.071-.09-1.586-.273a4.44 4.44 0 01-1.374-.773 3.873 3.873 0 01-.97-1.217 3.695 3.695 0 01-.395-1.612h1.27c.028.407.122.78.282 1.12a2.835 2.835 0 001.581 1.465c.363.138.76.207 1.192.207.387 0 .758-.042 1.112-.126a2.85 2.85 0 00.938-.399 2.01 2.01 0 00.647-.708c.16-.29.241-.642.241-1.054 0-.337-.087-.623-.261-.86a2.333 2.333 0 00-.69-.61 4.651 4.651 0 00-.495-.257h2.099z"/><path d="M3 7h10v1H3z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:#3d4757}</style><g id="_x30_0-公共_x2F_02工具栏_x2F_subscript"><path id="_x32_" class="st0" d="M15 13.3v.7h-3c0-.3.1-.5.3-.8.2-.2.5-.6 1-1 .4-.3.6-.5.7-.7.1-.2.2-.3.2-.5s-.1-.3-.2-.4c-.1-.1-.2-.1-.4-.1s-.3 0-.4.1-.2.4-.2.7l-.9-.1c.1-.4.2-.7.5-.9.3-.2.6-.3 1-.3s.8.1 1 .3c.3.2.4.5.4.8 0 .2 0 .4-.1.5-.1.2-.2.3-.3.5-.1.1-.3.3-.6.5s-.4.4-.5.4c-.1.1-.1.2-.2.3H15z"/><path id="合并形状" class="st0" d="M7.2 8.5l4 5.5H9.8L6.5 9.4 3.2 14H1.8l4-5.5-4-5.5h1.4l3.3 4.6L9.8 3h1.3L7.2 8.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 637 B

View File

@ -0,0 +1 @@
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 16 16" xml:space="preserve"><style>.st0{fill:#3d4757}</style><g id="_x30_0-公共_x2F_02工具栏_x2F_superscript"><path id="_x32_" class="st0" d="M15 6.3V7h-3c0-.3.1-.5.3-.8.2-.2.5-.6 1-1 .3-.2.6-.5.7-.6.1-.2.2-.3.2-.5s-.1-.3-.2-.4c-.1-.1-.2-.1-.4-.1s-.3 0-.4.1-.2.3-.2.6l-.9-.1c.1-.4.2-.7.5-.9s.6-.3 1-.3.8.1 1 .3c.3.2.4.5.4.8 0 .2 0 .4-.1.5s-.2.4-.4.5c-.1.1-.3.3-.6.5s-.4.4-.4.5c-.1.1-.1.2-.2.3l1.7-.1z"/><path id="合并形状" class="st0" d="M7.4 8.5l4 5.5H10L6.7 9.4 3.4 14H2l4-5.5L2 3h1.4l3.3 4.6L10 3h1.3L7.4 8.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 627 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect x=".5" y=".5" width="12" height="12" rx="1" transform="translate(1 1)" stroke="#3D4757"/><path fill="#3D4757" fill-rule="nonzero" d="M2 9h12v1H2zm0-4h12v1H2z"/><path fill="#3D4757" fill-rule="nonzero" d="M5 1h1v13H5zm4 0h1v13H9z"/></g></svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M14 1a1 1 0 011 1v12a1 1 0 01-1 1H2a1 1 0 01-1-1V2a1 1 0 011-1h12zm0 1H2v12h12V2z" fill-rule="nonzero"/><path fill-rule="nonzero" d="M4 11h8v1H4zm0-3h4v1H4zm0-3h2v1H4z"/><path d="M9 5h1v4H9z"/><path d="M7 5h5v1H7z"/></g></svg>

After

Width:  |  Height:  |  Size: 336 B

View File

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><g fill="#3d4757" fill-rule="evenodd"><path d="M17 3v4h4v2h-2v13H6V9H4V7h4V3h9zm0 6H8v11h9V9zm-2-4h-5v2h5V5z" fill-rule="nonzero"/><path d="M10 10h2v7h-2zm3 0h2v7h-2z"/></g></svg>

After

Width:  |  Height:  |  Size: 242 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 2v6a3 3 0 106 0V2h1v6a4 4 0 11-8 0V2h1zM4 13h8v1H4z" fill="#3D4757"/></svg>

After

Width:  |  Height:  |  Size: 170 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M6 2.763v7.544l-4.29-3.73zM13 14v-3a4 4 0 00-4-4H6V6h3a5 5 0 015 5v3h-1z" fill="#3D4757"/></svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><rect stroke="#3D4757" x="2.5" y="1.5" width="11" height="13" rx="1"/><path d="M4 7h8v1H4V7zm0-2h8v1H4V5zm0 6h8v1H4v-1zm0-2h8v1H4V9z" fill="#909AA9" fill-rule="nonzero"/><path d="M6 5.623c.36-.354.936-.638 2-.604 1.785.057 2-.008 2 1.894v4.098H8.984v-.993c1.046.662.885.993-.484.993-1.792 0-2.5-1.068-2.5-2 0-1.427.447-2 2.5-2h.484c0-1-.006-1.007-.984-1-.978.008-1.419.437-2 .437v-.825zm2.5 2.389c-.899 0-1.5-.232-1.5 1 0 1.31.438 1 1.5 1 .617 0 .484-.665.484-1.848v-.152H8.5z" fill="#3D4757"/></g></svg>

After

Width:  |  Height:  |  Size: 602 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="#3D4757" fill-rule="evenodd"><path d="M1 0h1v15H1zm5 4h7v1H6zm-3 6h7v1H3z"/><path d="M1 0h4v1H1zm10 14h4v1h-4zM3 7h10v1H3z"/><path d="M14 0h1v15h-1zM8 0l3 3V0zm6 0h-3v1h3zM8 15l-3-3v3zm-6-1h3v1H2z"/></g></svg>

After

Width:  |  Height:  |  Size: 281 B

1
src/assets/logo.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 276 B

35
src/assets/main.css Normal file
View File

@ -0,0 +1,35 @@
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}

1078
src/assets/style.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
<script setup>
defineProps({
msg: {
type: String,
required: true
}
})
</script>
<template>
<div class="">
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>

View File

@ -0,0 +1,12 @@
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
</script>
<template>
<div>aaa</div>
</template>

View File

@ -0,0 +1,87 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
position: relative;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>

View File

@ -0,0 +1,171 @@
import { EditorComponent, EDITOR_COMPONENT } from '@hufe921/canvas-editor'
import './dialog.css'
export interface IDialogData {
type: string
label?: string
name: string
value?: string
options?: { label: string; value: string }[]
placeholder?: string
width?: number
height?: number
required?: boolean
}
export interface IDialogConfirm {
name: string
value: string
}
export interface IDialogOptions {
onClose?: () => void
onCancel?: () => void
onConfirm?: (payload: IDialogConfirm[]) => void
title: string
data: IDialogData[]
}
export class Dialog {
private options: IDialogOptions
private mask: HTMLDivElement | null
private container: HTMLDivElement | null
private inputList: (
| HTMLInputElement
| HTMLTextAreaElement
| HTMLSelectElement
)[]
constructor(options: IDialogOptions) {
this.options = options
this.mask = null
this.container = null
this.inputList = []
this._render()
}
private _render() {
const { title, data, onClose, onCancel, onConfirm } = this.options
// 渲染遮罩层
const mask = document.createElement('div')
mask.classList.add('dialog-mask')
mask.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
document.body.append(mask)
// 渲染容器
const container = document.createElement('div')
container.classList.add('dialog-container')
container.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
// 弹窗
const dialogContainer = document.createElement('div')
dialogContainer.classList.add('dialog')
container.append(dialogContainer)
// 标题容器
const titleContainer = document.createElement('div')
titleContainer.classList.add('dialog-title')
// 标题&关闭按钮
const titleSpan = document.createElement('span')
titleSpan.append(document.createTextNode(title))
const titleClose = document.createElement('i')
titleClose.onclick = () => {
if (onClose) {
onClose()
}
this._dispose()
}
titleContainer.append(titleSpan)
titleContainer.append(titleClose)
dialogContainer.append(titleContainer)
// 选项容器
const optionContainer = document.createElement('div')
optionContainer.classList.add('dialog-option')
// 选项
for (let i = 0; i < data.length; i++) {
const option = data[i]
const optionItemContainer = document.createElement('div')
optionItemContainer.classList.add('dialog-option__item')
// 选项名称
if (option.label) {
const optionName = document.createElement('span')
optionName.append(document.createTextNode(option.label))
optionItemContainer.append(optionName)
if (option.required) {
optionName.classList.add('dialog-option__item--require')
}
}
// 选项输入框
let optionInput:
| HTMLInputElement
| HTMLTextAreaElement
| HTMLSelectElement
if (option.type === 'select') {
optionInput = document.createElement('select')
option.options?.forEach(item => {
const optionItem = document.createElement('option')
optionItem.value = item.value
optionItem.label = item.label
optionInput.append(optionItem)
})
} else if (option.type === 'textarea') {
optionInput = document.createElement('textarea')
} else {
optionInput = document.createElement('input')
optionInput.type = option.type
}
if (option.width) {
optionInput.style.width = `${option.width}px`
}
if (option.height) {
optionInput.style.height = `${option.height}px`
}
optionInput.name = option.name
optionInput.value = option.value || ''
if (!(optionInput instanceof HTMLSelectElement)) {
optionInput.placeholder = option.placeholder || ''
}
optionItemContainer.append(optionInput)
optionContainer.append(optionItemContainer)
this.inputList.push(optionInput)
}
dialogContainer.append(optionContainer)
// 按钮容器
const menuContainer = document.createElement('div')
menuContainer.classList.add('dialog-menu')
// 取消按钮
const cancelBtn = document.createElement('button')
cancelBtn.classList.add('dialog-menu__cancel')
cancelBtn.append(document.createTextNode('取消'))
cancelBtn.type = 'button'
cancelBtn.onclick = () => {
if (onCancel) {
onCancel()
}
this._dispose()
}
menuContainer.append(cancelBtn)
// 确认按钮
const confirmBtn = document.createElement('button')
confirmBtn.append(document.createTextNode('确定'))
confirmBtn.type = 'submit'
confirmBtn.onclick = () => {
if (onConfirm) {
const payload = this.inputList.map<IDialogConfirm>(input => ({
name: input.name,
value: input.value
}))
onConfirm(payload)
}
this._dispose()
}
menuContainer.append(confirmBtn)
dialogContainer.append(menuContainer)
// 渲染
document.body.append(container)
this.container = container
this.mask = mask
}
private _dispose() {
this.mask?.remove()
this.container?.remove()
}
}

View File

@ -0,0 +1,131 @@
.dialog-mask {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .5;
background: #000000;
z-index: 99;
}
.dialog-container {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
z-index: 999;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
.dialog {
position: absolute;
padding: 0 30px 30px;
background: #ffffff;
box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
border: 1px solid #e2e6ed;
border-radius: 2px;
}
.dialog-title {
position: relative;
border-bottom: 1px solid #e2e6ed;
margin-bottom: 30px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.dialog-title i {
width: 16px;
height: 16px;
cursor: pointer;
display: inline-block;
background: url(../../assets/images/close.svg);
}
.dialog-option__item {
margin-bottom: 18px;
display: flex;
align-items: center;
justify-content: space-between;
}
.dialog-option__item span {
margin-right: 12px;
font-size: 14px;
color: #3d4757;
position: relative;
}
.dialog-option__item input,
.dialog-option__item textarea,
.dialog-option__item select {
width: 276px;
height: 30px;
border-radius: 2px;
border: 1px solid #d3d3d3;
min-height: 30px;
padding: 5px;
box-sizing: border-box;
outline: none;
appearance: none;
user-select: none;
font-family: inherit;
}
.dialog-option__item input:focus,
.dialog-option__item textarea:focus {
border-color: #4991f2;
}
.dialog-option__item--require::before {
content: "*";
color: #f56c6c;
margin-right: 4px;
position: absolute;
left: -8px;
}
.dialog-menu {
display: flex;
align-items: center;
justify-content: flex-end;
}
.dialog-menu button {
position: relative;
display: inline-block;
border: 1px solid #e2e6ed;
border-radius: 2px;
background: #ffffff;
line-height: 22px;
padding: 0 16px;
white-space: nowrap;
cursor: pointer;
}
.dialog-menu button:hover {
background: rgba(25, 55, 88, .04);
}
.dialog-menu__cancel {
margin-right: 16px;
}
.dialog-menu button[type='submit'] {
color: #ffffff;
background: #4991f2;
border-color: #4991f2;
}
.dialog-menu button[type='submit']:hover {
background: #5b9cf3;
border-color: #5b9cf3;
}

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

View File

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

View File

@ -0,0 +1,19 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -0,0 +1,309 @@
import { EditorComponent, EDITOR_COMPONENT } from '@hufe921/canvas-editor'
import './signature.css'
export interface ISignatureResult {
value: string
width: number
height: number
}
export interface ISignatureOptions {
width?: number
height?: number
onClose?: () => void
onCancel?: () => void
onConfirm?: (payload: ISignatureResult | null) => void
}
export class Signature {
private readonly MAX_RECORD_COUNT = 1000
private readonly DEFAULT_WIDTH = 390
private readonly DEFAULT_HEIGHT = 180
private undoStack: Array<Function> = []
private x = 0
private y = 0
private isDrawing = false
private isDrawn = false
private linePoints: [number, number][] = []
private canvasWidth: number
private canvasHeight: number
private options: ISignatureOptions
private mask: HTMLDivElement
private container: HTMLDivElement
private trashContainer: HTMLDivElement
private undoContainer: HTMLDivElement
private canvas: HTMLCanvasElement
private ctx: CanvasRenderingContext2D
private preTimeStamp: number
private dpr: number
constructor(options: ISignatureOptions) {
this.options = options
this.preTimeStamp = 0
this.dpr = window.devicePixelRatio
this.canvasWidth = (options.width || this.DEFAULT_WIDTH) * this.dpr
this.canvasHeight = (options.height || this.DEFAULT_HEIGHT) * this.dpr
const { mask, container, trashContainer, undoContainer, canvas } =
this._render()
this.mask = mask
this.container = container
this.trashContainer = trashContainer
this.undoContainer = undoContainer
this.canvas = canvas
this.ctx = <CanvasRenderingContext2D>canvas.getContext('2d')
this.ctx.scale(this.dpr, this.dpr)
this.ctx.lineCap = 'round'
this._bindEvent()
this._clearUndoFn()
}
private _render() {
const { onClose, onCancel, onConfirm } = this.options
// 渲染遮罩层
const mask = document.createElement('div')
mask.classList.add('signature-mask')
mask.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
document.body.append(mask)
// 渲染容器
const container = document.createElement('div')
container.classList.add('signature-container')
container.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
// 弹窗
const signatureContainer = document.createElement('div')
signatureContainer.classList.add('signature')
container.append(signatureContainer)
// 标题容器
const titleContainer = document.createElement('div')
titleContainer.classList.add('signature-title')
// 标题&关闭按钮
const titleSpan = document.createElement('span')
titleSpan.append(document.createTextNode('插入签名'))
const titleClose = document.createElement('i')
titleClose.onclick = () => {
if (onClose) {
onClose()
}
this._dispose()
}
titleContainer.append(titleSpan)
titleContainer.append(titleClose)
signatureContainer.append(titleContainer)
// 操作区
const operationContainer = document.createElement('div')
operationContainer.classList.add('signature-operation')
// 撤销
const undoContainer = document.createElement('div')
undoContainer.classList.add('signature-operation__undo')
const undoIcon = document.createElement('i')
const undoLabel = document.createElement('span')
undoLabel.innerText = '撤销'
undoContainer.append(undoIcon)
undoContainer.append(undoLabel)
operationContainer.append(undoContainer)
// 清空画布
const trashContainer = document.createElement('div')
trashContainer.classList.add('signature-operation__trash')
const trashIcon = document.createElement('i')
const trashLabel = document.createElement('span')
trashLabel.innerText = '清空'
trashContainer.append(trashIcon)
trashContainer.append(trashLabel)
operationContainer.append(trashContainer)
signatureContainer.append(operationContainer)
// 绘图区
const canvasContainer = document.createElement('div')
canvasContainer.classList.add('signature-canvas')
const canvas = document.createElement('canvas')
canvas.width = this.canvasWidth
canvas.height = this.canvasHeight
canvas.style.width = `${this.canvasWidth / this.dpr}px`
canvas.style.height = `${this.canvasHeight / this.dpr}px`
canvasContainer.append(canvas)
signatureContainer.append(canvasContainer)
// 按钮容器
const menuContainer = document.createElement('div')
menuContainer.classList.add('signature-menu')
// 取消按钮
const cancelBtn = document.createElement('button')
cancelBtn.classList.add('signature-menu__cancel')
cancelBtn.append(document.createTextNode('取消'))
cancelBtn.type = 'button'
cancelBtn.onclick = () => {
if (onCancel) {
onCancel()
}
this._dispose()
}
menuContainer.append(cancelBtn)
// 确认按钮
const confirmBtn = document.createElement('button')
confirmBtn.append(document.createTextNode('确定'))
confirmBtn.type = 'submit'
confirmBtn.onclick = () => {
if (onConfirm) {
onConfirm(this._toData())
}
this._dispose()
}
menuContainer.append(confirmBtn)
signatureContainer.append(menuContainer)
// 渲染
document.body.append(container)
this.container = container
this.mask = mask
return {
mask,
canvas,
container,
trashContainer,
undoContainer
}
}
private _bindEvent() {
this.trashContainer.onclick = this._clearCanvas.bind(this)
this.undoContainer.onclick = this._undo.bind(this)
this.canvas.onmousedown = this._startDraw.bind(this)
this.canvas.onmousemove = this._draw.bind(this)
this.container.onmouseup = this._stopDraw.bind(this)
}
private _undo() {
if (this.undoStack.length > 1) {
this.undoStack.pop()
if (this.undoStack.length) {
this.undoStack[this.undoStack.length - 1]()
}
}
}
private _saveUndoFn(fn: Function) {
this.undoStack.push(fn)
while (this.undoStack.length > this.MAX_RECORD_COUNT) {
this.undoStack.shift()
}
}
private _clearUndoFn() {
const clearFn = () => {
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
}
this.undoStack = [clearFn]
}
private _clearCanvas() {
this._clearUndoFn()
this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
}
private _startDraw(evt: MouseEvent) {
this.isDrawing = true
this.x = evt.offsetX
this.y = evt.offsetY
this.ctx.lineWidth = 1
}
private _draw(evt: MouseEvent) {
if (!this.isDrawing) return
// 计算鼠标移动速度
const curTimestamp = performance.now()
const distance = Math.sqrt(evt.movementX ** 2 + evt.movementY ** 2)
const speed = distance / (curTimestamp - this.preTimeStamp)
// 目标线宽最小速度1最大速度5系数3
const SPEED_FACTOR = 3
const targetLineWidth = Math.min(5, Math.max(1, 5 - speed * SPEED_FACTOR))
// 平滑过渡算法20%的变化比例调整线条粗细系数0.2
const SMOOTH_FACTOR = 0.2
this.ctx.lineWidth =
this.ctx.lineWidth * (1 - SMOOTH_FACTOR) + targetLineWidth * SMOOTH_FACTOR
// 绘制
const { offsetX, offsetY } = evt
this.ctx.beginPath()
this.ctx.moveTo(this.x, this.y)
this.ctx.lineTo(offsetX, offsetY)
this.ctx.stroke()
this.x = offsetX
this.y = offsetY
this.linePoints.push([offsetX, offsetY])
this.isDrawn = true
// 缓存之前时间戳
this.preTimeStamp = curTimestamp
}
private _stopDraw() {
this.isDrawing = false
if (this.isDrawn) {
const imageData = this.ctx.getImageData(
0,
0,
this.canvasWidth,
this.canvasHeight
)
const self = this
this._saveUndoFn(function () {
self.ctx.clearRect(0, 0, self.canvasWidth, self.canvasHeight)
self.ctx.putImageData(imageData, 0, 0)
})
this.isDrawn = false
}
}
private _toData(): ISignatureResult | null {
if (!this.linePoints.length) return null
// 查找矩形四角坐标
const startX = this.linePoints[0][0]
const startY = this.linePoints[0][1]
let minX = startX
let minY = startY
let maxX = startX
let maxY = startY
for (let p = 0; p < this.linePoints.length; p++) {
const point = this.linePoints[p]
if (minX > point[0]) {
minX = point[0]
}
if (maxX < point[0]) {
maxX = point[0]
}
if (minY > point[1]) {
minY = point[1]
}
if (maxY < point[1]) {
maxY = point[1]
}
}
// 增加边框宽度
const lineWidth = this.ctx.lineWidth
minX = minX < lineWidth ? 0 : minX - lineWidth
minY = minY < lineWidth ? 0 : minY - lineWidth
maxX = maxX + lineWidth
maxY = maxY + lineWidth
const sw = maxX - minX
const sh = maxY - minY
// 裁剪图像
const imageData = this.ctx.getImageData(
minX * this.dpr,
minY * this.dpr,
sw * this.dpr,
sh * this.dpr
)
const canvas = document.createElement('canvas')
canvas.style.width = `${sw}px`
canvas.style.height = `${sh}px`
canvas.width = sw * this.dpr
canvas.height = sh * this.dpr
const ctx = <CanvasRenderingContext2D>canvas.getContext('2d')!
ctx.putImageData(imageData, 0, 0)
const value = canvas.toDataURL()
return {
value,
width: sw,
height: sh
}
}
private _dispose() {
this.mask.remove()
this.container.remove()
}
}

View File

@ -0,0 +1,128 @@
.signature-mask {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .5;
background: #000000;
z-index: 99;
}
.signature-container {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
z-index: 999;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
.signature {
position: absolute;
padding: 0 30px 30px;
background: #ffffff;
box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
border: 1px solid #e2e6ed;
border-radius: 2px;
}
.signature-title {
position: relative;
border-bottom: 1px solid #e2e6ed;
margin-bottom: 15px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.signature-title i {
width: 16px;
height: 16px;
cursor: pointer;
display: inline-block;
background: url(../../assets/images/close.svg);
}
.signature-operation>div {
cursor: pointer;
display: inline-flex;
align-items: center;
color: #3d4757;
user-select: none;
}
.signature-operation>div:hover {
color: #6e7175;
}
.signature-operation>div i {
width: 24px;
height: 24px;
display: inline-block;
}
.signature-operation__undo {
background: url(../../assets/images/signature-undo.svg) no-repeat;
}
.signature-operation__trash {
background: url(../../assets/images/trash.svg) no-repeat;
}
.signature-operation>div span {
font-size: 12px;
margin: 0 5px;
}
.signature-canvas {
margin: 15px 0;
user-select: none;
}
.signature-canvas canvas {
background: #f3f5f7;
}
.signature-menu {
display: flex;
align-items: center;
justify-content: flex-end;
}
.signature-menu button {
position: relative;
display: inline-block;
border: 1px solid #e2e6ed;
border-radius: 2px;
background: #ffffff;
line-height: 22px;
padding: 0 16px;
white-space: nowrap;
cursor: pointer;
}
.signature-menu button:hover {
background: rgba(25, 55, 88, .04);
}
.signature-menu__cancel {
margin-right: 16px;
}
.signature-menu button[type='submit'] {
color: #ffffff;
background: #4991f2;
border-color: #4991f2;
}
.signature-menu button[type='submit']:hover {
background: #5b9cf3;
border-color: #5b9cf3;
}

24
src/main.js Normal file
View File

@ -0,0 +1,24 @@
//import './assets/main.css'
import './assets/style.css'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createRouter, createWebHistory } from 'vue-router'
import { createApp } from 'vue'
import App from './App.vue'
import NewPage from './components/HelloWorld.vue'
const routes = [
{ path: '/', component: App },
{ path: '/new-page', component: NewPage }
]
const router = createRouter({
history: createWebHistory(),
routes
})
const app = createApp(App)
app.use(ElementPlus)
//app.provide('$axios',axios)
app.use(router)
app.mount('#app')
//createApp(App).use(ElementPlus,VueAxios, axios).mount('#app')

106
src/options.js Normal file
View File

@ -0,0 +1,106 @@
interface IEditorOption {
mode?: EditorMode // 编辑器模式:编辑、清洁(不显示视觉辅助元素。如:分页符)、只读、表单(仅控件内可编辑)、打印(不显示辅助元素、未书写控件及前后括号)。默认:编辑
defaultType?: string // 默认元素类型。默认TEXT
defaultColor?: string // 默认字体颜色。默认:#000000
defaultFont?: string // 默认字体。默认Microsoft YaHei
defaultSize?: number // 默认字号。默认16
minSize?: number // 最小字号。默认5
maxSize?: number // 最大字号。默认72
defaultBasicRowMarginHeight?: number // 默认行高。默认8
defaultRowMargin?: number // 默认行间距。默认1
defaultTabWidth?: number // 默认tab宽度。默认32
width?: number // 纸张宽度。默认794
height?: number // 纸张高度。默认1123
scale?: number // 缩放比例。默认1
pageGap?: number // 纸张间隔。默认20
underlineColor?: string // 下划线颜色。默认:#000000
strikeoutColor?: string // 删除线颜色。默认:#FF0000
rangeColor?: string // 选区颜色。默认:#AECBFA
rangeAlpha?: number // 选区透明度。默认0.6
rangeMinWidth?: number // 选区最小宽度。默认5
searchMatchColor?: string // 搜索高亮颜色。默认:#FFFF00
searchNavigateMatchColor?: string // 搜索导航高亮颜色。默认:#AAD280
searchMatchAlpha?: number // 搜索高亮透明度。默认0.6
highlightAlpha?: number // 高亮元素透明度。默认0.6
resizerColor?: string // 图片尺寸器颜色。默认:#4182D9
resizerSize?: number // 图片尺寸器大小。默认5
marginIndicatorSize?: number // 页边距指示器长度。默认35
marginIndicatorColor?: string // 页边距指示器颜色。默认:#BABABA
margins?: IMargin // 页面边距。默认:[100, 120, 100, 120]
pageMode?: PageMode // 纸张模式:连页、分页。默认:分页
defaultHyperlinkColor?: string // 默认超链接颜色。默认:#0000FF
table?: ITableOption // 表格配置。{tdPadding?:IPadding; defaultTrMinHeight?:number; defaultColMinWidth?:number}
header?: IHeader // 页眉信息。{top?:number; maxHeightRadio?:MaxHeightRatio;}
footer?: IFooter // 页脚信息。{bottom?:number; maxHeightRadio?:MaxHeightRatio;}
pageNumber?: IPageNumber // 页码信息。{bottom:number; size:number; font:string; color:string; rowFlex:RowFlex; format:string; numberType:NumberType;}
paperDirection?: PaperDirection // 纸张方向:纵向、横向
inactiveAlpha?: number // 正文内容失焦时透明度。默认值0.6
historyMaxRecordCount?: number // 历史撤销重做最大记录次数。默认100次
printPixelRatio?: number // 打印像素比率值越大越清晰但尺寸越大。默认3
maskMargin?: IMargin // 编辑器上的遮盖边距(如悬浮到编辑器上的菜单栏、底部工具栏)。默认:[0, 0, 0, 0]
letterClass?: string[] // 排版支持的字母类。默认a-zA-Z。内置可选择的字母表类LETTER_CLASS
contextMenuDisableKeys?: string[] // 禁用的右键菜单。默认:[]
scrollContainerSelector?: string // 滚动区域选择器。默认document
wordBreak?: WordBreak // 单词与标点断行BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认BREAK_WORD
watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;}
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
checkbox?: ICheckboxOption // 复选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
radio?: IRadioOption // 单选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
cursor?: ICursorOption // 光标样式。{width?: number; color?: string; dragWidth?: number; dragColor?: string;}
title?: ITitleOption // 标题配置。{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
placeholder?: IPlaceholder // 编辑器空白占位文本
group?: IGroup // 成组配置。{opacity?:number; backgroundColor?:string; activeOpacity?:number; activeBackgroundColor?:string; disabled?:boolean}
pageBreak?: IPageBreak // 分页符配置。{font?:string; fontSize?:number; lineDash?:number[];}
zone?: IZoneOption // 编辑器区域配置。{tipDisabled?:boolean;}
background?: IBackgroundOption // 背景配置。{color?:string; image?:string; size?:BackgroundSize; repeat?:BackgroundRepeat;}。默认:{color: '#FFFFFF'}
lineBreak?: ILineBreakOption // 换行符配置。{disabled?:boolean; color?:string; lineWidth?:number;}
separator?: ISeparatorOption // 分隔符配置。{lineWidth?:number; strokeStyle?:string;}
}
interface ITableOption {
tdPadding?: IPadding // 单元格内边距。默认:[0, 5, 5, 5]
defaultTrMinHeight?: number // 默认表格行最小高度。默认42
defaultColMinWidth?: number // 默认表格列最小宽度整体宽度足够时应用否则会按比例缩小。默认40
}
interface IHeader {
top?: number // 距离页面顶部大小。默认30
maxHeightRadio?: MaxHeightRatio // 占页面最大高度比。默认HALF
disabled?: boolean // 是否禁用
}
interface IFooter {
bottom?: number // 距离页面底部大小。默认30
maxHeightRadio?: MaxHeightRatio // 占页面最大高度比。默认HALF
disabled?: boolean // 是否禁用
}
interface IPageNumber {
bottom?: number // 距离页面底部大小。默认60
size?: number // 字体大小。默认12
font?: string // 字体。默认Microsoft YaHei
color?: string // 字体颜色。默认:#000000
rowFlex?: RowFlex // 行对齐方式。默认CENTER
format?: string // 页码格式。默认:{pageNo}。示例:第{pageNo}页/共{pageCount}页
numberType?: NumberType // 数字类型。默认ARABIC
disabled?: boolean // 是否禁用
startPageNo?: number // 起始页码。默认1
fromPageNo?: number // 从第几页开始出现页码。默认0
maxPageNo?: number | null // 最大页码从0开始。默认null
}
interface IWatermark {
data: string // 文本。
color?: string // 颜色。默认:#AEB5C0
opacity?: number // 透明度。默认0.3
size?: number // 字体大小。默认200
font?: string // 字体。默认Microsoft YaHei
}
interface IPlaceholder {
data: string // 文本。
color?: string // 颜色。默认:#DCDFE6
opacity?: number // 透明度。默认1
size?: number // 字体大小。默认16
font?: string // 字体。默认Microsoft YaHei
}

30
vite.config.js Normal file
View File

@ -0,0 +1,30 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
// 在此处编写代理规则
'/api': {
secure: false,
//target: 'https://192.168.3.198',
target: 'https://c.apxly.com',
changeOrigin: true,
rewrite: (path) => {
return path.replace(/\/api/, '')
}
}
}
}
})

0
vue.config.js Normal file
View File