refactor: rename the theme brand and every identifier from AKSRT to Jio

Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-01 20:05:04 +08:00
1 parent 5b16bc6e15
commit 35bb96e82f
997 files changed
+28216 -28188

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@
/.workbuddy/ /.workbuddy/
# Project planning, internal docs, and local-only development files # Project planning, internal docs, and local-only development files
/.aksrt-chrome-profile/ /.jio-chrome-profile/
/.specs/ /.specs/
/docs/ /docs/
+15 -15
View File
@@ -2,15 +2,15 @@
/** /**
* 404 template. * 404 template.
* *
* @package AKSRT * @package Jio
*/ */
defined('ABSPATH') || exit; defined('ABSPATH') || exit;
get_header(); get_header();
$search_placeholder = function_exists('aksrt_get_search_placeholder') ? aksrt_get_search_placeholder() : __('开启精彩搜索', 'aksrt'); $search_placeholder = function_exists('jio_get_search_placeholder') ? jio_get_search_placeholder() : __('开启精彩搜索', 'jio');
$hot_keywords = function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : []; $hot_keywords = function_exists('jio_get_search_hot_keywords') ? jio_get_search_hot_keywords() : [];
$hot_query = new WP_Query([ $hot_query = new WP_Query([
'post_type' => 'post', 'post_type' => 'post',
@@ -39,33 +39,33 @@ $top_cats = get_terms([
<i class="fa fas fa-compass"></i> <i class="fa fas fa-compass"></i>
</p> </p>
<p class="error-hero__code" id="error-title">404</p> <p class="error-hero__code" id="error-title">404</p>
<h1 class="error-hero__title"><?php esc_html_e('页面未找到', 'aksrt'); ?></h1> <h1 class="error-hero__title"><?php esc_html_e('页面未找到', 'jio'); ?></h1>
<p class="error-hero__desc"> <p class="error-hero__desc">
<?php esc_html_e('你访问的页面不存在或已被删除。试试搜索,或者从下方常用入口继续浏览。', 'aksrt'); ?> <?php esc_html_e('你访问的页面不存在或已被删除。试试搜索,或者从下方常用入口继续浏览。', 'jio'); ?>
</p> </p>
</div> </div>
<?php if (function_exists('aksrt_render_admin_quick_link')) { aksrt_render_admin_quick_link('page-display/other', __('404 页设置', 'aksrt')); } ?> <?php if (function_exists('jio_render_admin_quick_link')) { jio_render_admin_quick_link('page-display/other', __('404 页设置', 'jio')); } ?>
</div> </div>
<form role="search" method="get" class="error-hero__search" action="<?php echo esc_url(home_url('/')); ?>"> <form role="search" method="get" class="error-hero__search" action="<?php echo esc_url(home_url('/')); ?>">
<span class="error-hero__search-icon" aria-hidden="true"> <span class="error-hero__search-icon" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
</span> </span>
<label class="screen-reader-text" for="error-search-input"><?php esc_html_e('搜索', 'aksrt'); ?></label> <label class="screen-reader-text" for="error-search-input"><?php esc_html_e('搜索', 'jio'); ?></label>
<input type="search" id="error-search-input" name="s" placeholder="<?php echo esc_attr($search_placeholder); ?>" autocomplete="off"> <input type="search" id="error-search-input" name="s" placeholder="<?php echo esc_attr($search_placeholder); ?>" autocomplete="off">
<button type="submit" class="btn-primary btn-sm"><?php esc_html_e('搜索', 'aksrt'); ?></button> <button type="submit" class="btn-primary btn-sm"><?php esc_html_e('搜索', 'jio'); ?></button>
</form> </form>
<?php aksrt_render_search_hot_keywords($hot_keywords, 'aksrt-search-hot-keywords'); ?> <?php jio_render_search_hot_keywords($hot_keywords, 'jio-search-hot-keywords'); ?>
<div class="error-hero__actions"> <div class="error-hero__actions">
<a href="<?php echo esc_url(home_url('/')); ?>" class="btn-primary"><?php esc_html_e('返回首页', 'aksrt'); ?></a> <a href="<?php echo esc_url(home_url('/')); ?>" class="btn-primary"><?php esc_html_e('返回首页', 'jio'); ?></a>
<a href="javascript:history.back()" class="btn-outline"><?php esc_html_e('返回上一页', 'aksrt'); ?></a> <a href="javascript:history.back()" class="btn-outline"><?php esc_html_e('返回上一页', 'jio'); ?></a>
</div> </div>
</section> </section>
<?php if (!empty($top_cats) && !is_wp_error($top_cats)) : ?> <?php if (!empty($top_cats) && !is_wp_error($top_cats)) : ?>
<section class="error-section" aria-label="<?php esc_attr_e('热门分类', 'aksrt'); ?>"> <section class="error-section" aria-label="<?php esc_attr_e('热门分类', 'jio'); ?>">
<h2 class="error-section__title"><?php esc_html_e('热门分类', 'aksrt'); ?></h2> <h2 class="error-section__title"><?php esc_html_e('热门分类', 'jio'); ?></h2>
<div class="error-section__chips"> <div class="error-section__chips">
<?php foreach ($top_cats as $cat) : ?> <?php foreach ($top_cats as $cat) : ?>
<a class="error-section__chip" href="<?php echo esc_url(get_category_link($cat->term_id)); ?>"> <a class="error-section__chip" href="<?php echo esc_url(get_category_link($cat->term_id)); ?>">
@@ -78,8 +78,8 @@ $top_cats = get_terms([
<?php endif; ?> <?php endif; ?>
<?php if ($hot_query->have_posts()) : ?> <?php if ($hot_query->have_posts()) : ?>
<section class="error-section" aria-label="<?php esc_attr_e('热门内容', 'aksrt'); ?>"> <section class="error-section" aria-label="<?php esc_attr_e('热门内容', 'jio'); ?>">
<h2 class="error-section__title"><?php esc_html_e('热门内容', 'aksrt'); ?></h2> <h2 class="error-section__title"><?php esc_html_e('热门内容', 'jio'); ?></h2>
<ul class="error-section__list"> <ul class="error-section__list">
<?php while ($hot_query->have_posts()) : $hot_query->the_post(); ?> <?php while ($hot_query->have_posts()) : $hot_query->the_post(); ?>
<li> <li>
+28 -28
View File
@@ -1,4 +1,4 @@
# AKSRT WordPress Theme # Jio WordPress Theme
> **版本**: 3.4.0-dev | **架构**: 原生 PHP + WordPress (非 headless) > **版本**: 3.4.0-dev | **架构**: 原生 PHP + WordPress (非 headless)
> **要求**: WordPress >= 6.4 | PHP >= 8.1 > **要求**: WordPress >= 6.4 | PHP >= 8.1
@@ -7,7 +7,7 @@
## 项目概述 ## 项目概述
AKSRT 是一款现代化的 WordPress 主题,采用**原生 WordPress 主题架构**开发(PHP + HTML + CSS + JavaScript),不依赖 REST API 进行前端渲染。 Jio 是一款现代化的 WordPress 主题,采用**原生 WordPress 主题架构**开发(PHP + HTML + CSS + JavaScript),不依赖 REST API 进行前端渲染。
### 核心特性 ### 核心特性
@@ -22,14 +22,14 @@ AKSRT 是一款现代化的 WordPress 主题,采用**原生 WordPress 主题
## 文件结构 ## 文件结构
``` ```
AKSRT-theme/ Jio-theme/
├── functions.php # 入口:常量 + Composer autoload + bootstrap + 单例 init ├── functions.php # 入口:常量 + Composer autoload + bootstrap + 单例 init
├── style.css # WordPress 主题声明头 ├── style.css # WordPress 主题声明头
├── composer.json # 第三方依赖 + 主题 PSR-4(AKSRT\ → src/) ├── composer.json # 第三方依赖 + 主题 PSR-4(Jio\ → src/)
│ │
├── *.php # WP 核心模板保留根目录 ├── *.php # WP 核心模板保留根目录
│ │
├── src/ # Composer PSR-4 类型根(namespace AKSRT\) ├── src/ # Composer PSR-4 类型根(namespace Jio\)
│ ├── Admin/ # SPA 编排 + 域控制器 + Schema + Native ops │ ├── Admin/ # SPA 编排 + 域控制器 + Schema + Native ops
│ ├── Auth/ # 登录 / OAuth / 审核 / 邮箱 │ ├── Auth/ # 登录 / OAuth / 审核 / 邮箱
│ ├── Content/ # 下载 token / 付费内容 / VIP / 可见性 │ ├── Content/ # 下载 token / 付费内容 / VIP / 可见性
@@ -89,7 +89,7 @@ AKSRT-theme/
## 安装方式 ## 安装方式
主题类型(`AKSRT\…`)通过 Composer PSR-4 从 `src/` 自动加载;`vendor/` 不进 Git。**部署或更新主题后必须在主题根目录生成 autoload**,否则会出现 `Class "AKSRT\Core\DomainModel" not found` 等致命错误。 主题类型(`Jio\…`)通过 Composer PSR-4 从 `src/` 自动加载;`vendor/` 不进 Git。**部署或更新主题后必须在主题根目录生成 autoload**,否则会出现 `Class "Jio\Core\DomainModel" not found` 等致命错误。
### 前置:Composer(必做) ### 前置:Composer(必做)
@@ -106,16 +106,16 @@ composer dump-autoload -o
确认: 确认:
```bash ```bash
php -r "require 'vendor/autoload.php'; echo class_exists('AKSRT\\\\Core\\\\DomainModel') ? \"ok\\n\" : \"missing\\n\";" php -r "require 'vendor/autoload.php'; echo class_exists('Jio\\\\Core\\\\DomainModel') ? \"ok\\n\" : \"missing\\n\";"
``` ```
应输出 `ok`。若 PHP 开启了 OPcache,重载 php-fpm / 重启 PHP 后再访问站点。 应输出 `ok`。若 PHP 开启了 OPcache,重载 php-fpm / 重启 PHP 后再访问站点。
### 方式一:直接上传(推荐) ### 方式一:直接上传(推荐)
1. 将整个 `AKSRT-theme` 文件夹上传到 `wp-content/themes/` 1. 将整个 `Jio-theme` 文件夹上传到 `wp-content/themes/`
2. 在服务器主题目录执行上一节的 `composer install`(若打包时已带上完整 `vendor/` 且已 `dump-autoload`,可跳过) 2. 在服务器主题目录执行上一节的 `composer install`(若打包时已带上完整 `vendor/` 且已 `dump-autoload`,可跳过)
3. WordPress 后台 → **外观** → **主题** → 找到 **AKSRT** → **激活** 3. WordPress 后台 → **外观** → **主题** → 找到 **Jio** → **激活**
### 方式二:ZIP 打包上传 ### 方式二:ZIP 打包上传
@@ -126,7 +126,7 @@ php -r "require 'vendor/autoload.php'; echo class_exists('AKSRT\\\\Core\\\\Domai
SSH 进入主题目录后: SSH 进入主题目录后:
```bash ```bash
cd /path/to/wp-content/themes/AKsrt-theme # 以实际路径为准 cd /path/to/wp-content/themes/Jio-theme # 以实际路径为准
composer install --no-dev --optimize-autoloader composer install --no-dev --optimize-autoloader
# 或仅刷新映射:composer dump-autoload -o # 或仅刷新映射:composer dump-autoload -o
# 可选:reload php-fpm / 清 OPcache # 可选:reload php-fpm / 清 OPcache
@@ -150,9 +150,9 @@ composer install --no-dev --optimize-autoloader
### 2. 后台配置路径 ### 2. 后台配置路径
WordPress 后台左侧 **Admin Bar** → ⚡ **AKSRT 主题设置** WordPress 后台左侧 **Admin Bar** → ⚡ **Jio 主题设置**
或直接访问:`/wp-admin/admin.php?page=aksrt-settings` 或直接访问:`/wp-admin/admin.php?page=jio-settings`
### 3. 当前后台域 ### 3. 当前后台域
@@ -173,7 +173,7 @@ WordPress 后台左侧 **Admin Bar** → ⚡ **AKSRT 主题设置**
### 5. 部署注意事项 ### 5. 部署注意事项
- **佣金结算时效**:结算依赖小时级 wp-cron,并有收益页访问触发的懒结算兜底。高流量站点建议禁用 `WP_CRON_LOCK` 场景下的默认 WP-Cron,改用系统 crontab 定时请求 `wp-cron.php`,保证结算与过期任务准时执行。 - **佣金结算时效**:结算依赖小时级 wp-cron,并有收益页访问触发的懒结算兜底。高流量站点建议禁用 `WP_CRON_LOCK` 场景下的默认 WP-Cron,改用系统 crontab 定时请求 `wp-cron.php`,保证结算与过期任务准时执行。
- **反代 / CDN 与 IP 风控**:主题默认按 Cloudflare → 通用代理头顺序识别真实 IP。若需收紧伪造风险,添加 `add_filter('aksrt_trusted_proxies', fn() => ['10.0.0.0/8', '173.245.48.0/20'])`(填入你的代理/CDN 网段);名单非空时仅当 `REMOTE_ADDR` 命中名单才采纳转发头,否则直接使用 `REMOTE_ADDR`(推广奖励的 IP 日上限、验证码等均依赖该函数)。 - **反代 / CDN 与 IP 风控**:主题默认按 Cloudflare → 通用代理头顺序识别真实 IP。若需收紧伪造风险,添加 `add_filter('jio_trusted_proxies', fn() => ['10.0.0.0/8', '173.245.48.0/20'])`(填入你的代理/CDN 网段);名单非空时仅当 `REMOTE_ADDR` 命中名单才采纳转发头,否则直接使用 `REMOTE_ADDR`(推广奖励的 IP 日上限、验证码等均依赖该函数)。
--- ---
@@ -181,20 +181,20 @@ WordPress 后台左侧 **Admin Bar** → ⚡ **AKSRT 主题设置**
### Settings Facade 分层 ### Settings Facade 分层
- `AKSRT_Settings` 仍是主题设置的**唯一静态 facade**,外部调用方式保持 `AKSRT_Settings::*` - `JIO_Settings` 仍是主题设置的**唯一静态 facade**,外部调用方式保持 `JIO_Settings::*`
- 具体运行时 getter 已按领域拆分到 `inc/classes/settings/`,例如: - 具体运行时 getter 已按领域拆分到 `inc/classes/settings/`,例如:
- `class-aksrt-settings-theme-search.php` - `class-jio-settings-theme-search.php`
- `class-aksrt-settings-post-display.php` - `class-jio-settings-post-display.php`
- `class-aksrt-settings-home-cms.php` - `class-jio-settings-home-cms.php`
- `class-aksrt-settings-user-runtime.php` - `class-jio-settings-user-runtime.php`
- `class-aksrt-settings-integration.php` - `class-jio-settings-integration.php`
- `class-aksrt-settings-display-runtime.php` - `class-jio-settings-display-runtime.php`
- `class-aksrt-settings-extension-runtime.php` - `class-jio-settings-extension-runtime.php`
- `class-aksrt-settings-credits-runtime.php` - `class-jio-settings-credits-runtime.php`
- `class-aksrt-settings-category-runtime.php` - `class-jio-settings-category-runtime.php`
- `class-aksrt-settings-capabilities.php` - `class-jio-settings-capabilities.php`
- `inc/bootstrap.php` 会先加载 `settings/class-aksrt-settings.php`,再按领域加载这些 delegate 类 - `inc/bootstrap.php` 会先加载 `settings/class-jio-settings.php`,再按领域加载这些 delegate 类
- 新增设置运行时逻辑时,优先放入对应 settings 子类;仅把聚合输出、统一入口和跨域装配保留在 `AKSRT_Settings` - 新增设置运行时逻辑时,优先放入对应 settings 子类;仅把聚合输出、统一入口和跨域装配保留在 `JIO_Settings`
### 添加新辅助函数 ### 添加新辅助函数
@@ -202,14 +202,14 @@ WordPress 后台左侧 **Admin Bar** → ⚡ **AKSRT 主题设置**
### 添加新页面模板 ### 添加新页面模板
将 `page-{name}.php` 放入 `templates/pages/`,并在 `class-aksrt-templates.php` 中注册。 将 `page-{name}.php` 放入 `templates/pages/`,并在 `class-jio-templates.php` 中注册。
### CSS 组织规范 ### CSS 组织规范
| 目录 | 用途 | 加载场景 | | 目录 | 用途 | 加载场景 |
|------|------|---------| |------|------|---------|
| `css/frontend/` | 前端公共样式 | 所有前台页面 | | `css/frontend/` | 前端公共样式 | 所有前台页面 |
| `css/admin/` | 后台管理样式 | 仅 AKSRT 设置页面 | | `css/admin/` | 后台管理样式 | 仅 Jio 设置页面 |
| `css/shared/` | 共用组件样式 | 前后端按需加载(如验证码) | | `css/shared/` | 共用组件样式 | 前后端按需加载(如验证码) |
--- ---
+26 -26
View File
@@ -2,9 +2,9 @@
/** /**
* Resource Archive Template * Resource Archive Template
* *
* Virtual list at /resources/ — ordinary posts marked with _aksrt_is_resource. * Virtual list at /resources/ — ordinary posts marked with _jio_is_resource.
* *
* @package AKSRT * @package Jio
*/ */
defined('ABSPATH') || exit; defined('ABSPATH') || exit;
@@ -25,18 +25,18 @@ if (!in_array($current_price, ['all', 'free', 'paid'], true)) {
$price_min = isset($_GET['price_min']) && $_GET['price_min'] !== '' ? (float) $_GET['price_min'] : ''; $price_min = isset($_GET['price_min']) && $_GET['price_min'] !== '' ? (float) $_GET['price_min'] : '';
$price_max = isset($_GET['price_max']) && $_GET['price_max'] !== '' ? (float) $_GET['price_max'] : ''; $price_max = isset($_GET['price_max']) && $_GET['price_max'] !== '' ? (float) $_GET['price_max'] : '';
$archive_url = function_exists('aksrt_resource_archive_url') ? aksrt_resource_archive_url() : home_url('/resources/'); $archive_url = function_exists('jio_resource_archive_url') ? jio_resource_archive_url() : home_url('/resources/');
$sort_options = [ $sort_options = [
'date' => __('最新', 'aksrt'), 'date' => __('最新', 'jio'),
'downloads' => __('热门下载', 'aksrt'), 'downloads' => __('热门下载', 'jio'),
'views' => __('阅读最多', 'aksrt'), 'views' => __('阅读最多', 'jio'),
]; ];
$price_options = [ $price_options = [
'all' => __('全部', 'aksrt'), 'all' => __('全部', 'jio'),
'free' => __('免费', 'aksrt'), 'free' => __('免费', 'jio'),
'paid' => __('付费', 'aksrt'), 'paid' => __('付费', 'jio'),
]; ];
$preserve = []; $preserve = [];
@@ -59,18 +59,18 @@ $has_filter = $current_orderby !== 'date' || $current_price !== 'all' || $price_
<main id="main-content" class="site-main container" tabindex="-1"> <main id="main-content" class="site-main container" tabindex="-1">
<header class="resource-archive-header page-cover"> <header class="resource-archive-header page-cover">
<div class="container"> <div class="container">
<?php if (function_exists('aksrt_breadcrumbs')) : ?> <?php if (function_exists('jio_breadcrumbs')) : ?>
<nav class="resource-archive-header__breadcrumbs" aria-label="<?php esc_attr_e('面包屑', 'aksrt'); ?>"> <nav class="resource-archive-header__breadcrumbs" aria-label="<?php esc_attr_e('面包屑', 'jio'); ?>">
<?php aksrt_breadcrumbs(); ?> <?php jio_breadcrumbs(); ?>
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<h1 class="resource-archive-header__title"><?php esc_html_e('资源', 'aksrt'); ?></h1> <h1 class="resource-archive-header__title"><?php esc_html_e('资源', 'jio'); ?></h1>
<p class="resource-archive-header__sub"> <p class="resource-archive-header__sub">
<?php <?php
global $wp_query; global $wp_query;
/* translators: %s: resource count */ /* translators: %s: resource count */
printf(esc_html__('共 %s 个资源', 'aksrt'), esc_html(number_format_i18n((int) $wp_query->found_posts))); printf(esc_html__('共 %s 个资源', 'jio'), esc_html(number_format_i18n((int) $wp_query->found_posts)));
?> ?>
</p> </p>
</div> </div>
@@ -79,9 +79,9 @@ $has_filter = $current_orderby !== 'date' || $current_price !== 'all' || $price_
<div class="content-wrap"> <div class="content-wrap">
<div class="content-layout content-layout--no-sidebar"> <div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary resource-archive"> <div class="content-layout__primary resource-archive">
<nav class="resource-archive__toolbar" aria-label="<?php esc_attr_e('筛选', 'aksrt'); ?>"> <nav class="resource-archive__toolbar" aria-label="<?php esc_attr_e('筛选', 'jio'); ?>">
<div class="resource-archive__filter-group"> <div class="resource-archive__filter-group">
<span class="resource-archive__filter-label"><?php esc_html_e('排序', 'aksrt'); ?></span> <span class="resource-archive__filter-label"><?php esc_html_e('排序', 'jio'); ?></span>
<ul class="resource-archive__sort"> <ul class="resource-archive__sort">
<?php foreach ($sort_options as $key => $label) : <?php foreach ($sort_options as $key => $label) :
$args = $preserve; $args = $preserve;
@@ -105,7 +105,7 @@ $has_filter = $current_orderby !== 'date' || $current_price !== 'all' || $price_
</div> </div>
<div class="resource-archive__filter-group"> <div class="resource-archive__filter-group">
<span class="resource-archive__filter-label"><?php esc_html_e('价格', 'aksrt'); ?></span> <span class="resource-archive__filter-label"><?php esc_html_e('价格', 'jio'); ?></span>
<ul class="resource-archive__sort"> <ul class="resource-archive__sort">
<?php foreach ($price_options as $key => $label) : <?php foreach ($price_options as $key => $label) :
$args = $preserve; $args = $preserve;
@@ -139,43 +139,43 @@ $has_filter = $current_orderby !== 'date' || $current_price !== 'all' || $price_
} }
?> ?>
<label class="resource-archive__price-input"> <label class="resource-archive__price-input">
<span><?php esc_html_e('最低', 'aksrt'); ?></span> <span><?php esc_html_e('最低', 'jio'); ?></span>
<input type="number" name="price_min" min="0" step="1" value="<?php echo esc_attr((string) $price_min); ?>"> <input type="number" name="price_min" min="0" step="1" value="<?php echo esc_attr((string) $price_min); ?>">
</label> </label>
<span class="resource-archive__price-sep">—</span> <span class="resource-archive__price-sep">—</span>
<label class="resource-archive__price-input"> <label class="resource-archive__price-input">
<span><?php esc_html_e('最高', 'aksrt'); ?></span> <span><?php esc_html_e('最高', 'jio'); ?></span>
<input type="number" name="price_max" min="0" step="1" value="<?php echo esc_attr((string) $price_max); ?>"> <input type="number" name="price_max" min="0" step="1" value="<?php echo esc_attr((string) $price_max); ?>">
</label> </label>
<button type="submit" class="btn-primary btn-sm"><?php esc_html_e('应用', 'aksrt'); ?></button> <button type="submit" class="btn-primary btn-sm"><?php esc_html_e('应用', 'jio'); ?></button>
</form> </form>
<?php if ($has_filter) : ?> <?php if ($has_filter) : ?>
<a class="resource-archive__reset" href="<?php echo esc_url($archive_url); ?>"> <a class="resource-archive__reset" href="<?php echo esc_url($archive_url); ?>">
<i class="fa fas fa-times-circle" aria-hidden="true"></i> <i class="fa fas fa-times-circle" aria-hidden="true"></i>
<?php esc_html_e('清除筛选', 'aksrt'); ?> <?php esc_html_e('清除筛选', 'jio'); ?>
</a> </a>
<?php endif; ?> <?php endif; ?>
</nav> </nav>
<?php if (have_posts()) : ?> <?php if (have_posts()) : ?>
<?php <?php
$render_config = aksrt_resolve_post_list_render_config([ $render_config = jio_resolve_post_list_render_config([
'context' => 'archive', 'context' => 'archive',
'overrides' => ['type' => 'card'], 'overrides' => ['type' => 'card'],
]); ]);
aksrt_render_post_list(array_merge($render_config, ['wrapper_class' => 'content-stream__list'])); jio_render_post_list(array_merge($render_config, ['wrapper_class' => 'content-stream__list']));
aksrt_render_pagination(null, [ jio_render_pagination(null, [
'query_context' => 'archive', 'query_context' => 'archive',
'render_config' => $render_config, 'render_config' => $render_config,
]); ]);
?> ?>
<?php else : ?> <?php else : ?>
<div class="no-results"> <div class="no-results">
<p><?php esc_html_e('暂无资源。', 'aksrt'); ?></p> <p><?php esc_html_e('暂无资源。', 'jio'); ?></p>
<?php if ($has_filter) : ?> <?php if ($has_filter) : ?>
<p><a class="btn-outline btn-sm" href="<?php echo esc_url($archive_url); ?>"><?php esc_html_e('清除筛选条件', 'aksrt'); ?></a></p> <p><a class="btn-outline btn-sm" href="<?php echo esc_url($archive_url); ?>"><?php esc_html_e('清除筛选条件', 'jio'); ?></a></p>
<?php endif; ?> <?php endif; ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
+19 -19
View File
@@ -2,7 +2,7 @@
/** /**
* Generic archive template. * Generic archive template.
* *
* @package AKSRT * @package Jio
*/ */
defined('ABSPATH') || exit; defined('ABSPATH') || exit;
@@ -11,31 +11,31 @@ get_header();
global $wp_query; global $wp_query;
$render_config = function_exists('aksrt_archive_get_render_config') $render_config = function_exists('jio_archive_get_render_config')
? aksrt_archive_get_render_config(['context' => 'archive']) ? jio_archive_get_render_config(['context' => 'archive'])
: ['context' => 'archive', 'mode' => 'list']; : ['context' => 'archive', 'mode' => 'list'];
$has_sidebar = function_exists('aksrt_archive_has_sidebar') $has_sidebar = function_exists('jio_archive_has_sidebar')
? aksrt_archive_has_sidebar() ? jio_archive_has_sidebar()
: (function_exists('aksrt_is_show_sidebar') ? aksrt_is_show_sidebar() : false); : (function_exists('jio_is_show_sidebar') ? jio_is_show_sidebar() : false);
$archive_description = trim(wp_strip_all_tags((string) get_the_archive_description())); $archive_description = trim(wp_strip_all_tags((string) get_the_archive_description()));
$archive_summary = ''; $archive_summary = '';
if (is_author()) { if (is_author()) {
$author = get_queried_object(); $author = get_queried_object();
if ($author instanceof WP_User) { if ($author instanceof WP_User) {
$archive_summary = sprintf(__('作者:%s', 'aksrt'), $author->display_name); $archive_summary = sprintf(__('作者:%s', 'jio'), $author->display_name);
} }
} elseif ($archive_description !== '') { } elseif ($archive_description !== '') {
$archive_summary = $archive_description; $archive_summary = $archive_description;
} elseif (isset($wp_query->found_posts)) { } elseif (isset($wp_query->found_posts)) {
$archive_summary = sprintf( $archive_summary = sprintf(
esc_html(_n('共 %d 篇内容', '共 %d 篇内容', (int) $wp_query->found_posts, 'aksrt')), esc_html(_n('共 %d 篇内容', '共 %d 篇内容', (int) $wp_query->found_posts, 'jio')),
(int) $wp_query->found_posts (int) $wp_query->found_posts
); );
} }
if (function_exists('aksrt_archive_open_shell')) { if (function_exists('jio_archive_open_shell')) {
aksrt_archive_open_shell([ jio_archive_open_shell([
'main_class' => 'site-main container', 'main_class' => 'site-main container',
'has_sidebar' => $has_sidebar, 'has_sidebar' => $has_sidebar,
'page_kind' => 'archive', 'page_kind' => 'archive',
@@ -45,16 +45,16 @@ if (function_exists('aksrt_archive_open_shell')) {
} }
?> ?>
<div class="content-main content-main--archive"> <div class="content-main content-main--archive">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?> <?php if (function_exists('jio_breadcrumbs')) { jio_breadcrumbs(); } ?>
<?php <?php
ob_start(); ob_start();
if (function_exists('aksrt_render_admin_quick_link')) { if (function_exists('jio_render_admin_quick_link')) {
aksrt_render_admin_quick_link('post-list/list', __('列表样式设置', 'aksrt')); jio_render_admin_quick_link('post-list/list', __('列表样式设置', 'jio'));
} }
$admin_link = trim((string) ob_get_clean()); $admin_link = trim((string) ob_get_clean());
get_template_part('templates/parts/page-header', null, [ get_template_part('templates/parts/page-header', null, [
'eyebrow' => __('内容归档', 'aksrt'), 'eyebrow' => __('内容归档', 'jio'),
'title' => get_the_archive_title(), 'title' => get_the_archive_title(),
'desc' => $archive_summary, 'desc' => $archive_summary,
'extra' => $admin_link, 'extra' => $admin_link,
@@ -62,19 +62,19 @@ if (function_exists('aksrt_archive_open_shell')) {
?> ?>
<?php <?php
if (function_exists('aksrt_archive_render_stream')) { if (function_exists('jio_archive_render_stream')) {
aksrt_archive_render_stream(null, $render_config, [ jio_archive_render_stream(null, $render_config, [
'page_kind' => 'archive', 'page_kind' => 'archive',
'query_context' => 'archive', 'query_context' => 'archive',
'stream_class' => 'content-stream--archive', 'stream_class' => 'content-stream--archive',
'empty_text' => __('暂无文章', 'aksrt'), 'empty_text' => __('暂无文章', 'jio'),
]); ]);
} }
?> ?>
</div> </div>
<?php <?php
if (function_exists('aksrt_archive_close_shell')) { if (function_exists('jio_archive_close_shell')) {
aksrt_archive_close_shell(['has_sidebar' => $has_sidebar]); jio_archive_close_shell(['has_sidebar' => $has_sidebar]);
} else { } else {
echo '</div></div>'; echo '</div></div>';
if ($has_sidebar) { get_sidebar(); } if ($has_sidebar) { get_sidebar(); }
+6 -6
View File
@@ -104,7 +104,7 @@ const COMPONENT_STYLES = [
] ]
async function extractStyles() { async function extractStyles() {
console.log('\n[AKSRT] 开始提取 NaiveUI 组件样式...\n') console.log('\n[Jio] 开始提取 NaiveUI 组件样式...\n')
const allCss = [] const allCss = []
let successCount = 0 let successCount = 0
@@ -137,9 +137,9 @@ async function extractStyles() {
// 静默跳过的后果是组件样式整体缺失(取色器曾因此没有尺寸和边框,糊成一团), // 静默跳过的后果是组件样式整体缺失(取色器曾因此没有尺寸和边框,糊成一团),
// 而页面不报错,只能靠肉眼发现。 // 而页面不报错,只能靠肉眼发现。
if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') { if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {
console.error(`[AKSRT] 样式路径不存在,已跳过: ${componentPath}`) console.error(`[Jio] 样式路径不存在,已跳过: ${componentPath}`)
} else { } else {
console.error(`[AKSRT] 样式提取异常,已跳过: ${componentPath}: ${err && err.message}`) console.error(`[Jio] 样式提取异常,已跳过: ${componentPath}: ${err && err.message}`)
} }
failCount++ failCount++
} }
@@ -148,7 +148,7 @@ async function extractStyles() {
const cssOutput = allCss.join('\n\n') const cssOutput = allCss.join('\n\n')
if (!cssOutput.trim()) { if (!cssOutput.trim()) {
console.warn('[AKSRT] 警告:未提取到任何 NaiveUI 样式!') console.warn('[Jio] 警告:未提取到任何 NaiveUI 样式!')
return null return null
} }
@@ -165,7 +165,7 @@ ${cssOutput}`
await writeFile(cssFile, fullContent, 'utf-8') await writeFile(cssFile, fullContent, 'utf-8')
console.log(`[AKSRT] NaiveUI 样式提取完成:`) console.log(`[Jio] NaiveUI 样式提取完成:`)
console.log(` 成功: ${successCount} 个组件`) console.log(` 成功: ${successCount} 个组件`)
console.log(` 跳过: ${failCount} 个组件`) console.log(` 跳过: ${failCount} 个组件`)
console.log(` 输出: ${cssFile}`) console.log(` 输出: ${cssFile}`)
@@ -176,6 +176,6 @@ ${cssOutput}`
// 执行 // 执行
extractStyles().catch((err) => { extractStyles().catch((err) => {
console.error('[AKSRT] 样式提取失败:', err) console.error('[Jio] 样式提取失败:', err)
process.exit(1) process.exit(1)
}) })
+2 -2
View File
@@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AKSRT 主题设置</title> <title>Jio 主题设置</title>
</head> </head>
<body> <body>
<div id="aksrt-admin-app"></div> <div id="jio-admin-app"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
</body> </body>
</html> </html>
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "aksrt-admin", "name": "jio-admin",
"version": "1.0.0", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "aksrt-admin", "name": "jio-admin",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@codemirror/lang-css": "^6.3.1", "@codemirror/lang-css": "^6.3.1",
+1 -1
View File
@@ -1 +1 @@
{"name":"aksrt-admin","version":"1.0.0","private":true,"type":"module","scripts":{"dev":"vite","build":"vite build && node extract-naive-styles.mjs","build:public":"node ../../tools/build-public-assets.mjs","build:pay-charts":"node ../../tools/build-pay-charts.mjs","preview":"vite preview"},"dependencies":{"@codemirror/lang-css":"^6.3.1","@codemirror/lang-html":"^6.4.11","@codemirror/lang-javascript":"^6.2.5","@codemirror/theme-one-dark":"^6.1.3","codemirror":"^6.0.2","naive-ui":"^2.40.0","pinia":"^2.2.0","vue":"^3.5.0","vue-router":"^4.4.0","vuedraggable":"^4.1.0"},"devDependencies":{"@vitejs/plugin-vue":"^5.1.0","echarts":"^6.1.0","esbuild":"^0.25.12","vite":"^6.0.0"},"allowScripts":{"esbuild@0.25.12":true,"vue-demi@0.14.10":true}} {"name":"jio-admin","version":"1.0.0","private":true,"type":"module","scripts":{"dev":"vite","build":"vite build && node extract-naive-styles.mjs","build:public":"node ../../tools/build-public-assets.mjs","build:pay-charts":"node ../../tools/build-pay-charts.mjs","preview":"vite preview"},"dependencies":{"@codemirror/lang-css":"^6.3.1","@codemirror/lang-html":"^6.4.11","@codemirror/lang-javascript":"^6.2.5","@codemirror/theme-one-dark":"^6.1.3","codemirror":"^6.0.2","naive-ui":"^2.40.0","pinia":"^2.2.0","vue":"^3.5.0","vue-router":"^4.4.0","vuedraggable":"^4.1.0"},"devDependencies":{"@vitejs/plugin-vue":"^5.1.0","echarts":"^6.1.0","esbuild":"^0.25.12","vite":"^6.0.0"},"allowScripts":{"esbuild@0.25.12":true,"vue-demi@0.14.10":true}}
+45 -45
View File
@@ -6,9 +6,9 @@
<n-message-provider> <n-message-provider>
<n-dialog-provider> <n-dialog-provider>
<n-notification-provider> <n-notification-provider>
<n-layout v-if="!isMobile" class="aksrt-admin-layout" has-sider> <n-layout v-if="!isMobile" class="jio-admin-layout" has-sider>
<n-layout-sider <n-layout-sider
class="aksrt-admin-sider" class="jio-admin-sider"
bordered bordered
collapse-mode="width" collapse-mode="width"
:collapsed-width="64" :collapsed-width="64"
@@ -19,16 +19,16 @@
@collapse="collapsed = true" @collapse="collapsed = true"
@expand="collapsed = false" @expand="collapsed = false"
> >
<div class="aksrt-logo"> <div class="jio-logo">
<span class="logo-icon">AK</span> <span class="logo-icon">AK</span>
<span v-if="!collapsed" class="aksrt-logo__copy"> <span v-if="!collapsed" class="jio-logo__copy">
<span class="logo-text">AKSRT</span> <span class="logo-text">Jio</span>
<span class="aksrt-logo__version">v{{ themeVersion }}</span> <span class="jio-logo__version">v{{ themeVersion }}</span>
</span> </span>
</div> </div>
<n-menu <n-menu
class="aksrt-admin-menu" class="jio-admin-menu"
:value="activeMenuKey" :value="activeMenuKey"
:collapsed="collapsed" :collapsed="collapsed"
:collapsed-width="64" :collapsed-width="64"
@@ -37,39 +37,39 @@
/> />
</n-layout-sider> </n-layout-sider>
<n-layout :native-scrollbar="false" class="aksrt-admin-content"> <n-layout :native-scrollbar="false" class="jio-admin-content">
<div class="aksrt-admin-content__inner"> <div class="jio-admin-content__inner">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<transition name="fade-slide" mode="out-in"> <transition name="fade-slide" mode="out-in">
<div class="aksrt-page-wrapper" :key="route.fullPath"> <div class="jio-page-wrapper" :key="route.fullPath">
<component :is="Component" /> <component :is="Component" />
</div> </div>
</transition> </transition>
</router-view> </router-view>
<div v-if="pageError" class="aksrt-error-fallback"> <div v-if="pageError" class="jio-error-fallback">
<p class="aksrt-error-title">页面渲染异常</p> <p class="jio-error-title">页面渲染异常</p>
<p class="aksrt-error-msg">{{ pageError }}</p> <p class="jio-error-msg">{{ pageError }}</p>
<n-button size="small" @click="pageError = null">重试</n-button> <n-button size="small" @click="pageError = null">重试</n-button>
</div> </div>
</div> </div>
</n-layout> </n-layout>
</n-layout> </n-layout>
<div v-else class="aksrt-admin-mobile"> <div v-else class="jio-admin-mobile">
<MobileTopBar :title="currentPageTitle" @toggle="drawerActive = true" /> <MobileTopBar :title="currentPageTitle" @toggle="drawerActive = true" />
<n-drawer v-model:show="drawerActive" placement="left" :width="280"> <n-drawer v-model:show="drawerActive" placement="left" :width="280">
<n-drawer-content :native-scrollbar="false" body-content-style="padding:0;"> <n-drawer-content :native-scrollbar="false" body-content-style="padding:0;">
<div class="aksrt-logo aksrt-logo--drawer"> <div class="jio-logo jio-logo--drawer">
<span class="logo-icon">AK</span> <span class="logo-icon">AK</span>
<span class="aksrt-logo__copy"> <span class="jio-logo__copy">
<span class="logo-text">AKSRT</span> <span class="logo-text">Jio</span>
<span class="aksrt-logo__version">v{{ themeVersion }}</span> <span class="jio-logo__version">v{{ themeVersion }}</span>
</span> </span>
</div> </div>
<n-menu <n-menu
class="aksrt-admin-menu" class="jio-admin-menu"
:value="activeMenuKey" :value="activeMenuKey"
:options="menuOptions" :options="menuOptions"
@update:value="handleMenuClick" @update:value="handleMenuClick"
@@ -77,18 +77,18 @@
</n-drawer-content> </n-drawer-content>
</n-drawer> </n-drawer>
<div class="aksrt-admin-mobile__body"> <div class="jio-admin-mobile__body">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
<transition name="fade-slide" mode="out-in"> <transition name="fade-slide" mode="out-in">
<div class="aksrt-page-wrapper" :key="route.fullPath"> <div class="jio-page-wrapper" :key="route.fullPath">
<component :is="Component" /> <component :is="Component" />
</div> </div>
</transition> </transition>
</router-view> </router-view>
<div v-if="pageError" class="aksrt-error-fallback"> <div v-if="pageError" class="jio-error-fallback">
<p class="aksrt-error-title">页面渲染异常</p> <p class="jio-error-title">页面渲染异常</p>
<p class="aksrt-error-msg">{{ pageError }}</p> <p class="jio-error-msg">{{ pageError }}</p>
<n-button size="small" @click="pageError = null">重试</n-button> <n-button size="small" @click="pageError = null">重试</n-button>
</div> </div>
</div> </div>
@@ -113,7 +113,7 @@ const collapsed = ref(false)
const pageError = ref(null) const pageError = ref(null)
const isMobile = ref(false) const isMobile = ref(false)
const drawerActive = ref(false) const drawerActive = ref(false)
const themeVersion = window.aksrtAdminData?.themeVersion || window.aksrtAdminData?.version || '9.0' const themeVersion = window.jioAdminData?.themeVersion || window.jioAdminData?.version || '9.0'
const MOBILE_BREAKPOINT = 960 const MOBILE_BREAKPOINT = 960
const adminThemeOverrides = { const adminThemeOverrides = {
@@ -184,7 +184,7 @@ onBeforeUnmount(() => {
provide('collapsed', collapsed) provide('collapsed', collapsed)
onErrorCaptured((err) => { onErrorCaptured((err) => {
console.error('[AKSRT] 组件渲染错误:', err) console.error('[Jio] 组件渲染错误:', err)
pageError.value = err?.message || String(err) pageError.value = err?.message || String(err)
return false return false
}) })
@@ -224,7 +224,7 @@ const menuOptions = ADMIN_SECTIONS.filter((section) => !section.hidden).map((sec
children: section.children.map((child) => ({ children: section.children.map((child) => ({
label: child.secondaryEntry ? `${child.label} · 次级` : child.label, label: child.secondaryEntry ? `${child.label} · 次级` : child.label,
key: child.key, key: child.key,
props: child.secondaryEntry ? { class: 'aksrt-menu-item--secondary' } : undefined, props: child.secondaryEntry ? { class: 'jio-menu-item--secondary' } : undefined,
})), })),
} }
}) })
@@ -254,7 +254,7 @@ const activeMenuKey = computed(() => {
return ADMIN_SECTIONS[0]?.children?.[0]?.key || 'global-common' return ADMIN_SECTIONS[0]?.children?.[0]?.key || 'global-common'
}) })
const currentPageTitle = computed(() => route.meta?.title || 'AKSRT') const currentPageTitle = computed(() => route.meta?.title || 'Jio')
function handleMenuClick(key) { function handleMenuClick(key) {
if (keyToPath[key]) { if (keyToPath[key]) {
@@ -267,17 +267,17 @@ function handleMenuClick(key) {
</script> </script>
<style scoped> <style scoped>
.aksrt-logo { .jio-logo {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
height: 64px; height: 64px;
gap: 11px; gap: 11px;
padding: 0 18px; padding: 0 18px;
border-bottom: 1px solid var(--aksrt-color-border); border-bottom: 1px solid var(--jio-color-border);
} }
.aksrt-logo--drawer { .jio-logo--drawer {
height: 64px; height: 64px;
} }
@@ -289,14 +289,14 @@ function handleMenuClick(key) {
height: 28px; height: 28px;
flex: 0 0 28px; flex: 0 0 28px;
border-radius: 7px; border-radius: 7px;
background: var(--aksrt-color-primary); background: var(--jio-color-primary);
color: #fff; color: #fff;
font-size: 12px; font-size: 12px;
font-weight: 700; font-weight: 700;
letter-spacing: 0.08em; letter-spacing: 0.08em;
} }
.aksrt-logo__copy { .jio-logo__copy {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
gap: 7px; gap: 7px;
@@ -306,56 +306,56 @@ function handleMenuClick(key) {
.logo-text { .logo-text {
font-size: 17px; font-size: 17px;
font-weight: 700; font-weight: 700;
color: var(--aksrt-color-text); color: var(--jio-color-text);
letter-spacing: .08em; letter-spacing: .08em;
} }
.aksrt-logo__version { .jio-logo__version {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 10px; font-size: 10px;
letter-spacing: .02em; letter-spacing: .02em;
} }
.aksrt-admin-content__inner { .jio-admin-content__inner {
width: 100%; width: 100%;
max-width: 1236px; max-width: 1236px;
margin: 0 auto; margin: 0 auto;
padding: 26px 28px 42px; padding: 26px 28px 42px;
} }
.aksrt-admin-mobile { .jio-admin-mobile {
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
min-height: 100vh; min-height: 100vh;
} }
.aksrt-admin-mobile__body { .jio-admin-mobile__body {
padding: 14px 12px 32px; padding: 14px 12px 32px;
} }
.aksrt-page-wrapper { .jio-page-wrapper {
min-height: calc(100vh - 120px); min-height: calc(100vh - 120px);
} }
.aksrt-error-fallback { .jio-error-fallback {
padding: 48px 20px; padding: 48px 20px;
text-align: center; text-align: center;
} }
.aksrt-error-title { .jio-error-title {
margin: 0 0 10px; margin: 0 0 10px;
font-size: 16px; font-size: 16px;
color: #d03050; color: #d03050;
} }
.aksrt-error-msg { .jio-error-msg {
margin: 0 0 16px; margin: 0 0 16px;
font-size: 13px; font-size: 13px;
color: #777; color: #777;
} }
@media (max-width: 1100px) { @media (max-width: 1100px) {
.aksrt-admin-content__inner { .jio-admin-content__inner {
padding: 22px 20px 38px; padding: 22px 20px 38px;
} }
} }
+17 -17
View File
@@ -1,16 +1,16 @@
/** /**
* AKSRT Admin API Client * Jio Admin API Client
* *
* Communicates with the WordPress REST API at /wp-json/aksrt/v1 * Communicates with the WordPress REST API at /wp-json/jio/v1
* (or index.php?rest_route=/aksrt/v1 when pretty permalinks are off). * (or index.php?rest_route=/jio/v1 when pretty permalinks are off).
* Methods are organized into domain modules while the client keeps the shared * Methods are organized into domain modules while the client keeps the shared
* request pipeline and schema-domain normalization contract. * request pipeline and schema-domain normalization contract.
*/ */
import { apiMethods } from './modules/index.js' import { apiMethods } from './modules/index.js'
const API_ROOT = window.aksrtAdminData?.apiUrl || '/wp-json/aksrt/v1' const API_ROOT = window.jioAdminData?.apiUrl || '/wp-json/jio/v1'
const NONCE = window.aksrtAdminData?.nonce || '' const NONCE = window.jioAdminData?.nonce || ''
function createIdempotencyKey() { function createIdempotencyKey() {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
@@ -34,11 +34,11 @@ function normalizeDomainKey(domain) {
/** /**
* Join REST base + endpoint correctly for both pretty and plain permalinks. * Join REST base + endpoint correctly for both pretty and plain permalinks.
* *
* Pretty: https://site/wp-json/aksrt/v1 + /settings/schema/global/common * Pretty: https://site/wp-json/jio/v1 + /settings/schema/global/common
* → https://site/wp-json/aksrt/v1/settings/schema/global/common * → https://site/wp-json/jio/v1/settings/schema/global/common
* *
* Plain: https://site/index.php?rest_route=/aksrt/v1 + /settings/schema/global/common * Plain: https://site/index.php?rest_route=/jio/v1 + /settings/schema/global/common
* → https://site/index.php?rest_route=/aksrt/v1/settings/schema/global/common * → https://site/index.php?rest_route=/jio/v1/settings/schema/global/common
* *
* @param {string} baseUrl * @param {string} baseUrl
* @param {string} endpoint path starting with /, may include ?query * @param {string} endpoint path starting with /, may include ?query
@@ -56,7 +56,7 @@ function joinRestUrl(baseUrl, endpoint) {
path = '/' + path path = '/' + path
} }
const base = String(baseUrl || '').trim() || '/wp-json/aksrt/v1' const base = String(baseUrl || '').trim() || '/wp-json/jio/v1'
// Plain permalinks: rest_route query mode // Plain permalinks: rest_route query mode
if (base.includes('rest_route=')) { if (base.includes('rest_route=')) {
@@ -68,11 +68,11 @@ function joinRestUrl(baseUrl, endpoint) {
return base.replace(/\/?$/, '') + path + (extraQuery ? (base.includes('?') ? '&' : '?') + extraQuery : '') return base.replace(/\/?$/, '') + path + (extraQuery ? (base.includes('?') ? '&' : '?') + extraQuery : '')
} }
const baseRoute = (u.searchParams.get('rest_route') || '/aksrt/v1').replace(/\/$/, '') || '/aksrt/v1' const baseRoute = (u.searchParams.get('rest_route') || '/jio/v1').replace(/\/$/, '') || '/jio/v1'
let fullRoute let fullRoute
if (path === '/') { if (path === '/') {
fullRoute = baseRoute fullRoute = baseRoute
} else if (path.startsWith('/aksrt/')) { } else if (path.startsWith('/jio/')) {
fullRoute = path fullRoute = path
} else { } else {
fullRoute = baseRoute + path fullRoute = baseRoute + path
@@ -110,7 +110,7 @@ class ApiClient {
async request(endpointOrConfig, options = {}) { async request(endpointOrConfig, options = {}) {
// Dual-signature support: // Dual-signature support:
// request('/users/1/restrictions') // request('/users/1/restrictions')
// request({ url: '/aksrt/v1/users/1/restrictions', method: 'GET' }) // request({ url: '/jio/v1/users/1/restrictions', method: 'GET' })
let endpoint, method, headers, params, body, rest let endpoint, method, headers, params, body, rest
if (typeof endpointOrConfig === 'object' && endpointOrConfig !== null) { if (typeof endpointOrConfig === 'object' && endpointOrConfig !== null) {
@@ -134,10 +134,10 @@ class ApiClient {
delete rest.data; delete rest.headers delete rest.data; delete rest.headers
} }
if (endpoint.startsWith('/wp-json/aksrt/v1')) { if (endpoint.startsWith('/wp-json/jio/v1')) {
endpoint = endpoint.replace('/wp-json/aksrt/v1', '') || '/' endpoint = endpoint.replace('/wp-json/jio/v1', '') || '/'
} else if (endpoint.startsWith('/aksrt/v1')) { } else if (endpoint.startsWith('/jio/v1')) {
endpoint = endpoint.replace('/aksrt/v1', '') || '/' endpoint = endpoint.replace('/jio/v1', '') || '/'
} }
let url = joinRestUrl(this.baseUrl, endpoint) let url = joinRestUrl(this.baseUrl, endpoint)
+5 -5
View File
@@ -1,13 +1,13 @@
/** /**
* 工单管理端 REST(命名空间 aksrt/v1/admin)。 * 工单管理端 REST(命名空间 jio/v1/admin)。
* *
* TicketRestAdmin 把三块字典 CRUD(工单状态 / 部门 / 预设回复)挂在 * TicketRestAdmin 把三块字典 CRUD(工单状态 / 部门 / 预设回复)挂在
* aksrt/v1/admin 下,全部要求 manage_options。api 客户端的 baseUrl 只到 * jio/v1/admin 下,全部要求 manage_options。api 客户端的 baseUrl 只到
* aksrt/v1,因此这里必须用 /aksrt/ 全路径形式(joinRestUrl 的 * jio/v1,因此这里必须用 /jio/ 全路径形式(joinRestUrl 的
* startsWith('/aksrt/') 分支会原样拼接,不再追加 base 前缀)。 * startsWith('/jio/') 分支会原样拼接,不再追加 base 前缀)。
*/ */
const ADMIN = '/aksrt/v1/admin/tickets' const ADMIN = '/jio/v1/admin/tickets'
export const ticketsApiMethods = { export const ticketsApiMethods = {
/* ---------------- 工单状态 ---------------- */ /* ---------------- 工单状态 ---------------- */
+32 -32
View File
@@ -1,35 +1,35 @@
<template> <template>
<div class="aksrt-deferred-page"> <div class="jio-deferred-page">
<div class="aksrt-deferred-page__icon"> <div class="jio-deferred-page__icon">
<FaIcon :icon="resolvedIcon" :size="48" /> <FaIcon :icon="resolvedIcon" :size="48" />
</div> </div>
<h2 class="aksrt-deferred-page__title">{{ resolvedTitle }}</h2> <h2 class="jio-deferred-page__title">{{ resolvedTitle }}</h2>
<p class="aksrt-deferred-page__desc">{{ resolvedDesc }}</p> <p class="jio-deferred-page__desc">{{ resolvedDesc }}</p>
<div class="aksrt-deferred-page__meta"> <div class="jio-deferred-page__meta">
<n-tag size="small" type="info">{{ resolvedStatus }}</n-tag> <n-tag size="small" type="info">{{ resolvedStatus }}</n-tag>
<n-tag v-if="resolvedPhase" size="small" type="warning">Phase {{ resolvedPhase }}</n-tag> <n-tag v-if="resolvedPhase" size="small" type="warning">Phase {{ resolvedPhase }}</n-tag>
</div> </div>
<div v-if="resolvedDependsOn.length" class="aksrt-deferred-page__depends"> <div v-if="resolvedDependsOn.length" class="jio-deferred-page__depends">
<span class="aksrt-deferred-page__label">依赖</span> <span class="jio-deferred-page__label">依赖</span>
<div class="aksrt-deferred-page__depends-list"> <div class="jio-deferred-page__depends-list">
<n-tag v-for="item in resolvedDependsOn" :key="item" size="small" type="default">{{ item }}</n-tag> <n-tag v-for="item in resolvedDependsOn" :key="item" size="small" type="default">{{ item }}</n-tag>
</div> </div>
</div> </div>
<div v-if="resolvedReason" class="aksrt-deferred-page__reason"> <div v-if="resolvedReason" class="jio-deferred-page__reason">
<span class="aksrt-deferred-page__label">原因</span> <span class="jio-deferred-page__label">原因</span>
<p>{{ resolvedReason }}</p> <p>{{ resolvedReason }}</p>
</div> </div>
<div v-if="resolvedFeatures && resolvedFeatures.length" class="aksrt-deferred-page__features"> <div v-if="resolvedFeatures && resolvedFeatures.length" class="jio-deferred-page__features">
<div <div
v-for="(feat, i) in resolvedFeatures" v-for="(feat, i) in resolvedFeatures"
:key="i" :key="i"
class="aksrt-deferred-page__feature" class="jio-deferred-page__feature"
> >
<FaIcon icon="fa fas fa-check-circle" :size="14" /> <FaIcon icon="fa fas fa-check-circle" :size="14" />
<span>{{ feat }}</span> <span>{{ feat }}</span>
</div> </div>
</div> </div>
<div class="aksrt-deferred-page__badge"> <div class="jio-deferred-page__badge">
<n-tag type="info" size="small">即将推出</n-tag> <n-tag type="info" size="small">即将推出</n-tag>
</div> </div>
</div> </div>
@@ -78,7 +78,7 @@ const resolvedFeatures = computed(() => {
</script> </script>
<style scoped> <style scoped>
.aksrt-deferred-page { .jio-deferred-page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@@ -88,75 +88,75 @@ const resolvedFeatures = computed(() => {
padding: 40px 20px; padding: 40px 20px;
} }
.aksrt-deferred-page__icon { .jio-deferred-page__icon {
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
margin-bottom: 20px; margin-bottom: 20px;
} }
.aksrt-deferred-page__title { .jio-deferred-page__title {
margin: 0 0 10px; margin: 0 0 10px;
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
} }
.aksrt-deferred-page__desc { .jio-deferred-page__desc {
margin: 0 0 20px; margin: 0 0 20px;
font-size: 14px; font-size: 14px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
max-width: 400px; max-width: 400px;
line-height: 1.6; line-height: 1.6;
} }
.aksrt-deferred-page__meta { .jio-deferred-page__meta {
display: flex; display: flex;
gap: 10px; gap: 10px;
margin-bottom: 18px; margin-bottom: 18px;
} }
.aksrt-deferred-page__depends, .jio-deferred-page__depends,
.aksrt-deferred-page__reason { .jio-deferred-page__reason {
width: min(520px, 100%); width: min(520px, 100%);
margin-bottom: 18px; margin-bottom: 18px;
text-align: left; text-align: left;
} }
.aksrt-deferred-page__label { .jio-deferred-page__label {
display: inline-block; display: inline-block;
margin-bottom: 8px; margin-bottom: 8px;
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
} }
.aksrt-deferred-page__depends-list { .jio-deferred-page__depends-list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.aksrt-deferred-page__reason p { .jio-deferred-page__reason p {
margin: 0; margin: 0;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
line-height: 1.7; line-height: 1.7;
} }
.aksrt-deferred-page__features { .jio-deferred-page__features {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
margin-bottom: 20px; margin-bottom: 20px;
} }
.aksrt-deferred-page__feature { .jio-deferred-page__feature {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.aksrt-deferred-page__feature :deep(i) { .jio-deferred-page__feature :deep(i) {
color: #52c41a; color: #52c41a;
} }
</style> </style>
+11 -11
View File
@@ -1,10 +1,10 @@
<template> <template>
<div class="aksrt-empty-state"> <div class="jio-empty-state">
<div class="aksrt-empty-state__icon"> <div class="jio-empty-state__icon">
<i :class="icon" style="font-size: 48px;"></i> <i :class="icon" style="font-size: 48px;"></i>
</div> </div>
<h3 class="aksrt-empty-state__title">{{ title }}</h3> <h3 class="jio-empty-state__title">{{ title }}</h3>
<p class="aksrt-empty-state__desc">{{ desc }}</p> <p class="jio-empty-state__desc">{{ desc }}</p>
</div> </div>
</template> </template>
@@ -17,7 +17,7 @@ defineProps({
</script> </script>
<style scoped> <style scoped>
.aksrt-empty-state { .jio-empty-state {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@@ -26,22 +26,22 @@ defineProps({
text-align: center; text-align: center;
} }
.aksrt-empty-state__icon { .jio-empty-state__icon {
margin-bottom: 20px; margin-bottom: 20px;
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
} }
.aksrt-empty-state__title { .jio-empty-state__title {
margin: 0 0 8px; margin: 0 0 8px;
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
} }
.aksrt-empty-state__desc { .jio-empty-state__desc {
margin: 0; margin: 0;
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
max-width: 360px; max-width: 360px;
line-height: 1.65; line-height: 1.65;
} }
+16 -16
View File
@@ -1,7 +1,7 @@
<template> <template>
<header class="aksrt-mobile-topbar"> <header class="jio-mobile-topbar">
<button <button
class="aksrt-mobile-topbar__menu" class="jio-mobile-topbar__menu"
type="button" type="button"
aria-label="打开菜单" aria-label="打开菜单"
@click="$emit('toggle')" @click="$emit('toggle')"
@@ -13,35 +13,35 @@
</svg> </svg>
</button> </button>
<div class="aksrt-mobile-topbar__title">{{ title }}</div> <div class="jio-mobile-topbar__title">{{ title }}</div>
<div class="aksrt-mobile-topbar__brand">AK</div> <div class="jio-mobile-topbar__brand">AK</div>
</header> </header>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
title: { type: String, default: 'AKSRT' }, title: { type: String, default: 'Jio' },
}) })
defineEmits(['toggle']) defineEmits(['toggle'])
</script> </script>
<style scoped> <style scoped>
.aksrt-mobile-topbar { .jio-mobile-topbar {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
height: 48px; height: 48px;
padding: 0 14px; padding: 0 14px;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
border-bottom: 1px solid var(--aksrt-color-border); border-bottom: 1px solid var(--jio-color-border);
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 50; z-index: 50;
} }
.aksrt-mobile-topbar__menu { .jio-mobile-topbar__menu {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -50,26 +50,26 @@ defineEmits(['toggle'])
border: none; border: none;
border-radius: 8px; border-radius: 8px;
background: transparent; background: transparent;
color: var(--aksrt-color-text); color: var(--jio-color-text);
cursor: pointer; cursor: pointer;
margin-left: -6px; margin-left: -6px;
} }
.aksrt-mobile-topbar__menu:hover { .jio-mobile-topbar__menu:hover {
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
} }
.aksrt-mobile-topbar__title { .jio-mobile-topbar__title {
flex: 1 1 auto; flex: 1 1 auto;
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.aksrt-mobile-topbar__brand { .jio-mobile-topbar__brand {
flex: 0 0 auto; flex: 0 0 auto;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -77,7 +77,7 @@ defineEmits(['toggle'])
width: 28px; width: 28px;
height: 28px; height: 28px;
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-primary); background: var(--jio-color-primary);
color: #fff; color: #fff;
font-size: 11px; font-size: 11px;
font-weight: 700; font-weight: 700;
+17 -17
View File
@@ -1,15 +1,15 @@
<template> <template>
<header class="aksrt-page-header"> <header class="jio-page-header">
<div class="aksrt-page-header__main"> <div class="jio-page-header__main">
<h2 class="aksrt-page-header__title">{{ title }}</h2> <h2 class="jio-page-header__title">{{ title }}</h2>
<p v-if="desc" class="aksrt-page-header__desc"> <p v-if="desc" class="jio-page-header__desc">
<slot name="desc">{{ desc }}</slot> <slot name="desc">{{ desc }}</slot>
</p> </p>
<div v-else-if="$slots.desc" class="aksrt-page-header__desc"> <div v-else-if="$slots.desc" class="jio-page-header__desc">
<slot name="desc" /> <slot name="desc" />
</div> </div>
</div> </div>
<div v-if="$slots.actions" class="aksrt-page-header__actions"> <div v-if="$slots.actions" class="jio-page-header__actions">
<slot name="actions" /> <slot name="actions" />
</div> </div>
</header> </header>
@@ -23,7 +23,7 @@ defineProps({
</script> </script>
<style scoped> <style scoped>
.aksrt-page-header { .jio-page-header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
@@ -32,28 +32,28 @@ defineProps({
flex-wrap: wrap; flex-wrap: wrap;
} }
.aksrt-page-header__main { .jio-page-header__main {
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0; min-width: 0;
} }
.aksrt-page-header__title { .jio-page-header__title {
margin: 0 0 6px; margin: 0 0 6px;
color: var(--aksrt-color-text); color: var(--jio-color-text);
font-size: 22px; font-size: 22px;
font-weight: 700; font-weight: 700;
letter-spacing: -0.02em; letter-spacing: -0.02em;
line-height: 1.3; line-height: 1.3;
} }
.aksrt-page-header__desc { .jio-page-header__desc {
margin: 0; margin: 0;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
line-height: 1.65; line-height: 1.65;
} }
.aksrt-page-header__actions { .jio-page-header__actions {
flex: 0 0 auto; flex: 0 0 auto;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -61,20 +61,20 @@ defineProps({
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.aksrt-page-header { .jio-page-header {
margin-bottom: 14px; margin-bottom: 14px;
gap: 10px; gap: 10px;
} }
.aksrt-page-header__title { .jio-page-header__title {
font-size: 18px; font-size: 18px;
} }
.aksrt-page-header__desc { .jio-page-header__desc {
font-size: 12px; font-size: 12px;
} }
.aksrt-page-header__actions { .jio-page-header__actions {
width: 100%; width: 100%;
} }
} }
@@ -1,5 +1,5 @@
<template> <template>
<n-form label-placement="left" label-width="110" class="aksrt-form float-common-fields"> <n-form label-placement="left" label-width="110" class="jio-form float-common-fields">
<n-form-item label="PC端显示" :show-feedback="false"> <n-form-item label="PC端显示" :show-feedback="false">
<n-switch :value="!!modelValue.pc_s" @update:value="update('pc_s', $event)" /> <n-switch :value="!!modelValue.pc_s" @update:value="update('pc_s', $event)" />
</n-form-item> </n-form-item>
@@ -10,7 +10,7 @@
<div class="float-common-fields__colors"> <div class="float-common-fields__colors">
<div class="float-common-fields__color"> <div class="float-common-fields__color">
<span>自定义图标颜色</span> <span>自定义图标颜色</span>
<AksColorPicker <JioColorPicker
:model-value="modelValue.color?.color || ''" :model-value="modelValue.color?.color || ''"
alpha alpha
clearable clearable
@@ -19,7 +19,7 @@
</div> </div>
<div class="float-common-fields__color"> <div class="float-common-fields__color">
<span>自定义背景颜色</span> <span>自定义背景颜色</span>
<AksColorPicker <JioColorPicker
:model-value="modelValue.color?.bg || ''" :model-value="modelValue.color?.bg || ''"
alpha alpha
clearable clearable
@@ -33,7 +33,7 @@
</template> </template>
<script setup> <script setup>
import AksColorPicker from '@/components/form/AksColorPicker.vue' import JioColorPicker from '@/components/form/JioColorPicker.vue'
const props = defineProps({ const props = defineProps({
modelValue: { type: Object, required: true }, modelValue: { type: Object, required: true },
@@ -1,10 +1,10 @@
<template> <template>
<div class="float-btn-panel"> <div class="float-btn-panel">
<div class="aksrt-sortable__head" v-bind="headAttrs"> <div class="jio-sortable__head" v-bind="headAttrs">
<AksSortHandle @click.stop /> <JioSortHandle @click.stop />
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<div class="aksrt-sortable__title-row"> <div class="jio-sortable__title-row">
<span class="aksrt-sortable__title">{{ meta.title }}</span> <span class="jio-sortable__title">{{ meta.title }}</span>
<template v-if="modelValue.type !== 'more'"> <template v-if="modelValue.type !== 'more'">
<n-tag v-if="modelValue.pc_s" size="small" type="info" :bordered="false">PC</n-tag> <n-tag v-if="modelValue.pc_s" size="small" type="info" :bordered="false">PC</n-tag>
<n-tag v-if="modelValue.m_s" size="small" type="warning" :bordered="false">移动</n-tag> <n-tag v-if="modelValue.m_s" size="small" type="warning" :bordered="false">移动</n-tag>
@@ -12,18 +12,18 @@
</template> </template>
<n-tag v-else size="small" :bordered="false">{{ modelValue.buttons.length }} 个</n-tag> <n-tag v-else size="small" :bordered="false">{{ modelValue.buttons.length }} 个</n-tag>
</div> </div>
<span v-if="meta.warn" class="aksrt-sortable__desc float-btn-panel__warn"> <span v-if="meta.warn" class="jio-sortable__desc float-btn-panel__warn">
<i class="fa fas fa-info-circle" aria-hidden="true" /> {{ meta.warn }} <i class="fa fas fa-info-circle" aria-hidden="true" /> {{ meta.warn }}
</span> </span>
</div> </div>
<i <i
class="fa fas aksrt-sortable__toggle" class="fa fas jio-sortable__toggle"
:class="expanded ? 'fa-chevron-down' : 'fa-chevron-right'" :class="expanded ? 'fa-chevron-down' : 'fa-chevron-right'"
aria-hidden="true" aria-hidden="true"
/> />
</div> </div>
<div v-show="expanded" class="aksrt-sortable__body"> <div v-show="expanded" class="jio-sortable__body">
<div class="float-btn-panel__subtitle">{{ meta.panel }}</div> <div class="float-btn-panel__subtitle">{{ meta.panel }}</div>
<FloatMoreButtonsEditor <FloatMoreButtonsEditor
@@ -35,7 +35,7 @@
<template v-else> <template v-else>
<FloatBtnCommonFields :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" /> <FloatBtnCommonFields :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" />
<n-form label-placement="left" label-width="110" class="aksrt-form float-btn-panel__extra"> <n-form label-placement="left" label-width="110" class="jio-form float-btn-panel__extra">
<n-form-item v-if="modelValue.type === 'qrcode'" label="一句话简介"> <n-form-item v-if="modelValue.type === 'qrcode'" label="一句话简介">
<n-input :value="modelValue.desc" @update:value="patch({ desc: $event })" /> <n-input :value="modelValue.desc" @update:value="patch({ desc: $event })" />
</n-form-item> </n-form-item>
@@ -49,7 +49,7 @@
</n-form-item> </n-form-item>
<n-form-item v-if="modelValue.type === 'service_wechat'" label="微信二维码"> <n-form-item v-if="modelValue.type === 'service_wechat'" label="微信二维码">
<AksMediaField <JioMediaField
:model-value="modelValue.wechat_img" :model-value="modelValue.wechat_img"
placeholder="选择二维码图片" placeholder="选择二维码图片"
@update:model-value="patch({ wechat_img: $event })" @update:model-value="patch({ wechat_img: $event })"
@@ -62,11 +62,11 @@
</template> </template>
<script setup> <script setup>
/** 悬浮按钮排序列表中的单个卡片;外层 .aksrt-sortable__item 由 FloatingButtonsSettings 提供。 */ /** 悬浮按钮排序列表中的单个卡片;外层 .jio-sortable__item 由 FloatingButtonsSettings 提供。 */
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import FaIconPicker from '@/components/form/FaIconPicker.vue' import FaIconPicker from '@/components/form/FaIconPicker.vue'
import AksMediaField from '@/components/form/AksMediaField.vue' import JioMediaField from '@/components/form/JioMediaField.vue'
import AksSortHandle from '@/components/form/AksSortHandle.vue' import JioSortHandle from '@/components/form/JioSortHandle.vue'
import { collapseHeadAttrs } from '@/components/form/useCollapsibleItems.js' import { collapseHeadAttrs } from '@/components/form/useCollapsibleItems.js'
import FloatBtnCommonFields from './FloatBtnCommonFields.vue' import FloatBtnCommonFields from './FloatBtnCommonFields.vue'
import FloatMoreButtonsEditor from './FloatMoreButtonsEditor.vue' import FloatMoreButtonsEditor from './FloatMoreButtonsEditor.vue'
@@ -93,12 +93,12 @@ function patch(partial) {
<style scoped> <style scoped>
.float-btn-panel__warn { .float-btn-panel__warn {
color: var(--aksrt-color-warning, #D97706); color: var(--jio-color-warning, #D97706);
} }
.float-btn-panel__subtitle { .float-btn-panel__subtitle {
margin-bottom: 12px; margin-bottom: 12px;
color: var(--aksrt-color-text); color: var(--jio-color-text);
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
} }
@@ -24,7 +24,7 @@
</n-button> </n-button>
</template> </template>
<n-form label-placement="left" label-width="110" class="aksrt-form"> <n-form label-placement="left" label-width="110" class="jio-form">
<n-form-item label="按钮简介"> <n-form-item label="按钮简介">
<n-input :value="btn.desc" @update:value="patch(index, { desc: $event })" /> <n-input :value="btn.desc" @update:value="patch(index, { desc: $event })" />
</n-form-item> </n-form-item>
@@ -16,7 +16,7 @@ export const FLOAT_BTN_META = {
more: { title: '更多按钮', panel: '添加更多自定义按钮' }, more: { title: '更多按钮', panel: '添加更多自定义按钮' },
} }
const themeUri = (window.aksrtAdminData?.themeUri || '').replace(/\/$/, '') const themeUri = (window.jioAdminData?.themeUri || '').replace(/\/$/, '')
/** 「更多按钮」出厂默认项(对齐参考主题 float_btn.more 默认值)。 */ /** 「更多按钮」出厂默认项(对齐参考主题 float_btn.more 默认值)。 */
export function giftMoreButton() { export function giftMoreButton() {
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-fa-icon-picker"> <div class="jio-fa-icon-picker">
<n-popover v-model:show="popoverShow" trigger="click" placement="bottom-start" :width="460" :style="{ padding: 0 }"> <n-popover v-model:show="popoverShow" trigger="click" placement="bottom-start" :width="460" :style="{ padding: 0 }">
<template #trigger> <template #trigger>
<n-input <n-input
@@ -19,8 +19,8 @@
</n-input> </n-input>
</template> </template>
<div class="aksrt-icon-picker__panel" @click="onPanelClick"> <div class="jio-icon-picker__panel" @click="onPanelClick">
<div class="aksrt-icon-picker__search"> <div class="jio-icon-picker__search">
<n-input v-model:value="search" placeholder="搜索图标..." size="small" clearable> <n-input v-model:value="search" placeholder="搜索图标..." size="small" clearable>
<template #prefix> <template #prefix>
<FaIcon icon="fa fas fa-search" :size="12" /> <FaIcon icon="fa fas fa-search" :size="12" />
@@ -28,12 +28,12 @@
</n-input> </n-input>
</div> </div>
<div class="aksrt-icon-picker__tabs"> <div class="jio-icon-picker__tabs">
<button <button
v-for="tab in tabs" v-for="tab in tabs"
:key="tab.id" :key="tab.id"
type="button" type="button"
class="aksrt-icon-picker__tab" class="jio-icon-picker__tab"
:class="{ 'is-active': activeTab === tab.id }" :class="{ 'is-active': activeTab === tab.id }"
@click="activeTab = tab.id" @click="activeTab = tab.id"
> >
@@ -42,23 +42,23 @@
</div> </div>
<!-- Custom SVG tab --> <!-- Custom SVG tab -->
<div v-if="activeTab === 'custom'" class="aksrt-icon-picker__custom"> <div v-if="activeTab === 'custom'" class="jio-icon-picker__custom">
<n-input v-model:value="customCode" type="textarea" placeholder='&lt;svg viewBox="0 0 1024 1024"&gt;&lt;path d="…"&gt;&lt;/path&gt;&lt;/svg&gt;' :rows="4" /> <n-input v-model:value="customCode" type="textarea" placeholder='&lt;svg viewBox="0 0 1024 1024"&gt;&lt;path d="…"&gt;&lt;/path&gt;&lt;/svg&gt;' :rows="4" />
<div class="aksrt-icon-picker__custom-actions"> <div class="jio-icon-picker__custom-actions">
<span class="aksrt-icon-picker__custom-preview" v-html="customPreview"></span> <span class="jio-icon-picker__custom-preview" v-html="customPreview"></span>
<n-button size="small" type="primary" :disabled="!customPreview" @click="insertCustom"> <n-button size="small" type="primary" :disabled="!customPreview" @click="insertCustom">
确认插入 确认插入
</n-button> </n-button>
</div> </div>
<div <div
v-if="sessionCustom.length" v-if="sessionCustom.length"
class="aksrt-icon-picker__grid aksrt-icon-picker__grid--session" class="jio-icon-picker__grid jio-icon-picker__grid--session"
data-aksrt-icon-grid="custom" data-jio-icon-grid="custom"
> >
<div <div
v-for="(svg, i) in sessionCustom" v-for="(svg, i) in sessionCustom"
:key="i" :key="i"
class="aksrt-icon-picker__item" class="jio-icon-picker__item"
:class="{ 'is-active': modelValue === `customsvg-${svg}` }" :class="{ 'is-active': modelValue === `customsvg-${svg}` }"
title="customsvg" title="customsvg"
:data-icon="`customsvg-${svg}`" :data-icon="`customsvg-${svg}`"
@@ -68,11 +68,11 @@
</div> </div>
<!-- Catalog tab --> <!-- Catalog tab -->
<div v-else class="aksrt-icon-picker__grid" data-aksrt-icon-grid="catalog"> <div v-else class="jio-icon-picker__grid" data-jio-icon-grid="catalog">
<div <div
v-for="icon in filteredIcons" v-for="icon in filteredIcons"
:key="icon" :key="icon"
class="aksrt-icon-picker__item" class="jio-icon-picker__item"
:class="{ 'is-active': modelValue === composeIconValue(activeGroup, icon) }" :class="{ 'is-active': modelValue === composeIconValue(activeGroup, icon) }"
:title="icon" :title="icon"
:data-icon="composeIconValue(activeGroup, icon)" :data-icon="composeIconValue(activeGroup, icon)"
@@ -80,11 +80,11 @@
<i v-if="activeGroup.type === 'fa'" :class="[activeTab, 'fa-' + icon]"></i> <i v-if="activeGroup.type === 'fa'" :class="[activeTab, 'fa-' + icon]"></i>
<span <span
v-else v-else
class="aksrt-icon-picker__preview-svg" class="jio-icon-picker__preview-svg"
v-html="zibsvgMarkup(`zibsvg-${icon}`)" v-html="zibsvgMarkup(`zibsvg-${icon}`)"
></span> ></span>
</div> </div>
<div v-if="filteredIcons.length === 0" class="aksrt-icon-picker__empty"> <div v-if="filteredIcons.length === 0" class="jio-icon-picker__empty">
未找到匹配图标 未找到匹配图标
</div> </div>
</div> </div>
@@ -96,7 +96,7 @@
<script setup> <script setup>
/** /**
* FaIconPicker — universal icon picker backed by the server catalog * FaIconPicker — universal icon picker backed by the server catalog
* (GET /aksrt/v1/icons/catalog): full FA5 free set, the theme's built-in * (GET /jio/v1/icons/catalog): full FA5 free set, the theme's built-in
* SVG sprite keys and inline custom SVG values. * SVG sprite keys and inline custom SVG values.
*/ */
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
@@ -176,53 +176,53 @@ onMounted(async () => {
</script> </script>
<style scoped> <style scoped>
.aksrt-icon-picker__panel { .jio-icon-picker__panel {
/* The popover teleports to <body>, outside #aksrt-admin-app where the /* The popover teleports to <body>, outside #jio-admin-app where the
palette is declared — re-declare every token the panel consumes. */ palette is declared — re-declare every token the panel consumes. */
--aksrt-color-primary: #18A058; --jio-color-primary: #18A058;
--aksrt-color-primary-hover: #36AD6A; --jio-color-primary-hover: #36AD6A;
--aksrt-color-primary-soft: rgba(24, 160, 88, 0.12); --jio-color-primary-soft: rgba(24, 160, 88, 0.12);
--aksrt-color-text-secondary: #465149; --jio-color-text-secondary: #465149;
--aksrt-color-muted: #6F7A72; --jio-color-muted: #6F7A72;
--aksrt-color-border: #E2E8E3; --jio-color-border: #E2E8E3;
padding: 12px; padding: 12px;
} }
.aksrt-icon-picker__search { .jio-icon-picker__search {
margin-bottom: 10px; margin-bottom: 10px;
} }
.aksrt-icon-picker__tabs { .jio-icon-picker__tabs {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 6px;
margin-bottom: 10px; margin-bottom: 10px;
} }
.aksrt-icon-picker__tab { .jio-icon-picker__tab {
padding: 3px 10px; padding: 3px 10px;
font-size: 13px; font-size: 13px;
line-height: 20px; line-height: 20px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 4px; border-radius: 4px;
background: transparent; background: transparent;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
cursor: pointer; cursor: pointer;
transition: all 0.15s; transition: all 0.15s;
} }
.aksrt-icon-picker__tab:hover { .jio-icon-picker__tab:hover {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
.aksrt-icon-picker__tab.is-active { .jio-icon-picker__tab.is-active {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
background: var(--aksrt-color-primary); background: var(--jio-color-primary);
color: #fff; color: #fff;
} }
.aksrt-icon-picker__grid { .jio-icon-picker__grid {
display: grid; display: grid;
grid-template-columns: repeat(8, 1fr); grid-template-columns: repeat(8, 1fr);
gap: 4px; gap: 4px;
@@ -230,7 +230,7 @@ onMounted(async () => {
overflow-y: auto; overflow-y: auto;
} }
.aksrt-icon-picker__item { .jio-icon-picker__item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -239,60 +239,60 @@ onMounted(async () => {
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
transition: all 0.15s; transition: all 0.15s;
} }
.aksrt-icon-picker__item:hover { .jio-icon-picker__item:hover {
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
.aksrt-icon-picker__item.is-active { .jio-icon-picker__item.is-active {
background: var(--aksrt-color-primary); background: var(--jio-color-primary);
color: #fff; color: #fff;
} }
.aksrt-icon-picker__item :deep(svg), .jio-icon-picker__item :deep(svg),
.aksrt-icon-picker__preview-svg :deep(svg), .jio-icon-picker__preview-svg :deep(svg),
.aksrt-icon-picker__preview-svg svg { .jio-icon-picker__preview-svg svg {
width: 18px; width: 18px;
height: 18px; height: 18px;
fill: currentColor; fill: currentColor;
} }
.aksrt-icon-picker__preview-svg { .jio-icon-picker__preview-svg {
display: inline-flex; display: inline-flex;
} }
.aksrt-icon-picker__empty { .jio-icon-picker__empty {
grid-column: 1 / -1; grid-column: 1 / -1;
text-align: center; text-align: center;
padding: 20px; padding: 20px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
} }
.aksrt-icon-picker__custom-actions { .jio-icon-picker__custom-actions {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
margin-top: 8px; margin-top: 8px;
} }
.aksrt-icon-picker__custom-preview { .jio-icon-picker__custom-preview {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 32px; width: 32px;
height: 32px; height: 32px;
border: 1px dashed var(--aksrt-color-muted); border: 1px dashed var(--jio-color-muted);
border-radius: 4px; border-radius: 4px;
} }
.aksrt-icon-picker__grid--session { .jio-icon-picker__grid--session {
margin-top: 10px; margin-top: 10px;
padding-top: 8px; padding-top: 8px;
border-top: 1px solid var(--aksrt-color-muted); border-top: 1px solid var(--jio-color-muted);
} }
</style> </style>
@@ -4,13 +4,13 @@
<!-- Built-in sprite value --> <!-- Built-in sprite value -->
<span <span
v-else-if="isZibsvgValue(value)" v-else-if="isZibsvgValue(value)"
class="aksrt-icon-value__svg" class="jio-icon-value__svg"
v-html="zibsvgMarkup(value)" v-html="zibsvgMarkup(value)"
></span> ></span>
<!-- Inline custom SVG value --> <!-- Inline custom SVG value -->
<span <span
v-else-if="isCustomSvgValue(value)" v-else-if="isCustomSvgValue(value)"
class="aksrt-icon-value__svg" class="jio-icon-value__svg"
v-html="cleanSvg(value.slice(10))" v-html="cleanSvg(value.slice(10))"
></span> ></span>
</template> </template>
@@ -35,12 +35,12 @@ const faClass = computed(() => {
</script> </script>
<style scoped> <style scoped>
.aksrt-icon-value__svg { .jio-icon-value__svg {
display: inline-flex; display: inline-flex;
} }
.aksrt-icon-value__svg :deep(svg), .jio-icon-value__svg :deep(svg),
.aksrt-icon-value__svg svg { .jio-icon-value__svg svg {
width: 1em; width: 1em;
height: 1em; height: 1em;
fill: currentColor; fill: currentColor;
@@ -17,7 +17,7 @@
<script setup> <script setup>
/** /**
* 后台唯一取色器:所有颜色字段都经由此组件,输出与 * 后台唯一取色器:所有颜色字段都经由此组件,输出与
* PHP `AKSRT\Core\Color::sanitize($value, $allow_alpha)` 同一规则的规范值。 * PHP `Jio\Core\Color::sanitize($value, $allow_alpha)` 同一规则的规范值。
* 清空 / 非法值统一回传空串。 * 清空 / 非法值统一回传空串。
*/ */
import { computed } from 'vue' import { computed } from 'vue'
@@ -1,6 +1,6 @@
<template> <template>
<!-- Between number (min/max pair) --> <!-- Between number (min/max pair) -->
<div class="aksrt-composite aksrt-composite--between"> <div class="jio-composite jio-composite--between">
<n-input-number <n-input-number
:value="betweenValue('min')" :value="betweenValue('min')"
:min="schema.min" :min="schema.min"
@@ -11,7 +11,7 @@
style="flex: 1" style="flex: 1"
@update:value="update('min', $event)" @update:value="update('min', $event)"
/> />
<span class="aksrt-composite__sep">—</span> <span class="jio-composite__sep">—</span>
<n-input-number <n-input-number
:value="betweenValue('max')" :value="betweenValue('max')"
:min="schema.min" :min="schema.min"
@@ -22,7 +22,7 @@
style="flex: 1" style="flex: 1"
@update:value="update('max', $event)" @update:value="update('max', $event)"
/> />
<span v-if="schema.unit" class="aksrt-composite__unit">{{ schema.unit }}</span> <span v-if="schema.unit" class="jio-composite__unit">{{ schema.unit }}</span>
</div> </div>
</template> </template>
@@ -52,23 +52,23 @@ function betweenValue(part) {
</script> </script>
<style scoped> <style scoped>
.aksrt-composite { .jio-composite {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.aksrt-composite--between { .jio-composite--between {
max-width: 360px; max-width: 360px;
} }
.aksrt-composite__sep { .jio-composite__sep {
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
font-size: 14px; font-size: 14px;
} }
.aksrt-composite__unit { .jio-composite__unit {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
white-space: nowrap; white-space: nowrap;
} }
@@ -1,19 +1,19 @@
<template> <template>
<div class="aksrt-field" :class="fieldClasses"> <div class="jio-field" :class="fieldClasses">
<div v-if="schema.label" class="aksrt-field__label-row"> <div v-if="schema.label" class="jio-field__label-row">
<label class="aksrt-field__label"> <label class="jio-field__label">
{{ schema.label }} {{ schema.label }}
<span v-if="schema.required" class="aksrt-field__required">*</span> <span v-if="schema.required" class="jio-field__required">*</span>
</label> </label>
<n-tooltip v-if="schema.help" trigger="hover"> <n-tooltip v-if="schema.help" trigger="hover">
<template #trigger> <template #trigger>
<FaIcon icon="fa fas fa-question-circle" :size="13" class="aksrt-field__help-icon" /> <FaIcon icon="fa fas fa-question-circle" :size="13" class="jio-field__help-icon" />
</template> </template>
{{ schema.help }} {{ schema.help }}
</n-tooltip> </n-tooltip>
</div> </div>
<p v-if="schema.description && !schema.help" class="aksrt-field__desc"> <p v-if="schema.description && !schema.help" class="jio-field__desc">
{{ schema.description }} {{ schema.description }}
</p> </p>
@@ -25,7 +25,7 @@
/> />
<!-- Input (text, email, url, password) --> <!-- Input (text, email, url, password) -->
<div v-else-if="schema.type === 'input' || schema.type === 'text' || schema.type === 'url'" class="aksrt-field__input-wrap"> <div v-else-if="schema.type === 'input' || schema.type === 'text' || schema.type === 'url'" class="jio-field__input-wrap">
<n-input <n-input
:value="secretDisplayValue" :value="secretDisplayValue"
:placeholder="schema.placeholder || ''" :placeholder="schema.placeholder || ''"
@@ -36,11 +36,11 @@
<template v-if="schema.prefix" #prefix>{{ schema.prefix }}</template> <template v-if="schema.prefix" #prefix>{{ schema.prefix }}</template>
<template v-if="schema.suffix" #suffix>{{ schema.suffix }}</template> <template v-if="schema.suffix" #suffix>{{ schema.suffix }}</template>
</n-input> </n-input>
<AksSecretClear :visible="secretClearVisible" :marked="secretMarkedForClear" @toggle="toggleSecretClear" /> <JioSecretClear :visible="secretClearVisible" :marked="secretMarkedForClear" @toggle="toggleSecretClear" />
</div> </div>
<!-- Textarea(secret 时不回显已配置值,聚焦后输入新值即覆盖) --> <!-- Textarea(secret 时不回显已配置值,聚焦后输入新值即覆盖) -->
<div v-else-if="schema.type === 'textarea'" class="aksrt-field__input-wrap"> <div v-else-if="schema.type === 'textarea'" class="jio-field__input-wrap">
<n-input <n-input
:value="secretTextareaValue" :value="secretTextareaValue"
type="textarea" type="textarea"
@@ -49,11 +49,11 @@
:disabled="schema.disabled" :disabled="schema.disabled"
@update:value="emit('update:modelValue', $event)" @update:value="emit('update:modelValue', $event)"
/> />
<AksSecretClear :visible="secretClearVisible" :marked="secretMarkedForClear" @toggle="toggleSecretClear" /> <JioSecretClear :visible="secretClearVisible" :marked="secretMarkedForClear" @toggle="toggleSecretClear" />
</div> </div>
<!-- Number --> <!-- Number -->
<div v-else-if="schema.type === 'number' || schema.type === 'spinner'" class="aksrt-field__number"> <div v-else-if="schema.type === 'number' || schema.type === 'spinner'" class="jio-field__number">
<n-input-number <n-input-number
:value="modelValue" :value="modelValue"
:min="schema.min" :min="schema.min"
@@ -64,11 +64,11 @@
style="width: 100%" style="width: 100%"
@update:value="emit('update:modelValue', $event)" @update:value="emit('update:modelValue', $event)"
/> />
<span v-if="schema.unit" class="aksrt-field__unit">{{ schema.unit }}</span> <span v-if="schema.unit" class="jio-field__unit">{{ schema.unit }}</span>
</div> </div>
<!-- Select --> <!-- Select -->
<div v-else-if="schema.type === 'select'" class="aksrt-field__ordered-select"> <div v-else-if="schema.type === 'select'" class="jio-field__ordered-select">
<n-select <n-select
:value="modelValue" :value="modelValue"
:options="normalizedOptions" :options="normalizedOptions"
@@ -78,7 +78,7 @@
:disabled="schema.disabled" :disabled="schema.disabled"
@update:value="emit('update:modelValue', $event)" @update:value="emit('update:modelValue', $event)"
/> />
<AksSelectedOrder <JioSelectedOrder
v-if="schema.multiple && schema.sortable && Array.isArray(modelValue)" v-if="schema.multiple && schema.sortable && Array.isArray(modelValue)"
:model-value="modelValue" :model-value="modelValue"
:options="normalizedOptions" :options="normalizedOptions"
@@ -87,7 +87,7 @@
/> />
</div> </div>
<div v-else-if="schema.type === 'async_select'" class="aksrt-field__ordered-select"> <div v-else-if="schema.type === 'async_select'" class="jio-field__ordered-select">
<n-select <n-select
:value="schema.multiple === true && !Array.isArray(modelValue) ? [] : modelValue" :value="schema.multiple === true && !Array.isArray(modelValue) ? [] : modelValue"
:options="asyncOptions" :options="asyncOptions"
@@ -100,7 +100,7 @@
@search="handleAsyncSearch" @search="handleAsyncSearch"
@update:value="emit('update:modelValue', $event)" @update:value="emit('update:modelValue', $event)"
/> />
<AksSelectedOrder <JioSelectedOrder
v-if="schema.multiple && schema.sortable && Array.isArray(modelValue)" v-if="schema.multiple && schema.sortable && Array.isArray(modelValue)"
:model-value="modelValue" :model-value="modelValue"
:options="asyncOptions" :options="asyncOptions"
@@ -199,7 +199,7 @@
</n-checkbox-group> </n-checkbox-group>
<!-- Color picker --> <!-- Color picker -->
<AksColorPicker <JioColorPicker
v-else-if="schema.type === 'color'" v-else-if="schema.type === 'color'"
:model-value="typeof modelValue === 'string' ? modelValue : ''" :model-value="typeof modelValue === 'string' ? modelValue : ''"
:alpha="!!schema.showAlpha" :alpha="!!schema.showAlpha"
@@ -208,12 +208,12 @@
@update:model-value="emit('update:modelValue', $event)" @update:model-value="emit('update:modelValue', $event)"
/> />
<div v-else-if="schema.type === 'palette'" class="aksrt-field__palette"> <div v-else-if="schema.type === 'palette'" class="jio-field__palette">
<button <button
v-for="opt in normalizedOptions" v-for="opt in normalizedOptions"
:key="opt.value" :key="opt.value"
type="button" type="button"
class="aksrt-field__palette-item" class="jio-field__palette-item"
:class="{ 'is-active': modelValue === opt.value }" :class="{ 'is-active': modelValue === opt.value }"
:style="{ background: opt.label }" :style="{ background: opt.label }"
:title="opt.value" :title="opt.value"
@@ -230,7 +230,7 @@
/> />
<!-- Media upload --> <!-- Media upload -->
<AksMediaField <JioMediaField
v-else-if="schema.type === 'media' || schema.type === 'upload'" v-else-if="schema.type === 'media' || schema.type === 'upload'"
:model-value="modelValue" :model-value="modelValue"
:accept="schema.accept" :accept="schema.accept"
@@ -239,7 +239,7 @@
/> />
<!-- WordPress image gallery (attachment ID array) --> <!-- WordPress image gallery (attachment ID array) -->
<AksGalleryField <JioGalleryField
v-else-if="schema.type === 'gallery'" v-else-if="schema.type === 'gallery'"
:model-value="Array.isArray(modelValue) ? modelValue : []" :model-value="Array.isArray(modelValue) ? modelValue : []"
:title="schema.label || '选择图片'" :title="schema.label || '选择图片'"
@@ -259,7 +259,7 @@
/> />
<!-- Code editor with syntax highlighting (CodeMirror 6) --> <!-- Code editor with syntax highlighting (CodeMirror 6) -->
<AksCodeEditor <JioCodeEditor
v-else-if="schema.type === 'code'" v-else-if="schema.type === 'code'"
:model-value="modelValue" :model-value="modelValue"
:language="schema.language || 'html'" :language="schema.language || 'html'"
@@ -281,7 +281,7 @@
<!-- Pure HTML content (no form field, just display) --> <!-- Pure HTML content (no form field, just display) -->
<div <div
v-else-if="schema.type === 'content'" v-else-if="schema.type === 'content'"
class="aksrt-field__content" class="jio-field__content"
v-html="schema.content || modelValue || ''" v-html="schema.content || modelValue || ''"
/> />
@@ -316,7 +316,7 @@
/> />
<!-- Object composite: between_number (min/max pair) --> <!-- Object composite: between_number (min/max pair) -->
<AksCompositeField <JioCompositeField
v-else-if="schema.type === 'between_number'" v-else-if="schema.type === 'between_number'"
:schema="schema" :schema="schema"
:model-value="modelValue" :model-value="modelValue"
@@ -324,7 +324,7 @@
/> />
<!-- Image select (radio with image preview) --> <!-- Image select (radio with image preview) -->
<AksImageSelectField <JioImageSelectField
v-else-if="schema.type === 'image_select'" v-else-if="schema.type === 'image_select'"
:model-value="modelValue" :model-value="modelValue"
:options="normalizedOptions" :options="normalizedOptions"
@@ -334,24 +334,24 @@
/> />
<!-- Fieldset (single nested object) --> <!-- Fieldset (single nested object) -->
<div v-else-if="schema.type === 'fieldset' || schema.type === 'accordion'" class="aksrt-field__fieldset"> <div v-else-if="schema.type === 'fieldset' || schema.type === 'accordion'" class="jio-field__fieldset">
<template v-if="fieldsetSections.length"> <template v-if="fieldsetSections.length">
<div <div
v-for="(section, sIndex) in fieldsetSections" v-for="(section, sIndex) in fieldsetSections"
:key="section.title" :key="section.title"
class="aksrt-field__accordion-section" class="jio-field__accordion-section"
:class="{ 'is-collapsed': !isFieldsetSectionOpen(sIndex) }" :class="{ 'is-collapsed': !isFieldsetSectionOpen(sIndex) }"
> >
<div class="aksrt-field__accordion-section-head" @click="toggleFieldsetSection(sIndex)"> <div class="jio-field__accordion-section-head" @click="toggleFieldsetSection(sIndex)">
<span class="aksrt-field__accordion-section-title">{{ section.title }}</span> <span class="jio-field__accordion-section-title">{{ section.title }}</span>
<FaIcon <FaIcon
:icon="isFieldsetSectionOpen(sIndex) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'" :icon="isFieldsetSectionOpen(sIndex) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'"
:size="12" :size="12"
class="aksrt-field__accordion-section-toggle" class="jio-field__accordion-section-toggle"
/> />
</div> </div>
<div v-show="isFieldsetSectionOpen(sIndex)" class="aksrt-field__accordion-section-body"> <div v-show="isFieldsetSectionOpen(sIndex)" class="jio-field__accordion-section-body">
<AksField <JioField
v-for="field in sectionFields(section)" v-for="field in sectionFields(section)"
:key="field.key" :key="field.key"
:schema="field" :schema="field"
@@ -363,7 +363,7 @@
</div> </div>
</template> </template>
<template v-if="!fieldsetSections.length"> <template v-if="!fieldsetSections.length">
<AksField <JioField
v-for="field in visibleNestedFields" v-for="field in visibleNestedFields"
:key="field.key" :key="field.key"
:schema="field" :schema="field"
@@ -374,7 +374,7 @@
</template> </template>
</div> </div>
<div v-else-if="schema.type === 'link'" class="aksrt-field__link"> <div v-else-if="schema.type === 'link'" class="jio-field__link">
<n-input :value="modelValue?.url || ''" placeholder="https://" @update:value="updateLink('url', $event)" /> <n-input :value="modelValue?.url || ''" placeholder="https://" @update:value="updateLink('url', $event)" />
<n-select :value="modelValue?.target || ''" :options="linkTargetOptions" @update:value="updateLink('target', $event)" /> <n-select :value="modelValue?.target || ''" :options="linkTargetOptions" @update:value="updateLink('target', $event)" />
<n-input :value="modelValue?.text || ''" placeholder="链接文字(可选)" @update:value="updateLink('text', $event)" /> <n-input :value="modelValue?.text || ''" placeholder="链接文字(可选)" @update:value="updateLink('text', $event)" />
@@ -386,54 +386,54 @@
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="key" item-key="key"
:disabled="schema.disabled" :disabled="schema.disabled"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element: item, index }"> <template #item="{ element: item, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div <div
class="aksrt-sortable__head" class="jio-sortable__head"
v-bind="item.fields?.length ? listItemHeadAttrs(item.key) : {}" v-bind="item.fields?.length ? listItemHeadAttrs(item.key) : {}"
> >
<AksSortHandle @click.stop /> <JioSortHandle @click.stop />
<span class="aksrt-sortable__index">{{ index + 1 }}</span> <span class="jio-sortable__index">{{ index + 1 }}</span>
<span class="aksrt-sortable__main"> <span class="jio-sortable__main">
<span class="aksrt-sortable__title">{{ item.label }}</span> <span class="jio-sortable__title">{{ item.label }}</span>
</span> </span>
<FaIcon <FaIcon
v-if="item.fields?.length" v-if="item.fields?.length"
:icon="isListItemOpen(item.key) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'" :icon="isListItemOpen(item.key) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'"
:size="12" :size="12"
class="aksrt-sortable__toggle" class="jio-sortable__toggle"
/> />
</div> </div>
<div v-if="item.fields?.length" v-show="isListItemOpen(item.key)" class="aksrt-sortable__body aksrt-field__sortable-body"> <div v-if="item.fields?.length" v-show="isListItemOpen(item.key)" class="jio-sortable__body jio-field__sortable-body">
<AksField v-for="field in item.fields" :key="field.key" :schema="field" :model-value="modelValue?.[item.key]?.[field.key] ?? field.default" :form-data="formData" @update:model-value="updateSortable(item.key, field.key, $event)" /> <JioField v-for="field in item.fields" :key="field.key" :schema="field" :model-value="modelValue?.[item.key]?.[field.key] ?? field.default" :form-data="formData" @update:model-value="updateSortable(item.key, field.key, $event)" />
</div> </div>
</div> </div>
</template> </template>
</draggable> </draggable>
<!-- Repeater (array of objects) — inline expand (default, draggable) --> <!-- Repeater (array of objects) — inline expand (default, draggable) -->
<div v-else-if="(schema.type === 'repeater' || schema.type === 'group') && schema.ui !== 'list-modal'" class="aksrt-field__repeater"> <div v-else-if="(schema.type === 'repeater' || schema.type === 'group') && schema.ui !== 'list-modal'" class="jio-field__repeater">
<draggable <draggable
v-if="repeaterDragList.length" v-if="repeaterDragList.length"
v-model="repeaterDragList" v-model="repeaterDragList"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
:item-key="repeaterDragKey" :item-key="repeaterDragKey"
:disabled="schema.disabled" :disabled="schema.disabled"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head" v-bind="repeaterHeadAttrs(repeaterDragKey(element))"> <div class="jio-sortable__head" v-bind="repeaterHeadAttrs(repeaterDragKey(element))">
<AksSortHandle @click.stop /> <JioSortHandle @click.stop />
<span class="aksrt-sortable__index">{{ index + 1 }}</span> <span class="jio-sortable__index">{{ index + 1 }}</span>
<span class="aksrt-sortable__main"> <span class="jio-sortable__main">
<span class="aksrt-sortable__title aksrt-field__repeater-summary"> <span class="jio-sortable__title jio-field__repeater-summary">
{{ repeaterItemSummary(element) || '未填写' }} {{ repeaterItemSummary(element) || '未填写' }}
</span> </span>
</span> </span>
<div class="aksrt-sortable__actions" @click.stop> <div class="jio-sortable__actions" @click.stop>
<n-button <n-button
size="tiny" size="tiny"
type="error" type="error"
@@ -448,12 +448,12 @@
<FaIcon <FaIcon
:icon="isRepeaterItemOpen(repeaterDragKey(element)) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'" :icon="isRepeaterItemOpen(repeaterDragKey(element)) ? 'fa fas fa-chevron-down' : 'fa fas fa-chevron-right'"
:size="12" :size="12"
class="aksrt-sortable__toggle" class="jio-sortable__toggle"
/> />
</div> </div>
<div v-show="isRepeaterItemOpen(repeaterDragKey(element))" class="aksrt-sortable__body aksrt-field__repeater-fields"> <div v-show="isRepeaterItemOpen(repeaterDragKey(element))" class="jio-sortable__body jio-field__repeater-fields">
<template v-for="field in (schema.fields || [])" :key="field.key"> <template v-for="field in (schema.fields || [])" :key="field.key">
<AksField <JioField
v-if="matchDependency(field.dependsOn, element)" v-if="matchDependency(field.dependsOn, element)"
:schema="field" :schema="field"
:model-value="element[field.key]" :model-value="element[field.key]"
@@ -466,7 +466,7 @@
</div> </div>
</template> </template>
</draggable> </draggable>
<div v-else class="aksrt-sortable__empty"> <div v-else class="jio-sortable__empty">
<FaIcon icon="fa fas fa-inbox" :size="18" /> <FaIcon icon="fa fas fa-inbox" :size="18" />
<span>{{ schema.emptyText || '暂无数据' }}</span> <span>{{ schema.emptyText || '暂无数据' }}</span>
</div> </div>
@@ -483,7 +483,7 @@
</div> </div>
<!-- Repeater list-modal: draggable card list + modal editor --> <!-- Repeater list-modal: draggable card list + modal editor -->
<AksRepeaterListModal <JioRepeaterListModal
v-else-if="(schema.type === 'repeater' || schema.type === 'group') && schema.ui === 'list-modal'" v-else-if="(schema.type === 'repeater' || schema.type === 'group') && schema.ui === 'list-modal'"
:schema="schema" :schema="schema"
:model-value="modelValue" :model-value="modelValue"
@@ -503,35 +503,35 @@
/> />
<!-- Validation message --> <!-- Validation message -->
<p v-if="errorMessage" class="aksrt-field__error">{{ errorMessage }}</p> <p v-if="errorMessage" class="jio-field__error">{{ errorMessage }}</p>
</div> </div>
</template> </template>
<script setup> <script setup>
/** /**
* AksField — renders a single form field based on its schema definition. * JioField — renders a single form field based on its schema definition.
* *
* Supported types: switch, input/text, textarea, number, select, radio, * Supported types: switch, input/text, textarea, number, select, radio,
* checkbox, color, icon, media, gallery, slider, code, alert, fieldset, sortable, * checkbox, color, icon, media, gallery, slider, code, alert, fieldset, sortable,
* repeater (inline|list-modal), custom (slot). * repeater (inline|list-modal), custom (slot).
* *
* 所有可拖拽列表(sortable / 已选值排序 / repeater)共用 sortable-list.css + * 所有可拖拽列表(sortable / 已选值排序 / repeater)共用 sortable-list.css +
* SORTABLE_LIST_ATTRS + AksSortHandle。 * SORTABLE_LIST_ATTRS + JioSortHandle。
*/ */
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import FaIcon from './FaIcon.vue' import FaIcon from './FaIcon.vue'
import FaIconPicker from './FaIconPicker.vue' import FaIconPicker from './FaIconPicker.vue'
import AksMediaField from './AksMediaField.vue' import JioMediaField from './JioMediaField.vue'
import AksGalleryField from './AksGalleryField.vue' import JioGalleryField from './JioGalleryField.vue'
import AksCodeEditor from './AksCodeEditor.vue' import JioCodeEditor from './JioCodeEditor.vue'
import AksCompositeField from './AksCompositeField.vue' import JioCompositeField from './JioCompositeField.vue'
import AksColorPicker from './AksColorPicker.vue' import JioColorPicker from './JioColorPicker.vue'
import AksImageSelectField from './AksImageSelectField.vue' import JioImageSelectField from './JioImageSelectField.vue'
import AksSortHandle from './AksSortHandle.vue' import JioSortHandle from './JioSortHandle.vue'
import AksSecretClear from './AksSecretClear.vue' import JioSecretClear from './JioSecretClear.vue'
import AksSelectedOrder from './AksSelectedOrder.vue' import JioSelectedOrder from './JioSelectedOrder.vue'
import AksRepeaterListModal from './AksRepeaterListModal.vue' import JioRepeaterListModal from './JioRepeaterListModal.vue'
import { buildFieldsetSections } from './fieldset-sections.js' import { buildFieldsetSections } from './fieldset-sections.js'
import { matchDependency } from './field-dependency.js' import { matchDependency } from './field-dependency.js'
import { SORTABLE_LIST_ATTRS } from './sortable-options.js' import { SORTABLE_LIST_ATTRS } from './sortable-options.js'
@@ -567,12 +567,12 @@ const {
} = useFieldRemoteOptions(props) } = useFieldRemoteOptions(props)
const fieldClasses = computed(() => ({ const fieldClasses = computed(() => ({
'aksrt-field--disabled': props.schema.disabled, 'jio-field--disabled': props.schema.disabled,
'aksrt-field--inline': props.schema.inline, 'jio-field--inline': props.schema.inline,
[`aksrt-field--${props.schema.type}`]: !!props.schema.type, [`jio-field--${props.schema.type}`]: !!props.schema.type,
})) }))
const secretMarkedForClear = computed(() => props.schema.secret && props.modelValue === '__AKSRT_CLEAR_SECRET__') const secretMarkedForClear = computed(() => props.schema.secret && props.modelValue === '__JIO_CLEAR_SECRET__')
const secretDisplayValue = computed(() => secretMarkedForClear.value ? '' : props.modelValue) const secretDisplayValue = computed(() => secretMarkedForClear.value ? '' : props.modelValue)
/** 已配置密钥(服务端回传 '***'):textarea 不回显掩码,留空即保持原值。 */ /** 已配置密钥(服务端回传 '***'):textarea 不回显掩码,留空即保持原值。 */
const secretConfigured = computed(() => props.schema.secret && props.modelValue === '***') const secretConfigured = computed(() => props.schema.secret && props.modelValue === '***')
@@ -580,7 +580,7 @@ const secretClearVisible = computed(() => secretConfigured.value || secretMarked
const secretTextareaValue = computed(() => secretConfigured.value ? '' : secretDisplayValue.value) const secretTextareaValue = computed(() => secretConfigured.value ? '' : secretDisplayValue.value)
function toggleSecretClear() { function toggleSecretClear() {
emit('update:modelValue', secretMarkedForClear.value ? '***' : '__AKSRT_CLEAR_SECRET__') emit('update:modelValue', secretMarkedForClear.value ? '***' : '__JIO_CLEAR_SECRET__')
} }
/** Normalize options: support string[], {label, value}[], and dynamic formData-key references */ /** Normalize options: support string[], {label, value}[], and dynamic formData-key references */
@@ -682,7 +682,7 @@ function updateSortable(itemKey, fieldKey, value) {
emit('update:modelValue', { ...current, [itemKey]: { ...(current[itemKey] || {}), [fieldKey]: value } }) emit('update:modelValue', { ...current, [itemKey]: { ...(current[itemKey] || {}), [fieldKey]: value } })
} }
// ============ Repeater(inline 展开;list-modal 见 AksRepeaterListModal) ============ // ============ Repeater(inline 展开;list-modal 见 JioRepeaterListModal) ============
const repeaterLength = computed(() => Array.isArray(props.modelValue) ? props.modelValue.length : 0) const repeaterLength = computed(() => Array.isArray(props.modelValue) ? props.modelValue.length : 0)
const reachedRepeaterMinimum = computed(() => repeaterLength.value <= Number(props.schema.min || 0)) const reachedRepeaterMinimum = computed(() => repeaterLength.value <= Number(props.schema.min || 0))
const reachedRepeaterMaximum = computed(() => Number(props.schema.max || 0) > 0 && repeaterLength.value >= Number(props.schema.max)) const reachedRepeaterMaximum = computed(() => Number(props.schema.max || 0) > 0 && repeaterLength.value >= Number(props.schema.max))
@@ -754,165 +754,165 @@ function updateRepeaterItem(index, fieldKey, value) {
</script> </script>
<style scoped> <style scoped>
.aksrt-field { .jio-field {
margin-bottom: 18px; margin-bottom: 18px;
} }
.aksrt-field:last-child { .jio-field:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
/* 结构化分组(会员商品/续费商品/积分兑换/升级价格)与相邻字段之间留出更明确的间隔, /* 结构化分组(会员商品/续费商品/积分兑换/升级价格)与相邻字段之间留出更明确的间隔,
* 避免两个分组上下贴在一起,和参考主题的留白一致。 */ * 避免两个分组上下贴在一起,和参考主题的留白一致。 */
.aksrt-field--group, .jio-field--group,
.aksrt-field--repeater, .jio-field--repeater,
.aksrt-field--accordion, .jio-field--accordion,
.aksrt-field--fieldset { .jio-field--fieldset {
margin-bottom: 26px; margin-bottom: 26px;
} }
.aksrt-field__input-wrap { .jio-field__input-wrap {
display: grid; display: grid;
gap: 8px; gap: 8px;
} }
.aksrt-field__label-row { .jio-field__label-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
margin-bottom: 6px; margin-bottom: 6px;
} }
.aksrt-field__label { .jio-field__label {
font-size: 13px; font-size: 13px;
font-weight: 500; font-weight: 500;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
} }
.aksrt-field__required { .jio-field__required {
color: #d03050; color: #d03050;
margin-left: 2px; margin-left: 2px;
} }
.aksrt-field__help-icon { .jio-field__help-icon {
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
cursor: help; cursor: help;
transition: color 0.15s; transition: color 0.15s;
} }
.aksrt-field__help-icon:hover { .jio-field__help-icon:hover {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
.aksrt-field__desc { .jio-field__desc {
margin: -2px 0 8px; margin: -2px 0 8px;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
line-height: 1.5; line-height: 1.5;
} }
.aksrt-field__error { .jio-field__error {
margin: 4px 0 0; margin: 4px 0 0;
font-size: 12px; font-size: 12px;
color: #d03050; color: #d03050;
} }
.aksrt-field--disabled { .jio-field--disabled {
opacity: 0.6; opacity: 0.6;
pointer-events: none; pointer-events: none;
} }
.aksrt-field__number { .jio-field__number {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
max-width: 360px; max-width: 360px;
} }
.aksrt-field__unit { .jio-field__unit {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
white-space: nowrap; white-space: nowrap;
} }
.aksrt-field__palette { .jio-field__palette {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.aksrt-field__palette-item { .jio-field__palette-item {
width: 34px; width: 34px;
height: 26px; height: 26px;
padding: 0; padding: 0;
border: 3px solid var(--aksrt-color-surface); border: 3px solid var(--jio-color-surface);
border-radius: 3px; border-radius: 3px;
box-shadow: 0 0 0 1px var(--aksrt-color-border-strong); box-shadow: 0 0 0 1px var(--jio-color-border-strong);
cursor: pointer; cursor: pointer;
} }
.aksrt-field__palette-item.is-active { .jio-field__palette-item.is-active {
box-shadow: 0 0 0 2px var(--aksrt-color-primary); box-shadow: 0 0 0 2px var(--jio-color-primary);
} }
.aksrt-field__link { .jio-field__link {
display: grid; display: grid;
grid-template-columns: minmax(220px, 1fr) 120px minmax(140px, .5fr); grid-template-columns: minmax(220px, 1fr) 120px minmax(140px, .5fr);
gap: 8px; gap: 8px;
} }
/* sortable 卡片展开区:两列字段栅格(卡片本身见 styles/sortable-list.css) */ /* sortable 卡片展开区:两列字段栅格(卡片本身见 styles/sortable-list.css) */
.aksrt-field__sortable-body { .jio-field__sortable-body {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px; gap: 16px;
} }
/* Fieldset / Accordion */ /* Fieldset / Accordion */
.aksrt-field__fieldset { .jio-field__fieldset {
padding: 14px; padding: 14px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
.aksrt-field__accordion-section + .aksrt-field__accordion-section { .jio-field__accordion-section + .jio-field__accordion-section {
margin-top: 14px; margin-top: 14px;
} }
.aksrt-field__accordion-section-head { .jio-field__accordion-section-head {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 8px; gap: 8px;
padding: 8px 10px; padding: 8px 10px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 6px; border-radius: 6px;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
transition: border-color 0.15s, color 0.15s; transition: border-color 0.15s, color 0.15s;
} }
.aksrt-field__accordion-section-head:hover { .jio-field__accordion-section-head:hover {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
.aksrt-field__accordion-section-title { .jio-field__accordion-section-title {
min-width: 0; min-width: 0;
} }
.aksrt-field__accordion-section-toggle { .jio-field__accordion-section-toggle {
flex-shrink: 0; flex-shrink: 0;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
} }
.aksrt-field__accordion-section-body { .jio-field__accordion-section-body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
@@ -920,58 +920,58 @@ function updateRepeaterItem(index, fieldKey, value) {
} }
/* Repeater inline(卡片 / 手柄 / 拖拽态见 styles/sortable-list.css) */ /* Repeater inline(卡片 / 手柄 / 拖拽态见 styles/sortable-list.css) */
.aksrt-field__repeater { .jio-field__repeater {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
} }
.aksrt-field__repeater-fields { .jio-field__repeater-fields {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
} }
/* Content field */ /* Content field */
.aksrt-field__content { .jio-field__content {
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
line-height: 1.6; line-height: 1.6;
} }
.aksrt-field__content :deep(p) { .jio-field__content :deep(p) {
margin: 0; margin: 0;
} }
.aksrt-field__content :deep(p + ul) { .jio-field__content :deep(p + ul) {
margin-top: 6px; margin-top: 6px;
} }
.aksrt-field__content :deep(ul) { .jio-field__content :deep(ul) {
margin: 0; margin: 0;
padding-left: 18px; padding-left: 18px;
line-height: 1.9; line-height: 1.9;
} }
/* 说明文字的小号灰色段落与警示文字(schema content 里用 class 引用) */ /* 说明文字的小号灰色段落与警示文字(schema content 里用 class 引用) */
.aksrt-field__content :deep(.aksrt-hint) { .jio-field__content :deep(.jio-hint) {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 12px; font-size: 12px;
line-height: 1.7; line-height: 1.7;
} }
.aksrt-field__content :deep(.aksrt-hint + .aksrt-hint) { .jio-field__content :deep(.jio-hint + .jio-hint) {
margin-top: 6px; margin-top: 6px;
} }
.aksrt-field__content :deep(.aksrt-warn) { .jio-field__content :deep(.jio-warn) {
color: var(--aksrt-color-warning, #d97706); color: var(--jio-color-warning, #d97706);
} }
/* Mobile */ /* Mobile */
@media (max-width: 768px) { @media (max-width: 768px) {
.aksrt-field__link, .jio-field__link,
.aksrt-field__sortable-body { .jio-field__sortable-body {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
@@ -1,26 +1,26 @@
<template> <template>
<div class="aksrt-field-group" :class="{ 'is-collapsible': collapsible, 'is-collapsed': collapsible && collapsed }"> <div class="jio-field-group" :class="{ 'is-collapsible': collapsible, 'is-collapsed': collapsible && collapsed }">
<div <div
v-if="title" v-if="title"
class="aksrt-field-group__header" class="jio-field-group__header"
:class="{ 'is-clickable': collapsible }" :class="{ 'is-clickable': collapsible }"
@click="collapsible ? toggleCollapse() : undefined" @click="collapsible ? toggleCollapse() : undefined"
> >
<div class="aksrt-field-group__header-left"> <div class="jio-field-group__header-left">
<FaIcon v-if="icon" :icon="icon" :size="16" class="aksrt-field-group__icon" /> <FaIcon v-if="icon" :icon="icon" :size="16" class="jio-field-group__icon" />
<div> <div>
<h3 class="aksrt-field-group__title">{{ title }}</h3> <h3 class="jio-field-group__title">{{ title }}</h3>
<p v-if="description" class="aksrt-field-group__desc">{{ description }}</p> <p v-if="description" class="jio-field-group__desc">{{ description }}</p>
</div> </div>
</div> </div>
<div class="aksrt-field-group__header-right"> <div class="jio-field-group__header-right">
<div v-if="$slots.actions" class="aksrt-field-group__actions" @click.stop> <div v-if="$slots.actions" class="jio-field-group__actions" @click.stop>
<slot name="actions" /> <slot name="actions" />
</div> </div>
<button <button
v-if="collapsible" v-if="collapsible"
type="button" type="button"
class="aksrt-field-group__collapse-btn" class="jio-field-group__collapse-btn"
:aria-expanded="(!collapsed).toString()" :aria-expanded="(!collapsed).toString()"
:title="collapsed ? '展开配置' : '收起配置'" :title="collapsed ? '展开配置' : '收起配置'"
@click.stop="toggleCollapse" @click.stop="toggleCollapse"
@@ -34,8 +34,8 @@
</div> </div>
</div> </div>
<transition name="aksrt-collapse"> <transition name="jio-collapse">
<div v-show="!collapsed" class="aksrt-field-group__body"> <div v-show="!collapsed" class="jio-field-group__body">
<slot /> <slot />
</div> </div>
</transition> </transition>
@@ -44,7 +44,7 @@
<script setup> <script setup>
/** /**
* AksFieldGroup — card-style container for grouping related form fields. * JioFieldGroup — card-style container for grouping related form fields.
* Supports collapsible sections, icon headers, and description text. * Supports collapsible sections, icon headers, and description text.
* *
* defaultCollapsed only seeds the initial state; afterwards the user toggles freely. * defaultCollapsed only seeds the initial state; afterwards the user toggles freely.
@@ -69,16 +69,16 @@ function toggleCollapse() {
</script> </script>
<style scoped> <style scoped>
.aksrt-field-group { .jio-field-group {
margin-bottom: 20px; margin-bottom: 20px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 12px; border-radius: 12px;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
box-shadow: var(--aksrt-shadow-card); box-shadow: var(--jio-shadow-card);
overflow: hidden; overflow: hidden;
} }
.aksrt-field-group__header { .jio-field-group__header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
@@ -86,66 +86,66 @@ function toggleCollapse() {
gap: 12px; gap: 12px;
} }
.aksrt-field-group__header.is-clickable { .jio-field-group__header.is-clickable {
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
.aksrt-field-group__header.is-clickable:hover .aksrt-field-group__title { .jio-field-group__header.is-clickable:hover .jio-field-group__title {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
.aksrt-field-group.is-collapsed .aksrt-field-group__header { .jio-field-group.is-collapsed .jio-field-group__header {
padding-bottom: 18px; padding-bottom: 18px;
} }
.aksrt-field-group__header-left { .jio-field-group__header-left {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
gap: 10px; gap: 10px;
min-width: 0; min-width: 0;
} }
.aksrt-field-group__header-right { .jio-field-group__header-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
flex-shrink: 0; flex-shrink: 0;
} }
.aksrt-field-group__icon { .jio-field-group__icon {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
margin-top: 2px; margin-top: 2px;
} }
.aksrt-field-group__title { .jio-field-group__title {
margin: 0; margin: 0;
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
transition: color 0.15s; transition: color 0.15s;
} }
.aksrt-field-group__desc { .jio-field-group__desc {
margin: 4px 0 0; margin: 4px 0 0;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
line-height: 1.5; line-height: 1.5;
} }
.aksrt-field-group__actions { .jio-field-group__actions {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.aksrt-field-group__collapse-btn { .jio-field-group__collapse-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
border-radius: 999px; border-radius: 999px;
padding: 4px 10px; padding: 4px 10px;
font-size: 12px; font-size: 12px;
@@ -153,25 +153,25 @@ function toggleCollapse() {
transition: color 0.15s, border-color 0.15s, background 0.15s; transition: color 0.15s, border-color 0.15s, background 0.15s;
} }
.aksrt-field-group__collapse-btn:hover { .jio-field-group__collapse-btn:hover {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
} }
.aksrt-field-group__body { .jio-field-group__body {
padding: 16px 20px 20px; padding: 16px 20px 20px;
} }
/* Collapse transition */ /* Collapse transition */
.aksrt-collapse-enter-active, .jio-collapse-enter-active,
.aksrt-collapse-leave-active { .jio-collapse-leave-active {
transition: all 0.2s ease; transition: all 0.2s ease;
overflow: hidden; overflow: hidden;
} }
.aksrt-collapse-enter-from, .jio-collapse-enter-from,
.aksrt-collapse-leave-to { .jio-collapse-leave-to {
opacity: 0; opacity: 0;
max-height: 0; max-height: 0;
padding-top: 0; padding-top: 0;
@@ -1,15 +1,15 @@
<template> <template>
<div class="aksrt-form-renderer"> <div class="jio-form-renderer">
<!-- Page header with title and description --> <!-- Page header with title and description -->
<div v-if="title" class="aksrt-form-renderer__header"> <div v-if="title" class="jio-form-renderer__header">
<div class="aksrt-form-renderer__header-left"> <div class="jio-form-renderer__header-left">
<FaIcon v-if="icon" :icon="icon" :size="22" class="aksrt-form-renderer__header-icon" /> <FaIcon v-if="icon" :icon="icon" :size="22" class="jio-form-renderer__header-icon" />
<div> <div>
<h1 class="aksrt-form-renderer__title">{{ title }}</h1> <h1 class="jio-form-renderer__title">{{ title }}</h1>
<p v-if="description" class="aksrt-form-renderer__desc">{{ description }}</p> <p v-if="description" class="jio-form-renderer__desc">{{ description }}</p>
</div> </div>
</div> </div>
<div v-if="showSearch" class="aksrt-form-renderer__search"> <div v-if="showSearch" class="jio-form-renderer__search">
<n-input <n-input
v-model:value="searchQuery" v-model:value="searchQuery"
placeholder="搜索设置项..." placeholder="搜索设置项..."
@@ -24,7 +24,7 @@
</div> </div>
<!-- Loading state --> <!-- Loading state -->
<div v-if="loading" class="aksrt-form-renderer__loading"> <div v-if="loading" class="jio-form-renderer__loading">
<n-spin size="medium" /> <n-spin size="medium" />
<span>加载中...</span> <span>加载中...</span>
</div> </div>
@@ -45,7 +45,7 @@
<!-- Form content --> <!-- Form content -->
<template v-else-if="schema && schema.length"> <template v-else-if="schema && schema.length">
<template v-for="group in filteredSchema" :key="groupKey(group)"> <template v-for="group in filteredSchema" :key="groupKey(group)">
<AksFieldGroup <JioFieldGroup
v-if="isGroupVisible(group)" v-if="isGroupVisible(group)"
:title="group.title" :title="group.title"
:description="group.description" :description="group.description"
@@ -59,7 +59,7 @@
<!-- Tabbed: renders tabs whose sub-fields are flat top-level keys --> <!-- Tabbed: renders tabs whose sub-fields are flat top-level keys -->
<div <div
v-if="field.type === 'tabbed' && (field.tabs || []).length" v-if="field.type === 'tabbed' && (field.tabs || []).length"
class="aksrt-form-renderer__tabbed" class="jio-form-renderer__tabbed"
> >
<n-tabs type="line" animated> <n-tabs type="line" animated>
<n-tab-pane <n-tab-pane
@@ -69,7 +69,7 @@
:tab="tabName(tab)" :tab="tabName(tab)"
> >
<template v-for="sub in (tab.fields || [])" :key="sub.key"> <template v-for="sub in (tab.fields || [])" :key="sub.key">
<AksField <JioField
v-if="isFieldVisible(sub)" v-if="isFieldVisible(sub)"
:schema="sub" :schema="sub"
:model-value="getFieldValue(sub.key)" :model-value="getFieldValue(sub.key)"
@@ -82,7 +82,7 @@
</n-tab-pane> </n-tab-pane>
</n-tabs> </n-tabs>
</div> </div>
<AksSorterField <JioSorterField
v-else-if="field.type === 'custom' && field.renderer === 'sorter'" v-else-if="field.type === 'custom' && field.renderer === 'sorter'"
:model-value="getFieldValue(field.key) || {}" :model-value="getFieldValue(field.key) || {}"
:options="field.options || []" :options="field.options || []"
@@ -93,7 +93,7 @@
:name="`field-${field.key}`" :name="`field-${field.key}`"
v-bind="{ field, value: getFieldValue(field.key), setValue: (value) => setFieldValue(field.key, value), formData }" v-bind="{ field, value: getFieldValue(field.key), setValue: (value) => setFieldValue(field.key, value), formData }"
> >
<AksField <JioField
:schema="field" :schema="field"
:model-value="getFieldValue(field.key)" :model-value="getFieldValue(field.key)"
:form-data="formData" :form-data="formData"
@@ -102,7 +102,7 @@
@action="emit('field-action', $event)" @action="emit('field-action', $event)"
/> />
</slot> </slot>
<AksField <JioField
v-else v-else
:schema="field" :schema="field"
:model-value="getFieldValue(field.key)" :model-value="getFieldValue(field.key)"
@@ -117,24 +117,24 @@
<!-- Custom group content slot --> <!-- Custom group content slot -->
<slot :name="`group-${group.key}`" v-bind="{ group, formData }" /> <slot :name="`group-${group.key}`" v-bind="{ group, formData }" />
</AksFieldGroup> </JioFieldGroup>
</template> </template>
</template> </template>
<!-- Empty state --> <!-- Empty state -->
<div v-else class="aksrt-form-renderer__empty"> <div v-else class="jio-form-renderer__empty">
<FaIcon icon="fa fas fa-cog" :size="32" /> <FaIcon icon="fa fas fa-cog" :size="32" />
<p>暂无配置项</p> <p>暂无配置项</p>
</div> </div>
<!-- Sticky save bar --> <!-- Sticky save bar -->
<AksSaveBar :dirty="dirty" :saving="saving" @save="$emit('save')" @reload="$emit('reload')" /> <JioSaveBar :dirty="dirty" :saving="saving" @save="$emit('save')" @reload="$emit('reload')" />
</div> </div>
</template> </template>
<script setup> <script setup>
/** /**
* AksFormRenderer — the core schema-driven form engine. * JioFormRenderer — the core schema-driven form engine.
* *
* Takes a schema definition (array of field groups) and a reactive form data object, * Takes a schema definition (array of field groups) and a reactive form data object,
* and renders a complete settings page with: * and renders a complete settings page with:
@@ -146,10 +146,10 @@
*/ */
import { ref, computed, useSlots } from 'vue' import { ref, computed, useSlots } from 'vue'
import FaIcon from './FaIcon.vue' import FaIcon from './FaIcon.vue'
import AksSaveBar from './AksSaveBar.vue' import JioSaveBar from './JioSaveBar.vue'
import AksFieldGroup from './AksFieldGroup.vue' import JioFieldGroup from './JioFieldGroup.vue'
import AksField from './AksField.vue' import JioField from './JioField.vue'
import AksSorterField from './AksSorterField.vue' import JioSorterField from './JioSorterField.vue'
const props = defineProps({ const props = defineProps({
/** Page title */ /** Page title */
@@ -308,7 +308,7 @@ const filteredSchema = computed(() => {
</script> </script>
<style scoped> <style scoped>
.aksrt-form-renderer__header { .jio-form-renderer__header {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
justify-content: space-between; justify-content: space-between;
@@ -317,73 +317,73 @@ const filteredSchema = computed(() => {
flex-wrap: wrap; flex-wrap: wrap;
} }
.aksrt-form-renderer__header-left { .jio-form-renderer__header-left {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
gap: 12px; gap: 12px;
} }
.aksrt-form-renderer__header-icon { .jio-form-renderer__header-icon {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
margin-top: 4px; margin-top: 4px;
} }
.aksrt-form-renderer__title { .jio-form-renderer__title {
margin: 0; margin: 0;
font-size: 22px; font-size: 22px;
font-weight: 700; font-weight: 700;
color: var(--aksrt-color-text); color: var(--jio-color-text);
letter-spacing: -0.02em; letter-spacing: -0.02em;
} }
.aksrt-form-renderer__desc { .jio-form-renderer__desc {
margin: 4px 0 0; margin: 4px 0 0;
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
line-height: 1.6; line-height: 1.6;
} }
.aksrt-form-renderer__tabbed { .jio-form-renderer__tabbed {
margin-bottom: 8px; margin-bottom: 8px;
} }
.aksrt-form-renderer__search { .jio-form-renderer__search {
min-width: 200px; min-width: 200px;
max-width: 280px; max-width: 280px;
} }
.aksrt-form-renderer__loading { .jio-form-renderer__loading {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
padding: 60px 0; padding: 60px 0;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 14px; font-size: 14px;
} }
.aksrt-form-renderer__empty { .jio-form-renderer__empty {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
padding: 60px 0; padding: 60px 0;
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
} }
.aksrt-form-renderer__empty p { .jio-form-renderer__empty p {
margin: 0; margin: 0;
font-size: 14px; font-size: 14px;
} }
/* Mobile */ /* Mobile */
@media (max-width: 768px) { @media (max-width: 768px) {
.aksrt-form-renderer__header { .jio-form-renderer__header {
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
} }
.aksrt-form-renderer__search { .jio-form-renderer__search {
max-width: 100%; max-width: 100%;
width: 100%; width: 100%;
} }
@@ -1,23 +1,23 @@
<template> <template>
<div class="aksrt-gallery-field"> <div class="jio-gallery-field">
<div v-if="attachmentIds.length" class="aksrt-gallery-field__grid"> <div v-if="attachmentIds.length" class="jio-gallery-field__grid">
<article <article
v-for="(attachmentId, index) in attachmentIds" v-for="(attachmentId, index) in attachmentIds"
:key="attachmentId" :key="attachmentId"
class="aksrt-gallery-field__item" class="jio-gallery-field__item"
> >
<img <img
v-if="previews[attachmentId]?.url" v-if="previews[attachmentId]?.url"
:src="previews[attachmentId].url" :src="previews[attachmentId].url"
:alt="previews[attachmentId].alt || `附件 ${attachmentId}`" :alt="previews[attachmentId].alt || `附件 ${attachmentId}`"
class="aksrt-gallery-field__image" class="jio-gallery-field__image"
/> />
<div v-else class="aksrt-gallery-field__placeholder"> <div v-else class="jio-gallery-field__placeholder">
<FaIcon icon="fa fas fa-image" :size="22" /> <FaIcon icon="fa fas fa-image" :size="22" />
<span>#{{ attachmentId }}</span> <span>#{{ attachmentId }}</span>
</div> </div>
<div class="aksrt-gallery-field__actions"> <div class="jio-gallery-field__actions">
<n-button <n-button
size="tiny" size="tiny"
quaternary quaternary
@@ -49,12 +49,12 @@
</article> </article>
</div> </div>
<div v-else class="aksrt-gallery-field__empty"> <div v-else class="jio-gallery-field__empty">
<FaIcon icon="fa fas fa-images" :size="28" /> <FaIcon icon="fa fas fa-images" :size="28" />
<span>尚未选择图片</span> <span>尚未选择图片</span>
</div> </div>
<div class="aksrt-gallery-field__buttons"> <div class="jio-gallery-field__buttons">
<n-button type="primary" secondary @click="openMediaLibrary"> <n-button type="primary" secondary @click="openMediaLibrary">
<FaIcon icon="fa fas fa-plus" /> <FaIcon icon="fa fas fa-plus" />
{{ attachmentIds.length ? '编辑图片' : '选择图片' }} {{ attachmentIds.length ? '编辑图片' : '选择图片' }}
@@ -64,7 +64,7 @@
</n-button> </n-button>
</div> </div>
<p v-if="mediaError" class="aksrt-gallery-field__error">{{ mediaError }}</p> <p v-if="mediaError" class="jio-gallery-field__error">{{ mediaError }}</p>
</div> </div>
</template> </template>
@@ -172,25 +172,25 @@ watch(attachmentIds, hydratePreviews, { immediate: true })
</script> </script>
<style scoped> <style scoped>
.aksrt-gallery-field__grid { .jio-gallery-field__grid {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: flex-start; align-items: flex-start;
gap: 8px; gap: 8px;
} }
.aksrt-gallery-field__item { .jio-gallery-field__item {
display: inline-flex; display: inline-flex;
flex-direction: column; flex-direction: column;
max-width: 100%; max-width: 100%;
padding: 4px 4px 0; padding: 4px 4px 0;
overflow: hidden; overflow: hidden;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
.aksrt-gallery-field__image { .jio-gallery-field__image {
display: block; display: block;
width: auto; width: auto;
height: auto; height: auto;
@@ -199,7 +199,7 @@ watch(attachmentIds, hydratePreviews, { immediate: true })
border-radius: 4px; border-radius: 4px;
} }
.aksrt-gallery-field__placeholder { .jio-gallery-field__placeholder {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 90px; width: 90px;
@@ -207,35 +207,35 @@ watch(attachmentIds, hydratePreviews, { immediate: true })
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 4px; gap: 4px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.aksrt-gallery-field__actions { .jio-gallery-field__actions {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 4px; padding: 4px;
border-top: 1px solid var(--aksrt-color-border); border-top: 1px solid var(--jio-color-border);
} }
.aksrt-gallery-field__empty { .jio-gallery-field__empty {
display: flex; display: flex;
min-height: 116px; min-height: 116px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
border: 1px dashed var(--aksrt-color-border-strong); border: 1px dashed var(--jio-color-border-strong);
border-radius: 8px; border-radius: 8px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.aksrt-gallery-field__buttons { .jio-gallery-field__buttons {
display: flex; display: flex;
gap: 8px; gap: 8px;
margin-top: 10px; margin-top: 10px;
} }
.aksrt-gallery-field__error { .jio-gallery-field__error {
margin: 8px 0 0; margin: 8px 0 0;
color: #d03050; color: #d03050;
font-size: 12px; font-size: 12px;
@@ -1,21 +1,21 @@
<template> <template>
<div class="aksrt-image-select" role="radiogroup"> <div class="jio-image-select" role="radiogroup">
<button <button
v-for="opt in options" v-for="opt in options"
:key="opt.value" :key="opt.value"
type="button" type="button"
role="radio" role="radio"
class="aksrt-image-select__item" class="jio-image-select__item"
:class="{ 'is-active': modelValue === opt.value }" :class="{ 'is-active': modelValue === opt.value }"
:aria-checked="modelValue === opt.value" :aria-checked="modelValue === opt.value"
:disabled="disabled" :disabled="disabled"
@click="emit('update:modelValue', opt.value)" @click="emit('update:modelValue', opt.value)"
> >
<img v-if="opt.image" :src="opt.image" :alt="opt.label" class="aksrt-image-select__img" :style="imgStyle(opt)" /> <img v-if="opt.image" :src="opt.image" :alt="opt.label" class="jio-image-select__img" :style="imgStyle(opt)" />
<span v-else class="aksrt-image-select__placeholder" :style="imgStyle(opt)"> <span v-else class="jio-image-select__placeholder" :style="imgStyle(opt)">
<FaIcon :icon="opt.icon || 'fa fas fa-image'" :size="20" /> <FaIcon :icon="opt.icon || 'fa fas fa-image'" :size="20" />
</span> </span>
<span class="aksrt-image-select__label">{{ opt.label }}</span> <span class="jio-image-select__label">{{ opt.label }}</span>
</button> </button>
</div> </div>
</template> </template>
@@ -37,78 +37,78 @@ const emit = defineEmits(['update:modelValue'])
// An option may override the group width via its own `width`. // An option may override the group width via its own `width`.
function imgStyle(opt) { function imgStyle(opt) {
const width = opt && opt.width ? opt.width : props.previewWidth const width = opt && opt.width ? opt.width : props.previewWidth
return { '--aksrt-image-select-max': typeof width === 'number' ? `${width}px` : width } return { '--jio-image-select-max': typeof width === 'number' ? `${width}px` : width }
} }
</script> </script>
<style scoped> <style scoped>
.aksrt-image-select { .jio-image-select {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 12px; gap: 12px;
} }
.aksrt-image-select__item { .jio-image-select__item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
min-width: 80px; min-width: 80px;
padding: 8px; padding: 8px;
border: 2px solid var(--aksrt-color-border); border: 2px solid var(--jio-color-border);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
cursor: pointer; cursor: pointer;
transition: border-color .15s ease, background-color .15s ease; transition: border-color .15s ease, background-color .15s ease;
} }
.aksrt-image-select__item:hover, .jio-image-select__item:hover,
.aksrt-image-select__item:focus-visible { .jio-image-select__item:focus-visible {
outline: none; outline: none;
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
} }
.aksrt-image-select__item.is-active { .jio-image-select__item.is-active {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
} }
.aksrt-image-select__item:disabled { .jio-image-select__item:disabled {
cursor: not-allowed; cursor: not-allowed;
} }
.aksrt-image-select__img { .jio-image-select__img {
display: block; display: block;
/* Preview images are wide layout strips (header 597x57, footer 800x190, slide /* Preview images are wide layout strips (header 597x57, footer 800x190, slide
align 200x101), so let them keep their own aspect ratio inside the card. align 200x101), so let them keep their own aspect ratio inside the card.
A fixed square box with object-fit:cover crops the layout to an A fixed square box with object-fit:cover crops the layout to an
unrecognisable sliver — the width is capped instead and the height follows. */ unrecognisable sliver — the width is capped instead and the height follows. */
width: 100%; width: 100%;
max-width: var(--aksrt-image-select-max, 140px); max-width: var(--jio-image-select-max, 140px);
height: auto; height: auto;
border-radius: 4px; border-radius: 4px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
.aksrt-image-select__placeholder { .jio-image-select__placeholder {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: var(--aksrt-image-select-max, 140px); width: var(--jio-image-select-max, 140px);
height: 60px; height: 60px;
border-radius: 4px; border-radius: 4px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
color: var(--aksrt-color-border-strong); color: var(--jio-color-border-strong);
} }
.aksrt-image-select__label { .jio-image-select__label {
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
font-size: 11px; font-size: 11px;
text-align: center; text-align: center;
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.aksrt-image-select__item { .jio-image-select__item {
transition: none; transition: none;
} }
} }
@@ -1,17 +1,17 @@
<template> <template>
<div class="aksrt-media-field"> <div class="jio-media-field">
<div v-if="modelValue" class="aksrt-media-field__preview"> <div v-if="modelValue" class="jio-media-field__preview">
<img <img
v-if="isImage" v-if="isImage"
:src="modelValue" :src="modelValue"
:alt="placeholder" :alt="placeholder"
class="aksrt-media-field__image" class="jio-media-field__image"
/> />
<div v-else class="aksrt-media-field__file"> <div v-else class="jio-media-field__file">
<FaIcon icon="fa fas fa-file" :size="24" /> <FaIcon icon="fa fas fa-file" :size="24" />
<span class="aksrt-media-field__filename">{{ fileName }}</span> <span class="jio-media-field__filename">{{ fileName }}</span>
</div> </div>
<div class="aksrt-media-field__overlay"> <div class="jio-media-field__overlay">
<n-button size="tiny" secondary circle title="更换" @click="openMediaLibrary"> <n-button size="tiny" secondary circle title="更换" @click="openMediaLibrary">
<FaIcon icon="fa fas fa-exchange-alt" /> <FaIcon icon="fa fas fa-exchange-alt" />
</n-button> </n-button>
@@ -21,7 +21,7 @@
</div> </div>
</div> </div>
<div v-else class="aksrt-media-field__empty" @click="openMediaLibrary"> <div v-else class="jio-media-field__empty" @click="openMediaLibrary">
<FaIcon icon="fa fas fa-cloud-upload-alt" :size="28" /> <FaIcon icon="fa fas fa-cloud-upload-alt" :size="28" />
<span>{{ placeholder }}</span> <span>{{ placeholder }}</span>
</div> </div>
@@ -30,7 +30,7 @@
:value="modelValue" :value="modelValue"
:placeholder="'或直接输入 URL'" :placeholder="'或直接输入 URL'"
size="small" size="small"
class="aksrt-media-field__url" class="jio-media-field__url"
@update:value="emit('update:modelValue', $event)" @update:value="emit('update:modelValue', $event)"
/> />
</div> </div>
@@ -38,7 +38,7 @@
<script setup> <script setup>
/** /**
* AksMediaField — image/file selector with preview. * JioMediaField — image/file selector with preview.
* *
* In the WordPress admin context, this can open the WP Media Library. * In the WordPress admin context, this can open the WP Media Library.
* For now, it supports direct URL input with preview. * For now, it supports direct URL input with preview.
@@ -95,7 +95,7 @@ function clearMedia() {
</script> </script>
<style scoped> <style scoped>
.aksrt-media-field__preview { .jio-media-field__preview {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
max-width: 100%; max-width: 100%;
@@ -104,13 +104,13 @@ function clearMedia() {
padding: 4px; padding: 4px;
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
margin-bottom: 8px; margin-bottom: 8px;
vertical-align: top; vertical-align: top;
} }
.aksrt-media-field__image { .jio-media-field__image {
display: block; display: block;
width: auto; width: auto;
height: auto; height: auto;
@@ -119,21 +119,21 @@ function clearMedia() {
border-radius: 4px; border-radius: 4px;
} }
.aksrt-media-field__file { .jio-media-field__file {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
padding: 16px; padding: 16px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
.aksrt-media-field__filename { .jio-media-field__filename {
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-text-secondary); color: var(--jio-color-text-secondary);
word-break: break-all; word-break: break-all;
} }
.aksrt-media-field__overlay { .jio-media-field__overlay {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
@@ -144,33 +144,33 @@ function clearMedia() {
transition: opacity 0.2s; transition: opacity 0.2s;
} }
.aksrt-media-field__preview:hover .aksrt-media-field__overlay { .jio-media-field__preview:hover .jio-media-field__overlay {
opacity: 1; opacity: 1;
} }
.aksrt-media-field__empty { .jio-media-field__empty {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 8px; gap: 8px;
padding: 32px; padding: 32px;
border: 2px dashed var(--aksrt-color-border-strong); border: 2px dashed var(--jio-color-border-strong);
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
transition: all 0.2s; transition: all 0.2s;
margin-bottom: 8px; margin-bottom: 8px;
} }
.aksrt-media-field__empty:hover { .jio-media-field__empty:hover {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
background: var(--aksrt-color-primary-soft); background: var(--jio-color-primary-soft);
} }
.aksrt-media-field__url { .jio-media-field__url {
margin-top: 4px; margin-top: 4px;
} }
</style> </style>
@@ -1,27 +1,27 @@
<template> <template>
<div class="aksrt-repeater-list"> <div class="jio-repeater-list">
<draggable <draggable
v-if="rows.length" v-if="rows.length"
v-model="rows" v-model="rows"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
:item-key="rowKey" :item-key="rowKey"
:disabled="schema.disabled" :disabled="schema.disabled"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head"> <div class="jio-sortable__head">
<AksSortHandle /> <JioSortHandle />
<span class="aksrt-sortable__icon" :class="preview(element).iconClass"> <span class="jio-sortable__icon" :class="preview(element).iconClass">
<span v-if="preview(element).customIcon" class="aksrt-repeater-list__icon-html" v-html="preview(element).customIcon" /> <span v-if="preview(element).customIcon" class="jio-repeater-list__icon-html" v-html="preview(element).customIcon" />
<i v-else-if="preview(element).icon" :class="preview(element).icon" aria-hidden="true" /> <i v-else-if="preview(element).icon" :class="preview(element).icon" aria-hidden="true" />
<FaIcon v-else icon="fa fas fa-star" :size="16" /> <FaIcon v-else icon="fa fas fa-star" :size="16" />
</span> </span>
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<span class="aksrt-sortable__title">{{ preview(element).title }}</span> <span class="jio-sortable__title">{{ preview(element).title }}</span>
<span class="aksrt-sortable__desc">{{ preview(element).desc }}</span> <span class="jio-sortable__desc">{{ preview(element).desc }}</span>
</div> </div>
<div class="aksrt-sortable__actions"> <div class="jio-sortable__actions">
<n-button size="tiny" quaternary type="primary" :disabled="schema.disabled" @click="openModal(index)"> <n-button size="tiny" quaternary type="primary" :disabled="schema.disabled" @click="openModal(index)">
<template #icon><FaIcon icon="fa fas fa-edit" :size="12" /></template> <template #icon><FaIcon icon="fa fas fa-edit" :size="12" /></template>
编辑 编辑
@@ -35,7 +35,7 @@
</div> </div>
</template> </template>
</draggable> </draggable>
<div v-else class="aksrt-sortable__empty"> <div v-else class="jio-sortable__empty">
<FaIcon icon="fa fas fa-inbox" :size="18" /> <FaIcon icon="fa fas fa-inbox" :size="18" />
<span>{{ schema.emptyText || '暂无数据' }}</span> <span>{{ schema.emptyText || '暂无数据' }}</span>
</div> </div>
@@ -50,11 +50,11 @@
:mask-closable="false" :mask-closable="false"
preset="card" preset="card"
:title="editingIndex >= 0 ? (schema.editText || '编辑项目') : (schema.addText || '添加项目')" :title="editingIndex >= 0 ? (schema.editText || '编辑项目') : (schema.addText || '添加项目')"
class="aksrt-modal-card" class="jio-modal-card"
style="max-width: 640px; width: 92vw;" style="max-width: 640px; width: 92vw;"
> >
<div class="aksrt-repeater-list__modal-fields"> <div class="jio-repeater-list__modal-fields">
<AksField <JioField
v-for="field in draftFields" v-for="field in draftFields"
:key="field.key" :key="field.key"
:schema="field" :schema="field"
@@ -63,7 +63,7 @@
@update:model-value="draft = { ...draft, [field.key]: $event }" @update:model-value="draft = { ...draft, [field.key]: $event }"
/> />
</div> </div>
<div class="aksrt-modal-footer"> <div class="jio-modal-footer">
<n-button @click="closeModal">取消</n-button> <n-button @click="closeModal">取消</n-button>
<n-button type="primary" @click="confirmModal">确定</n-button> <n-button type="primary" @click="confirmModal">确定</n-button>
</div> </div>
@@ -76,8 +76,8 @@
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import FaIcon from './FaIcon.vue' import FaIcon from './FaIcon.vue'
import AksField from './AksField.vue' import JioField from './JioField.vue'
import AksSortHandle from './AksSortHandle.vue' import JioSortHandle from './JioSortHandle.vue'
import { matchDependency } from './field-dependency.js' import { matchDependency } from './field-dependency.js'
import { SORTABLE_LIST_ATTRS } from './sortable-options.js' import { SORTABLE_LIST_ATTRS } from './sortable-options.js'
import { createRepeaterRow, createRepeaterRowId, repeaterRowPreview } from './repeater-rows.js' import { createRepeaterRow, createRepeaterRowId, repeaterRowPreview } from './repeater-rows.js'
@@ -151,13 +151,13 @@ function confirmModal() {
</script> </script>
<style scoped> <style scoped>
.aksrt-repeater-list { .jio-repeater-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
} }
.aksrt-repeater-list__icon-html { .jio-repeater-list__icon-html {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -165,14 +165,14 @@ function confirmModal() {
height: 100%; height: 100%;
} }
.aksrt-repeater-list__icon-html :deep(svg), .jio-repeater-list__icon-html :deep(svg),
.aksrt-repeater-list__icon-html :deep(img) { .jio-repeater-list__icon-html :deep(img) {
width: 20px; width: 20px;
height: 20px; height: 20px;
object-fit: contain; object-fit: contain;
} }
.aksrt-repeater-list__modal-fields { .jio-repeater-list__modal-fields {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
@@ -1,11 +1,11 @@
<template> <template>
<div v-if="dirty" class="aksrt-form-renderer__save-bar"> <div v-if="dirty" class="jio-form-renderer__save-bar">
<div class="aksrt-form-renderer__save-bar__inner"> <div class="jio-form-renderer__save-bar__inner">
<div class="aksrt-form-renderer__save-bar__info"> <div class="jio-form-renderer__save-bar__info">
<FaIcon icon="fa fas fa-exclamation-circle" :size="14" /> <FaIcon icon="fa fas fa-exclamation-circle" :size="14" />
<span>您有未保存的更改</span> <span>您有未保存的更改</span>
</div> </div>
<div class="aksrt-form-renderer__save-bar__actions"> <div class="jio-form-renderer__save-bar__actions">
<n-button size="small" :disabled="saving" @click="emit('reload')">放弃更改</n-button> <n-button size="small" :disabled="saving" @click="emit('reload')">放弃更改</n-button>
<n-button <n-button
size="small" size="small"
@@ -23,8 +23,8 @@
<script setup> <script setup>
/** /**
* AksSaveBar — the admin-wide sticky save bar (shown only when dirty). * JioSaveBar — the admin-wide sticky save bar (shown only when dirty).
* Shared by AksFormRenderer (schema pages) and custom settings pages. * Shared by JioFormRenderer (schema pages) and custom settings pages.
*/ */
import FaIcon from './FaIcon.vue' import FaIcon from './FaIcon.vue'
@@ -37,19 +37,19 @@ const emit = defineEmits(['save', 'reload'])
</script> </script>
<style scoped> <style scoped>
.aksrt-form-renderer__save-bar { .jio-form-renderer__save-bar {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 1000; z-index: 1000;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
border-top: 1px solid var(--aksrt-color-border); border-top: 1px solid var(--jio-color-border);
box-shadow: var(--aksrt-shadow-floating); box-shadow: var(--jio-shadow-floating);
animation: slideUp 0.2s ease; animation: slideUp 0.2s ease;
} }
.aksrt-form-renderer__save-bar__inner { .jio-form-renderer__save-bar__inner {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -59,7 +59,7 @@ const emit = defineEmits(['save', 'reload'])
gap: 16px; gap: 16px;
} }
.aksrt-form-renderer__save-bar__info { .jio-form-renderer__save-bar__info {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -67,7 +67,7 @@ const emit = defineEmits(['save', 'reload'])
font-size: 13px; font-size: 13px;
} }
.aksrt-form-renderer__save-bar__actions { .jio-form-renderer__save-bar__actions {
display: flex; display: flex;
gap: 8px; gap: 8px;
} }
@@ -84,17 +84,17 @@ const emit = defineEmits(['save', 'reload'])
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.aksrt-form-renderer__save-bar__inner { .jio-form-renderer__save-bar__inner {
flex-direction: column; flex-direction: column;
padding: 10px 14px; padding: 10px 14px;
gap: 8px; gap: 8px;
} }
.aksrt-form-renderer__save-bar__actions { .jio-form-renderer__save-bar__actions {
width: 100%; width: 100%;
} }
.aksrt-form-renderer__save-bar__actions .n-button { .jio-form-renderer__save-bar__actions .n-button {
flex: 1; flex: 1;
} }
} }
@@ -1,9 +1,9 @@
<template> <template>
<div v-if="visible" class="aksrt-secret-clear"> <div v-if="visible" class="jio-secret-clear">
<n-button size="small" secondary :type="marked ? 'warning' : 'error'" @click="$emit('toggle')"> <n-button size="small" secondary :type="marked ? 'warning' : 'error'" @click="$emit('toggle')">
{{ marked ? '取消清除' : '清除已配置密钥' }} {{ marked ? '取消清除' : '清除已配置密钥' }}
</n-button> </n-button>
<span v-if="marked" class="aksrt-secret-clear__hint">保存后将删除此密钥</span> <span v-if="marked" class="jio-secret-clear__hint">保存后将删除此密钥</span>
</div> </div>
</template> </template>
@@ -22,15 +22,15 @@ defineEmits(['toggle'])
</script> </script>
<style scoped> <style scoped>
.aksrt-secret-clear { .jio-secret-clear {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.aksrt-secret-clear__hint { .jio-secret-clear__hint {
color: var(--aksrt-color-warning, #d97706); color: var(--jio-color-warning, #d97706);
font-size: 12px; font-size: 12px;
} }
</style> </style>
@@ -4,14 +4,14 @@
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
:item-key="valueKey" :item-key="valueKey"
:disabled="disabled" :disabled="disabled"
class="aksrt-sortable aksrt-sortable--compact aksrt-selected-order" class="jio-sortable jio-sortable--compact jio-selected-order"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head"> <div class="jio-sortable__head">
<AksSortHandle /> <JioSortHandle />
<span class="aksrt-sortable__index">{{ index + 1 }}</span> <span class="jio-sortable__index">{{ index + 1 }}</span>
<span class="aksrt-sortable__title">{{ labelOf(element) }}</span> <span class="jio-sortable__title">{{ labelOf(element) }}</span>
</div> </div>
</div> </div>
</template> </template>
@@ -22,7 +22,7 @@
/** 多选 + sortable 的已选值排序列表(select / async_select 下方)。 */ /** 多选 + sortable 的已选值排序列表(select / async_select 下方)。 */
import { computed } from 'vue' import { computed } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import AksSortHandle from './AksSortHandle.vue' import JioSortHandle from './JioSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from './sortable-options.js' import { SORTABLE_LIST_ATTRS } from './sortable-options.js'
const props = defineProps({ const props = defineProps({
@@ -47,7 +47,7 @@ function labelOf(value) {
</script> </script>
<style scoped> <style scoped>
.aksrt-selected-order { .jio-selected-order {
margin-top: 8px; margin-top: 8px;
} }
</style> </style>
@@ -1,5 +1,5 @@
<template> <template>
<button type="button" class="aksrt-sortable__handle" :title="label" :aria-label="label"> <button type="button" class="jio-sortable__handle" :title="label" :aria-label="label">
<i class="fa fas fa-grip-vertical" aria-hidden="true"></i> <i class="fa fas fa-grip-vertical" aria-hidden="true"></i>
</button> </button>
</template> </template>
@@ -1,12 +1,12 @@
<template> <template>
<div class="aksrt-sorter"> <div class="jio-sorter">
<div <div
v-for="column in COLUMNS" v-for="column in COLUMNS"
:key="column.key" :key="column.key"
class="aksrt-sorter__column" class="jio-sorter__column"
:class="`aksrt-sorter__column--${column.key}`" :class="`jio-sorter__column--${column.key}`"
> >
<div class="aksrt-sorter__title"> <div class="jio-sorter__title">
<span>{{ column.title }}</span> <span>{{ column.title }}</span>
<n-tag size="small" :type="column.tagType" :bordered="false">{{ columns[column.key].length }}</n-tag> <n-tag size="small" :type="column.tagType" :bordered="false">{{ columns[column.key].length }}</n-tag>
</div> </div>
@@ -14,21 +14,21 @@
v-model="columns[column.key]" v-model="columns[column.key]"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="value" item-key="value"
group="aksrt-sorter" group="jio-sorter"
class="aksrt-sortable aksrt-sortable--compact aksrt-sorter__list" class="jio-sortable jio-sortable--compact jio-sorter__list"
@change="commit" @change="commit"
> >
<template #item="{ element }"> <template #item="{ element }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head"> <div class="jio-sortable__head">
<AksSortHandle /> <JioSortHandle />
<i v-if="element.icon" :class="element.icon" class="aksrt-sorter__icon" aria-hidden="true"></i> <i v-if="element.icon" :class="element.icon" class="jio-sorter__icon" aria-hidden="true"></i>
<span class="aksrt-sortable__title">{{ element.label }}</span> <span class="jio-sortable__title">{{ element.label }}</span>
</div> </div>
</div> </div>
</template> </template>
</draggable> </draggable>
<div v-if="columns[column.key].length === 0" class="aksrt-sortable__empty aksrt-sorter__empty"> <div v-if="columns[column.key].length === 0" class="jio-sortable__empty jio-sorter__empty">
{{ column.empty }} {{ column.empty }}
</div> </div>
</div> </div>
@@ -39,7 +39,7 @@
/** 启用 / 未启用两列拖拽排序器;样式见 styles/sortable-list.css。 */ /** 启用 / 未启用两列拖拽排序器;样式见 styles/sortable-list.css。 */
import { reactive, watch } from 'vue' import { reactive, watch } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import AksSortHandle from './AksSortHandle.vue' import JioSortHandle from './JioSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from './sortable-options.js' import { SORTABLE_LIST_ATTRS } from './sortable-options.js'
const COLUMNS = [ const COLUMNS = [
@@ -89,37 +89,37 @@ watch(() => [props.modelValue, props.options], syncColumns, { immediate: true, d
</script> </script>
<style scoped> <style scoped>
.aksrt-sorter { .jio-sorter {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px; gap: 14px;
} }
.aksrt-sorter__column { .jio-sorter__column {
position: relative; position: relative;
min-height: 210px; min-height: 210px;
padding: 12px; padding: 12px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
.aksrt-sorter__title { .jio-sorter__title {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: 10px; margin-bottom: 10px;
color: var(--aksrt-color-text); color: var(--jio-color-text);
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
} }
/* 空列也要留出可放置区域,拖拽目标不能塌成 0 高度。 */ /* 空列也要留出可放置区域,拖拽目标不能塌成 0 高度。 */
.aksrt-sorter__list { .jio-sorter__list {
min-height: 44px; min-height: 44px;
} }
.aksrt-sorter__empty { .jio-sorter__empty {
position: absolute; position: absolute;
right: 12px; right: 12px;
bottom: 12px; bottom: 12px;
@@ -128,15 +128,15 @@ watch(() => [props.modelValue, props.options], syncColumns, { immediate: true, d
pointer-events: none; pointer-events: none;
} }
.aksrt-sorter__icon { .jio-sorter__icon {
flex: 0 0 auto; flex: 0 0 auto;
width: 16px; width: 16px;
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
text-align: center; text-align: center;
} }
@media (max-width: 720px) { @media (max-width: 720px) {
.aksrt-sorter { .jio-sorter {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
@@ -1,15 +1,15 @@
/** /**
* 所有后台 vuedraggable 列表共用的 Sortable 选项(v-bind 到 <draggable>)。 * 所有后台 vuedraggable 列表共用的 Sortable 选项(v-bind 到 <draggable>)。
* 配套样式见 src/styles/sortable-list.css,拖拽手柄统一用 AksSortHandle。 * 配套样式见 src/styles/sortable-list.css,拖拽手柄统一用 JioSortHandle。
*/ */
const prefersReducedMotion = typeof window !== 'undefined' const prefersReducedMotion = typeof window !== 'undefined'
&& typeof window.matchMedia === 'function' && typeof window.matchMedia === 'function'
&& window.matchMedia('(prefers-reduced-motion: reduce)').matches && window.matchMedia('(prefers-reduced-motion: reduce)').matches
export const SORTABLE_LIST_ATTRS = Object.freeze({ export const SORTABLE_LIST_ATTRS = Object.freeze({
handle: '.aksrt-sortable__handle', handle: '.jio-sortable__handle',
ghostClass: 'aksrt-sortable__ghost', ghostClass: 'jio-sortable__ghost',
chosenClass: 'aksrt-sortable__chosen', chosenClass: 'jio-sortable__chosen',
dragClass: 'aksrt-sortable__drag', dragClass: 'jio-sortable__drag',
animation: prefersReducedMotion ? 0 : 180, animation: prefersReducedMotion ? 0 : 180,
}) })
@@ -2,7 +2,7 @@ import { onMounted, ref } from 'vue'
import api from '@/api' import api from '@/api'
/** /**
* AksField 的远程选项加载:async_select / taxonomy_select / user_select / page_select。 * JioField 的远程选项加载:async_select / taxonomy_select / user_select / page_select。
* 仅按 schema.type 在挂载时拉取对应数据源。 * 仅按 schema.type 在挂载时拉取对应数据源。
*/ */
export function useFieldRemoteOptions(props) { export function useFieldRemoteOptions(props) {
@@ -47,7 +47,7 @@ export function useFieldRemoteOptions(props) {
value: t.term_id, value: t.term_id,
})) }))
} catch (e) { } catch (e) {
console.warn('[AksField] taxonomy load failed:', e) console.warn('[JioField] taxonomy load failed:', e)
taxonomyOptions.value = [] taxonomyOptions.value = []
} finally { } finally {
taxonomyLoading.value = false taxonomyLoading.value = false
@@ -64,7 +64,7 @@ export function useFieldRemoteOptions(props) {
value: u.id, value: u.id,
})) }))
} catch (e) { } catch (e) {
console.warn('[AksField] user load failed:', e) console.warn('[JioField] user load failed:', e)
userOptions.value = [] userOptions.value = []
} finally { } finally {
userLoading.value = false userLoading.value = false
@@ -84,7 +84,7 @@ export function useFieldRemoteOptions(props) {
const items = res?.data || res || [] const items = res?.data || res || []
pageOptions.value = Array.isArray(items) ? items : [] pageOptions.value = Array.isArray(items) ? items : []
} catch (e) { } catch (e) {
console.warn('[AksField] page load failed:', e) console.warn('[JioField] page load failed:', e)
pageOptions.value = [] pageOptions.value = []
} finally { } finally {
pageLoading.value = false pageLoading.value = false
+11 -11
View File
@@ -14,35 +14,35 @@ app.use(NaiveUI)
// 全局错误处理 // 全局错误处理
app.config.errorHandler = (err, vm, info) => { app.config.errorHandler = (err, vm, info) => {
console.error('[AKSRT] 全局错误:', err, info) console.error('[Jio] 全局错误:', err, info)
} }
// 兜底:立即显示加载状态(防止白屏) // 兜底:立即显示加载状态(防止白屏)
function showFallback(el) { function showFallback(el) {
el.innerHTML = '<div style="padding:40px;text-align:center;color:#666;font-family:sans-serif;">' el.innerHTML = '<div style="padding:40px;text-align:center;color:#666;font-family:sans-serif;">'
+ '<p style="font-size:18px;margin-bottom:8px;">AKSRT 正在加载...</p>' + '<p style="font-size:18px;margin-bottom:8px;">Jio 正在加载...</p>'
+ '<p style="font-size:13px;color:#999;">如果长时间停留在此页面,请按 F12 查看控制台错误</p>' + '<p style="font-size:13px;color:#999;">如果长时间停留在此页面,请按 F12 查看控制台错误</p>'
+ '</div>' + '</div>'
} }
showFallback(document.getElementById('aksrt-admin-app') || document.body.appendChild( showFallback(document.getElementById('jio-admin-app') || document.body.appendChild(
Object.assign(document.createElement('div'), { id: 'aksrt-admin-app' }) Object.assign(document.createElement('div'), { id: 'jio-admin-app' })
)) ))
/** /**
* 获取或创建一个干净的挂载容器 * 获取或创建一个干净的挂载容器
* 核心问题:WordPress 后台的 jQuery/脚本会在页面加载后持续操作 DOM, * 核心问题:WordPress 后台的 jQuery/脚本会在页面加载后持续操作 DOM,
* 导致 PHP 输出的 <div id="aksrt-admin-app"> 可能被外部修改或其兄弟节点被移除, * 导致 PHP 输出的 <div id="jio-admin-app"> 可能被外部修改或其兄弟节点被移除,
* Vue patch 时遍历到 null 节点 → nextSibling 报错。 * Vue patch 时遍历到 null 节点 → nextSibling 报错。
* *
* 解决方案:在挂载前一刻,动态创建一个全新的容器元素替换旧的, * 解决方案:在挂载前一刻,动态创建一个全新的容器元素替换旧的,
* 确保该节点及其父级在 Vue 接管前不被任何外部脚本污染。 * 确保该节点及其父级在 Vue 接管前不被任何外部脚本污染。
*/ */
function getCleanContainer() { function getCleanContainer() {
const existing = document.getElementById('aksrt-admin-app') const existing = document.getElementById('jio-admin-app')
if (!existing) { if (!existing) {
// 极端情况:PHP 没有输出容器,手动创建 // 极端情况:PHP 没有输出容器,手动创建
const fresh = document.createElement('div') const fresh = document.createElement('div')
fresh.id = 'aksrt-admin-app' fresh.id = 'jio-admin-app'
document.body.appendChild(fresh) document.body.appendChild(fresh)
return fresh return fresh
} }
@@ -53,13 +53,13 @@ function getCleanContainer() {
if (!parent) { if (!parent) {
// 旧容器已脱离文档树,重新创建 // 旧容器已脱离文档树,重新创建
const fresh = document.createElement('div') const fresh = document.createElement('div')
fresh.id = 'aksrt-admin-app' fresh.id = 'jio-admin-app'
document.body.appendChild(fresh) document.body.appendChild(fresh)
return fresh return fresh
} }
const fresh = document.createElement('div') const fresh = document.createElement('div')
fresh.id = 'aksrt-admin-app' fresh.id = 'jio-admin-app'
// 将旧容器的位置信息转移给新容器(保留 fallback 内容) // 将旧容器的位置信息转移给新容器(保留 fallback 内容)
fresh.innerHTML = existing.innerHTML || '' fresh.innerHTML = existing.innerHTML || ''
@@ -91,12 +91,12 @@ router.isReady().then(() => {
styleMountTarget.value = container styleMountTarget.value = container
app.mount(container) app.mount(container)
} catch (err) { } catch (err) {
console.error('[AKSRT] Vue 挂载失败:', err) console.error('[Jio] Vue 挂载失败:', err)
showError(getCleanContainer(), err) showError(getCleanContainer(), err)
} }
}) })
}) })
}) })
}).catch((err) => { }).catch((err) => {
console.error('[AKSRT] Router 初始化失败:', err) console.error('[Jio] Router 初始化失败:', err)
}) })
+22 -22
View File
@@ -1,20 +1,20 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<h2 class="aksrt-page-title">积分配置</h2> <h2 class="jio-page-title">积分配置</h2>
<p class="aksrt-page-desc"> <p class="jio-page-desc">
配置积分规则与发放策略。可自定义货币名称(如”金币”、”魔石”等)。用户余额与手工调整在 WordPress 原生”用户”菜单中管理。 配置积分规则与发放策略。可自定义货币名称(如”金币”、”魔石”等)。用户余额与手工调整在 WordPress 原生”用户”菜单中管理。
</p> </p>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>主开关 + 基础设置</h3></div> <div class="jio-section-header"><h3>主开关 + 基础设置</h3></div>
<n-form :model="cfg" label-placement="left" label-width="200" class="aksrt-form"> <n-form :model="cfg" label-placement="left" label-width="200" class="jio-form">
<n-form-item label="启用积分系统"> <n-form-item label="启用积分系统">
<n-switch v-model:value="cfg.enabled" /> <n-switch v-model:value="cfg.enabled" />
</n-form-item> </n-form-item>
<n-form-item label="自定义货币名称"> <n-form-item label="自定义货币名称">
<n-input v-model:value="cfg.currency_name" placeholder="积分" maxlength="20" /> <n-input v-model:value="cfg.currency_name" placeholder="积分" maxlength="20" />
<template #feedback> <template #feedback>
<span class="aksrt-hint-text">自定义货币显示名称,如"金币"、"魔石"等。留空则使用默认名称"积分"。</span> <span class="jio-hint-text">自定义货币显示名称,如"金币"、"魔石"等。留空则使用默认名称"积分"。</span>
</template> </template>
</n-form-item> </n-form-item>
<n-form-item label="注册赠送积分"> <n-form-item label="注册赠送积分">
@@ -23,9 +23,9 @@
</n-form> </n-form>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>每日签到</h3></div> <div class="jio-section-header"><h3>每日签到</h3></div>
<n-form :model="cfg.daily_signin" label-placement="left" label-width="200" class="aksrt-form"> <n-form :model="cfg.daily_signin" label-placement="left" label-width="200" class="jio-form">
<n-form-item label="启用"> <n-form-item label="启用">
<n-switch v-model:value="cfg.daily_signin.enabled" /> <n-switch v-model:value="cfg.daily_signin.enabled" />
</n-form-item> </n-form-item>
@@ -40,15 +40,15 @@
:autosize="{ minRows: 2 }" :autosize="{ minRows: 2 }"
/> />
<template #feedback> <template #feedback>
<span class="aksrt-hint-text">连续 N 天时额外发放的积分。</span> <span class="jio-hint-text">连续 N 天时额外发放的积分。</span>
</template> </template>
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>评论奖励</h3></div> <div class="jio-section-header"><h3>评论奖励</h3></div>
<n-form :model="cfg.comment_reward" label-placement="left" label-width="200" class="aksrt-form"> <n-form :model="cfg.comment_reward" label-placement="left" label-width="200" class="jio-form">
<n-form-item label="启用"> <n-form-item label="启用">
<n-switch v-model:value="cfg.comment_reward.enabled" /> <n-switch v-model:value="cfg.comment_reward.enabled" />
</n-form-item> </n-form-item>
@@ -67,9 +67,9 @@
</n-form> </n-form>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>Ref 推广奖励</h3></div> <div class="jio-section-header"><h3>Ref 推广奖励</h3></div>
<n-form :model="cfg.referral_reward" label-placement="left" label-width="200" class="aksrt-form"> <n-form :model="cfg.referral_reward" label-placement="left" label-width="200" class="jio-form">
<n-form-item label="启用"> <n-form-item label="启用">
<n-switch v-model:value="cfg.referral_reward.enabled" /> <n-switch v-model:value="cfg.referral_reward.enabled" />
</n-form-item> </n-form-item>
@@ -91,19 +91,19 @@
</n-form> </n-form>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>下载消费(参考)</h3></div> <div class="jio-section-header"><h3>下载消费(参考)</h3></div>
<n-form :model="cfg" label-placement="left" label-width="200" class="aksrt-form"> <n-form :model="cfg" label-placement="left" label-width="200" class="jio-form">
<n-form-item :label="`默认积分价参考(${cfg.currency_name || '积分'})`"> <n-form-item :label="`默认积分价参考(${cfg.currency_name || '积分'})`">
<n-input-number v-model:value="cfg.download_default_cost" :min="0" :max="100000" /> <n-input-number v-model:value="cfg.download_default_cost" :min="0" :max="100000" />
<template #feedback> <template #feedback>
<span class="aksrt-hint-text">实际价格以文章「付费内容设置」的积分价或现金价为准;下载解锁走收银台订单,不按次扣费。</span> <span class="jio-hint-text">实际价格以文章「付费内容设置」的积分价或现金价为准;下载解锁走收银台订单,不按次扣费。</span>
</template> </template>
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-card> </n-card>
<div class="aksrt-form-footer"> <div class="jio-form-footer">
<n-button type="primary" :loading="saving" @click="saveCfg">保存配置</n-button> <n-button type="primary" :loading="saving" @click="saveCfg">保存配置</n-button>
</div> </div>
</div> </div>
+15 -15
View File
@@ -1,6 +1,6 @@
<template> <template>
<div class="aksrt-schema-page"> <div class="jio-schema-page">
<AksFormRenderer <JioFormRenderer
:title="pageMeta.title" :title="pageMeta.title"
:description="pageMeta.description" :description="pageMeta.description"
:icon="pageMeta.icon" :icon="pageMeta.icon"
@@ -24,7 +24,7 @@
v-model:value="captchaProviderTab" v-model:value="captchaProviderTab"
type="segment" type="segment"
animated animated
class="aksrt-tabs aksrt-captcha-provider-tabs" class="jio-tabs jio-captcha-provider-tabs"
> >
<n-tab-pane <n-tab-pane
v-for="provider in captchaProviders" v-for="provider in captchaProviders"
@@ -48,18 +48,18 @@
#field-geoip_block_countries="{ value, setValue }" #field-geoip_block_countries="{ value, setValue }"
> >
<n-dynamic-tags :value="Array.isArray(value) ? value : []" @update:value="setValue" /> <n-dynamic-tags :value="Array.isArray(value) ? value : []" @update:value="setValue" />
<p class="aksrt-schema-page__field-hint">使用 ISO 国家代码,如 CN / US / RU。</p> <p class="jio-schema-page__field-hint">使用 ISO 国家代码,如 CN / US / RU。</p>
</template> </template>
<!-- Slot for custom group content (override per page if needed) --> <!-- Slot for custom group content (override per page if needed) -->
<template v-for="(_, name) in $slots" #[name]="slotData"> <template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData" /> <slot :name="name" v-bind="slotData" />
</template> </template>
</AksFormRenderer> </JioFormRenderer>
<div <div
v-if="isPermissionsLogin && !loading" v-if="isPermissionsLogin && !loading"
class="aksrt-schema-page__tool-actions" class="jio-schema-page__tool-actions"
> >
<n-button <n-button
:disabled="!formData?.enabled || !formData?.active_provider" :disabled="!formData?.enabled || !formData?.active_provider"
@@ -80,7 +80,7 @@
<n-spin /> <n-spin />
<p style="margin-top:10px;color:#999;">加载中...</p> <p style="margin-top:10px;color:#999;">加载中...</p>
</div> </div>
<div v-if="testResult && !testLoading" :style="{color: testResult.success ? 'var(--aksrt-color-primary)' : '#d03050', textAlign:'center', padding:'20px'}"> <div v-if="testResult && !testLoading" :style="{color: testResult.success ? 'var(--jio-color-primary)' : '#d03050', textAlign:'center', padding:'20px'}">
<p style="font-size:16px;margin:0;">{{ testResult.message }}</p> <p style="font-size:16px;margin:0;">{{ testResult.message }}</p>
</div> </div>
<div v-if="!testLoading && !testResult" id="captcha-test-box" style="min-height:150px;"></div> <div v-if="!testLoading && !testResult" id="captcha-test-box" style="min-height:150px;"></div>
@@ -95,7 +95,7 @@
* SchemaPage — generic Schema-driven settings page. * SchemaPage — generic Schema-driven settings page.
* *
* Reads the schema from the Vue-side schema registry, fetches/saves settings * Reads the schema from the Vue-side schema registry, fetches/saves settings
* via the API client, and renders using AksFormRenderer. * via the API client, and renders using JioFormRenderer.
* *
* Usage (in router or parent): * Usage (in router or parent):
* <SchemaPage domain="global" section="logo" /> * <SchemaPage domain="global" section="logo" />
@@ -106,7 +106,7 @@
import { computed, watch, ref, nextTick, onBeforeUnmount } from 'vue' import { computed, watch, ref, nextTick, onBeforeUnmount } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
import AksFormRenderer from '@/components/form/AksFormRenderer.vue' import JioFormRenderer from '@/components/form/JioFormRenderer.vue'
import { useSectionForm } from '@/composables/useSectionForm' import { useSectionForm } from '@/composables/useSectionForm'
import { getSchema, normalizeSchemaDomain } from '@/schema/index.js' import { getSchema, normalizeSchemaDomain } from '@/schema/index.js'
import api from '@/api/index.js' import api from '@/api/index.js'
@@ -221,7 +221,7 @@ const {
const payload = { ...data } const payload = { ...data }
const clearSecrets = [] const clearSecrets = []
Object.keys(payload).forEach((key) => { Object.keys(payload).forEach((key) => {
if (payload[key] === '__AKSRT_CLEAR_SECRET__') { if (payload[key] === '__JIO_CLEAR_SECRET__') {
clearSecrets.push(key) clearSecrets.push(key)
delete payload[key] delete payload[key]
} }
@@ -417,7 +417,7 @@ function loadProviderSDK(provider, cfg) {
sitekey: cfg.site_key, sitekey: cfg.site_key,
theme: cfg.theme || 'auto', theme: cfg.theme || 'auto',
size: cfg.size || 'normal', size: cfg.size || 'normal',
action: 'aksrt-admin-test', action: 'jio-admin-test',
cdata: 'admin-captcha-test', cdata: 'admin-captcha-test',
callback: function(token) { callback: function(token) {
submitCaptchaTest('cloudflare', { cf_turnstile_response: token }) submitCaptchaTest('cloudflare', { cf_turnstile_response: token })
@@ -539,21 +539,21 @@ onBeforeUnmount(() => {
</script> </script>
<style scoped> <style scoped>
.aksrt-schema-page { .jio-schema-page {
max-width: none; max-width: none;
margin: 0; margin: 0;
} }
.aksrt-schema-page__tool-actions { .jio-schema-page__tool-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-top: 16px; margin-top: 16px;
} }
.aksrt-schema-page__field-hint { .jio-schema-page__field-hint {
margin: 8px 0 0; margin: 8px 0 0;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.captcha-test-overlay { .captcha-test-overlay {
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container content-page"> <div class="jio-page-container content-page">
<PageHeader title="右侧悬浮按钮" desc="显示在页面右侧的悬浮按钮,支持排序及添加自定义按钮。" /> <PageHeader title="右侧悬浮按钮" desc="显示在页面右侧的悬浮按钮,支持排序及添加自定义按钮。" />
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
@@ -7,8 +7,8 @@
<b>全局悬浮按钮:</b>显示在页面右侧的悬浮按钮,支持排序及添加自定义按钮 <b>全局悬浮按钮:</b>显示在页面右侧的悬浮按钮,支持排序及添加自定义按钮
</n-alert> </n-alert>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form"> <n-form :model="form" label-placement="left" label-width="160" class="jio-form">
<n-form-item label="按钮样式"> <n-form-item label="按钮样式">
<n-radio-group v-model:value="form.style"> <n-radio-group v-model:value="form.style">
<n-space> <n-space>
@@ -53,7 +53,7 @@
v-model="form.items" v-model="form.items"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="type" item-key="type"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<FloatBtnItemPanel :model-value="element" @update:model-value="updateItem(index, $event)" /> <FloatBtnItemPanel :model-value="element" @update:model-value="updateItem(index, $event)" />
@@ -63,7 +63,7 @@
</n-card> </n-card>
</n-spin> </n-spin>
<AksSaveBar :dirty="dirty" :saving="saving" @save="handleSave" @reload="loadSettings" /> <JioSaveBar :dirty="dirty" :saving="saving" @save="handleSave" @reload="loadSettings" />
</div> </div>
</template> </template>
@@ -73,7 +73,7 @@ import { useMessage } from 'naive-ui'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import api from '@/api' import api from '@/api'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
import AksSaveBar from '@/components/form/AksSaveBar.vue' import JioSaveBar from '@/components/form/JioSaveBar.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js' import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
import FloatBtnItemPanel from '@/components/floating/FloatBtnItemPanel.vue' import FloatBtnItemPanel from '@/components/floating/FloatBtnItemPanel.vue'
import { defaultSettings, normalizeItems } from '@/components/floating/floating-defaults.js' import { defaultSettings, normalizeItems } from '@/components/floating/floating-defaults.js'
@@ -162,13 +162,13 @@ onMounted(loadSettings)
.float-settings__desc { .float-settings__desc {
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
} }
.float-settings__label { .float-settings__label {
margin-left: 12px; margin-left: 12px;
font-size: 13px; font-size: 13px;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
} }
.float-settings__section { .float-settings__section {
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container content-page"> <div class="jio-page-container content-page">
<PageHeader title="底部Tab配置" desc="自定义移动端底部导航栏的按钮,支持排序、图标配置和返回顶部功能。"> <PageHeader title="底部Tab配置" desc="自定义移动端底部导航栏的按钮,支持排序、图标配置和返回顶部功能。">
<template #actions> <template #actions>
<n-button type="primary" :loading="saving" @click="handleSave">保存</n-button> <n-button type="primary" :loading="saving" @click="handleSave">保存</n-button>
@@ -8,24 +8,24 @@
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<!-- 基础设置 --> <!-- 基础设置 -->
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<template #header> <template #header>
<div class="aksrt-card-header-row"> <div class="jio-card-header-row">
<div class="aksrt-card-header-row__left"> <div class="jio-card-header-row__left">
<span class="header-icon"><i class="fa fas fa-cog"></i></span> <span class="header-icon"><i class="fa fas fa-cog"></i></span>
<strong class="aksrt-card-header-row__title">基础设置</strong> <strong class="jio-card-header-row__title">基础设置</strong>
</div> </div>
</div> </div>
</template> </template>
<n-form :model="form" label-placement="left" label-width="140" class="aksrt-form"> <n-form :model="form" label-placement="left" label-width="140" class="jio-form">
<n-form-item label="启用底部Tab"> <n-form-item label="启用底部Tab">
<n-switch v-model:value="form.enabled" /> <n-switch v-model:value="form.enabled" />
<span class="aksrt-hint-text" style="margin-left: 12px;">移动端底部导航栏总开关</span> <span class="jio-hint-text" style="margin-left: 12px;">移动端底部导航栏总开关</span>
</n-form-item> </n-form-item>
<n-form-item label="向下滚动隐藏"> <n-form-item label="向下滚动隐藏">
<n-switch v-model:value="form.scroll_down_hide" /> <n-switch v-model:value="form.scroll_down_hide" />
<span class="aksrt-hint-text" style="margin-left: 12px;">页面向下滚动时隐藏,向上滚动时显示</span> <span class="jio-hint-text" style="margin-left: 12px;">页面向下滚动时隐藏,向上滚动时显示</span>
</n-form-item> </n-form-item>
<n-form-item label="文章页专属Tab"> <n-form-item label="文章页专属Tab">
<n-select <n-select
@@ -36,18 +36,18 @@
]" ]"
style="width: 240px;" style="width: 240px;"
/> />
<span class="aksrt-hint-text" style="margin-left: 12px;">文章详情页底部显示的Tab按钮类型</span> <span class="jio-hint-text" style="margin-left: 12px;">文章详情页底部显示的Tab按钮类型</span>
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-card> </n-card>
<!-- Tab按钮配置 --> <!-- Tab按钮配置 -->
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<template #header> <template #header>
<div class="aksrt-card-header-row"> <div class="jio-card-header-row">
<div class="aksrt-card-header-row__left"> <div class="jio-card-header-row__left">
<span class="header-icon"><i class="fa fas fa-list-ul"></i></span> <span class="header-icon"><i class="fa fas fa-list-ul"></i></span>
<strong class="aksrt-card-header-row__title">Tab按钮配置 ({{ form.items.length }})</strong> <strong class="jio-card-header-row__title">Tab按钮配置 ({{ form.items.length }})</strong>
</div> </div>
<n-button type="primary" size="small" @click="addItem"> <n-button type="primary" size="small" @click="addItem">
<template #icon><i class="fa fas fa-plus"></i></template> <template #icon><i class="fa fas fa-plus"></i></template>
@@ -63,27 +63,27 @@
v-model="form.items" v-model="form.items"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="id" item-key="id"
class="aksrt-sortable" class="jio-sortable"
@end="resetSortOrder" @end="resetSortOrder"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head"> <div class="jio-sortable__head">
<AksSortHandle /> <JioSortHandle />
<span class="aksrt-sortable__icon"> <span class="jio-sortable__icon">
<IconValue v-if="element.icon" :value="element.icon" /> <IconValue v-if="element.icon" :value="element.icon" />
</span> </span>
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<div class="aksrt-sortable__title-row"> <div class="jio-sortable__title-row">
<span class="aksrt-sortable__title">{{ element.text || '按钮' }}</span> <span class="jio-sortable__title">{{ element.text || '按钮' }}</span>
<n-tag size="small" :bordered="false">{{ typeLabelMap[element.type] || element.type }}</n-tag> <n-tag size="small" :bordered="false">{{ typeLabelMap[element.type] || element.type }}</n-tag>
<n-tag v-if="element.badge" size="small" type="error" :bordered="false">徽标 {{ element.badge }}</n-tag> <n-tag v-if="element.badge" size="small" type="error" :bordered="false">徽标 {{ element.badge }}</n-tag>
<n-tag v-if="element.type === 'home' && element.ontop" size="small" type="success" :bordered="false">返回顶部</n-tag> <n-tag v-if="element.type === 'home' && element.ontop" size="small" type="success" :bordered="false">返回顶部</n-tag>
<n-tag size="small" :type="element.enabled ? 'success' : 'default'" :bordered="false">{{ element.enabled ? '启用' : '禁用' }}</n-tag> <n-tag size="small" :type="element.enabled ? 'success' : 'default'" :bordered="false">{{ element.enabled ? '启用' : '禁用' }}</n-tag>
</div> </div>
<div class="aksrt-sortable__desc">{{ getItemSummary(element) }}</div> <div class="jio-sortable__desc">{{ getItemSummary(element) }}</div>
</div> </div>
<div class="aksrt-sortable__actions"> <div class="jio-sortable__actions">
<n-button size="tiny" quaternary type="primary" @click="editItem(index)"> <n-button size="tiny" quaternary type="primary" @click="editItem(index)">
<template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template> <template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template>
编辑 编辑
@@ -100,7 +100,7 @@
<n-empty v-else description="暂无Tab按钮,请点击上方按钮添加" /> <n-empty v-else description="暂无Tab按钮,请点击上方按钮添加" />
</n-card> </n-card>
<div class="aksrt-form-actions"> <div class="jio-form-actions">
<n-button type="primary" :loading="saving" @click="handleSave">保存底部Tab配置</n-button> <n-button type="primary" :loading="saving" @click="handleSave">保存底部Tab配置</n-button>
</div> </div>
</n-spin> </n-spin>
@@ -111,10 +111,10 @@
:mask-closable="false" :mask-closable="false"
preset="card" preset="card"
:title="editingIndex >= 0 ? '编辑Tab按钮' : '添加Tab按钮'" :title="editingIndex >= 0 ? '编辑Tab按钮' : '添加Tab按钮'"
class="aksrt-modal-card" class="jio-modal-card"
style="max-width: 520px;" style="max-width: 520px;"
> >
<n-form :model="editingItem" label-placement="top" class="aksrt-form"> <n-form :model="editingItem" label-placement="top" class="jio-form">
<n-form-item label="按钮类型"> <n-form-item label="按钮类型">
<n-select <n-select
v-model:value="editingItem.type" v-model:value="editingItem.type"
@@ -214,12 +214,12 @@
v-model="editingItem.add_items" v-model="editingItem.add_items"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="id" item-key="id"
class="aksrt-sortable aksrt-sortable--compact" class="jio-sortable jio-sortable--compact"
> >
<template #item="{ element, index: subIndex }"> <template #item="{ element, index: subIndex }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head add-items-editor__row"> <div class="jio-sortable__head add-items-editor__row">
<AksSortHandle /> <JioSortHandle />
<n-input v-model:value="element.label" placeholder="名称,例如:写文章" /> <n-input v-model:value="element.label" placeholder="名称,例如:写文章" />
<FaIconPicker v-model="element.icon" placeholder="选择图标" /> <FaIconPicker v-model="element.icon" placeholder="选择图标" />
<n-input v-model:value="element.url" placeholder="链接,例如:/wp-admin/post-new.php" /> <n-input v-model:value="element.url" placeholder="链接,例如:/wp-admin/post-new.php" />
@@ -236,7 +236,7 @@
<n-form-item v-if="editingItem.type === 'home'" label="返回顶部功能"> <n-form-item v-if="editingItem.type === 'home'" label="返回顶部功能">
<n-switch v-model:value="editingItem.ontop" /> <n-switch v-model:value="editingItem.ontop" />
<span class="aksrt-hint-text" style="margin-left: 12px;">页面滚动后切换为返回顶部按钮</span> <span class="jio-hint-text" style="margin-left: 12px;">页面滚动后切换为返回顶部按钮</span>
</n-form-item> </n-form-item>
<n-form-item label="启用状态"> <n-form-item label="启用状态">
@@ -245,7 +245,7 @@
</n-form> </n-form>
<template #footer> <template #footer>
<div class="aksrt-modal-footer"> <div class="jio-modal-footer">
<n-button @click="showModal = false">取消</n-button> <n-button @click="showModal = false">取消</n-button>
<n-button type="primary" @click="saveItem">保存</n-button> <n-button type="primary" @click="saveItem">保存</n-button>
</div> </div>
@@ -262,7 +262,7 @@ import api from '@/api'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
import FaIconPicker from '@/components/form/FaIconPicker.vue' import FaIconPicker from '@/components/form/FaIconPicker.vue'
import IconValue from '@/components/form/IconValue.vue' import IconValue from '@/components/form/IconValue.vue'
import AksSortHandle from '@/components/form/AksSortHandle.vue' import JioSortHandle from '@/components/form/JioSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js' import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
const message = useMessage() const message = useMessage()
@@ -606,7 +606,7 @@ onMounted(loadSettings)
} }
.icon-preview-row a { .icon-preview-row a {
color: var(--aksrt-color-primary, #18A058); color: var(--jio-color-primary, #18A058);
text-decoration: none; text-decoration: none;
} }
@@ -615,12 +615,12 @@ onMounted(loadSettings)
} }
.muted-text { .muted-text {
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 12px; font-size: 12px;
} }
.section-desc { .section-desc {
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 13px; font-size: 13px;
margin: 0 0 16px; margin: 0 0 16px;
} }
@@ -650,7 +650,7 @@ onMounted(loadSettings)
.add-items-editor__presets-label { .add-items-editor__presets-label {
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
} }
.add-items-editor__row { .add-items-editor__row {
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container content-page"> <div class="jio-page-container content-page">
<PageHeader title="通知管理" desc="管理通知内容开关、user 徽标统计口径和自动清理策略。"> <PageHeader title="通知管理" desc="管理通知内容开关、user 徽标统计口径和自动清理策略。">
<template #actions> <template #actions>
<n-space> <n-space>
@@ -10,7 +10,7 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<n-card title="通知内容开关" class="aksrt-section-card"> <n-card title="通知内容开关" class="jio-section-card">
<n-form :model="settings" label-placement="left" label-width="180"> <n-form :model="settings" label-placement="left" label-width="180">
<n-form-item label="评论回复通知"> <n-form-item label="评论回复通知">
<n-switch v-model:value="settings.enabled_types.comment_reply" /> <n-switch v-model:value="settings.enabled_types.comment_reply" />
@@ -35,21 +35,21 @@
<n-grid :cols="2" :x-gap="16" responsive="screen" item-responsive style="margin-top: 16px;"> <n-grid :cols="2" :x-gap="16" responsive="screen" item-responsive style="margin-top: 16px;">
<n-grid-item span="24 l:10"> <n-grid-item span="24 l:10">
<n-card title="user 徽标规则" class="aksrt-section-card"> <n-card title="user 徽标规则" class="jio-section-card">
<n-form :model="settings" label-placement="left" label-width="180"> <n-form :model="settings" label-placement="left" label-width="180">
<n-form-item label="启用 user 动态徽标"> <n-form-item label="启用 user 动态徽标">
<n-switch v-model:value="settings.user_badge_enabled" /> <n-switch v-model:value="settings.user_badge_enabled" />
</n-form-item> </n-form-item>
<n-form-item label="徽标包含状态提醒"> <n-form-item label="徽标包含状态提醒">
<n-switch v-model:value="settings.badge_include_stateful" /> <n-switch v-model:value="settings.badge_include_stateful" />
<span class="aksrt-hint-text" style="margin-left: 12px;">未读持久化通知之外,叠加邮箱待验证、待审核评论等即时提醒</span> <span class="jio-hint-text" style="margin-left: 12px;">未读持久化通知之外,叠加邮箱待验证、待审核评论等即时提醒</span>
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-card> </n-card>
</n-grid-item> </n-grid-item>
<n-grid-item span="24 l:14"> <n-grid-item span="24 l:14">
<n-card title="通知清理策略" class="aksrt-section-card"> <n-card title="通知清理策略" class="jio-section-card">
<n-form :model="settings" label-placement="left" label-width="180"> <n-form :model="settings" label-placement="left" label-width="180">
<n-form-item label="已读通知保留天数"> <n-form-item label="已读通知保留天数">
<n-input-number v-model:value="settings.read_retention_days" :min="1" :max="365" style="width: 180px;" /> <n-input-number v-model:value="settings.read_retention_days" :min="1" :max="365" style="width: 180px;" />
+42 -42
View File
@@ -1,12 +1,12 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader title="文档中心" desc="主题使用文档、开发指南、迁移说明和更新日志。" /> <PageHeader title="文档中心" desc="主题使用文档、开发指南、迁移说明和更新日志。" />
<!-- Quick Actions --> <!-- Quick Actions -->
<n-card title="常用操作" size="small" class="aksrt-docs__section"> <n-card title="常用操作" size="small" class="jio-docs__section">
<n-grid :cols="2" :x-gap="12" :y-gap="12"> <n-grid :cols="2" :x-gap="12" :y-gap="12">
<n-grid-item> <n-grid-item>
<div class="aksrt-docs__action"> <div class="jio-docs__action">
<FaIcon icon="fa fas fa-paint-brush" :size="16" /> <FaIcon icon="fa fas fa-paint-brush" :size="16" />
<div> <div>
<strong>全局设置</strong> <strong>全局设置</strong>
@@ -16,7 +16,7 @@
</div> </div>
</n-grid-item> </n-grid-item>
<n-grid-item> <n-grid-item>
<div class="aksrt-docs__action"> <div class="jio-docs__action">
<FaIcon icon="fa fas fa-home" :size="16" /> <FaIcon icon="fa fas fa-home" :size="16" />
<div> <div>
<strong>首页配置</strong> <strong>首页配置</strong>
@@ -26,7 +26,7 @@
</div> </div>
</n-grid-item> </n-grid-item>
<n-grid-item> <n-grid-item>
<div class="aksrt-docs__action"> <div class="jio-docs__action">
<FaIcon icon="fa fas fa-users" :size="16" /> <FaIcon icon="fa fas fa-users" :size="16" />
<div> <div>
<strong>用户管理</strong> <strong>用户管理</strong>
@@ -36,7 +36,7 @@
</div> </div>
</n-grid-item> </n-grid-item>
<n-grid-item> <n-grid-item>
<div class="aksrt-docs__action"> <div class="jio-docs__action">
<FaIcon icon="fa fas fa-wrench" :size="16" /> <FaIcon icon="fa fas fa-wrench" :size="16" />
<div> <div>
<strong>工具</strong> <strong>工具</strong>
@@ -49,30 +49,30 @@
</n-card> </n-card>
<!-- Reference Docs --> <!-- Reference Docs -->
<div class="aksrt-docs__grid"> <div class="jio-docs__grid">
<n-card <n-card
v-for="doc in docs" v-for="doc in docs"
:key="doc.key" :key="doc.key"
class="aksrt-docs__card" class="jio-docs__card"
size="small" size="small"
hoverable hoverable
@click="openDoc(doc)" @click="openDoc(doc)"
> >
<div class="aksrt-docs__card-inner"> <div class="jio-docs__card-inner">
<div class="aksrt-docs__card-icon" :style="{ background: doc.color }"> <div class="jio-docs__card-icon" :style="{ background: doc.color }">
<FaIcon :icon="doc.icon" :size="20" color="#fff" /> <FaIcon :icon="doc.icon" :size="20" color="#fff" />
</div> </div>
<div class="aksrt-docs__card-body"> <div class="jio-docs__card-body">
<h4 class="aksrt-docs__card-title">{{ doc.title }}</h4> <h4 class="jio-docs__card-title">{{ doc.title }}</h4>
<p class="aksrt-docs__card-desc">{{ doc.description }}</p> <p class="jio-docs__card-desc">{{ doc.description }}</p>
</div> </div>
<FaIcon icon="fa fas fa-external-link-alt" :size="12" class="aksrt-docs__card-arrow" /> <FaIcon icon="fa fas fa-external-link-alt" :size="12" class="jio-docs__card-arrow" />
</div> </div>
</n-card> </n-card>
</div> </div>
<!-- Version Info --> <!-- Version Info -->
<n-card title="当前版本" size="small" class="aksrt-docs__section"> <n-card title="当前版本" size="small" class="jio-docs__section">
<n-descriptions :column="2" bordered label-placement="left" size="small"> <n-descriptions :column="2" bordered label-placement="left" size="small">
<n-descriptions-item label="主题版本"> <n-descriptions-item label="主题版本">
<n-tag type="success" size="small">{{ themeVersion }}</n-tag> <n-tag type="success" size="small">{{ themeVersion }}</n-tag>
@@ -91,12 +91,12 @@ import PageHeader from '@/components/PageHeader.vue'
import FaIcon from '@/components/form/FaIcon.vue' import FaIcon from '@/components/form/FaIcon.vue'
import api from '@/api/index.js' import api from '@/api/index.js'
const themeVersion = ref(window.aksrtAdminData?.themeVersion || '3.4.0-dev') const themeVersion = ref(window.jioAdminData?.themeVersion || '3.4.0-dev')
const dbSchemaVersion = ref('—') const dbSchemaVersion = ref('—')
const docs = ref([ const docs = ref([
{ key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fa fas fa-sitemap', color: 'var(--aksrt-color-primary)', file: 'admin-ia-map.md' }, { key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fa fas fa-sitemap', color: 'var(--jio-color-primary)', file: 'admin-ia-map.md' },
{ key: 'legacy-gap-matrix', title: '对标差异矩阵', description: 'AKSRT 当前 → 原主题参考 → AKSRT 目标三层对照表。', icon: 'fa fas fa-columns', color: '#722ed1', file: 'legacy-gap-matrix.md' }, { key: 'legacy-gap-matrix', title: '对标差异矩阵', description: 'Jio 当前 → 原主题参考 → Jio 目标三层对照表。', icon: 'fa fas fa-columns', color: '#722ed1', file: 'legacy-gap-matrix.md' },
{ key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fa fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' }, { key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fa fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' },
{ key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fa fas fa-clipboard', color: '#52c41a', file: 'manual-acceptance-baseline.md' }, { key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fa fas fa-clipboard', color: '#52c41a', file: 'manual-acceptance-baseline.md' },
{ key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fa fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' }, { key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fa fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' },
@@ -117,35 +117,35 @@ onMounted(async () => {
function openDoc(doc) { function openDoc(doc) {
// Link to local docs directory (admin can open in new tab) // Link to local docs directory (admin can open in new tab)
const base = window.aksrtAdminData?.siteUrl || window.location.origin const base = window.jioAdminData?.siteUrl || window.location.origin
window.open(`${base}/wp-content/themes/AKSRT-theme/docs/${doc.file}`, '_blank') window.open(`${base}/wp-content/themes/Jio-theme/docs/${doc.file}`, '_blank')
} }
</script> </script>
<style scoped> <style scoped>
.aksrt-docs__grid { .jio-docs__grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 12px; gap: 12px;
margin-bottom: 16px; margin-bottom: 16px;
} }
.aksrt-docs__card { .jio-docs__card {
cursor: pointer; cursor: pointer;
transition: box-shadow 0.2s; transition: box-shadow 0.2s;
} }
.aksrt-docs__card:hover { .jio-docs__card:hover {
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
} }
.aksrt-docs__card-inner { .jio-docs__card-inner {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
} }
.aksrt-docs__card-icon { .jio-docs__card-icon {
flex-shrink: 0; flex-shrink: 0;
width: 40px; width: 40px;
height: 40px; height: 40px;
@@ -155,38 +155,38 @@ function openDoc(doc) {
justify-content: center; justify-content: center;
} }
.aksrt-docs__card-body { .jio-docs__card-body {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
} }
.aksrt-docs__card-title { .jio-docs__card-title {
margin: 0 0 2px; margin: 0 0 2px;
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
} }
.aksrt-docs__card-desc { .jio-docs__card-desc {
margin: 0; margin: 0;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
line-height: 1.5; line-height: 1.5;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.aksrt-docs__card-arrow { .jio-docs__card-arrow {
flex-shrink: 0; flex-shrink: 0;
color: #c0c4cc; color: #c0c4cc;
} }
.aksrt-docs__section { .jio-docs__section {
margin-bottom: 16px; margin-bottom: 16px;
} }
.aksrt-docs__action { .jio-docs__action {
display: flex; display: flex;
gap: 12px; gap: 12px;
align-items: flex-start; align-items: flex-start;
@@ -195,31 +195,31 @@ function openDoc(doc) {
background: #fafafa; background: #fafafa;
} }
.aksrt-docs__action i { .jio-docs__action i {
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
margin-top: 2px; margin-top: 2px;
} }
.aksrt-docs__action strong { .jio-docs__action strong {
display: block; display: block;
font-size: 14px; font-size: 14px;
color: var(--aksrt-color-text); color: var(--jio-color-text);
margin-bottom: 2px; margin-bottom: 2px;
} }
.aksrt-docs__action p { .jio-docs__action p {
margin: 0 0 4px; margin: 0 0 4px;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.aksrt-docs__action a { .jio-docs__action a {
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
text-decoration: none; text-decoration: none;
} }
.aksrt-docs__action a:hover { .jio-docs__action a:hover {
text-decoration: underline; text-decoration: underline;
} }
</style> </style>
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader :title="title" :desc="desc"> <PageHeader :title="title" :desc="desc">
<template #actions> <template #actions>
<n-space v-if="links.length"> <n-space v-if="links.length">
@@ -10,7 +10,7 @@
</template> </template>
</PageHeader> </PageHeader>
<n-card v-if="note" class="aksrt-section-card"> <n-card v-if="note" class="jio-section-card">
<n-alert type="info" :show-icon="false"> <n-alert type="info" :show-icon="false">
{{ note }} {{ note }}
</n-alert> </n-alert>
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="基本权限 / 能力矩阵" title="基本权限 / 能力矩阵"
desc="统一管理用户治理、投稿和评论的角色能力矩阵。" desc="统一管理用户治理、投稿和评论的角色能力矩阵。"
@@ -17,8 +17,8 @@
<n-spin :show="loading" style="width: 100%; min-height: 240px;"> <n-spin :show="loading" style="width: 100%; min-height: 240px;">
<n-card class="aksrt-section-card" v-if="summary.cap_count"> <n-card class="jio-section-card" v-if="summary.cap_count">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>矩阵概览</h3> <h3>矩阵概览</h3>
</div> </div>
<n-space> <n-space>
@@ -28,12 +28,12 @@
</n-space> </n-space>
</n-card> </n-card>
<n-card v-for="group in groups" :key="group.key" class="aksrt-section-card"> <n-card v-for="group in groups" :key="group.key" class="jio-section-card">
<template #header> <template #header>
<div class="aksrt-cap-matrix__header"> <div class="jio-cap-matrix__header">
<div> <div>
<h3 class="aksrt-cap-matrix__title">{{ group.title }}</h3> <h3 class="jio-cap-matrix__title">{{ group.title }}</h3>
<p class="aksrt-cap-matrix__desc">共 {{ group.items.length }} 项能力</p> <p class="jio-cap-matrix__desc">共 {{ group.items.length }} 项能力</p>
</div> </div>
</div> </div>
</template> </template>
@@ -48,7 +48,7 @@
/> />
</n-card> </n-card>
<div class="aksrt-form-actions"> <div class="jio-form-actions">
<n-button type="primary" :loading="saving" @click="handleSave">保存能力矩阵</n-button> <n-button type="primary" :loading="saving" @click="handleSave">保存能力矩阵</n-button>
</div> </div>
</n-spin> </n-spin>
@@ -117,7 +117,7 @@ function buildColumns(group) {
key: 'label', key: 'label',
fixed: 'left', fixed: 'left',
width: 280, width: 280,
render: (row) => h('div', { class: 'aksrt-cap-matrix__cap' }, [ render: (row) => h('div', { class: 'jio-cap-matrix__cap' }, [
h('strong', row.label), h('strong', row.label),
h('code', row.cap_id), h('code', row.cap_id),
]), ]),
@@ -148,7 +148,7 @@ function buildColumns(group) {
function renderCapCell(row, col) { function renderCapCell(row, col) {
const hidden = !(row.visible_columns || []).includes(col) const hidden = !(row.visible_columns || []).includes(col)
if (hidden) { if (hidden) {
return h('span', { class: 'aksrt-cap-matrix__empty' }, '—') return h('span', { class: 'jio-cap-matrix__empty' }, '—')
} }
if (!userCaps[row.cap_id]) { if (!userCaps[row.cap_id]) {
@@ -209,40 +209,40 @@ async function handleSave() {
</script> </script>
<style scoped> <style scoped>
.aksrt-cap-matrix__header { .jio-cap-matrix__header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.aksrt-cap-matrix__title { .jio-cap-matrix__title {
margin: 0; margin: 0;
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
} }
.aksrt-cap-matrix__desc { .jio-cap-matrix__desc {
margin: 4px 0 0; margin: 4px 0 0;
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
.aksrt-cap-matrix__cap { .jio-cap-matrix__cap {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
} }
.aksrt-cap-matrix__cap code { .jio-cap-matrix__cap code {
font-size: 11px; font-size: 11px;
color: #667085; color: #667085;
} }
.aksrt-cap-matrix__empty { .jio-cap-matrix__empty {
color: #c0c4cc; color: #c0c4cc;
} }
.aksrt-form-actions { .jio-form-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
margin-top: 16px; margin-top: 16px;
@@ -21,7 +21,7 @@ const title = computed(() => route.meta?.title || '运营功能已迁移')
const nativeUrl = computed(() => { const nativeUrl = computed(() => {
const path = route.meta?.nativeAdminPath || '' const path = route.meta?.nativeAdminPath || ''
if (!path) return '' if (!path) return ''
const base = (window.aksrtAdminData?.adminUrl || '/wp-admin/').replace(/\/?$/, '/') const base = (window.jioAdminData?.adminUrl || '/wp-admin/').replace(/\/?$/, '/')
return base + path.replace(/^\//, '') return base + path.replace(/^\//, '')
}) })
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="主题授权" title="主题授权"
desc="当前版本按产品决策不实现在线授权/撤销授权,仅保留主题信息与更新能力。" desc="当前版本按产品决策不实现在线授权/撤销授权,仅保留主题信息与更新能力。"
@@ -12,14 +12,14 @@
</template> </template>
</PageHeader> </PageHeader>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<n-alert type="info" title="按设计省略" :show-icon="true"> <n-alert type="info" title="按设计省略" :show-icon="true">
本主题当前不实现 原主题风格的授权码校验、域名绑定、撤销授权、本地免授权等机制。 本主题当前不实现 原主题风格的授权码校验、域名绑定、撤销授权、本地免授权等机制。
`AKSRT_Update_Checker` 仅负责匿名版本检测与更新提示,不与授权系统耦合。 `JIO_Update_Checker` 仅负责匿名版本检测与更新提示,不与授权系统耦合。
</n-alert> </n-alert>
</n-card> </n-card>
<n-card class="aksrt-section-card" title="当前策略" size="small"> <n-card class="jio-section-card" title="当前策略" size="small">
<n-list bordered> <n-list bordered>
<n-list-item>不提供授权码输入框或“立即授权”按钮</n-list-item> <n-list-item>不提供授权码输入框或“立即授权”按钮</n-list-item>
<n-list-item>不提供“已授权 / 未授权 / 本地免授权”三态逻辑</n-list-item> <n-list-item>不提供“已授权 / 未授权 / 本地免授权”三态逻辑</n-list-item>
+27 -27
View File
@@ -1,14 +1,14 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader title="主题信息" desc="主题版本、运行环境、已启用模块和关键系统信息。" /> <PageHeader title="主题信息" desc="主题版本、运行环境、已启用模块和关键系统信息。" />
<div v-if="loading" class="aksrt-theme-info__loading"> <div v-if="loading" class="jio-theme-info__loading">
<n-spin size="medium" /> <n-spin size="medium" />
</div> </div>
<template v-else> <template v-else>
<!-- Version Card --> <!-- Version Card -->
<n-card class="aksrt-theme-info__card" title="版本信息" size="small"> <n-card class="jio-theme-info__card" title="版本信息" size="small">
<n-descriptions :column="2" bordered label-placement="left" size="small"> <n-descriptions :column="2" bordered label-placement="left" size="small">
<n-descriptions-item label="主题版本"> <n-descriptions-item label="主题版本">
<n-tag type="success" size="small">{{ info.themeVersion }}</n-tag> <n-tag type="success" size="small">{{ info.themeVersion }}</n-tag>
@@ -33,7 +33,7 @@
</n-card> </n-card>
<!-- Environment Card --> <!-- Environment Card -->
<n-card class="aksrt-theme-info__card" title="运行环境" size="small"> <n-card class="jio-theme-info__card" title="运行环境" size="small">
<n-descriptions :column="2" bordered label-placement="left" size="small"> <n-descriptions :column="2" bordered label-placement="left" size="small">
<n-descriptions-item label="站点地址"> <n-descriptions-item label="站点地址">
<n-text code>{{ info.siteUrl }}</n-text> <n-text code>{{ info.siteUrl }}</n-text>
@@ -61,14 +61,14 @@
</n-card> </n-card>
<!-- Modules Card --> <!-- Modules Card -->
<n-card class="aksrt-theme-info__card" title="已启用模块" size="small"> <n-card class="jio-theme-info__card" title="已启用模块" size="small">
<div class="aksrt-theme-info__modules"> <div class="jio-theme-info__modules">
<n-tag <n-tag
v-for="mod in info.modules" v-for="mod in info.modules"
:key="mod.key" :key="mod.key"
:type="mod.enabled ? 'success' : 'default'" :type="mod.enabled ? 'success' : 'default'"
size="small" size="small"
class="aksrt-theme-info__module-tag" class="jio-theme-info__module-tag"
> >
<FaIcon :icon="mod.enabled ? 'fa fas fa-check-circle' : 'fa fas fa-circle'" :size="10" /> <FaIcon :icon="mod.enabled ? 'fa fas fa-check-circle' : 'fa fas fa-circle'" :size="10" />
{{ mod.label }} {{ mod.label }}
@@ -80,7 +80,7 @@
</n-card> </n-card>
<!-- Data Tables Card --> <!-- Data Tables Card -->
<n-card class="aksrt-theme-info__card" title="数据表状态" size="small"> <n-card class="jio-theme-info__card" title="数据表状态" size="small">
<n-data-table <n-data-table
:columns="tableColumns" :columns="tableColumns"
:data="info.tables" :data="info.tables"
@@ -91,25 +91,25 @@
</n-card> </n-card>
<!-- Docs Links Card --> <!-- Docs Links Card -->
<n-card class="aksrt-theme-info__card" title="快速入口" size="small"> <n-card class="jio-theme-info__card" title="快速入口" size="small">
<div class="aksrt-theme-info__links"> <div class="jio-theme-info__links">
<router-link to="/docs" class="aksrt-theme-info__link"> <router-link to="/docs" class="jio-theme-info__link">
<FaIcon icon="fa fas fa-book" :size="16" /> <FaIcon icon="fa fas fa-book" :size="16" />
<span>文档中心</span> <span>文档中心</span>
</router-link> </router-link>
<router-link to="/tools/update" class="aksrt-theme-info__link"> <router-link to="/tools/update" class="jio-theme-info__link">
<FaIcon icon="fa fas fa-cloud-download-alt" :size="16" /> <FaIcon icon="fa fas fa-cloud-download-alt" :size="16" />
<span>更新中心</span> <span>更新中心</span>
</router-link> </router-link>
<router-link to="/tools/backup" class="aksrt-theme-info__link"> <router-link to="/tools/backup" class="jio-theme-info__link">
<FaIcon icon="fa fas fa-archive" :size="16" /> <FaIcon icon="fa fas fa-archive" :size="16" />
<span>数据备份</span> <span>数据备份</span>
</router-link> </router-link>
<router-link to="/tools/health" class="aksrt-theme-info__link"> <router-link to="/tools/health" class="jio-theme-info__link">
<FaIcon icon="fa fas fa-heartbeat" :size="16" /> <FaIcon icon="fa fas fa-heartbeat" :size="16" />
<span>健康检查</span> <span>健康检查</span>
</router-link> </router-link>
<router-link to="/tools/import-export" class="aksrt-theme-info__link"> <router-link to="/tools/import-export" class="jio-theme-info__link">
<FaIcon icon="fa fas fa-exchange-alt" :size="16" /> <FaIcon icon="fa fas fa-exchange-alt" :size="16" />
<span>导入导出</span> <span>导入导出</span>
</router-link> </router-link>
@@ -173,13 +173,13 @@ onMounted(async () => {
const data = res?.data || res || {} const data = res?.data || res || {}
info.value = { info.value = {
themeVersion: window.aksrtAdminData?.themeVersion || data.theme_version || '3.4.0-dev', themeVersion: window.jioAdminData?.themeVersion || data.theme_version || '3.4.0-dev',
wpVersion: data.wp_version || '', wpVersion: data.wp_version || '',
phpVersion: data.php_version || '', phpVersion: data.php_version || '',
dbSchemaVersion: data.db_schema_version || '', dbSchemaVersion: data.db_schema_version || '',
emailBackfillDone: !!data.email_backfill_done, emailBackfillDone: !!data.email_backfill_done,
siteUrl: data.site_url || window.aksrtAdminData?.siteUrl || '', siteUrl: data.site_url || window.jioAdminData?.siteUrl || '',
apiUrl: data.api_url || window.aksrtAdminData?.apiUrl || '', apiUrl: data.api_url || window.jioAdminData?.apiUrl || '',
themeDir: data.theme_dir || '', themeDir: data.theme_dir || '',
uploadDir: data.upload_dir || '', uploadDir: data.upload_dir || '',
isMultisite: !!data.is_multisite, isMultisite: !!data.is_multisite,
@@ -191,8 +191,8 @@ onMounted(async () => {
console.error('[ThemeInfo] Failed to load health data:', err) console.error('[ThemeInfo] Failed to load health data:', err)
// Fallback with minimal info // Fallback with minimal info
info.value.themeVersion = '3.4.0-dev' info.value.themeVersion = '3.4.0-dev'
info.value.siteUrl = window.aksrtAdminData?.siteUrl || '' info.value.siteUrl = window.jioAdminData?.siteUrl || ''
info.value.apiUrl = window.aksrtAdminData?.apiUrl || '' info.value.apiUrl = window.jioAdminData?.apiUrl || ''
} finally { } finally {
loading.value = false loading.value = false
} }
@@ -218,35 +218,35 @@ function normalizeTables(raw) {
</script> </script>
<style scoped> <style scoped>
.aksrt-theme-info__loading { .jio-theme-info__loading {
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 60px 0; padding: 60px 0;
} }
.aksrt-theme-info__card { .jio-theme-info__card {
margin-bottom: 16px; margin-bottom: 16px;
} }
.aksrt-theme-info__modules { .jio-theme-info__modules {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.aksrt-theme-info__module-tag { .jio-theme-info__module-tag {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 5px; gap: 5px;
} }
.aksrt-theme-info__links { .jio-theme-info__links {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 12px; gap: 12px;
} }
.aksrt-theme-info__link { .jio-theme-info__link {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
@@ -259,7 +259,7 @@ function normalizeTables(raw) {
transition: background 0.2s; transition: background 0.2s;
} }
.aksrt-theme-info__link:hover { .jio-theme-info__link:hover {
background: #e8eaed; background: #e8eaed;
} }
</style> </style>
+13 -13
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="数据备份" title="数据备份"
desc="管理设置快照、创建手动备份,并执行恢复或删除。" desc="管理设置快照、创建手动备份,并执行恢复或删除。"
@@ -12,8 +12,8 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>备份策略</h3> <h3>备份策略</h3>
</div> </div>
<n-space vertical size="small" style="width: 100%;"> <n-space vertical size="small" style="width: 100%;">
@@ -26,19 +26,19 @@
<n-tag round :type="backups.length ? 'success' : 'default'">现有快照:{{ backups.length }} 份</n-tag> <n-tag round :type="backups.length ? 'success' : 'default'">现有快照:{{ backups.length }} 份</n-tag>
</n-space> </n-space>
<n-space align="center" wrap> <n-space align="center" wrap>
<span class="aksrt-backup__label">自动备份</span> <span class="jio-backup__label">自动备份</span>
<n-switch v-model:value="settings.backup_auto" /> <n-switch v-model:value="settings.backup_auto" />
<span class="aksrt-backup__label">频率</span> <span class="jio-backup__label">频率</span>
<n-select v-model:value="settings.backup_frequency" :options="frequencyOptions" style="width: 140px;" /> <n-select v-model:value="settings.backup_frequency" :options="frequencyOptions" style="width: 140px;" />
<span class="aksrt-backup__label">保留</span> <span class="jio-backup__label">保留</span>
<n-input-number v-model:value="settings.backup_retain" :min="3" :max="20" style="width: 140px;" /> <n-input-number v-model:value="settings.backup_retain" :min="3" :max="20" style="width: 140px;" />
<n-button type="primary" :loading="savingPolicy" @click="handleSavePolicy">保存策略</n-button> <n-button type="primary" :loading="savingPolicy" @click="handleSavePolicy">保存策略</n-button>
</n-space> </n-space>
</n-space> </n-space>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>手动创建快照</h3> <h3>手动创建快照</h3>
</div> </div>
<n-space vertical size="small" style="width: 100%;"> <n-space vertical size="small" style="width: 100%;">
@@ -50,8 +50,8 @@
</n-space> </n-space>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>快照列表</h3> <h3>快照列表</h3>
</div> </div>
<n-empty v-if="!backups.length" description="暂无设置快照" /> <n-empty v-if="!backups.length" description="暂无设置快照" />
@@ -64,7 +64,7 @@
:single-line="false" :single-line="false"
:scroll-x="900" :scroll-x="900"
/> />
<p class="aksrt-backup__hint"> <p class="jio-backup__hint">
恢复非当前网站 / 非当前版本的快照可能导致配置异常,恢复前请确认站点环境一致。 恢复非当前网站 / 非当前版本的快照可能导致配置异常,恢复前请确认站点环境一致。
</p> </p>
</n-card> </n-card>
@@ -264,14 +264,14 @@ async function handleDelete(row) {
</script> </script>
<style scoped> <style scoped>
.aksrt-backup__hint { .jio-backup__hint {
margin: 12px 0 0; margin: 12px 0 0;
color: #667085; color: #667085;
font-size: 12px; font-size: 12px;
line-height: 1.7; line-height: 1.7;
} }
.aksrt-backup__label { .jio-backup__label {
color: #344054; color: #344054;
font-size: 12px; font-size: 12px;
} }
+5 -5
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="健康检查" title="健康检查"
desc="集中查看运行环境、数据库表和系统诊断状态。" desc="集中查看运行环境、数据库表和系统诊断状态。"
@@ -12,9 +12,9 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<div class="aksrt-health-grid"> <div class="jio-health-grid">
<n-card v-for="check in checkItems" :key="check.key" class="aksrt-section-card"> <n-card v-for="check in checkItems" :key="check.key" class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>{{ check.label }}</h3> <h3>{{ check.label }}</h3>
<n-tag round :type="statusToTag(check.status)">{{ check.status }}</n-tag> <n-tag round :type="statusToTag(check.status)">{{ check.status }}</n-tag>
</div> </div>
@@ -76,7 +76,7 @@ onMounted(load)
</script> </script>
<style scoped> <style scoped>
.aksrt-health-grid { .jio-health-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px; gap: 16px;
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="导入导出" title="导入导出"
desc="导出当前设置快照、执行 dry-run 导入校验,并支持按域重置到 schema 默认值。" desc="导出当前设置快照、执行 dry-run 导入校验,并支持按域重置到 schema 默认值。"
@@ -12,8 +12,8 @@
</template> </template>
</PageHeader> </PageHeader>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>导出与导入</h3> <h3>导出与导入</h3>
</div> </div>
<n-space style="margin-bottom: 16px;"> <n-space style="margin-bottom: 16px;">
@@ -27,13 +27,13 @@
:autosize="{ minRows: 12, maxRows: 20 }" :autosize="{ minRows: 12, maxRows: 20 }"
placeholder="导出的 JSON 会出现在这里,也可以直接粘贴导入。" placeholder="导出的 JSON 会出现在这里,也可以直接粘贴导入。"
/> />
<p class="aksrt-tools-hint"> <p class="jio-tools-hint">
正式导入前会自动创建一份“导入前自动快照”,与“数据备份”页的快照体系共用,便于回滚。 正式导入前会自动创建一份“导入前自动快照”,与“数据备份”页的快照体系共用,便于回滚。
</p> </p>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>按域重置</h3> <h3>按域重置</h3>
</div> </div>
<n-space align="center" wrap> <n-space align="center" wrap>
@@ -41,14 +41,14 @@
<n-button :loading="resetting" @click="handleReset">重置所选域</n-button> <n-button :loading="resetting" @click="handleReset">重置所选域</n-button>
<n-button type="error" tertiary :loading="resettingAll" @click="handleResetAll">重置全部</n-button> <n-button type="error" tertiary :loading="resettingAll" @click="handleResetAll">重置全部</n-button>
</n-space> </n-space>
<p class="aksrt-tools-hint">仅支持重置 schema 托管的业务域。健康检查和迁移状态属于运维面板,不参与按域回滚。</p> <p class="jio-tools-hint">仅支持重置 schema 托管的业务域。健康检查和迁移状态属于运维面板,不参与按域回滚。</p>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>最近结果</h3> <h3>最近结果</h3>
</div> </div>
<pre class="aksrt-tools-output">{{ resultText || '尚未执行操作。' }}</pre> <pre class="jio-tools-output">{{ resultText || '尚未执行操作。' }}</pre>
</n-card> </n-card>
</div> </div>
</template> </template>
@@ -169,7 +169,7 @@ async function handleResetAll() {
</script> </script>
<style scoped> <style scoped>
.aksrt-tools-output { .jio-tools-output {
margin: 0; margin: 0;
padding: 14px; padding: 14px;
border-radius: 12px; border-radius: 12px;
@@ -181,7 +181,7 @@ async function handleResetAll() {
word-break: break-word; word-break: break-word;
} }
.aksrt-tools-hint { .jio-tools-hint {
margin: 12px 0 0; margin: 12px 0 0;
color: #667085; color: #667085;
font-size: 12px; font-size: 12px;
+18 -18
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="更新中心" title="更新中心"
desc="查看版本状态、检测更新并浏览更新日志与教程入口。" desc="查看版本状态、检测更新并浏览更新日志与教程入口。"
@@ -13,8 +13,8 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 220px;"> <n-spin :show="loading" style="width: 100%; min-height: 220px;">
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>版本状态</h3> <h3>版本状态</h3>
</div> </div>
<n-space> <n-space>
@@ -26,8 +26,8 @@
</n-space> </n-space>
</n-card> </n-card>
<n-card class="aksrt-section-card" v-if="updateInfo.update_available"> <n-card class="jio-section-card" v-if="updateInfo.update_available">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>可用更新</h3> <h3>可用更新</h3>
</div> </div>
<n-alert type="warning" style="margin-bottom: 12px;"> <n-alert type="warning" style="margin-bottom: 12px;">
@@ -39,18 +39,18 @@
</n-button> </n-button>
<n-button @click="handleDismiss" :loading="dismissing">忽略此版本</n-button> <n-button @click="handleDismiss" :loading="dismissing">忽略此版本</n-button>
</n-space> </n-space>
<div v-if="updateInfo.changelog" class="aksrt-update__changelog"> <div v-if="updateInfo.changelog" class="jio-update__changelog">
<h4>更新日志</h4> <h4>更新日志</h4>
<pre>{{ updateInfo.changelog }}</pre> <pre>{{ updateInfo.changelog }}</pre>
</div> </div>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>常用教程入口</h3> <h3>常用教程入口</h3>
</div> </div>
<div class="aksrt-update__grid"> <div class="jio-update__grid">
<a v-for="item in guides" :key="item.key" class="aksrt-update__guide" :href="item.url" target="_blank" rel="noreferrer"> <a v-for="item in guides" :key="item.key" class="jio-update__guide" :href="item.url" target="_blank" rel="noreferrer">
<strong>{{ item.title }}</strong> <strong>{{ item.title }}</strong>
<span>{{ item.desc }}</span> <span>{{ item.desc }}</span>
</a> </a>
@@ -152,11 +152,11 @@ async function handleDismiss() {
</script> </script>
<style scoped> <style scoped>
.aksrt-update__changelog { .jio-update__changelog {
margin-top: 16px; margin-top: 16px;
} }
.aksrt-update__changelog pre { .jio-update__changelog pre {
margin: 8px 0 0; margin: 8px 0 0;
padding: 12px 14px; padding: 12px 14px;
border-radius: 12px; border-radius: 12px;
@@ -168,30 +168,30 @@ async function handleDismiss() {
word-break: break-word; word-break: break-word;
} }
.aksrt-update__grid { .jio-update__grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 12px; gap: 12px;
} }
.aksrt-update__guide { .jio-update__guide {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
padding: 14px; padding: 14px;
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-radius: 12px; border-radius: 12px;
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
background: #fafafa; background: #fafafa;
} }
.aksrt-update__guide:hover { .jio-update__guide:hover {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
background: #f5faff; background: #f5faff;
} }
.aksrt-update__guide span { .jio-update__guide span {
font-size: 12px; font-size: 12px;
color: #667085; color: #667085;
} }
+12 -12
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader title="用户徽章" desc="配置勋章分类、自动授予条件与前台公开展示。"> <PageHeader title="用户徽章" desc="配置勋章分类、自动授予条件与前台公开展示。">
<template #actions> <template #actions>
<n-space> <n-space>
@@ -10,11 +10,11 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>徽章展示</h3> <h3>徽章展示</h3>
</div> </div>
<n-form :model="form" label-placement="left" label-width="180" class="aksrt-form"> <n-form :model="form" label-placement="left" label-width="180" class="jio-form">
<n-form-item label="启用徽章/勋章系统"> <n-form-item label="启用徽章/勋章系统">
<n-switch v-model:value="form.user_medal_s" /> <n-switch v-model:value="form.user_medal_s" />
</n-form-item> </n-form-item>
@@ -31,8 +31,8 @@
</n-form> </n-form>
</n-card> </n-card>
<n-card v-if="form.user_medal_s" class="aksrt-section-card"> <n-card v-if="form.user_medal_s" class="jio-section-card">
<div class="aksrt-section-header users-badge__header"> <div class="jio-section-header users-badge__header">
<h3>徽章明细</h3> <h3>徽章明细</h3>
<span class="users-badge__stats">{{ form.user_medal_args.length }} 个分类 · {{ itemCount }} 枚徽章</span> <span class="users-badge__stats">{{ form.user_medal_args.length }} 个分类 · {{ itemCount }} 枚徽章</span>
</div> </div>
@@ -40,7 +40,7 @@
拖动手柄调整分类与条目顺序,点击行头展开编辑。获取条件选择「仅手动授予」时不自动发放。 拖动手柄调整分类与条目顺序,点击行头展开编辑。获取条件选择「仅手动授予」时不自动发放。
</p> </p>
<div v-if="!form.user_medal_args.length" class="aksrt-sortable__empty"> <div v-if="!form.user_medal_args.length" class="jio-sortable__empty">
<i class="fa fas fa-trophy" aria-hidden="true" /> <i class="fa fas fa-trophy" aria-hidden="true" />
<span>暂无分类,请添加</span> <span>暂无分类,请添加</span>
</div> </div>
@@ -49,7 +49,7 @@
v-model="form.user_medal_args" v-model="form.user_medal_args"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
:item-key="rowKey" :item-key="rowKey"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<MedalCategoryCard <MedalCategoryCard
@@ -68,7 +68,7 @@
</n-card> </n-card>
</n-spin> </n-spin>
<AksSaveBar :dirty="dirty" :saving="saving" @save="handleSave" @reload="load" /> <JioSaveBar :dirty="dirty" :saving="saving" @save="handleSave" @reload="load" />
</div> </div>
</template> </template>
@@ -79,7 +79,7 @@ import { useMessage } from 'naive-ui'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import api from '@/api' import api from '@/api'
import PageHeader from '@/components/PageHeader.vue' import PageHeader from '@/components/PageHeader.vue'
import AksSaveBar from '@/components/form/AksSaveBar.vue' import JioSaveBar from '@/components/form/JioSaveBar.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js' import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
import { useCollapsibleItems } from '@/components/form/useCollapsibleItems.js' import { useCollapsibleItems } from '@/components/form/useCollapsibleItems.js'
import { defaultMedalArgs } from '@/schema/sections/users/badge.js' import { defaultMedalArgs } from '@/schema/sections/users/badge.js'
@@ -176,13 +176,13 @@ onMounted(load)
} }
.users-badge__stats { .users-badge__stats {
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 12px; font-size: 12px;
} }
.users-badge__hint { .users-badge__hint {
margin: 0 0 12px; margin: 0 0 12px;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 13px; font-size: 13px;
} }
+12 -12
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="用户等级" title="用户等级"
desc="配置等级开关、最高等级、升级经验阈值与经验获取矩阵(对齐 legacy 用户等级 / 经验值)。" desc="配置等级开关、最高等级、升级经验阈值与经验获取矩阵(对齐 legacy 用户等级 / 经验值)。"
@@ -13,8 +13,8 @@
</PageHeader> </PageHeader>
<n-spin :show="loading" style="width: 100%; min-height: 200px;"> <n-spin :show="loading" style="width: 100%; min-height: 200px;">
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>当前摘要</h3></div> <div class="jio-section-header"><h3>当前摘要</h3></div>
<n-space> <n-space>
<n-tag round :type="form.user_level_s ? 'success' : 'default'"> <n-tag round :type="form.user_level_s ? 'success' : 'default'">
等级系统:{{ form.user_level_s ? '已启用' : '已关闭' }} 等级系统:{{ form.user_level_s ? '已启用' : '已关闭' }}
@@ -24,9 +24,9 @@
</n-space> </n-space>
</n-card> </n-card>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"><h3>等级显示</h3></div> <div class="jio-section-header"><h3>等级显示</h3></div>
<n-form :model="form" label-placement="left" label-width="180" class="aksrt-form"> <n-form :model="form" label-placement="left" label-width="180" class="jio-form">
<n-form-item label="启用用户等级"> <n-form-item label="启用用户等级">
<n-switch v-model:value="form.user_level_s" /> <n-switch v-model:value="form.user_level_s" />
</n-form-item> </n-form-item>
@@ -42,17 +42,17 @@
</n-form> </n-form>
</n-card> </n-card>
<n-card v-if="form.user_level_s" class="aksrt-section-card"> <n-card v-if="form.user_level_s" class="jio-section-card">
<div class="aksrt-section-header"><h3>升级所需经验(累计)</h3></div> <div class="jio-section-header"><h3>升级所需经验(累计)</h3></div>
<n-alert type="info" :show-icon="false" style="margin-bottom: 12px;"> <n-alert type="info" :show-icon="false" style="margin-bottom: 12px;">
Lv.1 通常为 0。数值为升到该级所需的累计经验。修改最高等级后会自动补齐/截断行。 Lv.1 通常为 0。数值为升到该级所需的累计经验。修改最高等级后会自动补齐/截断行。
</n-alert> </n-alert>
<n-data-table :columns="levelColumns" :data="levelRows" :bordered="false" size="small" /> <n-data-table :columns="levelColumns" :data="levelRows" :bordered="false" size="small" />
</n-card> </n-card>
<n-card v-if="form.user_level_s" class="aksrt-section-card"> <n-card v-if="form.user_level_s" class="jio-section-card">
<div class="aksrt-section-header"><h3>经验值得分</h3></div> <div class="jio-section-header"><h3>经验值得分</h3></div>
<n-form :model="form" label-placement="left" label-width="180" class="aksrt-form"> <n-form :model="form" label-placement="left" label-width="180" class="jio-form">
<n-form-item label="每日上限"> <n-form-item label="每日上限">
<n-input-number v-model:value="form.user_integral_opt.day_max" :min="0" :max="10000" style="width: 180px;" /> <n-input-number v-model:value="form.user_integral_opt.day_max" :min="0" :max="10000" style="width: 180px;" />
</n-form-item> </n-form-item>
@@ -71,7 +71,7 @@
</div> </div>
</n-card> </n-card>
<div class="aksrt-form-actions"> <div class="jio-form-actions">
<n-button type="primary" :loading="saving" @click="handleSave">保存配置</n-button> <n-button type="primary" :loading="saving" @click="handleSave">保存配置</n-button>
</div> </div>
</n-spin> </n-spin>
+5 -5
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader <PageHeader
title="工单中心" title="工单中心"
desc="工单功能开关、提交公告与提交表单配置,以及部门、状态、预设回复三块字典维护。工单的日常处理在 WordPress 用户菜单的「工单管理」中完成。" desc="工单功能开关、提交公告与提交表单配置,以及部门、状态、预设回复三块字典维护。工单的日常处理在 WordPress 用户菜单的「工单管理」中完成。"
@@ -11,7 +11,7 @@
</template> </template>
</PageHeader> </PageHeader>
<n-tabs v-model:value="activeTab" type="segment" animated class="aksrt-ticket-tabs"> <n-tabs v-model:value="activeTab" type="segment" animated class="jio-ticket-tabs">
<n-tab-pane name="settings" tab="基础配置"> <n-tab-pane name="settings" tab="基础配置">
<SchemaPage domain="users" section="ticket" /> <SchemaPage domain="users" section="ticket" />
</n-tab-pane> </n-tab-pane>
@@ -57,13 +57,13 @@ watch(activeTab, (name) => {
}) })
function openNativeList() { function openNativeList() {
const base = (window.aksrtAdminData?.adminUrl || '/wp-admin/').replace(/\/?$/, '/') const base = (window.jioAdminData?.adminUrl || '/wp-admin/').replace(/\/?$/, '/')
window.location.href = base + 'users.php?page=aksrt_tickets' window.location.href = base + 'users.php?page=jio_tickets'
} }
</script> </script>
<style scoped> <style scoped>
.aksrt-ticket-tabs { .jio-ticket-tabs {
margin-bottom: 4px; margin-bottom: 4px;
} }
</style> </style>
+3 -3
View File
@@ -1,8 +1,8 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader title="身份认证" desc="配置通用认证申请规则;申请审核和用户认证资料管理位于 WordPress 用户菜单。" /> <PageHeader title="身份认证" desc="配置通用认证申请规则;申请审核和用户认证资料管理位于 WordPress 用户菜单。" />
<n-spin :show="loading" style="width: 100%; min-height: 240px"> <n-spin :show="loading" style="width: 100%; min-height: 240px">
<n-card class="aksrt-section-card" title="认证申请设置"> <n-card class="jio-section-card" title="认证申请设置">
<n-form :model="form" label-placement="left" label-width="190"> <n-form :model="form" label-placement="left" label-width="190">
<n-form-item label="启用身份认证"><n-switch v-model:value="form.user_auth_s" /></n-form-item> <n-form-item label="启用身份认证"><n-switch v-model:value="form.user_auth_s" /></n-form-item>
<n-form-item label="允许用户前台申请"><n-switch v-model:value="form.user_auth_apply_s" :disabled="!form.user_auth_s" /></n-form-item> <n-form-item label="允许用户前台申请"><n-switch v-model:value="form.user_auth_apply_s" :disabled="!form.user_auth_s" /></n-form-item>
@@ -18,7 +18,7 @@
</n-form-item> </n-form-item>
</n-form> </n-form>
</n-card> </n-card>
<div class="aksrt-form-actions"> <div class="jio-form-actions">
<n-button :disabled="!dirty || saving" @click="load">放弃更改</n-button> <n-button :disabled="!dirty || saving" @click="load">放弃更改</n-button>
<n-button type="primary" :disabled="!dirty" :loading="saving" @click="save">保存设置</n-button> <n-button type="primary" :disabled="!dirty" :loading="saving" @click="save">保存设置</n-button>
</div> </div>
@@ -1,80 +1,80 @@
<template> <template>
<div class="aksrt-page-container"> <div class="jio-page-container">
<PageHeader title="微信模板消息" desc="配置微信公众号模板消息推送。" /> <PageHeader title="微信模板消息" desc="配置微信公众号模板消息推送。" />
<!-- 状态卡片 --> <!-- 状态卡片 -->
<div class="aksrt-wechat__status"> <div class="jio-wechat__status">
<div class="aksrt-wechat__status-card"> <div class="jio-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.configured ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'"> <div class="jio-wechat__status-icon" :class="status.configured ? 'jio-wechat__status-icon--ok' : 'jio-wechat__status-icon--warn'">
<i :class="status.configured ? 'fa fas fa-check' : 'fa fas fa-exclamation'"></i> <i :class="status.configured ? 'fa fas fa-check' : 'fa fas fa-exclamation'"></i>
</div> </div>
<div class="aksrt-wechat__status-info"> <div class="jio-wechat__status-info">
<div class="aksrt-wechat__status-label">配置状态</div> <div class="jio-wechat__status-label">配置状态</div>
<div class="aksrt-wechat__status-value">{{ status.configured ? '已配置' : '未配置' }}</div> <div class="jio-wechat__status-value">{{ status.configured ? '已配置' : '未配置' }}</div>
</div> </div>
</div> </div>
<div class="aksrt-wechat__status-card"> <div class="jio-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.has_token ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'"> <div class="jio-wechat__status-icon" :class="status.has_token ? 'jio-wechat__status-icon--ok' : 'jio-wechat__status-icon--warn'">
<i :class="status.has_token ? 'fa fas fa-key' : 'fa fas fa-key'"></i> <i :class="status.has_token ? 'fa fas fa-key' : 'fa fas fa-key'"></i>
</div> </div>
<div class="aksrt-wechat__status-info"> <div class="jio-wechat__status-info">
<div class="aksrt-wechat__status-label">Access Token</div> <div class="jio-wechat__status-label">Access Token</div>
<div class="aksrt-wechat__status-value">{{ status.has_token ? '已获取' : '未获取' }}</div> <div class="jio-wechat__status-value">{{ status.has_token ? '已获取' : '未获取' }}</div>
</div> </div>
</div> </div>
<div class="aksrt-wechat__status-card"> <div class="jio-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.has_template ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'"> <div class="jio-wechat__status-icon" :class="status.has_template ? 'jio-wechat__status-icon--ok' : 'jio-wechat__status-icon--warn'">
<i :class="status.has_template ? 'fa fas fa-file-alt' : 'fa fas fa-file-alt'"></i> <i :class="status.has_template ? 'fa fas fa-file-alt' : 'fa fas fa-file-alt'"></i>
</div> </div>
<div class="aksrt-wechat__status-info"> <div class="jio-wechat__status-info">
<div class="aksrt-wechat__status-label">模板 ID</div> <div class="jio-wechat__status-label">模板 ID</div>
<div class="aksrt-wechat__status-value">{{ status.has_template ? '已配置' : '未配置' }}</div> <div class="jio-wechat__status-value">{{ status.has_template ? '已配置' : '未配置' }}</div>
</div> </div>
</div> </div>
<div class="aksrt-wechat__status-card"> <div class="jio-wechat__status-card">
<div class="aksrt-wechat__status-icon aksrt-wechat__status-icon--info"> <div class="jio-wechat__status-icon jio-wechat__status-icon--info">
<i class="fa fas fa-users"></i> <i class="fa fas fa-users"></i>
</div> </div>
<div class="aksrt-wechat__status-info"> <div class="jio-wechat__status-info">
<div class="aksrt-wechat__status-label">绑定用户</div> <div class="jio-wechat__status-label">绑定用户</div>
<div class="aksrt-wechat__status-value">{{ status.bound_users || 0 }} 人</div> <div class="jio-wechat__status-value">{{ status.bound_users || 0 }} 人</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 配置表单 --> <!-- 配置表单 -->
<div class="aksrt-wechat__form-card"> <div class="jio-wechat__form-card">
<h3>基本配置</h3> <h3>基本配置</h3>
<div class="aksrt-form-group"> <div class="jio-form-group">
<label> <label>
<input type="checkbox" v-model="form.enabled"> 启用微信模板消息 <input type="checkbox" v-model="form.enabled"> 启用微信模板消息
</label> </label>
</div> </div>
<div class="aksrt-form-group"> <div class="jio-form-group">
<label>AppID</label> <label>AppID</label>
<input v-model="form.app_id" type="text" class="aksrt-input" placeholder="微信公众号 AppID"> <input v-model="form.app_id" type="text" class="jio-input" placeholder="微信公众号 AppID">
</div> </div>
<div class="aksrt-form-group"> <div class="jio-form-group">
<label>AppSecret</label> <label>AppSecret</label>
<input v-model="form.app_secret" type="password" class="aksrt-input" placeholder="微信公众号 AppSecret"> <input v-model="form.app_secret" type="password" class="jio-input" placeholder="微信公众号 AppSecret">
<p class="aksrt-form-hint">保存后不会回显完整密钥</p> <p class="jio-form-hint">保存后不会回显完整密钥</p>
</div> </div>
<div class="aksrt-form-group"> <div class="jio-form-group">
<label>模板 ID</label> <label>模板 ID</label>
<input v-model="form.template_id" type="text" class="aksrt-input" placeholder="微信模板消息模板 ID"> <input v-model="form.template_id" type="text" class="jio-input" placeholder="微信模板消息模板 ID">
</div> </div>
<div class="aksrt-form-actions"> <div class="jio-form-actions">
<button class="aksrt-button aksrt-button--primary" :disabled="saving" @click="saveSettings"> <button class="jio-button jio-button--primary" :disabled="saving" @click="saveSettings">
{{ saving ? '保存中...' : '保存设置' }} {{ saving ? '保存中...' : '保存设置' }}
</button> </button>
</div> </div>
</div> </div>
<!-- 通知类型 --> <!-- 通知类型 -->
<div class="aksrt-wechat__form-card"> <div class="jio-wechat__form-card">
<h3>支持的通知类型</h3> <h3>支持的通知类型</h3>
<p class="aksrt-form-hint">以下事件类型可触发微信模板消息推送(需用户绑定微信且开启对应订阅):</p> <p class="jio-form-hint">以下事件类型可触发微信模板消息推送(需用户绑定微信且开启对应订阅):</p>
<table class="aksrt-table aksrt-table--sm"> <table class="jio-table jio-table--sm">
<thead> <thead>
<tr> <tr>
<th>事件类型</th> <th>事件类型</th>
@@ -87,7 +87,7 @@
<td><code>{{ evt.key }}</code></td> <td><code>{{ evt.key }}</code></td>
<td>{{ evt.desc }}</td> <td>{{ evt.desc }}</td>
<td> <td>
<span class="aksrt-badge" :class="evt.ready ? 'aksrt-badge--success' : 'aksrt-badge--warning'"> <span class="jio-badge" :class="evt.ready ? 'jio-badge--success' : 'jio-badge--warning'">
{{ evt.ready ? '可用' : '待接入' }} {{ evt.ready ? '可用' : '待接入' }}
</span> </span>
</td> </td>
@@ -192,13 +192,13 @@ export default {
</script> </script>
<style scoped> <style scoped>
.aksrt-wechat__status { .jio-wechat__status {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px; gap: 16px;
margin-bottom: 24px; margin-bottom: 24px;
} }
.aksrt-wechat__status-card { .jio-wechat__status-card {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
@@ -207,7 +207,7 @@ export default {
border-radius: 8px; border-radius: 8px;
border: 1px solid #e8e8e8; border: 1px solid #e8e8e8;
} }
.aksrt-wechat__status-icon { .jio-wechat__status-icon {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 8px; border-radius: 8px;
@@ -216,40 +216,40 @@ export default {
justify-content: center; justify-content: center;
font-size: 16px; font-size: 16px;
} }
.aksrt-wechat__status-icon--ok { .jio-wechat__status-icon--ok {
background: #d4edda; background: #d4edda;
color: #155724; color: #155724;
} }
.aksrt-wechat__status-icon--warn { .jio-wechat__status-icon--warn {
background: #fff3cd; background: #fff3cd;
color: #856404; color: #856404;
} }
.aksrt-wechat__status-icon--info { .jio-wechat__status-icon--info {
background: #d1ecf1; background: #d1ecf1;
color: #0c5460; color: #0c5460;
} }
.aksrt-wechat__status-value { .jio-wechat__status-value {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
} }
.aksrt-wechat__status-label { .jio-wechat__status-label {
font-size: 12px; font-size: 12px;
color: #888; color: #888;
} }
.aksrt-wechat__form-card { .jio-wechat__form-card {
background: #fff; background: #fff;
border: 1px solid #e8e8e8; border: 1px solid #e8e8e8;
border-radius: 8px; border-radius: 8px;
padding: 24px; padding: 24px;
margin-bottom: 16px; margin-bottom: 16px;
} }
.aksrt-wechat__form-card h3 { .jio-wechat__form-card h3 {
margin: 0 0 16px; margin: 0 0 16px;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
} }
.aksrt-form-hint { .jio-form-hint {
font-size: 12px; font-size: 12px;
color: #888; color: #888;
margin-top: 4px; margin-top: 4px;
@@ -1,16 +1,16 @@
<template> <template>
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head" v-bind="headAttrs"> <div class="jio-sortable__head" v-bind="headAttrs">
<AksSortHandle @click.stop /> <JioSortHandle @click.stop />
<span class="aksrt-sortable__index">{{ index + 1 }}</span> <span class="jio-sortable__index">{{ index + 1 }}</span>
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<div class="aksrt-sortable__title-row"> <div class="jio-sortable__title-row">
<span class="aksrt-sortable__title">{{ category.cat_name || '未命名分类' }}</span> <span class="jio-sortable__title">{{ category.cat_name || '未命名分类' }}</span>
<n-tag size="small" :bordered="false">{{ category.items.length }} 枚</n-tag> <n-tag size="small" :bordered="false">{{ category.items.length }} 枚</n-tag>
</div> </div>
<span class="aksrt-sortable__desc">{{ previewNames || '该分类暂无条目' }}</span> <span class="jio-sortable__desc">{{ previewNames || '该分类暂无条目' }}</span>
</div> </div>
<div class="aksrt-sortable__actions"> <div class="jio-sortable__actions">
<n-popconfirm @positive-click="emit('remove')"> <n-popconfirm @positive-click="emit('remove')">
<template #trigger> <template #trigger>
<n-button size="tiny" quaternary type="error" title="删除分类" @click.stop> <n-button size="tiny" quaternary type="error" title="删除分类" @click.stop>
@@ -20,17 +20,17 @@
删除分类「{{ category.cat_name || '未命名分类' }}」及其全部条目? 删除分类「{{ category.cat_name || '未命名分类' }}」及其全部条目?
</n-popconfirm> </n-popconfirm>
</div> </div>
<i class="fa fas aksrt-sortable__toggle" :class="open ? 'fa-chevron-down' : 'fa-chevron-right'" aria-hidden="true" /> <i class="fa fas jio-sortable__toggle" :class="open ? 'fa-chevron-down' : 'fa-chevron-right'" aria-hidden="true" />
</div> </div>
<div v-if="open" class="aksrt-sortable__body"> <div v-if="open" class="jio-sortable__body">
<n-form label-placement="left" label-width="96" class="aksrt-form"> <n-form label-placement="left" label-width="96" class="jio-form">
<n-form-item label="分类名称"> <n-form-item label="分类名称">
<n-input v-model:value="category.cat_name" placeholder="如:成长" style="max-width: 320px;" /> <n-input v-model:value="category.cat_name" placeholder="如:成长" style="max-width: 320px;" />
</n-form-item> </n-form-item>
</n-form> </n-form>
<div v-if="!category.items.length" class="aksrt-sortable__empty"> <div v-if="!category.items.length" class="jio-sortable__empty">
<i class="fa fas fa-medal" aria-hidden="true" /> <i class="fa fas fa-medal" aria-hidden="true" />
<span>该分类暂无条目</span> <span>该分类暂无条目</span>
</div> </div>
@@ -39,7 +39,7 @@
v-model="category.items" v-model="category.items"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
:item-key="rowKey" :item-key="rowKey"
class="aksrt-sortable aksrt-sortable--compact" class="jio-sortable jio-sortable--compact"
> >
<template #item="{ element, index: ii }"> <template #item="{ element, index: ii }">
<MedalItemCard <MedalItemCard
@@ -62,7 +62,7 @@
/** 徽章分类卡片:行头显示条目数与名称预览,展开后编辑分类名并拖拽排序条目。 */ /** 徽章分类卡片:行头显示条目数与名称预览,展开后编辑分类名并拖拽排序条目。 */
import { computed } from 'vue' import { computed } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import AksSortHandle from '@/components/form/AksSortHandle.vue' import JioSortHandle from '@/components/form/JioSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js' import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
import { useCollapsibleItems } from '@/components/form/useCollapsibleItems.js' import { useCollapsibleItems } from '@/components/form/useCollapsibleItems.js'
import { emptyItem, rowKey } from './badge-model.js' import { emptyItem, rowKey } from './badge-model.js'
@@ -15,7 +15,7 @@
<img :src="src" :alt="`预设图标 ${i + 1}`" /> <img :src="src" :alt="`预设图标 ${i + 1}`" />
</button> </button>
</div> </div>
<AksMediaField <JioMediaField
:model-value="modelValue" :model-value="modelValue"
placeholder="或从媒体库选择自定义图标" placeholder="或从媒体库选择自定义图标"
@update:model-value="emit('update:modelValue', $event)" @update:model-value="emit('update:modelValue', $event)"
@@ -25,7 +25,7 @@
<script setup> <script setup>
/** 勋章图标选择:主题预设 SVG 一键选用,或走媒体库 / 直接填 URL。 */ /** 勋章图标选择:主题预设 SVG 一键选用,或走媒体库 / 直接填 URL。 */
import AksMediaField from '@/components/form/AksMediaField.vue' import JioMediaField from '@/components/form/JioMediaField.vue'
import { MEDAL_PRESET_ICONS } from '@/schema/sections/users/badge.js' import { MEDAL_PRESET_ICONS } from '@/schema/sections/users/badge.js'
defineProps({ defineProps({
@@ -55,9 +55,9 @@ const emit = defineEmits(['update:modelValue'])
justify-content: center; justify-content: center;
height: 36px; height: 36px;
padding: 0; padding: 0;
border: 1px solid var(--aksrt-color-border, #E2E8E3); border: 1px solid var(--jio-color-border, #E2E8E3);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-surface, #fff); background: var(--jio-color-surface, #fff);
cursor: pointer; cursor: pointer;
transition: border-color .15s ease, background-color .15s ease; transition: border-color .15s ease, background-color .15s ease;
} }
@@ -70,13 +70,13 @@ const emit = defineEmits(['update:modelValue'])
.medal-icon-picker__preset:hover, .medal-icon-picker__preset:hover,
.medal-icon-picker__preset:focus-visible { .medal-icon-picker__preset:focus-visible {
border-color: var(--aksrt-color-primary, #18A058); border-color: var(--jio-color-primary, #18A058);
outline: none; outline: none;
} }
.medal-icon-picker__preset.is-active { .medal-icon-picker__preset.is-active {
border-color: var(--aksrt-color-primary, #18A058); border-color: var(--jio-color-primary, #18A058);
background: var(--aksrt-color-primary-soft, #EAF7EF); background: var(--jio-color-primary-soft, #EAF7EF);
box-shadow: 0 0 0 1px var(--aksrt-color-primary, #18A058); box-shadow: 0 0 0 1px var(--jio-color-primary, #18A058);
} }
</style> </style>
@@ -1,31 +1,31 @@
<template> <template>
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head" v-bind="headAttrs"> <div class="jio-sortable__head" v-bind="headAttrs">
<AksSortHandle @click.stop /> <JioSortHandle @click.stop />
<span class="aksrt-sortable__icon"> <span class="jio-sortable__icon">
<img v-if="item.icon" :src="item.icon" alt="" /> <img v-if="item.icon" :src="item.icon" alt="" />
<i v-else class="fa fas fa-medal" aria-hidden="true" /> <i v-else class="fa fas fa-medal" aria-hidden="true" />
</span> </span>
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<div class="aksrt-sortable__title-row"> <div class="jio-sortable__title-row">
<span class="aksrt-sortable__title">{{ item.name || '未命名徽章' }}</span> <span class="jio-sortable__title">{{ item.name || '未命名徽章' }}</span>
<n-tag size="small" :bordered="false" :type="item.get_type === 'manually_add' ? 'default' : 'info'"> <n-tag size="small" :bordered="false" :type="item.get_type === 'manually_add' ? 'default' : 'info'">
{{ conditionSummary(item) }} {{ conditionSummary(item) }}
</n-tag> </n-tag>
<n-tag v-if="!item.slug" size="small" type="warning" :bordered="false">缺少 slug</n-tag> <n-tag v-if="!item.slug" size="small" type="warning" :bordered="false">缺少 slug</n-tag>
</div> </div>
<span class="aksrt-sortable__desc">{{ item.slug || '—' }}{{ item.desc ? ` · ${item.desc}` : '' }}</span> <span class="jio-sortable__desc">{{ item.slug || '—' }}{{ item.desc ? ` · ${item.desc}` : '' }}</span>
</div> </div>
<div class="aksrt-sortable__actions"> <div class="jio-sortable__actions">
<n-button size="tiny" quaternary type="error" title="删除条目" @click.stop="emit('remove')"> <n-button size="tiny" quaternary type="error" title="删除条目" @click.stop="emit('remove')">
<i class="fa fas fa-trash-alt" aria-hidden="true" /> <i class="fa fas fa-trash-alt" aria-hidden="true" />
</n-button> </n-button>
</div> </div>
<i class="fa fas aksrt-sortable__toggle" :class="open ? 'fa-chevron-down' : 'fa-chevron-right'" aria-hidden="true" /> <i class="fa fas jio-sortable__toggle" :class="open ? 'fa-chevron-down' : 'fa-chevron-right'" aria-hidden="true" />
</div> </div>
<div v-if="open" class="aksrt-sortable__body"> <div v-if="open" class="jio-sortable__body">
<n-form label-placement="left" label-width="96" class="aksrt-form medal-item-card__form"> <n-form label-placement="left" label-width="96" class="jio-form medal-item-card__form">
<n-grid cols="1 m:2" :x-gap="16" responsive="screen"> <n-grid cols="1 m:2" :x-gap="16" responsive="screen">
<n-form-item-gi label="名称"> <n-form-item-gi label="名称">
<n-input v-model:value="item.name" placeholder="如:签到达人" /> <n-input v-model:value="item.name" placeholder="如:签到达人" />
@@ -59,7 +59,7 @@
<script setup> <script setup>
/** 徽章条目卡片:行头摘要(图标 / 名称 / 条件),展开后编辑字段。条目对象由父级直接持有并原地修改。 */ /** 徽章条目卡片:行头摘要(图标 / 名称 / 条件),展开后编辑字段。条目对象由父级直接持有并原地修改。 */
import AksSortHandle from '@/components/form/AksSortHandle.vue' import JioSortHandle from '@/components/form/JioSortHandle.vue'
import { MEDAL_GET_TYPES } from '@/schema/sections/users/badge.js' import { MEDAL_GET_TYPES } from '@/schema/sections/users/badge.js'
import { conditionSummary } from './badge-model.js' import { conditionSummary } from './badge-model.js'
import MedalIconPicker from './MedalIconPicker.vue' import MedalIconPicker from './MedalIconPicker.vue'
@@ -1,6 +1,6 @@
<template> <template>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>预设回复</h3> <h3>预设回复</h3>
<n-space> <n-space>
<n-button size="small" :disabled="saving || !reorderable" :loading="savingOrder" @click="saveOrder"> <n-button size="small" :disabled="saving || !reorderable" :loading="savingOrder" @click="saveOrder">
@@ -21,17 +21,17 @@
v-model="rows" v-model="rows"
v-bind="SORTABLE_LIST_ATTRS" v-bind="SORTABLE_LIST_ATTRS"
item-key="id" item-key="id"
class="aksrt-sortable" class="jio-sortable"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="aksrt-sortable__item"> <div class="jio-sortable__item">
<div class="aksrt-sortable__head"> <div class="jio-sortable__head">
<AksSortHandle /> <JioSortHandle />
<span class="aksrt-sortable__index">{{ index + 1 }}</span> <span class="jio-sortable__index">{{ index + 1 }}</span>
<div class="aksrt-sortable__main"> <div class="jio-sortable__main">
<span class="aksrt-ticket-prereply__content">{{ element.content }}</span> <span class="jio-ticket-prereply__content">{{ element.content }}</span>
</div> </div>
<div class="aksrt-sortable__actions"> <div class="jio-sortable__actions">
<n-button size="tiny" type="primary" quaternary @click="openEdit(element)">编辑</n-button> <n-button size="tiny" type="primary" quaternary @click="openEdit(element)">编辑</n-button>
<n-button size="tiny" type="error" quaternary @click="handleDelete(element)">删除</n-button> <n-button size="tiny" type="error" quaternary @click="handleDelete(element)">删除</n-button>
</div> </div>
@@ -74,7 +74,7 @@ import { computed, onMounted, ref } from 'vue'
import { NButton, NSpace, useDialog, useMessage } from 'naive-ui' import { NButton, NSpace, useDialog, useMessage } from 'naive-ui'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import api from '@/api' import api from '@/api'
import AksSortHandle from '@/components/form/AksSortHandle.vue' import JioSortHandle from '@/components/form/JioSortHandle.vue'
import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js' import { SORTABLE_LIST_ATTRS } from '@/components/form/sortable-options.js'
const message = useMessage() const message = useMessage()
@@ -193,8 +193,8 @@ defineExpose({ reload: load })
</script> </script>
<style scoped> <style scoped>
.aksrt-ticket-prereply__content { .jio-ticket-prereply__content {
color: var(--aksrt-color-text, #1F2923); color: var(--jio-color-text, #1F2923);
font-size: 13px; font-size: 13px;
line-height: 1.6; line-height: 1.6;
white-space: pre-wrap; white-space: pre-wrap;
@@ -1,6 +1,6 @@
<template> <template>
<n-card class="aksrt-section-card aksrt-ticket-status-panel"> <n-card class="jio-section-card jio-ticket-status-panel">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>工单状态</h3> <h3>工单状态</h3>
<n-button size="small" type="primary" :disabled="saving" @click="openCreate">新增状态</n-button> <n-button size="small" type="primary" :disabled="saving" @click="openCreate">新增状态</n-button>
</div> </div>
@@ -24,13 +24,13 @@
v-model:show="visible" v-model:show="visible"
:title="editing ? '编辑状态' : '新增状态'" :title="editing ? '编辑状态' : '新增状态'"
preset="card" preset="card"
class="aksrt-status-modal" class="jio-status-modal"
style="width: 460px; max-width: 92vw;" style="width: 460px; max-width: 92vw;"
:mask-closable="false" :mask-closable="false"
> >
<div class="aksrt-status-preview" aria-live="polite"> <div class="jio-status-preview" aria-live="polite">
<span class="aksrt-status-preview__label">预览</span> <span class="jio-status-preview__label">预览</span>
<span class="aksrt-ticket-badge" :style="{ '--aksrt-ticket-color': previewColor }"> <span class="jio-ticket-badge" :style="{ '--jio-ticket-color': previewColor }">
{{ form.name.trim() || '状态名称' }} {{ form.name.trim() || '状态名称' }}
</span> </span>
</div> </div>
@@ -40,30 +40,30 @@
<n-input v-model:value="form.name" placeholder="如:处理中" maxlength="60" show-count /> <n-input v-model:value="form.name" placeholder="如:处理中" maxlength="60" show-count />
</n-form-item> </n-form-item>
<n-form-item label="标识" path="status_key"> <n-form-item label="标识" path="status_key">
<div class="aksrt-status-key"> <div class="jio-status-key">
<n-input <n-input
v-model:value="form.status_key" v-model:value="form.status_key"
class="aksrt-status-key__input" class="jio-status-key__input"
:placeholder="editing ? '' : '留空则按名称自动生成'" :placeholder="editing ? '' : '留空则按名称自动生成'"
maxlength="24" maxlength="24"
show-count show-count
:input-props="{ autocomplete: 'off', spellcheck: false }" :input-props="{ autocomplete: 'off', spellcheck: false }"
@blur="form.status_key = normalizeKey(form.status_key)" @blur="form.status_key = normalizeKey(form.status_key)"
/> />
<span class="aksrt-ticket-status__hint"> <span class="jio-ticket-status__hint">
小写字母开头,仅含小写字母、数字与下划线(2–24 位)。修改后,使用该状态的工单会同步改为新标识。 小写字母开头,仅含小写字母、数字与下划线(2–24 位)。修改后,使用该状态的工单会同步改为新标识。
</span> </span>
</div> </div>
</n-form-item> </n-form-item>
<n-form-item label="状态颜色" path="color"> <n-form-item label="状态颜色" path="color">
<div class="aksrt-status-color"> <div class="jio-status-color">
<div class="aksrt-status-color__swatches" role="radiogroup" aria-label="状态颜色"> <div class="jio-status-color__swatches" role="radiogroup" aria-label="状态颜色">
<button <button
v-for="swatch in SWATCHES" v-for="swatch in SWATCHES"
:key="swatch" :key="swatch"
type="button" type="button"
role="radio" role="radio"
class="aksrt-status-color__swatch" class="jio-status-color__swatch"
:class="{ 'is-active': currentHex === swatch }" :class="{ 'is-active': currentHex === swatch }"
:style="{ '--swatch': swatch }" :style="{ '--swatch': swatch }"
:aria-checked="currentHex === swatch" :aria-checked="currentHex === swatch"
@@ -72,7 +72,7 @@
@click="form.color = swatch" @click="form.color = swatch"
/> />
<!-- 自定义色:未选中时显示色环,选中后显示当前色并带选中环。 --> <!-- 自定义色:未选中时显示色环,选中后显示当前色并带选中环。 -->
<AksColorPicker <JioColorPicker
:model-value="previewColor" :model-value="previewColor"
@update:model-value="setColor" @update:model-value="setColor"
> >
@@ -81,7 +81,7 @@
:ref="setTriggerRef" :ref="setTriggerRef"
type="button" type="button"
role="radio" role="radio"
class="aksrt-status-color__swatch aksrt-status-color__swatch--custom" class="jio-status-color__swatch jio-status-color__swatch--custom"
:class="{ 'is-active': isCustomColor }" :class="{ 'is-active': isCustomColor }"
:style="{ '--swatch': previewColor }" :style="{ '--swatch': previewColor }"
:aria-checked="isCustomColor" :aria-checked="isCustomColor"
@@ -90,25 +90,25 @@
@click="onClick" @click="onClick"
/> />
</template> </template>
</AksColorPicker> </JioColorPicker>
</div> </div>
<n-input <n-input
v-model:value="form.color" v-model:value="form.color"
class="aksrt-status-color__hex" class="jio-status-color__hex"
maxlength="7" maxlength="7"
placeholder="#6b7280" placeholder="#6b7280"
@blur="form.color = toHex(form.color) || form.color.trim()" @blur="form.color = toHex(form.color) || form.color.trim()"
> >
<template #prefix> <template #prefix>
<i class="aksrt-status-color__chip" :style="{ background: previewColor }" /> <i class="jio-status-color__chip" :style="{ background: previewColor }" />
</template> </template>
</n-input> </n-input>
</div> </div>
</n-form-item> </n-form-item>
<n-form-item label="完结状态" path="is_closed" :show-feedback="false"> <n-form-item label="完结状态" path="is_closed" :show-feedback="false">
<div class="aksrt-status-closed"> <div class="jio-status-closed">
<n-switch v-model:value="form.is_closed" /> <n-switch v-model:value="form.is_closed" />
<span class="aksrt-ticket-status__hint">开启后该状态视为终态,工单不可再流转</span> <span class="jio-ticket-status__hint">开启后该状态视为终态,工单不可再流转</span>
</div> </div>
</n-form-item> </n-form-item>
</n-form> </n-form>
@@ -126,7 +126,7 @@
import { computed, h, onMounted, ref } from 'vue' import { computed, h, onMounted, ref } from 'vue'
import { NButton, NSpace, useDialog, useMessage } from 'naive-ui' import { NButton, NSpace, useDialog, useMessage } from 'naive-ui'
import api from '@/api' import api from '@/api'
import AksColorPicker from '@/components/form/AksColorPicker.vue' import JioColorPicker from '@/components/form/JioColorPicker.vue'
import { toHex } from '@/utils/color.js' import { toHex } from '@/utils/color.js'
const message = useMessage() const message = useMessage()
@@ -194,7 +194,7 @@ const currentHex = computed(() => toHex(form.value.color))
const previewColor = computed(() => currentHex.value || DEFAULT_COLOR) const previewColor = computed(() => currentHex.value || DEFAULT_COLOR)
const isCustomColor = computed(() => currentHex.value !== '' && !SWATCHES.includes(currentHex.value)) const isCustomColor = computed(() => currentHex.value !== '' && !SWATCHES.includes(currentHex.value))
/** AksColorPicker 已归一化为 hex;清空(空串)时保留当前色。 */ /** JioColorPicker 已归一化为 hex;清空(空串)时保留当前色。 */
function setColor(value) { function setColor(value) {
const hex = toHex(value) const hex = toHex(value)
if (hex) form.value.color = hex if (hex) form.value.color = hex
@@ -208,15 +208,15 @@ const columns = computed(() => [
minWidth: 160, minWidth: 160,
// 注意:原生元素用 h('span', ...) 时,文本必须作为 children 直接传入; // 注意:原生元素用 h('span', ...) 时,文本必须作为 children 直接传入;
// 写成 () => row.name 的插槽函数对原生元素不生效,单元格会是空的。 // 写成 () => row.name 的插槽函数对原生元素不生效,单元格会是空的。
render: (row) => h('span', { class: 'aksrt-ticket-badge', style: { '--aksrt-ticket-color': row.color } }, row.name), render: (row) => h('span', { class: 'jio-ticket-badge', style: { '--jio-ticket-color': row.color } }, row.name),
}, },
{ {
title: '颜色', title: '颜色',
key: 'color', key: 'color',
width: 140, width: 140,
render: (row) => h('span', { class: 'aksrt-ticket-color-cell' }, [ render: (row) => h('span', { class: 'jio-ticket-color-cell' }, [
h('i', { class: 'aksrt-ticket-color-dot', style: { background: row.color } }), h('i', { class: 'jio-ticket-color-dot', style: { background: row.color } }),
h('span', { class: 'aksrt-ticket-color-value' }, row.color), h('span', { class: 'jio-ticket-color-value' }, row.color),
]), ]),
}, },
{ {
@@ -235,7 +235,7 @@ const columns = computed(() => [
title: '标识', title: '标识',
key: 'status_key', key: 'status_key',
minWidth: 140, minWidth: 140,
render: (row) => h('span', { class: 'aksrt-ticket-key' }, row.status_key), render: (row) => h('span', { class: 'jio-ticket-key' }, row.status_key),
}, },
{ {
title: '操作', title: '操作',
@@ -348,13 +348,13 @@ defineExpose({ reload: load })
(此前色块 <i> 因此没有尺寸,颜色列只剩色值文本。) (此前色块 <i> 因此没有尺寸,颜色列只剩色值文本。)
--> -->
<style> <style>
.aksrt-ticket-status-panel .aksrt-ticket-color-cell { .jio-ticket-status-panel .jio-ticket-color-cell {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.aksrt-ticket-status-panel .aksrt-ticket-color-dot { .jio-ticket-status-panel .jio-ticket-color-dot {
display: inline-block; display: inline-block;
width: 16px; width: 16px;
height: 16px; height: 16px;
@@ -363,21 +363,21 @@ defineExpose({ reload: load })
flex: 0 0 auto; flex: 0 0 auto;
} }
.aksrt-ticket-status-panel .aksrt-ticket-color-value, .jio-ticket-status-panel .jio-ticket-color-value,
.aksrt-ticket-status-panel .aksrt-ticket-key { .jio-ticket-status-panel .jio-ticket-key {
font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
font-size: 12px; font-size: 12px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
} }
/* 徽章与前台 assets/css/routes/tickets.css 的 .aksrt-ticket-badge 同构;表格与弹窗预览共用。 */ /* 徽章与前台 assets/css/routes/tickets.css 的 .jio-ticket-badge 同构;表格与弹窗预览共用。 */
.aksrt-ticket-status-panel .aksrt-ticket-badge, .jio-ticket-status-panel .jio-ticket-badge,
.aksrt-status-modal .aksrt-ticket-badge { .jio-status-modal .jio-ticket-badge {
display: inline-block; display: inline-block;
padding: 2px 10px; padding: 2px 10px;
border-radius: 999px; border-radius: 999px;
background: color-mix(in srgb, var(--aksrt-ticket-color, #6b7280) 16%, transparent); background: color-mix(in srgb, var(--jio-ticket-color, #6b7280) 16%, transparent);
color: var(--aksrt-ticket-color, #6b7280); color: var(--jio-ticket-color, #6b7280);
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
line-height: 1.6; line-height: 1.6;
@@ -387,24 +387,24 @@ defineExpose({ reload: load })
<style scoped> <style scoped>
/* —— 弹窗:顶部实时预览 —— */ /* —— 弹窗:顶部实时预览 —— */
.aksrt-status-preview { .jio-status-preview {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
gap: 12px; gap: 12px;
margin-bottom: 18px; margin-bottom: 18px;
padding: 14px 16px; padding: 14px 16px;
border: 1px dashed var(--aksrt-color-border); border: 1px dashed var(--jio-color-border);
border-radius: 8px; border-radius: 8px;
background: rgba(0, 0, 0, 0.02); background: rgba(0, 0, 0, 0.02);
} }
.aksrt-status-preview__label { .jio-status-preview__label {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 12px; font-size: 12px;
} }
.aksrt-status-preview .aksrt-ticket-badge { .jio-status-preview .jio-ticket-badge {
max-width: 70%; max-width: 70%;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -412,20 +412,20 @@ defineExpose({ reload: load })
} }
/* —— 弹窗:颜色选择(预设色板 + 自定义 + 十六进制输入) —— */ /* —— 弹窗:颜色选择(预设色板 + 自定义 + 十六进制输入) —— */
.aksrt-status-color { .jio-status-color {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 12px; gap: 12px;
width: 100%; width: 100%;
} }
.aksrt-status-color__swatches { .jio-status-color__swatches {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 10px; gap: 10px;
} }
.aksrt-status-color__swatch { .jio-status-color__swatch {
position: relative; position: relative;
width: 28px; width: 28px;
height: 28px; height: 28px;
@@ -438,21 +438,21 @@ defineExpose({ reload: load })
transition: transform 0.12s ease, box-shadow 0.12s ease; transition: transform 0.12s ease, box-shadow 0.12s ease;
} }
.aksrt-status-color__swatch:hover { .jio-status-color__swatch:hover {
transform: scale(1.1); transform: scale(1.1);
} }
.aksrt-status-color__swatch:focus-visible { .jio-status-color__swatch:focus-visible {
outline: 2px solid var(--aksrt-color-primary, #2271b1); outline: 2px solid var(--jio-color-primary, #2271b1);
outline-offset: 2px; outline-offset: 2px;
} }
/* 选中态:白色内圈 + 同色外环,深浅主题都清晰。 */ /* 选中态:白色内圈 + 同色外环,深浅主题都清晰。 */
.aksrt-status-color__swatch.is-active { .jio-status-color__swatch.is-active {
box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--swatch); box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--swatch);
} }
.aksrt-status-color__swatch.is-active::after { .jio-status-color__swatch.is-active::after {
content: ''; content: '';
position: absolute; position: absolute;
left: 50%; left: 50%;
@@ -465,11 +465,11 @@ defineExpose({ reload: load })
} }
/* 自定义:未选中时显示色环,提示「更多颜色」。 */ /* 自定义:未选中时显示色环,提示「更多颜色」。 */
.aksrt-status-color__swatch--custom:not(.is-active) { .jio-status-color__swatch--custom:not(.is-active) {
background: conic-gradient(#ef4444, #f59e0b, #eab308, #22c55e, #06b6d4, #3b82f6, #8b5cf6, #ec4899, #ef4444); background: conic-gradient(#ef4444, #f59e0b, #eab308, #22c55e, #06b6d4, #3b82f6, #8b5cf6, #ec4899, #ef4444);
} }
.aksrt-status-color__swatch--custom:not(.is-active)::after { .jio-status-color__swatch--custom:not(.is-active)::after {
content: '+'; content: '+';
position: absolute; position: absolute;
inset: 5px; inset: 5px;
@@ -484,12 +484,12 @@ defineExpose({ reload: load })
line-height: 1; line-height: 1;
} }
.aksrt-status-color__hex { .jio-status-color__hex {
width: 160px; width: 160px;
font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
} }
.aksrt-status-color__chip { .jio-status-color__chip {
display: inline-block; display: inline-block;
width: 14px; width: 14px;
height: 14px; height: 14px;
@@ -498,26 +498,26 @@ defineExpose({ reload: load })
} }
/* —— 弹窗:标识 —— */ /* —— 弹窗:标识 —— */
.aksrt-status-key { .jio-status-key {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
width: 100%; width: 100%;
} }
.aksrt-status-key__input { .jio-status-key__input {
font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace); font-family: var(--n-font-family-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
} }
/* —— 弹窗:完结开关 —— */ /* —— 弹窗:完结开关 —— */
.aksrt-status-closed { .jio-status-closed {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
} }
.aksrt-ticket-status__hint { .jio-ticket-status__hint {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 12px; font-size: 12px;
} }
</style> </style>
@@ -1,6 +1,6 @@
<template> <template>
<n-card class="aksrt-section-card"> <n-card class="jio-section-card">
<div class="aksrt-section-header"> <div class="jio-section-header">
<h3>工单部门</h3> <h3>工单部门</h3>
<n-button size="small" type="primary" :disabled="saving" @click="openCreate">新增部门</n-button> <n-button size="small" type="primary" :disabled="saving" @click="openCreate">新增部门</n-button>
</div> </div>
+4 -4
View File
@@ -12,7 +12,7 @@ function resolveComponent(page) {
// Log missing component for debugging — avoids silent fallback to DeferredPage // Log missing component for debugging — avoids silent fallback to DeferredPage
if (page.component && page.component !== 'DeferredPage') { if (page.component && page.component !== 'DeferredPage') {
console.warn( console.warn(
`[AKSRT Route] Component "${page.component}" not found in componentLoaders for route "${page.route}". Falling back to DeferredPage.` `[Jio Route] Component "${page.component}" not found in componentLoaders for route "${page.route}". Falling back to DeferredPage.`
) )
} }
@@ -77,9 +77,9 @@ function createSectionRedirectRoutes() {
* (封禁/举报 as a sidebar entry lives in constants/sections/users.js → /users/ban.) * (封禁/举报 as a sidebar entry lives in constants/sections/users.js → /users/ban.)
*/ */
const NATIVE_OPS_REDIRECTS = [ const NATIVE_OPS_REDIRECTS = [
{ path: '/users/messages', title: '消息中心', nativeAdminPath: 'users.php?page=aksrt_messages' }, { path: '/users/messages', title: '消息中心', nativeAdminPath: 'users.php?page=jio_messages' },
{ path: '/users/report', title: '禁封/举报', nativeAdminPath: 'users.php?page=aksrt_user_ban' }, { path: '/users/report', title: '禁封/举报', nativeAdminPath: 'users.php?page=jio_user_ban' },
{ path: '/users/tickets', title: '工单管理', nativeAdminPath: 'users.php?page=aksrt_tickets' }, { path: '/users/tickets', title: '工单管理', nativeAdminPath: 'users.php?page=jio_tickets' },
] ]
const routes = [ const routes = [
+1 -1
View File
@@ -2,7 +2,7 @@
* Schema Registry — central index for all admin section schemas. * Schema Registry — central index for all admin section schemas.
* *
* Each section's schema defines the form fields, groups, API endpoints, * Each section's schema defines the form fields, groups, API endpoints,
* and default values for a settings page. The AksFormRenderer component * and default values for a settings page. The JioFormRenderer component
* consumes these schemas to render settings pages automatically. * consumes these schemas to render settings pages automatically.
* *
* Schema shape per section: * Schema shape per section:
@@ -1,5 +1,5 @@
const themeRoot = typeof window !== 'undefined' && window.aksrtAdminData?.themeUri const themeRoot = typeof window !== 'undefined' && window.jioAdminData?.themeUri
? String(window.aksrtAdminData.themeUri).replace(/\/$/, '') ? String(window.jioAdminData.themeUri).replace(/\/$/, '')
: '' : ''
const defaultThumbnail = themeRoot ? `${themeRoot}/assets/img/thumbnail.svg` : '' const defaultThumbnail = themeRoot ? `${themeRoot}/assets/img/thumbnail.svg` : ''
@@ -37,7 +37,7 @@ export const i18nSchema = {
], ],
dependsOn: { key: 'i18n_enabled', value: true }, dependsOn: { key: 'i18n_enabled', value: true },
}, },
{ key: 'i18n_auto_detect', label: '自动检测浏览器语言', type: 'switch', default: true, dependsOn: { key: 'i18n_enabled', value: true }, help: '基于浏览器 Accept-Language 自动切换(AKSRT 方案,区别于 legacy IP 定位方案)' }, { key: 'i18n_auto_detect', label: '自动检测浏览器语言', type: 'switch', default: true, dependsOn: { key: 'i18n_enabled', value: true }, help: '基于浏览器 Accept-Language 自动切换(Jio 方案,区别于 legacy IP 定位方案)' },
], ],
}, },
{ {
@@ -20,7 +20,7 @@ export const searchSchema = {
search_custom_key: ['title', 'content', 'excerpt', 'category', 'post_tag'], search_custom_key: ['title', 'content', 'excerpt', 'category', 'post_tag'],
search_facets: {}, search_facets: {},
search_ms_s: false, search_ms_s: false,
search_ms_opt: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'aksrt', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] }, search_ms_opt: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'jio', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] },
}, },
groups: [ groups: [
{ {
@@ -98,10 +98,10 @@ export const searchSchema = {
icon: 'fa fas fa-bolt', icon: 'fa fas fa-bolt',
fields: [ fields: [
{ key: 'search_ms_s', label: '启用 Meilisearch', type: 'switch', default: false }, { key: 'search_ms_s', label: '启用 Meilisearch', type: 'switch', default: false },
{ key: 'search_ms_opt', label: 'Meilisearch 参数', type: 'fieldset', sanitizeType: 'array', dependsOn: { key: 'search_ms_s', value: true }, default: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'aksrt', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] }, fields: [ { key: 'search_ms_opt', label: 'Meilisearch 参数', type: 'fieldset', sanitizeType: 'array', dependsOn: { key: 'search_ms_s', value: true }, default: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'jio', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] }, fields: [
{ key: 'api_url', label: 'API 地址', type: 'input', default: 'http://127.0.0.1:7700' }, { key: 'api_url', label: 'API 地址', type: 'input', default: 'http://127.0.0.1:7700' },
{ key: 'api_key', label: 'API 密钥', type: 'input', default: '' }, { key: 'api_key', label: 'API 密钥', type: 'input', default: '' },
{ key: 'index_prefix', label: '索引前缀', type: 'input', default: 'aksrt' }, { key: 'index_prefix', label: '索引前缀', type: 'input', default: 'jio' },
{ key: 'synonyms', label: '同义词', type: 'repeater', default: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }], addText: '添加同义词', fields: [ { key: 'synonyms', label: '同义词', type: 'repeater', default: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }], addText: '添加同义词', fields: [
{ key: 'key', label: '关键词', type: 'input', default: '' }, { key: 'key', label: '关键词', type: 'input', default: '' },
{ key: 'val', label: '同义词', type: 'textarea', default: '' }, { key: 'val', label: '同义词', type: 'textarea', default: '' },
@@ -1,5 +1,5 @@
const themeRoot = typeof window !== 'undefined' && window.aksrtAdminData?.themeUri const themeRoot = typeof window !== 'undefined' && window.jioAdminData?.themeUri
? String(window.aksrtAdminData.themeUri).replace(/\/$/, '') ? String(window.jioAdminData.themeUri).replace(/\/$/, '')
: '' : ''
const shareOptions = [ const shareOptions = [
@@ -93,7 +93,7 @@ export const gatewaySchema = {
label: '', label: '',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<ul><li>以下收款接口,主题仅提供API接入服务,收款平台的可靠性请自行斟酌!</li><li>涉及到资金及信息安全,有相关执照的商家推荐使用官方接口</li><li>微信 / 支付宝接口可在「官方」与「易支付」之间选择;PayPal 与 Stripe 独立开关</li><li>异步回调由各网关验签,无需额外口令;回调地址固定为 /wp-json/aksrt/v1/payment/{gateway}/{notify|return}</li></ul>', content: '<ul><li>以下收款接口,主题仅提供API接入服务,收款平台的可靠性请自行斟酌!</li><li>涉及到资金及信息安全,有相关执照的商家推荐使用官方接口</li><li>微信 / 支付宝接口可在「官方」与「易支付」之间选择;PayPal 与 Stripe 独立开关</li><li>异步回调由各网关验签,无需额外口令;回调地址固定为 /wp-json/jio/v1/payment/{gateway}/{notify|return}</li></ul>',
}, },
], ],
}, },
@@ -159,7 +159,7 @@ export const gatewaySchema = {
], ],
}, },
{ key: 'pay_sdk_custom_title_s', label: '自定义收款标题', type: 'switch', default: false, help: '默认为付款类型加网站名,如需自定义请开启' }, { key: 'pay_sdk_custom_title_s', label: '自定义收款标题', type: 'switch', default: false, help: '默认为付款类型加网站名,如需自定义请开启' },
{ key: 'pay_sdk_custom_title', label: '自定义收款标题', type: 'input', default: '', dependsOn: { key: 'pay_sdk_custom_title_s', value: true }, help: '可使用变量:订单类型 %order_type%,例如:%order_type%-AKSRT;注意控制总长度,太长会导致部分接口报错' }, { key: 'pay_sdk_custom_title', label: '自定义收款标题', type: 'input', default: '', dependsOn: { key: 'pay_sdk_custom_title_s', value: true }, help: '可使用变量:订单类型 %order_type%,例如:%order_type%-Jio;注意控制总长度,太长会导致部分接口报错' },
], ],
}, },
{ {
@@ -208,7 +208,7 @@ export const gatewaySchema = {
label: '', label: '',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<ul><li>支付宝公钥为必填项目(公钥错误可以成功付款,但会回调失败)</li><li>回调地址固定为 /wp-json/aksrt/v1/payment/alipay/{notify|return}</li><li>电脑端按「电脑端收款」选择站内二维码或跳转;手机端开启 H5 时跳转,否则显示二维码</li></ul>', content: '<ul><li>支付宝公钥为必填项目(公钥错误可以成功付款,但会回调失败)</li><li>回调地址固定为 /wp-json/jio/v1/payment/alipay/{notify|return}</li><li>电脑端按「电脑端收款」选择站内二维码或跳转;手机端开启 H5 时跳转,否则显示二维码</li></ul>',
}, },
{ key: 'alipay_appid', label: '当面付:APPID', type: 'input', default: '' }, { key: 'alipay_appid', label: '当面付:APPID', type: 'input', default: '' },
{ key: 'alipay_privatekey', label: '当面付:应用私钥', type: 'textarea', sanitize_type: 'code', default: '', rows: 4, secret: true }, { key: 'alipay_privatekey', label: '当面付:应用私钥', type: 'textarea', sanitize_type: 'code', default: '', rows: 4, secret: true },
@@ -243,7 +243,7 @@ export const gatewaySchema = {
label: '', label: '',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<ul><li>微信企业支付:官方接口,商家可申请,有年费,申请较为复杂</li><li>回调地址固定为 /wp-json/aksrt/v1/payment/wechatpay/{notify|return},请配置 Native 支付回调链接</li><li>电脑端显示站内二维码;手机端按下方开关选择 H5 跳转或微信内 JSAPI,未开启时同样显示二维码</li></ul>', content: '<ul><li>微信企业支付:官方接口,商家可申请,有年费,申请较为复杂</li><li>回调地址固定为 /wp-json/jio/v1/payment/wechatpay/{notify|return},请配置 Native 支付回调链接</li><li>电脑端显示站内二维码;手机端按下方开关选择 H5 跳转或微信内 JSAPI,未开启时同样显示二维码</li></ul>',
}, },
{ key: 'wechat_merchantid', label: '商户号 PartnerID', type: 'input', default: '' }, { key: 'wechat_merchantid', label: '商户号 PartnerID', type: 'input', default: '' },
{ key: 'wechat_appid', label: '授权绑定的AppID', type: 'input', default: '' }, { key: 'wechat_appid', label: '授权绑定的AppID', type: 'input', default: '' },
@@ -1,6 +1,6 @@
/** /**
* 知识付费 — 1:1 复刻参考主题对应页面(免登陆购买 / 模块位置 / 优惠码 / * 知识付费 — 1:1 复刻参考主题对应页面(免登陆购买 / 模块位置 / 优惠码 /
* 客户服务 / 付费下载 / 商品预置参数),并保留 AKSRT 订单展示与状态文案。 * 客户服务 / 付费下载 / 商品预置参数),并保留 Jio 订单展示与状态文案。
*/ */
export const knowledgeSchema = { export const knowledgeSchema = {
key: 'payment.knowledge', key: 'payment.knowledge',
@@ -34,7 +34,7 @@ const vipUnitOptions = [
{ label: '月', value: 'month' }, { label: '月', value: 'month' },
]; ];
// 会员商品/续费商品:标题行显示价格与时长摘要(行默认收起由 AksField 统一处理)。 // 会员商品/续费商品:标题行显示价格与时长摘要(行默认收起由 JioField 统一处理)。
const vipProductGroupOptions = { const vipProductGroupOptions = {
listPreview: { prefix: '价格:', titleKey: 'price', descKey: 'time', descUnitKey: 'unit' }, listPreview: { prefix: '价格:', titleKey: 'price', descKey: 'time', descUnitKey: 'unit' },
}; };
@@ -5,7 +5,7 @@
/** /**
* User type options shared by the upload limit repeaters. * User type options shared by the upload limit repeaters.
* Mirrors AKSRT\Attachment\UploadLimits::user_type_options() (levels 2-10, VIP 1-2). * Mirrors Jio\Attachment\UploadLimits::user_type_options() (levels 2-10, VIP 1-2).
*/ */
const uploadUserTypeOptions = [ const uploadUserTypeOptions = [
{ label: '最小默认值(所有人)', value: 'default' }, { label: '最小默认值(所有人)', value: 'default' },
@@ -33,7 +33,7 @@ export const commentSchema = {
type: 'content', type: 'content',
ui_only: true, ui_only: true,
dependsOn: { key: 'close_comments', value: false }, dependsOn: { key: 'close_comments', value: false },
content: '<p class="aksrt-hint"><i class="fa fas fa-fw fa-info-circle"></i> WordPress默认关闭评论翻页功能,如需启用请按此进行设置:<br/>1. 进入WP讨论设置,勾选 <code>分页显示评论</code><br/>2. 设置默认显示 <code>最前</code>一页<br/>3. 设置在每个页面顶部显示 <code>旧的</code>评论<br/>4. 根据需要设置每一页显示数量<br/>5. 根据需要设置评论嵌套(推荐开启并设置为3层)<br/>6. wp默认开启免登陆评论,如需关闭则勾选<code>需要登录后才能发表评论</code><br/><a href="options-discussion.php">【去设置】</a></p>', content: '<p class="jio-hint"><i class="fa fas fa-fw fa-info-circle"></i> WordPress默认关闭评论翻页功能,如需启用请按此进行设置:<br/>1. 进入WP讨论设置,勾选 <code>分页显示评论</code><br/>2. 设置默认显示 <code>最前</code>一页<br/>3. 设置在每个页面顶部显示 <code>旧的</code>评论<br/>4. 根据需要设置每一页显示数量<br/>5. 根据需要设置评论嵌套(推荐开启并设置为3层)<br/>6. wp默认开启免登陆评论,如需关闭则勾选<code>需要登录后才能发表评论</code><br/><a href="options-discussion.php">【去设置】</a></p>',
}, },
{ key: 'close_comments', label: '关闭文章评论功能', type: 'switch', default: false, description: '部分网站无需交互,或需备案审核,可在此关闭所有文章的评论功能。同时每一篇文章可单独关闭评论功能' }, { key: 'close_comments', label: '关闭文章评论功能', type: 'switch', default: false, description: '部分网站无需交互,或需备案审核,可在此关闭所有文章的评论功能。同时每一篇文章可单独关闭评论功能' },
{ {
@@ -28,7 +28,7 @@ export const featureSchema = {
type: 'content', type: 'content',
ui_only: true, ui_only: true,
dependsOn: { key: 'article_nav', value: true }, dependsOn: { key: 'article_nav', value: true },
content: '<p class="aksrt-hint"><a href="https://www.zibll.com/1717.html" target="_blank">【查看官网教程】</a></p>', content: '<p class="jio-hint"><a href="https://www.zibll.com/1717.html" target="_blank">【查看官网教程】</a></p>',
}, },
{ key: 'article_nav_mobile_nav_s', label: '在移动端弹出菜单内显示', type: 'switch', default: true, dependsOn: { key: 'article_nav', value: true }, description: '如需显示在侧边栏等其它位置,请使用小工具模块添加' }, { key: 'article_nav_mobile_nav_s', label: '在移动端弹出菜单内显示', type: 'switch', default: true, dependsOn: { key: 'article_nav', value: true }, description: '如需显示在侧边栏等其它位置,请使用小工具模块添加' },
{ key: 'imagelightbox', label: '图片灯箱', type: 'switch', default: true, description: '点击图片查看原图功能,共两种模式' }, { key: 'imagelightbox', label: '图片灯箱', type: 'switch', default: true, description: '点击图片查看原图功能,共两种模式' },
@@ -38,7 +38,7 @@ export const featureSchema = {
type: 'content', type: 'content',
ui_only: true, ui_only: true,
dependsOn: { key: 'imagelightbox', value: true }, dependsOn: { key: 'imagelightbox', value: true },
content: '<p class="aksrt-hint"><a href="https://www.zibll.com/683.html" target="_blank">【查看官网教程】</a></p>', content: '<p class="jio-hint"><a href="https://www.zibll.com/683.html" target="_blank">【查看官网教程】</a></p>',
}, },
{ {
key: 'imagelightbox_type', key: 'imagelightbox_type',
@@ -18,7 +18,7 @@ export const filterSchema = {
key: 'filter_intro', key: 'filter_intro',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<p class="aksrt-hint"><b>文章高级筛选功能:</b>通过此功能可实现更加复杂、精细化的内容筛选<br/>添加筛选类型和内容值之后,编写文章时候,可以进行选择,且在前台也可以实现精准筛选<br/>例如影视网站:[类型]有[剧情/喜剧/悬疑/惊悚/犯罪],[地区]有[大陆/美国/日韩/港台/印度],[年份]有[2022/2021/2020/10年代/00年代]等<br/><span class="aksrt-warn">注意事项:添加类型key时候,只能使用英文加下划线,不能有空格,且尽量复杂一点(不能为tag,category等系统已存在的类型),避免与其他mate_key重复!类型名称不能为分类、标签等系统已存在的类型</span><br/><a href="https://www.zibll.com/15886.html" target="_blank">查看官网教程</a></p>', content: '<p class="jio-hint"><b>文章高级筛选功能:</b>通过此功能可实现更加复杂、精细化的内容筛选<br/>添加筛选类型和内容值之后,编写文章时候,可以进行选择,且在前台也可以实现精准筛选<br/>例如影视网站:[类型]有[剧情/喜剧/悬疑/惊悚/犯罪],[地区]有[大陆/美国/日韩/港台/印度],[年份]有[2022/2021/2020/10年代/00年代]等<br/><span class="jio-warn">注意事项:添加类型key时候,只能使用英文加下划线,不能有空格,且尽量复杂一点(不能为tag,category等系统已存在的类型),避免与其他mate_key重复!类型名称不能为分类、标签等系统已存在的类型</span><br/><a href="https://www.zibll.com/15886.html" target="_blank">查看官网教程</a></p>',
}, },
{ {
key: 'custom_filter_show', key: 'custom_filter_show',
@@ -146,7 +146,7 @@ export const pageSchema = {
key: 'yiyan_intro', key: 'yiyan_intro',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<p class="aksrt-hint"><b>精彩一言功能:</b>随机显示中英文文案,可插入文章页或添加“一言”小工具。默认句库位于 <code>themes/aksrt/yiyan/qv-yiyan.txt</code>。您也可以将自定义句库保存为 <code>wp-content/yiyan.txt</code>,更新主题时即可保留自定义内容。</p>', content: '<p class="jio-hint"><b>精彩一言功能:</b>随机显示中英文文案,可插入文章页或添加“一言”小工具。默认句库位于 <code>themes/jio/yiyan/qv-yiyan.txt</code>。您也可以将自定义句库保存为 <code>wp-content/yiyan.txt</code>,更新主题时即可保留自定义内容。</p>',
}, },
{ key: 'yiyan_single_content_header', label: '文章内容头部显示一言', type: 'switch', default: false }, { key: 'yiyan_single_content_header', label: '文章内容头部显示一言', type: 'switch', default: false },
{ key: 'yiyan_single_content_footer', label: '文章内容尾部显示一言', type: 'switch', default: false }, { key: 'yiyan_single_content_footer', label: '文章内容尾部显示一言', type: 'switch', default: false },
@@ -30,7 +30,7 @@ export const submitSchema = {
label: '', label: '',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<p class="aksrt-hint">此功能启用后,可以在<a href="admin.php?page=aksrt-settings#/permissions/capabilities">权限管理</a>中设置用户的发布、审核权限 <a href="admin.php?page=aksrt-settings#/permissions/capabilities">【去设置】</a></p>', content: '<p class="jio-hint">此功能启用后,可以在<a href="admin.php?page=jio-settings#/permissions/capabilities">权限管理</a>中设置用户的发布、审核权限 <a href="admin.php?page=jio-settings#/permissions/capabilities">【去设置】</a></p>',
}, },
{ key: 'post_article_btn_txte', label: '按钮文字', type: 'input', default: '发布文章', dependsOn: { key: 'post_article_s', value: true }, description: '投稿按钮的显示的文字,推荐4个字更加协调' }, { key: 'post_article_btn_txte', label: '按钮文字', type: 'input', default: '发布文章', dependsOn: { key: 'post_article_s', value: true }, description: '投稿按钮的显示的文字,推荐4个字更加协调' },
{ key: 'post_article_cat', label: '投稿允许选择的分类', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [], placeholder: '输入关键词以搜索分类', dependsOn: { key: 'post_article_s', value: true }, description: '投稿允许选择的分类,为空则允许选择全部分类,所选分类下如果有子分类则会自动显示,如果选择了上级分类,则不要再选该分类下的子分类。注意:请确保所选分类包含子分类总数不要超过50个,否则可能会引起页面崩溃' }, { key: 'post_article_cat', label: '投稿允许选择的分类', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [], placeholder: '输入关键词以搜索分类', dependsOn: { key: 'post_article_s', value: true }, description: '投稿允许选择的分类,为空则允许选择全部分类,所选分类下如果有子分类则会自动显示,如果选择了上级分类,则不要再选该分类下的子分类。注意:请确保所选分类包含子分类总数不要超过50个,否则可能会引起页面崩溃' },
@@ -40,7 +40,7 @@ export const submitSchema = {
label: '', label: '',
type: 'content', type: 'content',
ui_only: true, ui_only: true,
content: '<p class="aksrt-hint">此功能启用后,请先在<a href="admin.php?page=aksrt-settings#/post-list/filter">文章列表/高级筛选</a>中添加高级筛选明细 <a href="admin.php?page=aksrt-settings#/post-list/filter">【去设置】</a></p>', content: '<p class="jio-hint">此功能启用后,请先在<a href="admin.php?page=jio-settings#/post-list/filter">文章列表/高级筛选</a>中添加高级筛选明细 <a href="admin.php?page=jio-settings#/post-list/filter">【去设置】</a></p>',
}, },
{ key: 'post_article_tag', label: '允许插入标签', type: 'switch', default: true, dependsOn: { key: 'post_article_s', value: true }, description: '前台投稿时候允许设置文章标签' }, { key: 'post_article_tag', label: '允许插入标签', type: 'switch', default: true, dependsOn: { key: 'post_article_s', value: true }, description: '前台投稿时候允许设置文章标签' },
{ key: 'post_article_user', label: '免登陆投稿发布用户', type: 'user_select', default: 1, dependsOn: { key: 'post_article_s', value: true }, description: '当选择投稿权限为无需登录就能投稿时,投稿文章的用户' }, { key: 'post_article_user', label: '免登陆投稿发布用户', type: 'user_select', default: 1, dependsOn: { key: 'post_article_s', value: true }, description: '当选择投稿权限为无需登录就能投稿时,投稿文章的用户' },
@@ -1,6 +1,6 @@
/** legacy 9.0 list-thumbnail settings. */ /** legacy 9.0 list-thumbnail settings. */
const themeRoot = typeof window !== 'undefined' && window.aksrtAdminData?.themeUri const themeRoot = typeof window !== 'undefined' && window.jioAdminData?.themeUri
? String(window.aksrtAdminData.themeUri).replace(/\/$/, '') ? String(window.jioAdminData.themeUri).replace(/\/$/, '')
: '' : ''
const spareThumbnailDefault = [{ img: `${themeRoot}/assets/img/thumbnail.svg` }] const spareThumbnailDefault = [{ img: `${themeRoot}/assets/img/thumbnail.svg` }]
@@ -11,7 +11,7 @@ export const importExportSchema = {
icon: 'fa fas fa-share', icon: 'fa fas fa-share',
fields: [ fields: [
{ key: 'export_settings', label: '导出主题设置', type: 'button', help: '导出当前所有主题配置为 JSON 文件' }, { key: 'export_settings', label: '导出主题设置', type: 'button', help: '导出当前所有主题配置为 JSON 文件' },
{ key: 'export_options', label: '导出 WordPress 选项', type: 'button', help: '导出 aksrt_settings 等选项' }, { key: 'export_options', label: '导出 WordPress 选项', type: 'button', help: '导出 jio_settings 等选项' },
], ],
}, },
{ {
@@ -74,7 +74,7 @@ export const authSchema = {
{ key: 'sign_modal_auto_waiting_time', label: '等待时间(秒)', type: 'number', default: 5, min: 1, max: 100, dependsOn: { key: 'sign_modal_auto_s', value: true } }, { key: 'sign_modal_auto_waiting_time', label: '等待时间(秒)', type: 'number', default: 5, min: 1, max: 100, dependsOn: { key: 'sign_modal_auto_s', value: true } },
{ key: 'sign_modal_auto_expires', label: '自动弹窗周期(小时)', type: 'number', default: 1, min: 0, max: 2000, dependsOn: { key: 'sign_modal_auto_s', value: true } }, { key: 'sign_modal_auto_expires', label: '自动弹窗周期(小时)', type: 'number', default: 1, min: 0, max: 2000, dependsOn: { key: 'sign_modal_auto_s', value: true } },
{ key: 'replace_wp_login', label: '代替 WP 自带登录页面', type: 'switch', default: true }, { key: 'replace_wp_login', label: '代替 WP 自带登录页面', type: 'switch', default: true },
{ key: 'admin_sign_key', label: '应急登录 Key', type: 'input', default: '', dependsOn: { key: 'replace_wp_login', value: true }, help: '通过 /wp-login.php?aksrt_bypass=<key> 使用 WP 登录页' }, { key: 'admin_sign_key', label: '应急登录 Key', type: 'input', default: '', dependsOn: { key: 'replace_wp_login', value: true }, help: '通过 /wp-login.php?jio_bypass=<key> 使用 WP 登录页' },
], ],
}, },
{ {
@@ -19,7 +19,7 @@ export const MEDAL_GET_TYPES = [
// Resolve medal SVG asset path from theme assets when running in admin context. // Resolve medal SVG asset path from theme assets when running in admin context.
const MEDAL_BASE = (() => { const MEDAL_BASE = (() => {
const root = window.aksrtAdminData?.themeUri || '' const root = window.jioAdminData?.themeUri || ''
return root ? String(root).replace(/\/$/, '') + '/assets/img/medal' : '/assets/img/medal' return root ? String(root).replace(/\/$/, '') + '/assets/img/medal' : '/assets/img/medal'
})() })()
@@ -82,7 +82,7 @@ export const creditsSchema = {
title: '积分抵扣(预留)', title: '积分抵扣(预留)',
icon: 'fa fas fa-percent', icon: 'fa fas fa-percent',
fields: [ fields: [
{ key: 'points_deduction_s', label: '启用积分抵扣', type: 'switch', default: false, help: '对齐 legacy:运行时暂未启用(aksrtpay_is_allow_points_deduction 恒为 false)。字段保留供后续接收银台现金单抵扣。' }, { key: 'points_deduction_s', label: '启用积分抵扣', type: 'switch', default: false, help: '对齐 legacy:运行时暂未启用(jiopay_is_allow_points_deduction 恒为 false)。字段保留供后续接收银台现金单抵扣。' },
{ key: 'points_deduction_rate', label: '积分换算比例', type: 'number', default: 100, min: 1, max: 10000, dependsOn: { key: 'points_deduction_s', value: true }, help: 'legacy 语义:points_deduction_rate = 多少积分抵 1 元(示例 30 表示 30 积分=1 元)。当前未参与下单计算。' }, { key: 'points_deduction_rate', label: '积分换算比例', type: 'number', default: 100, min: 1, max: 10000, dependsOn: { key: 'points_deduction_s', value: true }, help: 'legacy 语义:points_deduction_rate = 多少积分抵 1 元(示例 30 表示 30 积分=1 元)。当前未参与下单计算。' },
{ key: 'points_deduction_max', label: '最大抵扣比例(%)', type: 'number', default: 50, min: 1, max: 100, dependsOn: { key: 'points_deduction_s', value: true }, help: '预留:最多可抵订单金额的百分比。当前未参与下单计算。' }, { key: 'points_deduction_max', label: '最大抵扣比例(%)', type: 'number', default: 50, min: 1, max: 100, dependsOn: { key: 'points_deduction_s', value: true }, help: '预留:最多可抵订单金额的百分比。当前未参与下单计算。' },
], ],
@@ -1,5 +1,5 @@
const themeRoot = typeof window !== 'undefined' && window.aksrtAdminData?.themeUri const themeRoot = typeof window !== 'undefined' && window.jioAdminData?.themeUri
? String(window.aksrtAdminData.themeUri).replace(/\/$/, '') ? String(window.jioAdminData.themeUri).replace(/\/$/, '')
: '' : ''
export const featuresSchema = { export const featuresSchema = {
+141 -141
View File
@@ -1,33 +1,33 @@
#aksrt-admin-app, #jio-admin-app,
#aksrt-admin-app * { #jio-admin-app * {
box-sizing: border-box; box-sizing: border-box;
} }
#aksrt-admin-app { #jio-admin-app {
--aksrt-color-primary: #18A058; --jio-color-primary: #18A058;
--aksrt-color-primary-hover: #36AD6A; --jio-color-primary-hover: #36AD6A;
--aksrt-color-primary-pressed: #0C7A43; --jio-color-primary-pressed: #0C7A43;
--aksrt-color-primary-soft: #EAF7EF; --jio-color-primary-soft: #EAF7EF;
--aksrt-color-canvas: #F5F7F6; --jio-color-canvas: #F5F7F6;
--aksrt-color-surface: #FFFFFF; --jio-color-surface: #FFFFFF;
--aksrt-color-text: #1F2923; --jio-color-text: #1F2923;
--aksrt-color-text-secondary: #465149; --jio-color-text-secondary: #465149;
--aksrt-color-muted: #6F7A72; --jio-color-muted: #6F7A72;
--aksrt-color-border: #E2E8E3; --jio-color-border: #E2E8E3;
--aksrt-color-border-strong: #CCD7CE; --jio-color-border-strong: #CCD7CE;
--aksrt-shadow-card: 0 1px 2px rgba(31, 41, 35, .04); --jio-shadow-card: 0 1px 2px rgba(31, 41, 35, .04);
--aksrt-shadow-floating: 0 12px 32px rgba(31, 41, 35, .12); --jio-shadow-floating: 0 12px 32px rgba(31, 41, 35, .12);
min-height: 100%; min-height: 100%;
color: var(--aksrt-color-text); color: var(--jio-color-text);
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
font-size: 14px; font-size: 14px;
line-height: 1.6; line-height: 1.6;
} }
/* ==================== FA5 Icon in NaiveUI Menu ==================== */ /* ==================== FA5 Icon in NaiveUI Menu ==================== */
#aksrt-admin-app .n-menu .n-menu-item-content i[class*="fa-"], #jio-admin-app .n-menu .n-menu-item-content i[class*="fa-"],
#aksrt-admin-app .n-menu-item-content i[class*="fa-"] { #jio-admin-app .n-menu-item-content i[class*="fa-"] {
font-size: 18px; font-size: 18px;
width: 18px; width: 18px;
text-align: center; text-align: center;
@@ -39,243 +39,243 @@
transition: opacity 0.15s; transition: opacity 0.15s;
} }
#aksrt-admin-app .n-menu-item-content--selected i[class*="fa-"], #jio-admin-app .n-menu-item-content--selected i[class*="fa-"],
#aksrt-admin-app .n-menu-item-content:hover i[class*="fa-"] { #jio-admin-app .n-menu-item-content:hover i[class*="fa-"] {
opacity: 1; opacity: 1;
} }
#aksrt-admin-app .n-layout, #jio-admin-app .n-layout,
#aksrt-admin-app .n-layout-sider { #jio-admin-app .n-layout-sider {
min-height: 100vh; min-height: 100vh;
} }
#aksrt-admin-app .aksrt-admin-layout { #jio-admin-app .jio-admin-layout {
min-height: 100vh; min-height: 100vh;
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
#aksrt-admin-app .aksrt-admin-sider { #jio-admin-app .jio-admin-sider {
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
border-right: 1px solid var(--aksrt-color-border); border-right: 1px solid var(--jio-color-border);
} }
#aksrt-admin-app .aksrt-admin-sider .n-layout-toggle-button { #jio-admin-app .jio-admin-sider .n-layout-toggle-button {
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
box-shadow: var(--aksrt-shadow-card); box-shadow: var(--jio-shadow-card);
} }
#aksrt-admin-app .aksrt-admin-sider .n-layout-toggle-button:hover { #jio-admin-app .jio-admin-sider .n-layout-toggle-button:hover {
border-color: var(--aksrt-color-primary); border-color: var(--jio-color-primary);
color: var(--aksrt-color-primary); color: var(--jio-color-primary);
} }
#aksrt-admin-app .aksrt-admin-menu { #jio-admin-app .jio-admin-menu {
padding: 10px 8px 18px; padding: 10px 8px 18px;
} }
#aksrt-admin-app .aksrt-admin-menu .n-menu-item-content { #jio-admin-app .jio-admin-menu .n-menu-item-content {
position: relative; position: relative;
border-radius: 8px; border-radius: 8px;
transition: color .16s ease, background-color .16s ease; transition: color .16s ease, background-color .16s ease;
} }
#aksrt-admin-app .aksrt-admin-menu .n-menu-item-content--selected::after { #jio-admin-app .jio-admin-menu .n-menu-item-content--selected::after {
position: absolute; position: absolute;
top: 9px; top: 9px;
bottom: 9px; bottom: 9px;
left: 0; left: 0;
width: 3px; width: 3px;
border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0;
background: var(--aksrt-color-primary); background: var(--jio-color-primary);
content: ''; content: '';
} }
#aksrt-admin-app .aksrt-admin-menu .n-submenu-children { #jio-admin-app .jio-admin-menu .n-submenu-children {
margin: 2px 0 6px; margin: 2px 0 6px;
} }
#aksrt-admin-app .aksrt-admin-menu .n-menu-item-content-header { #jio-admin-app .jio-admin-menu .n-menu-item-content-header {
font-weight: 500; font-weight: 500;
} }
#aksrt-admin-app .aksrt-menu-item--secondary .n-menu-item-content-header { #jio-admin-app .jio-menu-item--secondary .n-menu-item-content-header {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 12px; font-size: 12px;
} }
#aksrt-admin-app .aksrt-admin-content { #jio-admin-app .jio-admin-content {
background: var(--aksrt-color-canvas); background: var(--jio-color-canvas);
} }
#aksrt-admin-app .aksrt-schema-page, #jio-admin-app .jio-schema-page,
#aksrt-admin-app .aksrt-page-container, #jio-admin-app .jio-page-container,
#aksrt-admin-app .content-page { #jio-admin-app .content-page {
width: 100%; width: 100%;
max-width: 1180px; max-width: 1180px;
margin: 0 auto; margin: 0 auto;
} }
#aksrt-admin-app .aksrt-form-renderer__save-bar { #jio-admin-app .jio-form-renderer__save-bar {
right: 28px; right: 28px;
left: auto; left: auto;
width: min(1180px, calc(100vw - 448px)); width: min(1180px, calc(100vw - 448px));
border: 1px solid var(--aksrt-color-border); border: 1px solid var(--jio-color-border);
border-bottom: 0; border-bottom: 0;
border-radius: 12px 12px 0 0; border-radius: 12px 12px 0 0;
background: rgba(255, 255, 255, .96); background: rgba(255, 255, 255, .96);
box-shadow: var(--aksrt-shadow-floating); box-shadow: var(--jio-shadow-floating);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
} }
#aksrt-admin-app .aksrt-form-renderer__save-bar__inner { #jio-admin-app .jio-form-renderer__save-bar__inner {
max-width: 1180px; max-width: 1180px;
} }
#aksrt-admin-app .aksrt-form-renderer__save-bar .n-button--primary-type { #jio-admin-app .jio-form-renderer__save-bar .n-button--primary-type {
box-shadow: 0 4px 12px rgba(24, 160, 88, .18); box-shadow: 0 4px 12px rgba(24, 160, 88, .18);
} }
#aksrt-admin-app :where(a, button, input, textarea, select, [tabindex]):focus-visible { #jio-admin-app :where(a, button, input, textarea, select, [tabindex]):focus-visible {
outline: 2px solid var(--aksrt-color-primary); outline: 2px solid var(--jio-color-primary);
outline-offset: 2px; outline-offset: 2px;
} }
#aksrt-admin-app .aksrt-page-title { #jio-admin-app .jio-page-title {
margin: 0 0 12px; margin: 0 0 12px;
color: var(--aksrt-color-text); color: var(--jio-color-text);
font-size: 22px; font-size: 22px;
font-weight: 700; font-weight: 700;
letter-spacing: -0.02em; letter-spacing: -0.02em;
} }
#aksrt-admin-app .aksrt-page-desc { #jio-admin-app .jio-page-desc {
margin: 0 0 24px; margin: 0 0 24px;
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 13px; font-size: 13px;
line-height: 1.7; line-height: 1.7;
} }
#aksrt-admin-app .aksrt-section-card { #jio-admin-app .jio-section-card {
margin-bottom: 18px; margin-bottom: 18px;
border-radius: 12px !important; border-radius: 12px !important;
border: 1px solid var(--aksrt-color-border) !important; border: 1px solid var(--jio-color-border) !important;
background: var(--aksrt-color-surface); background: var(--jio-color-surface);
box-shadow: var(--aksrt-shadow-card); box-shadow: var(--jio-shadow-card);
} }
#aksrt-admin-app .aksrt-section-card .n-card__content { #jio-admin-app .jio-section-card .n-card__content {
padding: 18px 20px 20px !important; padding: 18px 20px 20px !important;
} }
#aksrt-admin-app .aksrt-section-card .n-card-header { #jio-admin-app .jio-section-card .n-card-header {
padding: 18px 20px 0 !important; padding: 18px 20px 0 !important;
} }
#aksrt-admin-app .aksrt-section-header { #jio-admin-app .jio-section-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
margin-bottom: 14px; margin-bottom: 14px;
} }
#aksrt-admin-app .aksrt-section-header h3 { #jio-admin-app .jio-section-header h3 {
margin: 0; margin: 0;
color: var(--aksrt-color-text); color: var(--jio-color-text);
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
} }
#aksrt-admin-app .section-icon, #jio-admin-app .section-icon,
#aksrt-admin-app .header-icon { #jio-admin-app .header-icon {
font-size: 17px; font-size: 17px;
opacity: 0.8; opacity: 0.8;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
} }
#aksrt-admin-app .section-desc, #jio-admin-app .section-desc,
#aksrt-admin-app .aksrt-hint-text { #jio-admin-app .jio-hint-text {
color: var(--aksrt-color-muted); color: var(--jio-color-muted);
font-size: 12px; font-size: 12px;
line-height: 1.6; line-height: 1.6;
} }
#aksrt-admin-app .section-desc { #jio-admin-app .section-desc {
margin: 0 0 14px; margin: 0 0 14px;
} }
#aksrt-admin-app .aksrt-form .n-form-item { #jio-admin-app .jio-form .n-form-item {
margin-bottom: 18px; margin-bottom: 18px;
} }
#aksrt-admin-app .aksrt-form .n-form-item:last-child { #jio-admin-app .jio-form .n-form-item:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
#aksrt-admin-app .aksrt-form .n-form-item-label { #jio-admin-app .jio-form .n-form-item-label {
color: var(--aksrt-color-text-secondary) !important; color: var(--jio-color-text-secondary) !important;
font-size: 13px; font-size: 13px;
font-weight: 500; font-weight: 500;
} }
#aksrt-admin-app .aksrt-form .n-input, #jio-admin-app .jio-form .n-input,
#aksrt-admin-app .aksrt-form .n-select .n-base-selection, #jio-admin-app .jio-form .n-select .n-base-selection,
#aksrt-admin-app .aksrt-form .n-input-number { #jio-admin-app .jio-form .n-input-number {
min-height: 36px; min-height: 36px;
--n-height: 36px !important; --n-height: 36px !important;
} }
#aksrt-admin-app .aksrt-form .n-input--textarea textarea { #jio-admin-app .jio-form .n-input--textarea textarea {
min-height: 84px; min-height: 84px;
} }
#aksrt-admin-app .aksrt-form .n-switch { #jio-admin-app .jio-form .n-switch {
--n-rail-height: 26px !important; --n-rail-height: 26px !important;
--n-rail-width: 48px !important; --n-rail-width: 48px !important;
} }
#aksrt-admin-app .aksrt-form-actions { #jio-admin-app .jio-form-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
padding: 24px 0 8px; padding: 24px 0 8px;
margin-top: 28px; margin-top: 28px;
border-top: 1px solid var(--aksrt-color-border); border-top: 1px solid var(--jio-color-border);
} }
#aksrt-admin-app .aksrt-form-actions .n-button { #jio-admin-app .jio-form-actions .n-button {
min-width: 120px; min-width: 120px;
height: 40px; height: 40px;
font-weight: 500; font-weight: 500;
} }
#aksrt-admin-app .aksrt-tabs .n-tabs-nav { #jio-admin-app .jio-tabs .n-tabs-nav {
margin-bottom: 20px !important; margin-bottom: 20px !important;
} }
#aksrt-admin-app .aksrt-tabs .n-tabs-tab { #jio-admin-app .jio-tabs .n-tabs-tab {
padding: 10px 20px !important; padding: 10px 20px !important;
font-size: 14px !important; font-size: 14px !important;
font-weight: 500; font-weight: 500;
} }
#aksrt-admin-app .n-data-table { #jio-admin-app .n-data-table {
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
} }
#aksrt-admin-app .n-data-table .n-data-table-th { #jio-admin-app .n-data-table .n-data-table-th {
background: #f7f9f7; background: #f7f9f7;
} }
#aksrt-admin-app .n-empty { #jio-admin-app .n-empty {
padding: 24px 0; padding: 24px 0;
} }
#aksrt-admin-app .aksrt-card-header-row { #jio-admin-app .jio-card-header-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -284,19 +284,19 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
#aksrt-admin-app .aksrt-card-header-row__left { #jio-admin-app .jio-card-header-row__left {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
min-width: 0; min-width: 0;
} }
#aksrt-admin-app .aksrt-card-header-row__title { #jio-admin-app .jio-card-header-row__title {
font-weight: 600; font-weight: 600;
} }
/* ==================== 卡片 header 行(标题 + 按钮) ==================== */ /* ==================== 卡片 header 行(标题 + 按钮) ==================== */
#aksrt-admin-app .aksrt-card-header-row { #jio-admin-app .jio-card-header-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -305,18 +305,18 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
#aksrt-admin-app .aksrt-card-header-row__left { #jio-admin-app .jio-card-header-row__left {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
min-width: 0; min-width: 0;
} }
#aksrt-admin-app .aksrt-card-header-row__title { #jio-admin-app .jio-card-header-row__title {
margin: 0; margin: 0;
font-size: 15px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: var(--aksrt-color-text); color: var(--jio-color-text);
} }
/* ==================== 过渡 ==================== */ /* ==================== 过渡 ==================== */
@@ -336,23 +336,23 @@
} }
/* ==================== Modal 样式(弹层) ==================== */ /* ==================== Modal 样式(弹层) ==================== */
.aksrt-modal-card { .jio-modal-card {
width: 100%; width: 100%;
max-width: 520px; max-width: 520px;
} }
/* 弹层底部操作栏;弹层 teleport 到 #aksrt-admin-app 之外,token 带回退值。 */ /* 弹层底部操作栏;弹层 teleport 到 #jio-admin-app 之外,token 带回退值。 */
.aksrt-modal-footer { .jio-modal-footer {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
gap: 8px; gap: 8px;
margin-top: 16px; margin-top: 16px;
padding-top: 12px; padding-top: 12px;
border-top: 1px solid var(--aksrt-color-border, #E2E8E3); border-top: 1px solid var(--jio-color-border, #E2E8E3);
} }
@media (max-width: 960px) { @media (max-width: 960px) {
#aksrt-admin-app .aksrt-form-renderer__save-bar { #jio-admin-app .jio-form-renderer__save-bar {
right: 0; right: 0;
left: 0; left: 0;
width: auto; width: auto;
@@ -361,11 +361,11 @@
border-radius: 0; border-radius: 0;
} }
#aksrt-admin-app .aksrt-page-wrapper { #jio-admin-app .jio-page-wrapper {
width: 100%; width: 100%;
} }
#aksrt-admin-app .aksrt-admin-menu { #jio-admin-app .jio-admin-menu {
padding-top: 8px; padding-top: 8px;
} }
} }
@@ -373,50 +373,50 @@
/* ==================== 移动端适配 ==================== */ /* ==================== 移动端适配 ==================== */
@media (max-width: 768px) { @media (max-width: 768px) {
/* 容器 */ /* 容器 */
#aksrt-admin-app .aksrt-page-container, #jio-admin-app .jio-page-container,
#aksrt-admin-app .content-page { #jio-admin-app .content-page {
max-width: 100%; max-width: 100%;
padding: 0; padding: 0;
} }
#aksrt-admin-app .aksrt-field__desc { #jio-admin-app .jio-field__desc {
margin: 2px 0 8px; margin: 2px 0 8px;
} }
#aksrt-admin-app .aksrt-page-title { #jio-admin-app .jio-page-title {
font-size: 18px; font-size: 18px;
margin-bottom: 8px; margin-bottom: 8px;
} }
#aksrt-admin-app .aksrt-page-desc { #jio-admin-app .jio-page-desc {
font-size: 12px; font-size: 12px;
margin-bottom: 14px; margin-bottom: 14px;
} }
/* 卡片紧凑 */ /* 卡片紧凑 */
#aksrt-admin-app .aksrt-section-card { #jio-admin-app .jio-section-card {
margin-bottom: 12px; margin-bottom: 12px;
border-radius: 10px !important; border-radius: 10px !important;
} }
#aksrt-admin-app .aksrt-section-card .n-card__content { #jio-admin-app .jio-section-card .n-card__content {
padding: 14px !important; padding: 14px !important;
} }
#aksrt-admin-app .aksrt-section-card .n-card-header { #jio-admin-app .jio-section-card .n-card-header {
padding: 14px 14px 0 !important; padding: 14px 14px 0 !important;
} }
#aksrt-admin-app .aksrt-section-header { #jio-admin-app .jio-section-header {
margin-bottom: 10px; margin-bottom: 10px;
} }
/* 表单:label 改为顶部排列(覆盖 left 模式) */ /* 表单:label 改为顶部排列(覆盖 left 模式) */
#aksrt-admin-app .aksrt-form .n-form-item { #jio-admin-app .jio-form .n-form-item {
margin-bottom: 14px; margin-bottom: 14px;
} }
#aksrt-admin-app .aksrt-form .n-form-item .n-form-item-label { #jio-admin-app .jio-form .n-form-item .n-form-item-label {
text-align: left !important; text-align: left !important;
padding: 0 0 6px !important; padding: 0 0 6px !important;
width: auto !important; width: auto !important;
@@ -425,44 +425,44 @@
justify-content: flex-start !important; justify-content: flex-start !important;
} }
#aksrt-admin-app .aksrt-form .n-form-item-blank { #jio-admin-app .jio-form .n-form-item-blank {
width: 100%; width: 100%;
} }
/* 强制行内表单单列 */ /* 强制行内表单单列 */
#aksrt-admin-app .aksrt-form .n-form-item .n-form-item-label, #jio-admin-app .jio-form .n-form-item .n-form-item-label,
#aksrt-admin-app .aksrt-form .n-form-item-row { #jio-admin-app .jio-form .n-form-item-row {
display: block !important; display: block !important;
} }
/* radio button 自动换行 */ /* radio button 自动换行 */
#aksrt-admin-app .aksrt-form .n-radio-group { #jio-admin-app .jio-form .n-radio-group {
width: 100%; width: 100%;
} }
#aksrt-admin-app .aksrt-form .n-radio-group .n-space { #jio-admin-app .jio-form .n-radio-group .n-space {
flex-wrap: wrap !important; flex-wrap: wrap !important;
gap: 6px 8px !important; gap: 6px 8px !important;
} }
#aksrt-admin-app .aksrt-form .n-radio-button { #jio-admin-app .jio-form .n-radio-button {
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0; min-width: 0;
} }
/* 输入组在窄屏堆叠 */ /* 输入组在窄屏堆叠 */
#aksrt-admin-app .aksrt-form .n-input-group { #jio-admin-app .jio-form .n-input-group {
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 6px;
} }
#aksrt-admin-app .aksrt-form .n-input-group > .n-input, #jio-admin-app .jio-form .n-input-group > .n-input,
#aksrt-admin-app .aksrt-form .n-input-group > .n-button { #jio-admin-app .jio-form .n-input-group > .n-button {
border-radius: 6px !important; border-radius: 6px !important;
} }
/* 表单底部按钮区 */ /* 表单底部按钮区 */
#aksrt-admin-app .aksrt-form-actions { #jio-admin-app .jio-form-actions {
flex-direction: column-reverse; flex-direction: column-reverse;
align-items: stretch; align-items: stretch;
padding: 16px 0 8px; padding: 16px 0 8px;
@@ -470,14 +470,14 @@
gap: 8px; gap: 8px;
} }
#aksrt-admin-app .aksrt-form-actions .n-button { #jio-admin-app .jio-form-actions .n-button {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
height: 42px; height: 42px;
} }
/* 卡片 header 行:换行排列 */ /* 卡片 header 行:换行排列 */
#aksrt-admin-app .aksrt-card-header-row { #jio-admin-app .jio-card-header-row {
gap: 8px; gap: 8px;
} }
@@ -491,7 +491,7 @@
min-height: 100vh; min-height: 100vh;
} }
.aksrt-modal-card { .jio-modal-card {
max-width: 100vw !important; max-width: 100vw !important;
width: 100vw !important; width: 100vw !important;
min-height: 100vh; min-height: 100vh;
@@ -499,19 +499,19 @@
} }
/* 数据表格隐藏次要列 */ /* 数据表格隐藏次要列 */
.aksrt-table-mobile-hide, .jio-table-mobile-hide,
#aksrt-admin-app .n-data-table .aksrt-table-mobile-hide { #jio-admin-app .n-data-table .jio-table-mobile-hide {
display: none !important; display: none !important;
} }
/* 表格内边距收紧 */ /* 表格内边距收紧 */
#aksrt-admin-app .n-data-table .n-data-table-td, #jio-admin-app .n-data-table .n-data-table-td,
#aksrt-admin-app .n-data-table .n-data-table-th { #jio-admin-app .n-data-table .n-data-table-th {
padding: 8px 10px !important; padding: 8px 10px !important;
} }
/* tabs */ /* tabs */
#aksrt-admin-app .aksrt-tabs .n-tabs-tab { #jio-admin-app .jio-tabs .n-tabs-tab {
padding: 8px 12px !important; padding: 8px 12px !important;
font-size: 13px !important; font-size: 13px !important;
} }
@@ -524,19 +524,19 @@
/* ==================== 超窄设备(<= 480px)追加 ==================== */ /* ==================== 超窄设备(<= 480px)追加 ==================== */
@media (max-width: 480px) { @media (max-width: 480px) {
#aksrt-admin-app .aksrt-section-card .n-card__content { #jio-admin-app .jio-section-card .n-card__content {
padding: 12px !important; padding: 12px !important;
} }
#aksrt-admin-app .aksrt-section-card .n-card-header { #jio-admin-app .jio-section-card .n-card-header {
padding: 12px 12px 0 !important; padding: 12px 12px 0 !important;
} }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
#aksrt-admin-app *, #jio-admin-app *,
#aksrt-admin-app *::before, #jio-admin-app *::before,
#aksrt-admin-app *::after { #jio-admin-app *::after {
scroll-behavior: auto !important; scroll-behavior: auto !important;
animation-duration: .01ms !important; animation-duration: .01ms !important;
animation-iteration-count: 1 !important; animation-iteration-count: 1 !important;
+65 -65
View File
@@ -4,36 +4,36 @@
* 后台所有可排序列表(schema 排序字段 / 重复器 / 启用-停用排序器 / 悬浮按钮 / * 后台所有可排序列表(schema 排序字段 / 重复器 / 启用-停用排序器 / 悬浮按钮 /
* 底部 Tab / 工单预设回复)统一使用这套类名,并配合 SORTABLE_LIST_ATTRS: * 底部 Tab / 工单预设回复)统一使用这套类名,并配合 SORTABLE_LIST_ATTRS:
* *
* .aksrt-sortable 列表容器(draggable 根节点) * .jio-sortable 列表容器(draggable 根节点)
* .aksrt-sortable__item 卡片行 * .jio-sortable__item 卡片行
* .aksrt-sortable__head 行头:handle / index / icon / main / actions * .jio-sortable__head 行头:handle / index / icon / main / actions
* .aksrt-sortable__body 可选:展开后的字段区 * .jio-sortable__body 可选:展开后的字段区
* *
* 弹窗内容会被 teleport 到 #aksrt-admin-app 之外,因此 token 都带回退值。 * 弹窗内容会被 teleport 到 #jio-admin-app 之外,因此 token 都带回退值。
*/ */
.aksrt-sortable { .jio-sortable {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
} }
.aksrt-sortable--compact { .jio-sortable--compact {
gap: 6px; gap: 6px;
} }
.aksrt-sortable__item { .jio-sortable__item {
border: 1px solid var(--aksrt-color-border, #E2E8E3); border: 1px solid var(--jio-color-border, #E2E8E3);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-surface, #FFFFFF); background: var(--jio-color-surface, #FFFFFF);
box-shadow: var(--aksrt-shadow-card, 0 1px 2px rgba(31, 41, 35, .04)); box-shadow: var(--jio-shadow-card, 0 1px 2px rgba(31, 41, 35, .04));
transition: border-color .15s ease, box-shadow .15s ease; transition: border-color .15s ease, box-shadow .15s ease;
} }
.aksrt-sortable__item:hover { .jio-sortable__item:hover {
border-color: var(--aksrt-color-border-strong, #CCD7CE); border-color: var(--jio-color-border-strong, #CCD7CE);
} }
.aksrt-sortable__head { .jio-sortable__head {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
@@ -41,29 +41,29 @@
padding: 8px 12px 8px 8px; padding: 8px 12px 8px 8px;
} }
.aksrt-sortable--compact .aksrt-sortable__head { .jio-sortable--compact .jio-sortable__head {
gap: 8px; gap: 8px;
min-height: 38px; min-height: 38px;
padding: 4px 10px 4px 4px; padding: 4px 10px 4px 4px;
} }
.aksrt-sortable__head.is-clickable { .jio-sortable__head.is-clickable {
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
} }
.aksrt-sortable__head.is-clickable:focus-visible { .jio-sortable__head.is-clickable:focus-visible {
outline: 2px solid var(--aksrt-color-primary, #18A058); outline: 2px solid var(--jio-color-primary, #18A058);
outline-offset: -2px; outline-offset: -2px;
border-radius: 8px; border-radius: 8px;
} }
.aksrt-sortable__head.is-clickable:hover .aksrt-sortable__title, .jio-sortable__head.is-clickable:hover .jio-sortable__title,
.aksrt-sortable__head.is-clickable:hover .aksrt-sortable__toggle { .jio-sortable__head.is-clickable:hover .jio-sortable__toggle {
color: var(--aksrt-color-primary, #18A058); color: var(--jio-color-primary, #18A058);
} }
.aksrt-sortable__handle { .jio-sortable__handle {
display: inline-flex; display: inline-flex;
flex: 0 0 auto; flex: 0 0 auto;
align-items: center; align-items: center;
@@ -74,25 +74,25 @@
border: 0; border: 0;
border-radius: 6px; border-radius: 6px;
background: transparent; background: transparent;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 13px; font-size: 13px;
cursor: grab; cursor: grab;
touch-action: none; touch-action: none;
transition: color .15s ease, background-color .15s ease; transition: color .15s ease, background-color .15s ease;
} }
.aksrt-sortable__handle:hover, .jio-sortable__handle:hover,
.aksrt-sortable__handle:focus-visible { .jio-sortable__handle:focus-visible {
outline: none; outline: none;
background: var(--aksrt-color-primary-soft, #EAF7EF); background: var(--jio-color-primary-soft, #EAF7EF);
color: var(--aksrt-color-primary, #18A058); color: var(--jio-color-primary, #18A058);
} }
.aksrt-sortable__handle:active { .jio-sortable__handle:active {
cursor: grabbing; cursor: grabbing;
} }
.aksrt-sortable__index { .jio-sortable__index {
display: inline-flex; display: inline-flex;
flex: 0 0 auto; flex: 0 0 auto;
align-items: center; align-items: center;
@@ -101,14 +101,14 @@
height: 22px; height: 22px;
padding: 0 6px; padding: 0 6px;
border-radius: 11px; border-radius: 11px;
background: var(--aksrt-color-canvas, #F5F7F6); background: var(--jio-color-canvas, #F5F7F6);
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
.aksrt-sortable__icon { .jio-sortable__icon {
display: inline-flex; display: inline-flex;
flex: 0 0 auto; flex: 0 0 auto;
align-items: center; align-items: center;
@@ -117,19 +117,19 @@
height: 36px; height: 36px;
overflow: hidden; overflow: hidden;
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-primary-soft, #EAF7EF); background: var(--jio-color-primary-soft, #EAF7EF);
color: var(--aksrt-color-primary, #18A058); color: var(--jio-color-primary, #18A058);
font-size: 16px; font-size: 16px;
} }
.aksrt-sortable__icon svg, .jio-sortable__icon svg,
.aksrt-sortable__icon img { .jio-sortable__icon img {
width: 20px; width: 20px;
height: 20px; height: 20px;
object-fit: contain; object-fit: contain;
} }
.aksrt-sortable__main { .jio-sortable__main {
display: flex; display: flex;
flex: 1 1 auto; flex: 1 1 auto;
flex-direction: column; flex-direction: column;
@@ -138,7 +138,7 @@
min-width: 0; min-width: 0;
} }
.aksrt-sortable__title-row { .jio-sortable__title-row {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
@@ -146,10 +146,10 @@
min-width: 0; min-width: 0;
} }
.aksrt-sortable__title { .jio-sortable__title {
min-width: 0; min-width: 0;
overflow: hidden; overflow: hidden;
color: var(--aksrt-color-text, #1F2923); color: var(--jio-color-text, #1F2923);
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
line-height: 1.4; line-height: 1.4;
@@ -158,17 +158,17 @@
transition: color .15s ease; transition: color .15s ease;
} }
.aksrt-sortable__desc { .jio-sortable__desc {
min-width: 0; min-width: 0;
overflow: hidden; overflow: hidden;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 12px; font-size: 12px;
line-height: 1.4; line-height: 1.4;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.aksrt-sortable__actions { .jio-sortable__actions {
display: flex; display: flex;
flex: 0 0 auto; flex: 0 0 auto;
align-items: center; align-items: center;
@@ -176,67 +176,67 @@
margin-left: auto; margin-left: auto;
} }
.aksrt-sortable__toggle { .jio-sortable__toggle {
flex: 0 0 auto; flex: 0 0 auto;
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 12px; font-size: 12px;
transition: color .15s ease; transition: color .15s ease;
} }
.aksrt-sortable__body { .jio-sortable__body {
padding: 14px 16px 16px; padding: 14px 16px 16px;
border-top: 1px solid var(--aksrt-color-border, #E2E8E3); border-top: 1px solid var(--jio-color-border, #E2E8E3);
} }
/* 拖拽中:原位置留下虚线占位,被拖动的卡片浮起。 */ /* 拖拽中:原位置留下虚线占位,被拖动的卡片浮起。 */
.aksrt-sortable__chosen { .jio-sortable__chosen {
border-color: var(--aksrt-color-primary, #18A058); border-color: var(--jio-color-primary, #18A058);
} }
.aksrt-sortable__drag { .jio-sortable__drag {
box-shadow: var(--aksrt-shadow-floating, 0 12px 32px rgba(31, 41, 35, .12)); box-shadow: var(--jio-shadow-floating, 0 12px 32px rgba(31, 41, 35, .12));
} }
.aksrt-sortable__ghost { .jio-sortable__ghost {
border-style: dashed; border-style: dashed;
border-color: var(--aksrt-color-primary, #18A058); border-color: var(--jio-color-primary, #18A058);
background: var(--aksrt-color-primary-soft, #EAF7EF); background: var(--jio-color-primary-soft, #EAF7EF);
box-shadow: none; box-shadow: none;
} }
.aksrt-sortable__ghost > * { .jio-sortable__ghost > * {
visibility: hidden; visibility: hidden;
} }
.aksrt-sortable__empty { .jio-sortable__empty {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 6px; gap: 6px;
padding: 20px 12px; padding: 20px 12px;
border: 1px dashed var(--aksrt-color-border-strong, #CCD7CE); border: 1px dashed var(--jio-color-border-strong, #CCD7CE);
border-radius: 8px; border-radius: 8px;
background: var(--aksrt-color-canvas, #F5F7F6); background: var(--jio-color-canvas, #F5F7F6);
color: var(--aksrt-color-muted, #6F7A72); color: var(--jio-color-muted, #6F7A72);
font-size: 13px; font-size: 13px;
} }
@media (max-width: 640px) { @media (max-width: 640px) {
.aksrt-sortable__head { .jio-sortable__head {
flex-wrap: wrap; flex-wrap: wrap;
} }
.aksrt-sortable__main { .jio-sortable__main {
flex-basis: 160px; flex-basis: 160px;
} }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.aksrt-sortable__item, .jio-sortable__item,
.aksrt-sortable__handle, .jio-sortable__handle,
.aksrt-sortable__title, .jio-sortable__title,
.aksrt-sortable__toggle { .jio-sortable__toggle {
transition: none; transition: none;
} }
} }
+1 -1
View File
@@ -1,5 +1,5 @@
/** /**
* 颜色值归一化:与 PHP `AKSRT\Core\Color::sanitize()` 规则一致。 * 颜色值归一化:与 PHP `Jio\Core\Color::sanitize()` 规则一致。
* *
* - 不带 alpha:仅 #rgb / #rrggbb; * - 不带 alpha:仅 #rgb / #rrggbb;
* - 带 alpha:另允许 #rgba / #rrggbbaa 与 rgb()/rgba(); * - 带 alpha:另允许 #rgba / #rrggbbaa 与 rgb()/rgba();
+1 -1
View File
@@ -3,7 +3,7 @@
* *
* Supported stored formats: * Supported stored formats:
* "fa fas fa-star" — FA5 class string * "fa fas fa-star" — FA5 class string
* "zibsvg-hot" — theme built-in SVG sprite key (window.aksrt_svgs) * "zibsvg-hot" — theme built-in SVG sprite key (window.jio_svgs)
* "customsvg-<svg>" — inline user SVG markup * "customsvg-<svg>" — inline user SVG markup
*/ */
+29 -29
View File
@@ -1,10 +1,10 @@
/* AKSRT universal icon picker (admin) */ /* Jio universal icon picker (admin) */
#aksrt-modal-icon.aksrt-icon-modal { #jio-modal-icon.jio-icon-modal {
display: none; display: none;
} }
#aksrt-modal-icon.aksrt-icon-modal:not(.hidden) { #jio-modal-icon.jio-icon-modal:not(.hidden) {
display: flex; display: flex;
position: fixed; position: fixed;
inset: 0; inset: 0;
@@ -15,17 +15,17 @@
/* Tab/search switching toggles the [hidden] attribute, but the explicit /* Tab/search switching toggles the [hidden] attribute, but the explicit
display rules below would beat the UA's [hidden] rule — re-assert it. */ display rules below would beat the UA's [hidden] rule — re-assert it. */
#aksrt-modal-icon [hidden] { #jio-modal-icon [hidden] {
display: none !important; display: none !important;
} }
#aksrt-modal-icon .aksrt-icon-modal__overlay { #jio-modal-icon .jio-icon-modal__overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
background: rgba(0, 0, 0, 0.55); background: rgba(0, 0, 0, 0.55);
} }
#aksrt-modal-icon .aksrt-icon-modal__inner { #jio-modal-icon .jio-icon-modal__inner {
position: relative; position: relative;
z-index: 1; z-index: 1;
display: flex; display: flex;
@@ -38,7 +38,7 @@
overflow: hidden; overflow: hidden;
} }
#aksrt-modal-icon .aksrt-icon-modal__header { #jio-modal-icon .jio-icon-modal__header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -47,14 +47,14 @@
font-size: 14px; font-size: 14px;
} }
#aksrt-modal-icon .aksrt-icon-modal__close { #jio-modal-icon .jio-icon-modal__close {
font-size: 20px; font-size: 20px;
line-height: 1; line-height: 1;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
} }
#aksrt-modal-icon .aksrt-icon-modal__toolbar { #jio-modal-icon .jio-icon-modal__toolbar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
@@ -63,40 +63,40 @@
border-bottom: 1px solid #e2e4e7; border-bottom: 1px solid #e2e4e7;
} }
#aksrt-modal-icon .aksrt-icon-modal__tabs { #jio-modal-icon .jio-icon-modal__tabs {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 6px;
} }
#aksrt-modal-icon .aksrt-icon-modal__tab.is-active { #jio-modal-icon .jio-icon-modal__tab.is-active {
border-color: #2271b1; border-color: #2271b1;
color: #2271b1; color: #2271b1;
} }
#aksrt-modal-icon .aksrt-icon-modal__body { #jio-modal-icon .jio-icon-modal__body {
position: relative; position: relative;
overflow-y: auto; overflow-y: auto;
padding: 12px 16px 16px; padding: 12px 16px 16px;
} }
#aksrt-modal-icon .aksrt-icon-modal__loading { #jio-modal-icon .jio-icon-modal__loading {
padding: 24px 0; padding: 24px 0;
text-align: center; text-align: center;
} }
#aksrt-modal-icon .aksrt-icon-modal__error { #jio-modal-icon .jio-icon-modal__error {
color: #b32d2e; color: #b32d2e;
} }
#aksrt-modal-icon .aksrt-icon-modal__grid { #jio-modal-icon .jio-icon-modal__grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(42px, 1fr));
gap: 4px; gap: 4px;
margin-top: 8px; margin-top: 8px;
} }
#aksrt-modal-icon .aksrt-icon-picker__item { #jio-modal-icon .jio-icon-picker__item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -111,18 +111,18 @@
cursor: pointer; cursor: pointer;
} }
#aksrt-modal-icon .aksrt-icon-picker__item:hover { #jio-modal-icon .jio-icon-picker__item:hover {
border-color: #2271b1; border-color: #2271b1;
color: #2271b1; color: #2271b1;
} }
#aksrt-modal-icon .aksrt-icon-picker__item .icon { #jio-modal-icon .jio-icon-picker__item .icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: currentColor; fill: currentColor;
} }
#aksrt-modal-icon .aksrt-icon-picker__empty { #jio-modal-icon .jio-icon-picker__empty {
grid-column: 1 / -1; grid-column: 1 / -1;
padding: 20px 0; padding: 20px 0;
color: #787c82; color: #787c82;
@@ -131,22 +131,22 @@
/* Custom SVG tab */ /* Custom SVG tab */
#aksrt-modal-icon .aksrt-icon-modal__custom { #jio-modal-icon .jio-icon-modal__custom {
margin-top: 4px; margin-top: 4px;
} }
#aksrt-modal-icon .aksrt-icon-modal__custom textarea { #jio-modal-icon .jio-icon-modal__custom textarea {
margin-top: 4px; margin-top: 4px;
} }
#aksrt-modal-icon .aksrt-icon-modal__custom-actions { #jio-modal-icon .jio-icon-modal__custom-actions {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
margin-top: 8px; margin-top: 8px;
} }
#aksrt-modal-icon .aksrt-icon-modal__custom-preview { #jio-modal-icon .jio-icon-modal__custom-preview {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -157,12 +157,12 @@
font-size: 18px; font-size: 18px;
} }
#aksrt-modal-icon .aksrt-icon-modal__custom-preview svg { #jio-modal-icon .jio-icon-modal__custom-preview svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
#aksrt-modal-icon .aksrt-icon-modal__grid--session { #jio-modal-icon .jio-icon-modal__grid--session {
margin-top: 12px; margin-top: 12px;
padding-top: 8px; padding-top: 8px;
border-top: 1px solid #e2e4e7; border-top: 1px solid #e2e4e7;
@@ -170,14 +170,14 @@
/* Field markup (widgets, nav menus, meta boxes) */ /* Field markup (widgets, nav menus, meta boxes) */
.aksrt-icon-picker { .jio-icon-picker {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
} }
.aksrt-icon-picker .aksrt-icon-picker__preview { .jio-icon-picker .jio-icon-picker__preview {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -189,13 +189,13 @@
font-size: 16px; font-size: 16px;
} }
.aksrt-icon-picker .aksrt-icon-picker__preview svg { .jio-icon-picker .jio-icon-picker__preview svg {
width: 18px; width: 18px;
height: 18px; height: 18px;
fill: currentColor; fill: currentColor;
} }
.aksrt-icon-picker .aksrt-icon-picker__value { .jio-icon-picker .jio-icon-picker__value {
flex: 1 1 160px; flex: 1 1 160px;
min-width: 0; min-width: 0;
} }
+7 -7
View File
@@ -669,7 +669,7 @@ code {
/**---------------------通知结束-------------**/ /**---------------------通知结束-------------**/
/**---------批量编辑------------**/ /**---------批量编辑------------**/
.aksrt-bulk-edit-box { .jio-bulk-edit-box {
margin: -1px; margin: -1px;
background: #f8fcff; background: #f8fcff;
border: 1px solid #d2d2d2; border: 1px solid #d2d2d2;
@@ -677,25 +677,25 @@ code {
flex: auto; flex: auto;
} }
.aksrt-bulk-edit-box label { .jio-bulk-edit-box label {
line-height: 1.2; line-height: 1.2;
} }
.aksrt-bulk-edit-box > * + * { .jio-bulk-edit-box > * + * {
margin-top: 6px; margin-top: 6px;
} }
.aksrt-bulk-edit-box select, .jio-bulk-edit-box select,
.aksrt-bulk-edit-box input[type="text"] { .jio-bulk-edit-box input[type="text"] {
max-width: 100%; max-width: 100%;
margin-right: 4px; margin-right: 4px;
} }
.inline-edit-row fieldset .aksrt-bulk-edit-box { .inline-edit-row fieldset .jio-bulk-edit-box {
min-width: 168px; min-width: 168px;
} }
.aksrt-bulk-edit-desc { .jio-bulk-edit-desc {
color: #787c82; color: #787c82;
} }
+1 -1
View File
@@ -1 +1 @@
a:focus{box-shadow:none;outline:0}.px12{font-size:12px}.em12{font-size:1.2em}.em14{font-size:1.4em}.em16{font-size:1.6em}.em2x{font-size:2em}.em3x{font-size:3em}.em4x{font-size:4em}.em09{font-size:.9em}.dashicons{width:1em;height:1em}.text-center{text-align:center}.font-bold{font-weight:700}.opacity3{opacity:.3}.pointer{cursor:pointer}.relative{position:relative}.but[disabled],.but[disabled]:hover,.opacity5{opacity:.5}.opacity8{opacity:.8}badge{font-size:.8em;line-height:1.2;padding:.1em .4em;min-width:.8em;min-height:.8em;display:inline-block;vertical-align:.1em;border-radius:50px;background:var(--this-bg);color:var(--this-color);top:5px;--this-color:#fff;text-align:center;--this-bg:#fe3459}code{border-radius:4px}.badg,.but{border-radius:4px;display:inline-block;border-radius:4px;transition:.15s!important;vertical-align:middle;font-size:14px;padding:5px 20px;text-align:center;box-shadow:var(--this-shadow);background:var(--this-bg);color:var(--this-color);border:1px solid var(--this-border);--main-color:var(--this-color);--this-bg:rgba(136, 136, 136, 0.1);--this-border:transparent;--this-shadow:none;--this-color:#888;line-height:1.44;margin:2px;min-height:unset;text-decoration:none}.badg{font-size:.9em;padding:.05em .25em}.but a{color:inherit}.but svg.icon,.but>.fa{margin-right:.25em}.but.radius,.radius>.but{border-radius:50px;padding:.3em .8em}.badg.hollow,.but.hollow{background:0 0;--this-border:var(--this-color)}.but:focus,.but:hover{opacity:.8;background:var(--this-bg);color:var(--this-color);--this-shadow:0;box-shadow:none}.but:active{--this-shadow:inset 0 2px 6px rgba(0, 0, 0, 0.2);background:var(--this-bg);color:var(--this-color)}.but.hollow:hover{background:var(--this-color);color:#fff}[disabled]{opacity:.6!important;-webkit-filter:grayscale(20%);filter:grayscale(20%);cursor:no-drop!important}.but.padding-lg,.padding-lg{padding:.5em 2em}.b-black,.b-blue,.b-cyan,.b-green,.b-purple,.b-red,.b-theme,.b-yellow,.jb-blue,.jb-green,.jb-pink,.jb-purple,.jb-red,.jb-vip1,.jb-vip2,.jb-yellow{color:#fff;background:var(--this-bg);--this-color:#fff}.jb-blue,.jb-cyan,.jb-green,.jb-pink,.jb-purple,.jb-red,.jb-vip1,.jb-vip2,.jb-yellow{border:none}.b-cyan{--this-bg:#08c4c1}.b-theme{--this-bg:var(--focus-color)}.b-red{--this-bg:#ff5473}.b-yellow{--this-bg:#ff6f06}.b-blue{--this-bg:#2997f7}.b-green{--this-bg:#12b928}.b-purple{--this-bg:#d448f5}.b-black{--this-bg:#121517}.c-blue,.c-blue-2,.c-green,.c-purple,.c-red,.c-yellow{color:var(--this-color)}.c-red{--this-color:#ff5473;--this-bg:rgba(255, 84, 115, 0.1)}.c-yellow{--this-color:#ff6f06;--this-bg:rgba(255, 111, 6, 0.1)}.c-blue{--this-color:#2997f7;--this-bg:rgba(41, 151, 247, 0.1)}.c-blue-2{--this-color:#5c7cff;--this-bg:rgba(77, 130, 249, 0.1)}.c-green{--this-color:#12b928;--this-bg:rgba(18, 185, 40, 0.1)}.c-purple{--this-color:#d448f5;--this-bg:rgba(213, 72, 245, 0.1)}.jb-red{--this-bg:linear-gradient(135deg, #fd7a64 10%, #fb2d2d 100%)}.jb-yellow{--this-bg:linear-gradient(135deg, #f99d4d 10%, #f7631d 100%)}.jb-blue{--this-bg:linear-gradient(135deg, #59c3fb 10%, #268df7 100%)}.jb-green{--this-bg:linear-gradient(135deg, #60e464 10%, #5cb85b 100%)}.jb-purple{--this-bg:linear-gradient(135deg, #f98dfb 10%, #ea00f9 100%)}.jb-pink{--this-bg:linear-gradient(135deg, #ff5e7f 30%, #ff967e 100%)}.jb-vip1{--this-bg:linear-gradient(25deg, #eabe7b 10%, #f5e3c7 70%, #edc788 100%);--this-color:#866127}.jb-vip2{--this-bg:linear-gradient(317deg, #4d4c4c 30%, #7b7b7b 70%, #5f5c5c 100%);--this-color:#ddd}.c-cyan{--this-color:#09a4a1;--this-bg:rgba(8, 196, 193, 0.1)}.hide{display:none!important}.absolute{position:absolute;left:0;top:0;right:0;bottom:0;width:100%;height:100%}.flex{display:flex}.inflex{display:inline-flex}.flex.xx,.inflex.xx{flex-direction:column}.flex.hh{flex-wrap:wrap}.flex.ac,.inflex.ac{align-items:center}.flex.abl,.inflex.abl{align-items:baseline}.flex.ab,.inflex.ab{align-items:end}.flex.jc,.inflex.jc{align-items:center;justify-content:center}.flex.je{justify-content:flex-end}.flex.jsb,.inflex.jsb{justify-content:space-between}.flex .grow1{flex-grow:1}.flex .shrink0{flex-shrink:0}.flex .flex0{flex:none}.flex .flex1{flex:1}.overflow-hidden{overflow:hidden}.mm3{margin:3px}.mr3{margin-right:3px}.mr6{margin-right:6px}.mr10{margin-right:10px}.mr20{margin-right:20px}.ml3{margin-left:3px}.mln3{margin-left:-3px}.ml6{margin-left:6px}.ml10{margin-left:10px}.ml20{margin-left:20px}.mt3{margin-top:3px}.mt6{margin-top:6px}.mt10{margin-top:10px}.mt15{margin-top:15px}.mt20{margin-top:20px}.mb6{margin-bottom:6px}.mb10{margin-bottom:10px}.mb20{margin-bottom:20px}.padding-10{padding:10px}.padding-15{padding:15px}.padding-h6{padding-top:6px;padding-bottom:6px}.padding-h10{padding-top:10px;padding-bottom:10px}.border-bottom{border-bottom:1px solid #e8e8e8}.border-bottom:last-of-type{border:none}.max-vh5,.max-vh7{max-height:70vh;-ms-overflow-style:none;overflow:-moz-scrollbars-none;overflow-x:hidden;overflow-y:auto}.max-vh5{max-height:50vh}.muted-2-color{opacity:.6}.text-ellipsis{overflow:hLine truncated a:focus{box-shadow:none;outline:0}.px12{font-size:12px}.em12{font-size:1.2em}.em14{font-size:1.4em}.em16{font-size:1.6em}.em2x{font-size:2em}.em3x{font-size:3em}.em4x{font-size:4em}.em09{font-size:.9em}.dashicons{width:1em;height:1em}.text-center{text-align:center}.font-bold{font-weight:700}.opacity3{opacity:.3}.pointer{cursor:pointer}.relative{position:relative}.but[disabled],.but[disabled]:hover,.opacity5{opacity:.5}.opacity8{opacity:.8}badge{font-size:.8em;line-height:1.2;padding:.1em .4em;min-width:.8em;min-height:.8em;display:inline-block;vertical-align:.1em;border-radius:50px;background:var(--this-bg);color:var(--this-color);top:5px;--this-color:#fff;text-align:center;--this-bg:#fe3459}code{border-radius:4px}.badg,.but{border-radius:4px;display:inline-block;border-radius:4px;transition:.15s!important;vertical-align:middle;font-size:14px;padding:5px 20px;text-align:center;box-shadow:var(--this-shadow);background:var(--this-bg);color:var(--this-color);border:1px solid var(--this-border);--main-color:var(--this-color);--this-bg:rgba(136, 136, 136, 0.1);--this-border:transparent;--this-shadow:none;--this-color:#888;line-height:1.44;margin:2px;min-height:unset;text-decoration:none}.badg{font-size:.9em;padding:.05em .25em}.but a{color:inherit}.but svg.icon,.but>.fa{margin-right:.25em}.but.radius,.radius>.but{border-radius:50px;padding:.3em .8em}.badg.hollow,.but.hollow{background:0 0;--this-border:var(--this-color)}.but:focus,.but:hover{opacity:.8;background:var(--this-bg);color:var(--this-color);--this-shadow:0;box-shadow:none}.but:active{--this-shadow:inset 0 2px 6px rgba(0, 0, 0, 0.2);background:var(--this-bg);color:var(--this-color)}.but.hollow:hover{background:var(--this-color);color:#fff}[disabled]{opacity:.6!important;-webkit-filter:grayscale(20%);filter:grayscale(20%);cursor:no-drop!important}.but.padding-lg,.padding-lg{padding:.5em 2em}.b-black,.b-blue,.b-cyan,.b-green,.b-purple,.b-red,.b-theme,.b-yellow,.jb-blue,.jb-green,.jb-pink,.jb-purple,.jb-red,.jb-vip1,.jb-vip2,.jb-yellow{color:#fff;background:var(--this-bg);--this-color:#fff}.jb-blue,.jb-cyan,.jb-green,.jb-pink,.jb-purple,.jb-red,.jb-vip1,.jb-vip2,.jb-yellow{border:none}.b-cyan{--this-bg:#08c4c1}.b-theme{--this-bg:var(--focus-color)}.b-red{--this-bg:#ff5473}.b-yellow{--this-bg:#ff6f06}.b-blue{--this-bg:#2997f7}.b-green{--this-bg:#12b928}.b-purple{--this-bg:#d448f5}.b-black{--this-bg:#121517}.c-blue,.c-blue-2,.c-green,.c-purple,.c-red,.c-yellow{color:var(--this-color)}.c-red{--this-color:#ff5473;--this-bg:rgba(255, 84, 115, 0.1)}.c-yellow{--this-color:#ff6f06;--this-bg:rgba(255, 111, 6, 0.1)}.c-blue{--this-color:#2997f7;--this-bg:rgba(41, 151, 247, 0.1)}.c-blue-2{--this-color:#5c7cff;--this-bg:rgba(77, 130, 249, 0.1)}.c-green{--this-color:#12b928;--this-bg:rgba(18, 185, 40, 0.1)}.c-purple{--this-color:#d448f5;--this-bg:rgba(213, 72, 245, 0.1)}.jb-red{--this-bg:linear-gradient(135deg, #fd7a64 10%, #fb2d2d 100%)}.jb-yellow{--this-bg:linear-gradient(135deg, #f99d4d 10%, #f7631d 100%)}.jb-blue{--this-bg:linear-gradient(135deg, #59c3fb 10%, #268df7 100%)}.jb-green{--this-bg:linear-gradient(135deg, #60e464 10%, #5cb85b 100%)}.jb-purple{--this-bg:linear-gradient(135deg, #f98dfb 10%, #ea00f9 100%)}.jb-pink{--this-bg:linear-gradient(135deg, #ff5e7f 30%, #ff967e 100%)}.jb-vip1{--this-bg:linear-gradient(25deg, #eabe7b 10%, #f5e3c7 70%, #edc788 100%);--this-color:#866127}.jb-vip2{--this-bg:linear-gradient(317deg, #4d4c4c 30%, #7b7b7b 70%, #5f5c5c 100%);--this-color:#ddd}.c-cyan{--this-color:#09a4a1;--this-bg:rgba(8, 196, 193, 0.1)}.hide{display:none!important}.absolute{position:absolute;left:0;top:0;right:0;bottom:0;width:100%;height:100%}.flex{display:flex}.inflex{display:inline-flex}.flex.xx,.inflex.xx{flex-direction:column}.flex.hh{flex-wrap:wrap}.flex.ac,.inflex.ac{align-items:center}.flex.abl,.inflex.abl{align-items:baseline}.flex.ab,.inflex.ab{align-items:end}.flex.jc,.inflex.jc{align-items:center;justify-content:center}.flex.je{justify-content:flex-end}.flex.jsb,.inflex.jsb{justify-content:space-between}.flex .grow1{flex-grow:1}.flex .shrink0{flex-shrink:0}.flex .flex0{flex:none}.flex .flex1{flex:1}.overflow-hidden{overflow:hidden}.mm3{margin:3px}.mr3{margin-right:3px}.mr6{margin-right:6px}.mr10{margin-right:10px}.mr20{margin-right:20px}.ml3{margin-left:3px}.mln3{margin-left:-3px}.ml6{margin-left:6px}.ml10{margin-left:10px}.ml20{margin-left:20px}.mt3{margin-top:3px}.mt6{margin-top:6px}.mt10{margin-top:10px}.mt15{margin-top:15px}.mt20{margin-top:20px}.mb6{margin-bottom:6px}.mb10{margin-bottom:10px}.mb20{margin-bottom:20px}.padding-10{padding:10px}.padding-15{padding:15px}.padding-h6{padding-top:6px;padding-bottom:6px}.padding-h10{padding-top:10px;padding-bottom:10px}.border-bottom{border-bottom:1px solid #e8e8e8}.border-bottom:last-of-type{border:none}.max-vh5,.max-vh7{max-height:70vh;-ms-overflow-style:none;overflow:-moz-scrollbars-none;overflow-x:hidden;overflow-y:auto}.max-vh5{max-height:50vh}.muted-2-color{opacity:.6}.text-ellipsis{overflow:hLine truncated
+17 -17
View File
@@ -1,45 +1,45 @@
body.toplevel_page_aksrt-settings { body.toplevel_page_jio-settings {
background: #f5f7fb; background: #f5f7fb;
} }
body.toplevel_page_aksrt-settings #wpcontent { body.toplevel_page_jio-settings #wpcontent {
padding-left: 0; padding-left: 0;
} }
body.toplevel_page_aksrt-settings #wpbody-content { body.toplevel_page_jio-settings #wpbody-content {
padding-bottom: 0; padding-bottom: 0;
} }
body.toplevel_page_aksrt-settings #wpbody-content .wrap { body.toplevel_page_jio-settings #wpbody-content .wrap {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
body.toplevel_page_aksrt-settings #wpbody-content .wrap > h1:first-child { body.toplevel_page_jio-settings #wpbody-content .wrap > h1:first-child {
display: none !important; display: none !important;
} }
body.toplevel_page_aksrt-settings #wpbody-content .notice, body.toplevel_page_jio-settings #wpbody-content .notice,
body.toplevel_page_aksrt-settings #wpbody-content .updated, body.toplevel_page_jio-settings #wpbody-content .updated,
body.toplevel_page_aksrt-settings #wpbody-content .error { body.toplevel_page_jio-settings #wpbody-content .error {
position: relative; position: relative;
z-index: 3; z-index: 3;
margin: 18px 20px 0 0; margin: 18px 20px 0 0;
} }
body.toplevel_page_aksrt-settings #collapse-menu { body.toplevel_page_jio-settings #collapse-menu {
display: none !important; display: none !important;
} }
#aksrt-admin-app { #jio-admin-app {
position: relative; position: relative;
min-height: calc(100vh - 32px); min-height: calc(100vh - 32px);
isolation: isolate; isolation: isolate;
background: transparent; background: transparent;
} }
#aksrt-admin-app:empty::before { #jio-admin-app:empty::before {
content: "AKSRT 管理台加载中..."; content: "Jio 管理台加载中...";
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -63,21 +63,21 @@ body.toplevel_page_aksrt-settings #collapse-menu {
@media screen and (max-width: 782px) { @media screen and (max-width: 782px) {
/* 隐藏 WP 后台默认顶栏的多余间距 */ /* 隐藏 WP 后台默认顶栏的多余间距 */
body.toplevel_page_aksrt-settings #wpbody { body.toplevel_page_jio-settings #wpbody {
padding-top: 0; padding-top: 0;
} }
body.toplevel_page_aksrt-settings #wpcontent { body.toplevel_page_jio-settings #wpcontent {
margin-left: 0 !important; margin-left: 0 !important;
} }
#aksrt-admin-app, #jio-admin-app,
#aksrt-admin-app:empty::before { #jio-admin-app:empty::before {
min-height: calc(100vh - 46px); min-height: calc(100vh - 46px);
} }
/* 移动端把 WP 折叠菜单按钮藏掉,避免与自定义菜单按钮重叠 */ /* 移动端把 WP 折叠菜单按钮藏掉,避免与自定义菜单按钮重叠 */
body.toplevel_page_aksrt-settings #wp-admin-bar-menu-toggle { body.toplevel_page_jio-settings #wp-admin-bar-menu-toggle {
display: none; display: none;
} }
} }
+44 -44
View File
@@ -1,54 +1,54 @@
/* 优惠码(aksrt_coupons):页头按钮 + 新建/批量生成弹窗。复用 native-ui.css 的 --an-* 令牌,规则限定在本页类名下。 */ /* 优惠码(jio_coupons):页头按钮 + 新建/批量生成弹窗。复用 native-ui.css 的 --an-* 令牌,规则限定在本页类名下。 */
.aksrt-coupons-page [hidden], .jio-coupons-page [hidden],
.aksrt-coupon-dialog [hidden] { display: none !important; } .jio-coupon-dialog [hidden] { display: none !important; }
.aksrt-coupons-page .aksrt-native-header__actions .button, .jio-coupons-page .jio-native-header__actions .button,
.aksrt-coupon-generated .aksrt-native-card__actions .button { display: inline-flex; align-items: center; gap: 5px; } .jio-coupon-generated .jio-native-card__actions .button { display: inline-flex; align-items: center; gap: 5px; }
.aksrt-coupons-page .aksrt-native-header__actions .dashicons { margin: 0; font-size: 17px; line-height: 20px; } .jio-coupons-page .jio-native-header__actions .dashicons { margin: 0; font-size: 17px; line-height: 20px; }
.aksrt-coupon-generated .aksrt-native-card__actions .dashicons { margin: 0; font-size: 14px; width: 14px; height: 14px; } .jio-coupon-generated .jio-native-card__actions .dashicons { margin: 0; font-size: 14px; width: 14px; height: 14px; }
/* ---------- 列表 ---------- */ /* ---------- 列表 ---------- */
.aksrt-coupons-page .wp-list-table { min-width: 1000px; } .jio-coupons-page .wp-list-table { min-width: 1000px; }
.aksrt-coupons-page .wp-list-table td { vertical-align: middle; overflow-wrap: anywhere; } .jio-coupons-page .wp-list-table td { vertical-align: middle; overflow-wrap: anywhere; }
.aksrt-coupon-code { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 4px 7px; color: var(--an-text); background: var(--an-bg-soft); border: 1px solid transparent; border-radius: 5px; text-align: left; font-size: 13px; overflow-wrap: anywhere; cursor: pointer; } .jio-coupon-code { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 4px 7px; color: var(--an-text); background: var(--an-bg-soft); border: 1px solid transparent; border-radius: 5px; text-align: left; font-size: 13px; overflow-wrap: anywhere; cursor: pointer; }
.aksrt-coupon-code .dashicons { flex: none; width: 14px; height: 14px; color: var(--an-muted); font-size: 14px; } .jio-coupon-code .dashicons { flex: none; width: 14px; height: 14px; color: var(--an-muted); font-size: 14px; }
.aksrt-coupon-code:hover { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); } .jio-coupon-code:hover { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); }
.aksrt-coupon-code:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-coupon-code:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; }
.aksrt-coupon-generated textarea { margin-top: 8px; resize: vertical; } .jio-coupon-generated textarea { margin-top: 8px; resize: vertical; }
/* ---------- 弹窗 ---------- */ /* ---------- 弹窗 ---------- */
html.aksrt-coupons-modal-open { overflow: hidden; } html.jio-coupons-modal-open { overflow: hidden; }
.aksrt-coupon-dialog { width: min(720px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); margin: auto; padding: 0; overflow: hidden; color: var(--an-text-2); background: var(--an-card); border: 0; border-radius: var(--an-radius); box-shadow: 0 16px 64px rgba(15, 23, 42, .2); } .jio-coupon-dialog { width: min(720px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); margin: auto; padding: 0; overflow: hidden; color: var(--an-text-2); background: var(--an-card); border: 0; border-radius: var(--an-radius); box-shadow: 0 16px 64px rgba(15, 23, 42, .2); }
.aksrt-coupon-dialog::backdrop { background: rgba(15, 23, 42, .45); } .jio-coupon-dialog::backdrop { background: rgba(15, 23, 42, .45); }
.aksrt-coupon-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; } .jio-coupon-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; }
.aksrt-coupon-dialog__head { display: flex; flex: none; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 24px 18px; border-bottom: 1px solid var(--an-border-soft); } .jio-coupon-dialog__head { display: flex; flex: none; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 24px 18px; border-bottom: 1px solid var(--an-border-soft); }
.aksrt-coupon-dialog .aksrt-coupon-dialog__head h2 { margin: 0; padding: 0; color: var(--an-text); font-size: 18px; font-weight: 600; line-height: 1.5; } .jio-coupon-dialog .jio-coupon-dialog__head h2 { margin: 0; padding: 0; color: var(--an-text); font-size: 18px; font-weight: 600; line-height: 1.5; }
.aksrt-coupon-dialog__head p { margin: 5px 0 0; font-size: 13px; line-height: 1.6; } .jio-coupon-dialog__head p { margin: 5px 0 0; font-size: 13px; line-height: 1.6; }
.aksrt-coupon-dialog__close { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; color: var(--an-text-2); background: transparent; border: 0; border-radius: var(--an-radius-sm); cursor: pointer; } .jio-coupon-dialog__close { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; color: var(--an-text-2); background: transparent; border: 0; border-radius: var(--an-radius-sm); cursor: pointer; }
.aksrt-coupon-dialog__close:hover { color: var(--an-text); background: var(--an-bg-soft); } .jio-coupon-dialog__close:hover { color: var(--an-text); background: var(--an-bg-soft); }
.aksrt-coupon-dialog__body { min-height: 0; padding: 20px 24px 24px; overflow-y: auto; overscroll-behavior: contain; } .jio-coupon-dialog__body { min-height: 0; padding: 20px 24px 24px; overflow-y: auto; overscroll-behavior: contain; }
.aksrt-coupon-dialog__foot { display: flex; flex: none; justify-content: flex-end; gap: 8px; padding: 14px 24px; background: var(--an-card); border-top: 1px solid var(--an-border-soft); } .jio-coupon-dialog__foot { display: flex; flex: none; justify-content: flex-end; gap: 8px; padding: 14px 24px; background: var(--an-card); border-top: 1px solid var(--an-border-soft); }
.aksrt-coupon-dialog__foot .button { min-width: 110px; } .jio-coupon-dialog__foot .button { min-width: 110px; }
.aksrt-coupon-dialog .button:disabled { opacity: .65; cursor: not-allowed; } .jio-coupon-dialog .button:disabled { opacity: .65; cursor: not-allowed; }
.aksrt-coupon-dialog :is(a, button, input, select, textarea):focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-coupon-dialog :is(a, button, input, select, textarea):focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; }
.aksrt-coupon-dialog .aksrt-native-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .jio-coupon-dialog .jio-native-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.aksrt-coupon-dialog .aksrt-coupon-batch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .jio-coupon-dialog .jio-coupon-batch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.aksrt-coupon-dialog .aksrt-coupon-section { margin: 0 0 12px; color: var(--an-text); font-size: 14px; font-weight: 600; line-height: 1.5; } .jio-coupon-dialog .jio-coupon-section { margin: 0 0 12px; color: var(--an-text); font-size: 14px; font-weight: 600; line-height: 1.5; }
.aksrt-coupon-dialog .aksrt-coupon-section ~ .aksrt-coupon-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--an-border-soft); } .jio-coupon-dialog .jio-coupon-section ~ .jio-coupon-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--an-border-soft); }
.aksrt-coupon-inline { display: flex; align-items: center; gap: 6px; } .jio-coupon-inline { display: flex; align-items: center; gap: 6px; }
.aksrt-coupon-inline input { flex: 1 1 auto; min-width: 0; } .jio-coupon-inline input { flex: 1 1 auto; min-width: 0; }
.aksrt-coupon-unit { flex: none; min-width: 1.2em; color: var(--an-muted); } .jio-coupon-unit { flex: none; min-width: 1.2em; color: var(--an-muted); }
/* ---------- 复制提示 ---------- */ /* ---------- 复制提示 ---------- */
.aksrt-coupon-toast { position: fixed; right: 24px; bottom: 24px; z-index: 100000; max-width: min(360px, calc(100vw - 48px)); padding: 10px 14px; color: #fff; background: rgba(15, 23, 42, .9); border-radius: var(--an-radius-sm); font-size: 13px; opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s; pointer-events: none; } .jio-coupon-toast { position: fixed; right: 24px; bottom: 24px; z-index: 100000; max-width: min(360px, calc(100vw - 48px)); padding: 10px 14px; color: #fff; background: rgba(15, 23, 42, .9); border-radius: var(--an-radius-sm); font-size: 13px; opacity: 0; transform: translateY(8px); transition: opacity .2s, transform .2s; pointer-events: none; }
.aksrt-coupon-toast.is-visible { opacity: 1; transform: none; } .jio-coupon-toast.is-visible { opacity: 1; transform: none; }
@media (max-width: 600px) { @media (max-width: 600px) {
.aksrt-coupon-dialog { width: calc(100vw - 24px); max-height: calc(100dvh - 24px); } .jio-coupon-dialog { width: calc(100vw - 24px); max-height: calc(100dvh - 24px); }
.aksrt-coupon-dialog__head, .jio-coupon-dialog__head,
.aksrt-coupon-dialog__body, .jio-coupon-dialog__body,
.aksrt-coupon-dialog__foot { padding-left: 16px; padding-right: 16px; } .jio-coupon-dialog__foot { padding-left: 16px; padding-right: 16px; }
.aksrt-coupon-dialog .aksrt-native-form-grid, .jio-coupon-dialog .jio-native-form-grid,
.aksrt-coupon-dialog .aksrt-coupon-batch-grid { grid-template-columns: 1fr; } .jio-coupon-dialog .jio-coupon-batch-grid { grid-template-columns: 1fr; }
.aksrt-coupon-dialog__foot .button { flex: 1; min-width: 0; } .jio-coupon-dialog__foot .button { flex: 1; min-width: 0; }
} }
+39 -39
View File
@@ -1,52 +1,52 @@
/* 创作分成(aksrt_income):统计 + 状态视图 + 筛选 + 分成表。复用 native-ui.css 的 --an-* 令牌,规则限定在 .aksrt-income-page 下。 */ /* 创作分成(jio_income):统计 + 状态视图 + 筛选 + 分成表。复用 native-ui.css 的 --an-* 令牌,规则限定在 .jio-income-page 下。 */
/* ---------- 状态视图 ---------- */ /* ---------- 状态视图 ---------- */
.aksrt-income-page .aksrt-income-views { display: flex; width: fit-content; max-width: 100%; } .jio-income-page .jio-income-views { display: flex; width: fit-content; max-width: 100%; }
/* ---------- 筛选栏 ---------- */ /* ---------- 筛选栏 ---------- */
.aksrt-income-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; } .jio-income-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.aksrt-income-filters label { display: inline-flex; margin: 0; } .jio-income-filters label { display: inline-flex; margin: 0; }
.aksrt-income-filters__search { flex: 1 1 220px; } .jio-income-filters__search { flex: 1 1 220px; }
.aksrt-income-filters__search input { width: 100%; } .jio-income-filters__search input { width: 100%; }
.aksrt-income-filters__range { display: inline-flex; align-items: center; gap: 6px; color: var(--an-muted); } .jio-income-filters__range { display: inline-flex; align-items: center; gap: 6px; color: var(--an-muted); }
.aksrt-income-page .aksrt-income-filters__id { width: 96px; } .jio-income-page .jio-income-filters__id { width: 96px; }
.aksrt-income-filters__submit { display: inline-flex; gap: 8px; } .jio-income-filters__submit { display: inline-flex; gap: 8px; }
/* ---------- 批量操作 ---------- */ /* ---------- 批量操作 ---------- */
.aksrt-income-bulk { margin: 0; } .jio-income-bulk { margin: 0; }
.aksrt-income-bulk__count { color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; } .jio-income-bulk__count { color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.aksrt-income-bulk__count.is-active { color: var(--an-text); font-weight: 500; } .jio-income-bulk__count.is-active { color: var(--an-text); font-weight: 500; }
.aksrt-income-page .aksrt-income-bulk .button:disabled { opacity: .6; cursor: not-allowed; } .jio-income-page .jio-income-bulk .button:disabled { opacity: .6; cursor: not-allowed; }
.aksrt-income-table .check-column input:disabled { cursor: not-allowed; opacity: .45; } .jio-income-table .check-column input:disabled { cursor: not-allowed; opacity: .45; }
/* ---------- 分成表 ---------- */ /* ---------- 分成表 ---------- */
.aksrt-income-table { min-width: 1040px; table-layout: fixed; } .jio-income-table { min-width: 1040px; table-layout: fixed; }
.aksrt-income-table .column-record { width: 13%; } .jio-income-table .column-record { width: 13%; }
.aksrt-income-table .column-author { width: 15%; } .jio-income-table .column-author { width: 15%; }
.aksrt-income-table .column-source { width: 24%; } .jio-income-table .column-source { width: 24%; }
.aksrt-income-table .column-base { width: 14%; } .jio-income-table .column-base { width: 14%; }
.aksrt-income-table .column-amount { width: 12%; } .jio-income-table .column-amount { width: 12%; }
.aksrt-income-table .column-status { width: 12%; } .jio-income-table .column-status { width: 12%; }
.aksrt-income-table .column-actions { width: 13%; } .jio-income-table .column-actions { width: 13%; }
.aksrt-income-table td, .jio-income-table td,
.aksrt-income-table tbody th { vertical-align: top; } .jio-income-table tbody th { vertical-align: top; }
.aksrt-income-id { color: var(--an-text); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-weight: 600; } .jio-income-id { color: var(--an-text); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-weight: 600; }
.aksrt-income-post { display: block; color: var(--an-text); font-weight: 500; text-decoration: none; overflow-wrap: anywhere; } .jio-income-post { display: block; color: var(--an-text); font-weight: 500; text-decoration: none; overflow-wrap: anywhere; }
a.aksrt-income-post:hover, a.jio-income-post:hover,
a.aksrt-income-post:focus { color: var(--an-primary); } a.jio-income-post:focus { color: var(--an-primary); }
.aksrt-income-order { color: inherit; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; text-decoration: none; } .jio-income-order { color: inherit; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; text-decoration: none; }
.aksrt-income-order:hover, .jio-income-order:hover,
.aksrt-income-order:focus { color: var(--an-primary); } .jio-income-order:focus { color: var(--an-primary); }
.aksrt-income-sub { margin-top: 4px; color: var(--an-muted); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; } .jio-income-sub { margin-top: 4px; color: var(--an-muted); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
.aksrt-income-table .column-base, .jio-income-table .column-base,
.aksrt-income-table .column-amount { font-variant-numeric: tabular-nums; } .jio-income-table .column-amount { font-variant-numeric: tabular-nums; }
/* 行内操作:每个按钮是一个独立 POST 表单 */ /* 行内操作:每个按钮是一个独立 POST 表单 */
.aksrt-income-actions { display: flex; flex-wrap: wrap; gap: 6px; } .jio-income-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.aksrt-income-action { display: inline-flex; margin: 0; } .jio-income-action { display: inline-flex; margin: 0; }
.aksrt-income-action .button[disabled] { opacity: .6; cursor: progress; } .jio-income-action .button[disabled] { opacity: .6; cursor: progress; }
@media (max-width: 782px) { @media (max-width: 782px) {
.aksrt-income-filters__search { flex-basis: 100%; } .jio-income-filters__search { flex-basis: 100%; }
.aksrt-income-filters__range { flex-wrap: wrap; } .jio-income-filters__range { flex-wrap: wrap; }
} }
+103 -103
View File
@@ -1,109 +1,109 @@
/* 邀请码原生运营页;外壳、表格与表单令牌沿用 native-ui.css。 */ /* 邀请码原生运营页;外壳、表格与表单令牌沿用 native-ui.css。 */
.aksrt-inv-page [hidden] { display: none !important; } .jio-inv-page [hidden] { display: none !important; }
.aksrt-inv-page .aksrt-native-header__actions .button { display: inline-flex; align-items: center; gap: 5px; } .jio-inv-page .jio-native-header__actions .button { display: inline-flex; align-items: center; gap: 5px; }
.aksrt-inv-page .aksrt-native-header__actions .dashicons { margin: 0; font-size: 17px; line-height: 20px; } .jio-inv-page .jio-native-header__actions .dashicons { margin: 0; font-size: 17px; line-height: 20px; }
.aksrt-inv-toolbar { padding: 14px 20px; border-bottom: 1px solid var(--an-border-soft); } .jio-inv-toolbar { padding: 14px 20px; border-bottom: 1px solid var(--an-border-soft); }
.aksrt-inv-toolbar__views { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; } .jio-inv-toolbar__views { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; }
.aksrt-inv-toolbar .subsubsub { margin: 0; padding: 0; box-shadow: none; } .jio-inv-toolbar .subsubsub { margin: 0; padding: 0; box-shadow: none; }
.aksrt-inv-toolbar .aksrt-native-filters { margin: 0; } .jio-inv-toolbar .jio-native-filters { margin: 0; }
.aksrt-inv-filter-remark { max-width: 240px; color: var(--an-text-2); font-size: 12px; overflow-wrap: anywhere; } .jio-inv-filter-remark { max-width: 240px; color: var(--an-text-2); font-size: 12px; overflow-wrap: anywhere; }
.aksrt-inv-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 20px; border-bottom: 1px solid var(--an-border-soft); } .jio-inv-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 20px; border-bottom: 1px solid var(--an-border-soft); }
.aksrt-inv-selection { margin-right: auto; color: var(--an-text-2); font-size: 12px; font-variant-numeric: tabular-nums; } .jio-inv-selection { margin-right: auto; color: var(--an-text-2); font-size: 12px; font-variant-numeric: tabular-nums; }
.aksrt-inv-page .aksrt-inv-table { min-width: 1000px; table-layout: fixed; } .jio-inv-page .jio-inv-table { min-width: 1000px; table-layout: fixed; }
.aksrt-inv-table .column-code { width: 21%; } .jio-inv-table .column-code { width: 21%; }
.aksrt-inv-table .column-rewards { width: 14%; } .jio-inv-table .column-rewards { width: 14%; }
.aksrt-inv-table .column-created_at, .jio-inv-table .column-created_at,
.aksrt-inv-table .column-updated_at { width: 16%; } .jio-inv-table .column-updated_at { width: 16%; }
.aksrt-inv-table .column-used_count { width: 13%; } .jio-inv-table .column-used_count { width: 13%; }
.aksrt-inv-table .column-remark { width: 20%; } .jio-inv-table .column-remark { width: 20%; }
.aksrt-inv-page .aksrt-inv-table td { vertical-align: middle; overflow-wrap: anywhere; } .jio-inv-page .jio-inv-table td { vertical-align: middle; overflow-wrap: anywhere; }
.aksrt-inv-table .orderby-but { display: inline-flex; align-items: center; gap: 3px; color: var(--an-text-2); text-decoration: none; } .jio-inv-table .orderby-but { display: inline-flex; align-items: center; gap: 3px; color: var(--an-text-2); text-decoration: none; }
.aksrt-inv-table .orderby-but .dashicons { width: 14px; height: 14px; font-size: 14px; opacity: .35; } .jio-inv-table .orderby-but .dashicons { width: 14px; height: 14px; font-size: 14px; opacity: .35; }
.aksrt-inv-table .orderby-but:hover, .jio-inv-table .orderby-but:hover,
.aksrt-inv-table .orderby-but.is-active { color: var(--an-primary); } .jio-inv-table .orderby-but.is-active { color: var(--an-primary); }
.aksrt-inv-table .orderby-but.is-active .dashicons { opacity: 1; } .jio-inv-table .orderby-but.is-active .dashicons { opacity: 1; }
.aksrt-inv-code { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 5px 7px; color: var(--an-text); background: var(--an-bg-soft); border: 1px solid transparent; border-radius: 5px; text-align: left; font-size: 13px; overflow-wrap: anywhere; cursor: pointer; } .jio-inv-code { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 5px 7px; color: var(--an-text); background: var(--an-bg-soft); border: 1px solid transparent; border-radius: 5px; text-align: left; font-size: 13px; overflow-wrap: anywhere; cursor: pointer; }
.aksrt-inv-code .dashicons { flex: none; width: 14px; height: 14px; color: var(--an-muted); font-size: 14px; } .jio-inv-code .dashicons { flex: none; width: 14px; height: 14px; color: var(--an-muted); font-size: 14px; }
.aksrt-inv-code:hover { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); } .jio-inv-code:hover { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); }
.aksrt-inv-date { font-variant-numeric: tabular-nums; font-size: 12px; } .jio-inv-date { font-variant-numeric: tabular-nums; font-size: 12px; }
.aksrt-inv-user { margin-top: 4px; font-size: 12px; } .jio-inv-user { margin-top: 4px; font-size: 12px; }
.aksrt-inv-table tr.is-selected > td, .jio-inv-table tr.is-selected > td,
.aksrt-inv-table tr.is-selected > th { background: var(--an-primary-soft); } .jio-inv-table tr.is-selected > th { background: var(--an-primary-soft); }
.aksrt-inv-page .aksrt-inv-code:focus-visible, .jio-inv-page .jio-inv-code:focus-visible,
.aksrt-inv-page .aksrt-inv-dialog__close:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-inv-page .jio-inv-dialog__close:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; }
html.aksrt-inv-modal-open { overflow: hidden; } html.jio-inv-modal-open { overflow: hidden; }
.aksrt-inv-dialog { width: min(680px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 64px); max-height: calc(100dvh - 64px); margin: auto; padding: 0; overflow: hidden; color: var(--an-text-2); background: var(--an-card); border: 0; border-radius: var(--an-radius); box-shadow: 0 16px 64px rgba(15, 23, 42, .2); } .jio-inv-dialog { width: min(680px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 64px); max-height: calc(100dvh - 64px); margin: auto; padding: 0; overflow: hidden; color: var(--an-text-2); background: var(--an-card); border: 0; border-radius: var(--an-radius); box-shadow: 0 16px 64px rgba(15, 23, 42, .2); }
.aksrt-inv-dialog::backdrop { background: rgba(15, 23, 42, .45); } .jio-inv-dialog::backdrop { background: rgba(15, 23, 42, .45); }
#aksrt-inv-export { width: min(560px, calc(100vw - 32px)); } #jio-inv-export { width: min(560px, calc(100vw - 32px)); }
.aksrt-inv-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; } .jio-inv-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; }
.aksrt-inv-dialog__head { display: flex; flex: none; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 24px 18px; border-bottom: 1px solid var(--an-border-soft); } .jio-inv-dialog__head { display: flex; flex: none; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 24px 18px; border-bottom: 1px solid var(--an-border-soft); }
.aksrt-inv-dialog .aksrt-inv-dialog__head h2 { margin: 0; padding: 0; color: var(--an-text); font-size: 18px; font-weight: 600; line-height: 1.5; } .jio-inv-dialog .jio-inv-dialog__head h2 { margin: 0; padding: 0; color: var(--an-text); font-size: 18px; font-weight: 600; line-height: 1.5; }
.aksrt-inv-dialog__head p { margin: 5px 0 0; font-size: 12px; line-height: 1.7; } .jio-inv-dialog__head p { margin: 5px 0 0; font-size: 12px; line-height: 1.7; }
.aksrt-inv-dialog__close { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; color: var(--an-text-2); background: transparent; border: 0; border-radius: 6px; cursor: pointer; } .jio-inv-dialog__close { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; color: var(--an-text-2); background: transparent; border: 0; border-radius: 6px; cursor: pointer; }
.aksrt-inv-dialog__close:hover { color: var(--an-text); background: var(--an-bg-soft); } .jio-inv-dialog__close:hover { color: var(--an-text); background: var(--an-bg-soft); }
.aksrt-inv-dialog__body { min-height: 0; padding: 20px 24px 24px; overflow-y: auto; overscroll-behavior: contain; } .jio-inv-dialog__body { min-height: 0; padding: 20px 24px 24px; overflow-y: auto; overscroll-behavior: contain; }
.aksrt-inv-dialog__foot { display: flex; flex: none; justify-content: flex-end; gap: 8px; padding: 16px 24px; border-top: 1px solid var(--an-border-soft); background: var(--an-card); } .jio-inv-dialog__foot { display: flex; flex: none; justify-content: flex-end; gap: 8px; padding: 16px 24px; border-top: 1px solid var(--an-border-soft); background: var(--an-card); }
.aksrt-inv-dialog .aksrt-native-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .jio-inv-dialog .jio-native-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.aksrt-inv-dialog .aksrt-native-field { min-width: 0; } .jio-inv-dialog .jio-native-field { min-width: 0; }
.aksrt-inv-dialog .aksrt-native-field > input, .jio-inv-dialog .jio-native-field > input,
.aksrt-inv-dialog .aksrt-native-field > textarea { width: 100%; max-width: 100%; } .jio-inv-dialog .jio-native-field > textarea { width: 100%; max-width: 100%; }
.aksrt-inv-dialog textarea { resize: vertical; } .jio-inv-dialog textarea { resize: vertical; }
.aksrt-inv-pane { min-width: 0; margin: 0; padding: 0; border: 0; } .jio-inv-pane { min-width: 0; margin: 0; padding: 0; border: 0; }
.aksrt-inv-modes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 0 0 22px; padding: 4px; background: var(--an-bg-soft); border: 0; border-radius: var(--an-radius-sm); } .jio-inv-modes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 0 0 22px; padding: 4px; background: var(--an-bg-soft); border: 0; border-radius: var(--an-radius-sm); }
.aksrt-inv-modes label { position: relative; cursor: pointer; } .jio-inv-modes label { position: relative; cursor: pointer; }
.aksrt-inv-modes input { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; clip-path: inset(50%); } .jio-inv-modes input { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; clip-path: inset(50%); }
.aksrt-inv-modes span { display: block; padding: 9px 12px; border: 1px solid transparent; border-radius: 6px; text-align: center; } .jio-inv-modes span { display: block; padding: 9px 12px; border: 1px solid transparent; border-radius: 6px; text-align: center; }
.aksrt-inv-modes input:checked + span { color: var(--an-primary); background: var(--an-card); border-color: var(--an-primary); font-weight: 600; } .jio-inv-modes input:checked + span { color: var(--an-primary); background: var(--an-card); border-color: var(--an-primary); font-weight: 600; }
.aksrt-inv-modes input:focus-visible + span { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-inv-modes input:focus-visible + span { outline: 2px solid var(--an-primary); outline-offset: 2px; }
.aksrt-inv-rewards { min-width: 0; margin: 22px 0; padding: 18px; border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); } .jio-inv-rewards { min-width: 0; margin: 22px 0; padding: 18px; border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); }
.aksrt-inv-rewards > legend, .jio-inv-rewards > legend,
.aksrt-inv-options > legend { padding: 0 5px; color: var(--an-text); font-weight: 600; } .jio-inv-options > legend { padding: 0 5px; color: var(--an-text); font-weight: 600; }
.aksrt-inv-hint { margin: -2px 0 14px; font-size: 12px; line-height: 1.7; } .jio-inv-hint { margin: -2px 0 14px; font-size: 12px; line-height: 1.7; }
.aksrt-inv-dialog .aksrt-inv-reward-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .jio-inv-dialog .jio-inv-reward-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.aksrt-inv-vip { margin: 16px 0 0; padding: 0; border: 0; } .jio-inv-vip { margin: 16px 0 0; padding: 0; border: 0; }
.aksrt-inv-vip legend { margin-bottom: 8px; padding: 0; font-weight: 600; } .jio-inv-vip legend { margin-bottom: 8px; padding: 0; font-weight: 600; }
.aksrt-inv-radios { display: flex; flex-wrap: wrap; gap: 12px 18px; } .jio-inv-radios { display: flex; flex-wrap: wrap; gap: 12px 18px; }
.aksrt-inv-radios label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; } .jio-inv-radios label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.aksrt-inv-radios input { margin: 0; } .jio-inv-radios input { margin: 0; }
.aksrt-inv-vip-time { max-width: 200px; margin-top: 14px; } .jio-inv-vip-time { max-width: 200px; margin-top: 14px; }
.aksrt-inv-advanced { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; } .jio-inv-advanced { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.aksrt-inv-advanced input { margin: 0; } .jio-inv-advanced input { margin: 0; }
.aksrt-inv-length { margin-top: 12px; } .jio-inv-length { margin-top: 12px; }
.aksrt-inv-dialog .aksrt-inv-length input { max-width: 160px; } .jio-inv-dialog .jio-inv-length input { max-width: 160px; }
.aksrt-inv-separator { margin-top: 16px; } .jio-inv-separator { margin-top: 16px; }
.aksrt-inv-dialog .aksrt-inv-separator input { max-width: 100px; } .jio-inv-dialog .jio-inv-separator input { max-width: 100px; }
.aksrt-inv-help { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--an-border-soft); line-height: 1.8; } .jio-inv-help { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--an-border-soft); line-height: 1.8; }
.aksrt-inv-help summary { color: var(--an-primary); cursor: pointer; } .jio-inv-help summary { color: var(--an-primary); cursor: pointer; }
.aksrt-inv-help p { font-size: 12px; } .jio-inv-help p { font-size: 12px; }
.aksrt-inv-help pre { padding: 12px; overflow: auto; font-size: 12px; background: var(--an-bg-soft); border-radius: 6px; } .jio-inv-help pre { padding: 12px; overflow: auto; font-size: 12px; background: var(--an-bg-soft); border-radius: 6px; }
.aksrt-inv-options { min-width: 0; margin: 0 0 22px; padding: 0; border: 0; } .jio-inv-options { min-width: 0; margin: 0 0 22px; padding: 0; border: 0; }
.aksrt-inv-options > legend { margin-bottom: 12px; padding: 0; } .jio-inv-options > legend { margin-bottom: 12px; padding: 0; }
.aksrt-inv-formats { display: grid; gap: 10px; } .jio-inv-formats { display: grid; gap: 10px; }
.aksrt-inv-formats label { display: flex; align-items: flex-start; gap: 10px; padding: 13px 14px; border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); cursor: pointer; } .jio-inv-formats label { display: flex; align-items: flex-start; gap: 10px; padding: 13px 14px; border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); cursor: pointer; }
.aksrt-inv-formats label:has(input:checked) { background: var(--an-primary-soft); border-color: var(--an-primary); } .jio-inv-formats label:has(input:checked) { background: var(--an-primary-soft); border-color: var(--an-primary); }
.aksrt-inv-formats input { flex: none; margin: 3px 0 0; } .jio-inv-formats input { flex: none; margin: 3px 0 0; }
.aksrt-inv-formats strong { display: block; color: var(--an-text); font-weight: 600; } .jio-inv-formats strong { display: block; color: var(--an-text); font-weight: 600; }
.aksrt-inv-formats small { display: block; margin-top: 5px; font-size: 12px; line-height: 1.7; } .jio-inv-formats small { display: block; margin-top: 5px; font-size: 12px; line-height: 1.7; }
.aksrt-inv-page .aksrt-inv-export-note { margin: 20px 0 0; padding: 12px 14px; font-size: 12px; line-height: 1.8; } .jio-inv-page .jio-inv-export-note { margin: 20px 0 0; padding: 12px 14px; font-size: 12px; line-height: 1.8; }
.aksrt-inv-toast { position: fixed; z-index: 100100; top: 48px; left: 50%; max-width: calc(100vw - 48px); padding: 10px 18px; transform: translateX(-50%); color: #fff; background: #1f2329; border-radius: var(--an-radius-sm); box-shadow: var(--an-shadow); opacity: 0; pointer-events: none; } .jio-inv-toast { position: fixed; z-index: 100100; top: 48px; left: 50%; max-width: calc(100vw - 48px); padding: 10px 18px; transform: translateX(-50%); color: #fff; background: #1f2329; border-radius: var(--an-radius-sm); box-shadow: var(--an-shadow); opacity: 0; pointer-events: none; }
.aksrt-inv-toast.is-visible { opacity: 1; } .jio-inv-toast.is-visible { opacity: 1; }
@media (max-width: 600px) { @media (max-width: 600px) {
.aksrt-inv-page .aksrt-native-header__actions { width: 100%; } .jio-inv-page .jio-native-header__actions { width: 100%; }
.aksrt-inv-page .aksrt-native-header__actions .button { flex: 1; justify-content: center; } .jio-inv-page .jio-native-header__actions .button { flex: 1; justify-content: center; }
.aksrt-inv-toolbar, .jio-inv-toolbar,
.aksrt-inv-bulk { padding-left: 14px; padding-right: 14px; } .jio-inv-bulk { padding-left: 14px; padding-right: 14px; }
.aksrt-inv-toolbar .aksrt-native-filters { width: 100%; } .jio-inv-toolbar .jio-native-filters { width: 100%; }
.aksrt-inv-toolbar input[type="search"] { flex: 1 1 calc(100% - 76px); width: 0; min-width: 0; } .jio-inv-toolbar input[type="search"] { flex: 1 1 calc(100% - 76px); width: 0; min-width: 0; }
.aksrt-inv-dialog { max-height: calc(100dvh - 24px); } .jio-inv-dialog { max-height: calc(100dvh - 24px); }
.aksrt-inv-dialog__head, .jio-inv-dialog__head,
.aksrt-inv-dialog__body, .jio-inv-dialog__body,
.aksrt-inv-dialog__foot { padding-left: 16px; padding-right: 16px; } .jio-inv-dialog__foot { padding-left: 16px; padding-right: 16px; }
.aksrt-inv-dialog .aksrt-native-form-grid { grid-template-columns: 1fr; } .jio-inv-dialog .jio-native-form-grid { grid-template-columns: 1fr; }
.aksrt-inv-rewards { padding: 12px; } .jio-inv-rewards { padding: 12px; }
.aksrt-inv-dialog .aksrt-inv-reward-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; } .jio-inv-dialog .jio-inv-reward-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.aksrt-inv-radios { gap: 12px; } .jio-inv-radios { gap: 12px; }
.aksrt-inv-dialog__foot .button { flex: 1; } .jio-inv-dialog__foot .button { flex: 1; }
} }
+90 -90
View File
@@ -1,42 +1,42 @@
/* 消息管理原生页。共享卡片 / 表单 / 筛选沿用 native-ui.css 的 --an-* 令牌。 */ /* 消息管理原生页。共享卡片 / 表单 / 筛选沿用 native-ui.css 的 --an-* 令牌。 */
.aksrt-messages-admin [hidden] { display: none; } .jio-messages-admin [hidden] { display: none; }
.aksrt-messages-admin__muted { color: var(--an-muted); } .jio-messages-admin__muted { color: var(--an-muted); }
.aksrt-messages-admin__sub { margin-top: 3px; color: var(--an-muted); font-size: 12px; } .jio-messages-admin__sub { margin-top: 3px; color: var(--an-muted); font-size: 12px; }
.aksrt-messages-admin__sub code { padding: 0 4px; font-size: 12px; background: var(--an-bg-soft); } .jio-messages-admin__sub code { padding: 0 4px; font-size: 12px; background: var(--an-bg-soft); }
.aksrt-messages-admin .aksrt-native-header__actions .button { display: inline-flex; align-items: center; gap: 4px; } .jio-messages-admin .jio-native-header__actions .button { display: inline-flex; align-items: center; gap: 4px; }
.aksrt-messages-admin .aksrt-native-header__actions .button .dashicons { margin: 0; line-height: 1; vertical-align: middle; } .jio-messages-admin .jio-native-header__actions .button .dashicons { margin: 0; line-height: 1; vertical-align: middle; }
.aksrt-messages-admin .aksrt-native-stat:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-messages-admin .jio-native-stat:focus-visible { outline: 2px solid var(--an-primary); outline-offset: 2px; }
/* ---- 列表内的筛选与批量工具栏 ---- */ /* ---- 列表内的筛选与批量工具栏 ---- */
.aksrt-messages-admin__toolbar { padding: 14px 20px; border-bottom: 1px solid var(--an-border-soft); } .jio-messages-admin__toolbar { padding: 14px 20px; border-bottom: 1px solid var(--an-border-soft); }
.aksrt-messages-admin__toolbar .subsubsub { margin: 0 0 12px; } .jio-messages-admin__toolbar .subsubsub { margin: 0 0 12px; }
.aksrt-messages-admin__toolbar .aksrt-native-filters { margin: 0; } .jio-messages-admin__toolbar .jio-native-filters { margin: 0; }
.aksrt-messages-admin__bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 20px; } .jio-messages-admin__bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 20px; }
.aksrt-messages-admin__selection { margin-right: auto; color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; } .jio-messages-admin__selection { margin-right: auto; color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.aksrt-messages-admin .button:disabled, .jio-messages-admin .button:disabled,
.aksrt-messages-admin .button:disabled:hover { color: var(--an-muted) !important; background: var(--an-bg-soft) !important; border-color: var(--an-border-soft) !important; cursor: not-allowed; } .jio-messages-admin .button:disabled:hover { color: var(--an-muted) !important; background: var(--an-bg-soft) !important; border-color: var(--an-border-soft) !important; cursor: not-allowed; }
.aksrt-messages-admin__danger.button { color: var(--an-danger); border-color: var(--an-danger); } .jio-messages-admin__danger.button { color: var(--an-danger); border-color: var(--an-danger); }
.aksrt-messages-admin__danger.button:hover, .jio-messages-admin__danger.button:hover,
.aksrt-messages-admin__danger.button:focus { color: #fff; background: var(--an-danger); border-color: var(--an-danger); } .jio-messages-admin__danger.button:focus { color: #fff; background: var(--an-danger); border-color: var(--an-danger); }
.aksrt-messages-admin__table .column-title { width: 32%; } .jio-messages-admin__table .column-title { width: 32%; }
.aksrt-messages-admin__table .column-type { width: 10%; } .jio-messages-admin__table .column-type { width: 10%; }
.aksrt-messages-admin__table .column-user { width: 16%; } .jio-messages-admin__table .column-user { width: 16%; }
.aksrt-messages-admin__table .column-read { width: 8%; } .jio-messages-admin__table .column-read { width: 8%; }
.aksrt-messages-admin__table .column-time { width: 16%; } .jio-messages-admin__table .column-time { width: 16%; }
.aksrt-messages-admin .aksrt-messages-admin__table .column-actions { width: 18%; padding-left: 20px; padding-right: 20px; text-align: center; } .jio-messages-admin .jio-messages-admin__table .column-actions { width: 18%; padding-left: 20px; padding-right: 20px; text-align: center; }
.aksrt-messages-admin__table td { vertical-align: middle; } .jio-messages-admin__table td { vertical-align: middle; }
.aksrt-messages-admin__table .row-title { font-weight: 600; word-break: break-word; line-height: 1.5; } .jio-messages-admin__table .row-title { font-weight: 600; word-break: break-word; line-height: 1.5; }
.aksrt-messages-admin__table tr.is-unread .row-title { font-weight: 700; } .jio-messages-admin__table tr.is-unread .row-title { font-weight: 700; }
.aksrt-messages-admin__table tr.is-unread > th:first-child { box-shadow: inset 3px 0 0 var(--an-primary); } .jio-messages-admin__table tr.is-unread > th:first-child { box-shadow: inset 3px 0 0 var(--an-primary); }
.aksrt-messages-admin__table tr.is-selected > td, .jio-messages-admin__table tr.is-selected > td,
.aksrt-messages-admin__table tr.is-selected > th { background: var(--an-primary-soft); } .jio-messages-admin__table tr.is-selected > th { background: var(--an-primary-soft); }
.aksrt-messages-admin__desc { margin-top: 3px; color: var(--an-text-2); word-break: break-word; } .jio-messages-admin__desc { margin-top: 3px; color: var(--an-text-2); word-break: break-word; }
.aksrt-msg-row-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 12px; } .jio-msg-row-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 12px; }
.aksrt-msg-row-actions button { padding: 0; font-size: 12px; text-decoration: none; white-space: nowrap; } .jio-msg-row-actions button { padding: 0; font-size: 12px; text-decoration: none; white-space: nowrap; }
/* 类型徽章(可点击筛选) */ /* 类型徽章(可点击筛选) */
.aksrt-msg-badge { .jio-msg-badge {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
padding: 2px 8px; padding: 2px 8px;
@@ -45,27 +45,27 @@
line-height: 18px; line-height: 18px;
white-space: nowrap; white-space: nowrap;
text-decoration: none; text-decoration: none;
color: var(--aksrt-msg-tone, var(--an-muted)); color: var(--jio-msg-tone, var(--an-muted));
background: color-mix(in srgb, var(--aksrt-msg-tone, var(--an-muted)) 12%, #fff); background: color-mix(in srgb, var(--jio-msg-tone, var(--an-muted)) 12%, #fff);
border: 1px solid color-mix(in srgb, var(--aksrt-msg-tone, var(--an-muted)) 30%, #fff); border: 1px solid color-mix(in srgb, var(--jio-msg-tone, var(--an-muted)) 30%, #fff);
} }
.aksrt-msg-badge:hover, .jio-msg-badge:hover,
.aksrt-msg-badge:focus { color: var(--aksrt-msg-tone, var(--an-muted)); border-color: var(--aksrt-msg-tone, var(--an-muted)); } .jio-msg-badge:focus { color: var(--jio-msg-tone, var(--an-muted)); border-color: var(--jio-msg-tone, var(--an-muted)); }
.aksrt-msg-badge.is-info { --aksrt-msg-tone: var(--an-info); } .jio-msg-badge.is-info { --jio-msg-tone: var(--an-info); }
.aksrt-msg-badge.is-success { --aksrt-msg-tone: #00a32a; } .jio-msg-badge.is-success { --jio-msg-tone: #00a32a; }
.aksrt-msg-badge.is-danger { --aksrt-msg-tone: var(--an-danger); } .jio-msg-badge.is-danger { --jio-msg-tone: var(--an-danger); }
.aksrt-msg-badge.is-social { --aksrt-msg-tone: #8c5bd0; } .jio-msg-badge.is-social { --jio-msg-tone: #8c5bd0; }
.aksrt-msg-state { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; white-space: nowrap; } .jio-msg-state { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; white-space: nowrap; }
.aksrt-msg-state::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; } .jio-msg-state::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.aksrt-msg-state.is-unread { color: var(--an-primary); font-weight: 600; } .jio-msg-state.is-unread { color: var(--an-primary); font-weight: 600; }
.aksrt-msg-state.is-read { color: var(--an-muted); } .jio-msg-state.is-read { color: var(--an-muted); }
.aksrt-msg-user { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; text-decoration: none; } .jio-msg-user { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; text-decoration: none; }
.aksrt-msg-user img { flex: none; border-radius: 50%; } .jio-msg-user img { flex: none; border-radius: 50%; }
.aksrt-msg-user span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .jio-msg-user span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ---- 发送 / 详情 / 二次确认共用弹窗 ---- */ /* ---- 发送 / 详情 / 二次确认共用弹窗 ---- */
html.aksrt-msg-modal-open { overflow: hidden; } html.jio-msg-modal-open { overflow: hidden; }
.aksrt-msg-dialog { .jio-msg-dialog {
width: min(640px, calc(100vw - 32px)); width: min(640px, calc(100vw - 32px));
max-height: calc(100vh - 64px); max-height: calc(100vh - 64px);
padding: 0; padding: 0;
@@ -76,10 +76,10 @@ html.aksrt-msg-modal-open { overflow: hidden; }
border-radius: var(--an-radius); border-radius: var(--an-radius);
box-shadow: 0 12px 48px rgba(15, 23, 42, .18); box-shadow: 0 12px 48px rgba(15, 23, 42, .18);
} }
.aksrt-msg-dialog::backdrop { background: rgba(15, 23, 42, .45); } .jio-msg-dialog::backdrop { background: rgba(15, 23, 42, .45); }
.aksrt-msg-dialog--confirm { width: min(440px, calc(100vw - 32px)); } .jio-msg-dialog--confirm { width: min(440px, calc(100vw - 32px)); }
.aksrt-msg-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; } .jio-msg-dialog__frame { display: flex; flex-direction: column; max-height: inherit; margin: 0; }
.aksrt-msg-dialog__head { .jio-msg-dialog__head {
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;
@@ -88,47 +88,47 @@ html.aksrt-msg-modal-open { overflow: hidden; }
padding: 16px 20px; padding: 16px 20px;
border-bottom: 1px solid var(--an-border-soft); border-bottom: 1px solid var(--an-border-soft);
} }
.aksrt-msg-dialog .aksrt-msg-dialog__title { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--an-text); font-size: 16px; font-weight: 600; line-height: 1.4; } .jio-msg-dialog .jio-msg-dialog__title { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--an-text); font-size: 16px; font-weight: 600; line-height: 1.4; }
.aksrt-msg-dialog__title .dashicons { flex-shrink: 0; color: var(--an-primary); } .jio-msg-dialog__title .dashicons { flex-shrink: 0; color: var(--an-primary); }
.aksrt-msg-dialog__close { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; color: var(--an-muted); background: transparent; border: 0; border-radius: var(--an-radius-sm); cursor: pointer; } .jio-msg-dialog__close { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; color: var(--an-muted); background: transparent; border: 0; border-radius: var(--an-radius-sm); cursor: pointer; }
.aksrt-msg-dialog__close:hover, .jio-msg-dialog__close:hover,
.aksrt-msg-dialog__close:focus-visible { color: var(--an-text); background: var(--an-bg-soft); } .jio-msg-dialog__close:focus-visible { color: var(--an-text); background: var(--an-bg-soft); }
.aksrt-msg-dialog__body { min-height: 0; padding: 18px 20px; overflow-y: auto; overscroll-behavior: contain; } .jio-msg-dialog__body { min-height: 0; padding: 18px 20px; overflow-y: auto; overscroll-behavior: contain; }
.aksrt-msg-dialog__note { margin: 14px 0 0; font-size: 12px; } .jio-msg-dialog__note { margin: 14px 0 0; font-size: 12px; }
.aksrt-msg-dialog__foot { display: flex; flex-shrink: 0; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--an-border-soft); } .jio-msg-dialog__foot { display: flex; flex-shrink: 0; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--an-border-soft); }
.aksrt-msg-dialog .aksrt-native-form-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); } .jio-msg-dialog .jio-native-form-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.aksrt-msg-dialog--confirm .aksrt-msg-dialog__body p { margin: 0; line-height: 1.8; } .jio-msg-dialog--confirm .jio-msg-dialog__body p { margin: 0; line-height: 1.8; }
/* 分段单选:保留键盘语义,隐藏 WP 默认勾选标记。 */ /* 分段单选:保留键盘语义,隐藏 WP 默认勾选标记。 */
.aksrt-msg-modes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0 0 16px; padding: 0; border: 0; } .jio-msg-modes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0 0 16px; padding: 0; border: 0; }
.aksrt-msg-modes legend { margin-bottom: 8px; padding: 0; } .jio-msg-modes legend { margin-bottom: 8px; padding: 0; }
.aksrt-msg-mode { position: relative; cursor: pointer; } .jio-msg-mode { position: relative; cursor: pointer; }
.aksrt-msg-mode input[type="radio"] { position: absolute; width: 1px; height: 1px; min-width: 0; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); border: 0; opacity: 0; appearance: none; } .jio-msg-mode input[type="radio"] { position: absolute; width: 1px; height: 1px; min-width: 0; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); border: 0; opacity: 0; appearance: none; }
.aksrt-msg-mode > span { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 10px; color: var(--an-text-2); border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); } .jio-msg-mode > span { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 10px; color: var(--an-text-2); border: 1px solid var(--an-border); border-radius: var(--an-radius-sm); }
.aksrt-msg-mode input:checked + span { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); font-weight: 600; } .jio-msg-mode input:checked + span { color: var(--an-primary); background: var(--an-primary-soft); border-color: var(--an-primary); font-weight: 600; }
.aksrt-msg-mode:hover > span { border-color: var(--an-primary); } .jio-msg-mode:hover > span { border-color: var(--an-primary); }
.aksrt-msg-mode input:focus-visible + span { outline: 2px solid var(--an-primary); outline-offset: 2px; } .jio-msg-mode input:focus-visible + span { outline: 2px solid var(--an-primary); outline-offset: 2px; }
.aksrt-msg-counter { align-self: flex-end; color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; } .jio-msg-counter { align-self: flex-end; color: var(--an-muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.aksrt-msg-counter.is-over { color: var(--an-danger); font-weight: 600; } .jio-msg-counter.is-over { color: var(--an-danger); font-weight: 600; }
/* 详情原样展示纯文本,保留换行,不插入消息中的 HTML。 */ /* 详情原样展示纯文本,保留换行,不插入消息中的 HTML。 */
.aksrt-msg-detail__title { margin: 0 0 16px; color: var(--an-text); font-size: 17px; line-height: 1.5; overflow-wrap: anywhere; } .jio-msg-detail__title { margin: 0 0 16px; color: var(--an-text); font-size: 17px; line-height: 1.5; overflow-wrap: anywhere; }
.aksrt-msg-detail__meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 14px; background: var(--an-bg-soft); border-radius: var(--an-radius-sm); } .jio-msg-detail__meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 14px; background: var(--an-bg-soft); border-radius: var(--an-radius-sm); }
.aksrt-msg-detail__meta dt { color: var(--an-muted); font-size: 12px; } .jio-msg-detail__meta dt { color: var(--an-muted); font-size: 12px; }
.aksrt-msg-detail__meta dd { margin: 4px 0 0; overflow-wrap: anywhere; } .jio-msg-detail__meta dd { margin: 4px 0 0; overflow-wrap: anywhere; }
.aksrt-msg-detail__content { line-height: 1.8; white-space: pre-wrap; overflow-wrap: anywhere; } .jio-msg-detail__content { line-height: 1.8; white-space: pre-wrap; overflow-wrap: anywhere; }
.aksrt-msg-detail__link { display: block; margin-top: 16px; overflow-wrap: anywhere; } .jio-msg-detail__link { display: block; margin-top: 16px; overflow-wrap: anywhere; }
@media (max-width: 782px) { @media (max-width: 782px) {
.aksrt-messages-admin__toolbar, .jio-messages-admin__toolbar,
.aksrt-messages-admin__bulk { padding: 12px 14px; } .jio-messages-admin__bulk { padding: 12px 14px; }
.aksrt-messages-admin__table .column-type, .jio-messages-admin__table .column-type,
.aksrt-messages-admin__table .column-read { display: none; } .jio-messages-admin__table .column-read { display: none; }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.aksrt-msg-dialog { max-height: calc(100dvh - 32px); } .jio-msg-dialog { max-height: calc(100dvh - 32px); }
.aksrt-msg-dialog__head, .jio-msg-dialog__head,
.aksrt-msg-dialog__body, .jio-msg-dialog__body,
.aksrt-msg-dialog__foot { padding-left: 14px; padding-right: 14px; } .jio-msg-dialog__foot { padding-left: 14px; padding-right: 14px; }
.aksrt-msg-detail__meta { grid-template-columns: 1fr; } .jio-msg-detail__meta { grid-template-columns: 1fr; }
} }
+205 -205
View File
@@ -1,12 +1,12 @@
/* /*
* AKSRT 原生后台运营页共享 UI(支付中心 / 用户子菜单)。 * Jio 原生后台运营页共享 UI(支付中心 / 用户子菜单)。
* *
* 只在 NativeUi::SLUGS 列出的页面入队,全部规则限定在 .aksrt-native 下, * 只在 NativeUi::SLUGS 列出的页面入队,全部规则限定在 .jio-native 下,
* 不影响 WP 其它后台页。色板与圆角对齐 SPA 的 Naive UI 主题(App.vue)。 * 不影响 WP 其它后台页。色板与圆角对齐 SPA 的 Naive UI 主题(App.vue)。
* 标记由 src/Admin/Native/NativeUi.php 输出。 * 标记由 src/Admin/Native/NativeUi.php 输出。
*/ */
.aksrt-native { .jio-native {
--an-primary: #18a058; --an-primary: #18a058;
--an-primary-hover: #36ad6a; --an-primary-hover: #36ad6a;
--an-primary-soft: #e8f6ee; --an-primary-soft: #e8f6ee;
@@ -31,7 +31,7 @@
} }
/* ---------- 页头 ---------- */ /* ---------- 页头 ---------- */
.aksrt-native-header { .jio-native-header {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
@@ -39,8 +39,8 @@
gap: 12px 16px; gap: 12px 16px;
margin: 18px 0 16px; margin: 18px 0 16px;
} }
.aksrt-native-header__main { min-width: 0; } .jio-native-header__main { min-width: 0; }
.aksrt-native .aksrt-native-header__title { .jio-native .jio-native-header__title {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
@@ -51,7 +51,7 @@
font-weight: 600; font-weight: 600;
line-height: 1.3; line-height: 1.3;
} }
.aksrt-native-header__icon { .jio-native-header__icon {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -61,17 +61,17 @@
background: var(--an-primary-soft); background: var(--an-primary-soft);
border-radius: 10px; border-radius: 10px;
} }
.aksrt-native-header__icon.dashicons:before { font-size: 20px; line-height: 36px; } .jio-native-header__icon.dashicons:before { font-size: 20px; line-height: 36px; }
.aksrt-native-header__icon.dashicons { width: 36px; height: 36px; } .jio-native-header__icon.dashicons { width: 36px; height: 36px; }
.aksrt-native-header__desc { margin: 6px 0 0; color: var(--an-muted); } .jio-native-header__desc { margin: 6px 0 0; color: var(--an-muted); }
.aksrt-native-header__actions { display: flex; flex-wrap: wrap; gap: 8px; } .jio-native-header__actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* WP 把 .notice 挪到首个 h1/h2 后;保持与卡片同宽同圆角。 */ /* WP 把 .notice 挪到首个 h1/h2 后;保持与卡片同宽同圆角。 */
.aksrt-native .notice { margin: 0 0 16px; border-radius: var(--an-radius-sm); box-shadow: var(--an-shadow); } .jio-native .notice { margin: 0 0 16px; border-radius: var(--an-radius-sm); box-shadow: var(--an-shadow); }
/* ---------- 标签导航(.subsubsub / .nav-tab-wrapper / .aksrt-native-tabs) ---------- */ /* ---------- 标签导航(.subsubsub / .nav-tab-wrapper / .jio-native-tabs) ---------- */
.aksrt-native .subsubsub, .jio-native .subsubsub,
.aksrt-native-tabs { .jio-native-tabs {
display: inline-flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;
float: none; float: none;
@@ -84,10 +84,10 @@
box-shadow: var(--an-shadow); box-shadow: var(--an-shadow);
font-size: 13px; font-size: 13px;
} }
.aksrt-native .subsubsub li { margin: 0; font-size: 0; } .jio-native .subsubsub li { margin: 0; font-size: 0; }
.aksrt-native .subsubsub li > * { font-size: 13px; } .jio-native .subsubsub li > * { font-size: 13px; }
.aksrt-native .subsubsub a, .jio-native .subsubsub a,
.aksrt-native-tabs a { .jio-native-tabs a {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
@@ -98,17 +98,17 @@
line-height: 1.4; line-height: 1.4;
transition: background .15s, color .15s; transition: background .15s, color .15s;
} }
.aksrt-native .subsubsub a:hover, .jio-native .subsubsub a:hover,
.aksrt-native-tabs a:hover { color: var(--an-primary); background: var(--an-bg-soft); } .jio-native-tabs a:hover { color: var(--an-primary); background: var(--an-bg-soft); }
.aksrt-native .subsubsub a.current, .jio-native .subsubsub a.current,
.aksrt-native-tabs a.is-active, .jio-native-tabs a.is-active,
.aksrt-native-tabs a[aria-current="page"] { .jio-native-tabs a[aria-current="page"] {
color: var(--an-primary); color: var(--an-primary);
background: var(--an-primary-soft); background: var(--an-primary-soft);
font-weight: 600; font-weight: 600;
} }
.aksrt-native .subsubsub a .count, .jio-native .subsubsub a .count,
.aksrt-native-tabs .count { .jio-native-tabs .count {
padding: 0 6px; padding: 0 6px;
color: inherit; color: inherit;
font-size: 12px; font-size: 12px;
@@ -116,14 +116,14 @@
background: rgba(0, 0, 0, .05); background: rgba(0, 0, 0, .05);
border-radius: 999px; border-radius: 999px;
} }
.aksrt-native .nav-tab-wrapper { .jio-native .nav-tab-wrapper {
display: flex; display: flex;
gap: 4px; gap: 4px;
margin: 0 0 16px; margin: 0 0 16px;
padding: 0; padding: 0;
border-bottom: 1px solid var(--an-border); border-bottom: 1px solid var(--an-border);
} }
.aksrt-native .nav-tab { .jio-native .nav-tab {
margin: 0 0 -1px; margin: 0 0 -1px;
padding: 8px 14px; padding: 8px 14px;
color: var(--an-text-2); color: var(--an-text-2);
@@ -132,21 +132,21 @@
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
font-weight: 500; font-weight: 500;
} }
.aksrt-native .nav-tab:hover { color: var(--an-primary); background: transparent; } .jio-native .nav-tab:hover { color: var(--an-primary); background: transparent; }
.aksrt-native .nav-tab-active, .jio-native .nav-tab-active,
.aksrt-native .nav-tab-active:hover { color: var(--an-primary); border-bottom-color: var(--an-primary); background: transparent; } .jio-native .nav-tab-active:hover { color: var(--an-primary); border-bottom-color: var(--an-primary); background: transparent; }
.aksrt-native-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; } .jio-native-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; }
.aksrt-native-toolbar > .subsubsub, .jio-native-toolbar > .subsubsub,
.aksrt-native-toolbar > .aksrt-native-tabs { margin-bottom: 0; } .jio-native-toolbar > .jio-native-tabs { margin-bottom: 0; }
/* ---------- 统计卡 ---------- */ /* ---------- 统计卡 ---------- */
.aksrt-native-stats { .jio-native-stats {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 12px; gap: 12px;
margin: 0 0 16px; margin: 0 0 16px;
} }
.aksrt-native-stat { .jio-native-stat {
--an-tone: var(--an-primary); --an-tone: var(--an-primary);
position: relative; position: relative;
display: flex; display: flex;
@@ -162,7 +162,7 @@
overflow: hidden; overflow: hidden;
transition: box-shadow .2s, transform .2s; transition: box-shadow .2s, transform .2s;
} }
.aksrt-native-stat::after { .jio-native-stat::after {
content: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
@@ -172,12 +172,12 @@
background: radial-gradient(circle at top right, color-mix(in srgb, var(--an-tone) 16%, transparent), transparent 70%); background: radial-gradient(circle at top right, color-mix(in srgb, var(--an-tone) 16%, transparent), transparent 70%);
pointer-events: none; pointer-events: none;
} }
a.aksrt-native-stat:hover, a.jio-native-stat:hover,
a.aksrt-native-stat:focus { color: var(--an-text-2); box-shadow: var(--an-shadow-hover); transform: translateY(-1px); } a.jio-native-stat:focus { color: var(--an-text-2); box-shadow: var(--an-shadow-hover); transform: translateY(-1px); }
a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone) 40%, transparent); outline-offset: 1px; } a.jio-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone) 40%, transparent); outline-offset: 1px; }
.aksrt-native-stat__label { display: flex; align-items: center; gap: 6px; color: var(--an-muted); font-size: 13px; } .jio-native-stat__label { display: flex; align-items: center; gap: 6px; color: var(--an-muted); font-size: 13px; }
.aksrt-native-stat__label .dashicons { width: 16px; height: 16px; color: var(--an-tone); font-size: 16px; } .jio-native-stat__label .dashicons { width: 16px; height: 16px; color: var(--an-tone); font-size: 16px; }
.aksrt-native-stat__value { .jio-native-stat__value {
color: var(--an-text); color: var(--an-text);
font-size: 26px; font-size: 26px;
font-weight: 600; font-weight: 600;
@@ -185,24 +185,24 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
word-break: break-all; word-break: break-all;
} }
.aksrt-native-stat__unit { margin-right: 2px; color: var(--an-muted); font-size: 14px; font-weight: 400; } .jio-native-stat__unit { margin-right: 2px; color: var(--an-muted); font-size: 14px; font-weight: 400; }
.aksrt-native-stat__hint { color: var(--an-muted); font-size: 12px; } .jio-native-stat__hint { color: var(--an-muted); font-size: 12px; }
.aksrt-native-stat--success { --an-tone: var(--an-primary); } .jio-native-stat--success { --an-tone: var(--an-primary); }
.aksrt-native-stat--info { --an-tone: var(--an-info); } .jio-native-stat--info { --an-tone: var(--an-info); }
.aksrt-native-stat--warning { --an-tone: var(--an-warning); } .jio-native-stat--warning { --an-tone: var(--an-warning); }
.aksrt-native-stat--danger { --an-tone: var(--an-danger); } .jio-native-stat--danger { --an-tone: var(--an-danger); }
.aksrt-native-stat--neutral { --an-tone: var(--an-muted); } .jio-native-stat--neutral { --an-tone: var(--an-muted); }
.aksrt-native-stat--warning .aksrt-native-stat__value { color: #c27c0e; } .jio-native-stat--warning .jio-native-stat__value { color: #c27c0e; }
.aksrt-native-stat--danger .aksrt-native-stat__value { color: var(--an-danger); } .jio-native-stat--danger .jio-native-stat__value { color: var(--an-danger); }
/* ---------- 卡片 ---------- */ /* ---------- 卡片 ---------- */
.aksrt-native-card { .jio-native-card {
margin: 0 0 16px; margin: 0 0 16px;
background: var(--an-card); background: var(--an-card);
border-radius: var(--an-radius); border-radius: var(--an-radius);
box-shadow: var(--an-shadow); box-shadow: var(--an-shadow);
} }
.aksrt-native-card__head { .jio-native-card__head {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
@@ -211,7 +211,7 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
padding: 14px 20px; padding: 14px 20px;
border-bottom: 1px solid var(--an-border-soft); border-bottom: 1px solid var(--an-border-soft);
} }
.aksrt-native .aksrt-native-card__title { .jio-native .jio-native-card__title {
position: relative; position: relative;
margin: 0; margin: 0;
padding: 0 0 0 12px; padding: 0 0 0 12px;
@@ -220,7 +220,7 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
font-weight: 600; font-weight: 600;
line-height: 1.4; line-height: 1.4;
} }
.aksrt-native-card__title::before { .jio-native-card__title::before {
content: ""; content: "";
position: absolute; position: absolute;
top: 3px; top: 3px;
@@ -230,12 +230,12 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
background: var(--an-primary); background: var(--an-primary);
border-radius: 4px; border-radius: 4px;
} }
.aksrt-native-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .jio-native-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.aksrt-native-card__body { padding: 16px 20px; } .jio-native-card__body { padding: 16px 20px; }
.aksrt-native-card__body > :first-child { margin-top: 0; } .jio-native-card__body > :first-child { margin-top: 0; }
.aksrt-native-card__body > :last-child { margin-bottom: 0; } .jio-native-card__body > :last-child { margin-bottom: 0; }
.aksrt-native-card--flush > .aksrt-native-card__body { padding: 0; } .jio-native-card--flush > .jio-native-card__body { padding: 0; }
.aksrt-native-card__foot { .jio-native-card__foot {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
@@ -245,8 +245,8 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
border-top: 1px solid var(--an-border-soft); border-top: 1px solid var(--an-border-soft);
} }
/* 折叠卡片:<details class="aksrt-native-card aksrt-native-collapse"><summary>… */ /* 折叠卡片:<details class="jio-native-card jio-native-collapse"><summary>… */
.aksrt-native-collapse > summary { .jio-native-collapse > summary {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -257,75 +257,75 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
cursor: pointer; cursor: pointer;
list-style: none; list-style: none;
} }
.aksrt-native-collapse > summary::-webkit-details-marker { display: none; } .jio-native-collapse > summary::-webkit-details-marker { display: none; }
.aksrt-native-collapse > summary::after { .jio-native-collapse > summary::after {
content: "\f347"; content: "\f347";
margin-left: auto; margin-left: auto;
color: var(--an-muted); color: var(--an-muted);
font: normal 16px/1 dashicons; font: normal 16px/1 dashicons;
transition: transform .2s; transition: transform .2s;
} }
.aksrt-native-collapse[open] > summary { border-bottom: 1px solid var(--an-border-soft); } .jio-native-collapse[open] > summary { border-bottom: 1px solid var(--an-border-soft); }
.aksrt-native-collapse[open] > summary::after { transform: rotate(180deg); } .jio-native-collapse[open] > summary::after { transform: rotate(180deg); }
.aksrt-native-collapse > summary .dashicons { color: var(--an-primary); } .jio-native-collapse > summary .dashicons { color: var(--an-primary); }
/* ---------- 筛选栏 ---------- */ /* ---------- 筛选栏 ---------- */
.aksrt-native-filters { .jio-native-filters {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
margin: 0; margin: 0;
} }
.aksrt-native-filters label { display: inline-flex; align-items: center; gap: 6px; color: var(--an-muted); } .jio-native-filters label { display: inline-flex; align-items: center; gap: 6px; color: var(--an-muted); }
.aksrt-native-filters input[type="search"] { min-width: 220px; } .jio-native-filters input[type="search"] { min-width: 220px; }
.aksrt-native-filters__spacer { flex: 1 1 auto; } .jio-native-filters__spacer { flex: 1 1 auto; }
.aksrt-native-card__body > .aksrt-native-filters + .aksrt-native-filters { margin-top: 10px; } .jio-native-card__body > .jio-native-filters + .jio-native-filters { margin-top: 10px; }
/* ---------- 表单 ---------- */ /* ---------- 表单 ---------- */
.aksrt-native input[type="text"], .jio-native input[type="text"],
.aksrt-native input[type="search"], .jio-native input[type="search"],
.aksrt-native input[type="number"], .jio-native input[type="number"],
.aksrt-native input[type="date"], .jio-native input[type="date"],
.aksrt-native input[type="datetime-local"], .jio-native input[type="datetime-local"],
.aksrt-native input[type="email"], .jio-native input[type="email"],
.aksrt-native input[type="url"], .jio-native input[type="url"],
.aksrt-native input[type="password"], .jio-native input[type="password"],
.aksrt-native select, .jio-native select,
.aksrt-native textarea { .jio-native textarea {
min-height: 32px; min-height: 32px;
border-color: var(--an-border); border-color: var(--an-border);
border-radius: var(--an-radius-sm); border-radius: var(--an-radius-sm);
box-shadow: none; box-shadow: none;
} }
.aksrt-native select { padding-right: 28px; } .jio-native select { padding-right: 28px; }
.aksrt-native input:focus, .jio-native input:focus,
.aksrt-native select:focus, .jio-native select:focus,
.aksrt-native textarea:focus { .jio-native textarea:focus {
border-color: var(--an-primary); border-color: var(--an-primary);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--an-primary) 20%, transparent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--an-primary) 20%, transparent);
outline: 0; outline: 0;
} }
.aksrt-native-form-grid { .jio-native-form-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 14px 16px; gap: 14px 16px;
} }
.aksrt-native-form-grid .is-wide { grid-column: 1 / -1; } .jio-native-form-grid .is-wide { grid-column: 1 / -1; }
.aksrt-native-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; } .jio-native-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.aksrt-native-field__label { color: var(--an-text); font-weight: 500; } .jio-native-field__label { color: var(--an-text); font-weight: 500; }
.aksrt-native-field__hint { color: var(--an-muted); font-size: 12px; } .jio-native-field__hint { color: var(--an-muted); font-size: 12px; }
.aksrt-native-field input, .jio-native-field input,
.aksrt-native-field select, .jio-native-field select,
.aksrt-native-field textarea { width: 100%; max-width: none; } .jio-native-field textarea { width: 100%; max-width: none; }
.aksrt-native-form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; } .jio-native-form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 16px; }
.aksrt-native .form-table th { color: var(--an-text); font-weight: 500; } .jio-native .form-table th { color: var(--an-text); font-weight: 500; }
.aksrt-native .form-table td, .jio-native .form-table td,
.aksrt-native .form-table th { padding-top: 12px; padding-bottom: 12px; } .jio-native .form-table th { padding-top: 12px; padding-bottom: 12px; }
/* ---------- 按钮 ---------- */ /* ---------- 按钮 ---------- */
.aksrt-native .button, .jio-native .button,
.aksrt-native .page-title-action { .jio-native .page-title-action {
min-height: 32px; min-height: 32px;
padding: 0 14px; padding: 0 14px;
color: var(--an-text-2); color: var(--an-text-2);
@@ -335,42 +335,42 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
border-radius: var(--an-radius-sm); border-radius: var(--an-radius-sm);
transition: border-color .15s, color .15s, background .15s; transition: border-color .15s, color .15s, background .15s;
} }
.aksrt-native .page-title-action { top: 0; display: inline-flex; align-items: center; } .jio-native .page-title-action { top: 0; display: inline-flex; align-items: center; }
.aksrt-native .button:hover, .jio-native .button:hover,
.aksrt-native .button:focus, .jio-native .button:focus,
.aksrt-native .page-title-action:hover { .jio-native .page-title-action:hover {
color: var(--an-primary); color: var(--an-primary);
background: #fff; background: #fff;
border-color: var(--an-primary); border-color: var(--an-primary);
box-shadow: none; box-shadow: none;
} }
.aksrt-native .button-primary, .jio-native .button-primary,
.aksrt-native .button.button-primary { .jio-native .button.button-primary {
color: #fff; color: #fff;
background: var(--an-primary); background: var(--an-primary);
border-color: var(--an-primary); border-color: var(--an-primary);
} }
.aksrt-native .button-primary:hover, .jio-native .button-primary:hover,
.aksrt-native .button-primary:focus, .jio-native .button-primary:focus,
.aksrt-native .button.button-primary:hover { .jio-native .button.button-primary:hover {
color: #fff; color: #fff;
background: var(--an-primary-hover); background: var(--an-primary-hover);
border-color: var(--an-primary-hover); border-color: var(--an-primary-hover);
} }
.aksrt-native .button-small, .jio-native .button-small,
.aksrt-native .button.button-small { min-height: 26px; padding: 0 10px; font-size: 12px; line-height: 24px; } .jio-native .button.button-small { min-height: 26px; padding: 0 10px; font-size: 12px; line-height: 24px; }
.aksrt-native .button-link-delete, .jio-native .button-link-delete,
.aksrt-native .button.is-danger { color: var(--an-danger); } .jio-native .button.is-danger { color: var(--an-danger); }
.aksrt-native .button.is-danger:hover { color: #fff; background: var(--an-danger); border-color: var(--an-danger); } .jio-native .button.is-danger:hover { color: #fff; background: var(--an-danger); border-color: var(--an-danger); }
.aksrt-native .button .dashicons { width: 16px; height: 16px; margin: 0 4px 0 -2px; font-size: 16px; line-height: inherit; vertical-align: -1px; } .jio-native .button .dashicons { width: 16px; height: 16px; margin: 0 4px 0 -2px; font-size: 16px; line-height: inherit; vertical-align: -1px; }
.aksrt-native .submit { margin: 0; padding: 0; } .jio-native .submit { margin: 0; padding: 0; }
/* 批量操作行:下拉与「应用」按钮锁定同一高度与字号。 /* 批量操作行:下拉与「应用」按钮锁定同一高度与字号。
WP 核心给 select 14px/line-height:2、给 .button 13px,且 782px 以下再把两者各自放大, WP 核心给 select 14px/line-height:2、给 .button 13px,且 782px 以下再把两者各自放大,
只设 min-height 时两者会因字号、行高和基线对齐不同而错位,这里显式给定。 */ 只设 min-height 时两者会因字号、行高和基线对齐不同而错位,这里显式给定。 */
.aksrt-native-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .jio-native-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.aksrt-native-bulk select, .jio-native-bulk select,
.aksrt-native-bulk .button { .jio-native-bulk .button {
box-sizing: border-box; box-sizing: border-box;
height: 32px; height: 32px;
min-height: 32px; min-height: 32px;
@@ -379,21 +379,21 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
line-height: 30px; line-height: 30px;
vertical-align: middle; vertical-align: middle;
} }
.aksrt-native-bulk select { width: auto; max-width: 12.5rem; } .jio-native-bulk select { width: auto; max-width: 12.5rem; }
/* ---------- 表格 ---------- */ /* ---------- 表格 ---------- */
.aksrt-native-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; } .jio-native-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.aksrt-native .widefat, .jio-native .widefat,
.aksrt-native .wp-list-table { .jio-native .wp-list-table {
border: 0; border: 0;
border-radius: 0; border-radius: 0;
box-shadow: none; box-shadow: none;
} }
.aksrt-native .aksrt-native-card .widefat { background: transparent; } .jio-native .jio-native-card .widefat { background: transparent; }
.aksrt-native .widefat thead th, .jio-native .widefat thead th,
.aksrt-native .widefat thead td, .jio-native .widefat thead td,
.aksrt-native .widefat tfoot th, .jio-native .widefat tfoot th,
.aksrt-native .widefat tfoot td { .jio-native .widefat tfoot td {
padding: 10px 12px; padding: 10px 12px;
color: var(--an-muted); color: var(--an-muted);
font-size: 12px; font-size: 12px;
@@ -401,24 +401,24 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
background: var(--an-bg-soft); background: var(--an-bg-soft);
border-bottom: 1px solid var(--an-border-soft); border-bottom: 1px solid var(--an-border-soft);
} }
.aksrt-native .widefat thead th a { color: var(--an-muted); } .jio-native .widefat thead th a { color: var(--an-muted); }
.aksrt-native .widefat td, .jio-native .widefat td,
.aksrt-native .widefat tbody th { .jio-native .widefat tbody th {
padding: 12px; padding: 12px;
color: var(--an-text-2); color: var(--an-text-2);
vertical-align: middle; vertical-align: middle;
border-bottom: 1px solid var(--an-border-soft); border-bottom: 1px solid var(--an-border-soft);
} }
.aksrt-native .widefat tbody tr:last-child > td, .jio-native .widefat tbody tr:last-child > td,
.aksrt-native .widefat tbody tr:last-child > th { border-bottom: 0; } .jio-native .widefat tbody tr:last-child > th { border-bottom: 0; }
.aksrt-native .striped > tbody > :nth-child(odd) { background: transparent; } .jio-native .striped > tbody > :nth-child(odd) { background: transparent; }
.aksrt-native .widefat tbody tr { transition: background .15s; } .jio-native .widefat tbody tr { transition: background .15s; }
.aksrt-native .widefat tbody tr:hover { background: #fafbfc; } .jio-native .widefat tbody tr:hover { background: #fafbfc; }
.aksrt-native .widefat .check-column { width: 2.4em; padding: 12px 0 12px 12px; vertical-align: middle; } .jio-native .widefat .check-column { width: 2.4em; padding: 12px 0 12px 12px; vertical-align: middle; }
.aksrt-native .widefat thead .check-column { padding-top: 10px; padding-bottom: 10px; } .jio-native .widefat thead .check-column { padding-top: 10px; padding-bottom: 10px; }
.aksrt-native .widefat .check-column input { margin: 0; } .jio-native .widefat .check-column input { margin: 0; }
.aksrt-native .widefat code, .jio-native .widefat code,
.aksrt-native-mono { .jio-native-mono {
padding: 1px 6px; padding: 1px 6px;
color: var(--an-text); color: var(--an-text);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
@@ -426,36 +426,36 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
background: var(--an-bg-soft); background: var(--an-bg-soft);
border-radius: 4px; border-radius: 4px;
} }
.aksrt-native .row-actions { color: var(--an-muted); } .jio-native .row-actions { color: var(--an-muted); }
.aksrt-native .row-title, .jio-native .row-title,
.aksrt-native .widefat strong { color: var(--an-text); } .jio-native .widefat strong { color: var(--an-text); }
.aksrt-native-card > .aksrt-native-card__body > .widefat:first-child thead th:first-child, .jio-native-card > .jio-native-card__body > .widefat:first-child thead th:first-child,
.aksrt-native-card--flush .widefat thead > tr > :first-child { padding-left: 20px; } .jio-native-card--flush .widefat thead > tr > :first-child { padding-left: 20px; }
.aksrt-native-card--flush .widefat tbody > tr > :first-child { padding-left: 20px; } .jio-native-card--flush .widefat tbody > tr > :first-child { padding-left: 20px; }
.aksrt-native-card--flush .widefat thead > tr > :last-child, .jio-native-card--flush .widefat thead > tr > :last-child,
.aksrt-native-card--flush .widefat tbody > tr > :last-child { padding-right: 20px; } .jio-native-card--flush .widefat tbody > tr > :last-child { padding-right: 20px; }
.aksrt-native-card--flush .widefat thead th:first-child, .jio-native-card--flush .widefat thead th:first-child,
.aksrt-native-card--flush .widefat thead td:first-child { border-top-left-radius: 0; } .jio-native-card--flush .widefat thead td:first-child { border-top-left-radius: 0; }
/* 行内操作表单:单元格里的一组小控件 */ /* 行内操作表单:单元格里的一组小控件 */
.aksrt-native-inline { .jio-native-inline {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
margin: 0; margin: 0;
} }
.aksrt-native-inline + .aksrt-native-inline { margin-top: 6px; } .jio-native-inline + .jio-native-inline { margin-top: 6px; }
.aksrt-native-inline input[type="text"] { min-width: 0; width: 140px; } .jio-native-inline input[type="text"] { min-width: 0; width: 140px; }
/* 用户单元格:头像 + 名称 + 次要信息 */ /* 用户单元格:头像 + 名称 + 次要信息 */
.aksrt-native-user { display: inline-flex; align-items: center; gap: 8px; min-width: 0; color: var(--an-text); text-decoration: none; } .jio-native-user { display: inline-flex; align-items: center; gap: 8px; min-width: 0; color: var(--an-text); text-decoration: none; }
.aksrt-native-user img { flex: none; border-radius: 50%; } .jio-native-user img { flex: none; border-radius: 50%; }
.aksrt-native-user__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .jio-native-user__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aksrt-native-user__meta { display: block; color: var(--an-muted); font-size: 12px; } .jio-native-user__meta { display: block; color: var(--an-muted); font-size: 12px; }
/* ---------- 徽标 ---------- */ /* ---------- 徽标 ---------- */
.aksrt-native-badge { .jio-native-badge {
--an-tone: var(--an-muted); --an-tone: var(--an-muted);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -469,22 +469,22 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
background: color-mix(in srgb, var(--an-tone) 10%, #fff); background: color-mix(in srgb, var(--an-tone) 10%, #fff);
border-radius: 999px; border-radius: 999px;
} }
.aksrt-native-badge.has-dot::before { .jio-native-badge.has-dot::before {
content: ""; content: "";
width: 6px; width: 6px;
height: 6px; height: 6px;
background: currentColor; background: currentColor;
border-radius: 50%; border-radius: 50%;
} }
.aksrt-native-badge--success { --an-tone: var(--an-primary); } .jio-native-badge--success { --an-tone: var(--an-primary); }
.aksrt-native-badge--info { --an-tone: var(--an-info); } .jio-native-badge--info { --an-tone: var(--an-info); }
.aksrt-native-badge--warning { --an-tone: #c27c0e; } .jio-native-badge--warning { --an-tone: #c27c0e; }
.aksrt-native-badge--danger { --an-tone: var(--an-danger); } .jio-native-badge--danger { --an-tone: var(--an-danger); }
.aksrt-native-badge--neutral { --an-tone: #6b7785; } .jio-native-badge--neutral { --an-tone: #6b7785; }
.aksrt-native-badge--primary { --an-tone: #7c4dff; } .jio-native-badge--primary { --an-tone: #7c4dff; }
/* ---------- 空状态 / 提示 ---------- */ /* ---------- 空状态 / 提示 ---------- */
.aksrt-native-empty { .jio-native-empty {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@@ -493,19 +493,19 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
color: var(--an-muted); color: var(--an-muted);
text-align: center; text-align: center;
} }
.aksrt-native-empty .dashicons { width: 40px; height: 40px; color: #c9cdd4; font-size: 40px; } .jio-native-empty .dashicons { width: 40px; height: 40px; color: #c9cdd4; font-size: 40px; }
.aksrt-native-empty__title { color: var(--an-text-2); font-size: 14px; font-weight: 500; } .jio-native-empty__title { color: var(--an-text-2); font-size: 14px; font-weight: 500; }
.aksrt-native .widefat td.aksrt-native-empty-cell { padding: 0; } .jio-native .widefat td.jio-native-empty-cell { padding: 0; }
.aksrt-native-muted, .jio-native-muted,
.aksrt-native .description { color: var(--an-muted); } .jio-native .description { color: var(--an-muted); }
.aksrt-native-text--success { color: var(--an-primary); } .jio-native-text--success { color: var(--an-primary); }
.aksrt-native-text--info { color: var(--an-info); } .jio-native-text--info { color: var(--an-info); }
.aksrt-native-text--warning { color: #c27c0e; } .jio-native-text--warning { color: #c27c0e; }
.aksrt-native-text--danger { color: var(--an-danger); } .jio-native-text--danger { color: var(--an-danger); }
.aksrt-native-amount { color: var(--an-text); font-weight: 600; font-variant-numeric: tabular-nums; } .jio-native-amount { color: var(--an-text); font-weight: 600; font-variant-numeric: tabular-nums; }
.aksrt-native-amount.is-positive { color: var(--an-primary); } .jio-native-amount.is-positive { color: var(--an-primary); }
.aksrt-native-amount.is-negative { color: var(--an-danger); } .jio-native-amount.is-negative { color: var(--an-danger); }
.aksrt-native-callout { .jio-native-callout {
margin: 0 0 16px; margin: 0 0 16px;
padding: 12px 16px; padding: 12px 16px;
color: var(--an-text-2); color: var(--an-text-2);
@@ -513,43 +513,43 @@ a.aksrt-native-stat:focus { outline: 2px solid color-mix(in srgb, var(--an-tone)
border-left: 3px solid var(--an-info); border-left: 3px solid var(--an-info);
border-radius: var(--an-radius-sm); border-radius: var(--an-radius-sm);
} }
.aksrt-native-callout.is-warning { background: #fff8eb; border-left-color: var(--an-warning); } .jio-native-callout.is-warning { background: #fff8eb; border-left-color: var(--an-warning); }
.aksrt-native-callout.is-danger { background: #fdf0f2; border-left-color: var(--an-danger); } .jio-native-callout.is-danger { background: #fdf0f2; border-left-color: var(--an-danger); }
/* ---------- 分页条(AdminListPagination / paginate_links) ---------- */ /* ---------- 分页条(AdminListPagination / paginate_links) ---------- */
.aksrt-native .tablenav { height: auto; margin: 0; padding: 12px 20px; } .jio-native .tablenav { height: auto; margin: 0; padding: 12px 20px; }
.aksrt-native .aksrt-native-card .tablenav.bottom { border-top: 1px solid var(--an-border-soft); } .jio-native .jio-native-card .tablenav.bottom { border-top: 1px solid var(--an-border-soft); }
.aksrt-native .tablenav-pages { float: right; margin: 0; color: var(--an-muted); } .jio-native .tablenav-pages { float: right; margin: 0; color: var(--an-muted); }
.aksrt-native .tablenav-pages .button, .jio-native .tablenav-pages .button,
.aksrt-native .tablenav-pages .page-numbers { .jio-native .tablenav-pages .page-numbers {
min-width: 30px; min-width: 30px;
min-height: 30px; min-height: 30px;
padding: 0 8px; padding: 0 8px;
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
} }
.aksrt-native .tablenav-pages .page-numbers { .jio-native .tablenav-pages .page-numbers {
display: inline-block; display: inline-block;
color: var(--an-text-2); color: var(--an-text-2);
border: 1px solid var(--an-border); border: 1px solid var(--an-border);
border-radius: var(--an-radius-sm); border-radius: var(--an-radius-sm);
text-decoration: none; text-decoration: none;
} }
.aksrt-native .tablenav-pages .page-numbers.current { color: #fff; background: var(--an-primary); border-color: var(--an-primary); } .jio-native .tablenav-pages .page-numbers.current { color: #fff; background: var(--an-primary); border-color: var(--an-primary); }
.aksrt-native .tablenav-pages .page-numbers.dots { border-color: transparent; } .jio-native .tablenav-pages .page-numbers.dots { border-color: transparent; }
.aksrt-native .tablenav-pages .button.disabled { color: #c9cdd4 !important; background: var(--an-bg-soft) !important; border-color: var(--an-border-soft) !important; } .jio-native .tablenav-pages .button.disabled { color: #c9cdd4 !important; background: var(--an-bg-soft) !important; border-color: var(--an-border-soft) !important; }
.aksrt-native .tablenav .actions { padding: 0; } .jio-native .tablenav .actions { padding: 0; }
.aksrt-native .tablenav::after { content: ""; display: table; clear: both; } .jio-native .tablenav::after { content: ""; display: table; clear: both; }
@media (max-width: 782px) { @media (max-width: 782px) {
.aksrt-native { margin-right: 10px; } .jio-native { margin-right: 10px; }
.aksrt-native-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } .jio-native-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.aksrt-native-stat { padding: 12px 14px; } .jio-native-stat { padding: 12px 14px; }
.aksrt-native-stat__value { font-size: 20px; } .jio-native-stat__value { font-size: 20px; }
.aksrt-native-card__head, .jio-native-card__head,
.aksrt-native-card__body, .jio-native-card__body,
.aksrt-native-collapse > summary { padding-left: 14px; padding-right: 14px; } .jio-native-collapse > summary { padding-left: 14px; padding-right: 14px; }
.aksrt-native .tablenav { padding: 10px 14px; } .jio-native .tablenav { padding: 10px 14px; }
.aksrt-native .tablenav-pages { float: none; } .jio-native .tablenav-pages { float: none; }
.aksrt-native-filters input[type="search"] { min-width: 0; flex: 1 1 100%; } .jio-native-filters input[type="search"] { min-width: 0; flex: 1 1 100%; }
} }
Loaded 100 of 997 files, more files were not shown because too many files have changed in this diff. Show more