Compare commits

...
55 Commits
Author SHA1 Message Date
hooray ffb3c85b83 chore: release v2.3.0 2022-11-28 00:35:20 +08:00
hooray ca1ea48dc6 refactor: 修改 Menu.recordRaw 和 Menu.recordMainRaw 类型里的 meta 为可选参数 2022-11-27 23:40:16 +08:00
hooray 5c6494931b fix: 修复标题显示异常 2022-11-27 23:37:03 +08:00
hooray e24431c38a refactor!: 移除自定义 Route.recordRaw 类型,改用 RouteRecordRaw 类型 2022-11-27 17:50:31 +08:00
hooray f85a911b8e fix: 修复文件系统路由模式下,全局搜索列表 icon 显示不全 2022-11-27 04:09:30 +08:00
hooray 776fe7a944 feat: 路由meta.title修改为非必须 2022-11-27 03:52:22 +08:00
hooray ce099b3bea chore: release v2.2.0 2022-11-26 15:37:52 +08:00
hooray eff431a09d chore: 更新依赖 2022-11-26 09:42:50 +08:00
hooray 501a8955c3 chore: 更新依赖 2022-11-19 21:37:54 +08:00
hooray f0a523f505 fix: 修复文件系统路由下,次导航无法按层级依次展开 2022-11-19 09:11:03 +08:00
hooray b2e33ca05f refactor!: 控制台修改为主页,路由调整为根路由
从原有 /dashboard 路由调整为 / 根路由
2022-11-19 09:10:30 +08:00
hooray a401b1f5bf refactor: 优化 PageHeader 组件在移动端下的展示 2022-11-13 00:51:02 +08:00
hooray 07a13b004e chore: release v2.1.3 2022-11-11 10:09:02 +08:00
hooray defd87869e ci: 优化 release 产物 2022-11-11 10:06:45 +08:00
hooray 051e6a99e1 chore: release v2.1.1 2022-11-10 19:54:08 +08:00
hooray 5f3855cc82 chore: 更新依赖 2022-11-10 19:49:23 +08:00
hooray 6489e8b94a ci: 优化 release 发布工作流 2022-11-10 19:30:30 +08:00
hooray 98ca00326a chore: husky 替换为 simple-git-hooks 2022-11-09 16:05:52 +08:00
hooray fc033c8693 chore: 更新依赖 2022-11-08 00:38:40 +08:00
hooray 57b18c2710 feat: logo 支持非正方形图片 2022-11-04 17:24:16 +08:00
hooray d667088c89 chore: release v2.1.0 2022-10-30 04:14:59 +08:00
hooray 41b3cd7a8e chore: 更新依赖 2022-10-29 18:46:32 +08:00
hooray 8e9a1e5683 chore: 更新依赖 2022-10-25 08:33:13 +08:00
hooray 05939a99ee chore: 调整 copyright 信息和展示逻辑 2022-10-25 08:27:07 +08:00
hooray 84e1581dcf chore: 移除 vite-plugin-restart 2022-10-25 08:25:12 +08:00
hooray 4a2538cfe3 refactor: 优化配置项合并 2022-10-25 08:23:20 +08:00
hooray c091c685e8 refactor!: useCurrentInstance() 重命名为 useGlobalProperties() 2022-10-23 14:25:18 +08:00
hooray 613972f4a1 refactor: 将 element plus 反馈组件改为手动引入 2022-10-23 14:18:17 +08:00
hooray d860fe74c3 chore: 给 eslint 和 stylelint 命令增加 --cache 设置 2022-10-23 14:04:53 +08:00
hooray ffa8943267 chore: 重建 pnpm-lock.yaml 文件 2022-10-23 14:03:08 +08:00
hooray babd6c9c2a chore: 更新依赖 2022-10-23 13:59:59 +08:00
hooray 7250872ac0 chore: 增加 vscode 推荐扩展 2022-10-22 00:50:57 +08:00
hooray 7f42710a55 ci: 增加 vue-tsc 校验脚本 2022-10-21 03:59:06 +08:00
hooray fe6d81c08d fix: 修复类型报错 2022-10-16 07:11:04 +08:00
hooray 1842f10172 ci: 调整 commit 配置 2022-10-16 07:10:12 +08:00
hooray 5bbde8d102 refactor: 优化拦截器 2022-10-16 06:48:53 +08:00
hooray 8771b33834 chore: 更新依赖 2022-10-16 06:00:43 +08:00
hooray 842519768e chore: 更新 tinymce 主题样式和汉化文件 2022-10-16 05:59:19 +08:00
hooray 25458835e9 chore: release v2.0.2 2022-10-15 04:05:54 +08:00
hooray abc0ac8e4c chore: 更新依赖 2022-10-14 18:42:59 +08:00
hooray 0e222b986d revert: 回退部分定位组件的 z-index 设置,强制重写 v-loading 的 z-index 样式 2022-10-13 19:19:11 +08:00
hooray 925ee00287 fix: 调整部分定位组件的z-index层级
element plus 的 v-loading 遮罩层默认 z-index 为 2000
导致会遮挡住框架部分组件
2022-10-13 14:21:47 +08:00
hooray d9291175b9 docs: 路由导航守卫代码注释调整 2022-10-13 14:19:13 +08:00
hooray c2e9b16917 refactor: 优化代码逻辑 2022-10-13 14:15:23 +08:00
hooray c0881951d3 chore: 更新依赖 2022-10-13 14:12:48 +08:00
hooray f0c6ddd221 chore: 调整文件忽略 2022-10-12 01:35:34 +08:00
hooray 07b9e31b22 fix: 修复获取侧边栏导航最深一级路由可能返回为空的问题 2022-10-12 01:30:40 +08:00
hooray a0708253af refactor: 简化导航守卫里的逻辑 2022-10-12 01:29:32 +08:00
hooray a1e1f2e4db chore: 更新依赖 2022-10-10 23:43:55 +08:00
Hooray b93c86aa44 chore: 更新依赖 2022-10-09 02:41:17 +08:00
Hooray 49e78d5c20 style: 更新 stylelint 规则 2022-10-03 22:12:09 +08:00
Hooray 33ea08fa4b style: 控制语句代码风格调整 2022-10-02 03:29:37 +08:00
Hooray 0e89630b54 docs: 更新 readme 链接 2022-09-30 14:27:31 +08:00
Hooray d6d67d357d style: 优化文件生成模版 2022-09-29 22:04:29 +08:00
Hooray 848e107388 chore: 更新依赖 2022-09-29 21:59:19 +08:00
97 changed files with 2607 additions and 1783 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ module.exports = {
{ value: 'fix', name: 'fix: 🐛 修复缺陷 | A bug fix', emoji: ':bug:' },
{ value: 'docs', name: 'docs: 📝 文档更新 | Documentation only changes', emoji: ':memo:' },
{ value: 'style', name: 'style: 💄 代码格式 | Changes that do not affect the meaning of the code', emoji: ':lipstick:' },
{ value: 'refactor', name: 'refactor: ♻️ 代码重构 | A code change that neither fixes a bug nor adds a feature', emoji: ':recycle:' },
{ value: 'refactor', name: 'refactor: ♻️ 代码重构 | A code change that neither fixes a bug nor adds a feature', emoji: ':recycle:' },
{ value: 'perf', name: 'perf: ⚡️ 性能提升 | A code change that improves performance', emoji: ':zap:' },
{ value: 'test', name: 'test: ✅ 测试相关 | Adding missing tests or correcting existing tests', emoji: ':white_check_mark:' },
{ value: 'build', name: 'build: 📦️ 构建相关 | Changes that affect the build system or external dependencies', emoji: ':package:' },
-2
View File
@@ -1,2 +0,0 @@
dist/
node_modules/
+4 -1
View File
@@ -1,3 +1,6 @@
{
"extends": "@antfu"
"extends": "@antfu",
"rules": {
"curly": ["error", "all"]
}
}
+66 -1
View File
@@ -19,4 +19,69 @@ jobs:
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
upload-archive:
needs: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Release
id: last_release
uses: joutvhu/get-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
latest: true
- name: Create Archive
uses: thedoctor0/zip-release@main
with:
type: 'zip'
filename: fantastic-admin.${{ steps.last_release.outputs.tag_name }}.zip
exclusions: '/.git/* /.github/*'
- name: Upload Archive To Release
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release_id: ${{ steps.last_release.outputs.id }}
draft: false
file: fantastic-admin.${{ steps.last_release.outputs.tag_name }}.zip
upload-archive-example:
needs: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
ref: example
- name: Get Release
id: last_release
uses: joutvhu/get-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
latest: true
- name: Create Archive
uses: thedoctor0/zip-release@main
with:
type: 'zip'
filename: fantastic-admin.example.${{ steps.last_release.outputs.tag_name }}.zip
exclusions: '/.git/* /.github/*'
- name: Upload Archive To Release
uses: xresloader/upload-to-github-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release_id: ${{ steps.last_release.outputs.id }}
draft: false
file: fantastic-admin.example.${{ steps.last_release.outputs.tag_name }}.zip
+3
View File
@@ -3,5 +3,8 @@ node_modules
dist*
dist-ssr
*.local
.eslintcache
.stylelintcache
src/assets/sprites/*.*
!src/assets/sprites/.gitkeep
public/icons
-4
View File
@@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm lint-staged
+3 -3
View File
@@ -1,5 +1,5 @@
{
"src/**/*.{js,jsx,ts,tsx}": "eslint --fix",
"src/**/*.{css,scss}": "stylelint --fix --allow-empty-input",
"src/**/*.vue": ["eslint --fix", "stylelint --fix --allow-empty-input"]
"src/**/*.{js,jsx,ts,tsx}": "eslint --cache --fix",
"src/**/*.{css,scss}": "stylelint --cache --fix --allow-empty-input",
"src/**/*.vue": ["eslint --cache --fix", "stylelint --cache --fix --allow-empty-input"]
}
+4 -7
View File
@@ -1,14 +1,9 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-standard-scss",
"stylelint-config-standard-vue/scss"
],
"overrides": [
{
"files": ["**/*.scss"],
"customSyntax": "postcss-scss"
}
],
"plugins": [
"stylelint-scss"
],
@@ -18,6 +13,8 @@
"property-no-unknown": null,
"font-family-no-missing-generic-family-keyword": null,
"selector-class-pattern": null,
"max-line-length": null
"max-line-length": null,
"scss/double-slash-comment-empty-line-before": null,
"scss/no-global-function-names": null
}
}
+2 -1
View File
@@ -4,6 +4,7 @@
"mikestead.dotenv",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"vue.volar"
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
]
}
+2 -2
View File
@@ -11,8 +11,8 @@
( <a href="https://hooray.github.io/fantastic-admin" target="_blank">备用</a> )
<span>&nbsp;|&nbsp;</span>
演示
( <a href="https://hooray.gitee.io/fantastic-admin/vue3/basic" target="_blank">基础版</a>
<a href="https://hooray.gitee.io/fantastic-admin/vue3/pro" target="_blank">专业版</a> )
( <a href="https://hooray.gitee.io/fantastic-admin-example" target="_blank">基础版</a>
<a href="https://hooray.gitee.io/fantastic-admin-pro-example" target="_blank">专业版</a> )
<span>&nbsp;|&nbsp;</span>
<a href="https://hooray.gitee.io/fantastic-admin/support.html" target="_blank">技术支持</a>
<span>&nbsp;|&nbsp;</span>
+42 -38
View File
@@ -1,5 +1,5 @@
{
"version": "2.0.1",
"version": "2.3.0",
"scripts": {
"dev": "vite",
"build:test": "vue-tsc --noEmit && vite build --mode test",
@@ -8,77 +8,81 @@
"serve": "http-server ./dist -o",
"svgo": "svgo -f src/assets/icons",
"new": "plop",
"lint:eslint": "eslint src/**/*.{ts,tsx,vue} --fix",
"lint:stylelint": "stylelint src/**/*.{css,scss,vue} --fix",
"prepare": "husky install",
"postinstall": "esno scripts/prepare.js",
"lint": "npm-run-all -s lint:tsc lint:eslint lint:stylelint",
"lint:tsc": "vue-tsc --noEmit",
"lint:eslint": "eslint src/**/*.{ts,tsx,vue} --cache --fix",
"lint:stylelint": "stylelint src/**/*.{css,scss,vue} --cache --fix",
"postinstall": "simple-git-hooks && esno scripts/prepare.js",
"preinstall": "npx only-allow pnpm",
"commit": "git cz",
"release": "bumpp"
},
"dependencies": {
"@tinymce/tinymce-vue": "^5.0.0",
"@vueuse/core": "^9.2.0",
"@vueuse/integrations": "^9.2.0",
"axios": "^0.27.2",
"dayjs": "^1.11.5",
"element-plus": "^2.2.17",
"hotkeys-js": "^3.10.0",
"@vueuse/core": "^9.6.0",
"@vueuse/integrations": "^9.6.0",
"axios": "^1.2.0",
"dayjs": "^1.11.6",
"element-plus": "^2.2.25",
"hotkeys-js": "^3.10.1",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path-browserify": "^1.0.1",
"path-to-regexp": "^6.2.1",
"pinia": "^2.0.22",
"pinia": "^2.0.26",
"qs": "^6.11.0",
"tinymce": "^6.2.0",
"vue": "^3.2.39",
"vue-router": "^4.1.5"
"tinymce": "^6.3.0",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@antfu/eslint-config": "^0.27.0",
"@iconify-json/ep": "^1.1.7",
"@antfu/eslint-config": "^0.31.0",
"@iconify-json/ep": "^1.1.8",
"@iconify/vue": "^4.0.0",
"@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0",
"@types/qs": "^6.9.7",
"@vitejs/plugin-vue": "^3.1.0",
"@vitejs/plugin-vue-jsx": "^2.0.1",
"autoprefixer": "^10.4.12",
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1",
"autoprefixer": "^10.4.13",
"bumpp": "^8.2.1",
"cz-git": "^1.3.11",
"eslint": "^8.24.0",
"cz-git": "^1.3.12",
"eslint": "^8.28.0",
"esno": "^0.16.3",
"fs-extra": "^10.1.0",
"http-server": "^14.1.1",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"lint-staged": "^13.0.4",
"npm-run-all": "^4.1.5",
"plop": "^3.1.1",
"postcss-html": "^1.5.0",
"postcss-scss": "^4.0.5",
"sass": "^1.55.0",
"stylelint": "^14.12.1",
"stylelint-config-standard": "^28.0.0",
"stylelint-config-standard-scss": "^5.0.0",
"sass": "^1.56.1",
"simple-git-hooks": "^2.8.1",
"stylelint": "^14.15.0",
"stylelint-config-standard": "^29.0.0",
"stylelint-config-standard-scss": "^6.1.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-scss": "^4.3.0",
"svgo": "^2.8.0",
"typescript": "^4.8.3",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.7",
"vite": "^3.1.3",
"vite-plugin-banner": "^0.5.0",
"svgo": "^3.0.2",
"typescript": "^4.9.3",
"unplugin-auto-import": "^0.12.0",
"unplugin-vue-components": "^0.22.11",
"vite": "^3.2.4",
"vite-plugin-banner": "^0.6.1",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-pages": "^0.26.0",
"vite-plugin-restart": "^0.2.0",
"vite-plugin-pages": "^0.27.1",
"vite-plugin-spritesmith": "^0.1.1",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-layouts": "^0.6.0",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.40.13"
"vue-tsc": "^1.0.9"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged",
"preserveUnused": true
},
"config": {
"commitizen": {
+3 -3
View File
@@ -1,13 +1,13 @@
<script lang="ts" setup{{#if isGlobal}} name="{{ properCase name }}"{{/if}}>
// const proxy = useCurrentInstance()
// 逻辑代码
</script>
<template>
<div>
<!-- 内容区 -->
<!-- 布局 -->
</div>
</template>
<style lang="scss" scoped>
// scss
// 样式
</style>
+8 -7
View File
@@ -36,22 +36,23 @@ module.exports = {
name: 'name',
message: '请输入组件名称',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '组件名称不能为空'
else
}
else {
return true
}
},
},
],
actions: (data) => {
let path = ''
if (data.isGlobal)
if (data.isGlobal) {
path = 'src/components/{{properCase name}}/index.vue'
else
}
else {
path = `${data.path}/components/{{properCase name}}/index.vue`
}
const actions = [
{
type: 'add',
+3 -5
View File
@@ -1,15 +1,13 @@
<script lang="ts" setup name="{{ properCase componentName }}">
// const proxy = useCurrentInstance()
// const router = useRouter()
// const route = useRoute()
// 逻辑代码
</script>
<template>
<div>
页面内容区域
<!-- 布局 -->
</div>
</template>
<style lang="scss" scoped>
// scss
// 样式
</style>
+4 -3
View File
@@ -28,11 +28,12 @@ module.exports = {
name: 'name',
message: '请输入文件名',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '文件名不能为空'
else
}
else {
return true
}
},
},
],
+2 -2
View File
@@ -4,8 +4,8 @@ const use{{ properCase name }}Store = defineStore(
{
state: () => ({}),
getters: {},
actions: {}
}
actions: {},
},
)
export default use{{ properCase name }}Store
+5 -4
View File
@@ -6,11 +6,12 @@ module.exports = {
name: 'name',
message: '请输入模块名称',
validate: (v) => {
if (!v || v.trim === '')
if (!v || v.trim === '') {
return '模块名称不能为空'
else
}
else {
return true
}
},
},
],
@@ -18,7 +19,7 @@ module.exports = {
const actions = [
{
type: 'add',
path: 'src/store/modules/{{camelCase name}}.js',
path: 'src/store/modules/{{camelCase name}}.ts',
templateFile: 'plop-templates/store/index.hbs',
},
]
+1212 -1129
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+51 -6
View File
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -186,6 +203,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -215,6 +253,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.3);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.3);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%20fill%3D%22%23cccccc%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -506,10 +551,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+90 -19
View File
@@ -252,11 +252,24 @@ button::-moz-focus-inner {
margin: 0;
outline: none;
padding: 4px 16px;
position: relative;
text-align: center;
text-decoration: none;
text-transform: none;
white-space: nowrap;
}
.tox .tox-button::before {
border-radius: 6px;
bottom: -1px;
box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #006ce7, 0 0 0 3px rgba(0, 108, 231, 0.25);
content: '';
left: -1px;
opacity: 0;
pointer-events: none;
position: absolute;
right: -1px;
top: -1px;
}
.tox .tox-button[disabled] {
background-color: #006ce7;
background-image: none;
@@ -272,6 +285,9 @@ button::-moz-focus-inner {
box-shadow: none;
color: #fff;
}
.tox .tox-button:focus-visible:not(:disabled)::before {
opacity: 1;
}
.tox .tox-button:hover:not(:disabled) {
background-color: #0060ce;
background-image: none;
@@ -933,8 +949,9 @@ button::-moz-focus-inner {
justify-content: space-between;
}
.tox .tox-comment__date {
color: rgba(255, 255, 255, 0.5);
color: #fff;
font-size: 12px;
line-height: 18px;
}
.tox .tox-comment__body {
color: #fff;
@@ -1093,20 +1110,30 @@ button::-moz-focus-inner {
.tox .tox-user__avatar svg {
fill: rgba(255, 255, 255, 0.5);
}
.tox .tox-user__avatar img {
border-radius: 50%;
height: 36px;
object-fit: cover;
vertical-align: middle;
width: 36px;
}
.tox .tox-user__name {
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
color: #fff;
font-size: 14px;
font-style: normal;
font-weight: bold;
text-transform: uppercase;
line-height: 18px;
text-transform: none;
}
.tox:not([dir=rtl]) .tox-user__avatar svg {
.tox:not([dir=rtl]) .tox-user__avatar svg,
.tox:not([dir=rtl]) .tox-user__avatar img {
margin-right: 8px;
}
.tox:not([dir=rtl]) .tox-user__avatar + .tox-user__name {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar svg {
.tox[dir=rtl] .tox-user__avatar svg,
.tox[dir=rtl] .tox-user__avatar img {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar + .tox-user__name {
@@ -1151,10 +1178,11 @@ button::-moz-focus-inner {
width: 95vw;
z-index: 2;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog {
align-self: flex-start;
margin: 8px auto;
max-height: calc(100vh - 8px * 2);
width: calc(100vw - 16px);
}
}
@@ -1210,7 +1238,7 @@ button::-moz-focus-inner {
text-align: left;
text-transform: none;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body {
flex-direction: column;
}
@@ -1221,7 +1249,7 @@ button::-moz-focus-inner {
flex-direction: column;
padding: 16px 16px;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body-nav {
flex-direction: row;
-webkit-overflow-scrolling: touch;
@@ -1389,6 +1417,9 @@ button::-moz-focus-inner {
padding-bottom: 8px;
padding-top: 8px;
}
.tox .tox-dialog__iframe.tox-dialog__iframe--opaque {
background: #fff;
}
.tox .tox-dialog__popups {
position: absolute;
width: 100%;
@@ -1421,12 +1452,12 @@ button::-moz-focus-inner {
.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein {
transition-delay: 0s;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav {
margin-right: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child) {
margin-left: 8px;
}
@@ -1438,12 +1469,12 @@ button::-moz-focus-inner {
.tox[dir=rtl] .tox-dialog__body {
text-align: right;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav {
margin-left: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child) {
margin-right: 8px;
}
@@ -1500,6 +1531,8 @@ body.tox-dialog__disable-scroll {
overflow: hidden;
}
.tox .tox-editor-header {
display: grid;
grid-template-columns: 1fr min-content;
z-index: 1;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header {
@@ -1581,8 +1614,7 @@ body.tox-dialog__disable-scroll {
max-width: 25em;
}
.tox .tox-autocompleter .tox-menu {
border-color: #161f29;
box-shadow: none;
box-sizing: border-box;
max-width: 25em;
}
.tox .tox-autocompleter .tox-autocompleter-highlight {
@@ -2073,6 +2105,12 @@ body.tox-dialog__disable-scroll {
.tox .tox-menu.tox-collection.tox-collection--grid {
padding: 8px;
}
@media only screen and (min-width: 768px ) {
.tox .tox-menu .tox-collection__item-label {
overflow-wrap: break-word;
word-break: normal;
}
}
.tox .tox-menu__label h1,
.tox .tox-menu__label h2,
.tox .tox-menu__label h3,
@@ -2085,16 +2123,45 @@ body.tox-dialog__disable-scroll {
margin: 0;
}
.tox .tox-menubar {
background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='transparent'/%3E%3C/svg%3E") left 0 top 0 #222F3E;
background: repeating-linear-gradient(transparent 0px 1px, transparent 1px 39px) center top 39px / 100% calc(100% - 39px) no-repeat;
background-color: #222F3E;
display: flex;
flex: 0 0 auto;
flex-shrink: 0;
flex-wrap: wrap;
grid-column: 1 / -1;
grid-row: 1;
padding: 0 11px 0 12px;
}
.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid transparent;
.tox .tox-promotion + .tox-menubar {
grid-column: 1;
}
.tox .tox-promotion {
background: repeating-linear-gradient(transparent 0px 1px, transparent 1px 39px) center top 39px / 100% calc(100% - 39px) no-repeat;
background-color: #222F3E;
grid-column: 2;
grid-row: 1;
padding-inline-end: 8px;
padding-inline-start: 4px;
padding-top: 5px;
}
.tox .tox-promotion-link {
align-items: unsafe center;
background-color: #E8F1F8;
border-radius: 5px;
color: #086BE6;
cursor: pointer;
display: flex;
font-size: 14px;
height: 26.6px;
padding: 4px 8px;
white-space: nowrap;
}
.tox .tox-promotion-link:hover {
background-color: #B4D7FF;
}
.tox .tox-promotion-link:focus {
background-color: #D9EDF7;
}
/* Deprecated. Remove in next major release */
.tox .tox-mbtn {
@@ -2874,10 +2941,14 @@ body.tox-dialog__disable-scroll {
.tox .tox-toolbar__overflow--shrinking {
transition: opacity 0.3s ease, height 0.2s linear 0.1s, visibility 0s linear 0.3s;
}
.tox .tox-toolbar-overlord,
.tox .tox-anchorbar {
grid-column: 1 / -1;
}
.tox .tox-menubar + .tox-toolbar,
.tox .tox-menubar + .tox-toolbar-overlord {
border-top: 1px solid transparent;
margin-top: 0px;
margin-top: -1px;
padding-bottom: 1px;
padding-top: 1px;
}
File diff suppressed because one or more lines are too long
+51 -6
View File
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+90 -19
View File
@@ -252,11 +252,24 @@ button::-moz-focus-inner {
margin: 0;
outline: none;
padding: 4px 16px;
position: relative;
text-align: center;
text-decoration: none;
text-transform: none;
white-space: nowrap;
}
.tox .tox-button::before {
border-radius: 6px;
bottom: -1px;
box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #006ce7, 0 0 0 3px rgba(0, 108, 231, 0.25);
content: '';
left: -1px;
opacity: 0;
pointer-events: none;
position: absolute;
right: -1px;
top: -1px;
}
.tox .tox-button[disabled] {
background-color: #006ce7;
background-image: none;
@@ -272,6 +285,9 @@ button::-moz-focus-inner {
box-shadow: none;
color: #fff;
}
.tox .tox-button:focus-visible:not(:disabled)::before {
opacity: 1;
}
.tox .tox-button:hover:not(:disabled) {
background-color: #0060ce;
background-image: none;
@@ -933,8 +949,9 @@ button::-moz-focus-inner {
justify-content: space-between;
}
.tox .tox-comment__date {
color: rgba(34, 47, 62, 0.7);
color: #222f3e;
font-size: 12px;
line-height: 18px;
}
.tox .tox-comment__body {
color: #222f3e;
@@ -1093,20 +1110,30 @@ button::-moz-focus-inner {
.tox .tox-user__avatar svg {
fill: rgba(34, 47, 62, 0.7);
}
.tox .tox-user__avatar img {
border-radius: 50%;
height: 36px;
object-fit: cover;
vertical-align: middle;
width: 36px;
}
.tox .tox-user__name {
color: rgba(34, 47, 62, 0.7);
font-size: 12px;
color: #222f3e;
font-size: 14px;
font-style: normal;
font-weight: bold;
text-transform: uppercase;
line-height: 18px;
text-transform: none;
}
.tox:not([dir=rtl]) .tox-user__avatar svg {
.tox:not([dir=rtl]) .tox-user__avatar svg,
.tox:not([dir=rtl]) .tox-user__avatar img {
margin-right: 8px;
}
.tox:not([dir=rtl]) .tox-user__avatar + .tox-user__name {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar svg {
.tox[dir=rtl] .tox-user__avatar svg,
.tox[dir=rtl] .tox-user__avatar img {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar + .tox-user__name {
@@ -1151,10 +1178,11 @@ button::-moz-focus-inner {
width: 95vw;
z-index: 2;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog {
align-self: flex-start;
margin: 8px auto;
max-height: calc(100vh - 8px * 2);
width: calc(100vw - 16px);
}
}
@@ -1210,7 +1238,7 @@ button::-moz-focus-inner {
text-align: left;
text-transform: none;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body {
flex-direction: column;
}
@@ -1221,7 +1249,7 @@ button::-moz-focus-inner {
flex-direction: column;
padding: 16px 16px;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body-nav {
flex-direction: row;
-webkit-overflow-scrolling: touch;
@@ -1389,6 +1417,9 @@ button::-moz-focus-inner {
padding-bottom: 8px;
padding-top: 8px;
}
.tox .tox-dialog__iframe.tox-dialog__iframe--opaque {
background: #fff;
}
.tox .tox-dialog__popups {
position: absolute;
width: 100%;
@@ -1421,12 +1452,12 @@ button::-moz-focus-inner {
.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein {
transition-delay: 0s;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav {
margin-right: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child) {
margin-left: 8px;
}
@@ -1438,12 +1469,12 @@ button::-moz-focus-inner {
.tox[dir=rtl] .tox-dialog__body {
text-align: right;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav {
margin-left: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child) {
margin-right: 8px;
}
@@ -1500,6 +1531,8 @@ body.tox-dialog__disable-scroll {
overflow: hidden;
}
.tox .tox-editor-header {
display: grid;
grid-template-columns: 1fr min-content;
z-index: 1;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header {
@@ -1581,8 +1614,7 @@ body.tox-dialog__disable-scroll {
max-width: 25em;
}
.tox .tox-autocompleter .tox-menu {
border-color: #eeeeee;
box-shadow: none;
box-sizing: border-box;
max-width: 25em;
}
.tox .tox-autocompleter .tox-autocompleter-highlight {
@@ -2073,6 +2105,12 @@ body.tox-dialog__disable-scroll {
.tox .tox-menu.tox-collection.tox-collection--grid {
padding: 8px;
}
@media only screen and (min-width: 768px ) {
.tox .tox-menu .tox-collection__item-label {
overflow-wrap: break-word;
word-break: normal;
}
}
.tox .tox-menu__label h1,
.tox .tox-menu__label h2,
.tox .tox-menu__label h3,
@@ -2085,16 +2123,45 @@ body.tox-dialog__disable-scroll {
margin: 0;
}
.tox .tox-menubar {
background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='transparent'/%3E%3C/svg%3E") left 0 top 0 #fff;
background: repeating-linear-gradient(transparent 0px 1px, transparent 1px 39px) center top 39px / 100% calc(100% - 39px) no-repeat;
background-color: #fff;
display: flex;
flex: 0 0 auto;
flex-shrink: 0;
flex-wrap: wrap;
grid-column: 1 / -1;
grid-row: 1;
padding: 0 11px 0 12px;
}
.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid transparent;
.tox .tox-promotion + .tox-menubar {
grid-column: 1;
}
.tox .tox-promotion {
background: repeating-linear-gradient(transparent 0px 1px, transparent 1px 39px) center top 39px / 100% calc(100% - 39px) no-repeat;
background-color: #fff;
grid-column: 2;
grid-row: 1;
padding-inline-end: 8px;
padding-inline-start: 4px;
padding-top: 5px;
}
.tox .tox-promotion-link {
align-items: unsafe center;
background-color: #E8F1F8;
border-radius: 5px;
color: #086BE6;
cursor: pointer;
display: flex;
font-size: 14px;
height: 26.6px;
padding: 4px 8px;
white-space: nowrap;
}
.tox .tox-promotion-link:hover {
background-color: #B4D7FF;
}
.tox .tox-promotion-link:focus {
background-color: #D9EDF7;
}
/* Deprecated. Remove in next major release */
.tox .tox-mbtn {
@@ -2874,10 +2941,14 @@ body.tox-dialog__disable-scroll {
.tox .tox-toolbar__overflow--shrinking {
transition: opacity 0.3s ease, height 0.2s linear 0.1s, visibility 0s linear 0.3s;
}
.tox .tox-toolbar-overlord,
.tox .tox-anchorbar {
grid-column: 1 / -1;
}
.tox .tox-menubar + .tox-toolbar,
.tox .tox-menubar + .tox-toolbar-overlord {
border-top: 1px solid transparent;
margin-top: 0px;
margin-top: -1px;
padding-bottom: 1px;
padding-top: 1px;
}
File diff suppressed because one or more lines are too long
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -186,6 +203,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -215,6 +253,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.3);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.3);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%20fill%3D%22%23cccccc%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -506,10 +551,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+98 -18
View File
@@ -252,11 +252,24 @@ button::-moz-focus-inner {
margin: 0;
outline: none;
padding: 4px 16px;
position: relative;
text-align: center;
text-decoration: none;
text-transform: none;
white-space: nowrap;
}
.tox .tox-button::before {
border-radius: 3px;
bottom: -1px;
box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #207ab7, 0 0 0 3px rgba(32, 122, 183, 0.25);
content: '';
left: -1px;
opacity: 0;
pointer-events: none;
position: absolute;
right: -1px;
top: -1px;
}
.tox .tox-button[disabled] {
background-color: #207ab7;
background-image: none;
@@ -272,6 +285,9 @@ button::-moz-focus-inner {
box-shadow: none;
color: #fff;
}
.tox .tox-button:focus-visible:not(:disabled)::before {
opacity: 1;
}
.tox .tox-button:hover:not(:disabled) {
background-color: #1c6ca1;
background-image: none;
@@ -933,8 +949,9 @@ button::-moz-focus-inner {
justify-content: space-between;
}
.tox .tox-comment__date {
color: rgba(255, 255, 255, 0.5);
color: #fff;
font-size: 12px;
line-height: 18px;
}
.tox .tox-comment__body {
color: #fff;
@@ -1093,20 +1110,30 @@ button::-moz-focus-inner {
.tox .tox-user__avatar svg {
fill: rgba(255, 255, 255, 0.5);
}
.tox .tox-user__avatar img {
border-radius: 50%;
height: 36px;
object-fit: cover;
vertical-align: middle;
width: 36px;
}
.tox .tox-user__name {
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
color: #fff;
font-size: 14px;
font-style: normal;
font-weight: bold;
text-transform: uppercase;
line-height: 18px;
text-transform: none;
}
.tox:not([dir=rtl]) .tox-user__avatar svg {
.tox:not([dir=rtl]) .tox-user__avatar svg,
.tox:not([dir=rtl]) .tox-user__avatar img {
margin-right: 8px;
}
.tox:not([dir=rtl]) .tox-user__avatar + .tox-user__name {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar svg {
.tox[dir=rtl] .tox-user__avatar svg,
.tox[dir=rtl] .tox-user__avatar img {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar + .tox-user__name {
@@ -1151,10 +1178,11 @@ button::-moz-focus-inner {
width: 95vw;
z-index: 2;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog {
align-self: flex-start;
margin: 8px auto;
max-height: calc(100vh - 8px * 2);
width: calc(100vw - 16px);
}
}
@@ -1210,7 +1238,7 @@ button::-moz-focus-inner {
text-align: left;
text-transform: none;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body {
flex-direction: column;
}
@@ -1221,7 +1249,7 @@ button::-moz-focus-inner {
flex-direction: column;
padding: 16px 16px;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body-nav {
flex-direction: row;
-webkit-overflow-scrolling: touch;
@@ -1389,6 +1417,9 @@ button::-moz-focus-inner {
padding-bottom: 8px;
padding-top: 8px;
}
.tox .tox-dialog__iframe.tox-dialog__iframe--opaque {
background: #fff;
}
.tox .tox-dialog__popups {
position: absolute;
width: 100%;
@@ -1421,12 +1452,12 @@ button::-moz-focus-inner {
.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein {
transition-delay: 0s;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav {
margin-right: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child) {
margin-left: 8px;
}
@@ -1438,12 +1469,12 @@ button::-moz-focus-inner {
.tox[dir=rtl] .tox-dialog__body {
text-align: right;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav {
margin-left: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child) {
margin-right: 8px;
}
@@ -1500,6 +1531,8 @@ body.tox-dialog__disable-scroll {
overflow: hidden;
}
.tox .tox-editor-header {
display: grid;
grid-template-columns: 1fr min-content;
z-index: 1;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header {
@@ -1581,8 +1614,7 @@ body.tox-dialog__disable-scroll {
max-width: 25em;
}
.tox .tox-autocompleter .tox-menu {
border-color: #000000;
box-shadow: none;
box-sizing: border-box;
max-width: 25em;
}
.tox .tox-autocompleter .tox-autocompleter-highlight {
@@ -2073,6 +2105,12 @@ body.tox-dialog__disable-scroll {
.tox .tox-menu.tox-collection.tox-collection--grid {
padding: 4px;
}
@media only screen and (min-width: 768px ) {
.tox .tox-menu .tox-collection__item-label {
overflow-wrap: break-word;
word-break: normal;
}
}
.tox .tox-menu__label h1,
.tox .tox-menu__label h2,
.tox .tox-menu__label h3,
@@ -2091,10 +2129,39 @@ body.tox-dialog__disable-scroll {
flex: 0 0 auto;
flex-shrink: 0;
flex-wrap: wrap;
grid-column: 1 / -1;
grid-row: 1;
padding: 0 4px 0 4px;
}
.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid #000000;
.tox .tox-promotion + .tox-menubar {
grid-column: 1;
}
.tox .tox-promotion {
background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;
background-color: #222f3e;
grid-column: 2;
grid-row: 1;
padding-inline-end: 8px;
padding-inline-start: 4px;
padding-top: 5px;
}
.tox .tox-promotion-link {
align-items: unsafe center;
background-color: #E8F1F8;
border-radius: 5px;
color: #086BE6;
cursor: pointer;
display: flex;
font-size: 14px;
height: 26.6px;
padding: 4px 8px;
white-space: nowrap;
}
.tox .tox-promotion-link:hover {
background-color: #B4D7FF;
}
.tox .tox-promotion-link:focus {
background-color: #D9EDF7;
}
/* Deprecated. Remove in next major release */
.tox .tox-mbtn {
@@ -2874,10 +2941,14 @@ body.tox-dialog__disable-scroll {
.tox .tox-toolbar__overflow--shrinking {
transition: opacity 0.3s ease, height 0.2s linear 0.1s, visibility 0s linear 0.3s;
}
.tox .tox-toolbar-overlord,
.tox .tox-anchorbar {
grid-column: 1 / -1;
}
.tox .tox-menubar + .tox-toolbar,
.tox .tox-menubar + .tox-toolbar-overlord {
border-top: 1px solid #000000;
margin-top: 0;
margin-top: -1px;
padding-bottom: 0px;
padding-top: 0px;
}
@@ -3087,6 +3158,12 @@ body.tox-dialog__disable-scroll {
border: 1px solid #000000;
padding: 0;
}
.tox .tox-pop .tox-pop__dialog .tox-toolbar {
padding: 0;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid #000000;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar-overlord:first-child .tox-toolbar__primary,
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar:first-child {
border-top: 1px solid #000000;
@@ -3117,3 +3194,6 @@ body.tox-dialog__disable-scroll {
padding-bottom: 0;
padding-right: 0;
}
.tox .tox-button::before {
display: none;
}
File diff suppressed because one or more lines are too long
+51 -6
View File
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
@@ -21,11 +21,28 @@
.mce-content-body .mce-item-anchor[data-mce-selected] {
outline-offset: 1px;
}
.tox-comments-visible .tox-comment {
background-color: #fff0b7;
.tox-comments-visible .tox-comment[contenteditable="false"]:not([data-mce-selected]),
.tox-comments-visible span.tox-comment img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #ffe89d;
}
.tox-comments-visible .tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #ffe168;
.tox-comments-visible .tox-comment[contenteditable="false"][data-mce-annotation-active="true"]:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] img:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > audio:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] > video:not([data-mce-selected]),
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"] span.mce-preview-object:not([data-mce-selected]) {
outline: 3px solid #fed635;
}
.tox-comments-visible span.tox-comment:not([data-mce-selected]) {
background-color: #ffe89d;
outline: none;
}
.tox-comments-visible span.tox-comment[data-mce-annotation-active="true"]:not([data-mce-selected="inline-boundary"]) {
background-color: #fed635;
}
.tox-checklist > li:not(.tox-checklist--hidden) {
list-style: none;
@@ -205,6 +222,27 @@ pre[class*="language-"] {
.tox-cursor-format-painter {
cursor: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"), default;
}
div.mce-footnotes hr {
margin-inline-end: auto;
margin-inline-start: 0;
width: 25%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
text-decoration: none;
}
@media print {
sup.mce-footnote a {
color: black;
text-decoration: none;
}
div.mce-footnotes {
break-inside: avoid;
width: 100%;
}
div.mce-footnotes li > a.mce-footnotes-backlink {
display: none;
}
}
.mce-content-body figure.align-left {
float: left;
}
@@ -234,6 +272,13 @@ pre[class*="language-"] {
.mce-preview-object[data-mce-selected="2"] .mce-shim {
display: none;
}
.mce-content-body .mce-mergetag:hover {
background-color: rgba(0, 108, 231, 0.1);
}
.mce-content-body .mce-mergetag-affix {
background-color: rgba(0, 108, 231, 0.1);
color: #006ce7;
}
.mce-object {
background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;
border: 1px dashed #aaa;
@@ -525,10 +570,10 @@ pre[class*="language-"] {
border-color: rgba(0, 84, 180, 0.7);
}
}
.mce-content-body img::-moz-selection {
.mce-content-body img[data-mce-selected]::-moz-selection {
background: none;
}
.mce-content-body img::selection {
.mce-content-body img[data-mce-selected]::selection {
background: none;
}
.ephox-snooker-resizer-bar {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+99 -19
View File
@@ -252,11 +252,24 @@ button::-moz-focus-inner {
margin: 0;
outline: none;
padding: 4px 16px;
position: relative;
text-align: center;
text-decoration: none;
text-transform: none;
white-space: nowrap;
}
.tox .tox-button::before {
border-radius: 3px;
bottom: -1px;
box-shadow: inset 0 0 0 2px #fff, 0 0 0 1px #207ab7, 0 0 0 3px rgba(32, 122, 183, 0.25);
content: '';
left: -1px;
opacity: 0;
pointer-events: none;
position: absolute;
right: -1px;
top: -1px;
}
.tox .tox-button[disabled] {
background-color: #207ab7;
background-image: none;
@@ -272,6 +285,9 @@ button::-moz-focus-inner {
box-shadow: none;
color: #fff;
}
.tox .tox-button:focus-visible:not(:disabled)::before {
opacity: 1;
}
.tox .tox-button:hover:not(:disabled) {
background-color: #1c6ca1;
background-image: none;
@@ -933,8 +949,9 @@ button::-moz-focus-inner {
justify-content: space-between;
}
.tox .tox-comment__date {
color: rgba(34, 47, 62, 0.7);
color: #222f3e;
font-size: 12px;
line-height: 18px;
}
.tox .tox-comment__body {
color: #222f3e;
@@ -1093,20 +1110,30 @@ button::-moz-focus-inner {
.tox .tox-user__avatar svg {
fill: rgba(34, 47, 62, 0.7);
}
.tox .tox-user__avatar img {
border-radius: 50%;
height: 36px;
object-fit: cover;
vertical-align: middle;
width: 36px;
}
.tox .tox-user__name {
color: rgba(34, 47, 62, 0.7);
font-size: 12px;
color: #222f3e;
font-size: 14px;
font-style: normal;
font-weight: bold;
text-transform: uppercase;
line-height: 18px;
text-transform: none;
}
.tox:not([dir=rtl]) .tox-user__avatar svg {
.tox:not([dir=rtl]) .tox-user__avatar svg,
.tox:not([dir=rtl]) .tox-user__avatar img {
margin-right: 8px;
}
.tox:not([dir=rtl]) .tox-user__avatar + .tox-user__name {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar svg {
.tox[dir=rtl] .tox-user__avatar svg,
.tox[dir=rtl] .tox-user__avatar img {
margin-left: 8px;
}
.tox[dir=rtl] .tox-user__avatar + .tox-user__name {
@@ -1151,10 +1178,11 @@ button::-moz-focus-inner {
width: 95vw;
z-index: 2;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog {
align-self: flex-start;
margin: 8px auto;
max-height: calc(100vh - 8px * 2);
width: calc(100vw - 16px);
}
}
@@ -1210,7 +1238,7 @@ button::-moz-focus-inner {
text-align: left;
text-transform: none;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body {
flex-direction: column;
}
@@ -1221,7 +1249,7 @@ button::-moz-focus-inner {
flex-direction: column;
padding: 16px 16px;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox .tox-dialog__body-nav {
flex-direction: row;
-webkit-overflow-scrolling: touch;
@@ -1389,6 +1417,9 @@ button::-moz-focus-inner {
padding-bottom: 8px;
padding-top: 8px;
}
.tox .tox-dialog__iframe.tox-dialog__iframe--opaque {
background: #fff;
}
.tox .tox-dialog__popups {
position: absolute;
width: 100%;
@@ -1421,12 +1452,12 @@ button::-moz-focus-inner {
.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein {
transition-delay: 0s;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav {
margin-right: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child) {
margin-left: 8px;
}
@@ -1438,12 +1469,12 @@ button::-moz-focus-inner {
.tox[dir=rtl] .tox-dialog__body {
text-align: right;
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav {
margin-left: 0;
}
}
@media only screen and (max-width:767px) {
@media only screen and (max-width: 767px ) {
body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child) {
margin-right: 8px;
}
@@ -1500,6 +1531,8 @@ body.tox-dialog__disable-scroll {
overflow: hidden;
}
.tox .tox-editor-header {
display: grid;
grid-template-columns: 1fr min-content;
z-index: 1;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header {
@@ -1510,7 +1543,7 @@ body.tox-dialog__disable-scroll {
transition: box-shadow 0.5s;
}
.tox:not(.tox-tinymce-inline).tox-tinymce--toolbar-bottom .tox-editor-header {
border-top: 1px solid #c1c1c1;
border-top: 1px solid #cccccc;
box-shadow: none;
}
.tox:not(.tox-tinymce-inline).tox-tinymce--toolbar-sticky-on .tox-editor-header {
@@ -1581,8 +1614,7 @@ body.tox-dialog__disable-scroll {
max-width: 25em;
}
.tox .tox-autocompleter .tox-menu {
border-color: #cccccc;
box-shadow: none;
box-sizing: border-box;
max-width: 25em;
}
.tox .tox-autocompleter .tox-autocompleter-highlight {
@@ -2073,6 +2105,12 @@ body.tox-dialog__disable-scroll {
.tox .tox-menu.tox-collection.tox-collection--grid {
padding: 4px;
}
@media only screen and (min-width: 768px ) {
.tox .tox-menu .tox-collection__item-label {
overflow-wrap: break-word;
word-break: normal;
}
}
.tox .tox-menu__label h1,
.tox .tox-menu__label h2,
.tox .tox-menu__label h3,
@@ -2091,10 +2129,39 @@ body.tox-dialog__disable-scroll {
flex: 0 0 auto;
flex-shrink: 0;
flex-wrap: wrap;
grid-column: 1 / -1;
grid-row: 1;
padding: 0 4px 0 4px;
}
.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid #cccccc;
.tox .tox-promotion + .tox-menubar {
grid-column: 1;
}
.tox .tox-promotion {
background: url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;
background-color: #fff;
grid-column: 2;
grid-row: 1;
padding-inline-end: 8px;
padding-inline-start: 4px;
padding-top: 5px;
}
.tox .tox-promotion-link {
align-items: unsafe center;
background-color: #E8F1F8;
border-radius: 5px;
color: #086BE6;
cursor: pointer;
display: flex;
font-size: 14px;
height: 26.6px;
padding: 4px 8px;
white-space: nowrap;
}
.tox .tox-promotion-link:hover {
background-color: #B4D7FF;
}
.tox .tox-promotion-link:focus {
background-color: #D9EDF7;
}
/* Deprecated. Remove in next major release */
.tox .tox-mbtn {
@@ -2874,10 +2941,14 @@ body.tox-dialog__disable-scroll {
.tox .tox-toolbar__overflow--shrinking {
transition: opacity 0.3s ease, height 0.2s linear 0.1s, visibility 0s linear 0.3s;
}
.tox .tox-toolbar-overlord,
.tox .tox-anchorbar {
grid-column: 1 / -1;
}
.tox .tox-menubar + .tox-toolbar,
.tox .tox-menubar + .tox-toolbar-overlord {
border-top: 1px solid #cccccc;
margin-top: 0;
margin-top: -1px;
padding-bottom: 0px;
padding-top: 0px;
}
@@ -3087,6 +3158,12 @@ body.tox-dialog__disable-scroll {
border: 1px solid #cccccc;
padding: 0;
}
.tox .tox-pop .tox-pop__dialog .tox-toolbar {
padding: 0;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar {
border-top: 1px solid #cccccc;
}
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar-overlord:first-child .tox-toolbar__primary,
.tox:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar:first-child {
border-top: 1px solid #cccccc;
@@ -3117,3 +3194,6 @@ body.tox-dialog__disable-scroll {
padding-bottom: 0;
padding-right: 0;
}
.tox .tox-button::before {
display: none;
}
File diff suppressed because one or more lines are too long
+9 -10
View File
@@ -14,27 +14,28 @@ const buttonConfig = ref({
// 侧边栏主导航当前实际宽度
const mainSidebarActualWidth = computed(() => {
let actualWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--g-main-sidebar-width'))
if (['head', 'single'].includes(settingsStore.menu.menuMode))
if (['head', 'single'].includes(settingsStore.menu.menuMode)) {
actualWidth = 0
}
return `${actualWidth}px`
})
// 侧边栏次导航当前实际宽度
const subSidebarActualWidth = computed(() => {
let actualWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--g-sub-sidebar-width'))
if (settingsStore.menu.subMenuCollapse)
if (settingsStore.menu.subMenuCollapse) {
actualWidth = 64
}
return `${actualWidth}px`
})
watch(() => settingsStore.app.colorScheme, () => {
if (settingsStore.app.colorScheme === 'dark')
if (settingsStore.app.colorScheme === 'dark') {
document.documentElement.classList.add('dark')
else
}
else {
document.documentElement.classList.remove('dark')
}
}, {
immediate: true,
})
@@ -66,14 +67,12 @@ watch([
() => settingsStore.title,
], () => {
if (settingsStore.app.enableDynamicTitle && settingsStore.title) {
const title = settingsStore.title
const title = typeof settingsStore.title === 'function' ? settingsStore.title() : settingsStore.title
document.title = `${title} - ${import.meta.env.VITE_APP_TITLE}`
}
else {
document.title = import.meta.env.VITE_APP_TITLE
}
}, {
immediate: true,
})
onMounted(() => {
+13 -14
View File
@@ -1,9 +1,11 @@
import axios from 'axios'
// import qs from 'qs'
import { ElMessage } from 'element-plus'
import router from '@/router/index'
import useUserStore from '@/store/modules/user'
const toLogin = () => {
useUserStore().logout()
router.push({
path: '/login',
query: {
@@ -14,7 +16,7 @@ const toLogin = () => {
const api = axios.create({
baseURL: import.meta.env.DEV && import.meta.env.VITE_OPEN_PROXY === 'true' ? '/proxy/' : import.meta.env.VITE_APP_API_BASEURL,
timeout: 10000,
timeout: 1000 * 60,
responseType: 'json',
})
@@ -25,9 +27,9 @@ api.interceptors.request.use(
* 全局拦截请求发送前提交的参数
* 以下代码为示例,在请求头里带上 token 信息
*/
if (userStore.isLogin && request.headers)
if (userStore.isLogin && request.headers) {
request.headers.Token = userStore.token
}
// 是否将 POST 请求参数进行字符串化处理
if (request.method === 'post') {
// request.data = qs.stringify(request.data, {
@@ -47,11 +49,7 @@ api.interceptors.response.use(
* 请求出错时 error 会返回错误信息
*/
if (response.data.status === 1) {
if (response.data.error === '') {
// 请求成功并且没有报错
return Promise.resolve(response.data)
}
else {
if (response.data.error !== '') {
// 这里做错误提示,如果使用了 element plus 则可以使用 Message 进行提示
// ElMessage.error(options)
return Promise.reject(response.data)
@@ -60,18 +58,19 @@ api.interceptors.response.use(
else {
toLogin()
}
return Promise.resolve(response.data)
},
(error) => {
let message = error.message
if (message === 'Network Error')
if (message === 'Network Error') {
message = '后端网络故障'
else if (message.includes('timeout'))
}
else if (message.includes('timeout')) {
message = '接口请求超时'
else if (message.includes('Request failed with status code'))
}
else if (message.includes('Request failed with status code')) {
message = `接口${message.substr(message.length - 3)}异常`
}
ElMessage({
message,
type: 'error',
-1
View File
@@ -6,5 +6,4 @@
"overlay": #1d1e1f,
)
);
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
@@ -5,6 +5,5 @@
// )
// )
// );
@use "element-plus/theme-chalk/src/index.scss" as *;
@use "./dark.scss";
+4
View File
@@ -82,3 +82,7 @@ textarea {
margin-left: 10px;
}
}
.el-loading-mask {
z-index: 900 !important;
}
+5 -7
View File
@@ -1,12 +1,10 @@
// 文字超出隐藏,默认为单行超出隐藏,可设置多行
@mixin text-overflow($line: 1, $fixed-width: true) {
@if ($line == 1 and $fixed-width == true) {
@if $line == 1 and $fixed-width == true {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@else {
} @else {
/* stylelint-disable-next-line value-no-vendor-prefix */
display: -webkit-box;
-webkit-box-orient: vertical;
@@ -19,17 +17,17 @@
@mixin position-center($type: x) {
position: absolute;
@if ($type == x) {
@if $type == x {
left: 50%;
transform: translateX(-50%);
}
@if ($type == y) {
@if $type == y {
top: 50%;
transform: translateY(-50%);
}
@if ($type == xy) {
@if $type == xy {
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
+5 -2
View File
@@ -2,7 +2,6 @@
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
@@ -30,6 +29,8 @@ declare global {
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
@@ -46,6 +47,7 @@ declare global {
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const shallowReactive: typeof import('vue')['shallowReactive']
@@ -61,7 +63,8 @@ declare global {
const useAuth: typeof import('./utils/composables/useAuth')['default']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentInstance: typeof import('./utils/composables/useCurrentInstance')['default']
const useGlobalProperties: typeof import('./utils/composables/useGlobalProperties')['default']
const useLink: typeof import('vue-router')['useLink']
const useMainPage: typeof import('./utils/composables/useMainPage')['default']
const useMenu: typeof import('./utils/composables/useMenu')['default']
const useRoute: typeof import('vue-router')['useRoute']
+4 -4
View File
@@ -15,9 +15,9 @@ const emit = defineEmits(['checkAll', 'checkNull'])
const checkAll = computed({
get() {
let flag = false
if (props.data.length !== 0 && props.data.length === props.selectionData.length)
if (props.data.length !== 0 && props.data.length === props.selectionData.length) {
flag = true
}
return flag
},
set(newVal) {
@@ -27,9 +27,9 @@ const checkAll = computed({
const isIndeterminate = computed(() => {
let flag = false
if (props.selectionData.length > 0 && props.selectionData.length < props.data.length)
if (props.selectionData.length > 0 && props.selectionData.length < props.data.length) {
flag = true
}
return flag
})
</script>
+5 -5
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup name="FileUpload">
import { UploadUserFile } from 'element-plus'
import { ElMessage, UploadUserFile } from 'element-plus'
import type { UploadProps } from 'element-plus'
const props = defineProps({
@@ -48,12 +48,12 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传文件只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传文件大小不能超过 ${props.size}MB!`)
}
return isTypeOk && isSizeOk
}
+7 -6
View File
@@ -1,5 +1,6 @@
<script lang="ts" setup name="ImageUpload">
import type { UploadProps } from 'element-plus'
import { ElMessage } from 'element-plus'
const props = defineProps({
action: {
@@ -75,15 +76,15 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传图片只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)
if (isTypeOk && isSizeOk)
}
if (isTypeOk && isSizeOk) {
uploadData.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
const onProgress: UploadProps['onProgress'] = (file) => {
+11 -10
View File
@@ -1,5 +1,6 @@
<script lang="ts" setup name="ImagesUpload">
import type { UploadProps } from 'element-plus'
import { ElMessage } from 'element-plus'
const props = defineProps({
action: {
@@ -81,12 +82,12 @@ function remove(index: number) {
// 移动
function move(index: number, type: 'left' | 'right') {
const url = props.url
if (type === 'left' && index !== 0)
if (type === 'left' && index !== 0) {
url[index] = url.splice(index - 1, 1, url[index])[0]
if (type === 'right' && index !== url.length - 1)
}
if (type === 'right' && index !== url.length - 1) {
url[index] = url.splice(index + 1, 1, url[index])[0]
}
emit('update:url', url)
}
@@ -95,15 +96,15 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const fileExt = fileName.at(-1)
const isTypeOk = props.ext.includes(fileExt)
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk)
if (!isTypeOk) {
ElMessage.error(`上传图片只支持 ${props.ext.join(' / ')} 格式!`)
if (!isSizeOk)
}
if (!isSizeOk) {
ElMessage.error(`上传图片大小不能超过 ${props.size}MB!`)
if (isTypeOk && isSizeOk)
}
if (isTypeOk && isSizeOk) {
uploadData.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
const onProgress: UploadProps['onProgress'] = (file) => {
+14 -1
View File
@@ -9,6 +9,8 @@ defineProps({
default: '',
},
})
const slots = useSlots()
</script>
<template>
@@ -23,7 +25,7 @@ defineProps({
</slot>
</div>
</div>
<div class="sub">
<div v-if="slots.default" class="sub">
<slot />
</div>
</div>
@@ -65,4 +67,15 @@ defineProps({
flex: none;
}
}
[data-mode="mobile"] {
.header {
flex-direction: column;
.main {
margin-right: auto;
margin-bottom: 20px;
}
}
}
</style>
+10 -7
View File
@@ -91,18 +91,20 @@ function anyToCode(value: any[], dictionarie: any[] = pcasData.value) {
const input: string[] = []
if (value.length > 0) {
const findItem = dictionarie.find((item) => {
if (props.format === 'code')
if (props.format === 'code') {
return item.code === value[0]
else if (props.format === 'name')
}
else if (props.format === 'name') {
return item.name === value[0]
else
}
else {
return item.name === value[0].name && item.code === value[0].code
}
})
input.push(findItem.code)
if (findItem.children)
if (findItem.children) {
input.push(...anyToCode(value.slice(1 - value.length), findItem.children))
}
}
return input
}
@@ -125,8 +127,9 @@ function codeToAny(codes: string[], dictionarie: any[] = pcasData.value): any {
})
}
const newCodes = codes.slice(1 - codes.length)
if (newCodes.length > 0 && findItem.children)
if (newCodes.length > 0 && findItem.children) {
output.push(...codeToAny(newCodes, findItem.children))
}
}
return output
}
+2 -2
View File
@@ -32,9 +32,9 @@ const transformStyle = computed(() => {
break
}
}
if (props.rotate !== 0)
if (props.rotate !== 0) {
style.push(`rotate(${props.rotate}deg)`)
}
return `transform: ${style.join(' ')};`
})
</script>
+2 -2
View File
@@ -24,9 +24,9 @@ const props = defineProps({
const isUp = computed(() => {
let isUp = props.type === 'up'
if (props.reverse)
if (props.reverse) {
isUp = !isUp
}
return isUp
})
</script>
+15 -16
View File
@@ -4,6 +4,9 @@ import type { RouteRecordRaw, RouteMeta, NavigationGuard } from 'vue-router'
type RecursiveRequired<T> = {
[P in keyof T]-?: RecursiveRequired<T[P]>
}
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>
}
declare namespace Settings {
interface app {
@@ -49,15 +52,15 @@ declare namespace Settings {
*/
routeBaseOn?: 'frontend' | 'backend' | 'filesystem'
}
interface dashboard {
interface home {
/**
* 是否开启控制台页面
* 是否开启主页页面
* @默认值 `true`
*/
enable?: boolean
/**
* 控制台名称
* @默认值 `'控制台'`
* 主页名称
* @默认值 `'主页'`
*/
title?: string
}
@@ -186,8 +189,8 @@ declare namespace Settings {
interface all {
/** 应用设置 */
app?: app
/** 控制台设置 */
dashboard?: dashboard
/** 主页设置 */
home?: home
/** 布局设置 */
layout?: layout
/** 导航栏设置 */
@@ -207,7 +210,7 @@ declare namespace Settings {
declare module 'vue-router' {
interface RouteMeta {
title: string | Function
title?: string | Function
i18n?: string
icon?: string
activeIcon?: string
@@ -222,12 +225,8 @@ declare module 'vue-router' {
}
declare namespace Route {
interface recordRaw extends Omit<RouteRecordRaw, 'meta' | 'children'> {
meta: RouteMeta
children?: recordRaw[]
}
interface recordMainRaw {
meta: {
meta?: {
title?: string | Function
icon?: string
auth?: string | string[]
@@ -236,7 +235,7 @@ declare namespace Route {
}
interface breadcrumb {
path: string
title: string | Function
title?: string | Function
hide: boolean
}
}
@@ -245,8 +244,8 @@ declare namespace Menu {
/** 原始 */
interface recordRaw {
path?: string
meta: {
title: string
meta?: {
title?: string
icon?: string
defaultOpened?: boolean
auth?: string | string[]
@@ -256,7 +255,7 @@ declare namespace Menu {
}
/** 主导航 */
interface recordMainRaw {
meta: {
meta?: {
title?: string
icon?: string
auth?: string | string[]
+47 -42
View File
@@ -1,9 +1,10 @@
<script lang="ts" setup name="AppSetting">
import { useClipboard } from '@vueuse/core'
import { ElMessage } from 'element-plus'
import { cloneDeep } from 'lodash-es'
import eventBus from '@/utils/eventBus'
import useSettingsStore from '@/store/modules/settings'
import useMenuStore from '@/store/modules/menu'
import globalSettingsDefault from '@/settings.default'
const route = useRoute()
@@ -12,14 +13,13 @@ const menuStore = useMenuStore()
const isShow = ref(false)
const settings = ref(globalSettingsDefault)
watch(() => settings, () => {
settingsStore.updateSettings(settings.value)
menuStore.setActived(0)
settings.value.menu.menuMode !== 'single' && menuStore.setActived(route.fullPath)
}, {
deep: true,
watch(() => settingsStore.menu.menuMode, (value) => {
if (value === 'single') {
menuStore.setActived(0)
}
else {
menuStore.setActived(route.fullPath)
}
})
onMounted(() => {
@@ -31,12 +31,17 @@ onMounted(() => {
const { copy, copied, isSupported } = useClipboard()
watch(copied, (val) => {
if (val)
if (val) {
ElMessage.success('复制成功,请粘贴到 src/settings.ts 文件中!')
}
})
function handleCopy() {
copy(JSON.stringify(settings.value, null, 4))
const settings: any = cloneDeep(settingsStore.$state)
delete settings.subMenuCollapseLastStatus
delete settings.mode
delete settings.title
copy(JSON.stringify(settings, null, 2))
}
</script>
@@ -46,9 +51,9 @@ function handleCopy() {
<el-alert title="应用配置可实时预览效果,但只是临时生效,要想真正作用于项目,可以点击下方的“复制配置”按钮,并将配置粘贴到 src/settings.ts 文件中。同时建议在生产环境隐藏应用配置功能。" type="error" :closable="false" />
<el-divider>颜色主题</el-divider>
<div class="color-scheme">
<div class="switch" :class="settings.app.colorScheme" @click="settings.app.colorScheme = settings.app.colorScheme === 'dark' ? 'light' : 'dark'">
<div class="switch" :class="settingsStore.app.colorScheme" @click="settingsStore.app.colorScheme = settingsStore.app.colorScheme === 'dark' ? 'light' : 'dark'">
<el-icon class="icon">
<svg-icon :name="settings.app.colorScheme === 'light' ? 'ep:sunny' : 'ep:moon'" />
<svg-icon :name="settingsStore.app.colorScheme === 'light' ? 'ep:sunny' : 'ep:moon'" />
</el-icon>
</div>
</div>
@@ -57,7 +62,7 @@ function handleCopy() {
</el-divider>
<div v-if="settingsStore.mode === 'pc'" class="menu-mode">
<el-tooltip content="侧边栏模式(含主导航)" placement="top" :show-after="500">
<div class="mode mode-side" :class="{ active: settings.menu.menuMode === 'side' }" @click="settings.menu.menuMode = 'side'">
<div class="mode mode-side" :class="{ active: settingsStore.menu.menuMode === 'side' }" @click="settingsStore.menu.menuMode = 'side'">
<div class="mode-container" />
<el-icon>
<svg-icon name="ep:check" />
@@ -65,7 +70,7 @@ function handleCopy() {
</div>
</el-tooltip>
<el-tooltip content="顶部模式" placement="top" :show-after="500">
<div class="mode mode-head" :class="{ active: settings.menu.menuMode === 'head' }" @click="settings.menu.menuMode = 'head'">
<div class="mode mode-head" :class="{ active: settingsStore.menu.menuMode === 'head' }" @click="settingsStore.menu.menuMode = 'head'">
<div class="mode-container" />
<el-icon>
<svg-icon name="ep:check" />
@@ -73,7 +78,7 @@ function handleCopy() {
</div>
</el-tooltip>
<el-tooltip content="侧边栏模式(不含主导航)" placement="top" :show-after="500">
<div class="mode mode-single" :class="{ active: settings.menu.menuMode === 'single' }" @click="settings.menu.menuMode = 'single'">
<div class="mode mode-single" :class="{ active: settingsStore.menu.menuMode === 'single' }" @click="settingsStore.menu.menuMode = 'single'">
<div class="mode-container" />
<el-icon>
<svg-icon name="ep:check" />
@@ -91,7 +96,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.menu.switchMainMenuAndPageJump" :disabled="['single'].includes(settings.menu.menuMode)" />
<el-switch v-model="settingsStore.menu.switchMainMenuAndPageJump" :disabled="['single'].includes(settingsStore.menu.menuMode)" />
</div>
<div class="setting-item">
<div class="label">
@@ -102,32 +107,32 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.menu.subMenuUniqueOpened" />
<el-switch v-model="settingsStore.menu.subMenuUniqueOpened" />
</div>
<div class="setting-item">
<div class="label">
次导航是否折叠
</div>
<el-switch v-model="settings.menu.subMenuCollapse" />
<el-switch v-model="settingsStore.menu.subMenuCollapse" />
</div>
<div v-if="settingsStore.mode === 'pc'" class="setting-item">
<div class="label">
显示次导航折叠按钮
</div>
<el-switch v-model="settings.menu.enableSubMenuCollapseButton" />
<el-switch v-model="settingsStore.menu.enableSubMenuCollapseButton" />
</div>
<div class="setting-item">
<div class="label">
是否启用快捷键
</div>
<el-switch v-model="settings.menu.enableHotkeys" :disabled="['single'].includes(settingsStore.menu.menuMode)" />
<el-switch v-model="settingsStore.menu.enableHotkeys" :disabled="['single'].includes(settingsStore.menu.menuMode)" />
</div>
<el-divider>顶栏</el-divider>
<div class="setting-item">
<div class="label">
是否固定
</div>
<el-switch v-model="settings.topbar.fixed" />
<el-switch v-model="settingsStore.topbar.fixed" />
</div>
<el-divider>工具栏</el-divider>
<div v-if="settingsStore.mode === 'pc'" class="setting-item">
@@ -139,7 +144,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.toolbar.enableFullscreen" />
<el-switch v-model="settingsStore.toolbar.enableFullscreen" />
</div>
<div class="setting-item">
<div class="label">
@@ -150,7 +155,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.toolbar.enablePageReload" />
<el-switch v-model="settingsStore.toolbar.enablePageReload" />
</div>
<div class="setting-item">
<div class="label">
@@ -161,7 +166,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.toolbar.enableColorScheme" />
<el-switch v-model="settingsStore.toolbar.enableColorScheme" />
</div>
<el-divider v-if="settingsStore.mode === 'pc'">
面包屑导航
@@ -170,7 +175,7 @@ function handleCopy() {
<div class="label">
是否启用
</div>
<el-switch v-model="settings.breadcrumb.enable" />
<el-switch v-model="settingsStore.breadcrumb.enable" />
</div>
<el-divider>导航搜索</el-divider>
<div class="setting-item">
@@ -182,62 +187,62 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.navSearch.enable" />
<el-switch v-model="settingsStore.navSearch.enable" />
</div>
<div class="setting-item">
<div class="label">
是否启用快捷键
</div>
<el-switch v-model="settings.navSearch.enableHotkeys" :disabled="!settings.navSearch.enable" />
<el-switch v-model="settingsStore.navSearch.enableHotkeys" :disabled="!settingsStore.navSearch.enable" />
</div>
<el-divider>底部版权</el-divider>
<div class="setting-item">
<div class="label">
是否启用
</div>
<el-switch v-model="settings.copyright.enable" />
<el-switch v-model="settingsStore.copyright.enable" />
</div>
<div class="setting-item">
<div class="label">
日期
</div>
<el-input v-model="settings.copyright.dates" size="small" :disabled="!settings.copyright.enable" />
<el-input v-model="settingsStore.copyright.dates" size="small" :disabled="!settingsStore.copyright.enable" />
</div>
<div class="setting-item">
<div class="label">
公司
</div>
<el-input v-model="settings.copyright.company" size="small" :disabled="!settings.copyright.enable" />
<el-input v-model="settingsStore.copyright.company" size="small" :disabled="!settingsStore.copyright.enable" />
</div>
<div class="setting-item">
<div class="label">
网址
</div>
<el-input v-model="settings.copyright.website" size="small" :disabled="!settings.copyright.enable" />
<el-input v-model="settingsStore.copyright.website" size="small" :disabled="!settingsStore.copyright.enable" />
</div>
<div class="setting-item">
<div class="label">
备案
</div>
<el-input v-model="settings.copyright.beian" size="small" :disabled="!settings.copyright.enable" />
<el-input v-model="settingsStore.copyright.beian" size="small" :disabled="!settingsStore.copyright.enable" />
</div>
<el-divider>控制台</el-divider>
<el-divider>主页</el-divider>
<div class="setting-item">
<div class="label">
是否开启
<el-tooltip content="该功能开启时,登录成功默认进入控制台页面,反之则默认进入导航栏里第一个导航页面" placement="top">
<el-tooltip content="该功能开启时,登录成功默认进入主页,反之则默认进入导航栏里第一个导航页面" placement="top">
<el-icon>
<svg-icon name="ep:question-filled" />
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.dashboard.enable" />
<el-switch v-model="settingsStore.home.enable" />
</div>
<div class="setting-item">
<div class="label">
控制台名称
主页名称
</div>
<el-input v-model="settings.dashboard.title" size="small" />
<el-input v-model="settingsStore.home.title" size="small" />
</div>
<el-divider>其它</el-divider>
<div class="setting-item">
@@ -249,7 +254,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-radio-group v-model="settings.app.elementSize" size="small">
<el-radio-group v-model="settingsStore.app.elementSize" size="small">
<el-radio-button label="large">
较大
</el-radio-button>
@@ -265,7 +270,7 @@ function handleCopy() {
<div class="label">
是否启用权限
</div>
<el-switch v-model="settings.app.enablePermission" />
<el-switch v-model="settingsStore.app.enablePermission" />
</div>
<div class="setting-item">
<div class="label">
@@ -276,7 +281,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.app.enableProgress" />
<el-switch v-model="settingsStore.app.enableProgress" />
</div>
<div class="setting-item">
<div class="label">
@@ -287,7 +292,7 @@ function handleCopy() {
</el-icon>
</el-tooltip>
</div>
<el-switch v-model="settings.app.enableDynamicTitle" />
<el-switch v-model="settingsStore.app.enableDynamicTitle" />
</div>
<template v-if="isSupported" #footer>
<el-button type="primary" @click="handleCopy">
+3 -3
View File
@@ -30,10 +30,10 @@ function handlerMouserScroll(event: WheelEvent) {
<template v-for="(item, index) in menuStore.allMenus" :key="index">
<div v-if="item.children && item.children.length !== 0" class="item-container" :class="{ active: index === menuStore.actived }">
<div class="item" @click="switchTo(index)">
<el-icon>
<svg-icon v-if="item.meta.icon" :name="item.meta.icon" />
<el-icon v-if="item.meta?.icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span v-if="item.meta.title">{{ item.meta.title }}</span>
<span v-if="item.meta?.title">{{ item.meta.title }}</span>
</div>
</div>
</template>
+5 -4
View File
@@ -22,15 +22,15 @@ const to = computed(() => {
const rtn: {
name?: string
} = {}
if (settingsStore.dashboard.enable)
rtn.name = 'dashboard'
if (settingsStore.home.enable) {
rtn.name = 'home'
}
return rtn
})
</script>
<template>
<router-link :to="to" class="title" :class="{ 'is-link': settingsStore.dashboard.enable }" :title="title">
<router-link :to="to" class="title" :class="{ 'is-link': settingsStore.home.enable }" :title="title">
<img v-if="showLogo" :src="logo" class="logo">
<span v-if="showTitle">{{ title }}</span>
</router-link>
@@ -58,6 +58,7 @@ const to = computed(() => {
.logo {
width: 30px;
height: 30px;
object-fit: contain;
& + span {
margin-left: 10px;
+4 -4
View File
@@ -19,12 +19,12 @@ const { switchTo } = useMenu()
<div
v-if="item.children && item.children.length !== 0" :key="index" class="item" :class="{
active: index === menuStore.actived,
}" :title="item.meta.title" @click="switchTo(index)"
}" :title="item.meta?.title ?? '[ 无标题 ]'" @click="switchTo(index)"
>
<el-icon>
<svg-icon v-if="item.meta.icon" :name="item.meta.icon" />
<el-icon v-if="item.meta?.icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span>{{ item.meta.title }}</span>
<span>{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</div>
</template>
</div>
+70 -42
View File
@@ -1,6 +1,7 @@
<script lang="ts" setup name="Search">
import { cloneDeep } from 'lodash-es'
import hotkeys from 'hotkeys-js'
import type { RouteRecordRaw } from 'vue-router'
import { isExternalLink } from '@/utils'
import eventBus from '@/utils/eventBus'
import useSettingsStore from '@/store/modules/settings'
@@ -16,8 +17,8 @@ const menuStore = useMenuStore()
interface listTypes {
icon?: string
title: string
breadcrumb: string[]
title?: string | Function
breadcrumb: (string | Function | undefined)[]
path: string
}
@@ -38,15 +39,39 @@ const resultList = computed(() => {
let result = []
result = sourceList.value.filter((item) => {
let flag = false
if (item.title.includes(searchInput.value))
if (item.title) {
if (typeof item.title === 'function') {
if (item.title().includes(searchInput.value)) {
flag = true
}
}
else {
if (item.title.includes(searchInput.value)) {
flag = true
}
}
}
if (item.path.includes(searchInput.value)) {
flag = true
if (item.path.includes(searchInput.value))
}
if (item.breadcrumb.some((b) => {
let flag = false
if (b) {
if (typeof b === 'function') {
if (b().includes(searchInput.value)) {
flag = true
}
}
else {
if (b.includes(searchInput.value)) {
flag = true
}
}
}
return flag
})) {
flag = true
if (item.breadcrumb.some(b => b.includes(searchInput.value)))
flag = true
}
return flag
})
return result
@@ -109,33 +134,33 @@ onMounted(() => {
}
})
function hasChildren(item: Route.recordRaw) {
function hasChildren(item: RouteRecordRaw) {
let flag = true
if (item.children && item.children.every(i => i.meta.sidebar === false))
if (item.children?.every(i => i.meta?.sidebar === false)) {
flag = false
}
return flag
}
function getSourceList(arr: Route.recordRaw[], basePath?: string, icon?: string, breadcrumb?: string[]) {
function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string, breadcrumb?: (string | Function | undefined)[]) {
arr.forEach((item) => {
if (item.meta.sidebar !== false) {
if (item.meta?.sidebar !== false) {
const breadcrumbTemp = cloneDeep(breadcrumb) || []
if (item.children && hasChildren(item)) {
breadcrumbTemp.push(typeof item.meta.title === 'function' ? item.meta.title() : item.meta.title)
getSourceList(item.children, basePath ? [basePath, item.path].join('/') : item.path, item.meta.icon || icon, breadcrumbTemp)
breadcrumbTemp.push(item.meta?.title)
getSourceList(item.children, basePath ? [basePath, item.path].join('/') : item.path, item.meta?.icon ?? icon, breadcrumbTemp)
}
else {
breadcrumbTemp.push(typeof item.meta.title === 'function' ? item.meta.title() : item.meta.title)
breadcrumbTemp.push(item.meta?.title)
let path = ''
if (isExternalLink(item.path))
if (isExternalLink(item.path)) {
path = item.path
else
}
else {
path = basePath ? [basePath, item.path].join('/') : item.path
}
sourceList.value.push({
icon: item.meta.icon || icon,
title: typeof item.meta.title === 'function' ? item.meta.title() : item.meta.title,
icon: item.meta?.icon ?? icon,
title: item.meta?.title,
breadcrumb: breadcrumbTemp,
path,
})
@@ -143,18 +168,18 @@ function getSourceList(arr: Route.recordRaw[], basePath?: string, icon?: string,
}
})
}
function getSourceListByMenus(arr: Menu.recordRaw[], icon?: string, breadcrumb?: string[]) {
function getSourceListByMenus(arr: Menu.recordRaw[], icon?: string, breadcrumb?: (string | Function | undefined)[]) {
arr.forEach((item) => {
const breadcrumbTemp = cloneDeep(breadcrumb) || []
if (item.children && item.children.length > 0) {
breadcrumbTemp.push(item.meta.title)
getSourceListByMenus(item.children, item.meta.icon, breadcrumbTemp)
breadcrumbTemp.push(item.meta?.title)
getSourceListByMenus(item.children, item.meta?.icon ?? icon, breadcrumbTemp)
}
else {
breadcrumbTemp.push(item.meta.title)
breadcrumbTemp.push(item.meta?.title)
sourceList.value.push({
icon: item.meta.icon || icon,
title: item.meta.title,
icon: item.meta?.icon ?? icon,
title: item.meta?.title,
path: item.path as string,
breadcrumb: breadcrumbTemp,
})
@@ -165,24 +190,25 @@ function getSourceListByMenus(arr: Menu.recordRaw[], icon?: string, breadcrumb?:
function keyUp() {
if (resultList.value.length) {
actived.value -= 1
if (actived.value < 0)
if (actived.value < 0) {
actived.value = resultList.value.length - 1
}
handleScroll()
}
}
function keyDown() {
if (resultList.value.length) {
actived.value += 1
if (actived.value > resultList.value.length - 1)
if (actived.value > resultList.value.length - 1) {
actived.value = 0
}
handleScroll()
}
}
function keyEnter() {
if (actived.value !== -1)
if (actived.value !== -1) {
searchResultItemRef.value[actived.value].click()
}
}
function handleScroll() {
let scrollTo = 0
@@ -192,11 +218,12 @@ function handleScroll() {
const activedClientHeight = searchResultItemRef.value[actived.value].clientHeight
const searchScrollTop = searchResultRef.value.scrollTop
const searchClientHeight = searchResultRef.value.clientHeight
if (activedOffsetTop + activedClientHeight > searchScrollTop + searchClientHeight)
if (activedOffsetTop + activedClientHeight > searchScrollTop + searchClientHeight) {
scrollTo = activedOffsetTop + activedClientHeight - searchClientHeight
else if (activedOffsetTop <= searchScrollTop)
}
else if (activedOffsetTop <= searchScrollTop) {
scrollTo = activedOffsetTop
}
}
searchResultRef.value.scrollTo({
top: scrollTo,
@@ -204,11 +231,12 @@ function handleScroll() {
}
function pageJump(url: string) {
if (isExternalLink(url))
if (isExternalLink(url)) {
window.open(url, 'top')
else
}
else {
router.push(url)
}
}
</script>
@@ -262,11 +290,11 @@ function pageJump(url: string) {
</el-icon>
<div class="info">
<div class="title">
{{ item.title }}
{{ item.title ?? '[ 无标题 ]' }}
</div>
<div class="breadcrumb">
<span v-for="(bc, bcIndex) in item.breadcrumb" :key="bcIndex">
{{ bc }}
{{ bc ?? '[ 无标题 ]' }}
<el-icon>
<svg-icon name="ep:arrow-right" />
</el-icon>
+12 -8
View File
@@ -1,6 +1,7 @@
<script lang="ts" setup name="SidebarItem">
// import SidebarItem from './index.vue'
import { isExternalLink, resolveRoutePath } from '@/utils'
import useSettingsStore from '@/store/modules/settings'
import type { Menu } from '@/global'
const props = defineProps({
@@ -14,11 +15,14 @@ const props = defineProps({
},
})
const settingsStore = useSettingsStore()
const hasChildren = computed(() => {
let flag = true
if (props.item.children) {
if (props.item.children.every(item => item.meta.sidebar === false))
if (props.item.children.every(item => item.meta?.sidebar === false)) {
flag = false
}
}
else {
flag = false
@@ -31,23 +35,23 @@ const hasChildren = computed(() => {
<div class="sidebar-item">
<router-link v-if="!hasChildren" v-slot="{ href, navigate, isActive, isExactActive }" custom :to="resolveRoutePath(basePath, item.path || '')">
<a :href="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? resolveRoutePath(basePath, item.path || '') : href" :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']" :target="isExternalLink(resolveRoutePath(basePath, item.path || '')) ? '_blank' : '_self'" @click="navigate">
<el-menu-item :title="item.meta.title" :index="resolveRoutePath(basePath, item.path || '')">
<el-icon v-if="item.meta.icon" class="title-icon">
<el-menu-item :title="item.meta?.title ?? '[ 无标题 ]'" :index="resolveRoutePath(basePath, item.path || '')">
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span class="title">{{ item.meta.title }}</span>
<span class="title">{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</el-menu-item>
</a>
</router-link>
<el-sub-menu v-else :title="item.meta.title" :index="resolveRoutePath(basePath, item.path || '')">
<el-sub-menu v-else :title="item.meta?.title ?? '[ 无标题 ]'" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path || '') : JSON.stringify(item)">
<template #title>
<el-icon v-if="item.meta.icon" class="title-icon">
<el-icon v-if="item.meta?.icon" class="title-icon">
<svg-icon :name="item.meta.icon" />
</el-icon>
<span class="title">{{ item.meta.title }}</span>
<span class="title">{{ item.meta?.title ?? '[ 无标题 ]' }}</span>
</template>
<template v-for="route in item.children">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path || '')" />
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path" :item="route" :base-path="resolveRoutePath(basePath, item.path || '')" />
</template>
</el-sub-menu>
</div>
+1 -1
View File
@@ -30,7 +30,7 @@ function onSidebarScroll(e: Event) {
>
<transition-group name="sub-sidebar">
<template v-for="(route, index) in menuStore.sidebarMenus">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path || index" :item="route" :base-path="route.path" />
<SidebarItem v-if="route.meta?.sidebar !== false" :key="route.path || index" :item="route" :base-path="route.path" />
</template>
</transition-group>
</el-menu>
+5 -5
View File
@@ -12,11 +12,11 @@ const userStore = useUserStore()
const mainPage = useMainPage()
const { isFullscreen, toggle } = useFullscreen()
function userCommand(command: 'dashboard' | 'setting' | 'hotkeys' | 'logout') {
function userCommand(command: 'home' | 'setting' | 'hotkeys' | 'logout') {
switch (command) {
case 'dashboard':
case 'home':
router.push({
name: 'dashboard',
name: 'home',
})
break
case 'setting':
@@ -85,8 +85,8 @@ function pro() {
</div>
<template #dropdown>
<el-dropdown-menu class="user-dropdown">
<el-dropdown-item v-if="settingsStore.dashboard.enable" command="dashboard">
控制台
<el-dropdown-item v-if="settingsStore.home.enable" command="home">
{{ settingsStore.home.title }}
</el-dropdown-item>
<el-dropdown-item command="setting">
个人设置
+6 -6
View File
@@ -16,15 +16,15 @@ const enableSubMenuCollapseButton = computed(() => {
const breadcrumbList = computed(() => {
const breadcrumbList = []
if (settingsStore.dashboard.enable) {
if (settingsStore.home.enable) {
breadcrumbList.push({
path: '/dashboard',
title: settingsStore.dashboard.title,
path: '/',
title: settingsStore.home.title,
})
}
if (route.meta.breadcrumbNeste)
if (route.meta.breadcrumbNeste) {
breadcrumbList.push(...route.meta.breadcrumbNeste.filter(item => item.hide === false))
}
return breadcrumbList
})
@@ -61,7 +61,7 @@ function pathCompile(path: string) {
<el-breadcrumb v-if="settingsStore.breadcrumb.enable && settingsStore.mode === 'pc' && settingsStore.app.routeBaseOn !== 'filesystem'">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in breadcrumbList" :key="item.path" :to="index < breadcrumbList.length - 1 ? pathCompile(item.path) : ''">
{{ item.title }}
{{ item.title ?? '[ 无标题 ]' }}
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
+4 -3
View File
@@ -19,11 +19,12 @@ const menuStore = useMenuStore()
watch(() => settingsStore.menu.subMenuCollapse, (val) => {
if (settingsStore.mode === 'mobile') {
if (!val)
if (!val) {
document.body.classList.add('hidden')
else
}
else {
document.body.classList.remove('hidden')
}
}
})
+2 -1
View File
@@ -13,8 +13,9 @@ import 'virtual:svg-icons-register'
import '@/assets/styles/globals.scss'
// 加载 iconify 图标(element plus)
import { downloadAndInstall } from '@/iconify-ep'
if (useSettingsStore().app.iconifyOfflineUse)
if (useSettingsStore().app.iconifyOfflineUse) {
downloadAndInstall()
}
const app = createApp(App)
app.use(ElementPlus)
+1 -1
View File
@@ -3,7 +3,7 @@ import type { Menu } from '@/global'
const menus: Menu.recordRaw = {
meta: {
title: '多级导航',
icon: 'heroicons-solid:menu-alt-3',
icon: 'sidebar-menu',
},
children: [
{
+42 -42
View File
@@ -26,47 +26,37 @@ router.beforeEach(async (to, from, next) => {
settingsStore.app.enableProgress && (isLoading.value = true)
// 是否已登录
if (userStore.isLogin) {
// 是否已根据权限动态生成并挂载路由
// 是否已根据权限动态生成并注册路由
if (routeStore.isGenerate) {
// 导航栏如果不是 single 模式,则需要根据 path 定位主导航的选中状态
settingsStore.menu.menuMode !== 'single' && menuStore.setActived(to.path)
if (to.name) {
if (to.matched.length !== 0) {
// 如果已登录状态下,进入登录页会强制跳转到控制台页面
if (to.name === 'login') {
next({
name: 'dashboard',
replace: true,
})
}
else if (!settingsStore.dashboard.enable && to.name === 'dashboard') {
// 如果未开启控制台页面,则默认进入侧边栏导航第一个模块
if (menuStore.sidebarMenus.length > 0) {
next({
path: menuStore.sidebarMenusFirstDeepestPath,
replace: true,
})
}
else {
next()
}
}
else {
next()
}
}
else {
// 如果是通过 name 跳转,并且 name 对应的路由没有权限时,需要做这步处理,手动指向到 404 页面
// 如果已登录状态下,进入登录页会强制跳转到主页
if (to.name === 'login') {
next({
name: 'home',
replace: true,
})
}
// 如果未开启主页,但进入的是主页,则会进入侧边栏导航第一个模块
else if (!settingsStore.home.enable && to.name === 'home') {
if (menuStore.sidebarMenus.length > 0) {
next({
path: '/404',
path: menuStore.sidebarMenusFirstDeepestPath,
replace: true,
})
}
// 如果侧边栏导航第一个模块无法命中,则还是进入主页
else {
next()
}
}
// 正常访问页面
else {
next()
}
}
else {
// 生成动态路由
switch (settingsStore.app.routeBaseOn) {
case 'frontend':
await routeStore.generateRoutesAtFront(asyncRoutes)
@@ -76,6 +66,7 @@ router.beforeEach(async (to, from, next) => {
break
case 'filesystem':
await routeStore.generateRoutesAtFilesystem(asyncRoutesByFilesystem)
// 文件系统生成的路由,需要手动生成导航数据
switch (settingsStore.menu.baseOn) {
case 'frontend':
await menuStore.generateMenusAtFront()
@@ -86,18 +77,21 @@ router.beforeEach(async (to, from, next) => {
}
break
}
// 注册并记录路由数据
// 记录的数据会在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
const removeRoutes: Function[] = []
routeStore.flatRoutes.forEach((route) => {
if (!/^(https?:|mailto:|tel:)/.test(route.path))
if (!/^(https?:|mailto:|tel:)/.test(route.path)) {
removeRoutes.push(router.addRoute(route as RouteRecordRaw))
}
})
if (settingsStore.app.routeBaseOn !== 'filesystem') {
routeStore.flatSystemRoutes.forEach((route) => {
removeRoutes.push(router.addRoute(route as RouteRecordRaw))
})
}
// 记录路由数据,在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
routeStore.setCurrentRemoveRoutes(removeRoutes)
// 动态路由生成并注册后,重新进入当前路由
next({
path: to.path,
query: to.query,
@@ -110,7 +104,7 @@ router.beforeEach(async (to, from, next) => {
next({
name: 'login',
query: {
redirect: to.fullPath,
redirect: to.fullPath !== '/' ? to.fullPath : undefined,
},
})
}
@@ -125,15 +119,21 @@ router.afterEach((to, from) => {
const keepAliveStore = useKeepAliveStore()
settingsStore.app.enableProgress && (isLoading.value = false)
// 设置页面 title
to.meta.title && settingsStore.setTitle(typeof to.meta.title === 'function' ? to.meta.title() : to.meta.title)
if (settingsStore.app.routeBaseOn !== 'filesystem') {
settingsStore.setTitle(to.meta.breadcrumbNeste?.at(-1)?.title)
}
else {
settingsStore.setTitle(to.meta.title)
}
// 判断当前页面是否开启缓存,如果开启,则将当前页面的 name 信息存入 keep-alive 全局状态
if (to.meta.cache) {
const componentName = to.matched.at(-1)?.components?.default.name
if (componentName)
if (componentName) {
keepAliveStore.add(componentName)
else
}
else {
console.warn('该页面组件未设置组件名,会导致缓存失效,请检查')
}
}
// 判断离开页面是否开启缓存,如果开启,则根据缓存规则判断是否需要清空 keep-alive 全局状态里离开页面的 name 信息
if (from.meta.cache) {
@@ -142,22 +142,22 @@ router.afterEach((to, from) => {
// 通过 meta.cache 判断针对哪些页面进行缓存
switch (typeof from.meta.cache) {
case 'string':
if (from.meta.cache !== to.name)
if (from.meta.cache !== to.name) {
keepAliveStore.remove(componentName)
}
break
case 'object':
if (!from.meta.cache.includes(to.name as string))
if (!from.meta.cache.includes(to.name as string)) {
keepAliveStore.remove(componentName)
}
break
}
// 如果进入的是 reload 页面,则也将离开页面的缓存清空
if (to.name === 'reload')
if (to.name === 'reload') {
keepAliveStore.remove(componentName)
}
}
}
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
})
+2 -2
View File
@@ -1,8 +1,8 @@
import type { Route } from '@/global'
import type { RouteRecordRaw } from 'vue-router'
const Layout = () => import('@/layouts/index.vue')
const routes: Route.recordRaw = {
const routes: RouteRecordRaw = {
path: '/breadcrumb_example',
component: Layout,
redirect: '/breadcrumb_example/list1',
@@ -1,8 +1,8 @@
import type { Route } from '@/global'
import type { RouteRecordRaw } from 'vue-router'
const Layout = () => import('@/layouts/index.vue')
const routes: Route.recordRaw = {
const routes: RouteRecordRaw = {
path: '/multilevel_menu_example',
component: Layout,
redirect: '/multilevel_menu_example/page',
+17 -44
View File
@@ -1,19 +1,13 @@
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'
import type { RouteRecordRaw } from 'vue-router'
import MultilevelMenuExample from './modules/multilevel.menu.example'
import BreadcrumbExample from './modules/breadcrumb.example'
import type { Route } from '@/global'
import useSettingsStore from '@/store/modules/settings'
// 固定路由(默认路由)
const constantRoutes: Route.recordRaw[] = [
{
path: '/',
redirect: '/dashboard',
meta: {
title: '',
},
},
const constantRoutes: RouteRecordRaw[] = [
{
path: '/login',
name: 'login',
@@ -33,35 +27,33 @@ const constantRoutes: Route.recordRaw[] = [
]
// 系统路由
const systemRoutes: Route.recordRaw[] = [
const systemRoutes: RouteRecordRaw[] = [
{
path: '/dashboard',
path: '/',
component: () => import('@/layouts/index.vue'),
meta: {
title: () => useSettingsStore().dashboard.title,
title: () => useSettingsStore().home.title,
breadcrumb: false,
},
children: [
{
path: '',
name: 'dashboard',
name: 'home',
component: () => import('@/views/index.vue'),
meta: {
title: () => useSettingsStore().dashboard.title,
title: () => useSettingsStore().home.title,
breadcrumb: false,
},
},
{
path: 'reload',
name: 'reload',
component: () => import('@/views/reload.vue'),
meta: {
title: '重新加载',
breadcrumb: false,
},
},
],
},
{
path: '/personal',
component: () => import('@/layouts/index.vue'),
redirect: '/personal/setting',
meta: {
title: '个人中心',
breadcrumb: false,
},
children: [
{
path: 'setting',
name: 'personalSetting',
@@ -81,25 +73,6 @@ const systemRoutes: Route.recordRaw[] = [
},
],
},
{
path: '/reload',
component: () => import('@/layouts/index.vue'),
meta: {
title: '重新加载',
breadcrumb: false,
},
children: [
{
path: '',
name: 'reload',
component: () => import('@/views/reload.vue'),
meta: {
title: '重新加载',
breadcrumb: false,
},
},
],
},
]
// 动态路由(异步路由、导航栏路由)
@@ -122,7 +95,7 @@ const constantRoutesByFilesystem = generatedRoutes.filter((item) => {
const asyncRoutesByFilesystem = setupLayouts(generatedRoutes.filter((item) => {
return item.meta?.enabled !== false && item.meta?.constant !== true && item.meta?.layout !== false
})) as Route.recordRaw[]
}))
export {
constantRoutes,
+2 -2
View File
@@ -12,9 +12,9 @@ const globalSettingsDefault: RecursiveRequired<Settings.all> = {
enableDynamicTitle: false,
routeBaseOn: 'frontend',
},
dashboard: {
home: {
enable: true,
title: '控制台',
title: '主页',
},
layout: {
enableMobileAdaptation: false,
+14 -21
View File
@@ -10,15 +10,11 @@ import menu from '@/menu'
function getDeepestPath(menu: Menu.recordRaw, rootPath = '') {
let retnPath = ''
if (menu.path) {
if (menu.path !== undefined) {
if (menu.children) {
if (
menu.children.some((item) => {
return item.meta.sidebar !== false
})
) {
if (menu.children.some(item => item.meta?.sidebar !== false)) {
for (let i = 0; i < menu.children.length; i++) {
if (menu.children[i].meta.sidebar !== false) {
if (menu.children[i].meta?.sidebar !== false) {
retnPath = getDeepestPath(menu.children[i], resolveRoutePath(rootPath, menu.path))
break
}
@@ -39,9 +35,9 @@ function hasPermission(permissions: string[], menu: Menu.recordMainRaw | Menu.re
let isAuth = false
if (menu.meta && menu.meta.auth) {
isAuth = permissions.some((auth) => {
return typeof menu.meta.auth === 'string'
return typeof menu.meta?.auth === 'string'
? menu.meta.auth === auth
: typeof menu.meta.auth === 'object'
: typeof menu.meta?.auth === 'object'
? menu.meta.auth.includes(auth)
: false
})
@@ -72,11 +68,12 @@ function filterAsyncMenus<T extends Menu.recordMainRaw[] | Menu.recordRaw[]>(men
function getDefaultOpenedPaths(menus: Menu.recordRaw[], rootPath = '') {
const defaultOpenedPaths: string[] = []
menus.forEach((item) => {
if (item.path && item.meta.defaultOpened && item.children) {
if (item.path && item.meta?.defaultOpened && item.children) {
defaultOpenedPaths.push(resolveRoutePath(rootPath, item.path))
const childrenDefaultOpenedPaths = getDefaultOpenedPaths(item.children, resolveRoutePath(rootPath, item.path))
if (childrenDefaultOpenedPaths.length > 0)
if (childrenDefaultOpenedPaths.length > 0) {
defaultOpenedPaths.push(...childrenDefaultOpenedPaths)
}
}
})
return defaultOpenedPaths
@@ -133,9 +130,9 @@ const useMenuStore = defineStore(
defaultOpenedPaths() {
const settingsStore = useSettingsStore()
let defaultOpenedPaths: string[] = []
if (settingsStore.app.routeBaseOn !== 'filesystem')
if (settingsStore.app.routeBaseOn !== 'filesystem') {
defaultOpenedPaths = getDefaultOpenedPaths(this.sidebarMenus)
}
return defaultOpenedPaths
},
},
@@ -189,14 +186,10 @@ const useMenuStore = defineStore(
}
else {
// 如果是 string 类型,则认为是路由,需要查找对应的主导航索引
this.allMenus.forEach((item, index) => {
if (
item.children.some((r) => {
return data.indexOf(`${r.path}/`) === 0 || data === r.path
})
)
this.actived = index
})
const findIndex = this.allMenus.findIndex(item => item.children.some(r => data.indexOf(`${r.path}/`) === 0 || data === r.path))
if (findIndex >= 0) {
this.actived = findIndex
}
}
},
},
+33 -24
View File
@@ -1,4 +1,5 @@
import { cloneDeep } from 'lodash-es'
import type { RouteRecordRaw } from 'vue-router'
import useSettingsStore from './settings'
import useUserStore from './user'
import api from '@/api'
@@ -6,13 +7,13 @@ import { resolveRoutePath } from '@/utils'
import { systemRoutes } from '@/router/routes'
import type { Route } from '@/global'
function hasPermission(permissions: string[], route: Route.recordMainRaw | Route.recordRaw) {
function hasPermission(permissions: string[], route: Route.recordMainRaw | RouteRecordRaw) {
let isAuth = false
if (route.meta?.auth) {
isAuth = permissions.some((auth) => {
return typeof route.meta.auth === 'string'
return typeof route.meta?.auth === 'string'
? route.meta.auth === auth
: typeof route.meta.auth === 'object'
: typeof route.meta?.auth === 'object'
? route.meta.auth.includes(auth)
: false
})
@@ -23,7 +24,7 @@ function hasPermission(permissions: string[], route: Route.recordMainRaw | Route
return isAuth
}
function filterAsyncRoutes<T extends Route.recordMainRaw[] | Route.recordRaw[]>(routes: T, permissions: string[]): T {
function filterAsyncRoutes<T extends Route.recordMainRaw[] | RouteRecordRaw[]>(routes: T, permissions: string[]): T {
const res: any = []
routes.forEach((route) => {
if (hasPermission(permissions, route)) {
@@ -47,42 +48,46 @@ function formatBackRoutes(routes: any, views = import.meta.glob('../../views/**/
route.component = () => import('@/layouts/index.vue')
break
default:
if (route.component)
if (route.component) {
route.component = views[`../../views/${route.component}`]
}
}
if (route.children)
if (route.children) {
route.children = formatBackRoutes(route.children, views)
}
return route
})
}
// 将多层嵌套路由处理成两层,保留顶层和最子层路由,中间层级将被拍平
function flatAsyncRoutes<T extends Route.recordRaw>(routes: T): T {
function flatAsyncRoutes<T extends RouteRecordRaw>(routes: T): T {
if (routes.children) {
routes.children = flatAsyncRoutesRecursive(routes.children, [{
path: routes.path,
title: routes.meta.title,
hide: !routes.meta.breadcrumb && routes.meta.breadcrumb === false,
title: routes.meta?.title,
hide: !routes.meta?.breadcrumb && routes.meta?.breadcrumb === false,
}], routes.path)
}
return routes
}
function flatAsyncRoutesRecursive(routes: Route.recordRaw[], breadcrumb: Route.breadcrumb[] = [], baseUrl = ''): Route.recordRaw[] {
const res: Route.recordRaw[] = []
function flatAsyncRoutesRecursive(routes: RouteRecordRaw[], breadcrumb: Route.breadcrumb[] = [], baseUrl = ''): RouteRecordRaw[] {
const res: RouteRecordRaw[] = []
routes.forEach((route) => {
if (route.children) {
const childrenBaseUrl = resolveRoutePath(baseUrl, route.path)
const tmpBreadcrumb = cloneDeep(breadcrumb)
if (route.meta.breadcrumb !== false) {
if (route.meta?.breadcrumb !== false) {
tmpBreadcrumb.push({
path: childrenBaseUrl,
title: route.meta.title,
hide: !route.meta.breadcrumb && route.meta.breadcrumb === false,
title: route.meta?.title,
hide: !route.meta?.breadcrumb,
})
}
const tmpRoute = cloneDeep(route)
tmpRoute.path = childrenBaseUrl
if (!tmpRoute.meta) {
tmpRoute.meta = {}
}
tmpRoute.meta.breadcrumbNeste = tmpBreadcrumb
delete tmpRoute.children
res.push(tmpRoute)
@@ -91,8 +96,9 @@ function flatAsyncRoutesRecursive(routes: Route.recordRaw[], breadcrumb: Route.b
// 如果 path 一样则覆盖,因为子路由的 path 可能设置为空,导致和父路由一样,直接注册会提示路由重复
if (res.some(v => v.path === item.path)) {
res.forEach((v, i) => {
if (v.path === item.path)
if (v.path === item.path) {
res[i] = item
}
})
}
else {
@@ -107,9 +113,12 @@ function flatAsyncRoutesRecursive(routes: Route.recordRaw[], breadcrumb: Route.b
const tmpBreadcrumb = cloneDeep(breadcrumb)
tmpBreadcrumb.push({
path: tmpRoute.path,
title: tmpRoute.meta.title,
hide: !tmpRoute.meta.breadcrumb && tmpRoute.meta.breadcrumb === false,
title: tmpRoute.meta?.title,
hide: !tmpRoute.meta?.breadcrumb && tmpRoute.meta?.breadcrumb === false,
})
if (!tmpRoute.meta) {
tmpRoute.meta = {}
}
tmpRoute.meta.breadcrumbNeste = tmpBreadcrumb
res.push(tmpRoute)
}
@@ -124,14 +133,14 @@ const useRouteStore = defineStore(
state: () => ({
isGenerate: false,
routes: [] as Route.recordMainRaw[],
fileSystemRoutes: [] as Route.recordRaw[],
fileSystemRoutes: [] as RouteRecordRaw[],
currentRemoveRoutes: [] as Function[],
}),
getters: {
// 扁平化路由(将三级及以上路由数据拍平成二级)
flatRoutes: (state) => {
const settingsStore = useSettingsStore()
const routes: Route.recordRaw[] = []
const routes: RouteRecordRaw[] = []
if (state.routes) {
if (settingsStore.app.routeBaseOn !== 'filesystem') {
state.routes.forEach((item) => {
@@ -169,7 +178,7 @@ const useRouteStore = defineStore(
}
// 设置 routes 数据
this.isGenerate = true
this.routes = accessedRoutes.filter(item => item.children?.length !== 0)
this.routes = accessedRoutes.filter(item => item.children?.length !== 0) as any
resolve()
})
},
@@ -193,13 +202,13 @@ const useRouteStore = defineStore(
}
// 设置 routes 数据
this.isGenerate = true
this.routes = accessedRoutes.filter(item => item.children.length !== 0)
this.routes = accessedRoutes.filter(item => item.children.length !== 0) as any
resolve()
})
})
},
// 根据权限动态生成路由(文件系统生成)
generateRoutesAtFilesystem(asyncRoutes: Route.recordRaw[]) {
generateRoutesAtFilesystem(asyncRoutes: RouteRecordRaw[]) {
// eslint-disable-next-line no-async-promise-executor
return new Promise<void>(async (resolve) => {
const settingsStore = useSettingsStore()
@@ -215,7 +224,7 @@ const useRouteStore = defineStore(
}
// 设置 routes 数据
this.isGenerate = true
this.fileSystemRoutes = accessedRoutes.filter(item => item.children?.length !== 0)
this.fileSystemRoutes = accessedRoutes.filter(item => item.children?.length !== 0) as any
resolve()
})
},
+12 -15
View File
@@ -1,3 +1,5 @@
import { defaultsDeep } from 'lodash-es'
import type { RouteMeta } from 'vue-router'
import type { RecursiveRequired, Settings } from '@/global'
import settings from '@/settings'
import settingsDefault from '@/settings.default'
@@ -5,20 +7,16 @@ import settingsDefault from '@/settings.default'
interface SettingsStore extends RecursiveRequired<Settings.all> {
subMenuCollapseLastStatus: boolean
mode: 'pc' | 'mobile'
title: string
title?: RouteMeta['title']
}
// 合并配置
Object.keys(settingsDefault).forEach((key) => {
Object.assign(settingsDefault[key as keyof Settings.all], settings[key as keyof Settings.all])
})
const useSettingsStore = defineStore(
// 唯一ID
'settings',
{
state: (): SettingsStore => ({
...settingsDefault,
// 合并配置
...defaultsDeep(settings, settingsDefault),
// 侧边栏是否收起(用于记录 pc 模式下最后的状态)
subMenuCollapseLastStatus: settingsDefault.menu.subMenuCollapse,
// 显示模式,支持:mobile、pc
@@ -28,7 +26,7 @@ const useSettingsStore = defineStore(
}),
actions: {
// 设置网页标题
setTitle(title: string) {
setTitle(title: SettingsStore['title']) {
this.title = title
},
// 设置访问模式
@@ -40,11 +38,7 @@ const useSettingsStore = defineStore(
}
else {
// 如果为桌面设备,再根据页面宽度判断是否需要切换为移动端展示
if (width < 992)
this.mode = 'mobile'
else
this.mode = 'pc'
this.mode = width < 992 ? 'mobile' : 'pc'
}
}
else {
@@ -54,8 +48,9 @@ const useSettingsStore = defineStore(
// 切换侧边栏导航展开/收起
toggleSidebarCollapse() {
this.menu.subMenuCollapse = !this.menu.subMenuCollapse
if (this.mode === 'pc')
if (this.mode === 'pc') {
this.subMenuCollapseLastStatus = !this.subMenuCollapseLastStatus
}
},
// 设置主题颜色模式
setColorScheme(color: Required<Settings.app>['colorScheme']) {
@@ -63,7 +58,9 @@ const useSettingsStore = defineStore(
},
// 更新应用配置
updateSettings(data: Settings.all) {
Object.assign(this, data)
Object.keys(data).forEach((key) => {
this[key as keyof Settings.all] = defaultsDeep(data[key as keyof Settings.all], this[key as keyof Settings.all])
})
},
},
},
+2 -1
View File
@@ -16,8 +16,9 @@ const useUserStore = defineStore(
isLogin: (state) => {
let retn = false
if (state.token) {
if (new Date().getTime() < parseInt(state.failure_time) * 1000)
if (new Date().getTime() < parseInt(state.failure_time) * 1000) {
retn = true
}
}
return retn
},
+4 -3
View File
@@ -5,11 +5,12 @@ export default function useAuth() {
function hasPermission(permission: string) {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
if (settingsStore.app.enablePermission)
if (settingsStore.app.enablePermission) {
return userStore.permissions.includes(permission)
else
}
else {
return true
}
}
function auth(value: string | string[]) {
@@ -1,6 +1,6 @@
import type { ComponentInternalInstance } from 'vue'
export default function useCurrentInstance() {
export default function useGlobalProperties() {
const { appContext } = getCurrentInstance() as ComponentInternalInstance
return appContext.config.globalProperties
}
+4 -3
View File
@@ -10,11 +10,12 @@ export default function useMenu() {
function switchTo(index: number | string) {
menuStore.setActived(index)
if (settingsStore.menu.switchMainMenuAndPageJump) {
if (isExternalLink(menuStore.sidebarMenusFirstDeepestPath))
if (isExternalLink(menuStore.sidebarMenusFirstDeepestPath)) {
window.open(menuStore.sidebarMenusFirstDeepestPath, '_blank')
else
}
else {
router.push(menuStore.sidebarMenusFirstDeepestPath)
}
}
}
+4 -2
View File
@@ -4,14 +4,16 @@ export default function directive(app: App) {
// 注册 v-auth 和 v-auth-all 指令
app.directive('auth', {
mounted: (el, binding) => {
if (!useAuth().auth(binding.value))
if (!useAuth().auth(binding.value)) {
el.remove()
}
},
})
app.directive('auth-all', {
mounted: (el, binding) => {
if (!useAuth().authAll(binding.value))
if (!useAuth().authAll(binding.value)) {
el.remove()
}
},
})
}
+4 -4
View File
@@ -5,11 +5,11 @@ export function isExternalLink(path: string) {
}
export function resolveRoutePath(basePath: string, routePath: string) {
if (isExternalLink(routePath))
if (isExternalLink(routePath)) {
return routePath
if (isExternalLink(basePath))
}
if (isExternalLink(basePath)) {
return basePath
}
return basePath ? path.resolve(basePath, routePath) : routePath
}
+1 -2
View File
@@ -7,11 +7,10 @@ meta:
</route>
<script lang="ts" setup>
import { onBeforeRouteLeave } from 'vue-router'
const router = useRouter()
const data = ref({
inter: null as NodeJS.Timer | null,
inter: NaN,
countdown: 5,
})
+3 -3
View File
@@ -1,7 +1,7 @@
<route lang="yaml">
name: dashboard
name: home
meta:
title: 控制台
title: 主页
</route>
<script lang="ts" setup>
@@ -60,7 +60,7 @@ const oneStepAdminInfo = ref({
<div>注:在作者就职的公司,本框架已在电商、直播、OA、ERP等多个不同领域的中后台系统中应用并稳定运行</div>
</div>
</template>
<el-button-group style="margin-right: 10px;">
<el-button-group>
<el-button type="success" size="large" plain @click="open('https://hooray.gitee.io/fantastic-admin/')">
开发文档
</el-button>
+9 -7
View File
@@ -7,6 +7,7 @@ meta:
<script lang="ts" setup name="Login">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user'
const route = useRoute()
@@ -46,12 +47,12 @@ function handleLogin() {
loading.value = true
userStore.login(loginForm.value).then(() => {
loading.value = false
if (loginForm.value.remember)
if (loginForm.value.remember) {
localStorage.setItem('login_account', loginForm.value.account)
else
}
else {
localStorage.removeItem('login_account')
}
router.push(redirect.value)
}).catch(() => {
loading.value = false
@@ -85,11 +86,12 @@ const registerRules = ref<FormRules>({
{ required: true, trigger: 'blur', message: '请再次输入密码' },
{
validator: (rule, value, callback) => {
if (value !== registerForm.value.password)
if (value !== registerForm.value.password) {
callback(new Error('两次输入的密码不一致'))
else
}
else {
callback()
}
},
},
],
+5 -3
View File
@@ -6,6 +6,7 @@ meta:
<script lang="ts" setup name="PersonalEditPassword">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user'
const route = useRoute()
@@ -32,11 +33,12 @@ const rules = ref<FormRules>({
{ required: true, message: '请输入新密码', trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (value !== form.value.newpassword)
if (value !== form.value.newpassword) {
callback(new Error('请确认新密码'))
else
}
else {
callback()
}
},
},
],
+5 -3
View File
@@ -7,6 +7,7 @@ meta:
<script lang="ts" setup name="PersonalSetting">
import type { UploadProps } from 'element-plus'
import { ElMessage } from 'element-plus'
const router = useRouter()
@@ -19,11 +20,12 @@ const form = ref({
})
const handleSuccess: UploadProps['onSuccess'] = (res) => {
if (res.error === '')
if (res.error === '') {
form.value.headimg = res.data.path
else
}
else {
ElMessage.warning(res.error)
}
}
const editPassword = () => {
router.push({
+1 -12
View File
@@ -11,8 +11,7 @@ export default ({ mode, command }) => {
// 全局 scss 资源
const scssResources = []
fs.readdirSync('src/assets/styles/resources').forEach((dirname) => {
if (fs.statSync(`src/assets/styles/resources/${dirname}`).isFile())
scssResources.push(`@use "src/assets/styles/resources/${dirname}" as *;`)
if (fs.statSync(`src/assets/styles/resources/${dirname}`).isFile()) { scssResources.push(`@use "src/assets/styles/resources/${dirname}" as *;`) }
})
// css 精灵图相关
fs.readdirSync('src/assets/sprites').forEach((dirname) => {
@@ -50,16 +49,6 @@ export default ({ mode, command }) => {
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
}),
},
optimizeDeps: {
include: [
'element-plus',
'element-plus/es',
'element-plus/es/components/message/style/css',
'element-plus/es/components/notification/style/css',
'element-plus/es/components/message-box/style/css',
'element-plus/es/components/loading/style/css',
],
},
plugins: createVitePlugins(env, command === 'build'),
resolve: {
alias: {
-4
View File
@@ -1,5 +1,4 @@
import autoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default function createAutoImport() {
return autoImport({
@@ -12,8 +11,5 @@ export default function createAutoImport() {
dirs: [
'./src/utils/composables/**',
],
resolvers: [
ElementPlusResolver(),
],
})
}
+10 -9
View File
@@ -1,20 +1,22 @@
import { createHtmlPlugin } from 'vite-plugin-html'
const copyright_common_style = 'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff;'
const copyright_main_style = `${copyright_common_style} background: #e24329;`
const copyright_sub_style = `${copyright_common_style} background: #707070;`
export default function createHtml(env, isBuild) {
const { VITE_APP_TITLE, VITE_APP_DEBUG_TOOL } = env
const copyrightScript = `
let copyrightScript = ''
if (isBuild) {
const copyright_common_style = 'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff;'
const copyright_main_style = `${copyright_common_style} background: #e24329;`
const copyright_sub_style = `${copyright_common_style} background: #707070;`
copyrightScript += `
<script>
if ((navigator.language || navigator.browserLanguage).toLowerCase() === 'zh-cn') {
console.info('%c由%cFantastic-admin%c提供技术支持', '${copyright_sub_style}', '${copyright_main_style}', '${copyright_sub_style}', '\\nhttps://gitee.com/hooray/fantastic-admin');
console.info('%c由%cFantastic-admin%c驱动', '${copyright_sub_style}', '${copyright_main_style}', '${copyright_sub_style}', '\\nhttps://gitee.com/hooray/fantastic-admin');
} else {
console.info('%cPowered by%cFantastic-admin', '${copyright_sub_style}', '${copyright_main_style}', '\\nhttps://github.com/hooray/fantastic-admin');
}
</script>
`
`
}
let devtoolScript = ''
switch (VITE_APP_DEBUG_TOOL) {
case 'eruda':
@@ -54,7 +56,7 @@ if ((navigator.language || navigator.browserLanguage).toLowerCase() === 'zh-cn')
})()
</script>
`
const html = createHtmlPlugin({
return createHtmlPlugin({
inject: {
data: {
title: VITE_APP_TITLE,
@@ -65,5 +67,4 @@ if ((navigator.language || navigator.browserLanguage).toLowerCase() === 'zh-cn')
},
minify: isBuild,
})
return html
}
-2
View File
@@ -2,7 +2,6 @@ import type { PluginOption } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import createRestart from './restart'
import createHtml from './html'
import createAutoImport from './auto-import'
import createComponents from './components'
@@ -22,7 +21,6 @@ export default function createVitePlugins(viteEnv, isBuild = false) {
}),
vueJsx(),
]
!isBuild && vitePlugins.push(createRestart())
vitePlugins.push(createHtml(viteEnv, isBuild))
vitePlugins.push(createAutoImport())
vitePlugins.push(createComponents())
-13
View File
@@ -1,13 +0,0 @@
import fs from 'node:fs'
import ViteRestart from 'vite-plugin-restart'
export default function createRestart() {
const pluginsFile: string[] = []
fs.readdirSync('vite/plugins').forEach((dirname) => {
if (fs.statSync(`vite/plugins/${dirname}`).isFile())
pluginsFile.push(`vite/plugins/${dirname}`)
})
return ViteRestart({
restart: pluginsFile,
})
}
+2 -1
View File
@@ -4,8 +4,9 @@ import spritesmith from 'vite-plugin-spritesmith'
export default function createSpritesmith(isBuild) {
const spriteDirnames: string[] = []
fs.readdirSync('src/assets/sprites').forEach((dirname) => {
if (fs.statSync(`src/assets/sprites/${dirname}`).isDirectory())
if (fs.statSync(`src/assets/sprites/${dirname}`).isDirectory()) {
spriteDirnames.push(dirname)
}
})
const plugin: any[] = []
spriteDirnames.forEach((item) => {