diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4eac27a84..d34be7cb4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: - "**.csproj" env: - DOTNET_VERSION: "8.0.200" + DOTNET_VERSION: "9.0.101" jobs: build: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cb3855bc6..a3b942008 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,10 +1,10 @@ name: "Publish" on: - push: - branches: [ rel-8.3.0 ] + pull_request: + branches: [ main ] env: - DOTNET_VERSION: "8.0.200" + DOTNET_VERSION: "9.0.101" jobs: publish: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7794b528..5046b54bd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,8 @@ name: "Tagged Release" on: - push: - branches: [ rel-8.3.0 ] + pull_request: + branches: [ main ] jobs: tagged-release: @@ -14,4 +14,4 @@ jobs: with: repo_token: "${{ secrets.GITHUB_TOKEN }}" prerelease: false - automatic_release_tag: "8.3.0" + automatic_release_tag: "9.0.4" diff --git a/.gitignore b/.gitignore index a590125ce..597037eca 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ vue.config.js task obj bin +!apps/vben5/scripts/**/bin/ Logs appsettings.Production.json appsettings.secrets.json diff --git a/Directory.Packages.props b/Directory.Packages.props index 1bb7eb350..72c27a05d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,12 +2,12 @@ 8.2.0 2.14.1 - 3.2.3 - 8.3.0 - 8.3.0 - 8.0.0 - 8.0.0 - 8.0.0 + 3.3.0-rc7 + 9.0.4 + 9.0.4 + 9.0.0.0 + 9.0.0.0 + 9.0.0.0 true @@ -52,6 +52,7 @@ + @@ -140,15 +141,17 @@ - + - + + + @@ -156,7 +159,10 @@ - + + + + @@ -179,6 +185,21 @@ + + + + + + + + + + + + + + + @@ -186,33 +207,35 @@ + + - - + + - - - + + + - + - - + + - - - + + + @@ -222,27 +245,28 @@ - + - - - - - + + + + + + - - + + - + - + - - + + @@ -251,16 +275,16 @@ - + - + - + - - - - + + + + diff --git a/README.en.md b/README.en.md index 74883c04b..fb79ea7d0 100644 --- a/README.en.md +++ b/README.en.md @@ -10,6 +10,19 @@ This is a [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) -based Abp [](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml) +## Deployment Options + +### Monolithic Service Deployment + +If you don't need a microservices architecture, you can choose the monolithic service deployment option. Monolithic services are characterized by simple deployment and easy maintenance. + +- [Monolithic Service Startup Guide](./docs/startup-aio-readme.en.md) +- [单体服务启动说明](./docs/startup-aio-readme.md) + +### Microservices Deployment + +If you need higher scalability and a more flexible service architecture, you can choose the microservices deployment option. + ## Quick Start ### 0、Configurate hosts diff --git a/README.md b/README.md index 9f0c91c39..dbcc172d0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - [English](./README.en.md) | 简体中文 [更新说明](./RELEASE.md) 更新说明 @@ -11,6 +10,18 @@ [](https://github.com/colinin/abp-next-admin/actions/workflows/build.yml) +## 部署方案 + +### 单体服务部署 + +如果您不需要微服务架构,可以选择单体服务部署方案。单体服务具有部署简单、维护方便的特点。 + +- [单体服务启动说明](./docs/startup-aio-readme.md) +- [Monolithic Service Startup Guide](./docs/startup-aio-readme.en.md) + +### 微服务部署 + +如果您需要更高的可扩展性和更灵活的服务架构,可以选择微服务部署方案。 ## 快速搭建微服务启动项目 diff --git a/apps/vben5/.lintstagedrc.mjs b/apps/vben5/.lintstagedrc.mjs index e68d8a3e0..94b0192a7 100644 --- a/apps/vben5/.lintstagedrc.mjs +++ b/apps/vben5/.lintstagedrc.mjs @@ -1,4 +1,10 @@ export default { + '*.md': ['prettier --cache --ignore-unknown --write'], + '*.vue': [ + 'prettier --write', + 'eslint --cache --fix', + 'stylelint --fix --allow-empty-input', + ], '*.{js,jsx,ts,tsx}': [ 'prettier --cache --ignore-unknown --write', 'eslint --cache --fix', @@ -7,14 +13,8 @@ export default { 'prettier --cache --ignore-unknown --write', 'stylelint --fix --allow-empty-input', ], - '*.md': ['prettier --cache --ignore-unknown --write'], - '*.vue': [ - 'prettier --write', - 'eslint --cache --fix', - 'stylelint --fix --allow-empty-input', - ], + 'package.json': ['prettier --cache --write'], '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [ 'prettier --cache --write--parser json', ], - 'package.json': ['prettier --cache --write'], }; diff --git a/apps/vben5/apps/app-antd/.env.development b/apps/vben5/apps/app-antd/.env.development index 0692ed288..d7204a13d 100644 --- a/apps/vben5/apps/app-antd/.env.development +++ b/apps/vben5/apps/app-antd/.env.development @@ -7,7 +7,7 @@ VITE_BASE=/ VITE_GLOB_API_URL=/ # 是否开启 Nitro Mock服务,true 为开启,false 为关闭 -VITE_NITRO_MOCK=true +VITE_NITRO_MOCK=false # 是否打开 devtools,true 为打开,false 为关闭 VITE_DEVTOOLS=false @@ -15,5 +15,6 @@ VITE_DEVTOOLS=false # 是否注入全局loading VITE_INJECT_APP_LOADING=true +VITE_GLOB_AUDIENCE="openid email address phone profile offline_access lingyun-abp-application" VITE_GLOB_CLIENT_ID=vue-admin-client VITE_GLOB_CLIENT_SECRET=1q2w3e* diff --git a/apps/vben5/apps/app-antd/package.json b/apps/vben5/apps/app-antd/package.json index a4bc65408..e6a986ea1 100644 --- a/apps/vben5/apps/app-antd/package.json +++ b/apps/vben5/apps/app-antd/package.json @@ -1,18 +1,18 @@ { - "name": "@vben/app-antd", - "version": "5.4.8", - "homepage": "https://vben.pro", - "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", + "name": "@abp/app-antd", + "version": "9.0.4", + "homepage": "https://github.com/colinin/abp-next-admin", + "bugs": "https://github.com/colinin/abp-next-admin/issues", "repository": { "type": "git", - "url": "git+https://github.com/vbenjs/vue-vben-admin.git", + "url": "git+https://github.com/colinin/abp-next-admin.git", "directory": "apps/app-antd" }, "license": "MIT", "author": { - "name": "vben", - "email": "ann.vben@gmail.com", - "url": "https://github.com/anncwb" + "name": "colin", + "email": "colin.in@foxmail.com", + "url": "https://github.com/colinin" }, "type": "module", "scripts": { @@ -27,9 +27,16 @@ }, "dependencies": { "@abp/account": "workspace:*", + "@abp/auditing": "workspace:*", "@abp/core": "workspace:*", "@abp/identity": "workspace:*", + "@abp/notifications": "workspace:*", + "@abp/openiddict": "workspace:*", + "@abp/permissions": "workspace:*", + "@abp/platform": "workspace:*", "@abp/request": "workspace:*", + "@abp/settings": "workspace:*", + "@abp/ui": "workspace:*", "@vben/access": "workspace:*", "@vben/common-ui": "workspace:*", "@vben/constants": "workspace:*", diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/langs/en.js b/apps/vben5/apps/app-antd/public/resource/tinymce/langs/en.js new file mode 100644 index 000000000..27337c394 --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/langs/en.js @@ -0,0 +1,419 @@ +tinymce.addI18n('es', { + Redo: 'Rehacer', + Undo: 'Deshacer', + Cut: 'Cortar', + Copy: 'Copiar', + Paste: 'Pegar', + 'Select all': 'Seleccionar todo', + 'New document': 'Nuevo documento', + Ok: 'Ok', + Cancel: 'Cancelar', + 'Visual aids': 'Ayudas visuales', + Bold: 'Negrita', + Italic: 'Cursiva', + Underline: 'Subrayado', + Strikethrough: 'Tachado', + Superscript: 'Super\u00edndice', + Subscript: 'Sub\u00edndice', + 'Clear formatting': 'Limpiar formato', + 'Align left': 'Alinear a la izquierda', + 'Align center': 'Alinear al centro', + 'Align right': 'Alinear a la derecha', + Justify: 'Justificar', + 'Bullet list': 'Lista de vi\u00f1etas', + 'Numbered list': 'Lista numerada', + 'Decrease indent': 'Disminuir sangr\u00eda', + 'Increase indent': 'Incrementar sangr\u00eda', + Close: 'Cerrar', + Formats: 'Formatos', + "Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": 'Su navegador no es compatible con el acceso directo al portapapeles. Use las teclas Crtl+X\/C\/V de su teclado.', + Headers: 'Encabezados', + 'Header 1': 'Encabezado 1', + 'Header 2': 'Encabezado 2', + 'Header 3': 'Encabezado 3', + 'Header 4': 'Encabezado 4', + 'Header 5': 'Encabezado 5', + 'Header 6': 'Encabezado 6', + Headings: 'Encabezados', + 'Heading 1': 'Encabezado 1', + 'Heading 2': 'Encabezado 2', + 'Heading 3': 'Encabezado 3', + 'Heading 4': 'Encabezado 4', + 'Heading 5': 'Encabezado 5', + 'Heading 6': 'Encabezado 6', + Preformatted: 'Con formato previo', + Div: 'Div', + Pre: 'Pre', + Code: 'C\u00f3digo', + Paragraph: 'P\u00e1rrafo', + Blockquote: 'Blockquote', + Inline: 'Alineado', + Blocks: 'Bloques', + 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.': 'Pegar est\u00e1 ahora en modo de texto plano. El contenido se pegar\u00e1 como texto plano hasta que desactive esta opci\u00f3n.', + Fonts: 'Fuentes', + 'Font Sizes': 'Tama\u00f1os de fuente', + Class: 'Clase', + 'Browse for an image': 'Buscar una imagen', + OR: 'OR', + 'Drop an image here': 'Arrastre una imagen aqu\u00ed', + Upload: 'Cargar', + Block: 'Bloque', + Align: 'Alinear', + Default: 'Por defecto', + Circle: 'C\u00edrculo', + Disc: 'Disco', + Square: 'Cuadrado', + 'Lower Alpha': 'Inferior Alfa', + 'Lower Greek': 'Inferior Griega', + 'Lower Roman': 'Inferior Romana', + 'Upper Alpha': 'Superior Alfa', + 'Upper Roman': 'Superior Romana', + 'Anchor...': 'Anclaje...', + Name: 'Nombre', + Id: 'Id', + 'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.': 'Deber\u00eda comenzar por una letra, seguida solo de letras, n\u00fameros, guiones, puntos, dos puntos o guiones bajos.', + 'You have unsaved changes are you sure you want to navigate away?': 'Tiene cambios sin guardar. \u00bfEst\u00e1 seguro de que quiere salir?', + 'Restore last draft': 'Restaurar el \u00faltimo borrador', + 'Special character...': 'Car\u00e1cter especial...', + 'Source code': 'C\u00f3digo fuente', + 'Insert\/Edit code sample': 'Insertar\/editar c\u00f3digo de prueba', + Language: 'Idioma', + 'Code sample...': 'Ejemplo de c\u00f3digo...', + 'Color Picker': 'Selector de colores', + R: 'R', + G: 'V', + B: 'A', + 'Left to right': 'De izquierda a derecha', + 'Right to left': 'De derecha a izquierda', + 'Emoticons...': 'Emoticones...', + 'Metadata and Document Properties': 'Metadatos y propiedades del documento', + Title: 'T\u00edtulo', + Keywords: 'Palabras clave', + Description: 'Descripci\u00f3n', + Robots: 'Robots', + Author: 'Autor', + Encoding: 'Codificaci\u00f3n', + Fullscreen: 'Pantalla completa', + Action: 'Acci\u00f3n', + Shortcut: 'Atajo', + Help: 'Ayuda', + Address: 'Direcci\u00f3n', + 'Focus to menubar': 'Enfocar la barra del men\u00fa', + 'Focus to toolbar': 'Enfocar la barra de herramientas', + 'Focus to element path': 'Enfocar la ruta del elemento', + 'Focus to contextual toolbar': 'Enfocar la barra de herramientas contextual', + 'Insert link (if link plugin activated)': 'Insertar enlace (si el complemento de enlace est\u00e1 activado)', + 'Save (if save plugin activated)': 'Guardar (si el componente de salvar est\u00e1 activado)', + 'Find (if searchreplace plugin activated)': 'Buscar (si el complemento buscar-remplazar est\u00e1 activado)', + 'Plugins installed ({0}):': 'Plugins instalados ({0}):', + 'Premium plugins:': 'Complementos premium:', + 'Learn more...': 'Aprende m\u00e1s...', + 'You are using {0}': 'Estas usando {0}', + Plugins: 'Complementos', + 'Handy Shortcuts': 'Accesos directos', + 'Horizontal line': 'L\u00ednea horizontal', + 'Insert\/edit image': 'Insertar\/editar imagen', + 'Image description': 'Descripci\u00f3n de la imagen', + Source: 'Enlace', + Dimensions: 'Dimensiones', + 'Constrain proportions': 'Restringir proporciones', + General: 'General', + Advanced: 'Avanzado', + Style: 'Estilo', + 'Vertical space': 'Espacio vertical', + 'Horizontal space': 'Espacio horizontal', + Border: 'Borde', + 'Insert image': 'Insertar imagen', + 'Image...': 'Imagen...', + 'Image list': 'Lista de im\u00e1genes', + 'Rotate counterclockwise': 'Girar a la izquierda', + 'Rotate clockwise': 'Girar a la derecha', + 'Flip vertically': 'Invertir verticalmente', + 'Flip horizontally': 'Invertir horizontalmente', + 'Edit image': 'Editar imagen', + 'Image options': 'Opciones de imagen', + 'Zoom in': 'Acercar', + 'Zoom out': 'Alejar', + Crop: 'Recortar', + Resize: 'Redimensionar', + Orientation: 'Orientaci\u00f3n', + Brightness: 'Brillo', + Sharpen: 'Forma', + Contrast: 'Contraste', + 'Color levels': 'Niveles de color', + Gamma: 'Gamma', + Invert: 'Invertir', + Apply: 'Aplicar', + Back: 'Atr\u00e1s', + 'Insert date\/time': 'Insertar fecha\/hora', + 'Date\/time': 'Fecha\/hora', + 'Insert\/Edit Link': 'Insertar\/editar enlace', + 'Insert\/edit link': 'Insertar\/editar enlace', + 'Text to display': 'Texto para mostrar', + Url: 'URL', + 'Open link in...': 'Abrir enlace en...', + 'Current window': 'Ventana actual', + None: 'Ninguno', + 'New window': 'Nueva ventana', + 'Remove link': 'Quitar enlace', + Anchors: 'Anclas', + 'Link...': 'Enlace...', + 'Paste or type a link': 'Pega o introduce un enlace', + 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?': 'El enlace que has introducido no parece ser una direcci\u00f3n de correo electr\u00f3nico. Quieres a\u00f1adir el prefijo necesario mailto: ?', + 'The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?': 'El enlace que has introducido no parece ser una enlace externo. Quieres a\u00f1adir el prefijo necesario http:\/\/ ?', + 'Link list': 'Lista de enlaces', + 'Insert video': 'Insertar video', + 'Insert\/edit video': 'Insertar\/editar video', + 'Insert\/edit media': 'Insertar\/editar medio', + 'Alternative source': 'Enlace alternativo', + 'Alternative source URL': 'Origen de URL alternativo', + 'Media poster (Image URL)': 'P\u00f3ster de medio (URL de imagen)', + 'Paste your embed code below:': 'Pega tu c\u00f3digo embebido debajo', + Embed: 'Incrustado', + 'Media...': 'Medios...', + 'Nonbreaking space': 'Espacio fijo', + 'Page break': 'Salto de p\u00e1gina', + 'Paste as text': 'Pegar como texto', + Preview: 'Previsualizar', + 'Print...': 'Imprimir...', + Save: 'Guardar', + Find: 'Buscar', + 'Replace with': 'Reemplazar con', + Replace: 'Reemplazar', + 'Replace all': 'Reemplazar todo', + Previous: 'Anterior', + Next: 'Siguiente', + 'Find and replace...': 'Buscar y reemplazar...', + 'Could not find the specified string.': 'No se encuentra la cadena de texto especificada', + 'Match case': 'Coincidencia exacta', + 'Find whole words only': 'Solo palabras completas', + 'Spell check': 'Revisar ortograf\u00eda', + Ignore: 'Ignorar', + 'Ignore all': 'Ignorar todos', + Finish: 'Finalizar', + 'Add to Dictionary': 'A\u00f1adir al Diccionario', + 'Insert table': 'Insertar tabla', + 'Table properties': 'Propiedades de la tabla', + 'Delete table': 'Eliminar tabla', + Cell: 'Celda', + Row: 'Fila', + Column: 'Columna', + 'Cell properties': 'Propiedades de la celda', + 'Merge cells': 'Combinar celdas', + 'Split cell': 'Dividir celdas', + 'Insert row before': 'Insertar fila antes', + 'Insert row after': 'Insertar fila despu\u00e9s ', + 'Delete row': 'Eliminar fila', + 'Row properties': 'Propiedades de la fila', + 'Cut row': 'Cortar fila', + 'Copy row': 'Copiar fila', + 'Paste row before': 'Pegar la fila antes', + 'Paste row after': 'Pegar la fila despu\u00e9s', + 'Insert column before': 'Insertar columna antes', + 'Insert column after': 'Insertar columna despu\u00e9s', + 'Delete column': 'Eliminar columna', + Cols: 'Columnas', + Rows: 'Filas', + Width: 'Ancho', + Height: 'Alto', + 'Cell spacing': 'Espacio entre celdas', + 'Cell padding': 'Relleno de celda', + 'Show caption': 'Mostrar t\u00edtulo', + Left: 'Izquierda', + Center: 'Centrado', + Right: 'Derecha', + 'Cell type': 'Tipo de celda', + Scope: '\u00c1mbito', + Alignment: 'Alineaci\u00f3n', + 'H Align': 'Alineamiento Horizontal', + 'V Align': 'Alineamiento Vertical', + Top: 'Arriba', + Middle: 'Centro', + Bottom: 'Abajo', + 'Header cell': 'Celda de la cebecera', + 'Row group': 'Grupo de filas', + 'Column group': 'Grupo de columnas', + 'Row type': 'Tipo de fila', + Header: 'Cabecera', + Body: 'Cuerpo', + Footer: 'Pie de p\u00e1gina', + 'Border color': 'Color del borde', + 'Insert template...': 'Insertar plantilla...', + Templates: 'Plantillas', + Template: 'Plantilla', + 'Text color': 'Color del texto', + 'Background color': 'Color de fondo', + 'Custom...': 'Personalizar...', + 'Custom color': 'Color personalizado', + 'No color': 'Sin color', + 'Remove color': 'Quitar color', + 'Table of Contents': 'Tabla de contenidos', + 'Show blocks': 'Mostrar bloques', + 'Show invisible characters': 'Mostrar caracteres invisibles', + 'Word count': 'Contar palabras', + Count: 'Recuento', + Document: 'Documento', + Selection: 'Selecci\u00f3n', + Words: 'Palabras', + 'Words: {0}': 'Palabras: {0}', + '{0} words': '{0} palabras', + File: 'Archivo', + Edit: 'Editar', + Insert: 'Insertar', + View: 'Ver', + Format: 'Formato', + Table: 'Tabla', + Tools: 'Herramientas', + 'Powered by {0}': 'Desarrollado por {0}', + 'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help': '\u00c1rea de texto enriquecido. Pulse ALT-F9 para el menu. Pulse ALT-F10 para la barra de herramientas. Pulse ALT-0 para ayuda', + 'Image title': 'Titulo de imagen', + 'Border width': 'Ancho de borde', + 'Border style': 'Estilo de borde', + Error: 'Error', + Warn: 'Advertencia', + Valid: 'V\u00e1lido', + 'To open the popup, press Shift+Enter': 'Para abrir el elemento emergente, pulse May\u00fas+Intro', + 'Rich Text Area. Press ALT-0 for help.': '\u00c1rea de texto enriquecido. Pulse ALT-0 para abrir la ayuda.', + 'System Font': 'Fuente de sistema', + 'Failed to upload image: {0}': 'Fallo al cargar imagen: {0}', + 'Failed to load plugin: {0} from url {1}': 'Fallo al cargar complemento: {0} desde URL {1}', + 'Failed to load plugin url: {0}': 'Fallo al cargar URL del complemento: {0}', + 'Failed to initialize plugin: {0}': 'Fallo al iniciar el complemento: {0}', + example: 'ejemplo', + Search: 'Buscar', + All: 'Todo', + Currency: 'Divisa', + Text: 'Texto', + Quotations: 'Comillas', + Mathematical: 'S\u00edmbolo matem\u00e1tico', + 'Extended Latin': 'Latino extendido A', + Symbols: 'S\u00edmbolos', + Arrows: 'Flechas', + 'User Defined': 'Definido por el usuario', + 'dollar sign': 'signo de d\u00f3lar', + 'currency sign': 'signo de divisa', + 'euro-currency sign': 'signo de euro', + 'colon sign': 'signo de dos puntos', + 'cruzeiro sign': 'signo de cruceiro', + 'french franc sign': 'signo de franco franc\u00e9s', + 'lira sign': 'signo de lira', + 'mill sign': 'signo de mill', + 'naira sign': 'signo de naira', + 'peseta sign': 'signo de peseta', + 'rupee sign': 'signo de rupia', + 'won sign': 'signo de won', + 'new sheqel sign': 'signo de nuevo s\u00e9quel', + 'dong sign': 'signo de dong', + 'kip sign': 'signo de kip', + 'tugrik sign': 'signo de tugrik', + 'drachma sign': 'signo de dracma', + 'german penny symbol': 'signo de penique alem\u00e1n', + 'peso sign': 'signo de peso', + 'guarani sign': 'signo de guaran\u00ed', + 'austral sign': 'signo de austral', + 'hryvnia sign': 'signo de grivna', + 'cedi sign': 'signo de cedi', + 'livre tournois sign': 'signo de libra tornesa', + 'spesmilo sign': 'signo de spesmilo', + 'tenge sign': 'signo de tenge', + 'indian rupee sign': 'signo de rupia india', + 'turkish lira sign': 'signo de lira turca', + 'nordic mark sign': 'signo de marco n\u00f3rdico', + 'manat sign': 'signo de manat', + 'ruble sign': 'signo de rublo', + 'yen character': 'car\u00e1cter de yen', + 'yuan character': 'car\u00e1cter de yuan', + 'yuan character, in hong kong and taiwan': 'car\u00e1cter de yuan en Hong Kong y Taiw\u00e1n', + 'yen\/yuan character variant one': 'Variante uno de car\u00e1cter de yen\/yuan', + 'Loading emoticons...': 'Cargando emoticonos...', + 'Could not load emoticons': 'No se han podido cargar los emoticonos', + People: 'Personas', + 'Animals and Nature': 'Animales y naturaleza', + 'Food and Drink': 'Comida y bebida', + Activity: 'Actividad', + 'Travel and Places': 'Viajes y lugares', + Objects: 'Objetos', + Flags: 'Banderas', + Characters: 'Caracteres', + 'Characters (no spaces)': 'Caracteres (sin espacios)', + '{0} characters': '{0} caracteres', + 'Error: Form submit field collision.': 'Error: Colisi\u00f3n de campo al enviar formulario.', + 'Error: No form element found.': 'Error: No se encuentra ning\u00fan elemento de formulario.', + Update: 'Actualizar', + 'Color swatch': 'Muestrario de colores', + Turquoise: 'Turquesa', + Green: 'Verde', + Blue: 'Azul', + Purple: 'P\u00farpura', + 'Navy Blue': 'Azul marino', + 'Dark Turquoise': 'Turquesa oscuro', + 'Dark Green': 'Verde oscuro', + 'Medium Blue': 'Azul medio', + 'Medium Purple': 'P\u00farpura medio', + 'Midnight Blue': 'Azul medio', + Yellow: 'Amarillo', + Orange: 'Naranja', + Red: 'Rojo', + 'Light Gray': 'Gris claro', + Gray: 'Gris', + 'Dark Yellow': 'Amarillo oscuro', + 'Dark Orange': 'Naranja oscuro', + 'Dark Red': 'Rojo oscuro', + 'Medium Gray': 'Gris medio', + 'Dark Gray': 'Gris oscuro', + 'Light Green': 'Verde claro', + 'Light Yellow': 'Amarillo claro', + 'Light Red': 'Rojo claro', + 'Light Purple': 'Morado claro', + 'Light Blue': 'Azul claro', + 'Dark Purple': 'Morado oscuro', + 'Dark Blue': 'Azul oscuro', + Black: 'Negro', + White: 'Blanco', + 'Switch to or from fullscreen mode': 'Activar o desactivar modo pantalla completa', + 'Open help dialog': 'Abrir di\u00e1logo de ayuda', + history: 'historial', + styles: 'estilos', + formatting: 'formato', + alignment: 'alineaci\u00f3n', + indentation: 'sangr\u00eda', + 'permanent pen': 'bol\u00edgrafo permanente', + comments: 'comentarios', + 'Format Painter': 'Copiar formato', + 'Insert\/edit iframe': 'Insertar\/editar iframe', + Capitalization: 'Uso de may\u00fasculas', + lowercase: 'min\u00fasculas', + UPPERCASE: 'MAY\u00daSCULAS', + 'Title Case': 'Tipo T\u00edtulo', + 'Permanent Pen Properties': 'Propiedades del bol\u00edgrafo permanente', + 'Permanent pen properties...': 'Propiedades del bol\u00edgrafo permanente...', + Font: 'Fuente', + Size: 'Tama\u00f1o', + 'More...': 'M\u00e1s...', + 'Spellcheck Language': 'Corrector', + 'Select...': 'Seleccionar...', + Preferences: 'Preferencias', + Yes: 'S\u00ed', + No: 'No', + 'Keyboard Navigation': 'Navegaci\u00f3n con el teclado', + Version: 'Versi\u00f3n', + Anchor: 'Ancla', + 'Special character': 'Car\u00e1cter especial', + 'Code sample': 'Ejemplo de c\u00f3digo', + Color: 'Color', + Emoticons: 'Emoticonos', + 'Document properties': 'Propiedades del documento', + Image: 'Imagen', + 'Insert link': 'Insertar enlace', + Target: 'Destino', + Link: 'Enlace', + Poster: 'Miniatura', + Media: 'Media', + Print: 'Imprimir', + Prev: 'Anterior', + 'Find and replace': 'Buscar y reemplazar', + 'Whole words': 'Palabras completas', + Spellcheck: 'Corrector ortogr\u00e1fico', + Caption: 'Subt\u00edtulo', + 'Insert template': 'Insertar plantilla' +}) diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/langs/zh-CN.js b/apps/vben5/apps/app-antd/public/resource/tinymce/langs/zh-CN.js new file mode 100644 index 000000000..f9d8b5cfd --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/langs/zh-CN.js @@ -0,0 +1,389 @@ +tinymce.addI18n('zh_CN',{ +"Redo": "\u91cd\u505a", +"Undo": "\u64a4\u9500", +"Cut": "\u526a\u5207", +"Copy": "\u590d\u5236", +"Paste": "\u7c98\u8d34", +"Select all": "\u5168\u9009", +"New document": "\u65b0\u6587\u4ef6", +"Ok": "\u786e\u5b9a", +"Cancel": "\u53d6\u6d88", +"Visual aids": "\u7f51\u683c\u7ebf", +"Bold": "\u7c97\u4f53", +"Italic": "\u659c\u4f53", +"Underline": "\u4e0b\u5212\u7ebf", +"Strikethrough": "\u5220\u9664\u7ebf", +"Superscript": "\u4e0a\u6807", +"Subscript": "\u4e0b\u6807", +"Clear formatting": "\u6e05\u9664\u683c\u5f0f", +"Align left": "\u5de6\u8fb9\u5bf9\u9f50", +"Align center": "\u4e2d\u95f4\u5bf9\u9f50", +"Align right": "\u53f3\u8fb9\u5bf9\u9f50", +"Justify": "\u4e24\u7aef\u5bf9\u9f50", +"Bullet list": "\u9879\u76ee\u7b26\u53f7", +"Numbered list": "\u7f16\u53f7\u5217\u8868", +"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb", +"Increase indent": "\u589e\u52a0\u7f29\u8fdb", +"Close": "\u5173\u95ed", +"Formats": "\u683c\u5f0f", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002", +"Headers": "\u6807\u9898", +"Header 1": "\u6807\u98981", +"Header 2": "\u6807\u98982", +"Header 3": "\u6807\u98983", +"Header 4": "\u6807\u98984", +"Header 5": "\u6807\u98985", +"Header 6": "\u6807\u98986", +"Headings": "\u6807\u9898", +"Heading 1": "\u6807\u98981", +"Heading 2": "\u6807\u98982", +"Heading 3": "\u6807\u98983", +"Heading 4": "\u6807\u98984", +"Heading 5": "\u6807\u98985", +"Heading 6": "\u6807\u98986", +"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684", +"Div": "Div", +"Pre": "Pre", +"Code": "\u4ee3\u7801", +"Paragraph": "\u6bb5\u843d", +"Blockquote": "\u5f15\u6587\u533a\u5757", +"Inline": "\u6587\u672c", +"Blocks": "\u57fa\u5757", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002", +"Fonts": "\u5b57\u4f53", +"Font Sizes": "\u5b57\u53f7", +"Class": "\u7c7b\u578b", +"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf", +"OR": "\u6216", +"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64", +"Upload": "\u4e0a\u4f20", +"Block": "\u5757", +"Align": "\u5bf9\u9f50", +"Default": "\u9ed8\u8ba4", +"Circle": "\u7a7a\u5fc3\u5706", +"Disc": "\u5b9e\u5fc3\u5706", +"Square": "\u65b9\u5757", +"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd", +"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd", +"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd", +"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd", +"Anchor...": "\u951a\u70b9...", +"Name": "\u540d\u79f0", +"Id": "\u6807\u8bc6\u7b26", +"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002", +"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f", +"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f", +"Special characters...": "\u7279\u6b8a\u5b57\u7b26...", +"Source code": "\u6e90\u4ee3\u7801", +"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b", +"Language": "\u8bed\u8a00", +"Code sample...": "\u793a\u4f8b\u4ee3\u7801...", +"Color Picker": "\u9009\u8272\u5668", +"R": "R", +"G": "G", +"B": "B", +"Left to right": "\u4ece\u5de6\u5230\u53f3", +"Right to left": "\u4ece\u53f3\u5230\u5de6", +"Emoticons...": "\u8868\u60c5\u7b26\u53f7...", +"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027", +"Title": "\u6807\u9898", +"Keywords": "\u5173\u952e\u8bcd", +"Description": "\u63cf\u8ff0", +"Robots": "\u673a\u5668\u4eba", +"Author": "\u4f5c\u8005", +"Encoding": "\u7f16\u7801", +"Fullscreen": "\u5168\u5c4f", +"Action": "\u64cd\u4f5c", +"Shortcut": "\u5feb\u6377\u952e", +"Help": "\u5e2e\u52a9", +"Address": "\u5730\u5740", +"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f", +"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f", +"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84", +"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355", +"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)", +"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):", +"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a", +"Learn more...": "\u4e86\u89e3\u66f4\u591a...", +"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}", +"Plugins": "\u63d2\u4ef6", +"Handy Shortcuts": "\u5feb\u6377\u952e", +"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf", +"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247", +"Image description": "\u56fe\u7247\u63cf\u8ff0", +"Source": "\u5730\u5740", +"Dimensions": "\u5927\u5c0f", +"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4", +"General": "\u666e\u901a", +"Advanced": "\u9ad8\u7ea7", +"Style": "\u6837\u5f0f", +"Vertical space": "\u5782\u76f4\u8fb9\u8ddd", +"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd", +"Border": "\u8fb9\u6846", +"Insert image": "\u63d2\u5165\u56fe\u7247", +"Image...": "\u56fe\u7247...", +"Image list": "\u56fe\u7247\u5217\u8868", +"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c", +"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c", +"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c", +"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c", +"Edit image": "\u7f16\u8f91\u56fe\u7247", +"Image options": "\u56fe\u7247\u9009\u9879", +"Zoom in": "\u653e\u5927", +"Zoom out": "\u7f29\u5c0f", +"Crop": "\u88c1\u526a", +"Resize": "\u8c03\u6574\u5927\u5c0f", +"Orientation": "\u65b9\u5411", +"Brightness": "\u4eae\u5ea6", +"Sharpen": "\u9510\u5316", +"Contrast": "\u5bf9\u6bd4\u5ea6", +"Color levels": "\u989c\u8272\u5c42\u6b21", +"Gamma": "\u4f3d\u9a6c\u503c", +"Invert": "\u53cd\u8f6c", +"Apply": "\u5e94\u7528", +"Back": "\u540e\u9000", +"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4", +"Date\/time": "\u65e5\u671f\/\u65f6\u95f4", +"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5", +"Text to display": "\u663e\u793a\u6587\u5b57", +"Url": "\u5730\u5740", +"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...", +"Current window": "\u5f53\u524d\u7a97\u53e3", +"None": "\u65e0", +"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00", +"Remove link": "\u5220\u9664\u94fe\u63a5", +"Anchors": "\u951a\u70b9", +"Link...": "\u94fe\u63a5...", +"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f", +"Link list": "\u94fe\u63a5\u5217\u8868", +"Insert video": "\u63d2\u5165\u89c6\u9891", +"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891", +"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53", +"Alternative source": "\u955c\u50cf", +"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740", +"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)", +"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:", +"Embed": "\u5185\u5d4c", +"Media...": "\u591a\u5a92\u4f53...", +"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c", +"Page break": "\u5206\u9875\u7b26", +"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c", +"Preview": "\u9884\u89c8", +"Print...": "\u6253\u5370...", +"Save": "\u4fdd\u5b58", +"Find": "\u67e5\u627e", +"Replace with": "\u66ff\u6362\u4e3a", +"Replace": "\u66ff\u6362", +"Replace all": "\u5168\u90e8\u66ff\u6362", +"Previous": "\u4e0a\u4e00\u4e2a", +"Next": "\u4e0b\u4e00\u4e2a", +"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...", +"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.", +"Match case": "\u533a\u5206\u5927\u5c0f\u5199", +"Find whole words only": "\u5168\u5b57\u5339\u914d", +"Spell check": "\u62fc\u5199\u68c0\u67e5", +"Ignore": "\u5ffd\u7565", +"Ignore all": "\u5168\u90e8\u5ffd\u7565", +"Finish": "\u5b8c\u6210", +"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178", +"Insert table": "\u63d2\u5165\u8868\u683c", +"Table properties": "\u8868\u683c\u5c5e\u6027", +"Delete table": "\u5220\u9664\u8868\u683c", +"Cell": "\u5355\u5143\u683c", +"Row": "\u884c", +"Column": "\u5217", +"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027", +"Merge cells": "\u5408\u5e76\u5355\u5143\u683c", +"Split cell": "\u62c6\u5206\u5355\u5143\u683c", +"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165", +"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165", +"Delete row": "\u5220\u9664\u884c", +"Row properties": "\u884c\u5c5e\u6027", +"Cut row": "\u526a\u5207\u884c", +"Copy row": "\u590d\u5236\u884c", +"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9", +"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9", +"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165", +"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165", +"Delete column": "\u5220\u9664\u5217", +"Cols": "\u5217", +"Rows": "\u884c", +"Width": "\u5bbd", +"Height": "\u9ad8", +"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd", +"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd", +"Show caption": "\u663e\u793a\u6807\u9898", +"Left": "\u5de6\u5bf9\u9f50", +"Center": "\u5c45\u4e2d", +"Right": "\u53f3\u5bf9\u9f50", +"Cell type": "\u5355\u5143\u683c\u7c7b\u578b", +"Scope": "\u8303\u56f4", +"Alignment": "\u5bf9\u9f50\u65b9\u5f0f", +"H Align": "\u6c34\u5e73\u5bf9\u9f50", +"V Align": "\u5782\u76f4\u5bf9\u9f50", +"Top": "\u9876\u90e8\u5bf9\u9f50", +"Middle": "\u5782\u76f4\u5c45\u4e2d", +"Bottom": "\u5e95\u90e8\u5bf9\u9f50", +"Header cell": "\u8868\u5934\u5355\u5143\u683c", +"Row group": "\u884c\u7ec4", +"Column group": "\u5217\u7ec4", +"Row type": "\u884c\u7c7b\u578b", +"Header": "\u8868\u5934", +"Body": "\u8868\u4f53", +"Footer": "\u8868\u5c3e", +"Border color": "\u8fb9\u6846\u989c\u8272", +"Insert template...": "\u63d2\u5165\u6a21\u677f...", +"Templates": "\u6a21\u677f", +"Template": "\u6a21\u677f", +"Text color": "\u6587\u5b57\u989c\u8272", +"Background color": "\u80cc\u666f\u8272", +"Custom...": "\u81ea\u5b9a\u4e49...", +"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272", +"No color": "\u65e0", +"Remove color": "\u79fb\u9664\u989c\u8272", +"Table of Contents": "\u5185\u5bb9\u5217\u8868", +"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846", +"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26", +"Word count": "\u5b57\u6570", +"Words: {0}": "\u5b57\u6570\uff1a{0}", +"{0} words": "{0} \u5b57", +"File": "\u6587\u4ef6", +"Edit": "\u7f16\u8f91", +"Insert": "\u63d2\u5165", +"View": "\u89c6\u56fe", +"Format": "\u683c\u5f0f", +"Table": "\u8868\u683c", +"Tools": "\u5de5\u5177", +"Powered by {0}": "\u7531{0}\u9a71\u52a8", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9", +"Image title": "\u56fe\u7247\u6807\u9898", +"Border width": "\u8fb9\u6846\u5bbd\u5ea6", +"Border style": "\u8fb9\u6846\u6837\u5f0f", +"Error": "\u9519\u8bef", +"Warn": "\u8b66\u544a", +"Valid": "\u6709\u6548", +"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846", +"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002", +"System Font": "\u7cfb\u7edf\u5b57\u4f53", +"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}", +"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}", +"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}", +"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}", +"example": "\u793a\u4f8b", +"Search": "\u641c\u7d22", +"All": "\u5168\u90e8", +"Currency": "\u8d27\u5e01", +"Text": "\u6587\u5b57", +"Quotations": "\u5f15\u7528", +"Mathematical": "\u6570\u5b66", +"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145", +"Symbols": "\u7b26\u53f7", +"Arrows": "\u7bad\u5934", +"User Defined": "\u81ea\u5b9a\u4e49", +"dollar sign": "\u7f8e\u5143\u7b26\u53f7", +"currency sign": "\u8d27\u5e01\u7b26\u53f7", +"euro-currency sign": "\u6b27\u5143\u7b26\u53f7", +"colon sign": "\u5192\u53f7", +"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7", +"french franc sign": "\u6cd5\u90ce\u7b26\u53f7", +"lira sign": "\u91cc\u62c9\u7b26\u53f7", +"mill sign": "\u5bc6\u5c14\u7b26\u53f7", +"naira sign": "\u5948\u62c9\u7b26\u53f7", +"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7", +"rupee sign": "\u5362\u6bd4\u7b26\u53f7", +"won sign": "\u97e9\u5143\u7b26\u53f7", +"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7", +"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7", +"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7", +"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7", +"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7", +"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7", +"peso sign": "\u6bd4\u7d22\u7b26\u53f7", +"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7", +"austral sign": "\u6fb3\u5143\u7b26\u53f7", +"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7", +"cedi sign": "\u585e\u5730\u7b26\u53f7", +"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7", +"spesmilo sign": "spesmilo\u7b26\u53f7", +"tenge sign": "\u575a\u6208\u7b26\u53f7", +"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4", +"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9", +"nordic mark sign": "\u5317\u6b27\u9a6c\u514b", +"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7", +"ruble sign": "\u5362\u5e03\u7b26\u53f7", +"yen character": "\u65e5\u5143\u5b57\u6837", +"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837", +"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09", +"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09", +"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...", +"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7", +"People": "\u4eba\u7c7b", +"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136", +"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1", +"Activity": "\u6d3b\u52a8", +"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9", +"Objects": "\u7269\u4ef6", +"Flags": "\u65d7\u5e1c", +"Characters": "\u5b57\u7b26", +"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)", +"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002", +"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002", +"Update": "\u66f4\u65b0", +"Color swatch": "\u989c\u8272\u6837\u672c", +"Turquoise": "\u9752\u7eff\u8272", +"Green": "\u7eff\u8272", +"Blue": "\u84dd\u8272", +"Purple": "\u7d2b\u8272", +"Navy Blue": "\u6d77\u519b\u84dd", +"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272", +"Dark Green": "\u6df1\u7eff\u8272", +"Medium Blue": "\u4e2d\u84dd\u8272", +"Medium Purple": "\u4e2d\u7d2b\u8272", +"Midnight Blue": "\u6df1\u84dd\u8272", +"Yellow": "\u9ec4\u8272", +"Orange": "\u6a59\u8272", +"Red": "\u7ea2\u8272", +"Light Gray": "\u6d45\u7070\u8272", +"Gray": "\u7070\u8272", +"Dark Yellow": "\u6697\u9ec4\u8272", +"Dark Orange": "\u6df1\u6a59\u8272", +"Dark Red": "\u6df1\u7ea2\u8272", +"Medium Gray": "\u4e2d\u7070\u8272", +"Dark Gray": "\u6df1\u7070\u8272", +"Black": "\u9ed1\u8272", +"White": "\u767d\u8272", +"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f", +"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846", +"history": "\u5386\u53f2", +"styles": "\u6837\u5f0f", +"formatting": "\u683c\u5f0f\u5316", +"alignment": "\u5bf9\u9f50", +"indentation": "\u7f29\u8fdb", +"permanent pen": "\u8bb0\u53f7\u7b14", +"comments": "\u5907\u6ce8", +"Anchor": "\u951a\u70b9", +"Special character": "\u7279\u6b8a\u7b26\u53f7", +"Code sample": "\u4ee3\u7801\u793a\u4f8b", +"Color": "\u989c\u8272", +"Emoticons": "\u8868\u60c5", +"Document properties": "\u6587\u6863\u5c5e\u6027", +"Image": "\u56fe\u7247", +"Insert link": "\u63d2\u5165\u94fe\u63a5", +"Target": "\u6253\u5f00\u65b9\u5f0f", +"Link": "\u94fe\u63a5", +"Poster": "\u5c01\u9762", +"Media": "\u5a92\u4f53", +"Print": "\u6253\u5370", +"Prev": "\u4e0a\u4e00\u4e2a", +"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362", +"Whole words": "\u5168\u5b57\u5339\u914d", +"Spellcheck": "\u62fc\u5199\u68c0\u67e5", +"Caption": "\u6807\u9898", +"Insert template": "\u63d2\u5165\u6a21\u677f" +}); \ No newline at end of file diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css new file mode 100644 index 000000000..748f313bb --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.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--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.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;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.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;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +.tox-toolbar-dock-fadeout{opacity: 0;visibility: hidden;} + +.tox-toolbar-dock-fadein{opacity: 1;visibility: visible;} + +.tox-toolbar-dock-transition{transition: visibility 0s linear .3s,opacity .3s ease;} + +.tox-toolbar-dock-transition.tox-toolbar-dock-fadein{transition-delay: 0s;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.min.css new file mode 100644 index 000000000..6e7165f09 --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.min.css @@ -0,0 +1,235 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.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--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.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;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.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;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css new file mode 100644 index 000000000..c0522520e --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css @@ -0,0 +1,17 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} + +body{-webkit-text-size-adjust: none;} + +body img{max-width: 96vw;} + +body table img{max-width: 95%;} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css new file mode 100644 index 000000000..d8dc9b2da --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css @@ -0,0 +1,875 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tox{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-style: normal;font-weight: 400;line-height: normal;color: #222f3e;text-decoration: none;text-shadow: none;text-transform: none;white-space: normal;vertical-align: initial;cursor: auto;box-sizing: content-box;-webkit-tap-highlight-color: transparent;} + +.tox :not(svg){font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;line-height: inherit;color: inherit;text-align: inherit;text-decoration: inherit;text-shadow: inherit;text-transform: inherit;white-space: inherit;vertical-align: inherit;cursor: inherit;box-sizing: inherit;direction: inherit;-webkit-tap-highlight-color: inherit;} + +.tox :not(svg){position: static;float: none;width: auto;height: auto;max-width: none;padding: 0;margin: 0;background: 0 0;border: 0;outline: 0;} + +.tox:not([dir=rtl]){text-align: left;direction: ltr;} + +.tox[dir=rtl]{text-align: right;direction: rtl;} + +.tox-tinymce{position: relative;display: flex;overflow: hidden;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;border: 1px solid #000;border-radius: 0;visibility: inherit !important;box-shadow: none;box-sizing: border-box;flex-direction: column;} + +.tox-editor-container{display: flex;flex: 1 1 auto;flex-direction: column;overflow: hidden;} + +.tox-editor-container>:first-child{border-top: none !important;} + +.tox-tinymce-aux{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} + +.tox-tinymce :focus,.tox-tinymce-aux :focus{outline: 0;} + +button::-moz-focus-inner{border: 0;} + +.tox-silver-sink{z-index: 1300;} + +.tox .tox-anchorbar{display: flex;flex: 0 0 auto;} + +.tox .tox-bar{display: flex;flex: 0 0 auto;} + +.tox .tox-button{display: inline-block;padding: 4px 16px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 14px;font-weight: 700;line-height: 24px;letter-spacing: 1;color: #fff;text-align: center;text-decoration: none;text-transform: capitalize;white-space: nowrap;cursor: pointer;background-color: #207ab7;background-image: none;background-position: none;background-repeat: none;border-color: #207ab7;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-button[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: #207ab7;background-image: none;border-color: #207ab7;box-shadow: none;} + +.tox .tox-button:focus:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:hover:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:active:not(:disabled){color: #fff;background-color: #185d8c;background-image: none;border-color: #185d8c;box-shadow: none;} + +.tox .tox-button--secondary{padding: 4px 16px;color: #fff;text-decoration: none;text-transform: capitalize;background-color: #3d546f;background-image: none;background-position: none;background-repeat: none;border-color: #3d546f;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;} + +.tox .tox-button--secondary[disabled]{color: rgba(255,255,255,.5);background-color: #3d546f;background-image: none;border-color: #3d546f;box-shadow: none;} + +.tox .tox-button--secondary:focus:not(:disabled){color: #fff;background-color: #34485f;background-image: none;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--secondary:hover:not(:disabled){color: #fff;background-color: #34485f;background-image: none;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--secondary:active:not(:disabled){color: #fff;background-color: #2b3b4e;background-image: none;border-color: #2b3b4e;box-shadow: none;} + +.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding: 4px;} + +.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display: block;fill: currentColor;} + +.tox .tox-button-link{display: inline-block;padding: 0;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-weight: 400;line-height: 1.3;white-space: nowrap;cursor: pointer;background: 0;border: none;box-sizing: border-box;} + +.tox .tox-button-link--sm{font-size: 14px;} + +.tox .tox-button--naked{color: #fff;background-color: transparent;border-color: transparent;box-shadow: unset;} + +.tox .tox-button--naked:hover:not(:disabled){color: #fff;background-color: #34485f;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--naked:focus:not(:disabled){color: #fff;background-color: #34485f;border-color: #34485f;box-shadow: none;} + +.tox .tox-button--naked:active:not(:disabled){color: #fff;background-color: #2b3b4e;border-color: #2b3b4e;box-shadow: none;} + +.tox .tox-button--naked .tox-icon svg{fill: currentColor;} + +.tox .tox-button--naked.tox-button--icon{color: currentColor;} + +.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color: #fff;} + +.tox .tox-checkbox{display: flex;height: 36px;min-width: 36px;cursor: pointer;border-radius: 3px;align-items: center;} + +.tox .tox-checkbox__input{position: absolute;top: auto;left: -10000px;width: 1px;height: 1px;overflow: hidden;} + +.tox .tox-checkbox__icons{width: 24px;height: 24px;padding: calc(4px - 1px);border-radius: 3px;box-shadow: 0 0 0 2px transparent;box-sizing: content-box;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: block;fill: rgba(255,255,255,.2);} + +.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: none;fill: #207ab7;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display: none;fill: #207ab7;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display: block;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: block;} + +.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{padding: calc(4px - 1px);border-radius: 3px;box-shadow: inset 0 0 0 1px #207ab7;} + +.tox:not([dir=rtl]) .tox-checkbox__label{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left: 4px;} + +.tox[dir=rtl] .tox-checkbox__label{margin-right: 4px;} + +.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right: 4px;} + +.tox .tox-collection--toolbar .tox-collection__group{display: flex;padding: 0;} + +.tox .tox-collection--grid .tox-collection__group{display: flex;max-height: 208px;padding: 0;overflow-x: hidden;overflow-y: auto;flex-wrap: wrap;} + +.tox .tox-collection--list .tox-collection__group{padding: 4px 0;border-color: #1a1a1a;border-style: solid;border-top-width: 1px;border-right-width: 0;border-bottom-width: 0;border-left-width: 0;} + +.tox .tox-collection--list .tox-collection__group:first-child{border-top-width: 0;} + +.tox .tox-collection__group-heading{padding: 4px 8px;margin-top: -4px;margin-bottom: 4px;font-size: 12px;font-style: normal;font-weight: 400;color: #fff;text-transform: none;cursor: default;background-color: #333;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;-webkit-touch-callout: none;} + +.tox .tox-collection__item{display: flex;color: #fff;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;align-items: center;-webkit-touch-callout: none;} + +.tox .tox-collection--list .tox-collection__item{padding: 4px 8px;} + +.tox .tox-collection--toolbar .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--grid .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--list .tox-collection__item--enabled{color: contrast(inherit,#222f3e,#fff);background-color: inherit;} + +.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection--toolbar .tox-collection__item--enabled{color: #fff;background-color: #6f7882;} + +.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection--grid .tox-collection__item--enabled{color: #fff;background-color: #6f7882;} + +.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #fff;background-color: #434e5b;} + +.tox .tox-collection__item--state-disabled{color: rgba(255,255,255,.5);cursor: default;background-color: transparent;} + +.tox .tox-collection__item-icon{display: flex;width: 24px;height: 24px;align-items: center;justify-content: center;} + +.tox .tox-collection__item-icon svg{fill: currentColor;} + +.tox .tox-collection--toolbar-lg .tox-collection__item-icon{width: 48px;height: 48px;} + +.tox .tox-collection__item[role=menuitemcheckbox]:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display: none;} + +.tox .tox-collection__item-label{display: inline-block;font-size: 14px;font-style: normal;font-weight: 400;line-height: 24px;color: currentColor;text-transform: none;word-break: break-all;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-collection__item-accessory{display: inline-block;height: 24px;font-size: 14px;line-height: 24px;color: rgba(255,255,255,.5);text-transform: normal;} + +.tox .tox-collection__item-caret{align-items: center;display: flex;min-height: 24px;} + +.tox .tox-collection__item-caret::after{min-height: inherit;font-size: 0;content: '';} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item-label:first-child{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left: 16px;text-align: right;} + +.tox:not([dir=rtl]) .tox-collection__item-caret{margin-left: 16px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right: 8px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item-label:first-child{margin-right: 4px;} + +.tox[dir=rtl] .tox-collection__item-icon-rtl .tox-collection__item-icon svg{transform: rotateY(180deg);} + +.tox[dir=rtl] .tox-collection__item-accessory{margin-right: 16px;text-align: left;} + +.tox[dir=rtl] .tox-collection__item-caret{margin-right: 16px;transform: rotateY(180deg);} + +.tox .tox-color-picker-container{display: flex;flex-direction: row;height: 225px;margin: 0;} + +.tox .tox-sv-palette{display: flex;height: 100%;box-sizing: border-box;} + +.tox .tox-sv-palette-spectrum{height: 100%;} + +.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width: 225px;} + +.tox .tox-sv-palette-thumb{position: absolute;width: 12px;height: 12px;background: 0 0;border: 1px solid #000;border-radius: 50%;box-sizing: content-box;} + +.tox .tox-sv-palette-inner-thumb{position: absolute;width: 10px;height: 10px;border: 1px solid #fff;border-radius: 50%;} + +.tox .tox-hue-slider{width: 25px;height: 100%;box-sizing: border-box;} + +.tox .tox-hue-slider-spectrum{width: 100%;height: 100%;background: linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);} + +.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width: 20px;} + +.tox .tox-hue-slider-thumb{width: 100%;height: 4px;background: #fff;border: 1px solid #000;box-sizing: content-box;} + +.tox .tox-rgb-form{display: flex;flex-direction: column;justify-content: space-between;} + +.tox .tox-rgb-form div{display: flex;width: inherit;margin-bottom: 5px;align-items: center;justify-content: space-between;} + +.tox .tox-rgb-form input{width: 6em;} + +.tox .tox-rgb-form input.tox-invalid{border: 1px solid red !important;} + +.tox .tox-rgb-form .tox-rgba-preview{margin-bottom: 0;border: 1px solid #000;flex-grow: 2;} + +.tox:not([dir=rtl]) .tox-sv-palette{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left: -1px;} + +.tox:not([dir=rtl]) .tox-rgb-form label{margin-right: .5em;} + +.tox[dir=rtl] .tox-sv-palette{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider-thumb{margin-right: -1px;} + +.tox[dir=rtl] .tox-rgb-form label{margin-left: .5em;} + +.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin: 2px 0 3px 4px;} + +.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{margin: -4px 0;border: 0;} + +.tox .tox-swatches__row{display: flex;} + +.tox .tox-swatch{width: 30px;height: 30px;transition: transform .15s,box-shadow .15s;} + +.tox .tox-swatch:focus,.tox .tox-swatch:hover{transform: scale(.8);box-shadow: 0 0 0 1px rgba(127,127,127,.3) inset;} + +.tox .tox-swatch--remove{align-items: center;display: flex;justify-content: center;} + +.tox .tox-swatch--remove svg path{stroke: #e74c3c;} + +.tox .tox-swatches__picker-btn{display: flex;width: 30px;height: 30px;padding: 0;cursor: pointer;background-color: transparent;border: 0;outline: 0;align-items: center;justify-content: center;} + +.tox .tox-swatches__picker-btn svg{width: 24px;height: 24px;} + +.tox .tox-swatches__picker-btn:hover{background: #434e5b;} + +.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left: auto;} + +.tox[dir=rtl] .tox-swatches__picker-btn{margin-right: auto;} + +.tox .tox-comment-thread{position: relative;background: #2b3b4e;} + +.tox .tox-comment-thread>:not(:first-child){margin-top: 8px;} + +.tox .tox-comment{position: relative;padding: 8px 8px 16px 8px;background: #2b3b4e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-comment__header{display: flex;color: #fff;align-items: center;justify-content: space-between;} + +.tox .tox-comment__date{font-size: 12px;color: rgba(255,255,255,.5);} + +.tox .tox-comment__body{position: relative;margin-top: 8px;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: #fff;text-transform: initial;} + +.tox .tox-comment__body textarea{width: 100%;white-space: normal;resize: none;} + +.tox .tox-comment__expander{padding-top: 8px;} + +.tox .tox-comment__expander p{font-size: 14px;font-style: normal;color: rgba(255,255,255,.5);} + +.tox .tox-comment__body p{margin: 0;} + +.tox .tox-comment__buttonspacing{padding-top: 16px;text-align: center;} + +.tox .tox-comment-thread__overlay::after{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;background: #2b3b4e;content: "";opacity: .9;} + +.tox .tox-comment__reply{display: flex;flex-shrink: 0;flex-wrap: wrap;justify-content: flex-end;margin-top: 8px;} + +.tox .tox-comment__reply>:first-child{width: 100%;margin-bottom: 8px;} + +.tox .tox-comment__edit{display: flex;flex-wrap: wrap;justify-content: flex-end;margin-top: 16px;} + +.tox .tox-comment__gradient::after{position: absolute;bottom: 0;display: block;width: 100%;height: 5em;margin-top: -40px;background: linear-gradient(rgba(43,59,78,0),#2b3b4e);content: "";} + +.tox .tox-comment__overlay{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;text-align: center;background: #2b3b4e;opacity: .9;flex-direction: column;flex-grow: 1;} + +.tox .tox-comment__loading-text{position: relative;display: flex;color: #fff;align-items: center;flex-direction: column;} + +.tox .tox-comment__loading-text>div{padding-bottom: 16px;} + +.tox .tox-comment__overlaytext{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 10;padding: 1em;font-size: 14px;flex-direction: column;} + +.tox .tox-comment__overlaytext p{color: #fff;text-align: center;background-color: #2b3b4e;box-shadow: 0 0 8px 8px #2b3b4e;} + +.tox .tox-comment__overlaytext div:nth-of-type(2){font-size: .8em;} + +.tox .tox-comment__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: #2b3b4e;align-items: center;justify-content: center;} + +.tox .tox-comment__scroll{display: flex;flex-direction: column;flex-shrink: 1;overflow: auto;} + +.tox .tox-conversations{margin: 8px;} + +.tox:not([dir=rtl]) .tox-comment__edit{margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left: 8px;} + +.tox[dir=rtl] .tox-comment__edit{margin-right: 8px;} + +.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right: 8px;} + +.tox .tox-user{align-items: center;display: flex;} + +.tox .tox-user__avatar svg{fill: rgba(255,255,255,.5);} + +.tox .tox-user__name{font-size: 12px;font-style: normal;font-weight: 700;color: rgba(255,255,255,.5);text-transform: uppercase;} + +.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right: 8px;} + +.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar svg{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right: 8px;} + +.tox .tox-dialog-wrap{position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 1100;display: flex;align-items: center;justify-content: center;} + +.tox .tox-dialog-wrap__backdrop{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1101;background-color: rgba(34,47,62,.75);} + +.tox .tox-dialog{position: relative;z-index: 1102;display: flex;width: 95vw;max-width: 480px;max-height: 100%;overflow: hidden;background-color: #2b3b4e;border-color: #000;border-style: solid;border-width: 1px;border-radius: 3px;box-shadow: 0 16px 16px -10px rgba(34,47,62,.15),0 0 40px 1px rgba(34,47,62,.15);flex-direction: column;} + +.tox .tox-dialog__header{position: relative;display: flex;padding: 8px 16px 0 16px;margin-bottom: 16px;font-size: 16px;color: #fff;background-color: #2b3b4e;border-bottom: none;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__header .tox-button{z-index: 1;} + +.tox .tox-dialog__draghandle{position: absolute;top: 0;left: 0;width: 100%;height: 100%;cursor: grab;} + +.tox .tox-dialog__draghandle:active{cursor: grabbing;} + +.tox .tox-dialog__dismiss{margin-left: auto;} + +.tox .tox-dialog__title{margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 20px;font-style: normal;font-weight: 400;line-height: 1.3;text-transform: normal;} + +.tox .tox-dialog__body{display: flex;min-width: 0;padding: 0 16px;font-size: 16px;font-style: normal;font-weight: 400;line-height: 1.3;color: #fff;text-align: left;text-transform: normal;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-nav{align-items: flex-start;display: flex;flex-direction: column;} + +.tox .tox-dialog__body-nav-item{display: inline-block;margin-bottom: 8px;font-size: 14px;line-height: 1.3;color: rgba(255,255,255,.5);text-decoration: none;border-bottom: 2px solid transparent;} + +.tox .tox-dialog__body-nav-item--active{color: #207ab7;border-bottom: 2px solid #207ab7;} + +.tox .tox-dialog__body-content{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;max-height: 650px;overflow: auto;} + +.tox .tox-dialog__body-content>*{margin-top: 16px;margin-bottom: 0;} + +.tox .tox-dialog__body-content>:first-child{margin-top: 0;} + +.tox .tox-dialog__body-content>:last-child{margin-bottom: 0;} + +.tox .tox-dialog__body-content>:only-child{margin-top: 0;margin-bottom: 0;} + +.tox .tox-dialog--width-lg{height: 650px;max-width: 1200px;} + +.tox .tox-dialog--width-md{max-width: 800px;} + +.tox .tox-dialog--width-md .tox-dialog__body-content{overflow: auto;} + +.tox .tox-dialog__body-content--centered{text-align: center;} + +.tox .tox-dialog__body-content--spacious{margin-bottom: 16px;} + +.tox .tox-dialog__footer{display: flex;padding: 8px 16px;margin-top: 16px;background-color: #2b3b4e;border-top: 1px solid #000;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: rgba(34,47,62,.75);align-items: center;justify-content: center;} + +.tox .tox-dialog__table{width: 100%;border-collapse: collapse;} + +.tox .tox-dialog__table thead th{padding-bottom: 8px;font-weight: 700;} + +.tox .tox-dialog__table tbody tr{border-bottom: 1px solid #000;} + +.tox .tox-dialog__table tbody tr:last-child{border-bottom: none;} + +.tox .tox-dialog__table td{padding-top: 8px;padding-bottom: 8px;} + +.tox .tox-dialog__popups{position: absolute;z-index: 1100;width: 100%;} + +.tox .tox-dialog__body-iframe{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +body.tox-dialog__disable-scroll{overflow: hidden;} + +.tox.tox-platform-ie .tox-dialog-wrap{position: -ms-device-fixed;} + +.tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right: 32px;} + +.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left: 8px;} + +.tox[dir=rtl] .tox-dialog__body{text-align: right;} + +.tox[dir=rtl] .tox-dialog__body-nav{margin-left: 32px;} + +.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right: 8px;} + +.tox .tox-dropzone-container{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dropzone{display: flex;min-height: 100px;padding: 10px;background: #fff;border: 2px dashed #000;box-sizing: border-box;align-items: center;flex-direction: column;flex-grow: 1;justify-content: center;} + +.tox .tox-dropzone p{margin: 0 0 16px 0;color: rgba(255,255,255,.5);} + +.tox .tox-edit-area{position: relative;display: flex;overflow: hidden;border-top: 1px solid #000;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-edit-area__iframe{position: absolute;width: 100%;height: 100%;background-color: #fff;border: 0;box-sizing: border-box;flex: 1;-ms-flex-preferred-size: auto;} + +.tox.tox-inline-edit-area{border: 1px dotted #000;} + +.tox .tox-control-wrap{flex: 1;position: relative;} + +.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display: none;} + +.tox .tox-control-wrap svg{display: block;} + +.tox .tox-control-wrap__status-icon-wrap{position: absolute;top: 50%;transform: translateY(-50%);} + +.tox .tox-control-wrap__status-icon-invalid svg{fill: #c00;} + +.tox .tox-control-wrap__status-icon-unknown svg{fill: orange;} + +.tox .tox-control-wrap__status-icon-valid svg{fill: green;} + +.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right: 32px;} + +.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right: 4px;} + +.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left: 32px;} + +.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left: 4px;} + +.tox .tox-autocompleter{max-width: 25em;} + +.tox .tox-autocompleter .tox-menu{max-width: 25em;} + +.tox .tox-color-input{display: flex;} + +.tox .tox-color-input .tox-textfield{display: flex;border-radius: 3px 0 0 3px;} + +.tox .tox-color-input span{display: flex;width: 35px;cursor: pointer;border-color: rgba(34,47,62,.2);border-style: solid;border-width: 1px 1px 1px 0;border-radius: 0 3px 3px 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-color-input span:focus{border-color: #207ab7;} + +.tox[dir=rtl] .tox-color-input .tox-textfield{border-radius: 0 3px 3px 0;} + +.tox[dir=rtl] .tox-color-input span{border-width: 1px 0 1px 1px;border-radius: 3px 0 0 3px;} + +.tox .tox-label,.tox .tox-toolbar-label{display: block;padding: 0 8px 0 0;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: rgba(255,255,255,.5);text-transform: normal;white-space: nowrap;} + +.tox .tox-toolbar-label{padding: 0 8px;} + +.tox[dir=rtl] .tox-label{padding: 0 0 0 8px;} + +.tox .tox-form{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group{margin-bottom: 4px;box-sizing: border-box;} + +.tox .tox-form__group--error{color: #c00;} + +.tox .tox-form__group--collection{display: flex;} + +.tox .tox-form__grid{display: flex;flex-direction: row;flex-wrap: wrap;justify-content: space-between;} + +.tox .tox-form__grid--2col>.tox-form__group{width: calc(50% - (8px / 2));} + +.tox .tox-form__grid--3col>.tox-form__group{width: calc(100% / 3 - (8px / 2));} + +.tox .tox-form__grid--4col>.tox-form__group{width: calc(25% - (8px / 2));} + +.tox .tox-form__controls-h-stack{align-items: center;display: flex;} + +.tox .tox-form__group--inline{align-items: center;display: flex;} + +.tox .tox-form__group--stretched{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-textarea{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right: 4px;} + +.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display: none;} + +.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield,.tox:not([dir=rtl]) .tox-selectfield select,.tox[dir=rtl] .tox-selectfield select{width: 100%;padding: 5px 4.75px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;line-height: 24px;color: #fff;background-color: #2b3b4e;border-color: #000;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;resize: none;-webkit-appearance: none;-moz-appearance: none;appearance: none;} + +.tox .tox-selectfield select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{border-color: #207ab7;outline: 0;box-shadow: none;} + +.tox .tox-toolbar-textfield{max-width: 250px;margin-top: 2px;margin-bottom: 3px;border-width: 0;} + +.tox .tox-naked-btn{display: block;padding: 0;margin: 0;color: #207ab7;cursor: pointer;background-color: transparent;border: 0;border-color: transparent;box-shadow: unset;} + +.tox .tox-naked-btn svg{display: block;fill: #fff;} + +.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left: 4px;} + +.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right: 4px;} + +.tox .tox-selectfield{position: relative;cursor: pointer;} + +.tox .tox-selectfield select::-ms-expand{display: none;} + +.tox .tox-selectfield svg{position: absolute;top: 50%;pointer-events: none;transform: translateY(-50%);} + +.tox:not([dir=rtl]) .tox-selectfield select{padding-right: 24px;} + +.tox:not([dir=rtl]) .tox-selectfield svg{right: 8px;} + +.tox[dir=rtl] .tox-selectfield select{padding-left: 24px;} + +.tox[dir=rtl] .tox-selectfield svg{left: 8px;} + +.tox .tox-textarea{white-space: pre-wrap;-webkit-appearance: textarea;-moz-appearance: textarea;appearance: textarea;} + +.tox-fullscreen{position: fixed;top: 0;left: 0;width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;border: 0;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display: none;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen{z-index: 1200;} + +.tox-fullscreen .tox.tox-tinymce-aux{z-index: 1201;} + +.tox .tox-image-tools{width: 100%;} + +.tox .tox-image-tools__toolbar{align-items: center;display: flex;justify-content: center;} + +.tox .tox-image-tools__image{position: relative;width: 100%;height: 380px;overflow: auto;background-color: #666;} + +.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top: 8px;} + +.tox .tox-image-tools__image-bg{background: url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==);} + +.tox .tox-image-tools__toolbar>.tox-spacer{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-croprect-block{position: absolute;background: #000;opacity: .5;zoom: 1;} + +.tox .tox-croprect-handle{position: absolute;top: 0;left: 0;width: 20px;height: 20px;border: 2px solid #fff;} + +.tox .tox-croprect-handle-move{position: absolute;cursor: move;border: 0;} + +.tox .tox-croprect-handle-nw{top: 100px;left: 100px;margin: -2px 0 0 -2px;cursor: nw-resize;border-width: 2px 0 0 2px;} + +.tox .tox-croprect-handle-ne{top: 100px;left: 200px;margin: -2px 0 0 -20px;cursor: ne-resize;border-width: 2px 2px 0 0;} + +.tox .tox-croprect-handle-sw{top: 200px;left: 100px;margin: -20px 2px 0 -2px;cursor: sw-resize;border-width: 0 0 2px 2px;} + +.tox .tox-croprect-handle-se{top: 200px;left: 200px;margin: -20px 0 0 -20px;cursor: se-resize;border-width: 0 2px 2px 0;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left: 32px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right: 8px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right: 32px;} + +.tox .tox-insert-table-picker{display: flex;flex-wrap: wrap;width: 169px;} + +.tox .tox-insert-table-picker>div{width: 16px;height: 16px;border-color: #070a0d;border-style: solid;border-width: 0 1px 1px 0;box-sizing: content-box;} + +.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin: -4px 0;} + +.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color: rgba(32,122,183,.5);border-color: rgba(32,122,183,.5);} + +.tox .tox-insert-table-picker__label{display: block;width: 100%;padding: 4px;font-size: 14px;color: #fff;text-align: center;} + +.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right: 0;} + +.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right: 0;} + +.tox .tox-menu{z-index: 1;display: inline-block;overflow: hidden;vertical-align: top;background-color: #2b3b4e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-menu.tox-collection.tox-collection--list{padding: 0;} + +.tox .tox-menu.tox-collection.tox-collection--toolbar{padding: 4px;} + +.tox .tox-menu.tox-collection.tox-collection--grid{padding: 4px;} + +.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin: 0;} + +.tox .tox-menubar{display: flex;padding: 0 4px;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='43px' viewBox='0 0 40 43px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='42px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;background-color: #222f3e;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-mbtn{display: flex;width: auto;height: 34px;padding: 0 4px;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #fff;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-mbtn[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: none;border-color: none;box-shadow: none;} + +.tox .tox-mbtn:hover:not(:disabled){color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-mbtn:focus:not(:disabled){color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-mbtn--active{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-mbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor: not-allowed;} + +.tox .tox-mbtn__select-chevron{display: flex;display: none;width: 16px;align-items: center;justify-content: center;} + +.tox .tox-notification{display: grid;padding: 5px;margin-top: 5px;background-color: #fffaea;border-color: #ffe89d;border-style: solid;border-width: 1px;opacity: 0;box-sizing: border-box;transition: transform .1s ease-in,opacity 150ms ease-in;grid-template-columns: minmax(40px,1fr) auto minmax(40px,1fr);} + +.tox .tox-notification--in{opacity: 1;} + +.tox .tox-notification--success{background-color: #dff0d8;border-color: #d6e9c6;} + +.tox .tox-notification--error{background-color: #f2dede;border-color: #ebccd1;} + +.tox .tox-notification--warn{background-color: #fcf8e3;border-color: #faebcc;} + +.tox .tox-notification--info{background-color: #d9edf7;border-color: #779ecb;} + +.tox .tox-notification__body{font-size: 14px;color: #fff;text-align: center;word-break: break-all;word-break: break-word;white-space: normal;align-self: center;grid-column-end: 3;-ms-grid-column-span: 1;grid-column-start: 2;grid-row-end: 2;grid-row-start: 1;} + +.tox .tox-notification__body>*{margin: 0;} + +.tox .tox-notification__body>*+*{margin-top: 1rem;} + +.tox .tox-notification__icon{align-self: center;-ms-grid-column-align: end;grid-column-end: 2;-ms-grid-column-span: 1;grid-column-start: 1;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification__icon svg{display: block;} + +.tox .tox-notification__dismiss{align-self: start;-ms-grid-column-align: end;grid-column-end: 4;-ms-grid-column-span: 1;grid-column-start: 3;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification .tox-progress-bar{-ms-grid-column-align: center;grid-column-end: 4;-ms-grid-column-span: 3;grid-column-start: 1;grid-row-end: 3;-ms-grid-row-span: 1;grid-row-start: 2;justify-self: center;} + +.tox .tox-pop{position: relative;display: inline-block;} + +.tox .tox-pop--resizing{transition: width .1s ease;} + +.tox .tox-pop--resizing .tox-toolbar{flex-wrap: nowrap;} + +.tox .tox-pop__dialog{min-width: 0;overflow: hidden;background-color: #222f3e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox .tox-pop__dialog>:not(.tox-toolbar){margin: 4px 4px 4px 8px;} + +.tox .tox-pop__dialog .tox-toolbar{background-color: transparent;} + +.tox .tox-pop::after,.tox .tox-pop::before{position: absolute;display: block;width: 0;height: 0;border-style: solid;content: '';} + +.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{top: 100%;left: 50%;} + +.tox .tox-pop.tox-pop--bottom::after{margin-top: -1px;margin-left: -8px;border-color: #222f3e transparent transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--bottom::before{margin-left: -9px;border-color: #000 transparent transparent transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{top: 0;left: 50%;transform: translateY(-100%);} + +.tox .tox-pop.tox-pop--top::after{margin-top: 1px;margin-left: -8px;border-color: transparent transparent #222f3e transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--top::before{margin-left: -9px;border-color: transparent transparent #000 transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{top: calc(50% - 1px);left: 0;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--left::after{margin-left: -15px;border-color: transparent #222f3e transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--left::before{margin-left: -19px;border-color: transparent #000 transparent transparent;border-width: 10px;} + +.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{top: calc(50% + 1px);left: 100%;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--right::after{margin-left: -1px;border-color: transparent transparent transparent #222f3e;border-width: 8px;} + +.tox .tox-pop.tox-pop--right::before{margin-left: -1px;border-color: transparent transparent transparent #000;border-width: 10px;} + +.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left: 20px;} + +.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left: calc(100% - 20px);} + +.tox .tox-sidebar-wrap{display: flex;flex-direction: row;flex-grow: 1;min-height: 0;} + +.tox .tox-sidebar{display: flex;flex-direction: row;justify-content: flex-end;} + +.tox .tox-sidebar__slider{display: flex;overflow: hidden;} + +.tox .tox-sidebar__pane-container{display: flex;} + +.tox .tox-sidebar__pane{display: flex;} + +.tox .tox-sidebar--sliding-closed{opacity: 0;} + +.tox .tox-sidebar--sliding-open{opacity: 1;} + +.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition: width .5s ease,opacity .5s ease;} + +.tox .tox-slider{position: relative;display: flex;height: 24px;align-items: center;flex: 1;-ms-flex-preferred-size: auto;justify-content: center;} + +.tox .tox-slider__rail{width: 100%;height: 10px;min-width: 120px;background-color: transparent;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-slider__handle{position: absolute;top: 50%;left: 50%;width: 14px;height: 24px;background-color: #207ab7;border: 2px solid #185d8c;border-radius: 3px;transform: translateX(-50%) translateY(-50%);box-shadow: none;} + +.tox .tox-source-code{overflow: auto;} + +.tox .tox-spinner{display: flex;} + +.tox .tox-spinner>div{width: 8px;height: 8px;background-color: rgba(255,255,255,.5);border-radius: 100%;animation: tam-bouncing-dots 1.5s ease-in-out 0s infinite both;} + +.tox .tox-spinner>div:nth-child(1){animation-delay: -.32s;} + +.tox .tox-spinner>div:nth-child(2){animation-delay: -.16s;}@keyframes tam-bouncing-dots{0%,100%,80%{transform: scale(0);} + +40%{transform: scale(1);}} + +.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right: 4px;} + +.tox .tox-statusbar{position: relative;display: flex;height: 18px;padding: 0 8px;overflow: hidden;font-size: 12px;color: rgba(255,255,255,.5);text-transform: uppercase;background-color: #222f3e;border-top: 1px solid #000;align-items: center;flex: 0 0 auto;} + +.tox .tox-statusbar a{color: rgba(255,255,255,.5);text-decoration: none;} + +.tox .tox-statusbar a:hover{text-decoration: underline;} + +.tox .tox-statusbar__text-container{display: flex;flex: 1 1 auto;justify-content: flex-end;overflow: hidden;} + +.tox .tox-statusbar__path{display: flex;flex: 1 1 auto;margin-right: auto;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-statusbar__path>*{display: inline;white-space: nowrap;} + +.tox .tox-statusbar__wordcount{flex: 0 0 auto;margin-left: 1ch;} + +.tox .tox-statusbar__resize-handle{display: flex;padding-left: 1ch;margin-right: -8px;margin-left: auto;cursor: nwse-resize;align-items: flex-end;align-self: stretch;flex: 0 0 auto;justify-content: flex-end;} + +.tox .tox-statusbar__resize-handle svg{display: block;fill: rgba(255,255,255,.5);} + +.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right: 4px;} + +.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left: 1ch;} + +.tox[dir=rtl] .tox-statusbar{flex-direction: row-reverse;} + +.tox[dir=rtl] .tox-statusbar__path>*{margin-left: 4px;} + +.tox .tox-throbber{z-index: 1400;} + +.tox .tox-throbber__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;display: flex;background-color: rgba(34,47,62,.6);align-items: center;justify-content: center;} + +.tox .tox-tbtn{display: flex;width: 34px;height: 34px;padding: 0;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #fff;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-tbtn svg{display: block;fill: #fff;} + +.tox .tox-tbtn.tox-tbtn-more{width: inherit;padding-right: 5px;padding-left: 5px;} + +.tox .tox-tbtn--enabled{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-tbtn--enabled>*{transform: none;} + +.tox .tox-tbtn--enabled svg{fill: #fff;} + +.tox .tox-tbtn:hover{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-tbtn:hover svg{fill: #fff;} + +.tox .tox-tbtn:focus{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-tbtn:focus svg{fill: #fff;} + +.tox .tox-tbtn:active{color: #fff;background: #6f7882;box-shadow: none;} + +.tox .tox-tbtn:active svg{fill: #fff;} + +.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{color: rgba(255,255,255,.5);cursor: not-allowed;background: 0 0;box-shadow: none;} + +.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill: rgba(255,255,255,.5);} + +.tox .tox-tbtn:active>*{transform: none;} + +.tox .tox-tbtn--md{width: 51px;height: 51px;} + +.tox .tox-tbtn--lg{width: 68px;height: 68px;flex-direction: column;} + +.tox .tox-tbtn--return{width: 16px;height: unset;align-self: stretch;} + +.tox .tox-tbtn--labeled{width: unset;padding: 0 4px;} + +.tox .tox-tbtn__vlabel{display: block;margin-bottom: 4px;font-size: 10px;font-weight: 400;letter-spacing: -.025em;white-space: nowrap;} + +.tox .tox-tbtn--select{width: auto;padding: 0 4px;margin: 2px 0 3px 0;} + +.tox .tox-tbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-tbtn__select-chevron{align-items: center;display: flex;justify-content: center;width: 16px;} + +.tox .tox-tbtn__select-chevron svg{fill: rgba(255,255,255,.5);} + +.tox .tox-tbtn--bespoke .tox-tbtn__select-label{width: 7em;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-split-button{display: flex;margin: 2px 0 3px 0;overflow: hidden;border: 0;border-radius: 3px;box-sizing: border-box;} + +.tox .tox-split-button:hover{box-shadow: 0 0 0 1px #434e5b inset;} + +.tox .tox-split-button:focus{color: #fff;background: #434e5b;box-shadow: none;} + +.tox .tox-split-button>*{border-radius: 0;} + +.tox .tox-split-button__chevron{width: 16px;} + +.tox .tox-split-button__chevron svg{fill: rgba(255,255,255,.5);} + +.tox .tox-pop .tox-split-button__chevron svg{transform: rotate(-90deg);} + +.tox .tox-split-button .tox-tbtn{margin: 0;} + +.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{color: rgba(255,255,255,.5);background: 0 0;box-shadow: none;} + +.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{display: flex;padding: 0 0;margin-bottom: -1px;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;border-top: 1px solid #000;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height: 0;opacity: 0;visibility: hidden;} + +.tox .tox-toolbar__overflow--growing{transition: height .3s ease,opacity .2s linear .1s;} + +.tox .tox-toolbar__overflow--shrinking{transition: opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s;} + +.tox .tox-pop .tox-toolbar{border-width: 0;} + +.tox .tox-toolbar--no-divider{background-image: none;} + +.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color: #222f3e;border: 1px solid #000;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox.tox-tinymce-aux:not([dir=rtl]) .tox-toolbar__overflow{margin-left: 4px;} + +.tox[dir=rtl] .tox-tbtn__icon-rtl svg{transform: rotateY(180deg);} + +.tox[dir=rtl].tox-tinymce-aux .tox-toolbar__overflow{margin-right: 4px;} + +.tox .tox-toolbar__group{display: flex;padding: 0 4px;margin: 0 0;align-items: center;flex-wrap: wrap;} + +.tox .tox-toolbar__group--pull-right{margin-left: auto;} + +.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right: 1px solid #000;} + +.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left: 1px solid #000;} + +.tox .tox-tooltip{position: relative;display: inline-block;padding: 8px;} + +.tox .tox-tooltip__body{padding: 4px 8px;font-size: 14px;font-style: normal;font-weight: 400;color: rgba(255,255,255,.75);text-transform: normal;background-color: #3d546f;border-radius: 3px;box-shadow: 0 2px 4px rgba(34,47,62,.3);} + +.tox .tox-tooltip__arrow{position: absolute;} + +.tox .tox-tooltip--down .tox-tooltip__arrow{position: absolute;bottom: 0;left: 50%;border-top: 8px solid #3d546f;border-right: 8px solid transparent;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--up .tox-tooltip__arrow{position: absolute;top: 0;left: 50%;border-right: 8px solid transparent;border-bottom: 8px solid #3d546f;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--right .tox-tooltip__arrow{position: absolute;top: 50%;right: 0;border-top: 8px solid transparent;border-bottom: 8px solid transparent;border-left: 8px solid #3d546f;transform: translateY(-50%);} + +.tox .tox-tooltip--left .tox-tooltip__arrow{position: absolute;top: 50%;left: 0;border-top: 8px solid transparent;border-right: 8px solid #3d546f;border-bottom: 8px solid transparent;transform: translateY(-50%);} + +.tox .tox-well{width: 100%;padding: 8px;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-well>:first-child{margin-top: 0;} + +.tox .tox-well>:last-child{margin-bottom: 0;} + +.tox .tox-well>:only-child{margin: 0;} + +.tox .tox-custom-editor{display: flex;height: 525px;border: 1px solid #000;border-radius: 3px;} + +.tox .tox-dialog-loading::before{position: absolute;z-index: 1000;width: 100%;height: 100%;background-color: rgba(0,0,0,.5);content: "";} + +.tox .tox-tab{cursor: pointer;} + +.tox .tox-dialog__content-js{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-content .tox-collection{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox ul{display: block;list-style-type: disc;-webkit-margin-before: 1em;margin-block-start: 1em;-webkit-margin-after: 1em;margin-block-end: 1em;-webkit-margin-start: 0;margin-inline-start: 0;-webkit-margin-end: 0;margin-inline-end: 0;-webkit-padding-start: 40px;padding-inline-start: 40px;} + +.tox a{color: #2276d2;cursor: pointer;} + +.tox .tox-image-tools-edit-panel{height: 60px;} + +.tox .tox-image-tools__sidebar{height: 60px;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css new file mode 100644 index 000000000..14847d0a2 --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all: initial;display: block;} + +.tinymce-mobile-outer-container *{float: none;padding: 0;margin: 0;line-height: 1;text-shadow: none;white-space: nowrap;cursor: inherit;border: 0;outline: 0;box-sizing: initial;-webkit-tap-highlight-color: transparent;} + +.tinymce-mobile-icon-arrow-back::before{content: "\e5cd";} + +.tinymce-mobile-icon-image::before{content: "\e412";} + +.tinymce-mobile-icon-cancel-circle::before{content: "\e5c9";} + +.tinymce-mobile-icon-full-dot::before{content: "\e061";} + +.tinymce-mobile-icon-align-center::before{content: "\e234";} + +.tinymce-mobile-icon-align-left::before{content: "\e236";} + +.tinymce-mobile-icon-align-right::before{content: "\e237";} + +.tinymce-mobile-icon-bold::before{content: "\e238";} + +.tinymce-mobile-icon-italic::before{content: "\e23f";} + +.tinymce-mobile-icon-unordered-list::before{content: "\e241";} + +.tinymce-mobile-icon-ordered-list::before{content: "\e242";} + +.tinymce-mobile-icon-font-size::before{content: "\e245";} + +.tinymce-mobile-icon-underline::before{content: "\e249";} + +.tinymce-mobile-icon-link::before{content: "\e157";} + +.tinymce-mobile-icon-unlink::before{content: "\eca2";} + +.tinymce-mobile-icon-color::before{content: "\e891";} + +.tinymce-mobile-icon-previous::before{content: "\e314";} + +.tinymce-mobile-icon-next::before{content: "\e315";} + +.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content: "\e264";} + +.tinymce-mobile-icon-undo::before{content: "\e166";} + +.tinymce-mobile-icon-redo::before{content: "\e15a";} + +.tinymce-mobile-icon-removeformat::before{content: "\e239";} + +.tinymce-mobile-icon-small-font::before{content: "\e906";} + +.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content: "\e5ca";} + +.tinymce-mobile-icon-small-heading::before{content: "small";} + +.tinymce-mobile-icon-large-heading::before{content: "large";} + +.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family: sans-serif;font-size: 80%;} + +.tinymce-mobile-mask-edit-icon::before{content: "\e254";} + +.tinymce-mobile-icon-back::before{content: "\e5c4";} + +.tinymce-mobile-icon-heading::before{font-family: sans-serif;font-size: 80%;font-weight: 700;content: "Headings";} + +.tinymce-mobile-icon-h1::before{font-weight: 700;content: "H1";} + +.tinymce-mobile-icon-h2::before{font-weight: 700;content: "H2";} + +.tinymce-mobile-icon-h3::before{font-weight: 700;content: "H3";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{position: absolute;top: 0;display: flex;width: 100%;height: 100%;background: rgba(51,51,51,.5);align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{display: flex;font-family: sans-serif;font-size: 1em;border-radius: 50%;align-items: center;flex-direction: column;justify-content: space-between;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{display: flex;width: 2.1em;height: 2.1em;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items: center;display: flex;justify-content: center;flex-direction: column;font-size: 1em;}@media only screen and (min-device-width: 700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size: 1.2em;}} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{display: flex;width: 2.1em;height: 2.1em;color: #207ab7;background-color: #fff;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{font-family: tinymce-mobile,sans-serif;content: "\e900";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index: 2;} + +.tinymce-mobile-android-container.tinymce-mobile-android-maximized{position: fixed;top: 0;right: 0;bottom: 0;left: 0;display: flex;background: #fff;border: none;flex-direction: column;} + +.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position: relative;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display: flex;flex-grow: 1;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display: flex !important;flex-grow: 1;height: auto !important;} + +.tinymce-mobile-android-scroll-reload{overflow: hidden;} + +:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top: 23px;} + +.tinymce-mobile-toolstrip{z-index: 1;display: flex;background: #fff;flex: 0 0 auto;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{display: flex;width: 100%;height: 2.5em;background-color: #fff;border-bottom: 1px solid #ccc;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items: center;display: flex;height: 100%;flex-shrink: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background: #f44336;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-right: .5em;padding-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{display: flex;height: 80%;margin-right: 2px;margin-left: 2px;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{color: #ccc;background: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{color: #eceff1;background: #207ab7;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{display: flex;height: 100%;padding-top: .4em;padding-bottom: .4em;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{position: relative;display: flex;width: 100%;min-height: 1.5em;padding-right: 0;padding-left: 0;overflow: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display: flex;width: 100%;height: 100%;transition: left cubic-bezier(.4,0,1,1) .15s;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display: flex;flex: 0 0 auto;justify-content: space-between;width: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family: sans-serif;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{position: relative;display: flex;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{position: absolute;right: 0;height: 100%;padding-right: 2px;font-size: .6em;font-weight: 700;color: #888;background: inherit;border: none;border-radius: 50%;align-self: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display: none;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{display: flex;height: 100%;padding-right: .5em;padding-left: .5em;font-weight: 700;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{padding-top: 3px;margin: 0 2px;font-size: 10px;line-height: 10px;color: #ccc;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-right: .9em;margin-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-right: .5em;margin-left: .9em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{position: relative;display: flex;padding: .28em 0;margin-right: 0;margin-left: 0;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #ccc;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-right: 2em;padding-left: 2em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #000;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #fff;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{position: absolute;top: 0;bottom: 0;left: -10px;display: flex;width: .5em;height: .5em;margin: auto;color: #fff;background-color: #455a64;border: .5em solid rgba(136,136,136,0);border-radius: 3em;transition: border 120ms cubic-bezier(.39,.58,.57,1);background-clip: padding-box;align-items: center;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border: .5em solid rgba(136,136,136,.39);} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction: column;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{padding-top: .1em;padding-bottom: .1em;padding-left: 5px;font-size: .85em;color: #455a64;background: #fff;border: none;border-radius: 0;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color: #888;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color: #888;} + +.tinymce-mobile-dropup{display: flex;width: 100%;overflow: hidden;background: #fff;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition: height .3s ease-out;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition: height .3s ease-in;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow: 0;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow: 1;} + +.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}@media only screen and (orientation: landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 150px;}} + +.tinymce-mobile-styles-menu{position: relative;width: 100%;overflow: hidden;font-family: sans-serif;outline: 4px solid #000;} + +.tinymce-mobile-styles-menu [role=menu]{position: absolute;display: flex;width: 100%;height: 100%;flex-direction: column;} + +.tinymce-mobile-styles-menu [role=menu].transitioning{transition: transform .5s ease-in-out;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{position: relative;display: flex;padding: 1em 1em;color: #455a64;cursor: pointer;border-bottom: 1px solid #ddd;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e314";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e315";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{display: flex;min-height: 2.5em;padding-right: 1em;padding-left: 1em;color: #455a64;background: #fff;border-top: #455a64;align-items: center;} + +.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform: translate(-100%);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform: translate(0);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform: translate(100%);}@font-face{font-family: tinymce-mobile;font-style: normal;font-weight: 400;src: url(fonts/tinymce-mobile.woff?8x92w3) format('woff');}@media (min-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 25px;}}@media (max-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 18px;}} + +.tinymce-mobile-icon{font-family: tinymce-mobile,sans-serif;} + +.mixin-flex-and-centre{align-items: center;display: flex;justify-content: center;} + +.mixin-flex-bar{align-items: center;display: flex;height: 100%;} + +.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{width: 100%;background-color: #fff;} + +.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{position: fixed;right: 2em;bottom: 1em;display: flex;width: 2.1em;height: 2.1em;font-size: 1em;color: #fff;background-color: #207ab7;border-radius: 50%;align-items: center;justify-content: center;}@media only screen and (min-device-width: 700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size: 1.2em;}} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height: 300px;overflow: hidden;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height: 100%;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display: none;} + +input[type=file]::-webkit-file-upload-button{display: none;}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom: 50%;}} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.inline.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.inline.min.css new file mode 100644 index 000000000..748f313bb --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.inline.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.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--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.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;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.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;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +.tox-toolbar-dock-fadeout{opacity: 0;visibility: hidden;} + +.tox-toolbar-dock-fadein{opacity: 1;visibility: visible;} + +.tox-toolbar-dock-transition{transition: visibility 0s linear .3s,opacity .3s ease;} + +.tox-toolbar-dock-transition.tox-toolbar-dock-fadein{transition-delay: 0s;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.min.css new file mode 100644 index 000000000..6e7165f09 --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.min.css @@ -0,0 +1,235 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{display: inline-block;width: 8px !important;height: 12px !important;padding: 0 2px;cursor: default;background: transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;-webkit-user-select: all;-moz-user-select: all;-ms-user-select: all;user-select: all;-webkit-user-modify: read-only;-moz-user-modify: read-only;} + +.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--active{background-color: #ffe168;} + +.tox-checklist>li:not(.tox-checklist--hidden){margin: .25em 0;list-style: none;} + +.tox-checklist>li:not(.tox-checklist--hidden)::before{position: absolute;width: 1em;height: 1em;margin-top: .125em;margin-left: -1.5em;cursor: pointer;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");background-size: 100%;content: '';} + +.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");} + +[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-right: -1.5em;margin-left: 0;} + +code[class*=language-],pre[class*=language-]{font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size: .875rem;-webkit-hyphens: none;-ms-hyphens: none;hyphens: none;line-height: 1.5;word-spacing: normal;color: #000;text-shadow: 0 1px #fff;word-break: normal;word-wrap: normal;white-space: pre;-moz-tab-size: 4;tab-size: 4;} + +code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow: none;background: #b3d4fc;} + +code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow: none;background: #b3d4fc;}@media print{code[class*=language-],pre[class*=language-]{text-shadow: none;}} + +pre[class*=language-]{padding: 1em;margin: .5em 0;overflow: auto;} + +:not(pre)>code[class*=language-],pre[class*=language-]{background: 0 0 !important;border: 1px solid #ccc;} + +:not(pre)>code[class*=language-]{padding: .1em;border-radius: .3em;} + +.token.cdata,.token.comment,.token.doctype,.token.prolog{color: #708090;} + +.token.punctuation{color: #999;} + +.namespace{opacity: .7;} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color: #905;} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color: #690;} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color: #a67f59;background: hsla(0,0%,100%,.5);} + +.token.atrule,.token.attr-value,.token.keyword{color: #07a;} + +.token.function{color: #dd4a68;} + +.token.important,.token.regex,.token.variable{color: #e90;} + +.token.bold,.token.important{font-weight: 700;} + +.token.italic{font-style: italic;} + +.token.entity{cursor: help;} + +:not([dir=rtl]) code[class*=language-],:not([dir=rtl]) pre[class*=language-]{text-align: left;direction: ltr;} + +[dir=rtl] code[class*=language-],[dir=rtl] pre[class*=language-]{text-align: right;direction: rtl;} + +.mce-content-body{overflow-wrap: break-word;word-wrap: break-word;} + +.mce-content-body .mce-visual-caret{position: absolute;background-color: #000;background-color: currentColor;} + +.mce-content-body .mce-visual-caret-hidden{display: none;} + +.mce-content-body [data-mce-caret]{position: absolute;top: 0;right: auto;left: -1000px;padding: 0;margin: 0;} + +.mce-content-body .mce-offscreen-selection{position: absolute;left: -9999999999px;max-width: 1000000px;} + +.mce-content-body [contentEditable=false]{cursor: default;} + +.mce-content-body [contentEditable=true]{cursor: text;} + +.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;} + +.mce-content-body figure.align-left{float: left;} + +.mce-content-body figure.align-right{float: right;} + +.mce-content-body figure.image.align-center{display: table;margin-right: auto;margin-left: auto;} + +.mce-preview-object{position: relative;display: inline-block;margin: 0 2px 0 2px;line-height: 0;border: 1px solid gray;} + +.mce-preview-object .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.mce-preview-object[data-mce-selected="2"] .mce-shim{display: none;} + +.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;} + +.mce-pagebreak{display: block;width: 100%;height: 5px;margin-top: 15px;cursor: default;border: 1px dashed #aaa;page-break-before: always;}@media print{.mce-pagebreak{border: 0;}} + +.tiny-pageembed .mce-shim{position: absolute;top: 0;left: 0;width: 100%;height: 100%;background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);} + +.tiny-pageembed[data-mce-selected="2"] .mce-shim{display: none;} + +.tiny-pageembed{position: relative;display: inline-block;} + +.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{position: relative;display: block;width: 100%;padding: 0;overflow: hidden;} + +.tiny-pageembed--16by9::before,.tiny-pageembed--1by1::before,.tiny-pageembed--21by9::before,.tiny-pageembed--4by3::before{display: block;content: "";} + +.tiny-pageembed--21by9::before{padding-top: 42.857143%;} + +.tiny-pageembed--16by9::before{padding-top: 56.25%;} + +.tiny-pageembed--4by3::before{padding-top: 75%;} + +.tiny-pageembed--1by1::before{padding-top: 100%;} + +.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{position: absolute;top: 0;left: 0;width: 100%;height: 100%;border: 0;} + +.mce-content-body div.mce-resizehandle{position: absolute;z-index: 10000;width: 10px;height: 10px;background-color: #4099ff;border-color: #4099ff;border-style: solid;border-width: 1px;box-sizing: border-box;} + +.mce-content-body div.mce-resizehandle:hover{background-color: #4099ff;} + +.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor: nesw-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor: nwse-resize;} + +.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor: nesw-resize;} + +.mce-content-body .mce-clonedresizable{position: absolute;z-index: 10000;outline: 1px dashed #000;opacity: .5;} + +.mce-content-body .mce-resize-helper{position: absolute;z-index: 10001;display: none;padding: 5px;margin: 5px 10px;font-family: sans-serif;font-size: 12px;line-height: 14px;color: #fff;white-space: nowrap;background: #555;background: rgba(0,0,0,.75);border: 1px;border-radius: 3px;} + +.mce-match-marker{color: #fff;background: #aaa;} + +.mce-match-marker-selected{color: #fff;background: #39f;} + +.mce-content-body img[data-mce-selected],.mce-content-body table[data-mce-selected]{outline: 3px solid #b4d7ff;} + +.mce-content-body hr[data-mce-selected]{outline: 3px solid #b4d7ff;outline-offset: 1px;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline: 3px solid #b4d7ff;} + +.mce-content-body [contentEditable=false][data-mce-selected]{cursor: not-allowed;outline: 3px solid #b4d7ff;} + +.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline: 0;} + +.mce-content-body [data-mce-selected=inline-boundary]{background-color: #b4d7ff;} + +.mce-content-body .mce-edit-focus{outline: 3px solid #b4d7ff;} + +.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{background-color: #b4d7ff !important;} + +.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background: 0 0;} + +.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background: 0 0;} + +.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} + +.mce-content-body img::-moz-selection{background: 0 0;} + +.mce-content-body img::selection{background: 0 0;} + +.ephox-snooker-resizer-bar{background-color: #b4d7ff;opacity: 0;} + +.ephox-snooker-resizer-cols{cursor: col-resize;} + +.ephox-snooker-resizer-rows{cursor: row-resize;} + +.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity: 1;} + +.mce-spellchecker-word{height: 2rem;cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.5'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-spellchecker-grammar{cursor: default;background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23008800'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position: 0 calc(100% + 1px);background-repeat: repeat-x;background-size: auto 6px;} + +.mce-toc{border: 1px solid gray;} + +.mce-toc h2{margin: 4px;} + +.mce-toc li{list-style-type: none;} + +.mce-item-table,.mce-item-table caption,.mce-item-table td,.mce-item-table th{border: 1px dashed #bbb;} + +.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{padding-top: 10px;margin-left: 3px;background-repeat: no-repeat;border: 1px dashed #bbb;} + +.mce-visualblocks p{background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);} + +.mce-visualblocks h1{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);} + +.mce-visualblocks h2{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);} + +.mce-visualblocks h3{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);} + +.mce-visualblocks h4{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);} + +.mce-visualblocks h5{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);} + +.mce-visualblocks h6{background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);} + +.mce-visualblocks div:not([data-mce-bogus]){background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);} + +.mce-visualblocks section{background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);} + +.mce-visualblocks article{background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);} + +.mce-visualblocks blockquote{background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);} + +.mce-visualblocks address{background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);} + +.mce-visualblocks pre{background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);} + +.mce-visualblocks figure{background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);} + +.mce-visualblocks figcaption{border: 1px dashed #bbb;} + +.mce-visualblocks hgroup{background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);} + +.mce-visualblocks aside{background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);} + +.mce-visualblocks ul{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);} + +.mce-visualblocks ol{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);} + +.mce-visualblocks dl{background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);} + +.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left: 3px;} + +.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x: right;margin-right: 3px;} + +.mce-nbsp,.mce-shy{background: #aaa;} + +.mce-shy::after{content: '-';} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css new file mode 100644 index 000000000..c0522520e --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css @@ -0,0 +1,17 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} + +body{-webkit-text-size-adjust: none;} + +body img{max-width: 96vw;} + +body table img{max-width: 95%;} + +body{font-family: sans-serif;} + +table{border-collapse: collapse;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff new file mode 100644 index 000000000..1e3be038a Binary files /dev/null and b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff differ diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.min.css new file mode 100644 index 000000000..5886c594c --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.min.css @@ -0,0 +1,875 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tox{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-style: normal;font-weight: 400;line-height: normal;color: #222f3e;text-decoration: none;text-shadow: none;text-transform: none;white-space: normal;vertical-align: initial;cursor: auto;box-sizing: content-box;-webkit-tap-highlight-color: transparent;} + +.tox :not(svg){font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;line-height: inherit;color: inherit;text-align: inherit;text-decoration: inherit;text-shadow: inherit;text-transform: inherit;white-space: inherit;vertical-align: inherit;cursor: inherit;box-sizing: inherit;direction: inherit;-webkit-tap-highlight-color: inherit;} + +.tox :not(svg){position: static;float: none;width: auto;height: auto;max-width: none;padding: 0;margin: 0;background: 0 0;border: 0;outline: 0;} + +.tox:not([dir=rtl]){text-align: left;direction: ltr;} + +.tox[dir=rtl]{text-align: right;direction: rtl;} + +.tox-tinymce{position: relative;display: flex;overflow: hidden;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;border: 1px solid #ccc;border-radius: 0;visibility: inherit !important;box-shadow: none;box-sizing: border-box;flex-direction: column;} + +.tox-editor-container{display: flex;flex: 1 1 auto;flex-direction: column;overflow: hidden;} + +.tox-editor-container>:first-child{border-top: none !important;} + +.tox-tinymce-aux{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} + +.tox-tinymce :focus,.tox-tinymce-aux :focus{outline: 0;} + +button::-moz-focus-inner{border: 0;} + +.tox-silver-sink{z-index: 1300;} + +.tox .tox-anchorbar{display: flex;flex: 0 0 auto;} + +.tox .tox-bar{display: flex;flex: 0 0 auto;} + +.tox .tox-button{display: inline-block;padding: 4px 16px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 14px;font-weight: 700;line-height: 24px;letter-spacing: 1;color: #fff;text-align: center;text-decoration: none;text-transform: capitalize;white-space: nowrap;cursor: pointer;background-color: #207ab7;background-image: none;background-position: none;background-repeat: none;border-color: #207ab7;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-button[disabled]{color: rgba(255,255,255,.5);cursor: not-allowed;background-color: #207ab7;background-image: none;border-color: #207ab7;box-shadow: none;} + +.tox .tox-button:focus:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:hover:not(:disabled){color: #fff;background-color: #1c6ca1;background-image: none;border-color: #1c6ca1;box-shadow: none;} + +.tox .tox-button:active:not(:disabled){color: #fff;background-color: #185d8c;background-image: none;border-color: #185d8c;box-shadow: none;} + +.tox .tox-button--secondary{padding: 4px 16px;color: #222f3e;text-decoration: none;text-transform: capitalize;background-color: #f0f0f0;background-image: none;background-position: none;background-repeat: none;border-color: #f0f0f0;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;} + +.tox .tox-button--secondary[disabled]{color: rgba(34,47,62,.5);background-color: #f0f0f0;background-image: none;border-color: #f0f0f0;box-shadow: none;} + +.tox .tox-button--secondary:focus:not(:disabled){color: #222f3e;background-color: #e3e3e3;background-image: none;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--secondary:hover:not(:disabled){color: #222f3e;background-color: #e3e3e3;background-image: none;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--secondary:active:not(:disabled){color: #222f3e;background-color: #d6d6d6;background-image: none;border-color: #d6d6d6;box-shadow: none;} + +.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding: 4px;} + +.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display: block;fill: currentColor;} + +.tox .tox-button-link{display: inline-block;padding: 0;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;font-weight: 400;line-height: 1.3;white-space: nowrap;cursor: pointer;background: 0;border: none;box-sizing: border-box;} + +.tox .tox-button-link--sm{font-size: 14px;} + +.tox .tox-button--naked{color: #222f3e;background-color: transparent;border-color: transparent;box-shadow: unset;} + +.tox .tox-button--naked:hover:not(:disabled){color: #222f3e;background-color: #e3e3e3;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--naked:focus:not(:disabled){color: #222f3e;background-color: #e3e3e3;border-color: #e3e3e3;box-shadow: none;} + +.tox .tox-button--naked:active:not(:disabled){color: #222f3e;background-color: #d6d6d6;border-color: #d6d6d6;box-shadow: none;} + +.tox .tox-button--naked .tox-icon svg{fill: currentColor;} + +.tox .tox-button--naked.tox-button--icon{color: currentColor;} + +.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color: #222f3e;} + +.tox .tox-checkbox{display: flex;height: 36px;min-width: 36px;cursor: pointer;border-radius: 3px;align-items: center;} + +.tox .tox-checkbox__input{position: absolute;top: auto;left: -10000px;width: 1px;height: 1px;overflow: hidden;} + +.tox .tox-checkbox__icons{width: 24px;height: 24px;padding: calc(4px - 1px);border-radius: 3px;box-shadow: 0 0 0 2px transparent;box-sizing: content-box;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: block;fill: rgba(34,47,62,.3);} + +.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: none;fill: #207ab7;} + +.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display: none;fill: #207ab7;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display: block;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display: none;} + +.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display: block;} + +.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{padding: calc(4px - 1px);border-radius: 3px;box-shadow: inset 0 0 0 1px #207ab7;} + +.tox:not([dir=rtl]) .tox-checkbox__label{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left: 4px;} + +.tox[dir=rtl] .tox-checkbox__label{margin-right: 4px;} + +.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right: 4px;} + +.tox .tox-collection--toolbar .tox-collection__group{display: flex;padding: 0;} + +.tox .tox-collection--grid .tox-collection__group{display: flex;max-height: 208px;padding: 0;overflow-x: hidden;overflow-y: auto;flex-wrap: wrap;} + +.tox .tox-collection--list .tox-collection__group{padding: 4px 0;border-color: #ccc;border-style: solid;border-top-width: 1px;border-right-width: 0;border-bottom-width: 0;border-left-width: 0;} + +.tox .tox-collection--list .tox-collection__group:first-child{border-top-width: 0;} + +.tox .tox-collection__group-heading{padding: 4px 8px;margin-top: -4px;margin-bottom: 4px;font-size: 12px;font-style: normal;font-weight: 400;color: rgba(34,47,62,.7);text-transform: none;cursor: default;background-color: #e6e6e6;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;-webkit-touch-callout: none;} + +.tox .tox-collection__item{display: flex;color: #222f3e;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;align-items: center;-webkit-touch-callout: none;} + +.tox .tox-collection--list .tox-collection__item{padding: 4px 8px;} + +.tox .tox-collection--toolbar .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--grid .tox-collection__item{padding: 4px;border-radius: 3px;} + +.tox .tox-collection--list .tox-collection__item--enabled{color: contrast(inherit,#222f3e,#fff);background-color: inherit;} + +.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection--toolbar .tox-collection__item--enabled{color: #222f3e;background-color: #c8cbcf;} + +.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection--grid .tox-collection__item--enabled{color: #222f3e;background-color: #c8cbcf;} + +.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){color: #222f3e;background-color: #dee0e2;} + +.tox .tox-collection__item--state-disabled{color: rgba(34,47,62,.5);cursor: default;background-color: transparent;} + +.tox .tox-collection__item-icon{display: flex;width: 24px;height: 24px;align-items: center;justify-content: center;} + +.tox .tox-collection__item-icon svg{fill: currentColor;} + +.tox .tox-collection--toolbar-lg .tox-collection__item-icon{width: 48px;height: 48px;} + +.tox .tox-collection__item[role=menuitemcheckbox]:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display: none;} + +.tox .tox-collection__item-label{display: inline-block;font-size: 14px;font-style: normal;font-weight: 400;line-height: 24px;color: currentColor;text-transform: none;word-break: break-all;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-collection__item-accessory{display: inline-block;height: 24px;font-size: 14px;line-height: 24px;color: rgba(34,47,62,.7);text-transform: normal;} + +.tox .tox-collection__item-caret{align-items: center;display: flex;min-height: 24px;} + +.tox .tox-collection__item-caret::after{min-height: inherit;font-size: 0;content: '';} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item-label:first-child{margin-left: 4px;} + +.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left: 16px;text-align: right;} + +.tox:not([dir=rtl]) .tox-collection__item-caret{margin-left: 16px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right: 8px;} + +.tox[dir=rtl] .tox-collection--list .tox-collection__item-label:first-child{margin-right: 4px;} + +.tox[dir=rtl] .tox-collection__item-icon-rtl .tox-collection__item-icon svg{transform: rotateY(180deg);} + +.tox[dir=rtl] .tox-collection__item-accessory{margin-right: 16px;text-align: left;} + +.tox[dir=rtl] .tox-collection__item-caret{margin-right: 16px;transform: rotateY(180deg);} + +.tox .tox-color-picker-container{display: flex;flex-direction: row;height: 225px;margin: 0;} + +.tox .tox-sv-palette{display: flex;height: 100%;box-sizing: border-box;} + +.tox .tox-sv-palette-spectrum{height: 100%;} + +.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width: 225px;} + +.tox .tox-sv-palette-thumb{position: absolute;width: 12px;height: 12px;background: 0 0;border: 1px solid #000;border-radius: 50%;box-sizing: content-box;} + +.tox .tox-sv-palette-inner-thumb{position: absolute;width: 10px;height: 10px;border: 1px solid #fff;border-radius: 50%;} + +.tox .tox-hue-slider{width: 25px;height: 100%;box-sizing: border-box;} + +.tox .tox-hue-slider-spectrum{width: 100%;height: 100%;background: linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);} + +.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width: 20px;} + +.tox .tox-hue-slider-thumb{width: 100%;height: 4px;background: #fff;border: 1px solid #000;box-sizing: content-box;} + +.tox .tox-rgb-form{display: flex;flex-direction: column;justify-content: space-between;} + +.tox .tox-rgb-form div{display: flex;width: inherit;margin-bottom: 5px;align-items: center;justify-content: space-between;} + +.tox .tox-rgb-form input{width: 6em;} + +.tox .tox-rgb-form input.tox-invalid{border: 1px solid red !important;} + +.tox .tox-rgb-form .tox-rgba-preview{margin-bottom: 0;border: 1px solid #000;flex-grow: 2;} + +.tox:not([dir=rtl]) .tox-sv-palette{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider{margin-right: 15px;} + +.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left: -1px;} + +.tox:not([dir=rtl]) .tox-rgb-form label{margin-right: .5em;} + +.tox[dir=rtl] .tox-sv-palette{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider{margin-left: 15px;} + +.tox[dir=rtl] .tox-hue-slider-thumb{margin-right: -1px;} + +.tox[dir=rtl] .tox-rgb-form label{margin-left: .5em;} + +.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin: 2px 0 3px 4px;} + +.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{margin: -4px 0;border: 0;} + +.tox .tox-swatches__row{display: flex;} + +.tox .tox-swatch{width: 30px;height: 30px;transition: transform .15s,box-shadow .15s;} + +.tox .tox-swatch:focus,.tox .tox-swatch:hover{transform: scale(.8);box-shadow: 0 0 0 1px rgba(127,127,127,.3) inset;} + +.tox .tox-swatch--remove{align-items: center;display: flex;justify-content: center;} + +.tox .tox-swatch--remove svg path{stroke: #e74c3c;} + +.tox .tox-swatches__picker-btn{display: flex;width: 30px;height: 30px;padding: 0;cursor: pointer;background-color: transparent;border: 0;outline: 0;align-items: center;justify-content: center;} + +.tox .tox-swatches__picker-btn svg{width: 24px;height: 24px;} + +.tox .tox-swatches__picker-btn:hover{background: #dee0e2;} + +.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left: auto;} + +.tox[dir=rtl] .tox-swatches__picker-btn{margin-right: auto;} + +.tox .tox-comment-thread{position: relative;background: #fff;} + +.tox .tox-comment-thread>:not(:first-child){margin-top: 8px;} + +.tox .tox-comment{position: relative;padding: 8px 8px 16px 8px;background: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-comment__header{display: flex;color: #222f3e;align-items: center;justify-content: space-between;} + +.tox .tox-comment__date{font-size: 12px;color: rgba(34,47,62,.7);} + +.tox .tox-comment__body{position: relative;margin-top: 8px;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: #222f3e;text-transform: initial;} + +.tox .tox-comment__body textarea{width: 100%;white-space: normal;resize: none;} + +.tox .tox-comment__expander{padding-top: 8px;} + +.tox .tox-comment__expander p{font-size: 14px;font-style: normal;color: rgba(34,47,62,.7);} + +.tox .tox-comment__body p{margin: 0;} + +.tox .tox-comment__buttonspacing{padding-top: 16px;text-align: center;} + +.tox .tox-comment-thread__overlay::after{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;background: #fff;content: "";opacity: .9;} + +.tox .tox-comment__reply{display: flex;flex-shrink: 0;flex-wrap: wrap;justify-content: flex-end;margin-top: 8px;} + +.tox .tox-comment__reply>:first-child{width: 100%;margin-bottom: 8px;} + +.tox .tox-comment__edit{display: flex;flex-wrap: wrap;justify-content: flex-end;margin-top: 16px;} + +.tox .tox-comment__gradient::after{position: absolute;bottom: 0;display: block;width: 100%;height: 5em;margin-top: -40px;background: linear-gradient(rgba(255,255,255,0),#fff);content: "";} + +.tox .tox-comment__overlay{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 5;display: flex;text-align: center;background: #fff;opacity: .9;flex-direction: column;flex-grow: 1;} + +.tox .tox-comment__loading-text{position: relative;display: flex;color: #222f3e;align-items: center;flex-direction: column;} + +.tox .tox-comment__loading-text>div{padding-bottom: 16px;} + +.tox .tox-comment__overlaytext{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 10;padding: 1em;font-size: 14px;flex-direction: column;} + +.tox .tox-comment__overlaytext p{color: #222f3e;text-align: center;background-color: #fff;box-shadow: 0 0 8px 8px #fff;} + +.tox .tox-comment__overlaytext div:nth-of-type(2){font-size: .8em;} + +.tox .tox-comment__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: #fff;align-items: center;justify-content: center;} + +.tox .tox-comment__scroll{display: flex;flex-direction: column;flex-shrink: 1;overflow: auto;} + +.tox .tox-conversations{margin: 8px;} + +.tox:not([dir=rtl]) .tox-comment__edit{margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left: 8px;} + +.tox[dir=rtl] .tox-comment__edit{margin-right: 8px;} + +.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right: 8px;} + +.tox .tox-user{align-items: center;display: flex;} + +.tox .tox-user__avatar svg{fill: rgba(34,47,62,.7);} + +.tox .tox-user__name{font-size: 12px;font-style: normal;font-weight: 700;color: rgba(34,47,62,.7);text-transform: uppercase;} + +.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right: 8px;} + +.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar svg{margin-left: 8px;} + +.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right: 8px;} + +.tox .tox-dialog-wrap{position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 1100;display: flex;align-items: center;justify-content: center;} + +.tox .tox-dialog-wrap__backdrop{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1101;background-color: rgba(255,255,255,.75);} + +.tox .tox-dialog{position: relative;z-index: 1102;display: flex;width: 95vw;max-width: 480px;max-height: 100%;overflow: hidden;background-color: #fff;border-color: #ccc;border-style: solid;border-width: 1px;border-radius: 3px;box-shadow: 0 16px 16px -10px rgba(34,47,62,.15),0 0 40px 1px rgba(34,47,62,.15);flex-direction: column;} + +.tox .tox-dialog__header{position: relative;display: flex;padding: 8px 16px 0 16px;margin-bottom: 16px;font-size: 16px;color: #222f3e;background-color: #fff;border-bottom: none;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__header .tox-button{z-index: 1;} + +.tox .tox-dialog__draghandle{position: absolute;top: 0;left: 0;width: 100%;height: 100%;cursor: grab;} + +.tox .tox-dialog__draghandle:active{cursor: grabbing;} + +.tox .tox-dialog__dismiss{margin-left: auto;} + +.tox .tox-dialog__title{margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 20px;font-style: normal;font-weight: 400;line-height: 1.3;text-transform: normal;} + +.tox .tox-dialog__body{display: flex;min-width: 0;padding: 0 16px;font-size: 16px;font-style: normal;font-weight: 400;line-height: 1.3;color: #222f3e;text-align: left;text-transform: normal;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-nav{align-items: flex-start;display: flex;flex-direction: column;} + +.tox .tox-dialog__body-nav-item{display: inline-block;margin-bottom: 8px;font-size: 14px;line-height: 1.3;color: rgba(34,47,62,.7);text-decoration: none;border-bottom: 2px solid transparent;} + +.tox .tox-dialog__body-nav-item--active{color: #207ab7;border-bottom: 2px solid #207ab7;} + +.tox .tox-dialog__body-content{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;max-height: 650px;overflow: auto;} + +.tox .tox-dialog__body-content>*{margin-top: 16px;margin-bottom: 0;} + +.tox .tox-dialog__body-content>:first-child{margin-top: 0;} + +.tox .tox-dialog__body-content>:last-child{margin-bottom: 0;} + +.tox .tox-dialog__body-content>:only-child{margin-top: 0;margin-bottom: 0;} + +.tox .tox-dialog--width-lg{height: 650px;max-width: 1200px;} + +.tox .tox-dialog--width-md{max-width: 800px;} + +.tox .tox-dialog--width-md .tox-dialog__body-content{overflow: auto;} + +.tox .tox-dialog__body-content--centered{text-align: center;} + +.tox .tox-dialog__body-content--spacious{margin-bottom: 16px;} + +.tox .tox-dialog__footer{display: flex;padding: 8px 16px;margin-top: 16px;background-color: #fff;border-top: 1px solid #ccc;align-items: center;justify-content: space-between;} + +.tox .tox-dialog__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 1103;display: flex;background-color: rgba(255,255,255,.75);align-items: center;justify-content: center;} + +.tox .tox-dialog__table{width: 100%;border-collapse: collapse;} + +.tox .tox-dialog__table thead th{padding-bottom: 8px;font-weight: 700;} + +.tox .tox-dialog__table tbody tr{border-bottom: 1px solid #ccc;} + +.tox .tox-dialog__table tbody tr:last-child{border-bottom: none;} + +.tox .tox-dialog__table td{padding-top: 8px;padding-bottom: 8px;} + +.tox .tox-dialog__popups{position: absolute;z-index: 1100;width: 100%;} + +.tox .tox-dialog__body-iframe{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +body.tox-dialog__disable-scroll{overflow: hidden;} + +.tox.tox-platform-ie .tox-dialog-wrap{position: -ms-device-fixed;} + +.tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right: 32px;} + +.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left: 8px;} + +.tox[dir=rtl] .tox-dialog__body{text-align: right;} + +.tox[dir=rtl] .tox-dialog__body-nav{margin-left: 32px;} + +.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right: 8px;} + +.tox .tox-dropzone-container{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dropzone{display: flex;min-height: 100px;padding: 10px;background: #fff;border: 2px dashed #ccc;box-sizing: border-box;align-items: center;flex-direction: column;flex-grow: 1;justify-content: center;} + +.tox .tox-dropzone p{margin: 0 0 16px 0;color: rgba(34,47,62,.7);} + +.tox .tox-edit-area{position: relative;display: flex;overflow: hidden;border-top: 1px solid #ccc;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-edit-area__iframe{position: absolute;width: 100%;height: 100%;background-color: #fff;border: 0;box-sizing: border-box;flex: 1;-ms-flex-preferred-size: auto;} + +.tox.tox-inline-edit-area{border: 1px dotted #ccc;} + +.tox .tox-control-wrap{flex: 1;position: relative;} + +.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display: none;} + +.tox .tox-control-wrap svg{display: block;} + +.tox .tox-control-wrap__status-icon-wrap{position: absolute;top: 50%;transform: translateY(-50%);} + +.tox .tox-control-wrap__status-icon-invalid svg{fill: #c00;} + +.tox .tox-control-wrap__status-icon-unknown svg{fill: orange;} + +.tox .tox-control-wrap__status-icon-valid svg{fill: green;} + +.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right: 32px;} + +.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right: 4px;} + +.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left: 32px;} + +.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left: 4px;} + +.tox .tox-autocompleter{max-width: 25em;} + +.tox .tox-autocompleter .tox-menu{max-width: 25em;} + +.tox .tox-color-input{display: flex;} + +.tox .tox-color-input .tox-textfield{display: flex;border-radius: 3px 0 0 3px;} + +.tox .tox-color-input span{display: flex;width: 35px;cursor: pointer;border-color: rgba(34,47,62,.2);border-style: solid;border-width: 1px 1px 1px 0;border-radius: 0 3px 3px 0;box-shadow: none;box-sizing: border-box;} + +.tox .tox-color-input span:focus{border-color: #207ab7;} + +.tox[dir=rtl] .tox-color-input .tox-textfield{border-radius: 0 3px 3px 0;} + +.tox[dir=rtl] .tox-color-input span{border-width: 1px 0 1px 1px;border-radius: 3px 0 0 3px;} + +.tox .tox-label,.tox .tox-toolbar-label{display: block;padding: 0 8px 0 0;font-size: 14px;font-style: normal;font-weight: 400;line-height: 1.3;color: rgba(34,47,62,.7);text-transform: normal;white-space: nowrap;} + +.tox .tox-toolbar-label{padding: 0 8px;} + +.tox[dir=rtl] .tox-label{padding: 0 0 0 8px;} + +.tox .tox-form{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group{margin-bottom: 4px;box-sizing: border-box;} + +.tox .tox-form__group--error{color: #c00;} + +.tox .tox-form__group--collection{display: flex;} + +.tox .tox-form__grid{display: flex;flex-direction: row;flex-wrap: wrap;justify-content: space-between;} + +.tox .tox-form__grid--2col>.tox-form__group{width: calc(50% - (8px / 2));} + +.tox .tox-form__grid--3col>.tox-form__group{width: calc(100% / 3 - (8px / 2));} + +.tox .tox-form__grid--4col>.tox-form__group{width: calc(25% - (8px / 2));} + +.tox .tox-form__controls-h-stack{align-items: center;display: flex;} + +.tox .tox-form__group--inline{align-items: center;display: flex;} + +.tox .tox-form__group--stretched{display: flex;flex: 1;flex-direction: column;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-textarea{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex: 1;-ms-flex-preferred-size: auto;height: 100%;} + +.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right: 4px;} + +.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display: none;} + +.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield,.tox:not([dir=rtl]) .tox-selectfield select,.tox[dir=rtl] .tox-selectfield select{width: 100%;padding: 5px 4.75px;margin: 0;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size: 16px;line-height: 24px;color: #222f3e;background-color: #fff;border-color: #ccc;border-style: solid;border-width: 1px;border-radius: 3px;outline: 0;box-shadow: none;box-sizing: border-box;resize: none;-webkit-appearance: none;-moz-appearance: none;appearance: none;} + +.tox .tox-selectfield select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{border-color: #207ab7;outline: 0;box-shadow: none;} + +.tox .tox-toolbar-textfield{max-width: 250px;margin-top: 2px;margin-bottom: 3px;border-width: 0;} + +.tox .tox-naked-btn{display: block;padding: 0;margin: 0;color: #207ab7;cursor: pointer;background-color: transparent;border: 0;border-color: transparent;box-shadow: unset;} + +.tox .tox-naked-btn svg{display: block;fill: #222f3e;} + +.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left: 4px;} + +.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right: 4px;} + +.tox .tox-selectfield{position: relative;cursor: pointer;} + +.tox .tox-selectfield select::-ms-expand{display: none;} + +.tox .tox-selectfield svg{position: absolute;top: 50%;pointer-events: none;transform: translateY(-50%);} + +.tox:not([dir=rtl]) .tox-selectfield select{padding-right: 24px;} + +.tox:not([dir=rtl]) .tox-selectfield svg{right: 8px;} + +.tox[dir=rtl] .tox-selectfield select{padding-left: 24px;} + +.tox[dir=rtl] .tox-selectfield svg{left: 8px;} + +.tox .tox-textarea{white-space: pre-wrap;-webkit-appearance: textarea;-moz-appearance: textarea;appearance: textarea;} + +.tox-fullscreen{position: fixed;top: 0;left: 0;width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;border: 0;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display: none;} + +.tox-fullscreen .tox.tox-tinymce.tox-fullscreen{z-index: 1200;} + +.tox-fullscreen .tox.tox-tinymce-aux{z-index: 1201;} + +.tox .tox-image-tools{width: 100%;} + +.tox .tox-image-tools__toolbar{align-items: center;display: flex;justify-content: center;} + +.tox .tox-image-tools__image{position: relative;width: 100%;height: 380px;overflow: auto;background-color: #666;} + +.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top: 8px;} + +.tox .tox-image-tools__image-bg{background: url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==);} + +.tox .tox-image-tools__toolbar>.tox-spacer{flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-croprect-block{position: absolute;background: #000;opacity: .5;zoom: 1;} + +.tox .tox-croprect-handle{position: absolute;top: 0;left: 0;width: 20px;height: 20px;border: 2px solid #fff;} + +.tox .tox-croprect-handle-move{position: absolute;cursor: move;border: 0;} + +.tox .tox-croprect-handle-nw{top: 100px;left: 100px;margin: -2px 0 0 -2px;cursor: nw-resize;border-width: 2px 0 0 2px;} + +.tox .tox-croprect-handle-ne{top: 100px;left: 200px;margin: -2px 0 0 -20px;cursor: ne-resize;border-width: 2px 2px 0 0;} + +.tox .tox-croprect-handle-sw{top: 200px;left: 100px;margin: -20px 2px 0 -2px;cursor: sw-resize;border-width: 0 0 2px 2px;} + +.tox .tox-croprect-handle-se{top: 200px;left: 200px;margin: -20px 0 0 -20px;cursor: se-resize;border-width: 0 2px 2px 0;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left: 8px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left: 32px;} + +.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right: 8px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right: 32px;} + +.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right: 32px;} + +.tox .tox-insert-table-picker{display: flex;flex-wrap: wrap;width: 169px;} + +.tox .tox-insert-table-picker>div{width: 16px;height: 16px;border-color: #ccc;border-style: solid;border-width: 0 1px 1px 0;box-sizing: content-box;} + +.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin: -4px 0;} + +.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color: rgba(32,122,183,.5);border-color: rgba(32,122,183,.5);} + +.tox .tox-insert-table-picker__label{display: block;width: 100%;padding: 4px;font-size: 14px;color: rgba(34,47,62,.7);text-align: center;} + +.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right: 0;} + +.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right: 0;} + +.tox .tox-menu{z-index: 1;display: inline-block;overflow: hidden;vertical-align: top;background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 4px 8px 0 rgba(34,47,62,.1);} + +.tox .tox-menu.tox-collection.tox-collection--list{padding: 0;} + +.tox .tox-menu.tox-collection.tox-collection--toolbar{padding: 4px;} + +.tox .tox-menu.tox-collection.tox-collection--grid{padding: 4px;} + +.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin: 0;} + +.tox .tox-menubar{display: flex;padding: 0 4px;margin-bottom: -1px;background: url("data:image/svg+xml;charset=utf8,%3Csvg height='43px' viewBox='0 0 40 43px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='42px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;background-color: #fff;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-mbtn{display: flex;width: auto;height: 34px;padding: 0 4px;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #222f3e;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-mbtn[disabled]{color: rgba(34,47,62,.5);cursor: not-allowed;background-color: none;border-color: none;box-shadow: none;} + +.tox .tox-mbtn:hover:not(:disabled){color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-mbtn:focus:not(:disabled){color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-mbtn--active{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-mbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor: not-allowed;} + +.tox .tox-mbtn__select-chevron{display: flex;display: none;width: 16px;align-items: center;justify-content: center;} + +.tox .tox-notification{display: grid;padding: 5px;margin-top: 5px;background-color: #fffaea;border-color: #ffe89d;border-style: solid;border-width: 1px;opacity: 0;box-sizing: border-box;transition: transform .1s ease-in,opacity 150ms ease-in;grid-template-columns: minmax(40px,1fr) auto minmax(40px,1fr);} + +.tox .tox-notification--in{opacity: 1;} + +.tox .tox-notification--success{background-color: #dff0d8;border-color: #d6e9c6;} + +.tox .tox-notification--error{background-color: #f2dede;border-color: #ebccd1;} + +.tox .tox-notification--warn{background-color: #fcf8e3;border-color: #faebcc;} + +.tox .tox-notification--info{background-color: #d9edf7;border-color: #779ecb;} + +.tox .tox-notification__body{font-size: 14px;color: #222f3e;text-align: center;word-break: break-all;word-break: break-word;white-space: normal;align-self: center;grid-column-end: 3;-ms-grid-column-span: 1;grid-column-start: 2;grid-row-end: 2;grid-row-start: 1;} + +.tox .tox-notification__body>*{margin: 0;} + +.tox .tox-notification__body>*+*{margin-top: 1rem;} + +.tox .tox-notification__icon{align-self: center;-ms-grid-column-align: end;grid-column-end: 2;-ms-grid-column-span: 1;grid-column-start: 1;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification__icon svg{display: block;} + +.tox .tox-notification__dismiss{align-self: start;-ms-grid-column-align: end;grid-column-end: 4;-ms-grid-column-span: 1;grid-column-start: 3;grid-row-end: 2;grid-row-start: 1;justify-self: end;} + +.tox .tox-notification .tox-progress-bar{-ms-grid-column-align: center;grid-column-end: 4;-ms-grid-column-span: 3;grid-column-start: 1;grid-row-end: 3;-ms-grid-row-span: 1;grid-row-start: 2;justify-self: center;} + +.tox .tox-pop{position: relative;display: inline-block;} + +.tox .tox-pop--resizing{transition: width .1s ease;} + +.tox .tox-pop--resizing .tox-toolbar{flex-wrap: nowrap;} + +.tox .tox-pop__dialog{min-width: 0;overflow: hidden;background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox .tox-pop__dialog>:not(.tox-toolbar){margin: 4px 4px 4px 8px;} + +.tox .tox-pop__dialog .tox-toolbar{background-color: transparent;} + +.tox .tox-pop::after,.tox .tox-pop::before{position: absolute;display: block;width: 0;height: 0;border-style: solid;content: '';} + +.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{top: 100%;left: 50%;} + +.tox .tox-pop.tox-pop--bottom::after{margin-top: -1px;margin-left: -8px;border-color: #fff transparent transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--bottom::before{margin-left: -9px;border-color: #ccc transparent transparent transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{top: 0;left: 50%;transform: translateY(-100%);} + +.tox .tox-pop.tox-pop--top::after{margin-top: 1px;margin-left: -8px;border-color: transparent transparent #fff transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--top::before{margin-left: -9px;border-color: transparent transparent #ccc transparent;border-width: 9px;} + +.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{top: calc(50% - 1px);left: 0;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--left::after{margin-left: -15px;border-color: transparent #fff transparent transparent;border-width: 8px;} + +.tox .tox-pop.tox-pop--left::before{margin-left: -19px;border-color: transparent #ccc transparent transparent;border-width: 10px;} + +.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{top: calc(50% + 1px);left: 100%;transform: translateY(-50%);} + +.tox .tox-pop.tox-pop--right::after{margin-left: -1px;border-color: transparent transparent transparent #fff;border-width: 8px;} + +.tox .tox-pop.tox-pop--right::before{margin-left: -1px;border-color: transparent transparent transparent #ccc;border-width: 10px;} + +.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left: 20px;} + +.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left: calc(100% - 20px);} + +.tox .tox-sidebar-wrap{display: flex;flex-direction: row;flex-grow: 1;min-height: 0;} + +.tox .tox-sidebar{display: flex;flex-direction: row;justify-content: flex-end;} + +.tox .tox-sidebar__slider{display: flex;overflow: hidden;} + +.tox .tox-sidebar__pane-container{display: flex;} + +.tox .tox-sidebar__pane{display: flex;} + +.tox .tox-sidebar--sliding-closed{opacity: 0;} + +.tox .tox-sidebar--sliding-open{opacity: 1;} + +.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition: width .5s ease,opacity .5s ease;} + +.tox .tox-slider{position: relative;display: flex;height: 24px;align-items: center;flex: 1;-ms-flex-preferred-size: auto;justify-content: center;} + +.tox .tox-slider__rail{width: 100%;height: 10px;min-width: 120px;background-color: transparent;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-slider__handle{position: absolute;top: 50%;left: 50%;width: 14px;height: 24px;background-color: #207ab7;border: 2px solid #185d8c;border-radius: 3px;transform: translateX(-50%) translateY(-50%);box-shadow: none;} + +.tox .tox-source-code{overflow: auto;} + +.tox .tox-spinner{display: flex;} + +.tox .tox-spinner>div{width: 8px;height: 8px;background-color: rgba(34,47,62,.7);border-radius: 100%;animation: tam-bouncing-dots 1.5s ease-in-out 0s infinite both;} + +.tox .tox-spinner>div:nth-child(1){animation-delay: -.32s;} + +.tox .tox-spinner>div:nth-child(2){animation-delay: -.16s;}@keyframes tam-bouncing-dots{0%,100%,80%{transform: scale(0);} + +40%{transform: scale(1);}} + +.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left: 4px;} + +.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right: 4px;} + +.tox .tox-statusbar{position: relative;display: flex;height: 18px;padding: 0 8px;overflow: hidden;font-size: 12px;color: rgba(34,47,62,.7);text-transform: uppercase;background-color: #fff;border-top: 1px solid #ccc;align-items: center;flex: 0 0 auto;} + +.tox .tox-statusbar a{color: rgba(34,47,62,.7);text-decoration: none;} + +.tox .tox-statusbar a:hover{text-decoration: underline;} + +.tox .tox-statusbar__text-container{display: flex;flex: 1 1 auto;justify-content: flex-end;overflow: hidden;} + +.tox .tox-statusbar__path{display: flex;flex: 1 1 auto;margin-right: auto;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-statusbar__path>*{display: inline;white-space: nowrap;} + +.tox .tox-statusbar__wordcount{flex: 0 0 auto;margin-left: 1ch;} + +.tox .tox-statusbar__resize-handle{display: flex;padding-left: 1ch;margin-right: -8px;margin-left: auto;cursor: nwse-resize;align-items: flex-end;align-self: stretch;flex: 0 0 auto;justify-content: flex-end;} + +.tox .tox-statusbar__resize-handle svg{display: block;fill: rgba(34,47,62,.7);} + +.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right: 4px;} + +.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left: 1ch;} + +.tox[dir=rtl] .tox-statusbar{flex-direction: row-reverse;} + +.tox[dir=rtl] .tox-statusbar__path>*{margin-left: 4px;} + +.tox .tox-throbber{z-index: 1400;} + +.tox .tox-throbber__busy-spinner{position: absolute;top: 0;right: 0;bottom: 0;left: 0;display: flex;background-color: rgba(255,255,255,.6);align-items: center;justify-content: center;} + +.tox .tox-tbtn{display: flex;width: 34px;height: 34px;padding: 0;margin: 2px 0 3px 0;overflow: hidden;font-size: 14px;font-style: normal;font-weight: 400;color: #222f3e;text-transform: normal;background: 0 0;border: 0;border-radius: 3px;outline: 0;box-shadow: none;align-items: center;flex: 0 0 auto;justify-content: center;} + +.tox .tox-tbtn svg{display: block;fill: #222f3e;} + +.tox .tox-tbtn.tox-tbtn-more{width: inherit;padding-right: 5px;padding-left: 5px;} + +.tox .tox-tbtn--enabled{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-tbtn--enabled>*{transform: none;} + +.tox .tox-tbtn--enabled svg{fill: #222f3e;} + +.tox .tox-tbtn:hover{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-tbtn:hover svg{fill: #222f3e;} + +.tox .tox-tbtn:focus{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-tbtn:focus svg{fill: #222f3e;} + +.tox .tox-tbtn:active{color: #222f3e;background: #c8cbcf;box-shadow: none;} + +.tox .tox-tbtn:active svg{fill: #222f3e;} + +.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{color: rgba(34,47,62,.5);cursor: not-allowed;background: 0 0;box-shadow: none;} + +.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill: rgba(34,47,62,.5);} + +.tox .tox-tbtn:active>*{transform: none;} + +.tox .tox-tbtn--md{width: 51px;height: 51px;} + +.tox .tox-tbtn--lg{width: 68px;height: 68px;flex-direction: column;} + +.tox .tox-tbtn--return{width: 16px;height: unset;align-self: stretch;} + +.tox .tox-tbtn--labeled{width: unset;padding: 0 4px;} + +.tox .tox-tbtn__vlabel{display: block;margin-bottom: 4px;font-size: 10px;font-weight: 400;letter-spacing: -.025em;white-space: nowrap;} + +.tox .tox-tbtn--select{width: auto;padding: 0 4px;margin: 2px 0 3px 0;} + +.tox .tox-tbtn__select-label{margin: 0 4px;font-weight: 400;cursor: default;} + +.tox .tox-tbtn__select-chevron{align-items: center;display: flex;justify-content: center;width: 16px;} + +.tox .tox-tbtn__select-chevron svg{fill: rgba(34,47,62,.7);} + +.tox .tox-tbtn--bespoke .tox-tbtn__select-label{width: 7em;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;} + +.tox .tox-split-button{display: flex;margin: 2px 0 3px 0;overflow: hidden;border: 0;border-radius: 3px;box-sizing: border-box;} + +.tox .tox-split-button:hover{box-shadow: 0 0 0 1px #dee0e2 inset;} + +.tox .tox-split-button:focus{color: #222f3e;background: #dee0e2;box-shadow: none;} + +.tox .tox-split-button>*{border-radius: 0;} + +.tox .tox-split-button__chevron{width: 16px;} + +.tox .tox-split-button__chevron svg{fill: rgba(34,47,62,.7);} + +.tox .tox-pop .tox-split-button__chevron svg{transform: rotate(-90deg);} + +.tox .tox-split-button .tox-tbtn{margin: 0;} + +.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{color: rgba(34,47,62,.5);background: 0 0;box-shadow: none;} + +.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{display: flex;padding: 0 0;margin-bottom: -1px;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;border-top: 1px solid #ccc;flex: 0 0 auto;flex-shrink: 0;flex-wrap: wrap;} + +.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height: 0;opacity: 0;visibility: hidden;} + +.tox .tox-toolbar__overflow--growing{transition: height .3s ease,opacity .2s linear .1s;} + +.tox .tox-toolbar__overflow--shrinking{transition: opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s;} + +.tox .tox-pop .tox-toolbar{border-width: 0;} + +.tox .tox-toolbar--no-divider{background-image: none;} + +.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color: #fff;border: 1px solid #ccc;border-radius: 3px;box-shadow: 0 1px 3px rgba(0,0,0,.15);} + +.tox.tox-tinymce-aux:not([dir=rtl]) .tox-toolbar__overflow{margin-left: 4px;} + +.tox[dir=rtl] .tox-tbtn__icon-rtl svg{transform: rotateY(180deg);} + +.tox[dir=rtl].tox-tinymce-aux .tox-toolbar__overflow{margin-right: 4px;} + +.tox .tox-toolbar__group{display: flex;padding: 0 4px;margin: 0 0;align-items: center;flex-wrap: wrap;} + +.tox .tox-toolbar__group--pull-right{margin-left: auto;} + +.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right: 1px solid #ccc;} + +.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left: 1px solid #ccc;} + +.tox .tox-tooltip{position: relative;display: inline-block;padding: 8px;} + +.tox .tox-tooltip__body{padding: 4px 8px;font-size: 14px;font-style: normal;font-weight: 400;color: rgba(255,255,255,.75);text-transform: normal;background-color: #222f3e;border-radius: 3px;box-shadow: 0 2px 4px rgba(34,47,62,.3);} + +.tox .tox-tooltip__arrow{position: absolute;} + +.tox .tox-tooltip--down .tox-tooltip__arrow{position: absolute;bottom: 0;left: 50%;border-top: 8px solid #222f3e;border-right: 8px solid transparent;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--up .tox-tooltip__arrow{position: absolute;top: 0;left: 50%;border-right: 8px solid transparent;border-bottom: 8px solid #222f3e;border-left: 8px solid transparent;transform: translateX(-50%);} + +.tox .tox-tooltip--right .tox-tooltip__arrow{position: absolute;top: 50%;right: 0;border-top: 8px solid transparent;border-bottom: 8px solid transparent;border-left: 8px solid #222f3e;transform: translateY(-50%);} + +.tox .tox-tooltip--left .tox-tooltip__arrow{position: absolute;top: 50%;left: 0;border-top: 8px solid transparent;border-right: 8px solid #222f3e;border-bottom: 8px solid transparent;transform: translateY(-50%);} + +.tox .tox-well{width: 100%;padding: 8px;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-well>:first-child{margin-top: 0;} + +.tox .tox-well>:last-child{margin-bottom: 0;} + +.tox .tox-well>:only-child{margin: 0;} + +.tox .tox-custom-editor{display: flex;height: 525px;border: 1px solid #ccc;border-radius: 3px;} + +.tox .tox-dialog-loading::before{position: absolute;z-index: 1000;width: 100%;height: 100%;background-color: rgba(0,0,0,.5);content: "";} + +.tox .tox-tab{cursor: pointer;} + +.tox .tox-dialog__content-js{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox .tox-dialog__body-content .tox-collection{display: flex;flex: 1;-ms-flex-preferred-size: auto;} + +.tox ul{display: block;list-style-type: disc;-webkit-margin-before: 1em;margin-block-start: 1em;-webkit-margin-after: 1em;margin-block-end: 1em;-webkit-margin-start: 0;margin-inline-start: 0;-webkit-margin-end: 0;margin-inline-end: 0;-webkit-padding-start: 40px;padding-inline-start: 40px;} + +.tox a{color: #2276d2;cursor: pointer;} + +.tox .tox-image-tools-edit-panel{height: 60px;} + +.tox .tox-image-tools__sidebar{height: 60px;} diff --git a/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css new file mode 100644 index 000000000..14847d0a2 --- /dev/null +++ b/apps/vben5/apps/app-antd/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css @@ -0,0 +1,239 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all: initial;display: block;} + +.tinymce-mobile-outer-container *{float: none;padding: 0;margin: 0;line-height: 1;text-shadow: none;white-space: nowrap;cursor: inherit;border: 0;outline: 0;box-sizing: initial;-webkit-tap-highlight-color: transparent;} + +.tinymce-mobile-icon-arrow-back::before{content: "\e5cd";} + +.tinymce-mobile-icon-image::before{content: "\e412";} + +.tinymce-mobile-icon-cancel-circle::before{content: "\e5c9";} + +.tinymce-mobile-icon-full-dot::before{content: "\e061";} + +.tinymce-mobile-icon-align-center::before{content: "\e234";} + +.tinymce-mobile-icon-align-left::before{content: "\e236";} + +.tinymce-mobile-icon-align-right::before{content: "\e237";} + +.tinymce-mobile-icon-bold::before{content: "\e238";} + +.tinymce-mobile-icon-italic::before{content: "\e23f";} + +.tinymce-mobile-icon-unordered-list::before{content: "\e241";} + +.tinymce-mobile-icon-ordered-list::before{content: "\e242";} + +.tinymce-mobile-icon-font-size::before{content: "\e245";} + +.tinymce-mobile-icon-underline::before{content: "\e249";} + +.tinymce-mobile-icon-link::before{content: "\e157";} + +.tinymce-mobile-icon-unlink::before{content: "\eca2";} + +.tinymce-mobile-icon-color::before{content: "\e891";} + +.tinymce-mobile-icon-previous::before{content: "\e314";} + +.tinymce-mobile-icon-next::before{content: "\e315";} + +.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content: "\e264";} + +.tinymce-mobile-icon-undo::before{content: "\e166";} + +.tinymce-mobile-icon-redo::before{content: "\e15a";} + +.tinymce-mobile-icon-removeformat::before{content: "\e239";} + +.tinymce-mobile-icon-small-font::before{content: "\e906";} + +.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content: "\e5ca";} + +.tinymce-mobile-icon-small-heading::before{content: "small";} + +.tinymce-mobile-icon-large-heading::before{content: "large";} + +.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family: sans-serif;font-size: 80%;} + +.tinymce-mobile-mask-edit-icon::before{content: "\e254";} + +.tinymce-mobile-icon-back::before{content: "\e5c4";} + +.tinymce-mobile-icon-heading::before{font-family: sans-serif;font-size: 80%;font-weight: 700;content: "Headings";} + +.tinymce-mobile-icon-h1::before{font-weight: 700;content: "H1";} + +.tinymce-mobile-icon-h2::before{font-weight: 700;content: "H2";} + +.tinymce-mobile-icon-h3::before{font-weight: 700;content: "H3";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{position: absolute;top: 0;display: flex;width: 100%;height: 100%;background: rgba(51,51,51,.5);align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{display: flex;font-family: sans-serif;font-size: 1em;border-radius: 50%;align-items: center;flex-direction: column;justify-content: space-between;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{display: flex;width: 2.1em;height: 2.1em;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items: center;display: flex;justify-content: center;flex-direction: column;font-size: 1em;}@media only screen and (min-device-width: 700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size: 1.2em;}} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{display: flex;width: 2.1em;height: 2.1em;color: #207ab7;background-color: #fff;border-radius: 50%;align-items: center;justify-content: center;} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{font-family: tinymce-mobile,sans-serif;content: "\e900";} + +.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index: 2;} + +.tinymce-mobile-android-container.tinymce-mobile-android-maximized{position: fixed;top: 0;right: 0;bottom: 0;left: 0;display: flex;background: #fff;border: none;flex-direction: column;} + +.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position: relative;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display: flex;flex-grow: 1;} + +.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display: flex !important;flex-grow: 1;height: auto !important;} + +.tinymce-mobile-android-scroll-reload{overflow: hidden;} + +:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top: 23px;} + +.tinymce-mobile-toolstrip{z-index: 1;display: flex;background: #fff;flex: 0 0 auto;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{display: flex;width: 100%;height: 2.5em;background-color: #fff;border-bottom: 1px solid #ccc;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items: center;display: flex;height: 100%;flex-shrink: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background: #f44336;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-right: .5em;padding-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{display: flex;height: 80%;margin-right: 2px;margin-left: 2px;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{color: #ccc;background: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{color: #eceff1;background: #207ab7;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{display: flex;height: 100%;padding-top: .4em;padding-bottom: .4em;align-items: center;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{position: relative;display: flex;width: 100%;min-height: 1.5em;padding-right: 0;padding-left: 0;overflow: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display: flex;width: 100%;height: 100%;transition: left cubic-bezier(.4,0,1,1) .15s;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display: flex;flex: 0 0 auto;justify-content: space-between;width: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family: sans-serif;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{position: relative;display: flex;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{position: absolute;right: 0;height: 100%;padding-right: 2px;font-size: .6em;font-weight: 700;color: #888;background: inherit;border: none;border-radius: 50%;align-self: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display: none;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{display: flex;height: 100%;padding-right: .5em;padding-left: .5em;font-weight: 700;align-items: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility: hidden;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{padding-top: 3px;margin: 0 2px;font-size: 10px;line-height: 10px;color: #ccc;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color: #c8cbcf;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-right: .9em;margin-left: .5em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-right: .5em;margin-left: .9em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{position: relative;display: flex;padding: .28em 0;margin-right: 0;margin-left: 0;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #ccc;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-right: 2em;padding-left: 2em;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items: center;display: flex;flex-grow: 1;height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{display: flex;height: .2em;margin-top: .3em;margin-bottom: .3em;background: linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #000;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{width: 1.2em;height: .2em;margin-top: .3em;margin-bottom: .3em;background: #fff;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{position: absolute;top: 0;bottom: 0;left: -10px;display: flex;width: .5em;height: .5em;margin: auto;color: #fff;background-color: #455a64;border: .5em solid rgba(136,136,136,0);border-radius: 3em;transition: border 120ms cubic-bezier(.39,.58,.57,1);background-clip: padding-box;align-items: center;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border: .5em solid rgba(136,136,136,.39);} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items: center;display: flex;height: 100%;flex: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction: column;justify-content: center;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items: center;display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height: 100%;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display: flex;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{padding-top: .1em;padding-bottom: .1em;padding-left: 5px;font-size: .85em;color: #455a64;background: #fff;border: none;border-radius: 0;flex-grow: 1;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color: #888;} + +.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color: #888;} + +.tinymce-mobile-dropup{display: flex;width: 100%;overflow: hidden;background: #fff;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition: height .3s ease-out;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition: height .3s ease-in;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow: 0;} + +.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow: 1;} + +.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}@media only screen and (orientation: landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 200px;}}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height: 150px;}} + +.tinymce-mobile-styles-menu{position: relative;width: 100%;overflow: hidden;font-family: sans-serif;outline: 4px solid #000;} + +.tinymce-mobile-styles-menu [role=menu]{position: absolute;display: flex;width: 100%;height: 100%;flex-direction: column;} + +.tinymce-mobile-styles-menu [role=menu].transitioning{transition: transform .5s ease-in-out;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{position: relative;display: flex;padding: 1em 1em;color: #455a64;cursor: pointer;border-bottom: 1px solid #ddd;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e314";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;color: #455a64;content: "\e315";} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{position: absolute;right: 0;padding-right: 1em;padding-left: 1em;font-family: tinymce-mobile,sans-serif;} + +.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{display: flex;min-height: 2.5em;padding-right: 1em;padding-left: 1em;color: #455a64;background: #fff;border-top: #455a64;align-items: center;} + +.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform: translate(-100%);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform: translate(0);} + +.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform: translate(100%);}@font-face{font-family: tinymce-mobile;font-style: normal;font-weight: 400;src: url(fonts/tinymce-mobile.woff?8x92w3) format('woff');}@media (min-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 25px;}}@media (max-device-width: 700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size: 18px;}} + +.tinymce-mobile-icon{font-family: tinymce-mobile,sans-serif;} + +.mixin-flex-and-centre{align-items: center;display: flex;justify-content: center;} + +.mixin-flex-bar{align-items: center;display: flex;height: 100%;} + +.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{width: 100%;background-color: #fff;} + +.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{position: fixed;right: 2em;bottom: 1em;display: flex;width: 2.1em;height: 2.1em;font-size: 1em;color: #fff;background-color: #207ab7;border-radius: 50%;align-items: center;justify-content: center;}@media only screen and (min-device-width: 700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size: 1.2em;}} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height: 300px;overflow: hidden;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height: 100%;} + +.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display: none;} + +input[type=file]::-webkit-file-upload-button{display: none;}@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (orientation: landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom: 50%;}} diff --git a/apps/vben5/apps/app-antd/src/adapter/component/index.ts b/apps/vben5/apps/app-antd/src/adapter/component/index.ts index 1afa62174..818acdd0d 100644 --- a/apps/vben5/apps/app-antd/src/adapter/component/index.ts +++ b/apps/vben5/apps/app-antd/src/adapter/component/index.ts @@ -8,7 +8,7 @@ import type { BaseFormComponentType } from '@vben/common-ui'; import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState } from '@vben/common-ui'; +import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { @@ -21,6 +21,7 @@ import { Input, InputNumber, InputPassword, + InputSearch, Mentions, notification, Radio, @@ -48,15 +49,19 @@ const withDefaultPlaceholder = ( // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 export type ComponentType = + | 'ApiSelect' + | 'ApiTreeSelect' | 'AutoComplete' | 'Checkbox' | 'CheckboxGroup' | 'DatePicker' | 'DefaultButton' | 'Divider' + | 'IconPicker' | 'Input' | 'InputNumber' | 'InputPassword' + | 'InputSearch' | 'Mentions' | 'PrimaryButton' | 'Radio' @@ -77,7 +82,38 @@ async function initComponentAdapter() { // 如果你的组件体积比较大,可以使用异步加载 // Button: () => // import('xxx').then((res) => res.Button), - + ApiSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: Select, + loadingSlot: 'suffixIcon', + modelPropName: 'value', + visibleEvent: 'onDropdownVisibleChange', + }, + slots, + ); + }, + ApiTreeSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: TreeSelect, + fieldNames: { label: 'label', value: 'value', children: 'children' }, + loadingSlot: 'suffixIcon', + modelPropName: 'value', + optionsPropName: 'treeData', + visibleEvent: 'onVisibleChange', + }, + slots, + ); + }, AutoComplete, Checkbox, CheckboxGroup, @@ -87,9 +123,17 @@ async function initComponentAdapter() { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, + IconPicker: (props, { attrs, slots }) => { + return h( + IconPicker, + { iconSlot: 'addonAfter', inputComponent: Input, ...props, ...attrs }, + slots, + ); + }, Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), + InputSearch: withDefaultPlaceholder(InputSearch, 'input'), Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 PrimaryButton: (props, { attrs, slots }) => { diff --git a/apps/vben5/apps/app-antd/src/adapter/form.ts b/apps/vben5/apps/app-antd/src/adapter/form.ts deleted file mode 100644 index 65ff793b6..000000000 --- a/apps/vben5/apps/app-antd/src/adapter/form.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { - VbenFormSchema as FormSchema, - VbenFormProps, -} from '@vben/common-ui'; - -import type { ComponentType } from './component'; - -import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; -import { $t } from '@vben/locales'; - -setupVbenForm({ - config: { - // ant design vue组件库默认都是 v-model:value - baseModelPropName: 'value', - - // 一些组件是 v-model:checked 或者 v-model:fileList - modelPropNameMap: { - Checkbox: 'checked', - Radio: 'checked', - Switch: 'checked', - Upload: 'fileList', - }, - }, - defineRules: { - // 输入项目必填国际化适配 - required: (value, _params, ctx) => { - if (value === undefined || value === null || value.length === 0) { - return $t('ui.formRules.required', [ctx.label]); - } - return true; - }, - // 选择项目必填国际化适配 - selectRequired: (value, _params, ctx) => { - if (value === undefined || value === null) { - return $t('ui.formRules.selectRequired', [ctx.label]); - } - return true; - }, - }, -}); - -const useVbenForm = useForm; - -export { useVbenForm, z }; - -export type VbenFormSchema = FormSchema; -export type { VbenFormProps }; diff --git a/apps/vben5/apps/app-antd/src/adapter/request/index.ts b/apps/vben5/apps/app-antd/src/adapter/request/index.ts index 06284043b..855047496 100644 --- a/apps/vben5/apps/app-antd/src/adapter/request/index.ts +++ b/apps/vben5/apps/app-antd/src/adapter/request/index.ts @@ -5,12 +5,14 @@ import { } from '@vben/request'; import { useAccessStore } from '@vben/stores'; -import { requestClient } from '@abp/request'; +import { useOAuthError, useTokenApi } from '@abp/account'; +import { requestClient, useWrapperResult } from '@abp/request'; import { message } from 'ant-design-vue'; import { useAuthStore } from '#/store'; export function initRequestClient() { + const { refreshTokenApi } = useTokenApi(); /** * 重新认证逻辑 */ @@ -33,6 +35,20 @@ export function initRequestClient() { * 刷新token逻辑 */ async function doRefreshToken() { + const accessStore = useAccessStore(); + if (accessStore.refreshToken) { + try { + const { accessToken, tokenType, refreshToken } = await refreshTokenApi({ + refreshToken: accessStore.refreshToken, + }); + const newToken = `${tokenType} ${accessToken}`; + accessStore.setAccessToken(newToken); + accessStore.setRefreshToken(refreshToken); + return newToken; + } catch { + console.warn('The refresh token has expired or is unavailable.'); + } + } return ''; } @@ -47,6 +63,7 @@ export function initRequestClient() { config.headers.Authorization = `${accessStore.accessToken}`; } config.headers['Accept-Language'] = preferences.app.locale; + config.headers['X-Request-From'] = 'vben'; return config; }, }); @@ -54,17 +71,11 @@ export function initRequestClient() { // response数据解构 requestClient.addResponseInterceptor({ fulfilled: (response) => { - const { data, status, headers } = response; + const { data, status } = response; + const { hasWrapResult, getData } = useWrapperResult(response); - if (headers._abpwrapresult === 'true') { - const { code, result, message, details } = data; - const hasSuccess = data && Reflect.has(data, 'code') && code === '0'; - if (hasSuccess) { - return result; - } - const content = details || message; - - throw Object.assign({}, response, { response, message: content }); + if (hasWrapResult()) { + return getData(); } if (status >= 200 && status < 400) { @@ -92,6 +103,11 @@ export function initRequestClient() { // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg // 当前mock接口返回的错误字段是 error 或者 message const responseData = error?.response?.data ?? {}; + if (responseData?.error_description) { + const { formatError } = useOAuthError(); + message.error(formatError(responseData) || msg); + return; + } const errorMessage = responseData?.error ?? responseData?.message ?? ''; // 如果没有错误信息,则会根据状态码进行提示 message.error(errorMessage || msg); diff --git a/apps/vben5/apps/app-antd/src/adapter/vxe-table.ts b/apps/vben5/apps/app-antd/src/adapter/vxe-table.ts deleted file mode 100644 index d296b2050..000000000 --- a/apps/vben5/apps/app-antd/src/adapter/vxe-table.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { h } from 'vue'; - -import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; - -import { Button, Image } from 'ant-design-vue'; - -import { useVbenForm } from './form'; - -setupVbenVxeTable({ - configVxeTable: (vxeUI) => { - vxeUI.setConfig({ - grid: { - align: 'center', - border: false, - columnConfig: { - resizable: true, - }, - minHeight: 180, - formConfig: { - // 全局禁用vxe-table的表单配置,使用formOptions - enabled: false, - }, - proxyConfig: { - autoLoad: true, - response: { - result: 'items', - total: 'total', - list: 'items', - }, - showActiveMsg: true, - showResponseMsg: false, - }, - round: true, - showOverflow: true, - size: 'small', - }, - }); - - // 表格配置项可以用 cellRender: { name: 'CellImage' }, - vxeUI.renderer.add('CellImage', { - renderTableDefault(_renderOpts, params) { - const { column, row } = params; - return h(Image, { src: row[column.field] }); - }, - }); - - // 表格配置项可以用 cellRender: { name: 'CellLink' }, - vxeUI.renderer.add('CellLink', { - renderTableDefault(renderOpts) { - const { props } = renderOpts; - return h( - Button, - { size: 'small', type: 'link' }, - { default: () => props?.text }, - ); - }, - }); - - // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 - // vxeUI.formats.add - }, - useVbenForm, -}); - -export { useVbenVxeGrid }; - -export type * from '@vben/plugins/vxe-table'; diff --git a/apps/vben5/apps/app-antd/src/api/core/abp.ts b/apps/vben5/apps/app-antd/src/api/core/abp.ts deleted file mode 100644 index e5fba68f5..000000000 --- a/apps/vben5/apps/app-antd/src/api/core/abp.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { - ApplicationConfigurationDto, - ApplicationLocalizationDto, -} from '@abp/core'; - -import { requestClient } from '@abp/request'; - -/** - * 获取应用程序配置信息 - */ -export function getConfigApi(options?: { - includeLocalizationResources?: boolean; -}): Promise { - return requestClient.get( - '/api/abp/application-configuration', - { - params: options, - }, - ); -} - -/** - * 获取应用程序语言 - * @returns 本地化配置 - */ -export function getLocalizationApi(options: { - cultureName: string; - onlyDynamics?: boolean; -}): Promise { - return requestClient.get( - '/api/abp/application-localization', - { - params: options, - }, - ); -} diff --git a/apps/vben5/apps/app-antd/src/api/core/index.ts b/apps/vben5/apps/app-antd/src/api/core/index.ts index 5fe53ee1e..93c65bd62 100644 --- a/apps/vben5/apps/app-antd/src/api/core/index.ts +++ b/apps/vben5/apps/app-antd/src/api/core/index.ts @@ -1,2 +1,2 @@ -export * from './abp'; export * from './menu'; +export { useAbpConfigApi } from './useAbpConfigApi'; diff --git a/apps/vben5/apps/app-antd/src/api/core/useAbpConfigApi.ts b/apps/vben5/apps/app-antd/src/api/core/useAbpConfigApi.ts new file mode 100644 index 000000000..39715ab18 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/api/core/useAbpConfigApi.ts @@ -0,0 +1,48 @@ +import type { + ApplicationConfigurationDto, + ApplicationLocalizationDto, +} from '@abp/core'; + +import { useRequest } from '@abp/request'; + +export function useAbpConfigApi() { + const { cancel, request } = useRequest(); + + /** + * 获取应用程序配置信息 + */ + function getConfigApi(options?: { + includeLocalizationResources?: boolean; + }): Promise { + return request( + '/api/abp/application-configuration', + { + params: options, + method: 'GET', + }, + ); + } + + /** + * 获取应用程序语言 + * @returns 本地化配置 + */ + function getLocalizationApi(options: { + cultureName: string; + onlyDynamics?: boolean; + }): Promise { + return request( + '/api/abp/application-localization', + { + params: options, + method: 'GET', + }, + ); + } + + return { + cancel, + getConfigApi, + getLocalizationApi, + }; +} diff --git a/apps/vben5/apps/app-antd/src/bootstrap.ts b/apps/vben5/apps/app-antd/src/bootstrap.ts index a0af6fcfe..1967cea94 100644 --- a/apps/vben5/apps/app-antd/src/bootstrap.ts +++ b/apps/vben5/apps/app-antd/src/bootstrap.ts @@ -1,6 +1,7 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; +import { initTippy } from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -31,6 +32,9 @@ async function bootstrap(namespace: string) { // 安装权限指令 registerAccessDirective(app); + // 初始化 tippy + initTippy(app); + // 配置路由及路由守卫 app.use(router); diff --git a/apps/vben5/apps/app-antd/src/hooks/useSessions.ts b/apps/vben5/apps/app-antd/src/hooks/useSessions.ts new file mode 100644 index 000000000..ae8cc1e28 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/hooks/useSessions.ts @@ -0,0 +1,48 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import type { Notification as NotificationInfo } from '@abp/notifications'; + +import { onMounted, onUnmounted } from 'vue'; + +import { useAbpStore, useEventBus } from '@abp/core'; +import { NotificationNames, useNotifications } from '@abp/notifications'; +import { Modal } from 'ant-design-vue'; + +import { useAuthStore } from '#/store'; + +export function useSessions() { + const authStore = useAuthStore(); + const abpStore = useAbpStore(); + const { subscribe, unSubscribe } = useEventBus(); + const { register, release } = useNotifications(); + + function _register() { + subscribe(NotificationNames.SessionExpiration, _onSessionExpired); + register(); + } + + function _release() { + unSubscribe(NotificationNames.SessionExpiration, _onSessionExpired); + release(); + } + + /** 处理会话过期事件 */ + function _onSessionExpired(event?: NotificationInfo) { + const { data, title, message } = event!; + const sessionId = data.SessionId; + if (sessionId === abpStore.application?.currentUser?.sessionId) { + _release(); + Modal.confirm({ + iconType: 'warning', + title, + content: message, + centered: true, + afterClose: () => { + authStore.logout(); + }, + }); + } + } + + onMounted(_register); + onUnmounted(_release); +} diff --git a/apps/vben5/apps/app-antd/src/layouts/basic.vue b/apps/vben5/apps/app-antd/src/layouts/basic.vue index 51412956a..5367f444e 100644 --- a/apps/vben5/apps/app-antd/src/layouts/basic.vue +++ b/apps/vben5/apps/app-antd/src/layouts/basic.vue @@ -2,11 +2,17 @@ import type { NotificationItem } from '@vben/layouts'; import { computed, ref, watch } from 'vue'; +import { useRouter } from 'vue-router'; import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants'; import { useWatermark } from '@vben/hooks'; -import { BookOpenText, CircleHelp, MdiGithub } from '@vben/icons'; +import { + BookOpenText, + CircleHelp, + createIconifyIcon, + MdiGithub, +} from '@vben/icons'; import { BasicLayout, LockScreen, @@ -17,10 +23,13 @@ import { preferences } from '@vben/preferences'; import { useAccessStore, useUserStore } from '@vben/stores'; import { openWindow } from '@vben/utils'; +import { useSessions } from '#/hooks/useSessions'; import { $t } from '#/locales'; import { useAuthStore } from '#/store'; import LoginForm from '#/views/_core/authentication/login.vue'; +const UserSettingsIcon = createIconifyIcon('tdesign:user-setting'); + const notifications = ref([ { avatar: 'https://avatar.vercel.sh/vercel.svg?text=VB', @@ -52,6 +61,9 @@ const notifications = ref([ }, ]); +useSessions(); + +const { replace } = useRouter(); const userStore = useUserStore(); const authStore = useAuthStore(); const accessStore = useAccessStore(); @@ -61,6 +73,13 @@ const showDot = computed(() => ); const menus = computed(() => [ + { + handler: () => { + replace('/account/my-settings'); + }, + icon: UserSettingsIcon, + text: $t('abp.account.settings.title'), + }, { handler: () => { openWindow(VBEN_DOC_URL, { @@ -127,10 +146,10 @@ watch( diff --git a/apps/vben5/apps/app-antd/src/locales/index.ts b/apps/vben5/apps/app-antd/src/locales/index.ts index c71aba29e..7e50af3b5 100644 --- a/apps/vben5/apps/app-antd/src/locales/index.ts +++ b/apps/vben5/apps/app-antd/src/locales/index.ts @@ -1,7 +1,9 @@ -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; import type { Locale } from 'ant-design-vue/es/locale'; import type { App } from 'vue'; + +import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; + import { ref } from 'vue'; import { @@ -15,8 +17,9 @@ import { useAbpStore } from '@abp/core'; import antdEnLocale from 'ant-design-vue/es/locale/en_US'; import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN'; import dayjs from 'dayjs'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; -import { getLocalizationApi } from '#/api/core'; +import { useAbpConfigApi } from '#/api/core/useAbpConfigApi'; const antdLocale = ref(antdDefaultLocale); @@ -72,7 +75,9 @@ async function loadDayjsLocale(lang: SupportedLanguagesType) { } } if (locale) { + dayjs.extend(localizedFormat); dayjs.locale(locale); + dayjs.extend(localizedFormat); } else { console.error(`Failed to load dayjs locale for ${lang}`); } @@ -101,6 +106,7 @@ async function loadAntdLocale(lang: SupportedLanguagesType) { */ async function loadAbpLocale(lang: SupportedLanguagesType) { const abpStore = useAbpStore(); + const { getLocalizationApi } = useAbpConfigApi(); let localization = abpStore.localization; if (lang !== localization?.currentCulture.cultureName) { @@ -118,8 +124,7 @@ async function setupI18n(app: App, options: LocaleSetupOptions = {}) { await coreSetup(app, { defaultLocale: preferences.app.locale, loadMessages, - // missingWarn: !import.meta.env.PROD, - missingWarn: false, + missingWarn: !import.meta.env.PROD, ...options, }); } diff --git a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json index 199e139ab..ad3c91b93 100644 --- a/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json +++ b/apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json @@ -1,5 +1,15 @@ { "title": "Abp Framework", + "oauth": { + "twoFactor": { + "title": "Two Factor", + "authenticator": "Authenticator", + "emailAddress": "Email Address", + "phoneNumber": "Phone Number", + "getCode": "Get Code", + "code": "Code" + } + }, "manage": { "title": "Manage", "identity": { @@ -8,7 +18,63 @@ "role": "Role", "claimTypes": "Claim Types", "securityLogs": "Security Logs", - "organizationUnits": "Organization Units" + "organizationUnits": "Organization Units", + "auditLogs": "Audit Logs", + "sessions": "Sessions" + }, + "permissions": { + "title": "Permissions", + "groups": "Groups", + "definitions": "Definitions" + }, + "settings": { + "title": "Settings", + "definitions": "Definitions", + "system": "System Settings" + }, + "notifications": { + "title": "Notifications", + "myNotifilers": "My Notifilers" + } + }, + "openiddict": { + "title": "OpenIddict", + "applications": "Applications", + "authorizations": "Authorizations", + "scopes": "Scopes", + "tokens": "Tokens" + }, + "account": { + "title": "Account", + "settings": { + "title": "My Settings", + "basic": { + "title": "Basic Settings" + }, + "security": { + "title": "Security Settings", + "unSet": "Not Set", + "verified": "Verified", + "unVerified": "Not Verified", + "email": "Email", + "password": "Password", + "passwordDesc": "Reset My Password", + "phoneNumber": "PhoneNumber" + }, + "bindSettings": "Bind Settings", + "noticeSettings": "Notice Settings", + "authenticatorSettings": "Authenticator Settings", + "changeAvatar": "Change Avatar", + "sessionSettings": "Session Settings" + }, + "profile": "My Profile" + }, + "platform": { + "title": "Platform", + "messages": { + "title": "Message Manage", + "email": "Email Messages", + "sms": "Sms Messages" } } } diff --git a/apps/vben5/apps/app-antd/src/locales/langs/en-US/component.json b/apps/vben5/apps/app-antd/src/locales/langs/en-US/component.json new file mode 100644 index 000000000..ec06e040c --- /dev/null +++ b/apps/vben5/apps/app-antd/src/locales/langs/en-US/component.json @@ -0,0 +1,123 @@ +{ + "localizable_input": { + "placeholder": "Select localized resources", + "resources": { + "fiexed": { + "group": "Define", + "label": "Fiexed", + "placeholder": "Please enter custom content" + }, + "localization": { + "group": "Localization", + "placeholder": "Please select a name" + } + } + }, + "extra_property_dictionary": { + "title": "Extra properties", + "key": "Key", + "value": "Value", + "actions": { + "title": "Actions", + "create": "Add", + "update": "Edit", + "delete": "Delete", + "clean": "Clean" + }, + "itemWillBeDeleted": "{key} will be deleted!", + "validator": { + "duplicateKey": "A key of the same name has been added" + } + }, + "value_type_nput": { + "type": { + "name": "Type", + "FREE_TEXT": { + "name": "Free Text" + }, + "TOGGLE": { + "name": "Toggle" + }, + "SELECTION": { + "name": "Selection", + "displayText": "Display Text", + "displayTextNotBeEmpty": "Display text cannot be empty", + "value": "value", + "duplicateKeyOrValue": "The name or value of the selection is not allowed to be repeated", + "itemsNotBeEmpty": "Selectable items cannot be empty", + "itemsNotFound": "The selection is not included in the optional list", + "actions": { + "title": "Actions", + "create": "Add", + "update": "Edit", + "delete": "Delete", + "clean": "Clean" + }, + "modal": { + "title": "Selection" + } + } + }, + "validator": { + "name": "Validator", + "isInvalidValue": "The value failed to pass {0}; check the validator options.", + "NULL": { + "name": "None" + }, + "BOOLEAN": { + "name": "Boolean" + }, + "NUMERIC": { + "name": "Numeric", + "minValue": "Min Value", + "maxValue": "Max Value" + }, + "STRING": { + "name": "String", + "allowNull": "Allow Null", + "minLength": "Min Length", + "maxLength": "Max Length", + "regularExpression": "Regular Expression" + } + } + }, + "simple_state_checking": { + "title": "State checking", + "actions": { + "create": "Add", + "update": "Edit", + "delete": "Delete", + "clean": "Clean" + }, + "table": { + "name": "Name", + "properties": "Properties", + "actions": "Actions" + }, + "form": { + "name": "State checking" + }, + "requireAuthenticated": { + "title": "Require Authenticated" + }, + "requireFeatures": { + "title": "Require Features", + "requiresAll": "Requires All", + "requiresAllDesc": "If checked, all selected features need to be enabled.", + "featureNames": "Required features" + }, + "requireGlobalFeatures": { + "title": "Require Global Features", + "featureNames": "Required Global Features" + }, + "requirePermissions": { + "title": "Require Permissions", + "requiresAll": "Requires All", + "requiresAllDesc": "If checked, you need to have all the selected permissions.", + "permissions": "Required Permissions" + } + }, + "table": { + "selectedItemWellBeDeleted": "Multiple items selected will be deleted!" + } +} diff --git a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json index fd9d57776..bcf96d391 100644 --- a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json +++ b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json @@ -1,5 +1,15 @@ { "title": "Abp框架", + "oauth": { + "twoFactor": { + "title": "二次认证", + "authenticator": "验证方式", + "emailAddress": "电子邮件", + "phoneNumber": "手机号码", + "getCode": "获取验证码", + "code": "验证码" + } + }, "manage": { "title": "管理", "identity": { @@ -8,7 +18,63 @@ "role": "角色", "claimTypes": "身份标识", "securityLogs": "安全日志", - "organizationUnits": "组织机构" + "organizationUnits": "组织机构", + "auditLogs": "审计日志", + "sessions": "会话管理" + }, + "permissions": { + "title": "权限管理", + "groups": "权限分组", + "definitions": "权限定义" + }, + "settings": { + "title": "设置管理", + "definitions": "设置定义", + "system": "系统设置" + }, + "notifications": { + "title": "通知管理", + "myNotifilers": "我的通知" + } + }, + "openiddict": { + "title": "OpenIddict", + "applications": "应用管理", + "authorizations": "授权管理", + "scopes": "范围管理", + "tokens": "授权令牌" + }, + "account": { + "title": "账户管理", + "settings": { + "title": "个人设置", + "basic": { + "title": "基本设置" + }, + "security": { + "title": "安全设置", + "unSet": "未设置", + "verified": "已验证", + "unVerified": "未验证", + "email": "电子邮件", + "password": "密码", + "passwordDesc": "重置我的密码", + "phoneNumber": "手机号码" + }, + "bindSettings": "账号绑定", + "noticeSettings": "新消息通知", + "authenticatorSettings": "身份验证程序", + "changeAvatar": "更改头像", + "sessionSettings": "会话管理" + }, + "profile": "个人中心" + }, + "platform": { + "title": "平台管理", + "messages": { + "title": "消息管理", + "email": "邮件消息", + "sms": "短信消息" } } } diff --git a/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/component.json b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/component.json new file mode 100644 index 000000000..4a14cb108 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/locales/langs/zh-CN/component.json @@ -0,0 +1,123 @@ +{ + "localizable_input": { + "placeholder": "请选择本地化资源", + "resources": { + "fiexed": { + "group": "自定义", + "label": "固定内容", + "placeholder": "请输入自定义内容" + }, + "localization": { + "group": "本地化", + "placeholder": "请选择名称" + } + } + }, + "extra_property_dictionary": { + "title": "扩展属性", + "key": "名称", + "value": "键值", + "actions": { + "title": "操作", + "create": "新增", + "update": "编辑", + "delete": "删除", + "clean": "清除" + }, + "validator": { + "duplicateKey": "已经添加了一个相同名称的键" + }, + "itemWillBeDeleted": "{key} 将被删除!" + }, + "value_type_nput": { + "type": { + "name": "类型", + "FREE_TEXT": { + "name": "自由文本" + }, + "TOGGLE": { + "name": "切换" + }, + "SELECTION": { + "name": "选择", + "displayText": "显示名称", + "displayTextNotBeEmpty": "显示名称不可为空", + "value": "选择项", + "duplicateKeyOrValue": "选择项的名称或值不允许重复", + "itemsNotBeEmpty": "可选择项列表不能为空", + "itemsNotFound": "选择项不包含在可选列表中", + "actions": { + "title": "操作", + "create": "新增", + "update": "编辑", + "delete": "删除", + "clean": "清除" + }, + "modal": { + "title": "选择项" + } + } + }, + "validator": { + "name": "验证器", + "isInvalidValue": "值未能通过 {0} 校验, 请检查验证器选项.", + "NULL": { + "name": "未定义" + }, + "BOOLEAN": { + "name": "布尔类型" + }, + "NUMERIC": { + "name": "数值类型", + "minValue": "最小值", + "maxValue": "最大值" + }, + "STRING": { + "name": "字符类型", + "allowNull": "允许空值", + "minLength": "最小长度", + "maxLength": "最大长度", + "regularExpression": "正则表达式" + } + } + }, + "simple_state_checking": { + "title": "状态检查", + "actions": { + "create": "新增", + "update": "编辑", + "delete": "删除", + "clean": "清除" + }, + "table": { + "name": "名称", + "properties": "属性", + "actions": "操作" + }, + "form": { + "name": "状态检查器" + }, + "requireAuthenticated": { + "title": "需要用户认证" + }, + "requireFeatures": { + "title": "检查所需功能", + "requiresAll": "要求所有", + "requiresAllDesc": "如果勾选,则需要启用所有选择的功能.", + "featureNames": "需要的功能" + }, + "requireGlobalFeatures": { + "title": "检查全局功能", + "featureNames": "需要的全局功能" + }, + "requirePermissions": { + "title": "检查所需权限", + "requiresAll": "要求所有", + "requiresAllDesc": "如果勾选,则需要拥有所有选择的权限.", + "permissions": "需要的权限" + } + }, + "table": { + "selectedItemWellBeDeleted": "选择的多个项目将被删除!" + } +} diff --git a/apps/vben5/apps/app-antd/src/preferences.ts b/apps/vben5/apps/app-antd/src/preferences.ts index b2e9ace43..498967adc 100644 --- a/apps/vben5/apps/app-antd/src/preferences.ts +++ b/apps/vben5/apps/app-antd/src/preferences.ts @@ -8,6 +8,7 @@ import { defineOverridesPreferences } from '@vben/preferences'; export const overridesPreferences = defineOverridesPreferences({ // overrides app: { + enableRefreshToken: true, name: import.meta.env.VITE_APP_TITLE, }, }); diff --git a/apps/vben5/apps/app-antd/src/router/guard.ts b/apps/vben5/apps/app-antd/src/router/guard.ts index fce5a892c..cbb5235ec 100644 --- a/apps/vben5/apps/app-antd/src/router/guard.ts +++ b/apps/vben5/apps/app-antd/src/router/guard.ts @@ -54,7 +54,9 @@ function setupAccessGuard(router: Router) { if (coreRouteNames.includes(to.name as string)) { if (to.path === LOGIN_PATH && accessStore.accessToken) { return decodeURIComponent( - (to.query?.redirect as string) || DEFAULT_HOME_PATH, + (to.query?.redirect as string) || + userStore.userInfo?.homePath || + DEFAULT_HOME_PATH, ); } return true; @@ -72,7 +74,10 @@ function setupAccessGuard(router: Router) { return { path: LOGIN_PATH, // 如不需要,直接删除 query - query: { redirect: encodeURIComponent(to.fullPath) }, + query: + to.fullPath === DEFAULT_HOME_PATH + ? {} + : { redirect: encodeURIComponent(to.fullPath) }, // 携带当前跳转的页面,登录后重新跳转该页面 replace: true, }; @@ -102,7 +107,10 @@ function setupAccessGuard(router: Router) { accessStore.setAccessMenus(accessibleMenus); accessStore.setAccessRoutes(accessibleRoutes); accessStore.setIsAccessChecked(true); - const redirectPath = (from.query.redirect ?? to.fullPath) as string; + const redirectPath = (from.query.redirect ?? + (to.path === DEFAULT_HOME_PATH + ? userInfo.homePath || DEFAULT_HOME_PATH + : to.fullPath)) as string; return { ...router.resolve(decodeURIComponent(redirectPath)), diff --git a/apps/vben5/apps/app-antd/src/router/routes/core.ts b/apps/vben5/apps/app-antd/src/router/routes/core.ts index fe030a9a2..7218da228 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/core.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/core.ts @@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router'; import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; -import { AuthPageLayout } from '#/layouts'; +import { AuthPageLayout, BasicLayout } from '#/layouts'; import { $t } from '#/locales'; import Login from '#/views/_core/authentication/login.vue'; @@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts b/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts index 6fd11549e..a59ca4255 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts @@ -1,11 +1,9 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'https://abp.io/assets/favicon.ico/favicon-16x16.png', keepAlive: true, @@ -79,6 +77,210 @@ const routes: RouteRecordRaw[] = [ icon: 'clarity:organization-line', }, }, + { + component: () => import('#/views/identity/sessions/index.vue'), + name: 'IdentitySessions', + path: '/manage/identity/sessions', + meta: { + title: $t('abp.manage.identity.sessions'), + icon: 'carbon:prompt-session', + }, + }, + ], + }, + { + meta: { + title: $t('abp.manage.permissions.title'), + icon: 'arcticons:permissionsmanager', + }, + name: 'PermissionManagement', + path: '/manage/permissions', + children: [ + { + meta: { + title: $t('abp.manage.permissions.groups'), + icon: 'lucide:group', + }, + name: 'PermissionGroupDefinitions', + path: '/manage/permissions/groups', + component: () => import('#/views/permissions/groups/index.vue'), + }, + { + meta: { + title: $t('abp.manage.permissions.definitions'), + icon: 'icon-park-outline:permissions', + }, + name: 'PermissionDefinitions', + path: '/manage/permissions/definitions', + component: () => + import('#/views/permissions/definitions/index.vue'), + }, + ], + }, + { + meta: { + title: $t('abp.manage.settings.title'), + icon: 'ic:outline-settings', + }, + name: 'SettingManagement', + path: '/manage/settings', + children: [ + { + meta: { + title: $t('abp.manage.settings.definitions'), + icon: 'codicon:settings', + }, + name: 'SettingDefinitions', + path: '/manage/settings/definitions', + component: () => + import('#/views/settings/definitions/index.vue'), + }, + { + meta: { + title: $t('abp.manage.settings.system'), + icon: 'tabler:settings-cog', + }, + name: 'SystemSettings', + path: '/manage/settings/system', + component: () => import('#/views/settings/system/index.vue'), + }, + ], + }, + { + meta: { + title: $t('abp.manage.identity.auditLogs'), + icon: 'fluent-mdl2:compliance-audit', + }, + name: 'AuditingAuditLogs', + path: '/manage/audit-logs', + component: () => import('#/views/auditing/audit-logs/index.vue'), + }, + { + meta: { + title: $t('abp.manage.notifications.title'), + icon: 'tabler:notification', + }, + name: 'Notifications', + path: '/manage/notifications', + children: [ + { + meta: { + title: $t('abp.manage.notifications.myNotifilers'), + icon: 'ant-design:notification-outlined', + }, + name: 'MyNotifications', + path: '/manage/notifications/my-notifilers', + component: () => + import('#/views/notifications/my-notifilers/index.vue'), + }, + ], + }, + ], + }, + { + meta: { + title: $t('abp.openiddict.title'), + icon: 'mdi:openid', + }, + name: 'OpenIddict', + path: '/openiddict', + children: [ + { + meta: { + title: $t('abp.openiddict.applications'), + icon: 'carbon:application', + }, + name: 'OpenIddictApplications', + path: '/openiddict/applications', + component: () => + import('#/views/openiddict/applications/index.vue'), + }, + { + meta: { + title: $t('abp.openiddict.authorizations'), + icon: 'arcticons:ente-authenticator', + }, + name: 'OpenIddictAuthorizations', + path: '/openiddict/authorizations', + component: () => + import('#/views/openiddict/authorizations/index.vue'), + }, + { + meta: { + title: $t('abp.openiddict.scopes'), + icon: 'et:scope', + }, + name: 'OpenIddictScopes', + path: '/openiddict/scopes', + component: () => import('#/views/openiddict/scopes/index.vue'), + }, + { + meta: { + title: $t('abp.openiddict.tokens'), + icon: 'oui:token-key', + }, + name: 'OpenIddictTokens', + path: '/openiddict/tokens', + component: () => import('#/views/openiddict/tokens/index.vue'), + }, + ], + }, + { + name: 'Account', + path: '/account', + meta: { + title: $t('abp.account.title'), + icon: 'mdi:account-outline', + hideInMenu: true, + }, + children: [ + { + meta: { + title: $t('abp.account.settings.title'), + icon: 'tdesign:user-setting', + }, + name: 'MySettings', + path: '/account/my-settings', + component: () => import('#/views/account/my-settings/index.vue'), + }, + ], + }, + { + name: 'Platform', + path: '/platform', + meta: { + title: $t('abp.platform.title'), + icon: 'ep:platform', + }, + children: [ + { + meta: { + title: $t('abp.platform.messages.title'), + icon: 'tabler:message-cog', + }, + name: 'PlatformMessages', + path: '/platform/messages', + children: [ + { + meta: { + title: $t('abp.platform.messages.email'), + icon: 'material-symbols:attach-email-outline', + }, + name: 'PlatformEmailMessages', + path: '/platform/messages/email', + component: () => + import('#/views/platform/messages/email/index.vue'), + }, + { + meta: { + title: $t('abp.platform.messages.sms'), + icon: 'material-symbols:sms-outline', + }, + name: 'PlatformSmsMessages', + path: '/platform/messages/sms', + component: () => + import('#/views/platform/messages/sms/index.vue'), + }, ], }, ], diff --git a/apps/vben5/apps/app-antd/src/router/routes/modules/dashboard.ts b/apps/vben5/apps/app-antd/src/router/routes/modules/dashboard.ts index 1bddab9db..5254dc65d 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/modules/dashboard.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/modules/dashboard.ts @@ -1,18 +1,16 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'lucide:layout-dashboard', order: -1, title: $t('page.dashboard.title'), }, name: 'Dashboard', - path: '/', + path: '/dashboard', children: [ { name: 'Analytics', diff --git a/apps/vben5/apps/app-antd/src/router/routes/modules/demos.ts b/apps/vben5/apps/app-antd/src/router/routes/modules/demos.ts index 32bb338e0..55ade09c9 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/modules/demos.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/modules/demos.ts @@ -1,11 +1,9 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, diff --git a/apps/vben5/apps/app-antd/src/router/routes/modules/vben.ts b/apps/vben5/apps/app-antd/src/router/routes/modules/vben.ts index 210e8610f..98acf5821 100644 --- a/apps/vben5/apps/app-antd/src/router/routes/modules/vben.ts +++ b/apps/vben5/apps/app-antd/src/router/routes/modules/vben.ts @@ -8,30 +8,20 @@ import { VBEN_NAIVE_PREVIEW_URL, } from '@vben/constants'; -import { BasicLayout, IFrameView } from '#/layouts'; +import { IFrameView } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { badgeType: 'dot', icon: VBEN_LOGO_URL, - order: 9999, + order: 9998, title: $t('demos.vben.title'), }, name: 'VbenProject', path: '/vben-admin', children: [ - { - name: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - }, - }, { name: 'VbenDocument', path: '/vben-admin/document', @@ -76,6 +66,16 @@ const routes: RouteRecordRaw[] = [ }, ], }, + { + name: 'VbenAbout', + path: '/vben-admin/about', + component: () => import('#/views/_core/about/index.vue'), + meta: { + icon: 'lucide:copyright', + title: $t('demos.vben.about'), + order: 9999, + }, + }, ]; export default routes; diff --git a/apps/vben5/apps/app-antd/src/store/auth.ts b/apps/vben5/apps/app-antd/src/store/auth.ts index c4a8670fa..deb7fe4b8 100644 --- a/apps/vben5/apps/app-antd/src/store/auth.ts +++ b/apps/vben5/apps/app-antd/src/store/auth.ts @@ -6,15 +6,19 @@ import { useRouter } from 'vue-router'; import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores'; -import { getUserInfoApi, loginApi } from '@abp/account'; -import { useAbpStore } from '@abp/core'; +import { useTokenApi, useUserInfoApi } from '@abp/account'; +import { Events, useAbpStore, useEventBus } from '@abp/core'; import { notification } from 'ant-design-vue'; import { defineStore } from 'pinia'; -import { getConfigApi } from '#/api/core/abp'; +import { useAbpConfigApi } from '#/api/core/useAbpConfigApi'; import { $t } from '#/locales'; export const useAuthStore = defineStore('auth', () => { + const { publish } = useEventBus(); + const { loginApi } = useTokenApi(); + const { getUserInfoApi } = useUserInfoApi(); + const { getConfigApi } = useAbpConfigApi(); const accessStore = useAccessStore(); const userStore = useUserStore(); const abpStore = useAbpStore(); @@ -46,6 +50,8 @@ export const useAuthStore = defineStore('auth', () => { userStore.setUserInfo(userInfo); + publish(Events.UserLogin, userInfo); + if (accessStore.loginExpired) { accessStore.setLoginExpired(false); } else { @@ -80,6 +86,8 @@ export const useAuthStore = defineStore('auth', () => { resetAllStores(); accessStore.setLoginExpired(false); + publish(Events.UserLogout); + // 回登录页带上当前路由地址 await router.replace({ path: LOGIN_PATH, @@ -96,12 +104,18 @@ export const useAuthStore = defineStore('auth', () => { const userInfoRes = await getUserInfoApi(); const abpConfig = await getConfigApi(); userInfo = { - userId: userInfoRes.sub, - username: userInfoRes.uniqueName, - realName: userInfoRes.name, + userId: userInfoRes.sub ?? abpConfig.currentUser.id, + username: userInfoRes.uniqueName ?? abpConfig.currentUser.userName, + realName: userInfoRes.name ?? abpConfig.currentUser.name, avatar: userInfoRes.avatarUrl ?? userInfoRes.picture, desc: userInfoRes.uniqueName ?? userInfoRes.name, email: userInfoRes.email ?? userInfoRes.email, + emailVerified: + userInfoRes.emailVerified ?? abpConfig.currentUser.emailVerified, + phoneNumber: userInfoRes.phoneNumber ?? abpConfig.currentUser.phoneNumber, + phoneNumberVerified: + userInfoRes.phoneNumberVerified ?? + abpConfig.currentUser.phoneNumberVerified, token: '', roles: abpConfig.currentUser.roles, homePath: '/', diff --git a/apps/vben5/apps/app-antd/src/views/_core/authentication/login.vue b/apps/vben5/apps/app-antd/src/views/_core/authentication/login.vue index 7fee812fd..d0cd7f002 100644 --- a/apps/vben5/apps/app-antd/src/views/_core/authentication/login.vue +++ b/apps/vben5/apps/app-antd/src/views/_core/authentication/login.vue @@ -1,13 +1,17 @@ - + + + + diff --git a/apps/vben5/apps/app-antd/src/views/_core/authentication/two-factor-login.vue b/apps/vben5/apps/app-antd/src/views/_core/authentication/two-factor-login.vue new file mode 100644 index 000000000..cf9270deb --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/_core/authentication/two-factor-login.vue @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + {{ getSendValidCodeTitle }} + + + + + + + + + + + + + + {{ getSendValidCodeTitle }} + + + + + + + + + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/account/my-profile/index.vue b/apps/vben5/apps/app-antd/src/views/account/my-profile/index.vue new file mode 100644 index 000000000..bb567c555 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/account/my-profile/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue b/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue new file mode 100644 index 000000000..0ce7db2d0 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/account/my-settings/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/auditing/audit-logs/index.vue b/apps/vben5/apps/app-antd/src/views/auditing/audit-logs/index.vue new file mode 100644 index 000000000..2ee3b0880 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/auditing/audit-logs/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/dashboard/analytics/analytics-trends.vue b/apps/vben5/apps/app-antd/src/views/dashboard/analytics/analytics-trends.vue index fadfc917c..f1f0b232a 100644 --- a/apps/vben5/apps/app-antd/src/views/dashboard/analytics/analytics-trends.vue +++ b/apps/vben5/apps/app-antd/src/views/dashboard/analytics/analytics-trends.vue @@ -1,11 +1,9 @@ + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/notifications/my-notifilers/index.vue b/apps/vben5/apps/app-antd/src/views/notifications/my-notifilers/index.vue new file mode 100644 index 000000000..ed3d7e67b --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/notifications/my-notifilers/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/openiddict/applications/index.vue b/apps/vben5/apps/app-antd/src/views/openiddict/applications/index.vue new file mode 100644 index 000000000..1e347ea86 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/openiddict/applications/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/openiddict/authorizations/index.vue b/apps/vben5/apps/app-antd/src/views/openiddict/authorizations/index.vue new file mode 100644 index 000000000..cb96f15fd --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/openiddict/authorizations/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/openiddict/scopes/index.vue b/apps/vben5/apps/app-antd/src/views/openiddict/scopes/index.vue new file mode 100644 index 000000000..6b73e3266 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/openiddict/scopes/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/openiddict/tokens/index.vue b/apps/vben5/apps/app-antd/src/views/openiddict/tokens/index.vue new file mode 100644 index 000000000..c575482e4 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/openiddict/tokens/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/permissions/definitions/index.vue b/apps/vben5/apps/app-antd/src/views/permissions/definitions/index.vue new file mode 100644 index 000000000..a72624d3c --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/permissions/definitions/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/permissions/groups/index.vue b/apps/vben5/apps/app-antd/src/views/permissions/groups/index.vue new file mode 100644 index 000000000..f651c1d2d --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/permissions/groups/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/platform/messages/email/index.vue b/apps/vben5/apps/app-antd/src/views/platform/messages/email/index.vue new file mode 100644 index 000000000..d61fd6f64 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/platform/messages/email/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/platform/messages/sms/index.vue b/apps/vben5/apps/app-antd/src/views/platform/messages/sms/index.vue new file mode 100644 index 000000000..ed5c319b5 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/platform/messages/sms/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/settings/definitions/index.vue b/apps/vben5/apps/app-antd/src/views/settings/definitions/index.vue new file mode 100644 index 000000000..545f397d3 --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/settings/definitions/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/src/views/settings/system/index.vue b/apps/vben5/apps/app-antd/src/views/settings/system/index.vue new file mode 100644 index 000000000..f602c52ef --- /dev/null +++ b/apps/vben5/apps/app-antd/src/views/settings/system/index.vue @@ -0,0 +1,15 @@ + + + + + + + diff --git a/apps/vben5/apps/app-antd/vite.config.mts b/apps/vben5/apps/app-antd/vite.config.mts index cc4b2bef1..ae6f52e14 100644 --- a/apps/vben5/apps/app-antd/vite.config.mts +++ b/apps/vben5/apps/app-antd/vite.config.mts @@ -6,18 +6,21 @@ export default defineConfig(async () => { vite: { server: { proxy: { + '/.well-known': { + changeOrigin: true, + target: 'http://127.0.0.1:30001/', + }, '/api': { changeOrigin: true, - // rewrite: (path) => path.replace(/^\/api/, ''), - // mock代理目标地址 - target: 'http://81.68.64.105:30001/', - ws: true, + target: 'http://127.0.0.1:30001/', }, '/connect': { changeOrigin: true, - // rewrite: (path) => path.replace(/^\/api/, ''), - // mock代理目标地址 - target: 'http://81.68.64.105:30001/', + target: 'http://127.0.0.1:30001/', + }, + '/signalr-hubs': { + changeOrigin: true, + target: 'http://127.0.0.1:30001/', ws: true, }, }, diff --git a/apps/vben5/apps/backend-mock/api/table/list.ts b/apps/vben5/apps/backend-mock/api/table/list.ts index 4a0db94ec..55b88eaaa 100644 --- a/apps/vben5/apps/backend-mock/api/table/list.ts +++ b/apps/vben5/apps/backend-mock/api/table/list.ts @@ -43,6 +43,31 @@ export default eventHandler(async (event) => { await sleep(600); - const { page, pageSize } = getQuery(event); - return usePageResponseSuccess(page as string, pageSize as string, mockData); + const { page, pageSize, sortBy, sortOrder } = getQuery(event); + const listData = structuredClone(mockData); + if (sortBy && Reflect.has(listData[0], sortBy as string)) { + listData.sort((a, b) => { + if (sortOrder === 'asc') { + if (sortBy === 'price') { + return ( + Number.parseFloat(a[sortBy as string]) - + Number.parseFloat(b[sortBy as string]) + ); + } else { + return a[sortBy as string] > b[sortBy as string] ? 1 : -1; + } + } else { + if (sortBy === 'price') { + return ( + Number.parseFloat(b[sortBy as string]) - + Number.parseFloat(a[sortBy as string]) + ); + } else { + return a[sortBy as string] < b[sortBy as string] ? 1 : -1; + } + } + }); + } + + return usePageResponseSuccess(page as string, pageSize as string, listData); }); diff --git a/apps/vben5/apps/backend-mock/utils/mock-data.ts b/apps/vben5/apps/backend-mock/utils/mock-data.ts index 71970a285..8fa12fe57 100644 --- a/apps/vben5/apps/backend-mock/utils/mock-data.ts +++ b/apps/vben5/apps/backend-mock/utils/mock-data.ts @@ -4,6 +4,7 @@ export interface UserInfo { realName: string; roles: string[]; username: string; + homePath?: string; } export const MOCK_USERS: UserInfo[] = [ @@ -20,6 +21,7 @@ export const MOCK_USERS: UserInfo[] = [ realName: 'Admin', roles: ['admin'], username: 'admin', + homePath: '/workspace', }, { id: 2, @@ -27,6 +29,7 @@ export const MOCK_USERS: UserInfo[] = [ realName: 'Jack', roles: ['user'], username: 'jack', + homePath: '/analytics', }, ]; @@ -50,13 +53,12 @@ export const MOCK_CODES = [ const dashboardMenus = [ { - component: 'BasicLayout', meta: { order: -1, title: 'page.dashboard.title', }, name: 'Dashboard', - path: '/', + path: '/dashboard', redirect: '/analytics', children: [ { @@ -113,7 +115,6 @@ const createDemosMenus = (role: 'admin' | 'super' | 'user') => { return [ { - component: 'BasicLayout', meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, diff --git a/apps/vben5/apps/web-antd/package.json b/apps/vben5/apps/web-antd/package.json index 42afa3c69..487622574 100644 --- a/apps/vben5/apps/web-antd/package.json +++ b/apps/vben5/apps/web-antd/package.json @@ -1,6 +1,6 @@ { "name": "@vben/web-antd", - "version": "5.4.8", + "version": "5.5.3", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/apps/vben5/apps/web-antd/src/adapter/component/index.ts b/apps/vben5/apps/web-antd/src/adapter/component/index.ts index 1afa62174..17436a834 100644 --- a/apps/vben5/apps/web-antd/src/adapter/component/index.ts +++ b/apps/vben5/apps/web-antd/src/adapter/component/index.ts @@ -3,12 +3,13 @@ * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, */ +import type { Component, SetupContext } from 'vue'; + import type { BaseFormComponentType } from '@vben/common-ui'; -import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState } from '@vben/common-ui'; +import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { @@ -48,12 +49,15 @@ const withDefaultPlaceholder = ( // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 export type ComponentType = + | 'ApiSelect' + | 'ApiTreeSelect' | 'AutoComplete' | 'Checkbox' | 'CheckboxGroup' | 'DatePicker' | 'DefaultButton' | 'Divider' + | 'IconPicker' | 'Input' | 'InputNumber' | 'InputPassword' @@ -77,7 +81,38 @@ async function initComponentAdapter() { // 如果你的组件体积比较大,可以使用异步加载 // Button: () => // import('xxx').then((res) => res.Button), - + ApiSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: Select, + loadingSlot: 'suffixIcon', + visibleEvent: 'onDropdownVisibleChange', + modelPropName: 'value', + }, + slots, + ); + }, + ApiTreeSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: TreeSelect, + fieldNames: { label: 'label', value: 'value', children: 'children' }, + loadingSlot: 'suffixIcon', + modelPropName: 'value', + optionsPropName: 'treeData', + visibleEvent: 'onVisibleChange', + }, + slots, + ); + }, AutoComplete, Checkbox, CheckboxGroup, @@ -87,6 +122,13 @@ async function initComponentAdapter() { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, + IconPicker: (props, { attrs, slots }) => { + return h( + IconPicker, + { iconSlot: 'addonAfter', inputComponent: Input, ...props, ...attrs }, + slots, + ); + }, Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), diff --git a/apps/vben5/apps/web-antd/src/api/request.ts b/apps/vben5/apps/web-antd/src/api/request.ts index 67ef35e44..288dddd09 100644 --- a/apps/vben5/apps/web-antd/src/api/request.ts +++ b/apps/vben5/apps/web-antd/src/api/request.ts @@ -1,12 +1,13 @@ /** * 该文件可自行根据业务逻辑进行调整 */ -import type { HttpResponse } from '@vben/request'; +import type { RequestClientOptions } from '@vben/request'; import { useAppConfig } from '@vben/hooks'; import { preferences } from '@vben/preferences'; import { authenticateResponseInterceptor, + defaultResponseInterceptor, errorMessageResponseInterceptor, RequestClient, } from '@vben/request'; @@ -20,8 +21,9 @@ import { refreshTokenApi } from './core'; const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); -function createRequestClient(baseURL: string) { +function createRequestClient(baseURL: string, options?: RequestClientOptions) { const client = new RequestClient({ + ...options, baseURL, }); @@ -69,19 +71,14 @@ function createRequestClient(baseURL: string) { }, }); - // response数据解构 - client.addResponseInterceptor({ - fulfilled: (response) => { - const { data: responseData, status } = response; - - const { code, data } = responseData; - if (status >= 200 && status < 400 && code === 0) { - return data; - } - - throw Object.assign({}, response, { response }); - }, - }); + // 处理返回的响应数据格式 + client.addResponseInterceptor( + defaultResponseInterceptor({ + codeField: 'code', + dataField: 'data', + successCode: 0, + }), + ); // token过期的处理 client.addResponseInterceptor( @@ -109,6 +106,8 @@ function createRequestClient(baseURL: string) { return client; } -export const requestClient = createRequestClient(apiURL); +export const requestClient = createRequestClient(apiURL, { + responseReturn: 'data', +}); export const baseRequestClient = new RequestClient({ baseURL: apiURL }); diff --git a/apps/vben5/apps/web-antd/src/bootstrap.ts b/apps/vben5/apps/web-antd/src/bootstrap.ts index 963d1c7f7..b46bfbcf2 100644 --- a/apps/vben5/apps/web-antd/src/bootstrap.ts +++ b/apps/vben5/apps/web-antd/src/bootstrap.ts @@ -1,6 +1,7 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; +import { initTippy } from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; @@ -18,6 +19,15 @@ async function bootstrap(namespace: string) { // 初始化组件适配器 await initComponentAdapter(); + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // zIndex: 1020, + // }); + const app = createApp(App); // 国际化 i18n 配置 @@ -29,6 +39,9 @@ async function bootstrap(namespace: string) { // 安装权限指令 registerAccessDirective(app); + // 初始化 tippy + initTippy(app); + // 配置路由及路由守卫 app.use(router); diff --git a/apps/vben5/apps/web-antd/src/locales/index.ts b/apps/vben5/apps/web-antd/src/locales/index.ts index 1972e06ee..7f32bd18e 100644 --- a/apps/vben5/apps/web-antd/src/locales/index.ts +++ b/apps/vben5/apps/web-antd/src/locales/index.ts @@ -1,7 +1,9 @@ -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; import type { Locale } from 'ant-design-vue/es/locale'; import type { App } from 'vue'; + +import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; + import { ref } from 'vue'; import { diff --git a/apps/vben5/apps/web-antd/src/router/guard.ts b/apps/vben5/apps/web-antd/src/router/guard.ts index fce5a892c..cbb5235ec 100644 --- a/apps/vben5/apps/web-antd/src/router/guard.ts +++ b/apps/vben5/apps/web-antd/src/router/guard.ts @@ -54,7 +54,9 @@ function setupAccessGuard(router: Router) { if (coreRouteNames.includes(to.name as string)) { if (to.path === LOGIN_PATH && accessStore.accessToken) { return decodeURIComponent( - (to.query?.redirect as string) || DEFAULT_HOME_PATH, + (to.query?.redirect as string) || + userStore.userInfo?.homePath || + DEFAULT_HOME_PATH, ); } return true; @@ -72,7 +74,10 @@ function setupAccessGuard(router: Router) { return { path: LOGIN_PATH, // 如不需要,直接删除 query - query: { redirect: encodeURIComponent(to.fullPath) }, + query: + to.fullPath === DEFAULT_HOME_PATH + ? {} + : { redirect: encodeURIComponent(to.fullPath) }, // 携带当前跳转的页面,登录后重新跳转该页面 replace: true, }; @@ -102,7 +107,10 @@ function setupAccessGuard(router: Router) { accessStore.setAccessMenus(accessibleMenus); accessStore.setAccessRoutes(accessibleRoutes); accessStore.setIsAccessChecked(true); - const redirectPath = (from.query.redirect ?? to.fullPath) as string; + const redirectPath = (from.query.redirect ?? + (to.path === DEFAULT_HOME_PATH + ? userInfo.homePath || DEFAULT_HOME_PATH + : to.fullPath)) as string; return { ...router.resolve(decodeURIComponent(redirectPath)), diff --git a/apps/vben5/apps/web-antd/src/router/routes/core.ts b/apps/vben5/apps/web-antd/src/router/routes/core.ts index fe030a9a2..7218da228 100644 --- a/apps/vben5/apps/web-antd/src/router/routes/core.ts +++ b/apps/vben5/apps/web-antd/src/router/routes/core.ts @@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router'; import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; -import { AuthPageLayout } from '#/layouts'; +import { AuthPageLayout, BasicLayout } from '#/layouts'; import { $t } from '#/locales'; import Login from '#/views/_core/authentication/login.vue'; @@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/vben5/apps/web-antd/src/router/routes/modules/dashboard.ts b/apps/vben5/apps/web-antd/src/router/routes/modules/dashboard.ts index 1bddab9db..5254dc65d 100644 --- a/apps/vben5/apps/web-antd/src/router/routes/modules/dashboard.ts +++ b/apps/vben5/apps/web-antd/src/router/routes/modules/dashboard.ts @@ -1,18 +1,16 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'lucide:layout-dashboard', order: -1, title: $t('page.dashboard.title'), }, name: 'Dashboard', - path: '/', + path: '/dashboard', children: [ { name: 'Analytics', diff --git a/apps/vben5/apps/web-antd/src/router/routes/modules/demos.ts b/apps/vben5/apps/web-antd/src/router/routes/modules/demos.ts index 32bb338e0..55ade09c9 100644 --- a/apps/vben5/apps/web-antd/src/router/routes/modules/demos.ts +++ b/apps/vben5/apps/web-antd/src/router/routes/modules/demos.ts @@ -1,11 +1,9 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, diff --git a/apps/vben5/apps/web-antd/src/router/routes/modules/vben.ts b/apps/vben5/apps/web-antd/src/router/routes/modules/vben.ts index 210e8610f..98acf5821 100644 --- a/apps/vben5/apps/web-antd/src/router/routes/modules/vben.ts +++ b/apps/vben5/apps/web-antd/src/router/routes/modules/vben.ts @@ -8,30 +8,20 @@ import { VBEN_NAIVE_PREVIEW_URL, } from '@vben/constants'; -import { BasicLayout, IFrameView } from '#/layouts'; +import { IFrameView } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { badgeType: 'dot', icon: VBEN_LOGO_URL, - order: 9999, + order: 9998, title: $t('demos.vben.title'), }, name: 'VbenProject', path: '/vben-admin', children: [ - { - name: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - }, - }, { name: 'VbenDocument', path: '/vben-admin/document', @@ -76,6 +66,16 @@ const routes: RouteRecordRaw[] = [ }, ], }, + { + name: 'VbenAbout', + path: '/vben-admin/about', + component: () => import('#/views/_core/about/index.vue'), + meta: { + icon: 'lucide:copyright', + title: $t('demos.vben.about'), + order: 9999, + }, + }, ]; export default routes; diff --git a/apps/vben5/apps/web-antd/src/views/_core/authentication/code-login.vue b/apps/vben5/apps/web-antd/src/views/_core/authentication/code-login.vue index 556b273af..acfd1fd78 100644 --- a/apps/vben5/apps/web-antd/src/views/_core/authentication/code-login.vue +++ b/apps/vben5/apps/web-antd/src/views/_core/authentication/code-login.vue @@ -10,6 +10,7 @@ import { $t } from '@vben/locales'; defineOptions({ name: 'CodeLogin' }); const loading = ref(false); +const CODE_LENGTH = 6; const formSchema = computed((): VbenFormSchema[] => { return [ @@ -30,6 +31,7 @@ const formSchema = computed((): VbenFormSchema[] => { { component: 'VbenPinInput', componentProps: { + codeLength: CODE_LENGTH, createText: (countdown: number) => { const text = countdown > 0 @@ -41,7 +43,9 @@ const formSchema = computed((): VbenFormSchema[] => { }, fieldName: 'code', label: $t('authentication.code'), - rules: z.string().min(1, { message: $t('authentication.codeTip') }), + rules: z.string().length(CODE_LENGTH, { + message: $t('authentication.codeTip', [CODE_LENGTH]), + }), }, ]; }); diff --git a/apps/vben5/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue b/apps/vben5/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue index fadfc917c..f1f0b232a 100644 --- a/apps/vben5/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue +++ b/apps/vben5/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue @@ -1,11 +1,9 @@ + + + + + + 基础表单演示 + 设置表单值 + + + + + + diff --git a/apps/vben5/apps/web-naive/package.json b/apps/vben5/apps/web-naive/package.json index 0710c3415..c649252d2 100644 --- a/apps/vben5/apps/web-naive/package.json +++ b/apps/vben5/apps/web-naive/package.json @@ -1,6 +1,6 @@ { "name": "@vben/web-naive", - "version": "5.4.8", + "version": "5.5.3", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/apps/vben5/apps/web-naive/src/adapter/component/index.ts b/apps/vben5/apps/web-naive/src/adapter/component/index.ts index c5dffddb8..a84159005 100644 --- a/apps/vben5/apps/web-naive/src/adapter/component/index.ts +++ b/apps/vben5/apps/web-naive/src/adapter/component/index.ts @@ -3,12 +3,13 @@ * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, */ +import type { Component, SetupContext } from 'vue'; + import type { BaseFormComponentType } from '@vben/common-ui'; -import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState } from '@vben/common-ui'; +import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { @@ -19,6 +20,8 @@ import { NDivider, NInput, NInputNumber, + NRadio, + NRadioButton, NRadioGroup, NSelect, NSpace, @@ -42,10 +45,13 @@ const withDefaultPlaceholder = ( // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 export type ComponentType = + | 'ApiSelect' + | 'ApiTreeSelect' | 'Checkbox' | 'CheckboxGroup' | 'DatePicker' | 'Divider' + | 'IconPicker' | 'Input' | 'InputNumber' | 'RadioGroup' @@ -63,8 +69,54 @@ async function initComponentAdapter() { // Button: () => // import('xxx').then((res) => res.Button), + ApiSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: NSelect, + modelPropName: 'value', + }, + slots, + ); + }, + ApiTreeSelect: (props, { attrs, slots }) => { + return h( + ApiComponent, + { + placeholder: $t('ui.placeholder.select'), + ...props, + ...attrs, + component: NTreeSelect, + nodeKey: 'value', + loadingSlot: 'arrow', + keyField: 'value', + modelPropName: 'value', + optionsPropName: 'options', + visibleEvent: 'onVisibleChange', + }, + slots, + ); + }, Checkbox: NCheckbox, - CheckboxGroup: NCheckboxGroup, + CheckboxGroup: (props, { attrs, slots }) => { + let defaultSlot; + if (Reflect.has(slots, 'default')) { + defaultSlot = slots.default; + } else { + const { options } = attrs; + if (Array.isArray(options)) { + defaultSlot = () => options.map((option) => h(NCheckbox, option)); + } + } + return h( + NCheckboxGroup, + { ...props, ...attrs }, + { default: defaultSlot }, + ); + }, DatePicker: NDatePicker, // 自定义默认按钮 DefaultButton: (props, { attrs, slots }) => { @@ -75,9 +127,37 @@ async function initComponentAdapter() { return h(NButton, { ...props, attrs, type: 'primary' }, slots); }, Divider: NDivider, + IconPicker: (props, { attrs, slots }) => { + return h( + IconPicker, + { iconSlot: 'suffix', inputComponent: NInput, ...props, ...attrs }, + slots, + ); + }, Input: withDefaultPlaceholder(NInput, 'input'), InputNumber: withDefaultPlaceholder(NInputNumber, 'input'), - RadioGroup: NRadioGroup, + RadioGroup: (props, { attrs, slots }) => { + let defaultSlot; + if (Reflect.has(slots, 'default')) { + defaultSlot = slots.default; + } else { + const { options } = attrs; + if (Array.isArray(options)) { + defaultSlot = () => + options.map((option) => + h(attrs.isButton ? NRadioButton : NRadio, option), + ); + } + } + const groupRender = h( + NRadioGroup, + { ...props, ...attrs }, + { default: defaultSlot }, + ); + return attrs.isButton + ? h(NSpace, { vertical: true }, () => groupRender) + : groupRender; + }, Select: withDefaultPlaceholder(NSelect, 'select'), Space: NSpace, Switch: NSwitch, diff --git a/apps/vben5/apps/web-naive/src/adapter/form.ts b/apps/vben5/apps/web-naive/src/adapter/form.ts index 2c3cee875..2f2ed2abe 100644 --- a/apps/vben5/apps/web-naive/src/adapter/form.ts +++ b/apps/vben5/apps/web-naive/src/adapter/form.ts @@ -10,8 +10,6 @@ import { $t } from '@vben/locales'; setupVbenForm({ config: { - // naive-ui组件不接受onChang事件,所以需要禁用 - disabledOnChangeListener: true, // naive-ui组件的空值为null,不能是undefined,否则重置表单时不生效 emptyStateValue: null, baseModelPropName: 'value', diff --git a/apps/vben5/apps/web-naive/src/api/request.ts b/apps/vben5/apps/web-naive/src/api/request.ts index 72056e198..f8fbacc0b 100644 --- a/apps/vben5/apps/web-naive/src/api/request.ts +++ b/apps/vben5/apps/web-naive/src/api/request.ts @@ -1,12 +1,13 @@ /** * 该文件可自行根据业务逻辑进行调整 */ -import type { HttpResponse } from '@vben/request'; +import type { RequestClientOptions } from '@vben/request'; import { useAppConfig } from '@vben/hooks'; import { preferences } from '@vben/preferences'; import { authenticateResponseInterceptor, + defaultResponseInterceptor, errorMessageResponseInterceptor, RequestClient, } from '@vben/request'; @@ -19,8 +20,9 @@ import { refreshTokenApi } from './core'; const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); -function createRequestClient(baseURL: string) { +function createRequestClient(baseURL: string, options?: RequestClientOptions) { const client = new RequestClient({ + ...options, baseURL, }); @@ -68,18 +70,14 @@ function createRequestClient(baseURL: string) { }, }); - // response数据解构 - client.addResponseInterceptor({ - fulfilled: (response) => { - const { data: responseData, status } = response; - - const { code, data } = responseData; - if (status >= 200 && status < 400 && code === 0) { - return data; - } - throw Object.assign({}, response, { response }); - }, - }); + // 处理返回的响应数据格式 + client.addResponseInterceptor( + defaultResponseInterceptor({ + codeField: 'code', + dataField: 'data', + successCode: 0, + }), + ); // token过期的处理 client.addResponseInterceptor( @@ -107,6 +105,8 @@ function createRequestClient(baseURL: string) { return client; } -export const requestClient = createRequestClient(apiURL); +export const requestClient = createRequestClient(apiURL, { + responseReturn: 'data', +}); export const baseRequestClient = new RequestClient({ baseURL: apiURL }); diff --git a/apps/vben5/apps/web-naive/src/bootstrap.ts b/apps/vben5/apps/web-naive/src/bootstrap.ts index fc7f961d6..a423bff4d 100644 --- a/apps/vben5/apps/web-naive/src/bootstrap.ts +++ b/apps/vben5/apps/web-naive/src/bootstrap.ts @@ -1,9 +1,11 @@ import { createApp, watchEffect } from 'vue'; import { registerAccessDirective } from '@vben/access'; +import { initTippy } from '@vben/common-ui'; import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; +import '@vben/styles/naive'; import { useTitle } from '@vueuse/core'; @@ -16,6 +18,16 @@ import { router } from './router'; async function bootstrap(namespace: string) { // 初始化组件适配器 initComponentAdapter(); + + // // 设置弹窗的默认配置 + // setDefaultModalProps({ + // fullscreenButton: false, + // }); + // // 设置抽屉的默认配置 + // setDefaultDrawerProps({ + // // zIndex: 2000, + // }); + const app = createApp(App); // 国际化 i18n 配置 @@ -27,6 +39,9 @@ async function bootstrap(namespace: string) { // 安装权限指令 registerAccessDirective(app); + // 初始化 tippy + initTippy(app); + // 配置路由及路由守卫 app.use(router); diff --git a/apps/vben5/apps/web-naive/src/locales/index.ts b/apps/vben5/apps/web-naive/src/locales/index.ts index 3d77913ad..58f63c10d 100644 --- a/apps/vben5/apps/web-naive/src/locales/index.ts +++ b/apps/vben5/apps/web-naive/src/locales/index.ts @@ -1,7 +1,7 @@ -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; - import type { App } from 'vue'; +import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; + import { $t, setupI18n as coreSetup, diff --git a/apps/vben5/apps/web-naive/src/locales/langs/en-US/demos.json b/apps/vben5/apps/web-naive/src/locales/langs/en-US/demos.json index 9fdffc765..839fc2e68 100644 --- a/apps/vben5/apps/web-naive/src/locales/langs/en-US/demos.json +++ b/apps/vben5/apps/web-naive/src/locales/langs/en-US/demos.json @@ -2,6 +2,7 @@ "title": "Demos", "naive": "Naive UI", "table": "Table", + "form": "Form", "vben": { "title": "Project", "about": "About", diff --git a/apps/vben5/apps/web-naive/src/locales/langs/zh-CN/demos.json b/apps/vben5/apps/web-naive/src/locales/langs/zh-CN/demos.json index 79b54fa21..e0d7e616d 100644 --- a/apps/vben5/apps/web-naive/src/locales/langs/zh-CN/demos.json +++ b/apps/vben5/apps/web-naive/src/locales/langs/zh-CN/demos.json @@ -2,6 +2,7 @@ "title": "演示", "naive": "Naive UI", "table": "Table", + "form": "表单", "vben": { "title": "项目", "about": "关于", diff --git a/apps/vben5/apps/web-naive/src/router/guard.ts b/apps/vben5/apps/web-naive/src/router/guard.ts index c95d994ec..281ea31a6 100644 --- a/apps/vben5/apps/web-naive/src/router/guard.ts +++ b/apps/vben5/apps/web-naive/src/router/guard.ts @@ -54,7 +54,9 @@ function setupAccessGuard(router: Router) { if (coreRouteNames.includes(to.name as string)) { if (to.path === LOGIN_PATH && accessStore.accessToken) { return decodeURIComponent( - (to.query?.redirect as string) || DEFAULT_HOME_PATH, + (to.query?.redirect as string) || + userStore.userInfo?.homePath || + DEFAULT_HOME_PATH, ); } return true; @@ -72,7 +74,10 @@ function setupAccessGuard(router: Router) { return { path: LOGIN_PATH, // 如不需要,直接删除 query - query: { redirect: encodeURIComponent(to.fullPath) }, + query: + to.fullPath === DEFAULT_HOME_PATH + ? {} + : { redirect: encodeURIComponent(to.fullPath) }, // 携带当前跳转的页面,登录后重新跳转该页面 replace: true, }; @@ -101,7 +106,10 @@ function setupAccessGuard(router: Router) { accessStore.setAccessMenus(accessibleMenus); accessStore.setAccessRoutes(accessibleRoutes); accessStore.setIsAccessChecked(true); - const redirectPath = (from.query.redirect ?? to.fullPath) as string; + const redirectPath = (from.query.redirect ?? + (to.path === DEFAULT_HOME_PATH + ? userInfo.homePath || DEFAULT_HOME_PATH + : to.fullPath)) as string; return { ...router.resolve(decodeURIComponent(redirectPath)), diff --git a/apps/vben5/apps/web-naive/src/router/routes/core.ts b/apps/vben5/apps/web-naive/src/router/routes/core.ts index fe030a9a2..7218da228 100644 --- a/apps/vben5/apps/web-naive/src/router/routes/core.ts +++ b/apps/vben5/apps/web-naive/src/router/routes/core.ts @@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router'; import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants'; -import { AuthPageLayout } from '#/layouts'; +import { AuthPageLayout, BasicLayout } from '#/layouts'; import { $t } from '#/locales'; import Login from '#/views/_core/authentication/login.vue'; @@ -21,13 +21,21 @@ const fallbackNotFoundRoute: RouteRecordRaw = { /** 基本路由,这些路由是必须存在的 */ const coreRoutes: RouteRecordRaw[] = [ + /** + * 根路由 + * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。 + * 此路由必须存在,且不应修改 + */ { + component: BasicLayout, meta: { + hideInBreadcrumb: true, title: 'Root', }, name: 'Root', path: '/', redirect: DEFAULT_HOME_PATH, + children: [], }, { component: AuthPageLayout, diff --git a/apps/vben5/apps/web-naive/src/router/routes/modules/dashboard.ts b/apps/vben5/apps/web-naive/src/router/routes/modules/dashboard.ts index 1bddab9db..5254dc65d 100644 --- a/apps/vben5/apps/web-naive/src/router/routes/modules/dashboard.ts +++ b/apps/vben5/apps/web-naive/src/router/routes/modules/dashboard.ts @@ -1,18 +1,16 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'lucide:layout-dashboard', order: -1, title: $t('page.dashboard.title'), }, name: 'Dashboard', - path: '/', + path: '/dashboard', children: [ { name: 'Analytics', diff --git a/apps/vben5/apps/web-naive/src/router/routes/modules/demos.ts b/apps/vben5/apps/web-naive/src/router/routes/modules/demos.ts index cf5658800..5e49ffa01 100644 --- a/apps/vben5/apps/web-naive/src/router/routes/modules/demos.ts +++ b/apps/vben5/apps/web-naive/src/router/routes/modules/demos.ts @@ -1,11 +1,9 @@ import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, @@ -31,6 +29,14 @@ const routes: RouteRecordRaw[] = [ path: '/demos/table', component: () => import('#/views/demos/table/index.vue'), }, + { + meta: { + title: $t('demos.form'), + }, + name: 'Form', + path: '/demos/form', + component: () => import('#/views/demos/form/basic.vue'), + }, ], }, ]; diff --git a/apps/vben5/apps/web-naive/src/router/routes/modules/vben.ts b/apps/vben5/apps/web-naive/src/router/routes/modules/vben.ts index 44461a7fd..169de855b 100644 --- a/apps/vben5/apps/web-naive/src/router/routes/modules/vben.ts +++ b/apps/vben5/apps/web-naive/src/router/routes/modules/vben.ts @@ -9,30 +9,20 @@ import { } from '@vben/constants'; import { SvgAntdvLogoIcon } from '@vben/icons'; -import { BasicLayout, IFrameView } from '#/layouts'; +import { IFrameView } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { badgeType: 'dot', icon: VBEN_LOGO_URL, - order: 9999, + order: 9998, title: $t('demos.vben.title'), }, name: 'VbenProject', path: '/vben-admin', children: [ - { - name: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - }, - }, { name: 'VbenDocument', path: '/vben-admin/document', @@ -77,6 +67,16 @@ const routes: RouteRecordRaw[] = [ }, ], }, + { + name: 'VbenAbout', + path: '/vben-admin/about', + component: () => import('#/views/_core/about/index.vue'), + meta: { + icon: 'lucide:copyright', + title: $t('demos.vben.about'), + order: 9999, + }, + }, ]; export default routes; diff --git a/apps/vben5/apps/web-naive/src/views/_core/authentication/code-login.vue b/apps/vben5/apps/web-naive/src/views/_core/authentication/code-login.vue index 556b273af..acfd1fd78 100644 --- a/apps/vben5/apps/web-naive/src/views/_core/authentication/code-login.vue +++ b/apps/vben5/apps/web-naive/src/views/_core/authentication/code-login.vue @@ -10,6 +10,7 @@ import { $t } from '@vben/locales'; defineOptions({ name: 'CodeLogin' }); const loading = ref(false); +const CODE_LENGTH = 6; const formSchema = computed((): VbenFormSchema[] => { return [ @@ -30,6 +31,7 @@ const formSchema = computed((): VbenFormSchema[] => { { component: 'VbenPinInput', componentProps: { + codeLength: CODE_LENGTH, createText: (countdown: number) => { const text = countdown > 0 @@ -41,7 +43,9 @@ const formSchema = computed((): VbenFormSchema[] => { }, fieldName: 'code', label: $t('authentication.code'), - rules: z.string().min(1, { message: $t('authentication.codeTip') }), + rules: z.string().length(CODE_LENGTH, { + message: $t('authentication.codeTip', [CODE_LENGTH]), + }), }, ]; }); diff --git a/apps/vben5/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue b/apps/vben5/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue index fadfc917c..f1f0b232a 100644 --- a/apps/vben5/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue +++ b/apps/vben5/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue @@ -1,11 +1,9 @@ + + + + + 设置表单值 + + + + + diff --git a/apps/vben5/apps/web-naive/src/views/demos/naive/index.vue b/apps/vben5/apps/web-naive/src/views/demos/naive/index.vue index 41d55109e..f72cdb20f 100644 --- a/apps/vben5/apps/web-naive/src/views/demos/naive/index.vue +++ b/apps/vben5/apps/web-naive/src/views/demos/naive/index.vue @@ -1,7 +1,8 @@ + + + +``` + +::: + +## API + +### Props + +| 属性名 | 描述 | 类型 | 默认值 | +| --- | --- | --- | --- | +| modelValue(v-model) | 当前值 | `any` | - | +| component | 欲包装的组件(以下称为目标组件) | `Component` | - | +| numberToString | 是否将value从数字转为string | `boolean` | `false` | +| api | 获取数据的函数 | `(arg?: any) => Promise>` | - | +| params | 传递给api的参数 | `Record` | - | +| resultField | 从api返回的结果中提取options数组的字段名 | `string` | - | +| labelField | label字段名 | `string` | `label` | +| childrenField | 子级数据字段名,需要层级数据的组件可用 | `string` | `` | +| valueField | value字段名 | `string` | `value` | +| optionsPropName | 目标组件接收options数据的属性名称 | `string` | `options` | +| modelPropName | 目标组件的双向绑定属性名,默认为modelValue。部分组件可能为value | `string` | `modelValue` | +| immediate | 是否立即调用api | `boolean` | `true` | +| alwaysLoad | 每次`visibleEvent`事件发生时都重新请求数据 | `boolean` | `false` | +| beforeFetch | 在api请求之前的回调函数 | `AnyPromiseFunction` | - | +| afterFetch | 在api请求之后的回调函数 | `AnyPromiseFunction` | - | +| options | 直接传入选项数据,也作为api返回空数据时的后备数据 | `OptionsItem[]` | - | +| visibleEvent | 触发重新请求数据的事件名 | `string` | - | +| loadingSlot | 目标组件的插槽名称,用来显示一个"加载中"的图标 | `string` | - | diff --git a/apps/vben5/docs/src/components/common-ui/vben-drawer.md b/apps/vben5/docs/src/components/common-ui/vben-drawer.md index 939593fa9..61b7c9e59 100644 --- a/apps/vben5/docs/src/components/common-ui/vben-drawer.md +++ b/apps/vben5/docs/src/components/common-ui/vben-drawer.md @@ -54,6 +54,8 @@ Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 dra - `VbenDrawer` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 +- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。 +- 如果抽屉的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultDrawerProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。 ::: @@ -74,12 +76,16 @@ const [Drawer, drawerApi] = useVbenDrawer({ | 属性名 | 描述 | 类型 | 默认值 | | --- | --- | --- | --- | +| appendToMain | 是否挂载到内容区域(默认挂载到body) | `boolean` | `false` | +| connectedComponent | 连接另一个Modal组件 | `Component` | - | +| destroyOnClose | 关闭时销毁`connectedComponent` | `boolean` | `false` | | title | 标题 | `string\|slot` | - | | titleTooltip | 标题提示信息 | `string\|slot` | - | | description | 描述信息 | `string\|slot` | - | | isOpen | 弹窗打开状态 | `boolean` | `false` | | loading | 弹窗加载状态 | `boolean` | `false` | | closable | 显示关闭按钮 | `boolean` | `true` | +| closeIconPlacement | 关闭按钮位置 | `'left'\|'right'` | `right` | | modal | 显示遮罩 | `boolean` | `true` | | header | 显示header | `boolean` | `true` | | footer | 显示footer | `boolean\|slot` | `true` | @@ -95,17 +101,27 @@ const [Drawer, drawerApi] = useVbenDrawer({ | contentClass | modal内容区域的class | `string` | - | | footerClass | modal底部区域的class | `string` | - | | headerClass | modal顶部区域的class | `string` | - | +| zIndex | 抽屉的ZIndex层级 | `number` | `1000` | +| overlayBlur | 遮罩模糊度 | `number` | - | + +::: info appendToMain + +`appendToMain`可以指定将抽屉挂载到内容区域,打开抽屉时,内容区域以外的部分(标签栏、导航菜单等等)不会被遮挡。默认情况下,抽屉会挂载到body上。但是:挂载到内容区域时,作为页面根容器的`Page`组件,需要设置`auto-content-height`属性,以便抽屉能够正确计算高度。 + +::: ### Event 以下事件,只有在 `useVbenDrawer({onCancel:()=>{}})` 中传入才会生效。 -| 事件名 | 描述 | 类型 | -| --- | --- | --- | -| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | -| onCancel | 点击取消按钮触发 | `()=>void` | -| onConfirm | 点击确认按钮触发 | `()=>void` | -| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | +| 事件名 | 描述 | 类型 | 版本限制 | +| --- | --- | --- | --- | +| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | --- | +| onCancel | 点击取消按钮触发 | `()=>void` | --- | +| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.5.2 | +| onConfirm | 点击确认按钮触发 | `()=>void` | --- | +| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | --- | +| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.5.2 | ### Slots @@ -116,14 +132,16 @@ const [Drawer, drawerApi] = useVbenDrawer({ | default | 默认插槽 - 弹窗内容 | | prepend-footer | 取消按钮左侧 | | append-footer | 取消按钮右侧 | +| close-icon | 关闭按钮图标 | +| extra | 额外内容(标题右侧) | -### modalApi +### drawerApi -| 事件名 | 描述 | 类型 | +| 方法 | 描述 | 类型 | | --- | --- | --- | -| setState | 动态设置弹窗状态属性 | `setState(props) \| setState((prev)=>(props))` | +| setState | 动态设置弹窗状态属性 | `(((prev: ModalState) => Partial)\| Partial)=>drawerApi` | | open | 打开弹窗 | `()=>void` | | close | 关闭弹窗 | `()=>void` | -| setData | 设置共享数据 | `(data:T)=>void` | +| setData | 设置共享数据 | `(data:T)=>drawerApi` | | getData | 获取共享数据 | `()=>T` | | useStore | 获取可响应式状态 | - | diff --git a/apps/vben5/docs/src/components/common-ui/vben-ellipsis-text.md b/apps/vben5/docs/src/components/common-ui/vben-ellipsis-text.md new file mode 100644 index 000000000..109f1161c --- /dev/null +++ b/apps/vben5/docs/src/components/common-ui/vben-ellipsis-text.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# Vben EllipsisText 省略文本 + +框架提供的文本展示组件,可配置超长省略、tooltip提示、展开收起等功能。 + +> 如果文档内没有参数说明,可以尝试在在线示例内寻找 + +## 基础用法 + +通过默认插槽设置文本内容,`maxWidth`属性设置最大宽度。 + + + +## 可折叠的文本块 + +通过`line`设置折叠后的行数,`expand`属性设置是否支持展开收起。 + + + +## 自定义提示浮层 + +通过名为`tooltip`的插槽定制提示信息。 + + + +## API + +### Props + +| 属性名 | 描述 | 类型 | 默认值 | +| --- | --- | --- | --- | +| expand | 支持点击展开或收起 | `boolean` | `false` | +| line | 文本最大行数 | `number` | `1` | +| maxWidth | 文本区域最大宽度 | `number \| string` | `'100%'` | +| placement | 提示浮层的位置 | `'bottom'\|'left'\|'right'\|'top'` | `'top'` | +| tooltip | 启用文本提示 | `boolean` | `true` | +| tooltipBackgroundColor | 提示文本的背景颜色 | `string` | - | +| tooltipColor | 提示文本的颜色 | `string` | - | +| tooltipFontSize | 提示文本的大小 | `string` | - | +| tooltipMaxWidth | 提示浮层的最大宽度。如不设置则保持与文本宽度一致 | `number` | - | +| tooltipOverlayStyle | 提示框内容区域样式 | `CSSProperties` | `{ textAlign: 'justify' }` | + +### Events + +| 事件名 | 描述 | 类型 | +| ------------ | ------------ | -------------------------- | +| expandChange | 展开状态改变 | `(isExpand:boolean)=>void` | + +### Slots + +| 插槽名 | 描述 | +| ------- | -------------------------------- | +| tooltip | 启用文本提示时,用来定制提示内容 | diff --git a/apps/vben5/docs/src/components/common-ui/vben-form.md b/apps/vben5/docs/src/components/common-ui/vben-form.md index 34e96adfd..ecaae6f8d 100644 --- a/apps/vben5/docs/src/components/common-ui/vben-form.md +++ b/apps/vben5/docs/src/components/common-ui/vben-form.md @@ -87,7 +87,7 @@ import type { BaseFormComponentType } from '@vben/common-ui'; import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState } from '@vben/common-ui'; +import { globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { @@ -149,6 +149,7 @@ export type ComponentType = | 'TimePicker' | 'TreeSelect' | 'Upload' + | 'IconPicker'; | BaseFormComponentType; async function initComponentAdapter() { @@ -166,6 +167,7 @@ async function initComponentAdapter() { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, + IconPicker, Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), @@ -285,6 +287,8 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单 | setValues | 设置表单值, 默认会过滤不在schema中定义的field, 可通过filterFields形参关闭过滤 | `(fields: Record, filterFields?: boolean, shouldValidate?: boolean) => Promise` | | getValues | 获取表单值 | `(fields:Record,shouldValidate: boolean = false)=>Promise` | | validate | 表单校验 | `()=>Promise` | +| validateField | 校验指定字段 | `(fieldName: string)=>Promise>` | +| isFieldValid | 检查某个字段是否已通过校验 | `(fieldName: string)=>Promise` | | resetValidate | 重置表单校验 | `()=>Promise` | | updateSchema | 更新formSchema | `(schema:FormSchema[])=>void` | | setFieldValue | 设置字段值 | `(field: string, value: any, shouldValidate?: boolean)=>Promise` | @@ -304,16 +308,25 @@ useVbenForm 返回的第二个参数,是一个对象,包含了一些表单 | actionWrapperClass | 表单操作区域class | `any` | - | | handleReset | 表单重置回调 | `(values: Record,) => Promise \| void` | - | | handleSubmit | 表单提交回调 | `(values: Record,) => Promise \| void` | - | +| handleValuesChange | 表单值变化回调 | `(values: Record,) => void` | - | +| actionButtonsReverse | 调换操作按钮位置 | `boolean` | `false` | | resetButtonOptions | 重置按钮组件参数 | `ActionButtonOptions` | - | | submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - | | showDefaultActions | 是否显示默认操作按钮 | `boolean` | `true` | -| collapsed | 是否折叠,在`是否展开,在showCollapseButton=true`时生效 | `boolean` | `false` | +| collapsed | 是否折叠,在`showCollapseButton`为`true`时生效 | `boolean` | `false` | | collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` | | collapsedRows | 折叠时保持的行数 | `number` | `1` | -| fieldMappingTime | 用于将表单内时间区域的应设成 2 个字段 | `[string, [string, string], string?][]` | - | +| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable\|[string,string]\|((any,string)=>any)?][]` | - | | commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - | -| schema | 表单项的每一项配置 | `FormSchema` | - | +| schema | 表单项的每一项配置 | `FormSchema[]` | - | | submitOnEnter | 按下回车健时提交表单 | `boolean` | false | +| submitOnChange | 字段值改变时提交表单(内部防抖,这个属性一般用于表格的搜索表单) | `boolean` | false | + +::: tip fieldMappingTime + +此属性用于将表单内的数组值映射成 2 个字段,它应当传入一个数组,数组的每一项是一个映射规则,规则的第一个成员是一个字符串,表示需要映射的字段名,第二个成员是一个数组,表示映射后的字段名,第三个成员是一个可选的格式掩码,用于格式化日期时间字段;也可以提供一个格式化函数(参数分别为当前值和当前字段名,返回格式化后的值)。如果明确地将格式掩码设为null,则原值映射而不进行格式化(适用于非日期时间字段)。例如:`[['timeRange', ['startTime', 'endTime'], 'YYYY-MM-DD']]`,`timeRange`应当是一个至少具有2个成员的数组类型的值。Form会将`timeRange`的值前两个值分别按照格式掩码`YYYY-MM-DD`格式化后映射到`startTime`和`endTime`字段上。每一项的第三个参数是一个可选的格式掩码, + +::: ### TS 类型说明 @@ -334,7 +347,7 @@ export interface ActionButtonOptions { /** 是否显示 */ show?: boolean; /** 按钮文本 */ - text?: string; + content?: string; /** 任意属性 */ [key: string]: any; } @@ -350,10 +363,21 @@ export interface FormCommonConfig { * 所有表单项的props */ componentProps?: ComponentProps; + /** + * 是否紧凑模式(移除表单底部为显示校验错误信息所预留的空间)。 + * 在有设置校验规则的场景下,建议不要将其设置为true + * 默认为false。但用作表格的搜索表单时,默认为true + * @default false + */ + compact?: boolean; /** * 所有表单项的控件样式 */ controlClass?: string; + /** + * 在表单项的Label后显示一个冒号 + */ + colon?: boolean; /** * 所有表单项的禁用状态 * @default false @@ -388,6 +412,11 @@ export interface FormCommonConfig { * 所有表单项的label宽度 */ labelWidth?: number; + /** + * 所有表单项的model属性名。使用自定义组件时可通过此配置指定组件的model属性名。已经在modelPropNameMap中注册的组件不受此配置影响 + * @default "modelValue" + */ + modelPropName?: string; /** * 所有表单项的wrapper样式 */ @@ -413,7 +442,7 @@ export interface FormSchema< dependencies?: FormItemDependencies; /** 描述 */ description?: string; - /** 字段名 */ + /** 字段名,也作为自定义插槽的名称 */ fieldName: string; /** 帮助信息 */ help?: string; @@ -436,7 +465,7 @@ export interface FormSchema< ```ts dependencies: { - // 只有当 name 字段的值变化时,才会触发联动 + // 触发字段。只有这些字段值变动时,联动才会触发 triggerFields: ['name'], // 动态判断当前字段是否需要显示,不显示则直接销毁 if(values,formApi){}, @@ -457,11 +486,11 @@ dependencies: { ### 表单校验 -表单联动需要通过 schema 内的 `rules` 属性进行配置。 +表单校验需要通过 schema 内的 `rules` 属性进行配置。 -rules的值可以是一个字符串,也可以是一个zod的schema。 +rules的值可以是字符串(预定义的校验规则名称),也可以是一个zod的schema。 -#### 字符串 +#### 预定义的校验规则 ```ts // 表示字段必填,默认会根据适配器的required进行国际化 @@ -487,11 +516,16 @@ import { z } from '#/adapter/form'; rules: z.string().min(1, { message: '请输入字符串' }); } -// 可选,并且携带默认值 +// 可选(可以是undefined),并且携带默认值。注意zod的optional不包括空字符串'' { rules: z.string().default('默认值').optional(), } +// 可以是空字符串、undefined或者一个邮箱地址 +{ + rules: z.union(z.string().email().optional(), z.literal("")) +} + // 复杂校验 { z.string().min(1, { message: "请输入" }) diff --git a/apps/vben5/docs/src/components/common-ui/vben-modal.md b/apps/vben5/docs/src/components/common-ui/vben-modal.md index 75f620ae5..e49196eed 100644 --- a/apps/vben5/docs/src/components/common-ui/vben-modal.md +++ b/apps/vben5/docs/src/components/common-ui/vben-modal.md @@ -60,6 +60,8 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda - `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 +- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。 +- 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。 ::: @@ -80,6 +82,9 @@ const [Modal, modalApi] = useVbenModal({ | 属性名 | 描述 | 类型 | 默认值 | | --- | --- | --- | --- | +| appendToMain | 是否挂载到内容区域(默认挂载到body) | `boolean` | `false` | +| connectedComponent | 连接另一个Modal组件 | `Component` | - | +| destroyOnClose | 关闭时销毁`connectedComponent` | `boolean` | `false` | | title | 标题 | `string\|slot` | - | | titleTooltip | 标题提示信息 | `string\|slot` | - | | description | 描述信息 | `string\|slot` | - | @@ -106,6 +111,15 @@ const [Modal, modalApi] = useVbenModal({ | footerClass | modal底部区域的class | `string` | - | | headerClass | modal顶部区域的class | `string` | - | | bordered | 是否显示border | `boolean` | `false` | +| zIndex | 弹窗的ZIndex层级 | `number` | `1000` | +| overlayBlur | 遮罩模糊度 | `number` | - | +| submitting | 标记为提交中,锁定弹窗当前状态 | `boolean` | `false` | + +::: info appendToMain + +`appendToMain`可以指定将弹窗挂载到内容区域,打开这种弹窗时,内容区域以外的部分(标签栏、导航菜单等等)不会被遮挡。默认情况下,弹窗会挂载到body上。但是:挂载到内容区域时,作为页面根容器的`Page`组件,需要设置`auto-content-height`属性,以便弹窗能够正确计算高度。 + +::: ### Event @@ -113,7 +127,7 @@ const [Modal, modalApi] = useVbenModal({ | 事件名 | 描述 | 类型 | 版本号 | | --- | --- | --- | --- | -| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | | +| onBeforeClose | 关闭前触发,返回 `false`或者被`reject`则禁止关闭 | `()=>Promise\|boolean` | >5.5.2支持Promise | | onCancel | 点击取消按钮触发 | `()=>void` | | | onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 | | onConfirm | 点击确认按钮触发 | `()=>void` | | @@ -132,11 +146,18 @@ const [Modal, modalApi] = useVbenModal({ ### modalApi -| 事件名 | 描述 | 类型 | -| --- | --- | --- | -| setState | 动态设置弹窗状态属性 | `setState(props) \| setState((prev)=>(props))` | -| open | 打开弹窗 | `()=>void` | -| close | 关闭弹窗 | `()=>void` | -| setData | 设置共享数据 | `(data:T)=>void` | -| getData | 获取共享数据 | `()=>T` | -| useStore | 获取可响应式状态 | - | +| 方法 | 描述 | 类型 | 版本 | +| --- | --- | --- | --- | +| setState | 动态设置弹窗状态属性 | `(((prev: ModalState) => Partial)\| Partial)=>modalApi` | - | +| open | 打开弹窗 | `()=>void` | - | +| close | 关闭弹窗 | `()=>void` | - | +| setData | 设置共享数据 | `(data:T)=>modalApi` | - | +| getData | 获取共享数据 | `()=>T` | - | +| useStore | 获取可响应式状态 | - | - | +| lock | 将弹窗标记为提交中,锁定当前状态 | `(isLock:boolean)=>modalApi` | >5.5.2 | + +::: info lock + +`lock`方法用于锁定当前弹窗的状态,一般用于提交数据的过程中防止用户重复提交或者弹窗被意外关闭、表单数据被改变等等。当处于锁定状态时,弹窗的确认按钮会变为loading状态,同时禁用确认按钮、隐藏关闭按钮、禁止ESC或者点击遮罩等方式关闭弹窗、开启弹窗的spinner动画以遮挡弹窗内容。调用`close`方法关闭处于锁定状态的弹窗时,会自动解锁。 + +::: diff --git a/apps/vben5/docs/src/components/common-ui/vben-vxe-table.md b/apps/vben5/docs/src/components/common-ui/vben-vxe-table.md index 29f679f6a..24d911da7 100644 --- a/apps/vben5/docs/src/components/common-ui/vben-vxe-table.md +++ b/apps/vben5/docs/src/components/common-ui/vben-vxe-table.md @@ -165,6 +165,8 @@ vxeUI.renderer.add('CellLink', { **表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。 +当启用了表单搜索时,可以在toolbarConfig中配置`search`为`true`来让表格在工具栏区域显示一个搜索表单控制按钮。 + ## 单元格编辑 @@ -215,14 +217,15 @@ const [Grid, gridApi] = useVbenVxeGrid({ useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。 -| 方法名 | 描述 | 类型 | -| --- | --- | --- | -| setLoading | 设置loading状态 | `(loading)=>void` | -| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partialvoid` | -| reload | 重载表格,会进行初始化 | `(params:any)=>void` | -| query | 重载表格,会保留当前分页 | `(params:any)=>void` | -| grid | vxe-table grid实例 | `VxeGridInstance` | -| formApi | vbenForm api实例 | `FormApi` | +| 方法名 | 描述 | 类型 | 说明 | +| --- | --- | --- | --- | +| setLoading | 设置loading状态 | `(loading)=>void` | - | +| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partialvoid` | - | +| reload | 重载表格,会进行初始化 | `(params:any)=>void` | - | +| query | 重载表格,会保留当前分页 | `(params:any)=>void` | - | +| grid | vxe-table grid实例 | `VxeGridInstance` | - | +| formApi | vbenForm api实例 | `FormApi` | - | +| toggleSearchForm | 设置搜索表单显示状态 | `(show?: boolean)=>boolean` | 当省略参数时,则将表单在显示和隐藏两种状态之间切换 | ## Props @@ -236,3 +239,4 @@ useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表 | gridOptions | grid组件的参数 | `VxeTableGridProps` | | gridEvents | grid组件的触发的⌚️ | `VxeGridListeners` | | formOptions | 表单参数 | `VbenFormProps` | +| showSearchForm | 是否显示搜索表单 | `boolean` | diff --git a/apps/vben5/docs/src/components/introduction.md b/apps/vben5/docs/src/components/introduction.md index 039ec8cd8..438470e9a 100644 --- a/apps/vben5/docs/src/components/introduction.md +++ b/apps/vben5/docs/src/components/introduction.md @@ -6,6 +6,10 @@ ::: +## 布局组件 + +布局组件一般在页面内容区域用作顶层容器组件,提供一些统一的布局样式和基本功能。 + ## 通用组件 通用组件是一些常用的组件,比如弹窗、抽屉、表单等。大部分基于 `Tailwind CSS` 实现,可适用于不同 UI 组件库的应用。 diff --git a/apps/vben5/docs/src/components/layout-ui/page.md b/apps/vben5/docs/src/components/layout-ui/page.md new file mode 100644 index 000000000..29fbdd40f --- /dev/null +++ b/apps/vben5/docs/src/components/layout-ui/page.md @@ -0,0 +1,44 @@ +--- +outline: deep +--- + +# Page 常规页面组件 + +提供一个常规页面布局的组件,包括头部、内容区域、底部三个部分。 + +::: info 写在前面 + +本组件是一个基本布局组件。如果有更多的通用页面布局需求(比如双列布局等),可以根据实际需求自行封装。 + +::: + +## 基础用法 + +将`Page`作为你的业务页面的根组件即可。 + +### Props + +| 属性名 | 描述 | 类型 | 默认值 | 说明 | +| --- | --- | --- | --- | --- | +| title | 页面标题 | `string\|slot` | - | - | +| description | 页面描述(标题下的内容) | `string\|slot` | - | - | +| contentClass | 内容区域的class | `string` | - | - | +| headerClass | 头部区域的class | `string` | - | - | +| footerClass | 底部区域的class | `string` | - | - | +| autoContentHeight | 自动调整内容区域的高度 | `boolean` | `false` | - | + +::: tip 注意 + +如果`title`、`description`、`extra`三者均未提供有效内容(通过`props`或者`slots`均可),则页面头部区域不会渲染。 + +::: + +### Slots + +| 插槽名称 | 描述 | +| ----------- | ------------ | +| default | 页面内容 | +| title | 页面标题 | +| description | 页面描述 | +| extra | 页面头部右侧 | +| footer | 页面底部 | diff --git a/apps/vben5/docs/src/demos/vben-api-component/cascader/index.vue b/apps/vben5/docs/src/demos/vben-api-component/cascader/index.vue new file mode 100644 index 000000000..957964cd3 --- /dev/null +++ b/apps/vben5/docs/src/demos/vben-api-component/cascader/index.vue @@ -0,0 +1,100 @@ + + + + diff --git a/apps/vben5/docs/src/demos/vben-drawer/dynamic/index.vue b/apps/vben5/docs/src/demos/vben-drawer/dynamic/index.vue index ad7e6565d..95464023a 100644 --- a/apps/vben5/docs/src/demos/vben-drawer/dynamic/index.vue +++ b/apps/vben5/docs/src/demos/vben-drawer/dynamic/index.vue @@ -13,8 +13,7 @@ function open() { } function handleUpdateTitle() { - drawerApi.setState({ title: '外部动态标题' }); - drawerApi.open(); + drawerApi.setState({ title: '外部动态标题' }).open(); } diff --git a/apps/vben5/docs/src/demos/vben-drawer/shared-data/index.vue b/apps/vben5/docs/src/demos/vben-drawer/shared-data/index.vue index 04885f157..fef6cb058 100644 --- a/apps/vben5/docs/src/demos/vben-drawer/shared-data/index.vue +++ b/apps/vben5/docs/src/demos/vben-drawer/shared-data/index.vue @@ -9,11 +9,12 @@ const [Drawer, drawerApi] = useVbenDrawer({ }); function open() { - drawerApi.setData({ - content: '外部传递的数据 content', - payload: '外部传递的数据 payload', - }); - drawerApi.open(); + drawerApi + .setData({ + content: '外部传递的数据 content', + payload: '外部传递的数据 payload', + }) + .open(); } diff --git a/apps/vben5/docs/src/demos/vben-ellipsis-text/expand/index.vue b/apps/vben5/docs/src/demos/vben-ellipsis-text/expand/index.vue new file mode 100644 index 000000000..842f6b32e --- /dev/null +++ b/apps/vben5/docs/src/demos/vben-ellipsis-text/expand/index.vue @@ -0,0 +1,10 @@ + + + {{ text }} + diff --git a/apps/vben5/docs/src/demos/vben-ellipsis-text/line/index.vue b/apps/vben5/docs/src/demos/vben-ellipsis-text/line/index.vue new file mode 100644 index 000000000..dfbf20eff --- /dev/null +++ b/apps/vben5/docs/src/demos/vben-ellipsis-text/line/index.vue @@ -0,0 +1,10 @@ + + + {{ text }} + diff --git a/apps/vben5/docs/src/demos/vben-ellipsis-text/tooltip/index.vue b/apps/vben5/docs/src/demos/vben-ellipsis-text/tooltip/index.vue new file mode 100644 index 000000000..e6287a12f --- /dev/null +++ b/apps/vben5/docs/src/demos/vben-ellipsis-text/tooltip/index.vue @@ -0,0 +1,14 @@ + + + + 住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪 + + + 《秦皇岛》住在我心里孤独的孤独的海怪 痛苦之王开始厌倦 + 深海的光 停滞的海浪 + + + + diff --git a/apps/vben5/docs/src/demos/vben-modal/dynamic/index.vue b/apps/vben5/docs/src/demos/vben-modal/dynamic/index.vue index 718e532bc..1b0255459 100644 --- a/apps/vben5/docs/src/demos/vben-modal/dynamic/index.vue +++ b/apps/vben5/docs/src/demos/vben-modal/dynamic/index.vue @@ -13,8 +13,7 @@ function openModal() { } function handleUpdateTitle() { - modalApi.setState({ title: '外部动态标题' }); - modalApi.open(); + modalApi.setState({ title: '外部动态标题' }).open(); } diff --git a/apps/vben5/docs/src/demos/vben-modal/shared-data/index.vue b/apps/vben5/docs/src/demos/vben-modal/shared-data/index.vue index 58c35e24d..91afeb70d 100644 --- a/apps/vben5/docs/src/demos/vben-modal/shared-data/index.vue +++ b/apps/vben5/docs/src/demos/vben-modal/shared-data/index.vue @@ -9,11 +9,12 @@ const [Modal, modalApi] = useVbenModal({ }); function openModal() { - modalApi.setData({ - content: '外部传递的数据 content', - payload: '外部传递的数据 payload', - }); - modalApi.open(); + modalApi + .setData({ + content: '外部传递的数据 content', + payload: '外部传递的数据 payload', + }) + .open(); } diff --git a/apps/vben5/docs/src/demos/vben-vxe-table/form/index.vue b/apps/vben5/docs/src/demos/vben-vxe-table/form/index.vue index a5e8a547b..bcf3f5a5d 100644 --- a/apps/vben5/docs/src/demos/vben-vxe-table/form/index.vue +++ b/apps/vben5/docs/src/demos/vben-vxe-table/form/index.vue @@ -76,6 +76,8 @@ const formOptions: VbenFormProps = { submitButtonOptions: { content: '查询', }, + // 是否在字段值改变时提交表单 + submitOnChange: false, // 按下回车时是否提交表单 submitOnEnter: false, }; @@ -108,6 +110,11 @@ const gridOptions: VxeGridProps = { }, }, }, + toolbarConfig: { + // 是否显示搜索表单控制按钮 + // @ts-ignore 正式环境时有完整的类型声明 + search: true, + }, }; const [Grid] = useVbenVxeGrid({ formOptions, gridOptions }); diff --git a/apps/vben5/docs/src/en/guide/essentials/route.md b/apps/vben5/docs/src/en/guide/essentials/route.md index bef40d691..8fb0a6d1c 100644 --- a/apps/vben5/docs/src/en/guide/essentials/route.md +++ b/apps/vben5/docs/src/en/guide/essentials/route.md @@ -73,7 +73,6 @@ import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { badgeType: 'dot', badgeVariants: 'destructive', @@ -124,7 +123,6 @@ import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, @@ -249,7 +247,6 @@ import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'mdi:home', title: $t('page.home.title'), diff --git a/apps/vben5/docs/src/en/guide/essentials/settings.md b/apps/vben5/docs/src/en/guide/essentials/settings.md index 68fef3e7e..a3cd579ec 100644 --- a/apps/vben5/docs/src/en/guide/essentials/settings.md +++ b/apps/vben5/docs/src/en/guide/essentials/settings.md @@ -217,6 +217,7 @@ const defaultPreferences: Preferences = { globalSearch: true, }, sidebar: { + autoActivateChild: false, collapsed: false, collapsedShowTitle: false, enable: true, diff --git a/apps/vben5/docs/src/guide/essentials/route.md b/apps/vben5/docs/src/guide/essentials/route.md index 0eb74aea4..d8a938dda 100644 --- a/apps/vben5/docs/src/guide/essentials/route.md +++ b/apps/vben5/docs/src/guide/essentials/route.md @@ -62,12 +62,10 @@ import type { RouteRecordRaw } from 'vue-router'; import { VBEN_LOGO_URL } from '@vben/constants'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { badgeType: 'dot', badgeVariants: 'destructive', @@ -103,7 +101,6 @@ export default routes; ::: tip -- 多级路由的父级路由无需设置 `component` 属性,只需设置 `children` 属性即可。除非你真的需要在父级路由嵌套下显示内容。 - 如果没有特殊情况,父级路由的 `redirect` 属性,不需要指定,默认会指向第一个子路由。 ::: @@ -113,12 +110,10 @@ export default routes; ```ts import type { RouteRecordRaw } from 'vue-router'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'ic:baseline-view-in-ar', keepAlive: true, @@ -238,12 +233,10 @@ import type { RouteRecordRaw } from 'vue-router'; import { VBEN_LOGO_URL } from '@vben/constants'; -import { BasicLayout } from '#/layouts'; import { $t } from '#/locales'; const routes: RouteRecordRaw[] = [ { - component: BasicLayout, meta: { icon: 'mdi:home', title: $t('page.home.title'), @@ -400,6 +393,10 @@ interface RouteMeta { * 菜单可以看到,但是访问会被重定向到403 */ menuVisibleWithForbidden?: boolean; + /** + * 当前路由不使用基础布局(仅在顶级生效) + */ + noBasicLayout?: boolean; /** * 在新窗口打开 */ @@ -584,6 +581,13 @@ _注意:_ 排序仅针对一级菜单有效,二级菜单的排序需要在对 用于配置页面的菜单参数,会在菜单中传递给页面。 +### noBasicLayout + +- 类型:`boolean` +- 默认值:`false` + +用于配置当前路由不使用基础布局,仅在顶级时生效。默认情况下,所有的路由都会被包裹在基础布局中(包含顶部以及侧边等导航部件),如果你的页面不需要这些部件,可以设置 `noBasicLayout` 为 `true`。 + ## 路由刷新 路由刷新方式如下: diff --git a/apps/vben5/docs/src/guide/essentials/server.md b/apps/vben5/docs/src/guide/essentials/server.md index 74a45d2ee..fedfbae25 100644 --- a/apps/vben5/docs/src/guide/essentials/server.md +++ b/apps/vben5/docs/src/guide/essentials/server.md @@ -231,19 +231,17 @@ function createRequestClient(baseURL: string) { }, }); - // response数据解构 - client.addResponseInterceptor({ - fulfilled: (response) => { - const { data: responseData, status } = response; - - const { code, data } = responseData; - - if (status >= 200 && status < 400 && code === 0) { - return data; - } - throw Object.assign({}, response, { response }); - }, - }); + // 处理返回的响应数据格式。会根据responseReturn指定的类型返回对应的数据 + client.addResponseInterceptor( + defaultResponseInterceptor({ + // 指定接口返回的数据中的 code 字段名 + codeField: 'code', + // 指定接口返回的数据中装载了主要数据的字段名 + dataField: 'data', + // 请求成功的 code 值,如果接口返回的 code 等于 successCode 则会认为是成功的请求 + successCode: 0, + }), + ); // token过期的处理 client.addResponseInterceptor( diff --git a/apps/vben5/docs/src/guide/essentials/settings.md b/apps/vben5/docs/src/guide/essentials/settings.md index e33572066..3669a771c 100644 --- a/apps/vben5/docs/src/guide/essentials/settings.md +++ b/apps/vben5/docs/src/guide/essentials/settings.md @@ -240,6 +240,7 @@ const defaultPreferences: Preferences = { globalSearch: true, }, sidebar: { + autoActivateChild: false, collapsed: false, collapsedShowTitle: false, enable: true, diff --git a/apps/vben5/docs/src/guide/in-depth/access.md b/apps/vben5/docs/src/guide/in-depth/access.md index c0c4bc991..be7d2ba0a 100644 --- a/apps/vben5/docs/src/guide/in-depth/access.md +++ b/apps/vben5/docs/src/guide/in-depth/access.md @@ -296,7 +296,7 @@ const { hasAccessByRoles } = useAccess(); #### 指令方式 -> 指令支持绑定单个或多个权限码。单个时可以直接传入字符串或数组中包含一个权限码,多个权限码则传入数组。 +> 指令支持绑定单个或多个角色。单个时可以直接传入字符串或数组中包含一个角色,多个角色均可访问则传入数组。 ```vue diff --git a/apps/vben5/docs/src/guide/in-depth/ui-framework.md b/apps/vben5/docs/src/guide/in-depth/ui-framework.md index ce05608fc..6a7508e1d 100644 --- a/apps/vben5/docs/src/guide/in-depth/ui-framework.md +++ b/apps/vben5/docs/src/guide/in-depth/ui-framework.md @@ -4,7 +4,7 @@ ## 新增组件库应用 -如果你想用其他别的组件库,你只需要按一下步骤进行操作: +如果你想用其他别的组件库,你只需要按以下步骤进行操作: 1. 在`apps`内创建一个新的文件夹,例如`apps/web-xxx`。 2. 更改`apps/web-xxx/package.json`的`name`字段为`web-xxx`。 diff --git a/apps/vben5/docs/src/guide/introduction/quick-start.md b/apps/vben5/docs/src/guide/introduction/quick-start.md index 747c52483..79410895f 100644 --- a/apps/vben5/docs/src/guide/introduction/quick-start.md +++ b/apps/vben5/docs/src/guide/introduction/quick-start.md @@ -67,7 +67,7 @@ pnpm install ::: tip 注意 - 项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。: -- 如果你的网络环境无法访问npm源,你可以设置系统的环境变量`COREPACK_REGISTRY=https://registry.npmmirror.com`,然后再执行`pnpm install`。 +- 如果你的网络环境无法访问npm源,你可以设置系统的环境变量`COREPACK_NPM_REGISTRY=https://registry.npmmirror.com`,然后再执行`pnpm install`。 - 如果你不想使用`corepack`,你需要禁用`corepack`,然后使用你自己的`pnpm`进行安装。 ::: diff --git a/apps/vben5/internal/lint-configs/commitlint-config/package.json b/apps/vben5/internal/lint-configs/commitlint-config/package.json index 6679a6627..a1645bb77 100644 --- a/apps/vben5/internal/lint-configs/commitlint-config/package.json +++ b/apps/vben5/internal/lint-configs/commitlint-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/commitlint-config", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/lint-configs/eslint-config/src/configs/import.ts b/apps/vben5/internal/lint-configs/eslint-config/src/configs/import.ts index 67a08feaf..ce6cf65d9 100644 --- a/apps/vben5/internal/lint-configs/eslint-config/src/configs/import.ts +++ b/apps/vben5/internal/lint-configs/eslint-config/src/configs/import.ts @@ -10,6 +10,7 @@ export async function importPluginConfig(): Promise { import: pluginImport, }, rules: { + 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], 'import/first': 'error', 'import/newline-after-import': 'error', 'import/no-duplicates': 'error', diff --git a/apps/vben5/internal/lint-configs/eslint-config/src/configs/javascript.ts b/apps/vben5/internal/lint-configs/eslint-config/src/configs/javascript.ts index 0d87c1ba1..f6b767fec 100644 --- a/apps/vben5/internal/lint-configs/eslint-config/src/configs/javascript.ts +++ b/apps/vben5/internal/lint-configs/eslint-config/src/configs/javascript.ts @@ -1,6 +1,5 @@ import type { Linter } from 'eslint'; -// @ts-expect-error - no types import js from '@eslint/js'; import pluginUnusedImports from 'eslint-plugin-unused-imports'; import globals from 'globals'; diff --git a/apps/vben5/internal/lint-configs/eslint-config/src/configs/perfectionist.ts b/apps/vben5/internal/lint-configs/eslint-config/src/configs/perfectionist.ts index 1b17b30f3..d4fd0bb8c 100644 --- a/apps/vben5/internal/lint-configs/eslint-config/src/configs/perfectionist.ts +++ b/apps/vben5/internal/lint-configs/eslint-config/src/configs/perfectionist.ts @@ -1,8 +1,13 @@ import type { Linter } from 'eslint'; -import perfectionistPlugin from 'eslint-plugin-perfectionist'; +import { interopDefault } from '../util'; export async function perfectionist(): Promise { + const perfectionistPlugin = await interopDefault( + // @ts-expect-error - no types + import('eslint-plugin-perfectionist'), + ); + return [ perfectionistPlugin.configs['recommended-natural'], { @@ -19,21 +24,28 @@ export async function perfectionist(): Promise { { customGroups: { type: { - vben: 'vben', - vue: 'vue', + 'vben-core-type': ['^@vben-core/.+'], + 'vben-type': ['^@vben/.+'], + 'vue-type': ['^vue$', '^vue-.+', '^@vue/.+'], }, value: { - vben: ['@vben*', '@vben/**/**', '@vben-core/**/**'], - vue: ['vue', 'vue-*', '@vue*'], + vben: ['^@vben/.+'], + 'vben-core': ['^@vben-core/.+'], + vue: ['^vue$', '^vue-.+', '^@vue/.+'], }, }, + environment: 'node', groups: [ ['external-type', 'builtin-type', 'type'], + 'vue-type', + 'vben-type', + 'vben-core-type', ['parent-type', 'sibling-type', 'index-type'], ['internal-type'], 'builtin', 'vue', 'vben', + 'vben-core', 'external', 'internal', ['parent', 'sibling', 'index'], @@ -43,12 +55,13 @@ export async function perfectionist(): Promise { 'object', 'unknown', ], - internalPattern: ['#*', '#*/**'], + internalPattern: ['^#/.+'], newlinesBetween: 'always', order: 'asc', type: 'natural', }, ], + 'perfectionist/sort-modules': 'off', 'perfectionist/sort-named-exports': [ 'error', { @@ -67,42 +80,6 @@ export async function perfectionist(): Promise { groups: ['unknown', 'items', 'list', 'children'], ignorePattern: ['children'], order: 'asc', - partitionByComment: 'Part:**', - type: 'natural', - }, - ], - 'perfectionist/sort-vue-attributes': [ - 'error', - { - // Based on: https://vuejs.org/style-guide/rules-recommended.html#element-attribute-order - customGroups: { - /* eslint-disable perfectionist/sort-objects */ - DEFINITION: '*(is|:is|v-is)', - LIST_RENDERING: 'v-for', - CONDITIONALS: 'v-*(else-if|if|else|show|cloak)', - RENDER_MODIFIERS: 'v-*(pre|once)', - GLOBAL: '*(:id|id)', - UNIQUE: '*(ref|key|:ref|:key)', - SLOT: '*(v-slot|slot)', - TWO_WAY_BINDING: '*(v-model|v-model:*)', - // OTHER_DIRECTIVES e.g. 'v-custom-directive' - EVENTS: '*(v-on|@*)', - CONTENT: 'v-*(html|text)', - /* eslint-enable perfectionist/sort-objects */ - }, - groups: [ - 'DEFINITION', - 'LIST_RENDERING', - 'CONDITIONALS', - 'RENDER_MODIFIERS', - 'GLOBAL', - 'UNIQUE', - 'SLOT', - 'TWO_WAY_BINDING', - 'unknown', - 'EVENTS', - 'CONTENT', - ], type: 'natural', }, ], diff --git a/apps/vben5/internal/lint-configs/eslint-config/src/configs/vue.ts b/apps/vben5/internal/lint-configs/eslint-config/src/configs/vue.ts index 27cc3cf29..d1c6521cf 100644 --- a/apps/vben5/internal/lint-configs/eslint-config/src/configs/vue.ts +++ b/apps/vben5/internal/lint-configs/eslint-config/src/configs/vue.ts @@ -4,7 +4,6 @@ import { interopDefault } from '../util'; export async function vue(): Promise { const [pluginVue, parserVue, parserTs] = await Promise.all([ - // @ts-expect-error missing types interopDefault(import('eslint-plugin-vue')), interopDefault(import('vue-eslint-parser')), // @ts-expect-error missing types diff --git a/apps/vben5/internal/lint-configs/stylelint-config/package.json b/apps/vben5/internal/lint-configs/stylelint-config/package.json index c9e8cf539..da7f4e8d1 100644 --- a/apps/vben5/internal/lint-configs/stylelint-config/package.json +++ b/apps/vben5/internal/lint-configs/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/stylelint-config", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/node-utils/package.json b/apps/vben5/internal/node-utils/package.json index 0cd1eaa3d..2ad95772b 100644 --- a/apps/vben5/internal/node-utils/package.json +++ b/apps/vben5/internal/node-utils/package.json @@ -1,6 +1,6 @@ { "name": "@vben/node-utils", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/node-utils/src/index.ts b/apps/vben5/internal/node-utils/src/index.ts index 2e39ccff6..963cb8756 100644 --- a/apps/vben5/internal/node-utils/src/index.ts +++ b/apps/vben5/internal/node-utils/src/index.ts @@ -2,7 +2,7 @@ export * from './constants'; export * from './date'; export * from './fs'; export * from './git'; -export { add as gitAdd, getStagedFiles } from './git'; +export { getStagedFiles, add as gitAdd } from './git'; export { generatorContentHash } from './hash'; export * from './monorepo'; export { toPosixPath } from './path'; diff --git a/apps/vben5/internal/node-utils/src/spinner.ts b/apps/vben5/internal/node-utils/src/spinner.ts index f07cc2567..13ad6a426 100644 --- a/apps/vben5/internal/node-utils/src/spinner.ts +++ b/apps/vben5/internal/node-utils/src/spinner.ts @@ -1,4 +1,6 @@ -import ora, { type Ora } from 'ora'; +import type { Ora } from 'ora'; + +import ora from 'ora'; interface SpinnerOptions { failedText?: string; diff --git a/apps/vben5/internal/tailwind-config/package.json b/apps/vben5/internal/tailwind-config/package.json index 004ae0bc1..9737ab338 100644 --- a/apps/vben5/internal/tailwind-config/package.json +++ b/apps/vben5/internal/tailwind-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/tailwind-config", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/tailwind-config/src/index.ts b/apps/vben5/internal/tailwind-config/src/index.ts index dafaaf91e..93332a3f4 100644 --- a/apps/vben5/internal/tailwind-config/src/index.ts +++ b/apps/vben5/internal/tailwind-config/src/index.ts @@ -130,7 +130,6 @@ export default { enterAnimationPlugin, ], prefix: '', - safelist: ['dark'], theme: { container: { center: true, @@ -202,6 +201,7 @@ export default { }, }, }, + safelist: ['dark'], } as Config; function createColorsPalette(name: string) { diff --git a/apps/vben5/internal/tsconfig/package.json b/apps/vben5/internal/tsconfig/package.json index d6bae6239..efeef619c 100644 --- a/apps/vben5/internal/tsconfig/package.json +++ b/apps/vben5/internal/tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@vben/tsconfig", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/vite-config/package.json b/apps/vben5/internal/vite-config/package.json index 2d68b95b7..708d519cd 100644 --- a/apps/vben5/internal/vite-config/package.json +++ b/apps/vben5/internal/vite-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/vite-config", - "version": "5.4.8", + "version": "5.5.3", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/apps/vben5/internal/vite-config/src/config/application.ts b/apps/vben5/internal/vite-config/src/config/application.ts index f22760944..f9808cc74 100644 --- a/apps/vben5/internal/vite-config/src/config/application.ts +++ b/apps/vben5/internal/vite-config/src/config/application.ts @@ -1,4 +1,4 @@ -import type { UserConfig } from 'vite'; +import type { CSSOptions, UserConfig } from 'vite'; import type { DefineApplicationOptions } from '../typing'; @@ -100,7 +100,7 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) { }); } -function createCssOptions(injectGlobalScss = true) { +function createCssOptions(injectGlobalScss = true): CSSOptions { const root = findMonorepoRoot(); return { preprocessorOptions: injectGlobalScss diff --git a/apps/vben5/internal/vite-config/src/plugins/importmap.ts b/apps/vben5/internal/vite-config/src/plugins/importmap.ts index c6154c9ea..0ccda99f8 100644 --- a/apps/vben5/internal/vite-config/src/plugins/importmap.ts +++ b/apps/vben5/internal/vite-config/src/plugins/importmap.ts @@ -10,11 +10,11 @@ import { minify } from 'html-minifier-terser'; const DEFAULT_PROVIDER = 'jspm.io'; -type pluginOptions = { +type pluginOptions = GeneratorOptions & { debug?: boolean; defaultProvider?: 'esm.sh' | 'jsdelivr' | 'jspm.io'; importmap?: Array<{ name: string; range?: string }>; -} & GeneratorOptions; +}; // async function getLatestVersionOfShims() { // const result = await fetch('https://ga.jspm.io/npm:es-module-shims'); diff --git a/apps/vben5/internal/vite-config/src/plugins/inject-app-loading/index.ts b/apps/vben5/internal/vite-config/src/plugins/inject-app-loading/index.ts index 9f6e2a5c8..c6a79830d 100644 --- a/apps/vben5/internal/vite-config/src/plugins/inject-app-loading/index.ts +++ b/apps/vben5/internal/vite-config/src/plugins/inject-app-loading/index.ts @@ -1,3 +1,5 @@ +import type { PluginOption } from 'vite'; + import fs from 'node:fs'; import fsp from 'node:fs/promises'; import { join } from 'node:path'; @@ -5,8 +7,6 @@ import { fileURLToPath } from 'node:url'; import { readPackageJSON } from '@vben/node-utils'; -import { type PluginOption } from 'vite'; - /** * 用于生成将loading样式注入到项目中 * 为多app提供loading样式,无需在每个 app -> index.html单独引入 diff --git a/apps/vben5/internal/vite-config/src/utils/env.ts b/apps/vben5/internal/vite-config/src/utils/env.ts index 1dfd18086..f34221617 100644 --- a/apps/vben5/internal/vite-config/src/utils/env.ts +++ b/apps/vben5/internal/vite-config/src/utils/env.ts @@ -1,5 +1,6 @@ import type { ApplicationPluginOptions } from '../typing'; +import { existsSync } from 'node:fs'; import { join } from 'node:path'; import { fs } from '@vben/node-utils'; @@ -21,12 +22,11 @@ function getConfFiles() { const script = process.env.npm_lifecycle_script as string; const reg = /--mode ([\d_a-z]+)/; const result = reg.exec(script); - + let mode = 'production'; if (result) { - const mode = result[1]; - return ['.env', `.env.${mode}`]; + mode = result[1] as string; } - return ['.env', '.env.production']; + return ['.env', '.env.local', `.env.${mode}`, `.env.${mode}.local`]; } /** @@ -42,11 +42,14 @@ async function loadEnv>( for (const confFile of confFiles) { try { - const envPath = await fs.readFile(join(process.cwd(), confFile), { - encoding: 'utf8', - }); - const env = dotenv.parse(envPath); - envConfig = { ...envConfig, ...env }; + const confFilePath = join(process.cwd(), confFile); + if (existsSync(confFilePath)) { + const envPath = await fs.readFile(confFilePath, { + encoding: 'utf8', + }); + const env = dotenv.parse(envPath); + envConfig = { ...envConfig, ...env }; + } } catch (error) { console.error(`Error while parsing ${confFile}`, error); } @@ -64,11 +67,11 @@ async function loadAndConvertEnv( match = 'VITE_', confFiles = getConfFiles(), ): Promise< - { + Partial & { appTitle: string; base: string; port: number; - } & Partial + } > { const envConfig = await loadEnv(match, confFiles); diff --git a/apps/vben5/package.json b/apps/vben5/package.json index 1bf68b17d..4b6b0a33f 100644 --- a/apps/vben5/package.json +++ b/apps/vben5/package.json @@ -1,6 +1,6 @@ { "name": "vben-admin-monorepo", - "version": "5.4.8", + "version": "5.5.3", "private": true, "keywords": [ "monorepo", @@ -27,6 +27,7 @@ "scripts": { "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build", "build:analyze": "turbo build:analyze", + "build:app": "pnpm run build --filter=@abp/app-antd", "build:antd": "pnpm run build --filter=@vben/web-antd", "build:docker": "./scripts/deploy/build-local-docker-image.sh", "build:docs": "pnpm run build --filter=@vben/docs", @@ -42,7 +43,7 @@ "clean": "node ./scripts/clean.mjs", "commit": "czg", "dev": "turbo-run dev", - "dev:app": "pnpm -F @vben/app-antd run dev", + "dev:app": "pnpm -F @abp/app-antd run dev", "dev:antd": "pnpm -F @vben/web-antd run dev", "dev:docs": "pnpm -F @vben/docs run dev", "dev:ele": "pnpm -F @vben/web-ele run dev", @@ -101,7 +102,7 @@ "node": ">=20.10.0", "pnpm": ">=9.12.0" }, - "packageManager": "pnpm@9.14.4", + "packageManager": "pnpm@9.15.5", "pnpm": { "peerDependencyRules": { "allowedVersions": { @@ -112,6 +113,7 @@ "@ast-grep/napi": "catalog:", "@ctrl/tinycolor": "catalog:", "clsx": "catalog:", + "esbuild": "0.24.0", "pinia": "catalog:", "vue": "catalog:" }, diff --git a/apps/vben5/packages/@abp/account/package.json b/apps/vben5/packages/@abp/account/package.json index 2a5a46074..5f1535bd2 100644 --- a/apps/vben5/packages/@abp/account/package.json +++ b/apps/vben5/packages/@abp/account/package.json @@ -1,6 +1,6 @@ { "name": "@abp/account", - "version": "8.2.3", + "version": "9.0.4", "homepage": "https://github.com/colinin/abp-next-admin", "bugs": "https://github.com/colinin/abp-next-admin/issues", "repository": { @@ -21,12 +21,21 @@ }, "dependencies": { "@abp/core": "workspace:*", + "@abp/identity": "workspace:*", "@abp/request": "workspace:*", "@abp/ui": "workspace:*", + "@ant-design/icons-vue": "catalog:", + "@vben-core/shadcn-ui": "workspace:*", + "@vben/common-ui": "workspace:*", "@vben/hooks": "workspace:*", "@vben/layouts": "workspace:*", "@vben/locales": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/stores": "workspace:*", + "@vueuse/core": "catalog:", + "@vueuse/integrations": "catalog:", "ant-design-vue": "catalog:", - "vue": "catalog:*" + "vue": "catalog:*", + "vue-router": "catalog:" } } diff --git a/apps/vben5/packages/@abp/account/src/api/index.ts b/apps/vben5/packages/@abp/account/src/api/index.ts index 76ba2a014..2aa1d0ab1 100644 --- a/apps/vben5/packages/@abp/account/src/api/index.ts +++ b/apps/vben5/packages/@abp/account/src/api/index.ts @@ -1,2 +1,5 @@ -export * from './token'; -export * from './user'; +export { useAccountApi } from './useAccountApi'; +export { useMySessionApi } from './useMySessionApi'; +export { useProfileApi } from './useProfileApi'; +export { useTokenApi } from './useTokenApi'; +export { useUserInfoApi } from './useUserInfoApi'; diff --git a/apps/vben5/packages/@abp/account/src/api/token.ts b/apps/vben5/packages/@abp/account/src/api/token.ts deleted file mode 100644 index 212cc707c..000000000 --- a/apps/vben5/packages/@abp/account/src/api/token.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { - OAuthTokenResult, - PasswordTokenRequestModel, - TokenResult, -} from '../types'; - -import { useAppConfig } from '@vben/hooks'; - -import { requestClient } from '@abp/request'; - -/** - * 用户登录 - * @param request 参数 - * @returns 用户token - */ -export async function loginApi( - request: PasswordTokenRequestModel, -): Promise { - const { clientId, clientSecret } = useAppConfig( - import.meta.env, - import.meta.env.PROD, - ); - const result = await requestClient.post( - '/connect/token', - { - client_id: clientId, - client_secret: clientSecret, - grant_type: 'password', - password: request.password, - scope: - 'openid email address phone profile offline_access lingyun-abp-application', - username: request.username, - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - }, - ); - return { - accessToken: result.access_token, - expiresIn: result.expires_in, - refreshToken: result.refresh_token, - tokenType: result.token_type, - }; -} diff --git a/apps/vben5/packages/@abp/account/src/api/useAccountApi.ts b/apps/vben5/packages/@abp/account/src/api/useAccountApi.ts new file mode 100644 index 000000000..a6c04c4fa --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/api/useAccountApi.ts @@ -0,0 +1,63 @@ +import type { ListResultDto } from '@abp/core'; + +import type { + GetTwoFactorProvidersInput, + SendEmailSigninCodeDto, + SendPhoneSigninCodeDto, + TwoFactorProvider, +} from '../types/account'; + +import { useRequest } from '@abp/request'; + +export function useAccountApi() { + const { cancel, request } = useRequest(); + + /** + * 获取可用的二次认证验证器 + * @param input 参数 + */ + function getTwoFactorProvidersApi( + input: GetTwoFactorProvidersInput, + ): Promise> { + return request>( + '/api/account/two-factor-providers', + { + method: 'GET', + params: input, + }, + ); + } + + /** + * 发送登陆验证邮件 + * @param input 参数 + */ + function sendEmailSigninCodeApi( + input: SendEmailSigninCodeDto, + ): Promise { + return request('/api/account/email/send-signin-code', { + data: input, + method: 'POST', + }); + } + + /** + * 发送登陆验证短信 + * @param input 参数 + */ + function sendPhoneSigninCodeApi( + input: SendPhoneSigninCodeDto, + ): Promise { + return request('/api/account/phone/send-signin-code', { + data: input, + method: 'POST', + }); + } + + return { + cancel, + getTwoFactorProvidersApi, + sendEmailSigninCodeApi, + sendPhoneSigninCodeApi, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/api/useMySessionApi.ts b/apps/vben5/packages/@abp/account/src/api/useMySessionApi.ts new file mode 100644 index 000000000..8a752a12b --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/api/useMySessionApi.ts @@ -0,0 +1,41 @@ +import type { PagedResultDto } from '@abp/core'; +import type { GetMySessionsInput, IdentitySessionDto } from '@abp/identity'; + +import { useRequest } from '@abp/request'; + +export function useMySessionApi() { + const { cancel, request } = useRequest(); + + /** + * 查询会话列表 + * @param { GetMySessionsInput } input 查询参数 + * @returns { Promise> } 用户会话列表 + */ + function getSessionsApi( + input?: GetMySessionsInput, + ): Promise> { + return request>( + '/api/account/my-profile/sessions', + { + method: 'GET', + params: input, + }, + ); + } + /** + * 撤销会话 + * @param { string } sessionId 会话id + * @returns { Promise } + */ + function revokeSessionApi(sessionId: string): Promise { + return request(`/api/account/my-profile/sessions/${sessionId}/revoke`, { + method: 'DELETE', + }); + } + + return { + cancel, + getSessionsApi, + revokeSessionApi, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/api/useProfileApi.ts b/apps/vben5/packages/@abp/account/src/api/useProfileApi.ts new file mode 100644 index 000000000..c0351e2d6 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/api/useProfileApi.ts @@ -0,0 +1,145 @@ +import type { + AuthenticatorDto, + AuthenticatorRecoveryCodeDto, + ChangePasswordInput, + ConfirmEmailInput, + ProfileDto, + SendEmailConfirmCodeDto, + TwoFactorEnabledDto, + UpdateProfileDto, + VerifyAuthenticatorCodeInput, +} from '../types/profile'; + +import { useRequest } from '@abp/request'; + +export function useProfileApi() { + const { cancel, request } = useRequest(); + + /** + * 查询个人信息 + * @returns 个人信息 + */ + function getApi(): Promise { + return request('/api/account/my-profile', { + method: 'GET', + }); + } + + /** + * 更新个人信息 + * @param input 参数 + * @returns 个人信息 + */ + function updateApi(input: UpdateProfileDto): Promise { + return request('/api/account/my-profile', { + data: input, + method: 'PUT', + }); + } + + /** + * 修改密码 + * @param input 参数 + */ + function changePasswordApi(input: ChangePasswordInput): Promise { + return request('/api/account/my-profile/change-password', { + data: input, + method: 'POST', + }); + } + + /** + * 获取二次认证启用状态 + */ + function getTwoFactorEnabledApi(): Promise { + return request('/api/account/my-profile/two-factor', { + method: 'GET', + }); + } + + /** + * 设置二次认证启用状态 + */ + function changeTwoFactorEnabledApi( + input: TwoFactorEnabledDto, + ): Promise { + return request('/api/account/my-profile/change-two-factor', { + data: input, + method: 'PUT', + }); + } + + /** + * 获取身份验证器配置 + * @returns 身份验证器 + */ + function getAuthenticatorApi(): Promise { + return request('/api/account/my-profile/authenticator', { + method: 'GET', + }); + } + + /** + * 验证身份验证代码 + * @param input 参数 + * @returns 重置代码 + */ + function verifyAuthenticatorCodeApi( + input: VerifyAuthenticatorCodeInput, + ): Promise { + return request( + '/api/account/my-profile/verify-authenticator-code', + { + data: input, + method: 'POST', + }, + ); + } + + /** + * 重置验证器 + */ + function resetAuthenticatorApi(): Promise { + return request('/api/account/my-profile/reset-authenticator', { + method: 'POST', + }); + } + + /** + * 发送邮件确认链接 + * @param input 参数 + */ + function sendEmailConfirmLinkApi( + input: SendEmailConfirmCodeDto, + ): Promise { + return request('/api/account/my-profile/send-email-confirm-link', { + data: input, + method: 'POST', + }); + } + + /** + * 确认邮件 + * @param input 参数 + */ + function confirmEmailApi(input: ConfirmEmailInput) { + return request('/api/account/my-profile/confirm-email', { + data: input, + method: 'PUT', + }); + } + + return { + cancel, + changePasswordApi, + changeTwoFactorEnabledApi, + confirmEmailApi, + getApi, + getAuthenticatorApi, + getTwoFactorEnabledApi, + resetAuthenticatorApi, + sendEmailConfirmLinkApi, + updateApi, + verifyAuthenticatorCodeApi, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/api/useTokenApi.ts b/apps/vben5/packages/@abp/account/src/api/useTokenApi.ts new file mode 100644 index 000000000..e41e84c10 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/api/useTokenApi.ts @@ -0,0 +1,83 @@ +import type { + OAuthTokenRefreshModel, + OAuthTokenResult, + PasswordTokenRequestModel, + TokenResult, +} from '../types'; + +import { useAppConfig } from '@vben/hooks'; + +import { useRequest } from '@abp/request'; + +export function useTokenApi() { + const { cancel, request } = useRequest(); + /** + * 用户登录 + * @param input 参数 + * @returns 用户token + */ + async function loginApi( + input: PasswordTokenRequestModel, + ): Promise { + const { audience, clientId, clientSecret } = useAppConfig( + import.meta.env, + import.meta.env.PROD, + ); + const result = await request('/connect/token', { + data: { + client_id: clientId, + client_secret: clientSecret, + grant_type: 'password', + scope: audience, + ...input, + }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + return { + accessToken: result.access_token, + expiresIn: result.expires_in, + refreshToken: result.refresh_token, + tokenType: result.token_type, + }; + } + + /** + * 刷新令牌 + * @param input 参数 + * @returns 用户token + */ + async function refreshTokenApi(input: OAuthTokenRefreshModel) { + const { audience, clientId, clientSecret } = useAppConfig( + import.meta.env, + import.meta.env.PROD, + ); + const result = await request('/connect/token', { + data: { + client_id: clientId, + client_secret: clientSecret, + grant_type: 'refresh_token', + refresh_token: input.refreshToken, + scope: audience, + }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + }); + return { + accessToken: result.access_token, + expiresIn: result.expires_in, + refreshToken: result.refresh_token, + tokenType: result.token_type, + }; + } + + return { + cancel, + loginApi, + refreshTokenApi, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/api/useUserInfoApi.ts b/apps/vben5/packages/@abp/account/src/api/useUserInfoApi.ts new file mode 100644 index 000000000..aa7c5adb3 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/api/useUserInfoApi.ts @@ -0,0 +1,29 @@ +import type { OAuthUserInfo, UserInfo } from '../types/user'; + +import { useRequest } from '@abp/request'; + +export function useUserInfoApi() { + const { cancel, request } = useRequest(); + + /** + * 获取用户信息 + */ + async function getUserInfoApi(): Promise { + const result = await request('/connect/userinfo', { + method: 'GET', + }); + return { + ...result, + emailVerified: result.email_verified, + givenName: result.given_name, + phoneNumberVerified: result.phone_number_verified, + preferredUsername: result.preferred_username, + uniqueName: result.unique_name, + }; + } + + return { + cancel, + getUserInfoApi, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/api/user.ts b/apps/vben5/packages/@abp/account/src/api/user.ts deleted file mode 100644 index 87611be89..000000000 --- a/apps/vben5/packages/@abp/account/src/api/user.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { OAuthUserInfo, UserInfo } from '../types/user'; - -import { requestClient } from '@abp/request'; - -/** - * 获取用户信息 - */ -export async function getUserInfoApi(): Promise { - const result = await requestClient.get('/connect/userinfo'); - return { - ...result, - emailVerified: result.email_verified, - givenName: result.given_name, - phoneNumberVerified: result.phone_number_verified, - preferredUsername: result.preferred_username, - uniqueName: result.unique_name, - }; -} diff --git a/apps/vben5/packages/@abp/account/src/components/MyProfile.vue b/apps/vben5/packages/@abp/account/src/components/MyProfile.vue new file mode 100644 index 000000000..a17f9b5eb --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/MyProfile.vue @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ $t('AbpUi.Submit') }} + + + + + + + + {{ $t('AbpUi.ProfilePicture') }} + + + + + + + + + {{ $t('abp.account.settings.changeAvatar') }} + + + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/MySetting.vue b/apps/vben5/packages/@abp/account/src/components/MySetting.vue new file mode 100644 index 000000000..f8fb3cd0d --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/MySetting.vue @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSettings.vue b/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSettings.vue new file mode 100644 index 000000000..f41ec0dfa --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSettings.vue @@ -0,0 +1,66 @@ + + + + + + + + + + {{ $t('AbpAccount.ResetAuthenticator') }} + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSteps.vue b/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSteps.vue new file mode 100644 index 000000000..a3323804e --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/AuthenticatorSteps.vue @@ -0,0 +1,214 @@ + + + + + + + + + + + {{ + $t('AbpAccount.Authenticator') + }} + {{ + $t('AbpAccount.AuthenticatorDesc') + }} + + + + + + + + + + + + + + + {{ $t('AbpAccount.Authenticator:CopyToClipboard') }} + + + + + {{ authenticator?.sharedKey }} + + + + + + + + + + + {{ + $t('AbpAccount.ValidAuthenticator') + }} + {{ + $t('AbpAccount.ValidAuthenticatorDesc') + }} + + + + + + + + + + + + + {{ $t('AbpAccount.Validation') }} + + + + + + + + + {{ + $t('AbpAccount.RecoveryCode') + }} + {{ + $t('AbpAccount.RecoveryCodeDesc') + }} + + + + + {{ $t('AbpAccount.Authenticator:CopyToClipboard') }} + + + + + {{ recoveryCodes.slice(0, 5).join('\r\n') }} + + + {{ recoveryCodes.slice(5).join('\r\n') }} + + + + + + + + {{ $t('AbpAccount.Steps:PreStep') }} + + + {{ $t('AbpAccount.Steps:NextStep') }} + + + {{ $t('AbpAccount.Steps:Done') }} + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/BasicSettings.vue b/apps/vben5/packages/@abp/account/src/components/components/BasicSettings.vue new file mode 100644 index 000000000..eec631aa4 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/BasicSettings.vue @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + {{ $t('AbpUi.Submit') }} + + + + + + + + {{ $t('AbpUi.ProfilePicture') }} + + + + + + + + + {{ $t('abp.account.settings.changeAvatar') }} + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/BindSettings.vue b/apps/vben5/packages/@abp/account/src/components/components/BindSettings.vue new file mode 100644 index 000000000..60ea57efc --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/BindSettings.vue @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/EmailConfirmModal.vue b/apps/vben5/packages/@abp/account/src/components/components/EmailConfirmModal.vue new file mode 100644 index 000000000..27b24715d --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/EmailConfirmModal.vue @@ -0,0 +1,60 @@ + + + + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/NoticeSettings.vue b/apps/vben5/packages/@abp/account/src/components/components/NoticeSettings.vue new file mode 100644 index 000000000..80b2914e0 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/NoticeSettings.vue @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue b/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue new file mode 100644 index 000000000..65ac3940b --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/SecuritySettings.vue @@ -0,0 +1,171 @@ + + + + + + + + + + {{ $t('AbpUi.Edit') }} + + + + + {{ + $t('abp.account.settings.security.password') + }} + + + + + + + + {{ $t('AbpUi.Edit') }} + + + + + {{ $t('abp.account.settings.security.phoneNumber') }} + + + {{ userInfo?.phoneNumber }} + + + {{ $t('abp.account.settings.security.unSet') }} + + + + + {{ $t('abp.account.settings.security.verified') }} + + + {{ $t('abp.account.settings.security.unVerified') }} + + + + + + + + + + {{ getSendMailTitle }} + + + + + {{ $t('abp.account.settings.security.email') }} + + + {{ userInfo?.email }} + + {{ $t('abp.account.settings.security.verified') }} + + + {{ $t('abp.account.settings.security.unVerified') }} + + + + + + + + onTwoFactorChange(Boolean(checked))" + /> + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/components/SessionSettings.vue b/apps/vben5/packages/@abp/account/src/components/components/SessionSettings.vue new file mode 100644 index 000000000..8e193c9bb --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/components/SessionSettings.vue @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/apps/vben5/packages/@abp/account/src/components/index.ts b/apps/vben5/packages/@abp/account/src/components/index.ts new file mode 100644 index 000000000..691de32ef --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/components/index.ts @@ -0,0 +1,2 @@ +export { default as MyProfile } from './MyProfile.vue'; +export { default as MySetting } from './MySetting.vue'; diff --git a/apps/vben5/packages/@abp/account/src/hooks/index.ts b/apps/vben5/packages/@abp/account/src/hooks/index.ts new file mode 100644 index 000000000..6c4512ba9 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/hooks/index.ts @@ -0,0 +1 @@ +export * from './useOAuthError'; diff --git a/apps/vben5/packages/@abp/account/src/hooks/useOAuthError.ts b/apps/vben5/packages/@abp/account/src/hooks/useOAuthError.ts new file mode 100644 index 000000000..d40ada311 --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/hooks/useOAuthError.ts @@ -0,0 +1,16 @@ +interface OAuthError { + error: string; + error_description?: string; + error_uri?: string; +} + +export function useOAuthError() { + function formatError(error: OAuthError) { + // TODO: 解决oauth消息国际化. + return error.error_description; + } + + return { + formatError, + }; +} diff --git a/apps/vben5/packages/@abp/account/src/index.ts b/apps/vben5/packages/@abp/account/src/index.ts index 4d4b4e299..14fa9fe25 100644 --- a/apps/vben5/packages/@abp/account/src/index.ts +++ b/apps/vben5/packages/@abp/account/src/index.ts @@ -1,2 +1,4 @@ export * from './api'; +export * from './components'; +export * from './hooks'; export * from './types'; diff --git a/apps/vben5/packages/@abp/account/src/types/account.ts b/apps/vben5/packages/@abp/account/src/types/account.ts new file mode 100644 index 000000000..e5e66d37c --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/types/account.ts @@ -0,0 +1,22 @@ +import type { NameValue } from '@abp/core'; + +interface GetTwoFactorProvidersInput { + userId: string; +} + +interface SendEmailSigninCodeDto { + emailAddress: string; +} + +interface SendPhoneSigninCodeDto { + phoneNumber: string; +} + +type TwoFactorProvider = NameValue; + +export type { + GetTwoFactorProvidersInput, + SendEmailSigninCodeDto, + SendPhoneSigninCodeDto, + TwoFactorProvider, +}; diff --git a/apps/vben5/packages/@abp/account/src/types/index.ts b/apps/vben5/packages/@abp/account/src/types/index.ts index 76ba2a014..1dd5f3324 100644 --- a/apps/vben5/packages/@abp/account/src/types/index.ts +++ b/apps/vben5/packages/@abp/account/src/types/index.ts @@ -1,2 +1,4 @@ +export * from './account'; +export * from './profile'; export * from './token'; export * from './user'; diff --git a/apps/vben5/packages/@abp/account/src/types/profile.ts b/apps/vben5/packages/@abp/account/src/types/profile.ts new file mode 100644 index 000000000..e614f818d --- /dev/null +++ b/apps/vben5/packages/@abp/account/src/types/profile.ts @@ -0,0 +1,78 @@ +import type { ExtensibleObject, IHasConcurrencyStamp } from '@abp/core'; + +interface ProfileDto extends ExtensibleObject, IHasConcurrencyStamp { + /** 电子邮件 */ + email: string; + hasPassword: boolean; + /** 是否外部用户 */ + isExternal: boolean; + /** 名称 */ + name?: string; + /** 手机号码 */ + phoneNumber?: string; + /** 姓氏 */ + surname?: string; + /** 用户名 */ + userName: string; +} + +interface UpdateProfileDto extends ExtensibleObject, IHasConcurrencyStamp { + /** 电子邮件 */ + email: string; + /** 名称 */ + name?: string; + /** 手机号码 */ + phoneNumber?: string; + /** 姓氏 */ + surname?: string; + /** 用户名 */ + userName: string; +} + +interface ChangePasswordInput { + /** 当前密码 */ + currentPassword: string; + /** 新密码 */ + newPassword: string; +} + +interface TwoFactorEnabledDto { + /** 是否启用二次认证 */ + enabled: boolean; +} + +interface AuthenticatorDto { + authenticatorUri: string; + isAuthenticated: boolean; + sharedKey: string; +} + +interface VerifyAuthenticatorCodeInput { + authenticatorCode: string; +} + +interface AuthenticatorRecoveryCodeDto { + recoveryCodes: string[]; +} + +interface SendEmailConfirmCodeDto { + appName: string; + email: string; + returnUrl?: string; +} + +interface ConfirmEmailInput { + confirmToken: string; +} + +export type { + AuthenticatorDto, + AuthenticatorRecoveryCodeDto, + ChangePasswordInput, + ConfirmEmailInput, + ProfileDto, + SendEmailConfirmCodeDto, + TwoFactorEnabledDto, + UpdateProfileDto, + VerifyAuthenticatorCodeInput, +}; diff --git a/apps/vben5/packages/@abp/account/src/types/token.ts b/apps/vben5/packages/@abp/account/src/types/token.ts index b8bb274d3..646681e9c 100644 --- a/apps/vben5/packages/@abp/account/src/types/token.ts +++ b/apps/vben5/packages/@abp/account/src/types/token.ts @@ -32,6 +32,10 @@ interface TokenResult { /** 令牌类型 */ tokenType: string; } +interface OAuthTokenRefreshModel { + /** 刷新令牌 */ + refreshToken: string; +} /** oauth标准令牌返回结构 */ interface OAuthTokenResult { /** 访问令牌 */ @@ -44,10 +48,27 @@ interface OAuthTokenResult { token_type: string; } +interface OAuthError { + /** 错误类型 */ + error: string; + /** 错误描述 */ + error_description: string; + /** 错误描述链接 */ + error_uri?: string; +} + +interface TwoFactorError extends OAuthError { + twoFactorToken: string; + userId: string; +} + export type { + OAuthError, + OAuthTokenRefreshModel, OAuthTokenResult, PasswordTokenRequest, PasswordTokenRequestModel, TokenRequest, TokenResult, + TwoFactorError, }; diff --git a/apps/vben5/packages/@abp/account/src/types/user.ts b/apps/vben5/packages/@abp/account/src/types/user.ts index b571e11a3..c0d40bf07 100644 --- a/apps/vben5/packages/@abp/account/src/types/user.ts +++ b/apps/vben5/packages/@abp/account/src/types/user.ts @@ -11,7 +11,7 @@ interface UserInfo { /** * 名称 */ - givenName: string; + givenName?: string; /** * 用户名 */ diff --git a/apps/vben5/packages/@abp/auditing/package.json b/apps/vben5/packages/@abp/auditing/package.json new file mode 100644 index 000000000..857f4ed39 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/package.json @@ -0,0 +1,38 @@ +{ + "name": "@abp/auditing", + "version": "9.0.4", + "homepage": "https://github.com/colinin/abp-next-admin", + "bugs": "https://github.com/colinin/abp-next-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/colinin/abp-next-admin.git", + "directory": "packages/@abp/auditing" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, + "dependencies": { + "@abp/components": "workspace:*", + "@abp/core": "workspace:*", + "@abp/request": "workspace:*", + "@abp/ui": "workspace:*", + "@ant-design/icons-vue": "catalog:", + "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/layouts": "workspace:*", + "@vben/locales": "workspace:*", + "ant-design-vue": "catalog:", + "vue": "catalog:*", + "vxe-table": "catalog:" + } +} diff --git a/apps/vben5/packages/@abp/auditing/src/api/index.ts b/apps/vben5/packages/@abp/auditing/src/api/index.ts new file mode 100644 index 000000000..8613244d7 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/api/index.ts @@ -0,0 +1,2 @@ +export { useAuditLogsApi } from './useAuditLogsApi'; +export { useEntityChangesApi } from './useEntityChangesApi'; diff --git a/apps/vben5/packages/@abp/auditing/src/api/useAuditLogsApi.ts b/apps/vben5/packages/@abp/auditing/src/api/useAuditLogsApi.ts new file mode 100644 index 000000000..fb63f8429 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/api/useAuditLogsApi.ts @@ -0,0 +1,65 @@ +import type { PagedResultDto } from '@abp/core'; + +import type { + AuditLogDeleteManyInput, + AuditLogDto, + AuditLogGetListInput, +} from '../types/audit-logs'; + +import { useRequest } from '@abp/request'; + +export function useAuditLogsApi() { + const { cancel, request } = useRequest(); + + /** + * 获取审计日志 + * @param id 日志id + */ + function getApi(id: string): Promise { + return request(`/api/auditing/audit-log/${id}`, { + method: 'GET', + }); + } + + /** + * 获取审计日志分页列表 + * @param input 参数 + */ + function getPagedListApi( + input: AuditLogGetListInput, + ): Promise> { + return request>('/api/auditing/audit-log', { + method: 'GET', + params: input, + }); + } + + /** + * 删除审计日志 + * @param id 日志id + */ + function deleteApi(id: string): Promise { + return request(`/api/auditing/audit-log/${id}`, { + method: 'DELETE', + }); + } + + /** + * 批量删除审计日志 + * @param input 参数 + */ + function deleteManyApi(input: AuditLogDeleteManyInput): Promise { + return request(`/api/auditing/audit-log/bulk`, { + data: input, + method: 'DELETE', + }); + } + + return { + cancel, + deleteApi, + deleteManyApi, + getApi, + getPagedListApi, + }; +} diff --git a/apps/vben5/packages/@abp/auditing/src/api/useEntityChangesApi.ts b/apps/vben5/packages/@abp/auditing/src/api/useEntityChangesApi.ts new file mode 100644 index 000000000..0ca12d55a --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/api/useEntityChangesApi.ts @@ -0,0 +1,33 @@ +import type { ListResultDto } from '@abp/core'; + +import type { + EntityChangeGetWithUsernameInput, + EntityChangeWithUsernameDto, +} from '../types/entity-changes'; + +import { useRequest } from '@abp/request'; + +export function useEntityChangesApi() { + const { cancel, request } = useRequest(); + + /** + * 获取包含用户名称的实体变更列表 + * @param input 参数 + */ + function getListWithUsernameApi( + input: EntityChangeGetWithUsernameInput, + ): Promise> { + return request>( + '/api/auditing/entity-changes/with-username', + { + method: 'GET', + params: input, + }, + ); + } + + return { + cancel, + getListWithUsernameApi, + }; +} diff --git a/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogDrawer.vue b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogDrawer.vue new file mode 100644 index 000000000..72d305b12 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogDrawer.vue @@ -0,0 +1,244 @@ + + + + + + + + + + {{ auditLogModel.applicationName }} + + + {{ formatToDateTime(auditLogModel.executionTime) }} + + + {{ auditLogModel.userName }} + + + + {{ auditLogModel.httpMethod }} + + + + {{ auditLogModel.url }} + + + + {{ auditLogModel.httpStatusCode }} + + + + {{ auditLogModel.executionDuration }} + + + {{ auditLogModel.clientId }} + + + {{ auditLogModel.clientIpAddress }} + + + {{ auditLogModel.clientName }} + + + {{ auditLogModel.correlationId }} + + + {{ auditLogModel.browserInfo }} + + + {{ auditLogModel.comments }} + + + {{ auditLogModel.exceptions }} + + + {{ auditLogModel.extraProperties }} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogTable.vue b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogTable.vue new file mode 100644 index 000000000..5c2e29ad6 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/AuditLogTable.vue @@ -0,0 +1,380 @@ + + + + + + + {{ $t('AbpUi.Delete') }} + + + + + {{ row.extraProperties?.Location }} + + {{ row.clientIpAddress }} + + + + {{ row.httpStatusCode }} + + + {{ row.httpMethod }} + + {{ row.url }} + + + + + + {{ $t('AbpAuditLogging.ShowLogDialog') }} + + + {{ $t('AbpUi.Delete') }} + + + + + + + + diff --git a/apps/vben5/packages/@abp/auditing/src/components/audit-logs/mapping.ts b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/mapping.ts new file mode 100644 index 000000000..01f6c8da0 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/audit-logs/mapping.ts @@ -0,0 +1,57 @@ +const httpMethodOptions = [ + { label: 'GET', value: 'GET' }, + { label: 'PUT', value: 'PUT' }, + { label: 'POST', value: 'POST' }, + { label: 'PATCH', value: 'PATCH' }, + { label: 'DELETE', value: 'DELETE' }, + { label: 'OPTIONS', value: 'OPTIONS' }, + { label: 'HEAD', value: 'HEAD' }, +]; + +const httpStatusCodeOptions = [ + { label: '100 - Continue', value: 100 }, + { label: '101 - Switching Protocols', value: 101 }, + { label: '200 - OK', value: 200 }, + { label: '201 - Created', value: 201 }, + { label: '202 - Accepted', value: 202 }, + { label: '203 - Non Authoritative Information', value: 203 }, + { label: '204 - No Content', value: 204 }, + { label: '205 - Reset Content', value: 205 }, + { label: '206 - Partial Content', value: 206 }, + { label: '300 - Multiple Choices', value: 300 }, + { label: '301 - Moved Permanently', value: 301 }, + { label: '302 - Found & Redirect', value: 302 }, + { label: '303 - See Other', value: 303 }, + { label: '304 - Not Modified', value: 304 }, + { label: '305 - Use Proxy', value: 305 }, + { label: '306 - Switch Proxy', value: 306 }, + { label: '307 - Temporary Redirect', value: 307 }, + { label: '308 - Permanent Redirect', value: 308 }, + { label: '400 - Bad Request', value: 400 }, + { label: '401 - Unauthorized', value: 401 }, + { label: '402 - Payment Required', value: 402 }, + { label: '403 - Forbidden', value: 403 }, + { label: '404 - Not Found', value: 404 }, + { label: '405 - Method Not Allowed', value: 405 }, + { label: '406 - Not Acceptable', value: 406 }, + { label: '407 - Proxy Authentication Required', value: 407 }, + { label: '408 - Request Timeout', value: 408 }, + { label: '409 - Conflict', value: 409 }, + { label: '410 - Gone', value: 410 }, + { label: '411 - Length Required', value: 411 }, + { label: '412 - Precondition Failed', value: 412 }, + { label: '413 - Request Entity Too Large', value: 413 }, + { label: '414 - Request Uri Too Long', value: 414 }, + { label: '415 - Unsupported Media Type', value: 415 }, + { label: '416 - Requested Range Not Satisfiable', value: 416 }, + { label: '417 - Expectation Failed', value: 417 }, + { label: '426 - Upgrade Required', value: 426 }, + { label: '500 - Internal Server Error', value: 500 }, + { label: '501 - Not mplemented', value: 501 }, + { label: '502 - Bad Gateway', value: 502 }, + { label: '503 - Service Unavailable', value: 503 }, + { label: '504 - Gateway Timeout', value: 504 }, + { label: '505 - Http Version Not Supported', value: 505 }, +]; + +export { httpMethodOptions, httpStatusCodeOptions }; diff --git a/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeDrawer.vue b/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeDrawer.vue new file mode 100644 index 000000000..5c45fab63 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeDrawer.vue @@ -0,0 +1,58 @@ + + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeTable.vue b/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeTable.vue new file mode 100644 index 000000000..f1c341341 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/entity-changes/EntityChangeTable.vue @@ -0,0 +1,171 @@ + + + + + + + {{ getChangeTypeValue(row.changeType) }} + + + + + + + + + diff --git a/apps/vben5/packages/@abp/auditing/src/components/index.ts b/apps/vben5/packages/@abp/auditing/src/components/index.ts new file mode 100644 index 000000000..1d99b4a46 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/components/index.ts @@ -0,0 +1,2 @@ +export { default as AuditLogTable } from './audit-logs/AuditLogTable.vue'; +export { default as EntityChangeDrawer } from './entity-changes/EntityChangeDrawer.vue'; diff --git a/apps/vben5/packages/@abp/permission/src/types/index.ts b/apps/vben5/packages/@abp/auditing/src/constants/index.ts similarity index 100% rename from apps/vben5/packages/@abp/permission/src/types/index.ts rename to apps/vben5/packages/@abp/auditing/src/constants/index.ts diff --git a/apps/vben5/packages/@abp/auditing/src/constants/permissions.ts b/apps/vben5/packages/@abp/auditing/src/constants/permissions.ts new file mode 100644 index 000000000..00e8dc003 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/constants/permissions.ts @@ -0,0 +1,6 @@ +/** 审计日志权限 */ +export const AuditLogPermissions = { + Default: 'AbpAuditing.AuditLog', + /** 删除 */ + Delete: 'AbpAuditing.AuditLog.Delete', +}; diff --git a/apps/vben5/packages/@abp/auditing/src/hooks/useAuditlogs.ts b/apps/vben5/packages/@abp/auditing/src/hooks/useAuditlogs.ts new file mode 100644 index 000000000..97dc83cdc --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/hooks/useAuditlogs.ts @@ -0,0 +1,62 @@ +import { computed } from 'vue'; + +import { useLocalization } from '@abp/core'; + +import { ChangeType } from '../types/entity-changes'; + +export function useAuditlogs() { + const { L } = useLocalization(['AbpAuditLogging', 'AbpUi']); + + const changeTypeColorMap = { + [ChangeType.Created]: { color: '#87d068', value: L('Created') }, + [ChangeType.Deleted]: { color: 'red', value: L('Deleted') }, + [ChangeType.Updated]: { color: '#108ee9', value: L('Updated') }, + }; + + const methodColorMap: { [key: string]: string } = { + DELETE: 'red', + GET: 'blue', + OPTIONS: 'cyan', + PATCH: 'pink', + POST: 'green', + PUT: 'orange', + }; + const getChangeTypeColor = computed(() => { + return (changeType: ChangeType) => changeTypeColorMap[changeType].color; + }); + const getChangeTypeValue = computed(() => { + return (changeType: ChangeType) => changeTypeColorMap[changeType].value; + }); + const getHttpMethodColor = computed(() => { + return (method?: string) => { + return method ? methodColorMap[method] : ''; + }; + }); + const getHttpStatusCodeColor = computed(() => { + return (statusCode?: number) => { + if (!statusCode) { + return ''; + } + if (statusCode >= 200 && statusCode < 300) { + return '#87d068'; + } + if (statusCode >= 300 && statusCode < 400) { + return '#108ee9'; + } + if (statusCode >= 400 && statusCode < 500) { + return 'orange'; + } + if (statusCode >= 500) { + return 'red'; + } + return 'cyan'; + }; + }); + + return { + getChangeTypeColor, + getChangeTypeValue, + getHttpMethodColor, + getHttpStatusCodeColor, + }; +} diff --git a/apps/vben5/packages/@abp/auditing/src/index.ts b/apps/vben5/packages/@abp/auditing/src/index.ts new file mode 100644 index 000000000..f43dbaee0 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './components'; +export * from './constants'; +export * from './types'; diff --git a/apps/vben5/packages/@abp/auditing/src/types/audit-logs.ts b/apps/vben5/packages/@abp/auditing/src/types/audit-logs.ts new file mode 100644 index 000000000..ce54b99ad --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/types/audit-logs.ts @@ -0,0 +1,71 @@ +import type { + ExtraPropertyDictionary, + PagedAndSortedResultRequestDto, +} from '@abp/core'; + +import type { EntityChangeDto } from './entity-changes'; + +interface Action { + [key: string]: any; + executionDuration?: number; + executionTime: Date; + extraProperties?: ExtraPropertyDictionary; + id: string; + methodName?: string; + parameters?: string; + serviceName?: string; +} + +interface AuditLogDeleteManyInput { + ids: string[]; +} + +interface AuditLogDto { + [key: string]: any; + actions?: Action[]; + applicationName?: string; + browserInfo?: string; + clientId?: string; + clientIpAddress?: string; + clientName?: string; + comments?: string; + correlationId?: string; + entityChanges?: EntityChangeDto[]; + exceptions?: string; + executionDuration?: number; + executionTime?: Date; + extraProperties?: ExtraPropertyDictionary; + httpMethod?: string; + httpStatusCode?: number; + id: string; + impersonatorTenantId?: string; + impersonatorUserId?: string; + tenantId?: string; + tenantName?: string; + url?: string; + userId?: string; + userName?: string; +} +interface AuditLogGetListInput extends PagedAndSortedResultRequestDto { + applicationName?: string; + clientId?: string; + clientIpAddress?: string; + correlationId?: string; + endTime?: Date; + hasException?: boolean; + httpMethod?: string; + httpStatusCode?: number; + maxExecutionDuration?: number; + minExecutionDuration?: number; + startTime?: Date; + url?: string; + userId?: string; + userName?: string; +} + +export type { + Action, + AuditLogDeleteManyInput, + AuditLogDto, + AuditLogGetListInput, +}; diff --git a/apps/vben5/packages/@abp/auditing/src/types/entity-changes.ts b/apps/vben5/packages/@abp/auditing/src/types/entity-changes.ts new file mode 100644 index 000000000..0ae5d4680 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/types/entity-changes.ts @@ -0,0 +1,63 @@ +import type { + ExtraPropertyDictionary, + PagedAndSortedResultRequestDto, +} from '@abp/core'; + +export enum ChangeType { + Created = 0, + Deleted = 2, + Updated = 1, +} + +interface PropertyChange { + id: string; + newValue?: string; + originalValue?: string; + propertyName?: string; + propertyTypeFullName?: string; +} + +interface EntityChangeDto { + [key: string]: any; + changeTime?: Date; + changeType: ChangeType; + entityId?: string; + entityTenantId?: string; + entityTypeFullName?: string; + extraProperties?: ExtraPropertyDictionary; + id: string; + propertyChanges?: PropertyChange[]; +} + +interface EntityChangeWithUsernameDto { + entityChange: EntityChangeDto; + userName?: string; +} + +interface EntityChangeGetListInput extends PagedAndSortedResultRequestDto { + auditLogId?: string; + changeType?: ChangeType; + endTime?: Date; + entityId?: string; + entityTypeFullName?: string; + startTime?: Date; +} + +interface EntityChangeGetWithUsernameInput { + entityId?: string; + entityTypeFullName?: string; +} + +interface RestoreEntityInput { + entityChangeId?: string; + entityId: string; +} + +export type { + EntityChangeDto, + EntityChangeGetListInput, + EntityChangeGetWithUsernameInput, + EntityChangeWithUsernameDto, + PropertyChange, + RestoreEntityInput, +}; diff --git a/apps/vben5/packages/@abp/auditing/src/types/index.ts b/apps/vben5/packages/@abp/auditing/src/types/index.ts new file mode 100644 index 000000000..900570716 --- /dev/null +++ b/apps/vben5/packages/@abp/auditing/src/types/index.ts @@ -0,0 +1,2 @@ +export * from './audit-logs'; +export * from './entity-changes'; diff --git a/apps/vben5/packages/@abp/permission/tsconfig.json b/apps/vben5/packages/@abp/auditing/tsconfig.json similarity index 100% rename from apps/vben5/packages/@abp/permission/tsconfig.json rename to apps/vben5/packages/@abp/auditing/tsconfig.json diff --git a/apps/vben5/packages/@abp/components/package.json b/apps/vben5/packages/@abp/components/package.json new file mode 100644 index 000000000..d152bb711 --- /dev/null +++ b/apps/vben5/packages/@abp/components/package.json @@ -0,0 +1,55 @@ +{ + "name": "@abp/components", + "version": "9.0.4", + "homepage": "https://github.com/colinin/abp-next-admin", + "bugs": "https://github.com/colinin/abp-next-admin/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/colinin/abp-next-admin.git", + "directory": "packages/@abp/components" + }, + "license": "MIT", + "type": "module", + "sideEffects": [ + "**/*.css" + ], + "exports": { + "./codeeditor": { + "types": "./src/codeeditor/index.ts", + "default": "./src/codeeditor/index.ts" + }, + "./codemirror": { + "types": "./src/codemirror/index.ts", + "default": "./src/codemirror/index.ts" + }, + "./tinymce": { + "types": "./src/tinymce/index.ts", + "default": "./src/tinymce/index.ts" + } + }, + "dependencies": { + "@abp/core": "workspace:*", + "@vben-core/form-ui": "workspace:*", + "@vben-core/preferences": "workspace:*", + "@vben-core/shadcn-ui": "workspace:*", + "@vben-core/shared": "workspace:*", + "@vben-core/typings": "workspace:*", + "@vben/common-ui": "workspace:*", + "@vben/hooks": "workspace:*", + "@vben/icons": "workspace:*", + "@vben/locales": "workspace:*", + "@vben/preferences": "workspace:*", + "@vben/types": "workspace:*", + "@vben/utils": "workspace:*", + "@vueuse/core": "catalog:", + "ant-design-vue": "catalog:", + "codemirror": "catalog:", + "lodash.isnumber": "catalog:", + "tinymce": "catalog:", + "vue": "catalog:*" + }, + "devDependencies": { + "@types/codemirror": "catalog:", + "@types/lodash.isnumber": "catalog:" + } +} diff --git a/apps/vben5/packages/@abp/components/src/codeeditor/CodeEditor.vue b/apps/vben5/packages/@abp/components/src/codeeditor/CodeEditor.vue new file mode 100644 index 000000000..ccf6e0607 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codeeditor/CodeEditor.vue @@ -0,0 +1,62 @@ + + + + + + diff --git a/apps/vben5/packages/@abp/components/src/codeeditor/index.ts b/apps/vben5/packages/@abp/components/src/codeeditor/index.ts new file mode 100644 index 000000000..6f9e255e7 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codeeditor/index.ts @@ -0,0 +1,2 @@ +export * from '../codemirror/types'; +export { default as CodeEditor } from './CodeEditor.vue'; diff --git a/apps/vben5/packages/@abp/components/src/codemirror/CodeMirror.vue b/apps/vben5/packages/@abp/components/src/codemirror/CodeMirror.vue new file mode 100644 index 000000000..2eea2947f --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codemirror/CodeMirror.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/apps/vben5/packages/@abp/components/src/codemirror/codemirror.css b/apps/vben5/packages/@abp/components/src/codemirror/codemirror.css new file mode 100644 index 000000000..cbcfa8764 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codemirror/codemirror.css @@ -0,0 +1,525 @@ +/* BASICS */ + +.CodeMirror { + --base: #545281; + --comment: hsl(210deg 25% 60%); + --keyword: #af4ab1; + --variable: #0055d1; + --function: #c25205; + --string: #2ba46d; + --number: #c25205; + --tags: #d00; + --qualifier: #ff6032; + --important: var(--string); + + position: relative; + height: auto; + height: 100%; + overflow: hidden; + font-family: var(--font-code); + background: white; + direction: ltr; +} + +/* PADDING */ + +.CodeMirror-lines { + min-height: 1px; /* prevents collapsing before first draw */ + padding: 4px 0; /* Vertical padding around content */ + cursor: text; +} + +.CodeMirror-scrollbar-filler, +.CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + position: absolute; + top: 0; + left: 5 !important; + z-index: 3; + min-height: 100%; + white-space: nowrap; + background-color: transparent; + border-right: 1px solid #ddd; +} + +.CodeMirror-linenumber { + min-width: 20px; + padding: 1 8px 0 5px; + color: var(--comment); + text-align: left !important; + white-space: nowrap; + opacity: 0.6; +} + +.CodeMirror-guttermarker { + color: black; +} + +.CodeMirror-guttermarker-subtle { + color: #999; +} + +/* FOLD GUTTER */ + +.CodeMirror-foldmarker { + font-family: arial; + line-height: 0.3; + color: #414141; + text-shadow: #f96 1px 1px 2px, #f96 -1px -1px 2px, #f96 1px -1px 2px, #f96 -1px 1px 2px; + cursor: pointer; +} + +.CodeMirror-foldgutter { + width: 0.7em; +} + +.CodeMirror-foldgutter-open, +.CodeMirror-foldgutter-folded { + cursor: pointer; +} + +.CodeMirror-foldgutter-open::after, +.CodeMirror-foldgutter-folded::after { + position: relative; + top: -0.1em; + display: inline-block; + font-size: 0.8em; + content: '>'; + opacity: 0.8; + transform: rotate(90deg); + transition: transform 0.2s; +} + +.CodeMirror-foldgutter-folded::after { + transform: none; +} + +/* CURSOR */ + +.CodeMirror-cursor { + position: absolute; + width: 0; + pointer-events: none; + border-right: none; + border-left: 1px solid black; +} + +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} + +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + background: #7e7; + border: 0 !important; +} + +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +.cm-fat-cursor-mark { + background-color: rgb(20 255 20 / 50%); + animation: blink 1.06s steps(1) infinite; +} + +.cm-animate-fat-cursor { + width: auto; + background-color: #7e7; + border: 0; + animation: blink 1.06s steps(1) infinite; +} +@keyframes blink { + 50% { + background-color: transparent; + } +} +@keyframes blink { + 50% { + background-color: transparent; + } +} +@keyframes blink { + 50% { + background-color: transparent; + } +} + +.cm-tab { + display: inline-block; + text-decoration: inherit; +} + +.CodeMirror-rulers { + position: absolute; + top: -50px; + right: 0; + bottom: -20px; + left: 0; + overflow: hidden; +} + +.CodeMirror-ruler { + position: absolute; + top: 0; + bottom: 0; + border-left: 1px solid #ccc; +} + +/* DEFAULT THEME */ +.cm-s-default.CodeMirror { + background-color: transparent; +} + +.cm-s-default .cm-header { + color: blue; +} + +.cm-s-default .cm-quote { + color: #090; +} + +.cm-negative { + color: #d44; +} + +.cm-positive { + color: #292; +} + +.cm-header, +.cm-strong { + font-weight: bold; +} + +.cm-em { + font-style: italic; +} + +.cm-link { + text-decoration: underline; +} + +.cm-strikethrough { + text-decoration: line-through; +} + +.cm-s-default .cm-atom, +.cm-s-default .cm-def, +.cm-s-default .cm-property, +.cm-s-default .cm-variable-2, +.cm-s-default .cm-variable-3, +.cm-s-default .cm-punctuation { + color: var(--base); +} + +.cm-s-default .cm-hr, +.cm-s-default .cm-comment { + color: var(--comment); +} + +.cm-s-default .cm-attribute, +.cm-s-default .cm-keyword { + color: var(--keyword); +} + +.cm-s-default .cm-variable { + color: var(--variable); +} + +.cm-s-default .cm-bracket, +.cm-s-default .cm-tag { + color: var(--tags); +} + +.cm-s-default .cm-number { + color: var(--number); +} + +.cm-s-default .cm-string, +.cm-s-default .cm-string-2 { + color: var(--string); +} + +.cm-s-default .cm-type { + color: #085; +} + +.cm-s-default .cm-meta { + color: #555; +} + +.cm-s-default .cm-qualifier { + color: var(--qualifier); +} + +.cm-s-default .cm-builtin { + color: #7539ff; +} + +.cm-s-default .cm-link { + color: var(--flash); +} + +.cm-s-default .cm-error { + color: #ff008c; +} + +.cm-invalidchar { + color: #ff008c; +} + +.CodeMirror-composing { + border-bottom: 2px solid; +} + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket { + color: #0b0; +} + +div.CodeMirror span.CodeMirror-nonmatchingbracket { + color: #a22; +} + +.CodeMirror-matchingtag { + background: rgb(255 150 0 / 30%); +} + +.CodeMirror-activeline-background { + background: #e8f2ff; +} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror-scroll { + position: relative; + height: 100%; + padding-bottom: 30px; + margin-right: -30px; + + /* 30px is the magic margin used to hide the element's real scrollbars */ + + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; + overflow: scroll !important; /* Things will break if this is overridden */ + outline: none; /* Prevent dragging from highlighting the element */ +} + +.CodeMirror-sizer { + position: relative; + margin-bottom: 20px !important; + border-right: 30px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, +.CodeMirror-hscrollbar, +.CodeMirror-scrollbar-filler, +.CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} + +.CodeMirror-vscrollbar { + top: 0; + right: 0; + overflow-x: hidden; + overflow-y: scroll; +} + +.CodeMirror-hscrollbar { + bottom: 0; + left: 0; + overflow-x: scroll; + overflow-y: hidden; +} + +.CodeMirror-scrollbar-filler { + right: 0; + bottom: 0; +} + +.CodeMirror-gutter-filler { + bottom: 0; + left: 0; +} + +.CodeMirror-gutter { + display: inline-block; + height: 100%; + margin-bottom: -30px; + white-space: normal; + vertical-align: top; +} + +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} + +.CodeMirror-gutter-background { + position: absolute; + top: 0; + bottom: 0; + z-index: 4; +} + +.CodeMirror-gutter-elt { + position: absolute; + z-index: 4; + cursor: default; +} + +.CodeMirror-gutter-wrapper ::selection { + background-color: transparent; +} + +.CodeMirrorwrapper ::selection { + background-color: transparent; +} + +.CodeMirror pre { + position: relative; + z-index: 2; + padding: 0 4px; /* Horizontal padding of content */ + margin: 0; + overflow: visible; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: inherit; + word-wrap: normal; + white-space: pre; + background: transparent; + border-width: 0; + + /* Reset some styles that the rest of the page might have set */ + border-radius: 0; + -webkit-tap-highlight-color: transparent; + font-variant-ligatures: contextual; +} + +.CodeMirror-wrap pre { + word-break: normal; + word-wrap: break-word; + white-space: pre-wrap; +} + +.CodeMirror-linebackground { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + padding: 0.1px; /* Force widget margins to stay inside of the container */ +} + +.CodeMirror-rtl pre { + direction: rtl; +} + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.CodeMirror-measure pre { + position: static; +} + +div.CodeMirror-cursors { + position: relative; + z-index: 3; + visibility: hidden; +} + +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { + background: #d9d9d9; +} + +.CodeMirror-focused .CodeMirror-selected { + background: #d7d4f0; +} + +.CodeMirror-crosshair { + cursor: crosshair; +} + +.CodeMirror-line::selection, +.CodeMirror-line > span::selection, +.CodeMirror-line > span > span::selection { + background: #d7d4f0; +} + +.cm-searching { + background-color: #ffa; + background-color: rgb(255 255 0 / 40%); +} + +/* Used to force a border model for a node */ +.cm-force-border { + padding-right: 0.1px; +} + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack::after { + content: ''; +} + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { + background: none; +} diff --git a/apps/vben5/packages/@abp/components/src/codemirror/codemirror.ts b/apps/vben5/packages/@abp/components/src/codemirror/codemirror.ts new file mode 100644 index 000000000..ad87e70b7 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codemirror/codemirror.ts @@ -0,0 +1,21 @@ +import './codemirror.css'; +import 'codemirror/theme/idea.css'; +import 'codemirror/theme/material-palenight.css'; +// import 'codemirror/addon/lint/lint.css'; + +// modes +import 'codemirror/mode/javascript/javascript'; +import 'codemirror/mode/css/css'; +import 'codemirror/mode/htmlmixed/htmlmixed'; +// addons +// import 'codemirror/addon/edit/closebrackets'; +// import 'codemirror/addon/edit/closetag'; +// import 'codemirror/addon/comment/comment'; +// import 'codemirror/addon/fold/foldcode'; +// import 'codemirror/addon/fold/foldgutter'; +// import 'codemirror/addon/fold/brace-fold'; +// import 'codemirror/addon/fold/indent-fold'; +// import 'codemirror/addon/lint/json-lint'; +// import 'codemirror/addon/fold/comment-fold'; + +export { default as CodeMirror } from 'codemirror'; diff --git a/apps/vben5/packages/@abp/components/src/codemirror/index.ts b/apps/vben5/packages/@abp/components/src/codemirror/index.ts new file mode 100644 index 000000000..3898fc040 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codemirror/index.ts @@ -0,0 +1,2 @@ +export { default as CodeMirror } from './CodeMirror.vue'; +export * from './types'; diff --git a/apps/vben5/packages/@abp/components/src/codemirror/types.ts b/apps/vben5/packages/@abp/components/src/codemirror/types.ts new file mode 100644 index 000000000..1b7e3e32a --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/codemirror/types.ts @@ -0,0 +1,5 @@ +export enum MODE { + HTML = 'htmlmixed', + JS = 'javascript', + JSON = 'application/json', +} diff --git a/apps/vben5/packages/@abp/components/src/tinymce/Editor.vue b/apps/vben5/packages/@abp/components/src/tinymce/Editor.vue new file mode 100644 index 000000000..a43236ec1 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/tinymce/Editor.vue @@ -0,0 +1,312 @@ + + + + + + + + + + diff --git a/apps/vben5/packages/@abp/components/src/tinymce/helper.ts b/apps/vben5/packages/@abp/components/src/tinymce/helper.ts new file mode 100644 index 000000000..6b331df4e --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/tinymce/helper.ts @@ -0,0 +1,85 @@ +const validEvents = new Set([ + 'onActivate', + 'onAddUndo', + 'onBeforeAddUndo', + 'onBeforeExecCommand', + 'onBeforeGetContent', + 'onBeforePaste', + 'onBeforeRenderUI', + 'onBeforeSetContent', + 'onBlur', + 'onChange', + 'onClearUndos', + 'onClick', + 'onContextMenu', + 'onCopy', + 'onCut', + 'onDblclick', + 'onDeactivate', + 'onDirty', + 'onDrag', + 'onDragDrop', + 'onDragEnd', + 'onDragGesture', + 'onDragOver', + 'onDrop', + 'onExecCommand', + 'onFocus', + 'onFocusIn', + 'onFocusOut', + 'onGetContent', + 'onHide', + 'onInit', + 'onKeyDown', + 'onKeyPress', + 'onKeyUp', + 'onLoadContent', + 'onMouseDown', + 'onMouseEnter', + 'onMouseLeave', + 'onMouseMove', + 'onMouseOut', + 'onMouseOver', + 'onMouseUp', + 'onNodeChange', + 'onObjectResized', + 'onObjectResizeStart', + 'onObjectSelected', + 'onPaste', + 'onPostProcess', + 'onPostRender', + 'onPreProcess', + 'onProgressState', + 'onRedo', + 'onRemove', + 'onReset', + 'onSaveContent', + 'onSelectionChange', + 'onSetAttrib', + 'onSetContent', + 'onShow', + 'onSubmit', + 'onUndo', + 'onVisualAid', +]); + +const isValidKey = (key: string) => validEvents.has(key); + +export const bindHandlers = ( + initEvent: Event, + listeners: any, + editor: any, +): void => { + Object.keys(listeners) + .filter((key) => isValidKey(key)) + .forEach((key: string) => { + const handler = listeners[key]; + if (typeof handler === 'function') { + if (key === 'onInit') { + handler(initEvent, editor); + } else { + editor.on(key.slice(2), (e: any) => handler(e, editor)); + } + } + }); +}; diff --git a/apps/vben5/packages/@abp/components/src/tinymce/index.ts b/apps/vben5/packages/@abp/components/src/tinymce/index.ts new file mode 100644 index 000000000..5f4575450 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/tinymce/index.ts @@ -0,0 +1 @@ +export { default as Tinymce } from './Editor.vue'; diff --git a/apps/vben5/packages/@abp/components/src/tinymce/tinymce.ts b/apps/vben5/packages/@abp/components/src/tinymce/tinymce.ts new file mode 100644 index 000000000..1374b4dab --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/tinymce/tinymce.ts @@ -0,0 +1,13 @@ +// Any plugins you want to setting has to be imported +// Detail plugins list see https://www.tinymce.com/docs/plugins/ +// Custom builds see https://www.tinymce.com/download/custom-builds/ +// colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration + +export const plugins = [ + 'advlist anchor autolink autosave code codesample directionality fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus template textpattern visualblocks visualchars wordcount', +]; + +export const toolbar = [ + 'fontsizeselect lineheight searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', + 'hr bullist numlist link preview anchor pagebreak insertdatetime media forecolor backcolor fullscreen', +]; diff --git a/apps/vben5/packages/@abp/components/src/tinymce/useTinymce.ts b/apps/vben5/packages/@abp/components/src/tinymce/useTinymce.ts new file mode 100644 index 000000000..0857db940 --- /dev/null +++ b/apps/vben5/packages/@abp/components/src/tinymce/useTinymce.ts @@ -0,0 +1,13 @@ +let unique = 0; +export function useTinymce() { + function buildShortUUID(prefix = ''): string { + const time = Date.now(); + const random = Math.floor(Math.random() * 1_000_000_000); + unique++; + return `${prefix}_${random}${unique}${String(time)}`; + } + + return { + buildShortUUID, + }; +} diff --git a/apps/vben5/packages/@abp/components/tsconfig.json b/apps/vben5/packages/@abp/components/tsconfig.json new file mode 100644 index 000000000..ce1a891fb --- /dev/null +++ b/apps/vben5/packages/@abp/components/tsconfig.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@vben/tsconfig/web.json", + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/apps/vben5/packages/@abp/core/package.json b/apps/vben5/packages/@abp/core/package.json index 7ffa6d8e4..2ec3857eb 100644 --- a/apps/vben5/packages/@abp/core/package.json +++ b/apps/vben5/packages/@abp/core/package.json @@ -1,6 +1,6 @@ { "name": "@abp/core", - "version": "8.3.2", + "version": "9.0.4", "homepage": "https://github.com/colinin/abp-next-admin", "bugs": "https://github.com/colinin/abp-next-admin/issues", "repository": { @@ -35,8 +35,14 @@ } }, "dependencies": { + "@vueuse/core": "catalog:", "dayjs": "catalog:", + "lodash.merge": "catalog:", "pinia": "catalog:", + "pinia-plugin-persistedstate": "catalog:", "vue": "catalog:" + }, + "devDependencies": { + "@types/lodash.merge": "catalog:" } } diff --git a/apps/vben5/packages/@abp/core/src/constants/events.ts b/apps/vben5/packages/@abp/core/src/constants/events.ts new file mode 100644 index 000000000..eb2360775 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/constants/events.ts @@ -0,0 +1,10 @@ +export const Events = { + /** 收到服务器消息 */ + GetNotification: 'get-notification', + /** 新通知消息 */ + NotificationRecevied: 'sys_notifications_recevied', + /** 用户登录事件 */ + UserLogin: 'sys_user_login', + /** 用户登出事件 */ + UserLogout: 'sys_user_logout', +}; diff --git a/apps/vben5/packages/@abp/core/src/constants/index.ts b/apps/vben5/packages/@abp/core/src/constants/index.ts new file mode 100644 index 000000000..b624aad55 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/constants/index.ts @@ -0,0 +1,2 @@ +export * from './events'; +export * from './validation'; diff --git a/apps/vben5/packages/@abp/core/src/constants/validation.ts b/apps/vben5/packages/@abp/core/src/constants/validation.ts new file mode 100644 index 000000000..27680e687 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/constants/validation.ts @@ -0,0 +1,46 @@ +export const ValidationEnum = { + DoNotMatch: "'{0}' and '{1}' do not match.", + FieldDoNotValidCreditCardNumber: + 'The {0} field is not a valid credit card number.', + FieldDoNotValidEmailAddress: 'The {0} field is not a valid e-mail address.', + FieldDoNotValidFullyQualifiedUrl: + 'The {0} field is not a valid fully-qualified http, https, or ftp URL.', + FieldDoNotValidPhoneNumber: 'The {0} field is not a valid phone number.', + FieldInvalid: 'The field {0} is invalid.', + FieldIsNotValid: '{0} is not valid.', + FieldMustBeetWeen: 'The field {0} must be between {1} and {2}.', + FieldMustBeStringOrArrayWithMaximumLength: + "The field {0} must be a string or array type with a maximum length of '{1}'.", + FieldMustBeStringOrArrayWithMinimumLength: + "The field {0} must be a string or array type with a minimum length of '{1}'.", + FieldMustBeStringWithMaximumLength: + 'The field {0} must be a string with a maximum length of {1}.', + FieldMustBeStringWithMinimumLengthAndMaximumLength: + 'The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.', + FieldMustMatchRegularExpression: + "The field {0} must match the regular expression '{1}'.", + FieldOnlyAcceptsFilesExtensions: + 'The {0} field only accepts files with the following extensions: {1}', + FieldRequired: 'The {0} field is required.', + ThisFieldIsInvalid: 'ThisFieldIsInvalid.', + ThisFieldIsNotAValidCreditCardNumber: 'ThisFieldIsNotAValidCreditCardNumber.', + ThisFieldIsNotAValidEmailAddress: 'ThisFieldIsNotAValidEmailAddress.', + ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl: + 'ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl', + ThisFieldIsNotAValidPhoneNumber: 'ThisFieldIsNotAValidPhoneNumber.', + ThisFieldIsNotValid: 'ThisFieldIsNotValid.', + ThisFieldIsRequired: 'ThisFieldIsRequired.', + ThisFieldMustBeAStringOrArrayTypeWithAMaximumLength: + 'ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}', + ThisFieldMustBeAStringOrArrayTypeWithAMinimumLength: + 'ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}', + ThisFieldMustBeAStringWithAMaximumLength: + 'ThisFieldMustBeAStringWithAMaximumLengthOf{0}', + ThisFieldMustBeAStringWithAMinimumLengthAndAMaximumLength: + 'ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}', + ThisFieldMustBeBetween: 'ThisFieldMustBeBetween{0}And{1}', + ThisFieldMustMatchTheRegularExpression: + 'ThisFieldMustMatchTheRegularExpression{0}', + ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions: + 'ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}', +}; diff --git a/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireAuthenticatedSimpleStateChecker.ts b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireAuthenticatedSimpleStateChecker.ts new file mode 100644 index 000000000..83c370e56 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireAuthenticatedSimpleStateChecker.ts @@ -0,0 +1,42 @@ +import type { + CurrentUser, + IHasSimpleStateCheckers, + ISimpleStateChecker, + SimpleStateCheckerContext, +} from '../../types/global'; + +import { useAbpStore } from '../../store/abp'; + +export interface RequireAuthenticatedStateChecker { + name: string; +} + +export class RequireAuthenticatedSimpleStateChecker< + TState extends IHasSimpleStateCheckers, + > + implements RequireAuthenticatedStateChecker, ISimpleStateChecker +{ + _currentUser?: CurrentUser; + name = 'A'; + constructor(currentUser?: CurrentUser) { + this._currentUser = currentUser; + } + isEnabled(_context: SimpleStateCheckerContext): boolean { + return this._currentUser?.isAuthenticated ?? false; + } + + serialize(): string { + return JSON.stringify({ + T: this.name, + }); + } +} + +export function useRequireAuthenticatedSimpleStateChecker< + TState extends IHasSimpleStateCheckers, +>(): ISimpleStateChecker { + const abpStore = useAbpStore(); + return new RequireAuthenticatedSimpleStateChecker( + abpStore.application?.currentUser, + ); +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireFeaturesSimpleStateChecker.ts b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireFeaturesSimpleStateChecker.ts new file mode 100644 index 000000000..3a155dff3 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireFeaturesSimpleStateChecker.ts @@ -0,0 +1,59 @@ +import type { IFeatureChecker } from '../../types/features'; +import type { + IHasSimpleStateCheckers, + ISimpleStateChecker, + SimpleStateCheckerContext, +} from '../../types/global'; + +import { useFeatures } from '../useFeatures'; + +export interface RequireFeaturesStateChecker { + featureNames: string[]; + name: string; + requiresAll: boolean; +} + +export class RequireFeaturesSimpleStateChecker< + TState extends IHasSimpleStateCheckers, + > + implements RequireFeaturesStateChecker, ISimpleStateChecker +{ + _featureChecker: IFeatureChecker; + featureNames: string[]; + name: string = 'F'; + requiresAll: boolean; + constructor( + featureChecker: IFeatureChecker, + featureNames: string[], + requiresAll: boolean = false, + ) { + this._featureChecker = featureChecker; + this.featureNames = featureNames; + this.requiresAll = requiresAll; + } + isEnabled(_context: SimpleStateCheckerContext): boolean { + return this._featureChecker.isEnabled(this.featureNames, this.requiresAll); + } + + serialize(): string { + return JSON.stringify({ + A: this.requiresAll, + N: this.featureNames, + T: this.name, + }); + } +} + +export function useRequireFeaturesSimpleStateChecker< + TState extends IHasSimpleStateCheckers, +>( + featureNames: string[], + requiresAll: boolean = false, +): ISimpleStateChecker { + const featureChecker = useFeatures(); + return new RequireFeaturesSimpleStateChecker( + featureChecker, + featureNames, + requiresAll, + ); +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireGlobalFeaturesSimpleStateChecker.ts b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireGlobalFeaturesSimpleStateChecker.ts new file mode 100644 index 000000000..700ea5ee6 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireGlobalFeaturesSimpleStateChecker.ts @@ -0,0 +1,62 @@ +import type { IGlobalFeatureChecker } from '../../types/features'; +import type { + IHasSimpleStateCheckers, + ISimpleStateChecker, + SimpleStateCheckerContext, +} from '../../types/global'; + +import { useGlobalFeatures } from '../useGlobalFeatures'; + +export interface RequireGlobalFeaturesStateChecker { + featureNames: string[]; + name: string; + requiresAll: boolean; +} + +export class RequireGlobalFeaturesSimpleStateChecker< + TState extends IHasSimpleStateCheckers, + > + implements RequireGlobalFeaturesStateChecker, ISimpleStateChecker +{ + _globalFeatureChecker: IGlobalFeatureChecker; + featureNames: string[]; + name: string = 'G'; + requiresAll: boolean; + constructor( + globalFeatureChecker: IGlobalFeatureChecker, + featureNames: string[], + requiresAll: boolean = false, + ) { + this._globalFeatureChecker = globalFeatureChecker; + this.featureNames = featureNames; + this.requiresAll = requiresAll; + } + isEnabled(_context: SimpleStateCheckerContext): boolean { + return this._globalFeatureChecker.isEnabled( + this.featureNames, + this.requiresAll, + ); + } + + serialize(): string { + return JSON.stringify({ + A: this.requiresAll, + N: this.featureNames, + T: this.name, + }); + } +} + +export function useRequireGlobalFeaturesSimpleStateChecker< + TState extends IHasSimpleStateCheckers, +>( + featureNames: string[], + requiresAll: boolean = false, +): ISimpleStateChecker { + const globalFeatureChecker = useGlobalFeatures(); + return new RequireGlobalFeaturesSimpleStateChecker( + globalFeatureChecker, + featureNames, + requiresAll, + ); +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequirePermissionsSimpleStateChecker.ts b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequirePermissionsSimpleStateChecker.ts new file mode 100644 index 000000000..5040cbb1b --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequirePermissionsSimpleStateChecker.ts @@ -0,0 +1,123 @@ +import type { + IHasSimpleStateCheckers, + ISimpleBatchStateChecker, + ISimpleStateChecker, + SimpleBatchStateCheckerContext, + SimpleStateCheckerContext, + SimpleStateCheckerResult, +} from '../../types/global'; +import type { IPermissionChecker } from '../../types/permissions'; + +import { useAuthorization } from '../useAuthorization'; + +export class RequirePermissionsSimpleBatchStateCheckerModel< + TState extends IHasSimpleStateCheckers, +> { + permissions: string[]; + requiresAll: boolean; + state: TState; + constructor( + state: TState, + permissions: string[], + requiresAll: boolean = true, + ) { + this.state = state; + this.permissions = permissions; + this.requiresAll = requiresAll; + } +} + +export interface RequirePermissionsStateChecker< + TState extends IHasSimpleStateCheckers, +> { + model: RequirePermissionsSimpleBatchStateCheckerModel; + name: string; +} + +export class RequirePermissionsSimpleStateChecker< + TState extends IHasSimpleStateCheckers, + > + implements RequirePermissionsStateChecker, ISimpleStateChecker +{ + _permissionChecker: IPermissionChecker; + model: RequirePermissionsSimpleBatchStateCheckerModel; + name: string = 'P'; + constructor( + permissionChecker: IPermissionChecker, + model: RequirePermissionsSimpleBatchStateCheckerModel, + ) { + this.model = model; + this._permissionChecker = permissionChecker; + } + isEnabled(_context: SimpleStateCheckerContext): boolean { + return this._permissionChecker.isGranted( + this.model.permissions, + this.model.requiresAll, + ); + } + + serialize(): string { + return JSON.stringify({ + A: this.model.requiresAll, + N: this.model.permissions, + T: this.name, + }); + } +} + +export class RequirePermissionsSimpleBatchStateChecker< + TState extends IHasSimpleStateCheckers, +> implements ISimpleBatchStateChecker +{ + _permissionChecker: IPermissionChecker; + models: RequirePermissionsSimpleBatchStateCheckerModel[]; + name: string = 'P'; + constructor( + permissionChecker: IPermissionChecker, + models: RequirePermissionsSimpleBatchStateCheckerModel[], + ) { + this.models = models; + this._permissionChecker = permissionChecker; + } + isEnabled(context: SimpleBatchStateCheckerContext) { + const result = {} as SimpleStateCheckerResult; + context.states.forEach((state) => { + const model = this.models.find((x) => x.state === state); + if (model) { + result[model.state] = this._permissionChecker.isGranted( + model.permissions, + model.requiresAll, + ); + } + }); + return result; + } + + serialize(): string | undefined { + return undefined; + } +} + +export function useRequirePermissionsSimpleStateChecker< + TState extends IHasSimpleStateCheckers, +>( + model: RequirePermissionsSimpleBatchStateCheckerModel, +): ISimpleStateChecker { + const permissionChecker = useAuthorization(); + return new RequirePermissionsSimpleStateChecker( + permissionChecker, + model, + ); +} + +export function useRequirePermissionsSimpleBatchStateChecker< + TState extends IHasSimpleStateCheckers, +>( + models: RequirePermissionsSimpleBatchStateCheckerModel[], +): ISimpleBatchStateChecker { + const permissionChecker = useAuthorization(); + return new RequirePermissionsSimpleBatchStateChecker( + permissionChecker, + models, + ); +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/index.ts b/apps/vben5/packages/@abp/core/src/hooks/index.ts new file mode 100644 index 000000000..cf94b1a90 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/index.ts @@ -0,0 +1,10 @@ +export * from './useAuthorization'; +export * from './useEventBus'; +export * from './useFeatures'; +export * from './useGlobalFeatures'; +export * from './useLocalization'; +export * from './useLocalizationSerializer'; +export * from './useSettings'; +export * from './useSimpleStateCheck'; +export * from './useValidation'; +export * from './useWindowSizeFn'; diff --git a/apps/vben5/packages/@abp/core/src/hooks/useAuthorization.ts b/apps/vben5/packages/@abp/core/src/hooks/useAuthorization.ts new file mode 100644 index 000000000..af25aa55a --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useAuthorization.ts @@ -0,0 +1,36 @@ +import type { IPermissionChecker } from '../types/permissions'; + +import { computed } from 'vue'; + +import { useAbpStore } from '../store/abp'; + +export function useAuthorization(): IPermissionChecker { + const abpStore = useAbpStore(); + const getGrantedPolicies = computed(() => { + return abpStore.application?.auth.grantedPolicies ?? {}; + }); + + function isGranted(name: string | string[], requiresAll?: boolean): boolean { + const grantedPolicies = getGrantedPolicies.value; + if (Array.isArray(name)) { + if (requiresAll === undefined || requiresAll === true) { + return name.every((name) => grantedPolicies[name]); + } + return name.some((name) => grantedPolicies[name]); + } + return grantedPolicies[name] ?? false; + } + + function authorize(name: string | string[]): void { + if (!isGranted(name)) { + throw new Error( + `Authorization failed! Given policy has not granted: ${name}`, + ); + } + } + + return { + authorize, + isGranted, + }; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useEventBus.ts b/apps/vben5/packages/@abp/core/src/hooks/useEventBus.ts new file mode 100644 index 000000000..a3339d12a --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useEventBus.ts @@ -0,0 +1,30 @@ +import type { EventType, Handler, WildcardHandler } from '../utils/mitt'; + +import mitt from '../utils/mitt'; + +const emitter = mitt(); + +interface EventBus { + /** 发布事件 */ + publish(type: '*', event?: any): void; + /** 发布事件 */ + publish(type: EventType, event?: T): void; + + /** 订阅事件 */ + subscribe(type: '*', handler: WildcardHandler): void; + /** 订阅事件 */ + subscribe(type: EventType, handler: Handler): void; + + /** 退订事件 */ + unSubscribe(type: '*', handler: WildcardHandler): void; + /** 退订事件 */ + unSubscribe(type: EventType, handler: Handler): void; +} + +export function useEventBus(): EventBus { + return { + publish: emitter.emit, + subscribe: emitter.on, + unSubscribe: emitter.off, + }; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useFeatures.ts b/apps/vben5/packages/@abp/core/src/hooks/useFeatures.ts new file mode 100644 index 000000000..9b1048f3e --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useFeatures.ts @@ -0,0 +1,72 @@ +import type { FeatureValue, IFeatureChecker } from '../types/features'; + +import { ref, watch } from 'vue'; + +import { useAbpStore } from '../store/abp'; + +export function useFeatures(): IFeatureChecker { + const abpStore = useAbpStore(); + + const features = ref([]); + + watch( + () => abpStore.application, + (application) => { + if (!application?.features.values) { + features.value = []; + return; + } + const featuresSet: FeatureValue[] = []; + Object.keys(application.features.values).forEach((name) => { + if (application.features.values[name]) { + featuresSet.push({ + name, + value: application.features.values[name], + }); + } + }); + features.value = featuresSet; + }, + { + deep: true, + immediate: true, + }, + ); + + function get(name: string): FeatureValue | undefined { + return features.value.find((feature) => name === feature.name); + } + + function _isEnabled(name: string): boolean { + const setting = get(name); + return setting?.value.toLowerCase() === 'true'; + } + + const featureChecker: IFeatureChecker = { + getOrEmpty(name: string) { + return get(name)?.value ?? ''; + }, + + isEnabled(featureNames: string | string[], requiresAll?: boolean) { + if (Array.isArray(featureNames)) { + if (featureNames.length === 0) return true; + if (requiresAll === undefined || requiresAll === true) { + for (const featureName of featureNames) { + if (!_isEnabled(featureName)) return false; + } + return true; + } + + for (const featureName of featureNames) { + if (_isEnabled(featureName)) return true; + } + } else { + return _isEnabled(featureNames); + } + + return false; + }, + }; + + return featureChecker; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useGlobalFeatures.ts b/apps/vben5/packages/@abp/core/src/hooks/useGlobalFeatures.ts new file mode 100644 index 000000000..49149a3ca --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useGlobalFeatures.ts @@ -0,0 +1,52 @@ +import { computed } from 'vue'; + +import { useAbpStore } from '../store/abp'; +import { isNullOrWhiteSpace } from '../utils/string'; + +export function useGlobalFeatures() { + const abpStore = useAbpStore(); + const getGlobalFeatures = computed(() => { + if (!abpStore.application) { + return []; + } + const enabledFeatures = + abpStore.application.globalFeatures.enabledFeatures ?? []; + return enabledFeatures; + }); + + function get(name: string): string | undefined { + return getGlobalFeatures.value.find((feature) => name === feature); + } + + function _isEnabled(name: string): boolean { + const feature = get(name); + return !isNullOrWhiteSpace(feature); + } + + function isEnabled( + featureNames: string | string[], + requiresAll?: boolean, + ): boolean { + if (Array.isArray(featureNames)) { + if (featureNames.length === 0) return true; + if (requiresAll === undefined || requiresAll === true) { + for (const featureName of featureNames) { + if (!_isEnabled(featureName)) return false; + } + return true; + } + + for (const featureName of featureNames) { + if (_isEnabled(featureName)) return true; + } + } else { + return _isEnabled(featureNames); + } + + return false; + } + + return { + isEnabled, + }; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useLocalization.ts b/apps/vben5/packages/@abp/core/src/hooks/useLocalization.ts new file mode 100644 index 000000000..a9e21b08d --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useLocalization.ts @@ -0,0 +1,89 @@ +import type { Dictionary, StringLocalizer } from '../types'; + +import { computed, ref, watch } from 'vue'; + +import merge from 'lodash.merge'; + +import { useAbpStore } from '../store/abp'; +import { format } from '../utils/string'; + +export function useLocalization(resourceNames?: string | string[]) { + const abpStore = useAbpStore(); + + const localizations = ref>>({}); + + watch( + () => abpStore.localization, + (localization) => { + if (!localization?.resources) { + localizations.value = {}; + return; + } + const localizationResource: Dictionary< + string, + Dictionary + > = {}; + Object.keys(localization.resources).forEach((resourceName) => { + if (localization.resources[resourceName]) { + localizationResource[resourceName] = + localization.resources[resourceName].texts; + } + }); + localizations.value = localizationResource; + }, + { + deep: true, + immediate: true, + }, + ); + + const getResource = computed(() => { + let resource: { [key: string]: string } = {}; + if (resourceNames) { + if (Array.isArray(resourceNames)) { + resourceNames.forEach((name) => { + resource = merge(resource, localizations.value[name]); + }); + } else { + resource = merge(resource, localizations.value[resourceNames]); + } + } else { + Object.keys(localizations.value).forEach((rs) => { + resource = merge(resource, localizations.value[rs]); + }); + } + + return resource; + }); + const getResourceByName = computed(() => { + return (resource: string): Dictionary => { + return localizations.value[resource] ?? {}; + }; + }); + + function L(key: string, args?: any[] | Record | undefined) { + if (!key) return ''; + if (!getResource.value) return key; + if (!getResource.value[key]) return key; + return format(getResource.value[key], args ?? []); + } + + function Lr( + resource: string, + key: string, + args?: any[] | Record | undefined, + ) { + if (!key) return ''; + const findResource = getResourceByName.value(resource); + if (!findResource) return key; + if (!findResource[key]) return key; + return format(findResource[key], args ?? []); + } + + const localizer: StringLocalizer = { + L, + Lr, + }; + + return { L, localizer, Lr }; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useLocalizationSerializer.ts b/apps/vben5/packages/@abp/core/src/hooks/useLocalizationSerializer.ts new file mode 100644 index 000000000..7b37a5008 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useLocalizationSerializer.ts @@ -0,0 +1,109 @@ +import type { LocalizableStringInfo } from '../types'; + +import { isNullOrWhiteSpace } from '../utils/string'; + +interface ValidateOptions { + required?: boolean; +} + +interface ILocalizableStringSerializer { + deserialize(value?: string): LocalizableStringInfo; + serialize(value?: LocalizableStringInfo): string; + validate(value?: string, opt?: ValidateOptions): boolean; +} + +export function useLocalizationSerializer(): ILocalizableStringSerializer { + function Validate(value?: string, opt?: ValidateOptions): boolean { + if (!value || isNullOrWhiteSpace(value)) { + if (!opt || opt.required === undefined || opt.required === true) { + return false; + } + return true; + } + if (value.length < 3 || value[1] !== ':') { + return false; + } + const type = value[0]; + switch (type) { + case 'F': { + return !isNullOrWhiteSpace(value.slice(2).trim()); + } + case 'L': { + const commaPosition = value.indexOf(',', 2); + if (commaPosition === -1) { + return false; + } + const name = value.slice(Math.max(0, commaPosition + 1)); + if (isNullOrWhiteSpace(name)) { + return false; + } + return true; + } + default: { + return false; + } + } + } + + function Serialize(value?: LocalizableStringInfo): string { + if (!value) return ''; + return `L:${value.resourceName},${value.name}`; + } + + function Deserialize(value?: string): LocalizableStringInfo { + if (!value || isNullOrWhiteSpace(value)) { + return { + name: '', + resourceName: '', + }; + } + if (value.length < 2 || value[1] !== ':') { + return { + name: value, + resourceName: '', + }; + } + const type = value[0]; + switch (type) { + case 'F': { + return { + name: value.slice(2), + resourceName: 'Fixed', + }; + } + case 'L': { + const commaPosition = value.indexOf(',', 2); + if (commaPosition === -1) { + return { + name: value, + resourceName: 'Default', + }; + } + const resourceName = value.slice(2, commaPosition); + const name = value.slice(Math.max(0, commaPosition + 1)); + if (isNullOrWhiteSpace(resourceName)) { + return { + name: value, + resourceName: 'Default', + }; + } + return { + name, + resourceName, + }; + } + default: { + return { + name: value, + resourceName: 'Default', + }; + } + } + } + + return { + deserialize: Deserialize, + serialize: Serialize, + validate: Validate, + }; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useSettings.ts b/apps/vben5/packages/@abp/core/src/hooks/useSettings.ts new file mode 100644 index 000000000..cca3d77e2 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useSettings.ts @@ -0,0 +1,74 @@ +import type { ISettingProvider, SettingValue } from '../types/settings'; + +import { ref, watch } from 'vue'; + +import { useAbpStore } from '../store'; + +export function useSettings(): ISettingProvider { + const abpStore = useAbpStore(); + + const settings = ref([]); + + watch( + () => abpStore.application, + (application) => { + if (!application?.setting.values) { + settings.value = []; + return; + } + const settingsSet: SettingValue[] = []; + Object.keys(application.setting.values).forEach((name) => { + if (application.setting.values[name]) { + settingsSet.push({ + name, + value: application.setting.values[name], + }); + } + }); + settings.value = settingsSet; + }, + { + deep: true, + immediate: true, + }, + ); + + function get(name: string): SettingValue | undefined { + return settings.value.find((setting) => name === setting.name); + } + + function getAll(...names: string[]): SettingValue[] { + if (names) { + return settings.value.filter((setting) => names.includes(setting.name)); + } + return settings.value; + } + + function getOrDefault(name: string, defaultValue: T): string | T { + const setting = get(name); + if (!setting) { + return defaultValue; + } + return setting.value; + } + + const settingProvider: ISettingProvider = { + getAll(...names: string[]) { + return getAll(...names); + }, + getNumber(name: string, defaultValue: number = 0) { + const value = getOrDefault(name, defaultValue); + const num = Number(value); + return Number.isNaN(num) ? defaultValue : num; + }, + getOrEmpty(name: string) { + return getOrDefault(name, ''); + }, + isTrue(name: string) { + const value = getOrDefault(name, 'false'); + return value.toLowerCase() === 'true'; + }, + }; + + return settingProvider; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useSimpleStateCheck.ts b/apps/vben5/packages/@abp/core/src/hooks/useSimpleStateCheck.ts new file mode 100644 index 000000000..68f811602 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useSimpleStateCheck.ts @@ -0,0 +1,133 @@ +import type { + IHasSimpleStateCheckers, + ISimpleStateChecker, + ISimpleStateCheckerSerializer, +} from '../types/global'; + +import { isNullOrUnDef } from '../utils/is'; +import { isNullOrWhiteSpace } from '../utils/string'; +import { useRequireAuthenticatedSimpleStateChecker } from './SimpleStateChecking/useRequireAuthenticatedSimpleStateChecker'; +import { useRequireFeaturesSimpleStateChecker } from './SimpleStateChecking/useRequireFeaturesSimpleStateChecker'; +import { useRequireGlobalFeaturesSimpleStateChecker } from './SimpleStateChecking/useRequireGlobalFeaturesSimpleStateChecker'; +import { useRequirePermissionsSimpleStateChecker } from './SimpleStateChecking/useRequirePermissionsSimpleStateChecker'; + +class SimpleStateCheckerSerializer implements ISimpleStateCheckerSerializer { + deserialize>( + jsonObject: any, + state: TState, + ): ISimpleStateChecker | undefined { + if (isNullOrUnDef(jsonObject) || !Reflect.has(jsonObject, 'T')) { + return undefined; + } + switch (String(jsonObject.T)) { + case 'A': { + return useRequireAuthenticatedSimpleStateChecker(); + } + case 'F': { + const features = jsonObject.N as string[]; + if (features === undefined) { + throw new Error( + `'N' is not an array in the serialized state checker! JsonObject: ${ + jsonObject + }`, + ); + } + return useRequireFeaturesSimpleStateChecker( + features, + jsonObject.A === true, + ); + } + case 'G': { + const globalFeatures = jsonObject.N as string[]; + if (globalFeatures === undefined) { + throw new Error( + `'N' is not an array in the serialized state checker! JsonObject: ${ + jsonObject + }`, + ); + } + return useRequireGlobalFeaturesSimpleStateChecker( + globalFeatures, + jsonObject.A === true, + ); + } + case 'P': { + const permissions = jsonObject.N as string[]; + if (permissions === undefined) { + throw new Error( + `'N' is not an array in the serialized state checker! JsonObject: ${ + jsonObject + }`, + ); + } + return useRequirePermissionsSimpleStateChecker({ + permissions, + requiresAll: jsonObject.A === true, + state, + }); + } + default: { + return undefined; + } + } + } + + deserializeArray>( + value: string, + state: TState, + ): ISimpleStateChecker[] { + if (isNullOrWhiteSpace(value)) return []; + const jsonObject = JSON.parse(value); + if (isNullOrUnDef(jsonObject)) return []; + if (Array.isArray(jsonObject)) { + if (jsonObject.length === 0) return []; + return jsonObject + .map((json) => this.deserialize(json, state)) + .filter((checker) => !isNullOrUnDef(checker)) + .map((checker) => checker); + } + const stateChecker = this.deserialize(jsonObject, state); + if (!stateChecker) return []; + return [stateChecker]; + } + + serialize>( + checker: ISimpleStateChecker, + ): string | undefined { + return checker.serialize(); + } + + serializeArray>( + stateCheckers: ISimpleStateChecker[], + ): string | undefined { + if (stateCheckers.length === 0) return undefined; + if (stateCheckers.length === 1) { + const stateChecker = stateCheckers[0]; + const single = stateChecker?.serialize(); + if (isNullOrUnDef(single)) return undefined; + return `[${single}]`; + } + let serializedCheckers: string = ''; + stateCheckers.forEach((checker) => { + const serializedChecker = checker.serialize(); + if (!isNullOrUnDef(serializedChecker)) { + serializedCheckers += `${serializedChecker},`; + } + }); + if (serializedCheckers.endsWith(',')) { + serializedCheckers = serializedCheckers.slice( + 0, + Math.max(0, serializedCheckers.length - 1), + ); + } + return serializedCheckers.length > 0 + ? `[${serializedCheckers}]` + : undefined; + } +} + +export function useSimpleStateCheck< + TState extends IHasSimpleStateCheckers, +>(): ISimpleStateCheckerSerializer { + return new SimpleStateCheckerSerializer(); +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useValidation.ts b/apps/vben5/packages/@abp/core/src/hooks/useValidation.ts new file mode 100644 index 000000000..afb24569e --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useValidation.ts @@ -0,0 +1,403 @@ +import type { RuleCreator } from '../types/rules'; +import type { + Field, + FieldBeetWeen, + FieldContains, + FieldDefineValidator, + FieldLength, + FieldMatch, + FieldRange, + FieldRegular, + FieldValidator, + Rule, + RuleType, +} from '../types/validations'; + +import { ValidationEnum } from '../constants'; +import { isEmail, isPhone } from '../utils/regex'; +import { useLocalization } from './useLocalization'; + +export function useValidation(): RuleCreator { + const { L } = useLocalization(['AbpValidation']); + function _getFieldName(field: Field) { + return __getFieldName( + field.name ?? '', + field.resourceName, + field.prefix, + field.connector, + ); + } + + function __getFieldName( + fieldName: string, + resourceName?: string, + prefix?: string, + connector?: string, + ) { + if (fieldName && resourceName) { + fieldName = prefix + ? `${prefix}${connector ?? ':'}${fieldName}` + : fieldName; + const { L: l } = useLocalization(resourceName); + return l(fieldName); + } + return fieldName; + } + + function _createRule(options: { + len?: number; + max?: number; + message?: string; + min?: number; + required?: boolean; + trigger?: 'blur' | 'change' | ['change', 'blur']; + type?: 'array' | RuleType; + validator?: ( + rule: any, + value: any, + callback: any, + source?: any, + options?: any, + ) => Promise | void; + }): Rule[] { + return [ + { + len: options.len, + max: options.max, + message: options.message, + min: options.min, + required: options.required, + trigger: options.trigger, + type: options.type, + validator: options.validator, + }, + ]; + } + + function _createValidator( + field: Field, + useNameEnum: string, + notNameEnum: string, + required?: boolean, + ): Rule { + const message = field.name + ? L(useNameEnum, [_getFieldName(field)]) + : L(notNameEnum); + return { + message, + required, + trigger: field.trigger, + type: field.type, + }; + } + + function _createLengthValidator( + field: FieldLength, + checkMaximum: boolean, + useNameEnum: string, + notNameEnum: string, + required?: boolean, + ): Rule { + const message = field.name + ? L(useNameEnum, [_getFieldName(field), field.length]) + : L(notNameEnum, [field.length]); + + function checkLength(value: any[] | string) { + return checkMaximum + ? field.length > value.length + : value.length > field.length; + } + + return { + message, + required, + trigger: field.trigger, + type: field.type, + validator: (_: any, value: string) => { + if (!checkLength(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }; + } + + function _createLengthRangValidator( + field: FieldRange, + useNameEnum: string, + notNameEnum: string, + required?: boolean, + ): Rule { + const message = field.name + ? L(useNameEnum, [_getFieldName(field), field.minimum, field.maximum]) + : L(notNameEnum, [field.minimum, field.maximum]); + return { + message, + required, + trigger: field.trigger, + type: field.type, + validator: (_: any, value: string) => { + if (value.length < field.minimum || value.length > field.maximum) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }; + } + + function _createBeetWeenValidator(field: FieldBeetWeen): Rule { + const message = field.name + ? L(ValidationEnum.FieldMustBeetWeen, [ + _getFieldName(field), + field.start, + field.end, + ]) + : L(ValidationEnum.ThisFieldMustBeBetween, [field.start, field.end]); + return { + message, + trigger: field.trigger, + validator: (_: any, value: number) => { + // beetween不在进行必输检查, 改为数字有效性检查 + if (Number.isNaN(value)) { + return Promise.reject(message); + } + return value < field.start || value > field.end + ? Promise.reject(message) + : Promise.resolve(); + }, + }; + } + + function _createRegularExpressionValidator( + field: FieldRegular, + required?: boolean, + ): Rule { + const message = field.name + ? L(ValidationEnum.FieldMustMatchRegularExpression, [ + _getFieldName(field), + field.expression, + ]) + : L(ValidationEnum.ThisFieldMustMatchTheRegularExpression, [ + field.expression, + ]); + return { + message, + pattern: new RegExp(field.expression), + required, + trigger: field.trigger, + type: field.type, + }; + } + + function _createEmailValidator(field: Field, required?: boolean): Rule { + const message = field.name + ? L(ValidationEnum.FieldDoNotValidEmailAddress, [_getFieldName(field)]) + : L(ValidationEnum.ThisFieldIsNotAValidEmailAddress); + return { + message, + required, + trigger: field.trigger, + type: field.type, + validator: (_: any, value: string) => { + if (!isEmail(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }; + } + + function _createPhoneValidator(field: Field, required?: boolean): Rule { + const message = field.name + ? L(ValidationEnum.FieldDoNotValidPhoneNumber, [_getFieldName(field)]) + : L(ValidationEnum.ThisFieldIsNotAValidPhoneNumber); + return { + message, + required, + trigger: field.trigger, + type: field.type, + validator: (_: any, value: string) => { + if (!isPhone(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }; + } + + const ruleCreator: RuleCreator = { + defineValidator(field: FieldDefineValidator) { + return _createRule(field); + }, + doNotMatch(field: FieldMatch) { + const message = L(ValidationEnum.DoNotMatch, [ + __getFieldName(field.name, field.resourceName, field.prefix), + __getFieldName(field.matchField, field.resourceName, field.prefix), + ]); + return _createRule({ + message, + required: field.required, + trigger: field.trigger, + type: field.type, + validator: (_, value: string) => { + if (value !== field.matchValue) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }); + }, + fieldDoNotValidCreditCardNumber(field: Field) { + if (field.name) { + return _createRule({ + message: L(ValidationEnum.FieldDoNotValidCreditCardNumber, [ + _getFieldName(field), + ]), + trigger: field.trigger, + type: field.type, + }); + } + return _createRule({ + message: L(ValidationEnum.ThisFieldIsNotAValidCreditCardNumber), + trigger: field.trigger, + type: field.type, + }); + }, + fieldDoNotValidEmailAddress(field: Field) { + return [_createEmailValidator(field)]; + }, + fieldDoNotValidFullyQualifiedUrl(field: Field) { + if (field.name) { + return _createRule({ + message: L(ValidationEnum.FieldDoNotValidFullyQualifiedUrl, [ + _getFieldName(field), + ]), + trigger: field.trigger, + type: field.type, + }); + } + return _createRule({ + message: L( + ValidationEnum.ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl, + ), + trigger: field.trigger, + type: field.type, + }); + }, + fieldDoNotValidPhoneNumber(field: Field) { + return [_createPhoneValidator(field)]; + }, + fieldInvalid(field: FieldValidator) { + const message = field.name + ? L(ValidationEnum.FieldInvalid, [_getFieldName(field)]) + : L(ValidationEnum.ThisFieldIsInvalid); + return _createRule({ + message, + required: field.required, + trigger: field.trigger, + type: field.type, + validator: (_, value: any) => { + if (!field.validator(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }); + }, + fieldIsNotValid(field: FieldValidator) { + const message = field.name + ? L(ValidationEnum.FieldIsNotValid, [_getFieldName(field)]) + : L(ValidationEnum.ThisFieldIsNotValid); + return _createRule({ + message, + required: field.required, + trigger: field.trigger, + type: field.type, + validator: (_, value: any) => { + if (field.validator(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }); + }, + fieldMustBeetWeen(field: FieldBeetWeen) { + return [_createBeetWeenValidator(field)]; + }, + fieldMustBeStringOrArrayWithMaximumLength(field: FieldLength) { + return [ + _createLengthValidator( + field, + true, + ValidationEnum.FieldMustBeStringOrArrayWithMaximumLength, + ValidationEnum.ThisFieldMustBeAStringOrArrayTypeWithAMaximumLength, + ), + ]; + }, + fieldMustBeStringOrArrayWithMinimumLength(field: FieldLength) { + return [ + _createLengthValidator( + field, + false, + ValidationEnum.FieldMustBeStringOrArrayWithMinimumLength, + ValidationEnum.ThisFieldMustBeAStringOrArrayTypeWithAMinimumLength, + ), + ]; + }, + fieldMustBeStringWithMaximumLength(field: FieldLength) { + return [ + _createLengthValidator( + field, + true, + ValidationEnum.FieldMustBeStringWithMaximumLength, + ValidationEnum.ThisFieldMustBeAStringWithAMaximumLength, + ), + ]; + }, + fieldMustBeStringWithMinimumLengthAndMaximumLength(field: FieldRange) { + return [ + _createLengthRangValidator( + field, + ValidationEnum.FieldMustBeStringWithMinimumLengthAndMaximumLength, + ValidationEnum.ThisFieldMustBeAStringWithAMinimumLengthAndAMaximumLength, + ), + ]; + }, + fieldMustMatchRegularExpression(field: FieldRegular) { + return [_createRegularExpressionValidator(field)]; + }, + fieldOnlyAcceptsFilesExtensions(field: FieldContains) { + const message = field.name + ? L(ValidationEnum.FieldOnlyAcceptsFilesExtensions, [ + _getFieldName(field), + field.value, + ]) + : L(ValidationEnum.ThisFieldMustMatchTheRegularExpression, [ + field.value, + ]); + return _createRule({ + message, + trigger: field.trigger, + type: field.type, + validator: (_, value: string) => { + if (!field.value.includes(value)) { + return Promise.reject(message); + } + return Promise.resolve(); + }, + }); + }, + fieldRequired(field: Field) { + return [ + _createValidator( + field, + ValidationEnum.FieldRequired, + ValidationEnum.ThisFieldIsRequired, + true, + ), + ]; + }, + }; + + return ruleCreator; +} diff --git a/apps/vben5/packages/@abp/core/src/hooks/useWindowSizeFn.ts b/apps/vben5/packages/@abp/core/src/hooks/useWindowSizeFn.ts new file mode 100644 index 000000000..9a617221a --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/hooks/useWindowSizeFn.ts @@ -0,0 +1,45 @@ +import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core'; + +interface WindowSizeOptions { + immediate?: boolean; + listenerOptions?: AddEventListenerOptions | boolean; + once?: boolean; +} + +interface Fn { + (...arg: T[]): R; +} + +export function useWindowSizeFn( + fn: Fn, + wait = 150, + options?: WindowSizeOptions, +) { + let handler = () => { + fn(); + }; + const handleSize = useDebounceFn(handler, wait); + handler = handleSize; + + const start = () => { + if (options && options.immediate) { + handler(); + } + window.addEventListener('resize', handler, { + passive: true, + }); + }; + + const stop = () => { + window.removeEventListener('resize', handler); + }; + + tryOnMounted(() => { + start(); + }); + + tryOnUnmounted(() => { + stop(); + }); + return [start, stop]; +} diff --git a/apps/vben5/packages/@abp/core/src/index.ts b/apps/vben5/packages/@abp/core/src/index.ts index 48ebf8d9a..067745944 100644 --- a/apps/vben5/packages/@abp/core/src/index.ts +++ b/apps/vben5/packages/@abp/core/src/index.ts @@ -1,3 +1,5 @@ +export * from './constants'; +export * from './hooks'; export * from './store'; export * from './types'; export * from './utils'; diff --git a/apps/vben5/packages/@abp/core/src/store/abp.ts b/apps/vben5/packages/@abp/core/src/store/abp.ts index 4134845b2..f17801928 100644 --- a/apps/vben5/packages/@abp/core/src/store/abp.ts +++ b/apps/vben5/packages/@abp/core/src/store/abp.ts @@ -7,54 +7,68 @@ import { ref } from 'vue'; import { acceptHMRUpdate, defineStore } from 'pinia'; -export const useAbpStore = defineStore('abp', () => { - const application = ref(); - const localization = ref(); - /** 获取 i18n 格式本地化文本 */ - function getI18nLocales() { - const abpLocales: Record = {}; - if (!localization.value) { +export const useAbpStore = defineStore( + 'abp', + () => { + const application = ref(); + const localization = ref(); + /** 获取 i18n 格式本地化文本 */ + function getI18nLocales() { + const abpLocales: Record = {}; + if (!localization.value) { + return abpLocales; + } + const resources = localization.value.resources; + // AbpValidation.The field {0} is invalid. + Object.keys(resources).forEach((resource) => { + // resource --> AbpValidation + const resourceLocales: Record = {}; + const resourcesByName = resources[resource]; + if (resourcesByName) { + Object.keys(resourcesByName.texts).forEach((key) => { + // The field {0} is invalid. --> The field {0} is invalid_ + let localeKey = key.replaceAll('.', '_'); + // The field {0} is invalid. --> The field {0} is invalid + localeKey.endsWith('_') && + (localeKey = localeKey.slice( + 0, + Math.max(0, localeKey.length - 1), + )); + // _The field {0} is invalid --> The field {0} is invalid + localeKey.startsWith('_') && + (localeKey = localeKey.slice(0, Math.max(1, localeKey.length))); + resourceLocales[localeKey] = resourcesByName.texts[key]; + }); + abpLocales[resource] = resourceLocales; + } + }); return abpLocales; } - const resources = localization.value.resources; - // AbpValidation.The field {0} is invalid. - Object.keys(resources).forEach((resource) => { - // resource --> AbpValidation - const resourceLocales: Record = {}; - const resourcesByName = resources[resource]; - if (resourcesByName) { - Object.keys(resourcesByName.texts).forEach((key) => { - // The field {0} is invalid. --> The field {0} is invalid_ - let localeKey = key.replaceAll('.', '_'); - // The field {0} is invalid. --> The field {0} is invalid - localeKey.endsWith('_') && - (localeKey = localeKey.slice(0, Math.max(0, localeKey.length - 1))); - // _The field {0} is invalid --> The field {0} is invalid - localeKey.startsWith('_') && - (localeKey = localeKey.slice(0, Math.max(1, localeKey.length))); - resourceLocales[localeKey] = resourcesByName.texts[key]; - }); - abpLocales[resource] = resourceLocales; - } - }); - return abpLocales; - } - function setApplication(val: ApplicationConfigurationDto) { - application.value = val; - } + function setApplication(val: ApplicationConfigurationDto) { + application.value = val; + } - function setLocalization(val: ApplicationLocalizationDto) { - localization.value = val; - } + function setLocalization(val: ApplicationLocalizationDto) { + localization.value = val; + } + + function $reset() { + application.value = undefined; + } - return { - application, - getI18nLocales, - localization, - setApplication, - setLocalization, - }; -}); + return { + $reset, + application, + getI18nLocales, + localization, + setApplication, + setLocalization, + }; + }, + { + persist: true, + }, +); // 解决热更新问题 const hot = import.meta.hot; diff --git a/apps/vben5/packages/@abp/core/src/types/error.ts b/apps/vben5/packages/@abp/core/src/types/error.ts new file mode 100644 index 000000000..a51bf5d9e --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/error.ts @@ -0,0 +1,14 @@ +interface RemoteServiceValidationErrorInfo { + members: string[]; + message: string; +} + +interface RemoteServiceErrorInfo { + code?: string; + data?: Record; + details?: string; + message?: string; + validationErrors?: RemoteServiceValidationErrorInfo[]; +} + +export type { RemoteServiceErrorInfo }; diff --git a/apps/vben5/packages/@abp/core/src/types/features.ts b/apps/vben5/packages/@abp/core/src/types/features.ts new file mode 100644 index 000000000..d46b26a58 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/features.ts @@ -0,0 +1,27 @@ +import type { NameValue } from './global'; + +type FeatureValue = NameValue; + +/** + * 特性检查接口 + */ +interface IFeatureChecker { + /** + * 获取特性值 + * @param name 特性名称 + * @returns 返回设定的特性值,不存在则为空字符串 + */ + getOrEmpty(name: string): string; + /** + * 是否启用特性 + * @param featureNames 特性名称 + * @param requiresAll 是否全部符合 + */ + isEnabled(featureNames: string | string[], requiresAll?: boolean): boolean; +} + +interface IGlobalFeatureChecker { + isEnabled(featureNames: string | string[], requiresAll?: boolean): boolean; +} + +export type { FeatureValue, IFeatureChecker, IGlobalFeatureChecker }; diff --git a/apps/vben5/packages/@abp/core/src/types/global.ts b/apps/vben5/packages/@abp/core/src/types/global.ts index b0ab7d8b1..8da06034a 100644 --- a/apps/vben5/packages/@abp/core/src/types/global.ts +++ b/apps/vben5/packages/@abp/core/src/types/global.ts @@ -206,31 +206,35 @@ interface CurrentUser { userName: string; } -// eslint-disable-next-line no-use-before-define +interface IHasSimpleStateCheckers< + TState extends IHasSimpleStateCheckers, +> { + // eslint-disable-next-line no-use-before-define + stateCheckers: ISimpleStateChecker[]; +} + +type SimpleStateRecord< + TState extends IHasSimpleStateCheckers, + TValue, +> = { + [P in TState]: TValue; +}; + type SimpleStateCheckerResult> = - Map; + SimpleStateRecord; interface SimpleStateCheckerContext< - // eslint-disable-next-line no-use-before-define TState extends IHasSimpleStateCheckers, > { state: TState; } interface SimpleBatchStateCheckerContext< - // eslint-disable-next-line no-use-before-define TState extends IHasSimpleStateCheckers, > { states: TState[]; } -interface IHasSimpleStateCheckers< - TState extends IHasSimpleStateCheckers, -> { - // eslint-disable-next-line no-use-before-define - stateCheckers: ISimpleStateChecker[]; -} - interface ISimpleStateChecker> { isEnabled(context: SimpleStateCheckerContext): boolean; serialize(): string | undefined; diff --git a/apps/vben5/packages/@abp/core/src/types/index.ts b/apps/vben5/packages/@abp/core/src/types/index.ts index 56615902d..e31262935 100644 --- a/apps/vben5/packages/@abp/core/src/types/index.ts +++ b/apps/vben5/packages/@abp/core/src/types/index.ts @@ -1,2 +1,11 @@ export * from './dto'; +export * from './error'; +export * from './features'; export * from './global'; +export * from './localization'; +export * from './openid'; +export * from './permissions'; +export * from './rules'; +export * from './settings'; +export * from './table'; +export * from './validations'; diff --git a/apps/vben5/packages/@abp/core/src/types/localization.ts b/apps/vben5/packages/@abp/core/src/types/localization.ts new file mode 100644 index 000000000..19bebb7d9 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/localization.ts @@ -0,0 +1,10 @@ +interface StringLocalizer { + L(key: string, args?: any[] | Record | undefined): string; + Lr( + resource: string, + key: string, + args?: any[] | Record | undefined, + ): string; +} + +export type { StringLocalizer }; diff --git a/apps/vben5/packages/@abp/core/src/types/openid.ts b/apps/vben5/packages/@abp/core/src/types/openid.ts new file mode 100644 index 000000000..e5bfca3f8 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/openid.ts @@ -0,0 +1,28 @@ +interface OpenIdConfiguration { + authorization_endpoint: string; + backchannel_logout_session_supported: boolean; + backchannel_logout_supported: boolean; + check_session_iframe: string; + claims_supported: string[]; + code_challenge_methods_supported: string[]; + device_authorization_endpoint: string; + end_session_endpoint: string; + frontchannel_logout_session_supported: boolean; + frontchannel_logout_supported: boolean; + grant_types_supported: string[]; + id_token_signing_alg_values_supported: string[]; + introspection_endpoint: string; + issuer: string; + jwks_uri: string; + request_parameter_supported: boolean; + response_modes_supported: string[]; + response_types_supported: string[]; + revocation_endpoint: string; + scopes_supported: string[]; + subject_types_supported: string[]; + token_endpoint: string; + token_endpoint_auth_methods_supported: string[]; + userinfo_endpoint: string; +} + +export type { OpenIdConfiguration }; diff --git a/apps/vben5/packages/@abp/core/src/types/permissions.ts b/apps/vben5/packages/@abp/core/src/types/permissions.ts new file mode 100644 index 000000000..cfc062872 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/permissions.ts @@ -0,0 +1,6 @@ +interface IPermissionChecker { + authorize(name: string | string[]): void; + isGranted(name: string | string[], requiresAll?: boolean): boolean; +} + +export type { IPermissionChecker }; diff --git a/apps/vben5/packages/@abp/core/src/types/rules.ts b/apps/vben5/packages/@abp/core/src/types/rules.ts new file mode 100644 index 000000000..aef6ed573 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/rules.ts @@ -0,0 +1,50 @@ +import type { + Field, + FieldBeetWeen, + FieldContains, + FieldDefineValidator, + FieldLength, + FieldMatch, + FieldRange, + FieldRegular, + FieldValidator, + Rule, +} from './validations'; + +/** 规则创建器 */ +interface RuleCreator { + /** 自定义验证器 */ + defineValidator(field: FieldDefineValidator): Rule[]; + /** input 与 value 是否匹配 */ + doNotMatch(field: FieldMatch): Rule[]; + /** 字段{0}不是有效的信用卡号码 */ + fieldDoNotValidCreditCardNumber(field: Field): Rule[]; + /** 字段{0}不是有效的邮箱地址 */ + fieldDoNotValidEmailAddress(field: Field): Rule[]; + /** 字段{0}不是有效的完全限定的http,https或ftp URL. */ + fieldDoNotValidFullyQualifiedUrl(field: Field): Rule[]; + /** 字段{0}不是有效的手机号码 */ + fieldDoNotValidPhoneNumber(field: Field): Rule[]; + /** 字段是无效值 */ + fieldInvalid(field: FieldValidator): Rule[]; + /** 验证未通过 */ + fieldIsNotValid(field: FieldValidator): Rule[]; + /** 字段{0}值必须在{1}和{2}范围内 */ + fieldMustBeetWeen(field: FieldBeetWeen): Rule[]; + /** 字段{0}必须是最大长度为'{1}'的字符串或数组 */ + fieldMustBeStringOrArrayWithMaximumLength(field: FieldLength): Rule[]; + /** 字段{0}必须是最小长度为'{1}'的字符串或数组 */ + fieldMustBeStringOrArrayWithMinimumLength(field: FieldLength): Rule[]; + /** 字段{0}必须是最大长度为{1}的字符串 */ + fieldMustBeStringWithMaximumLength(field: FieldLength): Rule[]; + /** 字段{0}必须是最小长度为{2}并且最大长度{1}的字符串 */ + fieldMustBeStringWithMinimumLengthAndMaximumLength(field: FieldRange): Rule[]; + /** 字段{0}与正则表达式不匹配 */ + fieldMustMatchRegularExpression(field: FieldRegular): Rule[]; + /** {0}字段只允许以下扩展名的文件: {1} */ + fieldOnlyAcceptsFilesExtensions(field: FieldContains): Rule[]; + /** 字段{0}不可为空 */ + fieldRequired(field: Field): Rule[]; +} + +export type { RuleCreator }; diff --git a/apps/vben5/packages/@abp/core/src/types/settings.ts b/apps/vben5/packages/@abp/core/src/types/settings.ts new file mode 100644 index 000000000..c00bdfc97 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/settings.ts @@ -0,0 +1,31 @@ +import type { NameValue } from './global'; + +type SettingValue = NameValue; +/** + * 设置接口 + */ +interface ISettingProvider { + /** + * 获取设定值结合 + * @param names 过滤的设置名称 + */ + getAll(...names: string[]): SettingValue[]; + /** + * 查询 number 类型设定值 + * @param name 设置名称 + * @returns 返回类型为 number 的设定值, 默认0 + */ + getNumber(name: string): number; + /** + * 获取设定值,如果为空返回空字符串 + * @param name 设置名称 + */ + getOrEmpty(name: string): string; + /** + * 查询 boolean 类型设定值 + * @param name 设置名称 + */ + isTrue(name: string): boolean; +} + +export type { ISettingProvider, SettingValue }; diff --git a/apps/vben5/packages/@abp/core/src/types/table.ts b/apps/vben5/packages/@abp/core/src/types/table.ts new file mode 100644 index 000000000..9d76b4da6 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/table.ts @@ -0,0 +1,3 @@ +type SortOrder = '' | 'asc' | 'desc' | null; + +export type { SortOrder }; diff --git a/apps/vben5/packages/@abp/core/src/types/validations.ts b/apps/vben5/packages/@abp/core/src/types/validations.ts new file mode 100644 index 000000000..4f4a10657 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/types/validations.ts @@ -0,0 +1,112 @@ +type RuleType = + | 'boolean' + | 'date' + | 'email' + | 'enum' + | 'float' + | 'hex' + | 'integer' + | 'method' + | 'number' + | 'object' + | 'regexp' + | 'string' + | 'url'; + +interface Rule { + [key: string]: any; + trigger?: 'blur' | 'change' | ['change', 'blur']; + type?: 'array' | RuleType; +} + +interface Field extends Rule { + /** 连接符 + * @description 用于本地化字段名称时的连接字符 + * @example . => L('ResourceName.DisplayName.Field') + * @example : => L('ResourceName.DisplayName:Field') + */ + connector?: string; + /** 字段名称 */ + name?: string; + /** 字段前缀 + * @description 用于本地化字段名称 + * @example DisplayName => L('ResourceName.DisplayName:Field') + */ + prefix?: string; + /** 本地化资源 */ + resourceName?: string; +} + +interface FieldRequired extends Field { + /** 是否必须 */ + required?: boolean; +} + +interface FieldBeetWeen extends Field { + /** 结束值 */ + end: number; + /** 起始值 */ + start: number; +} + +interface FieldLength extends Field { + /** 长度 */ + length: number; +} + +interface FieldRange extends Field { + /** 最大数值 */ + maximum: number; + /** 最小数值 */ + minimum: number; +} + +interface FieldRegular extends Field { + /** 正则表达式 */ + expression: string; +} + +interface FieldMatch extends FieldRequired { + /** 对比字段 */ + matchField: string; + /** 对比字段值 */ + matchValue: string; + /** 字段名称 */ + name: string; +} + +interface FieldContains extends Field { + /** 验证的值中是否包含在定义的值中 */ + value: string; +} + +interface FieldValidator extends FieldRequired { + /** 值是否有效验证器 */ + validator: (value: any) => boolean; +} + +interface FieldDefineValidator extends FieldRequired { + message?: string; + validator: ( + rule: any, + value: any, + callback: any, + source?: any, + options?: any, + ) => Promise | void; +} + +export type { + Field, + FieldBeetWeen, + FieldContains, + FieldDefineValidator, + FieldLength, + FieldMatch, + FieldRange, + FieldRegular, + FieldRequired, + FieldValidator, + Rule, + RuleType, +}; diff --git a/apps/vben5/packages/@abp/core/src/utils/index.ts b/apps/vben5/packages/@abp/core/src/utils/index.ts index 61cf91f96..2109114a1 100644 --- a/apps/vben5/packages/@abp/core/src/utils/index.ts +++ b/apps/vben5/packages/@abp/core/src/utils/index.ts @@ -1,2 +1,5 @@ export * from './date'; +export * from './mitt'; +export * from './regex'; +export * from './string'; export * from './tree'; diff --git a/apps/vben5/packages/@abp/core/src/utils/is.ts b/apps/vben5/packages/@abp/core/src/utils/is.ts new file mode 100644 index 000000000..c760f4afa --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/utils/is.ts @@ -0,0 +1,19 @@ +export function isNullAndUnDef(val: unknown): val is null | undefined { + return isUnDef(val) && isNull(val); +} + +export function isNullOrUnDef(val: unknown): val is null | undefined { + return isUnDef(val) || isNull(val); +} + +export function isDef(val?: T): val is T { + return val !== undefined; +} + +export function isUnDef(val?: T): val is T { + return !isDef(val); +} + +export function isNull(value: any): value is null { + return value === null; +} diff --git a/apps/vben5/packages/@abp/core/src/utils/mitt.ts b/apps/vben5/packages/@abp/core/src/utils/mitt.ts new file mode 100644 index 000000000..28668e4d2 --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/utils/mitt.ts @@ -0,0 +1,107 @@ +/* eslint-disable array-callback-return */ +/** + * copy to https://github.com/developit/mitt + * Expand clear method + */ + +export type EventType = string | symbol; + +// An event handler can take an optional event argument +// and should not return a value +export type Handler = (event?: T) => void; +export type WildcardHandler = (type: EventType, event?: any) => void; + +// An array of all currently registered event handlers for a type +export type EventHandlerList = Array; +export type WildCardEventHandlerList = Array; + +// A map of event types and their corresponding event handlers. +export type EventHandlerMap = Map< + EventType, + EventHandlerList | WildCardEventHandlerList +>; + +export interface Emitter { + all: EventHandlerMap; + + clear(): void; + emit(type: '*', event?: any): void; + + emit(type: EventType, event?: T): void; + off(type: '*', handler: WildcardHandler): void; + + off(type: EventType, handler: Handler): void; + on(type: '*', handler: WildcardHandler): void; + on(type: EventType, handler: Handler): void; +} + +/** + * Mitt: Tiny (~200b) functional event emitter / pubsub. + * @name mitt + * @returns {Mitt} Emitter + */ +export default function mitt(all?: EventHandlerMap): Emitter { + all = all || new Map(); + + return { + /** + * A Map of event names to registered handler functions. + */ + all, + + /** + * Clear all + */ + clear() { + this.all.clear(); + }, + + /** + * Invoke all handlers for the given type. + * If present, `"*"` handlers are invoked after type-matched handlers. + * + * Note: Manually firing "*" handlers is not supported. + * + * @param {string|symbol} type The event type to invoke + * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler + * @memberOf mitt + */ + emit(type: EventType, evt: T) { + [...((all?.get(type) || []) as EventHandlerList)].map((handler) => { + handler(evt); + }); + [...((all?.get('*') || []) as WildCardEventHandlerList)].map( + (handler) => { + handler(type, evt); + }, + ); + }, + + /** + * Remove an event handler for the given type. + * @param {string|symbol} type Type of event to unregister `handler` from, or `"*"` + * @param {Function} handler Handler function to remove + * @memberOf mitt + */ + off(type: EventType, handler: Handler) { + const handlers = all?.get(type); + if (handlers) { + handlers.splice(handlers.indexOf(handler) >>> 0, 1); + } + }, + + /** + * Register an event handler for the given type. + * @param {string|symbol} type Type of event to listen for, or `"*"` for all events + * @param {Function} handler Function to call in response to given event + * @memberOf mitt + */ + on(type: EventType, handler: Handler) { + const handlers = all?.get(type); + const added = handlers && handlers.push(handler); + if (!added) { + all?.set(type, [handler]); + } + }, + }; +} diff --git a/apps/vben5/packages/@abp/core/src/utils/regex.ts b/apps/vben5/packages/@abp/core/src/utils/regex.ts new file mode 100644 index 000000000..fb047e06d --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/utils/regex.ts @@ -0,0 +1,47 @@ +/* eslint-disable regexp/no-unused-capturing-group */ +export function isRegMatch(reg: RegExp, val: string) { + return reg.test(val); +} + +export function isEmail(val: string) { + const reg = /^\w+((-\w+)|(\.\w+))*@[A-Z0-9]+((\.|-)[A-Z0-9]+)*\.[A-Z0-9]+$/i; + return isRegMatch(reg, val); +} + +export function isPhone(val: string) { + const reg = /^(13\d|14[5|7]|15\d|17\d|18\d|19\d)\d{8}$/; + return isRegMatch(reg, val); +} + +export function isDigit(val: string) { + return [...val].some((element) => _isDigit(element)); +} + +export function isLower(val: string) { + return [...val].some((element) => _isLower(element)); +} + +export function isUpper(val: string) { + return [...val].some((element) => _isUpper(element)); +} + +export function isLetterOrDigit(val: string) { + const arr = [...val]; + return !arr.some((element) => _isLetterOrDigit(element)); +} + +function _isDigit(char: string) { + return isRegMatch(/\d/g, char); +} + +function _isLower(char: string) { + return isRegMatch(/[a-z]/g, char); +} + +function _isUpper(char: string) { + return isRegMatch(/[A-Z]/g, char); +} + +function _isLetterOrDigit(char: string) { + return isRegMatch(/[^ \w]/g, char); +} diff --git a/apps/vben5/packages/@abp/core/src/utils/string.ts b/apps/vben5/packages/@abp/core/src/utils/string.ts new file mode 100644 index 000000000..cca6eb5aa --- /dev/null +++ b/apps/vben5/packages/@abp/core/src/utils/string.ts @@ -0,0 +1,37 @@ +/** + * + * @param str 字符串是否为空或空格 + */ +export function isNullOrWhiteSpace(str?: string) { + return str === undefined || str === null || str === '' || str === ' '; +} + +/** + * 格式化字符串 + * @param formatted 需要处理的字符串 + * @param args 参数列表,可以是数组,也可以是对象 + * @returns 返回格式化的字符串 + * @example format('Hello, {0}!', ['World']) + * @example format('Hello, {name}!', {name: 'World'}) + */ +export function format(formatted: string, args: any[] | object) { + if (Array.isArray(args)) { + for (const [i, arg] of args.entries()) { + const regexp = new RegExp(String.raw`\{` + i + String.raw`\}`, 'gi'); + formatted = formatted.replace(regexp, arg); + } + } else if (typeof args === 'object') { + Object.keys(args).forEach((key) => { + const regexp = new RegExp(String.raw`\{` + key + String.raw`\}`, 'gi'); + const param = (args as any)[key]; + formatted = formatted.replace(regexp, param); + }); + } + return formatted; +} + +export function getUnique(val: string) { + const arr = [...val]; + const newArr = [...new Set(arr)]; + return newArr.join(''); +} diff --git a/apps/vben5/packages/@abp/identity/package.json b/apps/vben5/packages/@abp/identity/package.json index 0a1fad4a5..b01823c08 100644 --- a/apps/vben5/packages/@abp/identity/package.json +++ b/apps/vben5/packages/@abp/identity/package.json @@ -1,6 +1,6 @@ { "name": "@abp/identity", - "version": "8.2.3", + "version": "9.0.4", "homepage": "https://github.com/colinin/abp-next-admin", "bugs": "https://github.com/colinin/abp-next-admin/issues", "repository": { @@ -20,8 +20,9 @@ } }, "dependencies": { + "@abp/auditing": "workspace:*", "@abp/core": "workspace:*", - "@abp/permission": "workspace:*", + "@abp/permissions": "workspace:*", "@abp/request": "workspace:*", "@abp/ui": "workspace:*", "@ant-design/icons-vue": "catalog:", @@ -32,6 +33,10 @@ "@vben/layouts": "workspace:*", "@vben/locales": "workspace:*", "ant-design-vue": "catalog:", + "lodash.debounce": "catalog:", "vue": "catalog:*" + }, + "devDependencies": { + "@types/lodash.debounce": "catalog:" } } diff --git a/apps/vben5/packages/@abp/identity/src/api/claim-types.ts b/apps/vben5/packages/@abp/identity/src/api/claim-types.ts deleted file mode 100644 index dbbc8d603..000000000 --- a/apps/vben5/packages/@abp/identity/src/api/claim-types.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { PagedResultDto } from '@abp/core'; - -import type { - GetIdentityClaimTypePagedListInput, - IdentityClaimTypeCreateDto, - IdentityClaimTypeDto, - IdentityClaimTypeUpdateDto, -} from '../types/claim-types'; - -import { requestClient } from '@abp/request'; - -/** - * 新增用户声明 - * @param input 参数 - * @returns 用户声明实体数据传输对象 - */ -export function createApi( - input: IdentityClaimTypeCreateDto, -): Promise { - return requestClient.post( - '/api/identity/claim-types', - input, - ); -} - -/** - * 删除用户声明 - * @param id 用户声明id - */ -export function deleteApi(id: string): Promise { - return requestClient.delete(`/api/identity/claim-types/${id}`); -} - -/** - * 查询用户声明 - * @param id 用户声明id - * @returns 用户声明实体数据传输对象 - */ -export function getApi(id: string): Promise { - return requestClient.get( - `/api/identity/claim-types/${id}`, - ); -} - -/** - * 更新用户声明 - * @param id 用户声明id - * @returns 用户声明实体数据传输对象 - */ -export function updateApi( - id: string, - input: IdentityClaimTypeUpdateDto, -): Promise { - return requestClient.put( - `/api/identity/claim-types/${id}`, - input, - ); -} - -/** - * 查询用户声明分页列表 - * @param input 过滤参数 - * @returns 用户声明实体数据传输对象分页列表 - */ -export function getPagedListApi( - input?: GetIdentityClaimTypePagedListInput, -): Promise> { - return requestClient.get>( - `/api/identity/claim-types`, - { - params: input, - }, - ); -} diff --git a/apps/vben5/packages/@abp/identity/src/api/index.ts b/apps/vben5/packages/@abp/identity/src/api/index.ts new file mode 100644 index 000000000..bb910e41d --- /dev/null +++ b/apps/vben5/packages/@abp/identity/src/api/index.ts @@ -0,0 +1,7 @@ +export { useClaimTypesApi } from './useClaimTypesApi'; +export { useOrganizationUnitsApi } from './useOrganizationUnitsApi'; +export { useRolesApi } from './useRolesApi'; +export { useSecurityLogsApi } from './useSecurityLogsApi'; +export { useUserLookupApi } from './useUserLookupApi'; +export { useUsersApi } from './useUsersApi'; +export { useUserSessionsApi } from './useUserSessionsApi'; diff --git a/apps/vben5/packages/@abp/identity/src/api/organization-units.ts b/apps/vben5/packages/@abp/identity/src/api/organization-units.ts deleted file mode 100644 index aba2b746e..000000000 --- a/apps/vben5/packages/@abp/identity/src/api/organization-units.ts +++ /dev/null @@ -1,227 +0,0 @@ -import type { ListResultDto, PagedResultDto } from '@abp/core'; - -import type { IdentityRoleDto, IdentityUserDto } from '../types'; -import type { - GetIdentityRolesInput, - GetIdentityUsersInput, - GetOrganizationUnitPagedListInput, - GetUnaddedRoleListInput, - GetUnaddedUserListInput, - OrganizationUnitAddRoleDto, - OrganizationUnitAddUserDto, - OrganizationUnitCreateDto, - OrganizationUnitDto, - OrganizationUnitGetChildrenDto, - OrganizationUnitUpdateDto, -} from '../types/organization-units'; - -import { requestClient } from '@abp/request'; - -/** - * 新增组织机构 - * @param input 参数 - * @returns 组织机构实体数据传输对象 - */ -export function createApi( - input: OrganizationUnitCreateDto, -): Promise { - return requestClient.post( - '/api/identity/organization-units', - input, - ); -} - -/** - * 删除组织机构 - * @param id 组织机构id - */ -export function deleteApi(id: string): Promise { - return requestClient.delete(`/api/identity/organization-units/${id}`); -} - -/** - * 查询组织机构 - * @param id 组织机构id - * @returns 组织机构实体数据传输对象 - */ -export function getApi(id: string): Promise { - return requestClient.get( - `/api/identity/organization-units/${id}`, - ); -} - -/** - * 更新组织机构 - * @param id 组织机构id - * @returns 组织机构实体数据传输对象 - */ -export function updateApi( - id: string, - input: OrganizationUnitUpdateDto, -): Promise { - return requestClient.put( - `/api/identity/organization-units/${id}`, - input, - ); -} - -/** - * 查询组织机构分页列表 - * @param input 过滤参数 - * @returns 组织机构实体数据传输对象分页列表 - */ -export function getPagedListApi( - input?: GetOrganizationUnitPagedListInput, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units`, - { - params: input, - }, - ); -} - -/** - * 查询根组织机构列表 - * @returns 组织机构实体数据传输对象列表 - */ -export function getRootListApi(): Promise> { - return requestClient.get>( - `/api/identity/organization-units/root-node`, - ); -} - -/** - * 查询组织机构列表 - * @returns 组织机构实体数据传输对象列表 - */ -export function getAllListApi(): Promise> { - return requestClient.get>( - `/api/identity/organization-units/all`, - ); -} - -/** - * 查询下级组织机构列表 - * @param input 查询参数 - * @returns 组织机构实体数据传输对象列表 - */ -export function getChildrenApi( - input: OrganizationUnitGetChildrenDto, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units/find-children`, - { - params: input, - }, - ); -} - -/** - * 查询组织机构用户列表 - * @param id 组织机构id - * @param input 查询过滤参数 - * @returns 用户实体数据传输对象分页列表 - */ -export function getUserListApi( - id: string, - input?: GetIdentityUsersInput, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units/${id}/users`, - { - params: input, - }, - ); -} - -/** - * 查询未加入组织机构的用户列表 - * @param input 查询过滤参数 - * @returns 用户实体数据传输对象分页列表 - */ -export function getUnaddedUserListApi( - input: GetUnaddedUserListInput, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units/${input.id}/unadded-users`, - { - params: input, - }, - ); -} - -/** - * 用户添加到组织机构 - * @param id 组织机构id - * @param input 用户id列表 - */ -export function addMembers( - id: string, - input: OrganizationUnitAddUserDto, -): Promise { - return requestClient.post( - `/api/identity/organization-units/${id}/users`, - input, - ); -} - -/** - * 查询组织机构角色列表 - * @param id 组织机构id - * @param input 查询过滤参数 - * @returns 角色实体数据传输对象分页列表 - */ -export function getRoleListApi( - id: string, - input?: GetIdentityRolesInput, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units/${id}/roles`, - { - params: input, - }, - ); -} - -/** - * 查询未加入组织机构的角色列表 - * @param input 查询过滤参数 - * @returns 角色实体数据传输对象分页列表 - */ -export function getUnaddedRoleListApi( - input: GetUnaddedRoleListInput, -): Promise> { - return requestClient.get>( - `/api/identity/organization-units/${input.id}/unadded-roles`, - { - params: input, - }, - ); -} - -/** - * 角色添加到组织机构 - * @param id 组织机构id - * @param input 角色id列表 - */ -export function addRoles( - id: string, - input: OrganizationUnitAddRoleDto, -): Promise { - return requestClient.post( - `/api/identity/organization-units/${id}/roles`, - input, - ); -} - -/** - * 移动组织机构 - * @param id 组织机构id - * @param parentId 父级组织机构id - */ -export function moveTo(id: string, parentId?: string): Promise { - return requestClient.put(`api/identity/organization-units/${id}/move`, { - parentId, - }); -} diff --git a/apps/vben5/packages/@abp/identity/src/api/roles.ts b/apps/vben5/packages/@abp/identity/src/api/roles.ts deleted file mode 100644 index 8292bd7ae..000000000 --- a/apps/vben5/packages/@abp/identity/src/api/roles.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { PagedResultDto } from '@abp/core'; - -import type { - GetRolePagedListInput, - IdentityRoleCreateDto, - IdentityRoleDto, - IdentityRoleUpdateDto, -} from '../types/roles'; - -import { requestClient } from '@abp/request'; - -/** - * 新增角色 - * @param input 参数 - * @returns 角色实体数据传输对象 - */ -export function createApi( - input: IdentityRoleCreateDto, -): Promise { - return requestClient.post('/api/identity/roles', input); -} - -/** - * 删除角色 - * @param id 角色id - */ -export function deleteApi(id: string): Promise { - return requestClient.delete(`/api/identity/roles/${id}`); -} - -/** - * 查询角色 - * @param id 角色id - * @returns 角色实体数据传输对象 - */ -export function getApi(id: string): Promise { - return requestClient.get
{{ $t('AbpUi.ProfilePicture') }}