mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
update
This commit is contained in:
parent
fdbb6dde16
commit
5f20da11b3
348
package-lock.json
generated
348
package-lock.json
generated
@ -2258,6 +2258,122 @@
|
|||||||
"tslint": "^5.20.1",
|
"tslint": "^5.20.1",
|
||||||
"webpack": "^4.0.0",
|
"webpack": "^4.0.0",
|
||||||
"yorkie": "^2.0.0"
|
"yorkie": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1606792369066&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz?cache=0&sync_timestamp=1591687000046&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz?cache=0&sync_timestamp=1566248870121&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolor-convert%2Fdownload%2Fcolor-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"fork-ts-checker-webpack-plugin-v5": {
|
||||||
|
"version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz",
|
||||||
|
"integrity": "sha1-eTJthpeXkG+osk4qvPlCH8gFRQ0=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.8.3",
|
||||||
|
"@types/json-schema": "^7.0.5",
|
||||||
|
"chalk": "^4.1.0",
|
||||||
|
"cosmiconfig": "^6.0.0",
|
||||||
|
"deepmerge": "^4.2.2",
|
||||||
|
"fs-extra": "^9.0.0",
|
||||||
|
"memfs": "^3.1.2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"schema-utils": "2.7.0",
|
||||||
|
"semver": "^7.3.2",
|
||||||
|
"tapable": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz?cache=0&sync_timestamp=1594427484405&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flru-cache%2Fdownload%2Flru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schema-utils": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.0.tgz",
|
||||||
|
"integrity": "sha1-FxUfdtjq5n+793lgwzxnatn078c=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/json-schema": "^7.0.4",
|
||||||
|
"ajv": "^6.12.2",
|
||||||
|
"ajv-keywords": "^3.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "7.3.4",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.4.tgz?cache=0&sync_timestamp=1606852064928&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.4.tgz",
|
||||||
|
"integrity": "sha1-J6qn0uTKdkUvmNOt0JOnLJQ+3Jc=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"lru-cache": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1608033330722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/cli-plugin-unit-jest": {
|
"@vue/cli-plugin-unit-jest": {
|
||||||
@ -2421,6 +2537,17 @@
|
|||||||
"unique-filename": "^1.1.1"
|
"unique-filename": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz?cache=0&sync_timestamp=1591687000046&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cliui": {
|
"cliui": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-6.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-6.0.0.tgz",
|
||||||
@ -2483,6 +2610,18 @@
|
|||||||
"graceful-fs": "^4.1.6"
|
"graceful-fs": "^4.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"loader-utils": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
|
||||||
@ -2531,6 +2670,18 @@
|
|||||||
"integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=",
|
"integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vue-loader-v16": {
|
||||||
|
"version": "npm:vue-loader@16.1.2",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.1.2.tgz?cache=0&sync_timestamp=1608187974157&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-16.1.2.tgz",
|
||||||
|
"integrity": "sha1-XAO2xQ0qX5g8fOuhXFDXjKKymPQ=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^4.1.0",
|
||||||
|
"hash-sum": "^2.0.0",
|
||||||
|
"loader-utils": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wrap-ansi": {
|
"wrap-ansi": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz",
|
||||||
@ -7322,122 +7473,6 @@
|
|||||||
"worker-rpc": "^0.1.0"
|
"worker-rpc": "^0.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fork-ts-checker-webpack-plugin-v5": {
|
|
||||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz",
|
|
||||||
"integrity": "sha1-eTJthpeXkG+osk4qvPlCH8gFRQ0=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/code-frame": "^7.8.3",
|
|
||||||
"@types/json-schema": "^7.0.5",
|
|
||||||
"chalk": "^4.1.0",
|
|
||||||
"cosmiconfig": "^6.0.0",
|
|
||||||
"deepmerge": "^4.2.2",
|
|
||||||
"fs-extra": "^9.0.0",
|
|
||||||
"memfs": "^3.1.2",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"schema-utils": "2.7.0",
|
|
||||||
"semver": "^7.3.2",
|
|
||||||
"tapable": "^1.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1606792302448&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz",
|
|
||||||
"integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^4.1.0",
|
|
||||||
"supports-color": "^7.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"has-flag": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1596294337050&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
|
|
||||||
"integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"schema-utils": {
|
|
||||||
"version": "2.7.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.0.tgz",
|
|
||||||
"integrity": "sha1-FxUfdtjq5n+793lgwzxnatn078c=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"@types/json-schema": "^7.0.4",
|
|
||||||
"ajv": "^6.12.2",
|
|
||||||
"ajv-keywords": "^3.4.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"semver": {
|
|
||||||
"version": "7.3.4",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.4.tgz?cache=0&sync_timestamp=1606852122426&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.4.tgz",
|
|
||||||
"integrity": "sha1-J6qn0uTKdkUvmNOt0JOnLJQ+3Jc=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz",
|
|
||||||
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz",
|
||||||
@ -15883,87 +15918,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-loader-v16": {
|
|
||||||
"version": "npm:vue-loader@16.1.2",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.1.2.tgz?cache=0&sync_timestamp=1608187974157&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-16.1.2.tgz",
|
|
||||||
"integrity": "sha1-XAO2xQ0qX5g8fOuhXFDXjKKymPQ=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"chalk": "^4.1.0",
|
|
||||||
"hash-sum": "^2.0.0",
|
|
||||||
"loader-utils": "^2.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1606792302448&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz",
|
|
||||||
"integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^4.1.0",
|
|
||||||
"supports-color": "^7.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"has-flag": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1596294337050&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz",
|
|
||||||
"integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"loader-utils": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"big.js": "^5.2.2",
|
|
||||||
"emojis-list": "^3.0.0",
|
|
||||||
"json5": "^2.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz",
|
|
||||||
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
|
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^4.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vue-router": {
|
"vue-router": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-4.0.1.tgz?cache=0&sync_timestamp=1607347245114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-4.0.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-4.0.1.tgz?cache=0&sync_timestamp=1607347245114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-4.0.1.tgz",
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'
|
import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'
|
||||||
import { getElementListRange } from '../utils/elementRange'
|
import { getElementListRange } from '@/utils/element'
|
||||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const alignElementToCanvas = (command: ElementAlignCommand) => {
|
const alignElementToCanvas = (command: ElementAlignCommand) => {
|
||||||
const viewportWidth = VIEWPORT_SIZE
|
const viewportWidth = VIEWPORT_SIZE
|
||||||
const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO
|
const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO
|
||||||
const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)
|
const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)
|
||||||
|
|
||||||
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
|
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
for(const element of newElementList) {
|
for(const element of newElementList) {
|
||||||
if(!activeElementIdList.value.includes(element.elId)) continue
|
if(!activeElementIdList.value.includes(element.elId)) continue
|
||||||
|
|
@ -1,19 +1,20 @@
|
|||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { createRandomCode } from '@/utils/common'
|
import { createRandomCode } from '@/utils/common'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
// 组合元素(为当前所有激活元素添加一个相同的groupId)
|
// 组合元素(为当前所有激活元素添加一个相同的groupId)
|
||||||
const combineElements = () => {
|
const combineElements = () => {
|
||||||
if(!activeElementList.value.length) return
|
if(!activeElementList.value.length) return
|
||||||
|
|
||||||
let newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))
|
let newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
const groupId = createRandomCode()
|
const groupId = createRandomCode()
|
||||||
|
|
||||||
const combineElementList: PPTElement[] = []
|
const combineElementList: PPTElement[] = []
|
||||||
@ -41,7 +42,7 @@ export default (elementList: Ref<PPTElement[]>) => {
|
|||||||
const hasElementInGroup = activeElementList.value.some(item => item.groupId)
|
const hasElementInGroup = activeElementList.value.some(item => item.groupId)
|
||||||
if(!hasElementInGroup) return
|
if(!hasElementInGroup) return
|
||||||
|
|
||||||
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList))
|
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
for(const element of newElementList) {
|
for(const element of newElementList) {
|
||||||
if(activeElementIdList.value.includes(element.elId) && element.groupId) delete element.groupId
|
if(activeElementIdList.value.includes(element.elId) && element.groupId) delete element.groupId
|
||||||
}
|
}
|
@ -6,13 +6,15 @@ import { copyText, readClipboard } from '@/utils/clipboard'
|
|||||||
import { encrypt } from '@/utils/crypto'
|
import { encrypt } from '@/utils/crypto'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
|
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
|
||||||
|
import useDeleteElement from './useDeleteElement'
|
||||||
|
|
||||||
export default (deleteElement: () => void) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
||||||
|
|
||||||
const { pasteTextClipboardData } = usePasteTextClipboardData()
|
const { pasteTextClipboardData } = usePasteTextClipboardData()
|
||||||
|
const { deleteElement } = useDeleteElement()
|
||||||
|
|
||||||
const copyElement = () => {
|
const copyElement = () => {
|
||||||
if(!activeElementIdList.value.length) return
|
if(!activeElementIdList.value.length) return
|
||||||
@ -24,7 +26,6 @@ export default (deleteElement: () => void) => {
|
|||||||
|
|
||||||
copyText(text).then(() => {
|
copyText(text).then(() => {
|
||||||
store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
|
store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
|
||||||
message.success('元素已复制到剪贴板', 0.8)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,22 @@
|
|||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { Slide } from '@/types/slides'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const deleteElement = () => {
|
const deleteElement = () => {
|
||||||
if(!activeElementIdList.value.length) return
|
if(!activeElementIdList.value.length) return
|
||||||
const newElementList = elementList.value.filter(el => !activeElementIdList.value.includes(el.elId))
|
const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.elId))
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteAllElements = () => {
|
const deleteAllElements = () => {
|
||||||
if(!elementList.value.length) return
|
if(!currentSlide.value.elements.length) return
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })
|
||||||
}
|
}
|
@ -1,23 +1,24 @@
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const lockElement = (handleElement: PPTElement) => {
|
const lockElement = () => {
|
||||||
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
|
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
|
|
||||||
for(const element of newElementList) {
|
for(const element of newElementList) {
|
||||||
if(activeElementIdList.value.includes(handleElement.elId)) element.isLock = true
|
if(activeElementIdList.value.includes(element.elId)) element.isLock = true
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlockElement = (handleElement: PPTElement) => {
|
const unlockElement = (handleElement: PPTElement) => {
|
||||||
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
|
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
|
|
||||||
if(handleElement.groupId) {
|
if(handleElement.groupId) {
|
||||||
for(const element of newElementList) {
|
for(const element of newElementList) {
|
@ -1,15 +1,16 @@
|
|||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { Slide } from '@/types/slides'
|
||||||
import { KEYS } from '@/configs/hotkey'
|
import { KEYS } from '@/configs/hotkey'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const moveElement = (command: string) => {
|
const moveElement = (command: string) => {
|
||||||
const newElementList = elementList.value.map(el => {
|
const newElementList = currentSlide.value.elements.map(el => {
|
||||||
if(activeElementIdList.value.includes(el.elId)) {
|
if(activeElementIdList.value.includes(el.elId)) {
|
||||||
let { left, top } = el
|
let { left, top } = el
|
||||||
switch(command) {
|
switch(command) {
|
@ -1,11 +1,12 @@
|
|||||||
|
import { Ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { Ref } from 'vue'
|
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
|
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>) => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
// 获取组合元素层级范围(组合成员中的最大层级和最小层级)
|
// 获取组合元素层级范围(组合成员中的最大层级和最小层级)
|
||||||
const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {
|
const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {
|
||||||
@ -167,10 +168,10 @@ export default (elementList: Ref<PPTElement[]>) => {
|
|||||||
const orderElement = (element: PPTElement, command: ElementOrderCommand) => {
|
const orderElement = (element: PPTElement, command: ElementOrderCommand) => {
|
||||||
let newElementList = null
|
let newElementList = null
|
||||||
|
|
||||||
if(command === ElementOrderCommands.UP) newElementList = moveUpElement(elementList.value, element)
|
if(command === ElementOrderCommands.UP) newElementList = moveUpElement(currentSlide.value.elements, element)
|
||||||
else if(command === ElementOrderCommands.DOWN) newElementList = moveDownElement(elementList.value, element)
|
else if(command === ElementOrderCommands.DOWN) newElementList = moveDownElement(currentSlide.value.elements, element)
|
||||||
else if(command === ElementOrderCommands.TOP) newElementList = moveTopElement(elementList.value, element)
|
else if(command === ElementOrderCommands.TOP) newElementList = moveTopElement(currentSlide.value.elements, element)
|
||||||
else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(elementList.value, element)
|
else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
}
|
}
|
@ -5,6 +5,11 @@ import { decrypt } from '@/utils/crypto'
|
|||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { createRandomCode } from '@/utils/common'
|
import { createRandomCode } from '@/utils/common'
|
||||||
|
|
||||||
|
interface PasteTextClipboardDataOptions {
|
||||||
|
onlySlide?: boolean;
|
||||||
|
onlyElements?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
@ -37,15 +42,18 @@ export default () => {
|
|||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
const pasteSlide = (slides: Slide[]) => {
|
const pasteSlide = (slide: Slide) => {
|
||||||
console.log(slides)
|
store.commit(MutationTypes.ADD_SLIDE, slide)
|
||||||
}
|
}
|
||||||
|
|
||||||
const pasteText = (text: string) => {
|
const pasteText = (text: string) => {
|
||||||
console.log(text)
|
console.log(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
const pasteTextClipboardData = (text: string) => {
|
const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {
|
||||||
|
const onlySlide = options?.onlySlide || false
|
||||||
|
const onlyElements = options?.onlyElements || false
|
||||||
|
|
||||||
let clipboardData
|
let clipboardData
|
||||||
try {
|
try {
|
||||||
clipboardData = JSON.parse(decrypt(text))
|
clipboardData = JSON.parse(decrypt(text))
|
||||||
@ -58,12 +66,12 @@ export default () => {
|
|||||||
if(typeof clipboardData === 'object') {
|
if(typeof clipboardData === 'object') {
|
||||||
const { type, data } = clipboardData
|
const { type, data } = clipboardData
|
||||||
|
|
||||||
if(type === 'elements') pasteElement(data)
|
if(type === 'elements' && !onlySlide) pasteElement(data)
|
||||||
else if(type === 'slide') pasteSlide(data)
|
else if(type === 'slide' && !onlyElements) pasteSlide(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 粘贴普通文本
|
// 粘贴普通文本
|
||||||
else pasteText(clipboardData)
|
else if(!onlyElements && !onlySlide) pasteText(clipboardData)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
19
src/hooks/useSelectAllElement.ts
Normal file
19
src/hooks/useSelectAllElement.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Ref, computed } from 'vue'
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import { State, MutationTypes } from '@/store'
|
||||||
|
import { Slide } from '@/types/slides'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const store = useStore<State>()
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const selectAllElement = () => {
|
||||||
|
const unlockedElements = currentSlide.value.elements.filter(el => !el.isLock)
|
||||||
|
const newActiveElementIdList = unlockedElements.map(el => el.elId)
|
||||||
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectAllElement,
|
||||||
|
}
|
||||||
|
}
|
78
src/hooks/useSlideHandler.ts
Normal file
78
src/hooks/useSlideHandler.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { Ref, computed } from 'vue'
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import { State, MutationTypes } from '@/store'
|
||||||
|
import { Slide } from '@/types/slides'
|
||||||
|
import { createRandomCode } from '@/utils/common'
|
||||||
|
import { copyText, readClipboard } from '@/utils/clipboard'
|
||||||
|
import { encrypt } from '@/utils/crypto'
|
||||||
|
import { KEYS } from '@/configs/hotkey'
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const store = useStore<State>()
|
||||||
|
const slideIndex = computed(() => store.state.slideIndex)
|
||||||
|
const slidesLength = computed(() => store.state.slides.length)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { pasteTextClipboardData } = usePasteTextClipboardData()
|
||||||
|
|
||||||
|
const updateSlideIndex = (command: string) => {
|
||||||
|
let targetIndex = 0
|
||||||
|
if(command === KEYS.UP && slideIndex.value > 0) {
|
||||||
|
targetIndex = slideIndex.value - 1
|
||||||
|
}
|
||||||
|
else if(command === KEYS.DOWN && slideIndex.value < slidesLength.value - 1) {
|
||||||
|
targetIndex = slideIndex.value + 1
|
||||||
|
}
|
||||||
|
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
const copySlide = () => {
|
||||||
|
const text = encrypt(JSON.stringify({
|
||||||
|
type: 'slide',
|
||||||
|
data: currentSlide.value,
|
||||||
|
}))
|
||||||
|
|
||||||
|
copyText(text).then(() => {
|
||||||
|
store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const pasteSlide = () => {
|
||||||
|
readClipboard().then(text => {
|
||||||
|
pasteTextClipboardData(text, { onlySlide: true })
|
||||||
|
}).catch(err => message.warning(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
const createSlide = () => {
|
||||||
|
const emptySlide = {
|
||||||
|
id: createRandomCode(8),
|
||||||
|
elements: [],
|
||||||
|
}
|
||||||
|
store.commit(MutationTypes.ADD_SLIDE, emptySlide)
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyAndPasteSlide = () => {
|
||||||
|
store.commit(MutationTypes.ADD_SLIDE, currentSlide.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteSlide = () => {
|
||||||
|
store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cutSlide = () => {
|
||||||
|
copySlide()
|
||||||
|
deleteSlide()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
updateSlideIndex,
|
||||||
|
copySlide,
|
||||||
|
pasteSlide,
|
||||||
|
createSlide,
|
||||||
|
copyAndPasteSlide,
|
||||||
|
deleteSlide,
|
||||||
|
cutSlide,
|
||||||
|
}
|
||||||
|
}
|
@ -29,7 +29,7 @@ export interface State {
|
|||||||
const state: State = {
|
const state: State = {
|
||||||
activeElementIdList: [],
|
activeElementIdList: [],
|
||||||
handleElementId: '',
|
handleElementId: '',
|
||||||
editorAreaShowScale: 85,
|
editorAreaShowScale: 90,
|
||||||
thumbnailsFocus: false,
|
thumbnailsFocus: false,
|
||||||
editorAreaFocus: false,
|
editorAreaFocus: false,
|
||||||
disableHotkeys: false,
|
disableHotkeys: false,
|
||||||
|
@ -56,11 +56,9 @@ export const mutations: MutationTree<State> = {
|
|||||||
state.slides = slides
|
state.slides = slides
|
||||||
},
|
},
|
||||||
|
|
||||||
[MutationTypes.ADD_SLIDE](state, data: AddSlideData) {
|
[MutationTypes.ADD_SLIDE](state, slide: Slide) {
|
||||||
const { index, slide } = data
|
const addIndex = state.slideIndex + 1
|
||||||
const slides = Array.isArray(slide) ? slide : [slide]
|
state.slides.splice(addIndex, 0, slide)
|
||||||
const addIndex = index !== undefined ? index : (state.slideIndex + 1)
|
|
||||||
state.slides.splice(addIndex, 0, ...slides)
|
|
||||||
state.slideIndex = addIndex
|
state.slideIndex = addIndex
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -52,4 +52,22 @@ export enum OPERATE_KEYS {
|
|||||||
LEFT_BOTTOM = 6,
|
LEFT_BOTTOM = 6,
|
||||||
BOTTOM = 7,
|
BOTTOM = 7,
|
||||||
RIGHT_BOTTOM = 8,
|
RIGHT_BOTTOM = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlignmentLineAxis {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlignmentLineProps {
|
||||||
|
type: 'vertical' | 'horizontal';
|
||||||
|
axis: AlignmentLineAxis;
|
||||||
|
length: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MultiSelectRange {
|
||||||
|
minX: number;
|
||||||
|
maxX: number;
|
||||||
|
minY: number;
|
||||||
|
maxY: number;
|
||||||
}
|
}
|
@ -1,93 +1,116 @@
|
|||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement } from '@/types/slides'
|
||||||
|
|
||||||
// 获取矩形旋转后在画布中的位置范围
|
// 获取矩形旋转后在画布中的位置范围
|
||||||
interface RotatedElementData {
|
interface RotatedElementData {
|
||||||
left: number;
|
left: number;
|
||||||
top: number;
|
top: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
rotate: number;
|
rotate: number;
|
||||||
}
|
}
|
||||||
export const getRectRotatedRange = (element: RotatedElementData) => {
|
export const getRectRotatedRange = (element: RotatedElementData) => {
|
||||||
const { left, top, width, height, rotate = 0 } = element
|
const { left, top, width, height, rotate = 0 } = element
|
||||||
|
|
||||||
const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2
|
const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2
|
||||||
const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI
|
const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI
|
||||||
|
|
||||||
const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180
|
const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180
|
||||||
const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180
|
const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180
|
||||||
|
|
||||||
const halfWidth = width / 2
|
const halfWidth = width / 2
|
||||||
const halfHeight = height / 2
|
const halfHeight = height / 2
|
||||||
|
|
||||||
const middleLeft = left + halfWidth
|
const middleLeft = left + halfWidth
|
||||||
const middleTop = top + halfHeight
|
const middleTop = top + halfHeight
|
||||||
|
|
||||||
const xAxis = [
|
const xAxis = [
|
||||||
middleLeft + radius * Math.cos(tlbraRadian),
|
middleLeft + radius * Math.cos(tlbraRadian),
|
||||||
middleLeft + radius * Math.cos(trblaRadian),
|
middleLeft + radius * Math.cos(trblaRadian),
|
||||||
middleLeft - radius * Math.cos(tlbraRadian),
|
middleLeft - radius * Math.cos(tlbraRadian),
|
||||||
middleLeft - radius * Math.cos(trblaRadian),
|
middleLeft - radius * Math.cos(trblaRadian),
|
||||||
]
|
]
|
||||||
const yAxis = [
|
const yAxis = [
|
||||||
middleTop - radius * Math.sin(tlbraRadian),
|
middleTop - radius * Math.sin(tlbraRadian),
|
||||||
middleTop - radius * Math.sin(trblaRadian),
|
middleTop - radius * Math.sin(trblaRadian),
|
||||||
middleTop + radius * Math.sin(tlbraRadian),
|
middleTop + radius * Math.sin(tlbraRadian),
|
||||||
middleTop + radius * Math.sin(trblaRadian),
|
middleTop + radius * Math.sin(trblaRadian),
|
||||||
]
|
]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
xRange: [Math.min(...xAxis), Math.max(...xAxis)],
|
xRange: [Math.min(...xAxis), Math.max(...xAxis)],
|
||||||
yRange: [Math.min(...yAxis), Math.max(...yAxis)],
|
yRange: [Math.min(...yAxis), Math.max(...yAxis)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取元素在画布中的位置范围
|
// 获取元素在画布中的位置范围
|
||||||
export const getElementRange = (element: PPTElement) => {
|
export const getElementRange = (element: PPTElement) => {
|
||||||
let minX, maxX, minY, maxY
|
let minX, maxX, minY, maxY
|
||||||
|
|
||||||
if(element.type === 'line') {
|
if(element.type === 'line') {
|
||||||
minX = element.left
|
minX = element.left
|
||||||
maxX = element.left + Math.max(element.start[0], element.end[0])
|
maxX = element.left + Math.max(element.start[0], element.end[0])
|
||||||
minY = element.top
|
minY = element.top
|
||||||
maxY = element.top + Math.max(element.start[1], element.end[1])
|
maxY = element.top + Math.max(element.start[1], element.end[1])
|
||||||
}
|
}
|
||||||
else if('rotate' in element && element.rotate) {
|
else if('rotate' in element && element.rotate) {
|
||||||
const { left, top, width, height, rotate } = element
|
const { left, top, width, height, rotate } = element
|
||||||
const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })
|
const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })
|
||||||
minX = xRange[0]
|
minX = xRange[0]
|
||||||
maxX = xRange[1]
|
maxX = xRange[1]
|
||||||
minY = yRange[0]
|
minY = yRange[0]
|
||||||
maxY = yRange[1]
|
maxY = yRange[1]
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
minX = element.left
|
minX = element.left
|
||||||
maxX = element.left + element.width
|
maxX = element.left + element.width
|
||||||
minY = element.top
|
minY = element.top
|
||||||
maxY = element.top + element.height
|
maxY = element.top + element.height
|
||||||
}
|
}
|
||||||
return { minX, maxX, minY, maxY }
|
return { minX, maxX, minY, maxY }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取元素集合在画布中的位置范围
|
// 获取元素集合在画布中的位置范围
|
||||||
export const getElementListRange = (elementList: PPTElement[]) => {
|
export const getElementListRange = (elementList: PPTElement[]) => {
|
||||||
const leftValues: number[] = []
|
const leftValues: number[] = []
|
||||||
const topValues: number[] = []
|
const topValues: number[] = []
|
||||||
const rightValues: number[] = []
|
const rightValues: number[] = []
|
||||||
const bottomValues: number[] = []
|
const bottomValues: number[] = []
|
||||||
|
|
||||||
elementList.forEach(element => {
|
elementList.forEach(element => {
|
||||||
const { minX, maxX, minY, maxY } = getElementRange(element)
|
const { minX, maxX, minY, maxY } = getElementRange(element)
|
||||||
leftValues.push(minX)
|
leftValues.push(minX)
|
||||||
topValues.push(minY)
|
topValues.push(minY)
|
||||||
rightValues.push(maxX)
|
rightValues.push(maxX)
|
||||||
bottomValues.push(maxY)
|
bottomValues.push(maxY)
|
||||||
})
|
})
|
||||||
|
|
||||||
const minX = Math.min(...leftValues)
|
const minX = Math.min(...leftValues)
|
||||||
const maxX = Math.max(...rightValues)
|
const maxX = Math.max(...rightValues)
|
||||||
const minY = Math.min(...topValues)
|
const minY = Math.min(...topValues)
|
||||||
const maxY = Math.max(...bottomValues)
|
const maxY = Math.max(...bottomValues)
|
||||||
|
|
||||||
return { minX, maxX, minY, maxY }
|
return { minX, maxX, minY, maxY }
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlignLine {
|
||||||
|
value: number;
|
||||||
|
range: [number, number];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条
|
||||||
|
export const uniqAlignLines = (lines: AlignLine[]) => {
|
||||||
|
const uniqLines: AlignLine[] = []
|
||||||
|
lines.forEach(line => {
|
||||||
|
const index = uniqLines.findIndex(_line => _line.value === line.value)
|
||||||
|
if(index === -1) uniqLines.push(line)
|
||||||
|
else {
|
||||||
|
const uniqLine = uniqLines[index]
|
||||||
|
const rangeMin = Math.min(uniqLine.range[0], line.range[0])
|
||||||
|
const rangeMax = Math.max(uniqLine.range[1], line.range[1])
|
||||||
|
const range: [number, number] = [rangeMin, rangeMax]
|
||||||
|
const _line = { value: line.value, range }
|
||||||
|
uniqLines[index] = _line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return uniqLines
|
||||||
}
|
}
|
@ -1,5 +1,9 @@
|
|||||||
import mitt, { Emitter } from 'mitt'
|
import mitt, { Emitter } from 'mitt'
|
||||||
|
|
||||||
|
export enum EMITTER_EVENTS {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const emitter: Emitter = mitt()
|
const emitter: Emitter = mitt()
|
||||||
|
|
||||||
export default emitter
|
export default emitter
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PropType } from 'vue'
|
import { PropType } from 'vue'
|
||||||
import { AlignmentLineAxis } from './types/index'
|
import { AlignmentLineAxis } from '@/types/edit'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'alignment-line',
|
name: 'alignment-line',
|
||||||
|
@ -26,14 +26,12 @@ import { computed, defineComponent, reactive, PropType, watchEffect, toRefs } fr
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State } from '@/store'
|
import { State } from '@/store'
|
||||||
import { PPTElement, ElementTypes } from '@/types/slides'
|
import { PPTElement, ElementTypes } from '@/types/slides'
|
||||||
import { getElementListRange } from './utils/elementRange'
|
import { getElementListRange } from '@/utils/element'
|
||||||
import { ElementScaleHandler, OperateResizablePointTypes, OperateBorderLineTypes, OPERATE_KEYS } from '@/types/edit'
|
import { ElementScaleHandler, OperateResizablePointTypes, OperateBorderLineTypes, MultiSelectRange, OPERATE_KEYS } from '@/types/edit'
|
||||||
|
|
||||||
import ResizablePoint from '@/views/_common/_operate/ResizablePoint.vue'
|
import ResizablePoint from '@/views/_common/_operate/ResizablePoint.vue'
|
||||||
import BorderLine from '@/views/_common/_operate/BorderLine.vue'
|
import BorderLine from '@/views/_common/_operate/BorderLine.vue'
|
||||||
|
|
||||||
import { MultiSelectRange } from './types/index'
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'multi-select-operate',
|
name: 'multi-select-operate',
|
||||||
components: {
|
components: {
|
||||||
|
@ -2,10 +2,9 @@ import { Ref, computed } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { ElementTypes, PPTElement } from '@/types/slides'
|
import { ElementTypes, PPTElement } from '@/types/slides'
|
||||||
import { AlignmentLineProps } from '../types/index'
|
import { AlignmentLineProps } from '@/types/edit'
|
||||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
import { getRectRotatedRange } from '../utils/elementRange'
|
import { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'
|
||||||
import { AlignLine, uniqAlignLines } from '../utils/alignLines'
|
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
elementList: Ref<PPTElement[]>,
|
elementList: Ref<PPTElement[]>,
|
||||||
|
@ -2,7 +2,7 @@ import { Ref, reactive } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement } from '@/types/slides'
|
import { PPTElement } from '@/types/slides'
|
||||||
import { getElementRange } from '../utils/elementRange'
|
import { getElementRange } from '@/utils/element'
|
||||||
|
|
||||||
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>, canvasScale: Ref<number>) => {
|
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>, canvasScale: Ref<number>) => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
@ -2,10 +2,9 @@ import { computed, Ref } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { ElementTypes, PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'
|
import { ElementTypes, PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'
|
||||||
import { OPERATE_KEYS, ElementScaleHandler } from '@/types/edit'
|
import { OPERATE_KEYS, ElementScaleHandler, AlignmentLineProps, MultiSelectRange } from '@/types/edit'
|
||||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
import { AlignLine, uniqAlignLines } from '../utils/alignLines'
|
import { AlignLine, uniqAlignLines } from '@/utils/element'
|
||||||
import { AlignmentLineProps, MultiSelectRange } from '../types/index'
|
|
||||||
|
|
||||||
// 计算元素被旋转一定角度后,八个操作点的新坐标
|
// 计算元素被旋转一定角度后,八个操作点的新坐标
|
||||||
interface RotateElementData {
|
interface RotateElementData {
|
||||||
|
@ -56,15 +56,6 @@
|
|||||||
:selectElement="selectElement"
|
:selectElement="selectElement"
|
||||||
:rotateElement="rotateElement"
|
:rotateElement="rotateElement"
|
||||||
:scaleElement="scaleElement"
|
:scaleElement="scaleElement"
|
||||||
:orderElement="orderElement"
|
|
||||||
:combineElements="combineElements"
|
|
||||||
:uncombineElements="uncombineElements"
|
|
||||||
:alignElementToCanvas="alignElementToCanvas"
|
|
||||||
:deleteElement="deleteElement"
|
|
||||||
:lockElement="lockElement"
|
|
||||||
:unlockElement="unlockElement"
|
|
||||||
:copyElement="copyElement"
|
|
||||||
:cutElement="cutElement"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -76,21 +67,19 @@ import { useStore } from 'vuex'
|
|||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { AlignmentLineProps } from './types/index'
|
import { AlignmentLineProps } from '@/types/edit'
|
||||||
|
|
||||||
import useViewportSize from './hooks/useViewportSize'
|
import useViewportSize from './hooks/useViewportSize'
|
||||||
import useLockElement from './hooks/useLockElement'
|
import useMouseSelection from './hooks/useMouseSelection'
|
||||||
import useDeleteElement from './hooks/useDeleteElement'
|
import useDropImageElement from './hooks/useDropImageElement'
|
||||||
import useCombineElement from './hooks/useCombineElement'
|
|
||||||
import useOrderElement from './hooks/useOrderElement'
|
|
||||||
import useAlignElementToCanvas from './hooks/useAlignElementToCanvas'
|
|
||||||
import useCopyAndPasteElement from './hooks/useCopyAndPasteElement'
|
|
||||||
import useRotateElement from './hooks/useRotateElement'
|
import useRotateElement from './hooks/useRotateElement'
|
||||||
import useScaleElement from './hooks/useScaleElement'
|
import useScaleElement from './hooks/useScaleElement'
|
||||||
import useSelectElement from './hooks/useSelectElement'
|
import useSelectElement from './hooks/useSelectElement'
|
||||||
import useDragElement from './hooks/useDragElement'
|
import useDragElement from './hooks/useDragElement'
|
||||||
import useMouseSelection from './hooks/useMouseSelection'
|
|
||||||
import useDropImageElement from './hooks/useDropImageElement'
|
import useDeleteElement from '@/hooks/useDeleteElement'
|
||||||
|
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
||||||
|
import useSelectAllElement from '@/hooks/useSelectAllElement'
|
||||||
|
|
||||||
import EditableElement from '@/views/_common/_element/EditableElement.vue'
|
import EditableElement from '@/views/_common/_element/EditableElement.vue'
|
||||||
import MouseSelection from './MouseSelection.vue'
|
import MouseSelection from './MouseSelection.vue'
|
||||||
@ -137,15 +126,13 @@ export default defineComponent({
|
|||||||
const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef, canvasScale)
|
const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef, canvasScale)
|
||||||
|
|
||||||
const { dragElement } = useDragElement(elementList, activeGroupElementId, canvasScale, alignmentLines)
|
const { dragElement } = useDragElement(elementList, activeGroupElementId, canvasScale, alignmentLines)
|
||||||
const { selectElement, selectAllElement } = useSelectElement(elementList, activeGroupElementId, dragElement)
|
const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)
|
||||||
const { scaleElement, scaleMultiElement } = useScaleElement(elementList, canvasScale, activeGroupElementId, alignmentLines)
|
const { scaleElement, scaleMultiElement } = useScaleElement(elementList, canvasScale, activeGroupElementId, alignmentLines)
|
||||||
const { rotateElement } = useRotateElement(elementList, viewportRef, canvasScale)
|
const { rotateElement } = useRotateElement(elementList, viewportRef, canvasScale)
|
||||||
const { orderElement } = useOrderElement(elementList)
|
|
||||||
const { alignElementToCanvas } = useAlignElementToCanvas(elementList)
|
const { selectAllElement } = useSelectAllElement()
|
||||||
const { combineElements, uncombineElements } = useCombineElement(elementList)
|
const { deleteAllElements } = useDeleteElement()
|
||||||
const { deleteElement, deleteAllElements } = useDeleteElement(elementList)
|
const { pasteElement } = useCopyAndPasteElement()
|
||||||
const { lockElement, unlockElement } = useLockElement(elementList)
|
|
||||||
const { copyElement, cutElement, pasteElement } = useCopyAndPasteElement(deleteElement)
|
|
||||||
|
|
||||||
const handleClickBlankArea = (e: MouseEvent) => {
|
const handleClickBlankArea = (e: MouseEvent) => {
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
@ -195,15 +182,6 @@ export default defineComponent({
|
|||||||
rotateElement,
|
rotateElement,
|
||||||
scaleElement,
|
scaleElement,
|
||||||
scaleMultiElement,
|
scaleMultiElement,
|
||||||
orderElement,
|
|
||||||
combineElements,
|
|
||||||
uncombineElements,
|
|
||||||
alignElementToCanvas,
|
|
||||||
deleteElement,
|
|
||||||
lockElement,
|
|
||||||
unlockElement,
|
|
||||||
copyElement,
|
|
||||||
cutElement,
|
|
||||||
contextmenus,
|
contextmenus,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
export interface AlignmentLineAxis {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlignmentLineProps {
|
|
||||||
type: 'vertical' | 'horizontal';
|
|
||||||
axis: AlignmentLineAxis;
|
|
||||||
length: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MultiSelectRange {
|
|
||||||
minX: number;
|
|
||||||
maxX: number;
|
|
||||||
minY: number;
|
|
||||||
maxY: number;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
export interface AlignLine {
|
|
||||||
value: number;
|
|
||||||
range: [number, number];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条
|
|
||||||
export const uniqAlignLines = (lines: AlignLine[]) => {
|
|
||||||
const uniqLines: AlignLine[] = []
|
|
||||||
lines.forEach(line => {
|
|
||||||
const index = uniqLines.findIndex(_line => _line.value === line.value)
|
|
||||||
if(index === -1) uniqLines.push(line)
|
|
||||||
else {
|
|
||||||
const uniqLine = uniqLines[index]
|
|
||||||
const rangeMin = Math.min(uniqLine.range[0], line.range[0])
|
|
||||||
const rangeMax = Math.max(uniqLine.range[1], line.range[1])
|
|
||||||
const range: [number, number] = [rangeMin, rangeMax]
|
|
||||||
const _line = { value: line.value, range }
|
|
||||||
uniqLines[index] = _line
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return uniqLines
|
|
||||||
}
|
|
@ -23,7 +23,7 @@
|
|||||||
@mousedown="changSlideIndex(index)"
|
@mousedown="changSlideIndex(index)"
|
||||||
v-contextmenu="contextmenus"
|
v-contextmenu="contextmenus"
|
||||||
>
|
>
|
||||||
<div class="slide-index">{{ fillDigit(index + 1) }}</div>
|
<div class="slide-index">{{ fillDigit(index + 1, 2) }}</div>
|
||||||
<div class="thumbnail"></div>
|
<div class="thumbnail"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -38,6 +38,7 @@ import { useStore } from 'vuex'
|
|||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { fillDigit } from '@/utils/common'
|
import { fillDigit } from '@/utils/common'
|
||||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||||
|
import useSlideHandler from '@/hooks/useSlideHandler'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'thumbnails',
|
name: 'thumbnails',
|
||||||
@ -49,6 +50,15 @@ export default defineComponent({
|
|||||||
const slides = computed(() => store.state.slides)
|
const slides = computed(() => store.state.slides)
|
||||||
const slideIndex = computed(() => store.state.slideIndex)
|
const slideIndex = computed(() => store.state.slideIndex)
|
||||||
|
|
||||||
|
const {
|
||||||
|
copySlide,
|
||||||
|
pasteSlide,
|
||||||
|
createSlide,
|
||||||
|
copyAndPasteSlide,
|
||||||
|
deleteSlide,
|
||||||
|
cutSlide,
|
||||||
|
} = useSlideHandler()
|
||||||
|
|
||||||
const changSlideIndex = (index: number) => {
|
const changSlideIndex = (index: number) => {
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
|
|
||||||
@ -75,25 +85,6 @@ export default defineComponent({
|
|||||||
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)
|
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cutSlide = () => {
|
|
||||||
console.log('cutSlide')
|
|
||||||
}
|
|
||||||
const copySlide = () => {
|
|
||||||
console.log('copySlide')
|
|
||||||
}
|
|
||||||
const pasteSlide = () => {
|
|
||||||
console.log('pasteSlide')
|
|
||||||
}
|
|
||||||
const createSlide = () => {
|
|
||||||
console.log('createSlide')
|
|
||||||
}
|
|
||||||
const copyAndPasteSlide = () => {
|
|
||||||
console.log('copyAndPasteSlide')
|
|
||||||
}
|
|
||||||
const deleteSlide = () => {
|
|
||||||
console.log('deleteSlide')
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextmenus = (): ContextmenuItem[] => {
|
const contextmenus = (): ContextmenuItem[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -2,50 +2,98 @@ import { computed, onMounted, onUnmounted } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { KEYS } from '@/configs/hotkey'
|
import { KEYS } from '@/configs/hotkey'
|
||||||
|
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
|
|
||||||
|
import useSlideHandler from '@/hooks/useSlideHandler'
|
||||||
|
import useLockElement from '@/hooks/useLockElement'
|
||||||
|
import useDeleteElement from '@/hooks/useDeleteElement'
|
||||||
|
import useCombineElement from '@/hooks/useCombineElement'
|
||||||
|
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
||||||
|
import useSelectAllElement from '@/hooks/useSelectAllElement'
|
||||||
|
import useMoveElement from '@/hooks/useMoveElement'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
|
||||||
const ctrlKeyActive = computed(() => store.state.ctrlKeyState)
|
const ctrlKeyActive = computed(() => store.state.ctrlKeyState)
|
||||||
const shiftKeyActive = computed(() => store.state.shiftKeyState)
|
const shiftKeyActive = computed(() => store.state.shiftKeyState)
|
||||||
|
const disableHotkeys = computed(() => store.state.disableHotkeys)
|
||||||
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
|
|
||||||
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
|
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
|
||||||
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
|
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
|
||||||
|
|
||||||
|
const {
|
||||||
|
updateSlideIndex,
|
||||||
|
copySlide,
|
||||||
|
createSlide,
|
||||||
|
deleteSlide,
|
||||||
|
cutSlide,
|
||||||
|
} = useSlideHandler()
|
||||||
|
|
||||||
|
const { combineElements, uncombineElements } = useCombineElement()
|
||||||
|
const { deleteElement } = useDeleteElement()
|
||||||
|
const { lockElement } = useLockElement()
|
||||||
|
const { copyElement, cutElement } = useCopyAndPasteElement()
|
||||||
|
const { selectAllElement } = useSelectAllElement()
|
||||||
|
const { moveElement } = useMoveElement()
|
||||||
|
|
||||||
const copy = () => {
|
const copy = () => {
|
||||||
message.success('copy')
|
if(disableHotkeys.value) return
|
||||||
|
if(thumbnailsFocus.value) copySlide()
|
||||||
|
else if(activeElementIdList.value.length) copyElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
const cut = () => {
|
const cut = () => {
|
||||||
message.success('cut')
|
if(disableHotkeys.value) return
|
||||||
|
if(thumbnailsFocus.value) cutSlide()
|
||||||
|
else if(activeElementIdList.value.length) cutElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
const undo = () => {
|
const undo = () => {
|
||||||
message.success('undo')
|
message.success('undo')
|
||||||
}
|
}
|
||||||
|
|
||||||
const redo = () => {
|
const redo = () => {
|
||||||
message.success('redo')
|
message.success('redo')
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectAll = () => {
|
const selectAll = () => {
|
||||||
message.success('selectAll')
|
if(!editorAreaFocus.value && disableHotkeys.value) return
|
||||||
|
selectAllElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
const lock = () => {
|
const lock = () => {
|
||||||
message.success('lock')
|
if(!editorAreaFocus.value && disableHotkeys.value) return
|
||||||
|
lockElement()
|
||||||
}
|
}
|
||||||
const combine = () => {
|
const combine = () => {
|
||||||
message.success('combine')
|
if(!editorAreaFocus.value && disableHotkeys.value) return
|
||||||
|
combineElements()
|
||||||
}
|
}
|
||||||
|
|
||||||
const uncombine = () => {
|
const uncombine = () => {
|
||||||
message.success('uncombine')
|
if(!editorAreaFocus.value && disableHotkeys.value) return
|
||||||
|
uncombineElements()
|
||||||
}
|
}
|
||||||
|
|
||||||
const remove = () => {
|
const remove = () => {
|
||||||
message.success('remove')
|
if(disableHotkeys.value) return
|
||||||
|
if(thumbnailsFocus.value) deleteSlide()
|
||||||
|
else if(activeElementIdList.value.length) deleteElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
const move = (key: string) => {
|
const move = (key: string) => {
|
||||||
message.success(`move: ${key}`)
|
if(disableHotkeys.value) return
|
||||||
|
if(thumbnailsFocus.value && (key === KEYS.UP || key === KEYS.DOWN)) {
|
||||||
|
updateSlideIndex(key)
|
||||||
|
}
|
||||||
|
else if(activeElementIdList.value.length) moveElement(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
const create = () => {
|
const create = () => {
|
||||||
message.success('create')
|
if(!thumbnailsFocus.value || disableHotkeys.value) return
|
||||||
|
createSlide()
|
||||||
}
|
}
|
||||||
|
|
||||||
const keydownListener = (e: KeyboardEvent) => {
|
const keydownListener = (e: KeyboardEvent) => {
|
||||||
|
@ -27,13 +27,14 @@ import { computed, defineComponent, PropType } from 'vue'
|
|||||||
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement, PPTLineElement } from '@/types/slides'
|
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement, PPTLineElement } from '@/types/slides'
|
||||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||||
|
|
||||||
import {
|
import useLockElement from '@/hooks/useLockElement'
|
||||||
ElementOrderCommand,
|
import useDeleteElement from '@/hooks/useDeleteElement'
|
||||||
ElementOrderCommands,
|
import useCombineElement from '@/hooks/useCombineElement'
|
||||||
ElementAlignCommand,
|
import useOrderElement from '@/hooks/useOrderElement'
|
||||||
ElementAlignCommands,
|
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
|
||||||
ElementScaleHandler,
|
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
||||||
} from '@/types/edit'
|
|
||||||
|
import { ElementOrderCommands, ElementAlignCommands, ElementScaleHandler } from '@/types/edit'
|
||||||
|
|
||||||
import ImageElement from './ImageElement/index.vue'
|
import ImageElement from './ImageElement/index.vue'
|
||||||
import TextElement from './TextElement/index.vue'
|
import TextElement from './TextElement/index.vue'
|
||||||
@ -85,42 +86,6 @@ export default defineComponent({
|
|||||||
type: Function as PropType<(e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: ElementScaleHandler) => void>,
|
type: Function as PropType<(e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: ElementScaleHandler) => void>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
orderElement: {
|
|
||||||
type: Function as PropType<(element: PPTElement, command: ElementOrderCommand) => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
combineElements: {
|
|
||||||
type: Function as PropType<() => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
uncombineElements: {
|
|
||||||
type: Function as PropType<() => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
alignElementToCanvas: {
|
|
||||||
type: Function as PropType<(command: ElementAlignCommand) => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
deleteElement: {
|
|
||||||
type: Function as PropType<() => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
lockElement: {
|
|
||||||
type: Function as PropType<(element: PPTElement) => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
unlockElement: {
|
|
||||||
type: Function as PropType<(element: PPTElement) => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
copyElement: {
|
|
||||||
type: Function as PropType<() => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
cutElement: {
|
|
||||||
type: Function as PropType<() => void>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const currentElementComponent = computed(() => {
|
const currentElementComponent = computed(() => {
|
||||||
@ -131,12 +96,19 @@ export default defineComponent({
|
|||||||
return elementTypeMap[props.elementInfo.type] || null
|
return elementTypeMap[props.elementInfo.type] || null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { orderElement } = useOrderElement()
|
||||||
|
const { alignElementToCanvas } = useAlignElementToCanvas()
|
||||||
|
const { combineElements, uncombineElements } = useCombineElement()
|
||||||
|
const { deleteElement } = useDeleteElement()
|
||||||
|
const { lockElement, unlockElement } = useLockElement()
|
||||||
|
const { copyElement, cutElement } = useCopyAndPasteElement()
|
||||||
|
|
||||||
const contextmenus = (): ContextmenuItem[] => {
|
const contextmenus = (): ContextmenuItem[] => {
|
||||||
if(props.elementInfo.isLock) {
|
if(props.elementInfo.isLock) {
|
||||||
return [{
|
return [{
|
||||||
text: '解锁',
|
text: '解锁',
|
||||||
icon: 'icon-unlock',
|
icon: 'icon-unlock',
|
||||||
handler: () => props.unlockElement(props.elementInfo),
|
handler: () => unlockElement(props.elementInfo),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +117,13 @@ export default defineComponent({
|
|||||||
text: '剪切',
|
text: '剪切',
|
||||||
subText: 'Ctrl + X',
|
subText: 'Ctrl + X',
|
||||||
icon: 'icon-scissor',
|
icon: 'icon-scissor',
|
||||||
handler: props.cutElement,
|
handler: cutElement,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '复制',
|
text: '复制',
|
||||||
subText: 'Ctrl + C',
|
subText: 'Ctrl + C',
|
||||||
icon: 'icon-copy',
|
icon: 'icon-copy',
|
||||||
handler: props.copyElement,
|
handler: copyElement,
|
||||||
},
|
},
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{
|
{
|
||||||
@ -159,29 +131,29 @@ export default defineComponent({
|
|||||||
icon: 'icon-top-layer',
|
icon: 'icon-top-layer',
|
||||||
disable: props.isMultiSelect && !props.elementInfo.groupId,
|
disable: props.isMultiSelect && !props.elementInfo.groupId,
|
||||||
children: [
|
children: [
|
||||||
{ text: '置顶层', handler: () => props.orderElement(props.elementInfo, ElementOrderCommands.TOP) },
|
{ text: '置顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },
|
||||||
{ text: '置底层', handler: () => props.orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },
|
{ text: '置底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{ text: '上移一层', handler: () => props.orderElement(props.elementInfo, ElementOrderCommands.UP) },
|
{ text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },
|
||||||
{ text: '下移一层', handler: () => props.orderElement(props.elementInfo, ElementOrderCommands.DOWN) },
|
{ text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '水平对齐',
|
text: '水平对齐',
|
||||||
icon: 'icon-align-left',
|
icon: 'icon-align-left',
|
||||||
children: [
|
children: [
|
||||||
{ text: '水平居中', handler: () => props.alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },
|
{ text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },
|
||||||
{ text: '左对齐', handler: () => props.alignElementToCanvas(ElementAlignCommands.LEFT) },
|
{ text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },
|
||||||
{ text: '右对齐', handler: () => props.alignElementToCanvas(ElementAlignCommands.RIGHT) },
|
{ text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '垂直对齐',
|
text: '垂直对齐',
|
||||||
icon: 'icon-align-bottom',
|
icon: 'icon-align-bottom',
|
||||||
children: [
|
children: [
|
||||||
{ text: '垂直居中', handler: () => props.alignElementToCanvas(ElementAlignCommands.VERTICAL) },
|
{ text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },
|
||||||
{ text: '上对齐', handler: () => props.alignElementToCanvas(ElementAlignCommands.TOP) },
|
{ text: '上对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },
|
||||||
{ text: '下对齐', handler: () => props.alignElementToCanvas(ElementAlignCommands.BOTTOM) },
|
{ text: '下对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
@ -189,20 +161,20 @@ export default defineComponent({
|
|||||||
text: props.elementInfo.groupId ? '取消组合' : '组合',
|
text: props.elementInfo.groupId ? '取消组合' : '组合',
|
||||||
subText: 'Ctrl + G',
|
subText: 'Ctrl + G',
|
||||||
icon: 'icon-block',
|
icon: 'icon-block',
|
||||||
handler: props.elementInfo.groupId ? props.uncombineElements : props.combineElements,
|
handler: props.elementInfo.groupId ? uncombineElements : combineElements,
|
||||||
hide: !props.isMultiSelect,
|
hide: !props.isMultiSelect,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '锁定',
|
text: '锁定',
|
||||||
subText: 'Ctrl + L',
|
subText: 'Ctrl + L',
|
||||||
icon: 'icon-lock',
|
icon: 'icon-lock',
|
||||||
handler: () => props.lockElement(props.elementInfo),
|
handler: lockElement,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '删除',
|
text: '删除',
|
||||||
subText: 'Delete',
|
subText: 'Delete',
|
||||||
icon: 'icon-delete',
|
icon: 'icon-delete',
|
||||||
handler: props.deleteElement,
|
handler: deleteElement,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user