Compare commits
30 Commits
feat-wxwor
...
test/weixi
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a8e11414f | |||
| 46135002f9 | |||
| 72f6b341a1 | |||
| 0cb2dfa647 | |||
| 0443cc46ec | |||
| 85cf52b0e4 | |||
| c7aaa1bd16 | |||
| 0519879ebb | |||
| f461fe93f0 | |||
| 2eb98efe61 | |||
| 866ca8d938 | |||
| 267cfa12a2 | |||
| d7df9293bb | |||
| 604917b56c | |||
| 840ce860ea | |||
| 04e1735028 | |||
| ba829c4f53 | |||
| b266023afc | |||
| 23abd0496b | |||
| dffb2563be | |||
| 80998fba70 | |||
| 1f65bb61dd | |||
| 9e044672ee | |||
| 989494af6d | |||
| 5d8c3ba4ce | |||
| a973ce720e | |||
| 218d405f56 | |||
| 2d07082b81 | |||
| 15720c6a62 | |||
| 224c2a3117 |
3
.env
3
.env
@@ -7,8 +7,6 @@ APP_ENV=development
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
PHP_FPM_PORT=9100
|
||||
XDEBUG_POST=9103
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
@@ -23,5 +21,4 @@ REDIS_PORT=6399
|
||||
|
||||
# Nginx 配置
|
||||
NGINX_PORT=8010
|
||||
NGINX_SSL_PORT=8012
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ APP_ENV=development
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
PHP_FPM_PORT=9105
|
||||
XDEBUG_POST=9108
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
@@ -23,5 +21,4 @@ REDIS_PORT=6499
|
||||
|
||||
# Nginx 暴漏端口
|
||||
NGINX_PORT=8050
|
||||
NGINX_SSL_PORT=8052
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ APP_ENV=development
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
PHP_FPM_PORT=9100
|
||||
XDEBUG_POST=9103
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
@@ -23,4 +21,3 @@ REDIS_PORT=6399
|
||||
|
||||
# Nginx 配置
|
||||
NGINX_PORT=8010
|
||||
NGINX_SSL_PORT=8012
|
||||
|
||||
@@ -2,26 +2,23 @@
|
||||
PROJECT_NAME=newshop
|
||||
|
||||
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||
APP_ENV=local
|
||||
APP_ENV=production
|
||||
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
PHP_FPM_PORT=9100
|
||||
XDEBUG_POST=9103
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
MYSQL_DATABASE=shop_dev
|
||||
MYSQL_DATABASE=shop_mallnew
|
||||
MYSQL_USER=shop_mallnew
|
||||
MYSQL_PASSWORD=shop_mallnew
|
||||
MYSQL_PORT=3316
|
||||
MYSQL_PORT=3926
|
||||
|
||||
# Redis 配置
|
||||
# Redis 绑定端口及密码
|
||||
REDIS_PASSWORD=luckyshop123!@#
|
||||
REDIS_PORT=6399
|
||||
REDIS_PORT=6829
|
||||
|
||||
# Nginx 配置
|
||||
NGINX_PORT=8010
|
||||
NGINX_SSL_PORT=8012
|
||||
# Nginx 暴漏端口
|
||||
NGINX_PORT=8858
|
||||
|
||||
24
.env.staging
Normal file
24
.env.staging
Normal file
@@ -0,0 +1,24 @@
|
||||
# 项目配置, 请根据实际情况修改
|
||||
PROJECT_NAME=newshop
|
||||
|
||||
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||
APP_ENV=staging
|
||||
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
MYSQL_DATABASE=shop_mallnew
|
||||
MYSQL_USER=shop_mallnew
|
||||
MYSQL_PASSWORD=shop_mallnew
|
||||
MYSQL_PORT=3826
|
||||
|
||||
# Redis 绑定端口及密码
|
||||
REDIS_PASSWORD=luckyshop123!@#
|
||||
REDIS_PORT=6809
|
||||
|
||||
# Nginx 暴漏端口
|
||||
NGINX_PORT=8854
|
||||
|
||||
24
.env.test
Normal file
24
.env.test
Normal file
@@ -0,0 +1,24 @@
|
||||
# 项目配置, 请根据实际情况修改
|
||||
PROJECT_NAME=newshop
|
||||
|
||||
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||
APP_ENV=test
|
||||
|
||||
# PHP/PHP-FPM 配置
|
||||
PHP_VERSION=7.4
|
||||
PHP_FPM_VERSION=7.4-fpm
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_HOST=%
|
||||
MYSQL_DATABASE=shop_mallnew
|
||||
MYSQL_USER=shop_mallnew
|
||||
MYSQL_PASSWORD=shop_mallnew
|
||||
MYSQL_PORT=3346
|
||||
|
||||
# Redis 绑定端口及密码
|
||||
REDIS_PASSWORD=luckyshop123!@#
|
||||
REDIS_PORT=6799
|
||||
|
||||
# Nginx 暴漏端口
|
||||
NGINX_PORT=8360
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# 特别说明,本地local环境,方便操作,所以未使用的统一的docker-compose.yml文件,只保留了local环境的配置
|
||||
|
||||
x-shared-env: &shared-api-env
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}
|
||||
MYSQL_ROOT_HOST: ${MYSQL_ROOT_HOST:-'%'} # 允许root从任何主机连接
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-shop_mallnew}
|
||||
MYSQL_USER: ${MYSQL_USER:-shop_mallnew}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-shop_mallnew}
|
||||
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-luckyshop123!@#}
|
||||
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||
|
||||
# 将服务归类到目录 A 中
|
||||
services:
|
||||
php-fpm:
|
||||
build:
|
||||
context: ./docker/php
|
||||
dockerfile: Dockerfile
|
||||
container_name: ${PROJECT_NAME}_php
|
||||
restart: always
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # 支持主机名解析
|
||||
environment:
|
||||
PHP_ENV: ${PHP_ENV:-development}
|
||||
# 环境变量, APP_ENV 应用于 ThinkPHP 6.x 框架, .env.local 要想启用,需要在项目根目录下创建 .env.local 文件,并将 APP_ENV 设置为 local
|
||||
# 同理,如果要启用开发环境,则将 APP_ENV 设置为 development,如果要启用生产环境,则将 APP_ENV 设置为 production
|
||||
# 不然,ThinkPHP 6.x 系列,会只加载 .env 文件,而不会加载 .env.local 文件,导致 .env.local 文件中的配置不会生效
|
||||
APP_ENV: ${APP_ENV:-local}
|
||||
APP_DEBUG: ${APP_DEBUG:-true}
|
||||
ports:
|
||||
- "${PHP_FPM_PORT:-9000}:9000" # PHP-FPM
|
||||
volumes:
|
||||
- ./:/var/www/all_source
|
||||
- ./src:/var/www/html
|
||||
# 更新下载源列表以加速apt-get
|
||||
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
||||
- ./docker/php/php.ini:/usr/local/etc/php/php.ini:ro
|
||||
depends_on:
|
||||
- db
|
||||
healthcheck:
|
||||
test: ["CMD", "bash", "-c", "curl -f http://localhost:9000/status"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
networks:
|
||||
- sass-platform-net
|
||||
labels:
|
||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
||||
|
||||
nginx:
|
||||
build:
|
||||
context: ./docker/nginx
|
||||
dockerfile: Dockerfile
|
||||
container_name: ${PROJECT_NAME}_nginx
|
||||
restart: always
|
||||
ports:
|
||||
- "${NGINX_PORT:-80}:80"
|
||||
- "${NGINX_SSL_PORT:-443}:443"
|
||||
volumes:
|
||||
# 挂载项目代码到 Nginx 容器中
|
||||
- ./src:/var/www/html:rw
|
||||
# 更新下载源列表以加速apt-get
|
||||
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
||||
# 创建临时目录
|
||||
- /var/www/server/nginx/proxy_temp_dir
|
||||
- /var/www/server/nginx/proxy_cache_dir
|
||||
depends_on:
|
||||
- php-fpm
|
||||
networks:
|
||||
- sass-platform-net
|
||||
labels:
|
||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
||||
|
||||
db:
|
||||
image: mysql:5.7.44
|
||||
container_name: ${PROJECT_NAME}_mysql
|
||||
environment:
|
||||
<<: *shared-api-env
|
||||
volumes:
|
||||
- mysql_db_data:/var/lib/mysql
|
||||
- ./docker/mysql/init:/docker-entrypoint-initdb.d
|
||||
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/custom.cnf
|
||||
ports:
|
||||
- ${MYSQL_PORT:-3306}:3306
|
||||
networks:
|
||||
- sass-platform-net
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --innodb_buffer_pool_size=256M
|
||||
labels:
|
||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
||||
|
||||
# Redis 服务(可选)
|
||||
redis:
|
||||
image: redis:8.2
|
||||
container_name: ${PROJECT_NAME}_redis
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-luckyshop123!@#}
|
||||
REDISCLI_AUTH: ${REDIS_PASSWORD:-luckyshop123!@#}
|
||||
ports:
|
||||
- "${REDIS_PORT:-6379}:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
- ./docker/redis/redis.conf:/etc/redis/redis.conf
|
||||
networks:
|
||||
- sass-platform-net
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
||||
|
||||
volumes:
|
||||
mysql_db_data:
|
||||
redis_data:
|
||||
|
||||
networks:
|
||||
sass-platform-net:
|
||||
driver: bridge
|
||||
@@ -25,11 +25,13 @@ services:
|
||||
# 不然,ThinkPHP 6.x 系列,会只加载 .env 文件,而不会加载 .env.local 文件,导致 .env.local 文件中的配置不会生效
|
||||
APP_ENV: ${APP_ENV:-development}
|
||||
APP_DEBUG: ${APP_DEBUG:-true}
|
||||
ports:
|
||||
- "${PHP_FPM_PORT:-9000}:9000" # PHP-FPM
|
||||
# PHP应用根目录(可选,默认 /var/www/html)
|
||||
PHP_APP_ROOT: ${PHP_APP_ROOT:-/var/www/html}
|
||||
# 用户ID映射(可选,用于解决挂载权限问题)
|
||||
USER_ID: ${USER_ID:-33}
|
||||
GROUP_ID: ${GROUP_ID:-33}
|
||||
volumes:
|
||||
- ./:/var/www/all_source
|
||||
- ./src:/var/www/html
|
||||
- ./src:/var/www/html:rw
|
||||
# 更新下载源列表以加速apt-get
|
||||
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
||||
- ./docker/php/php.ini:/usr/local/etc/php/php.ini:ro
|
||||
@@ -54,7 +56,6 @@ services:
|
||||
restart: always
|
||||
ports:
|
||||
- "${NGINX_PORT:-80}:80"
|
||||
- "${NGINX_SSL_PORT:-443}:443"
|
||||
volumes:
|
||||
# 挂载项目代码到 Nginx 容器中
|
||||
- ./src:/var/www/html:rw
|
||||
@@ -129,5 +130,4 @@ volumes:
|
||||
networks:
|
||||
sass-platform-net:
|
||||
name: ${PROJECT_NAME}_${APP_ENV}_net
|
||||
driver: bridge
|
||||
external: true
|
||||
driver: bridge
|
||||
@@ -4231,7 +4231,7 @@ CREATE TABLE `lucky_member_label` (
|
||||
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
INDEX IDX_nc_member_label_label_id (`label_id`),
|
||||
PRIMARY KEY (`label_id`) USING BTREE,
|
||||
KEY `IDX_nc_member_label_label_id` (`label_id`) USING BTREE
|
||||
KEY `IDX_nc_member_label_label_id_key` (`label_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='会员标签';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
|
||||
15
docker/mysql_db_data/.gitignore
vendored
15
docker/mysql_db_data/.gitignore
vendored
@@ -1,10 +1,9 @@
|
||||
# 忽略目录下所有文件和子目录
|
||||
# 忽略所有文件
|
||||
*
|
||||
# 忽略所有子目录
|
||||
*/
|
||||
# 但不忽略 .gitkeep 文件
|
||||
!.gitkeep
|
||||
# 不忽略 .gitignore 文件自身
|
||||
|
||||
# 只保留指定的 .gitkeep 文件
|
||||
!.gitignore
|
||||
# 不忽略 development/.gitkeep 文件
|
||||
!development/.gitkeep
|
||||
!development/.gitkeep
|
||||
!test/.gitkeep
|
||||
!production/.gitkeep
|
||||
!staging/.gitkeep
|
||||
@@ -1,29 +1,21 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
# 删除默认配置
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
|
||||
#
|
||||
# - ./.docker/nginx/conf.c:/etc/nginx/conf.c:ro
|
||||
# - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
# - ./.docker/nginx/sites-enabled:/etc/nginx/sites-enabled:ro
|
||||
# 将本地 nginx 配置复制到镜像中并设置为只读
|
||||
COPY ./conf.c /etc/nginx/conf.c
|
||||
COPY ./default.conf /etc/nginx/conf.d/default.conf
|
||||
COPY ./sites-enabled /etc/nginx/sites-enabled
|
||||
|
||||
# 设置只读权限(文件 0444,目录及其内容 0555)
|
||||
RUN chmod 0444 /etc/nginx/conf.c \
|
||||
&& chmod 0444 /etc/nginx/conf.d/default.conf \
|
||||
&& chmod -R 0555 /etc/nginx/sites-enabled
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# 创建日志目录
|
||||
RUN mkdir -p /var/log/nginx
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 80 443
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
# 删除默认配置
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
|
||||
|
||||
# 将本地 nginx 配置复制到镜像中
|
||||
COPY ./conf.c/ /etc/nginx/conf.c/
|
||||
COPY ./default.conf /etc/nginx/conf.d/default.conf
|
||||
COPY ./sites-enabled/ /etc/nginx/sites-enabled/
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 80 443
|
||||
|
||||
# 添加在Dockerfile末尾,CMD命令之前
|
||||
COPY ./entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
# 启动nginx
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
14
docker/nginx/conf.c/enable-websocket.conf
Normal file
14
docker/nginx/conf.c/enable-websocket.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
location /ws {
|
||||
proxy_pass http://php-fpm:8080; # 注意:这里用的是 Docker 服务名或容器名
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 可选:设置超时(WebSocket 是长连接)
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
}
|
||||
18
docker/nginx/entrypoint.sh
Normal file
18
docker/nginx/entrypoint.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "=== NGINX Docker 权限初始化 ==="
|
||||
|
||||
# 设置权限
|
||||
chmod -R 0444 /etc/nginx/conf.c
|
||||
chmod 0444 /etc/nginx/conf.d/default.conf
|
||||
chmod -R 0755 /etc/nginx/sites-enabled
|
||||
|
||||
|
||||
# 创建日志目录
|
||||
mkdir -p /var/log/nginx
|
||||
|
||||
echo "=== NGINX Docker 权限初始化完成 ==="
|
||||
|
||||
# 执行原有的启动命令
|
||||
exec "$@"
|
||||
@@ -20,6 +20,9 @@
|
||||
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
# --- SSL configuration end ---
|
||||
|
||||
# 启用 WebSocket 支持
|
||||
include conf.c/enable-websocket.conf;
|
||||
|
||||
#PHP-INFO-START PHP引用配置,可以注释或修改
|
||||
include conf.c/enable-php-74.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
@@ -27,9 +27,14 @@ RUN apt-get update && apt-get install -y \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
iputils-ping \
|
||||
iputils-ping \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 安装 WebSocat 完成后,清理缓存
|
||||
COPY ./websocat /usr/local/bin/websocat
|
||||
RUN chmod +x /usr/local/bin/websocat
|
||||
|
||||
# 安装 PHP 扩展
|
||||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install \
|
||||
@@ -54,15 +59,15 @@ RUN composer --version
|
||||
|
||||
# 修改 PHP 配置
|
||||
RUN echo "memory_limit=256M" > /usr/local/etc/php/conf.d/memory-limit.ini \
|
||||
&& echo "upload_max_filesize=50M" >> /usr/local/etc/php/conf.d/uploads.ini \
|
||||
&& echo "post_max_size=50M" >> /usr/local/etc/php/conf.d/uploads.ini
|
||||
&& echo "upload_max_filesize=150M" >> /usr/local/etc/php/conf.d/uploads.ini \
|
||||
&& echo "post_max_size=150M" >> /usr/local/etc/php/conf.d/uploads.ini
|
||||
|
||||
# # 使用Composer安装项目依赖(可选,根据需要启用, 更多的时候,会出错,要在容器中执行操作)
|
||||
# RUN composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
|
||||
# RUN composer install --no-dev --optimize-autoloader --working-dir=/var/www/html
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 9000
|
||||
# 暴露端口,9000 为 PHP-FPM 端口,8080 为 WebSocket 端口
|
||||
EXPOSE 9000 8080
|
||||
|
||||
############ 查看 cron 进程
|
||||
## 查看 cron 进程
|
||||
|
||||
@@ -1,112 +1,343 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
# 移除 set -e 以便更好的错误控制
|
||||
|
||||
echo "=== ThinkPHP Docker权限初始化 ==="
|
||||
echo "=== Web应用权限初始化 ==="
|
||||
|
||||
# 定义应用根目录
|
||||
APP_ROOT="/var/www/html"
|
||||
# 定义应用根目录,优先使用环境变量,否则使用默认值
|
||||
APP_ROOT="${PHP_APP_ROOT:-/var/www/html}"
|
||||
|
||||
# 获取正确的用户和组
|
||||
if [ -n "$USER_ID" ] && [ -n "$GROUP_ID" ]; then
|
||||
# 如果指定了用户ID,修改www-data
|
||||
usermod -u $USER_ID www-data
|
||||
groupmod -g $GROUP_ID www-data
|
||||
echo "使用应用根目录: $APP_ROOT"
|
||||
|
||||
# 如果应用根目录不存在,则跳过权限设置
|
||||
if [ ! -d "$APP_ROOT" ]; then
|
||||
echo "❌ 应用根目录:'$APP_ROOT'不存在,跳过权限设置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建统一的Web组并配置所有用户(最高效的权限管理)
|
||||
configure_web_users() {
|
||||
# 常见Web服务器用户列表
|
||||
WEB_USERS=("www-data" "www" "apache" "nginx")
|
||||
|
||||
# 获取环境变量中的用户ID
|
||||
TARGET_UID=${USER_ID:-33}
|
||||
TARGET_GID=${GROUP_ID:-33}
|
||||
|
||||
echo "配置统一Web组权限,目标UID:GID = $TARGET_UID:$TARGET_GID"
|
||||
|
||||
# 创建统一的Web组(增强错误处理)
|
||||
WEB_GROUP="webaccess"
|
||||
if ! getent group "$WEB_GROUP" &>/dev/null; then
|
||||
echo "创建统一Web组: $WEB_GROUP"
|
||||
|
||||
# 尝试使用指定GID创建组
|
||||
if groupadd -g $TARGET_GID "$WEB_GROUP" 2>/dev/null; then
|
||||
echo "✅ 统一Web组创建成功,GID: $TARGET_GID"
|
||||
else
|
||||
echo "⚠️ GID $TARGET_GID 已被占用,尝试自动分配GID"
|
||||
|
||||
# 尝试不指定GID创建组
|
||||
if groupadd "$WEB_GROUP" 2>/dev/null; then
|
||||
ACTUAL_GID=$(getent group "$WEB_GROUP" | cut -d: -f3)
|
||||
echo "✅ 统一Web组创建成功,自动分配GID: $ACTUAL_GID"
|
||||
else
|
||||
echo "❌ 创建 $WEB_GROUP 组失败,尝试使用备用方案"
|
||||
|
||||
# 备用方案:使用现有的www-data组
|
||||
if getent group "www-data" &>/dev/null; then
|
||||
WEB_GROUP="www-data"
|
||||
echo "🔄 使用现有的www-data组作为统一组"
|
||||
else
|
||||
echo "❌ 备用方案也失败,权限配置可能不完整"
|
||||
WEB_GROUP=""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
ACTUAL_GID=$(getent group "$WEB_GROUP" | cut -d: -f3)
|
||||
echo "✅ 统一Web组 $WEB_GROUP 已存在,GID: $ACTUAL_GID"
|
||||
fi
|
||||
|
||||
# 最终验证组是否存在
|
||||
if [ -z "$WEB_GROUP" ] || ! getent group "$WEB_GROUP" &>/dev/null; then
|
||||
echo "❌ 无法创建或找到可用的Web组,权限配置将受限"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 只将已存在的Web用户加入统一组(增强错误处理)
|
||||
success_count=0
|
||||
total_users=0
|
||||
|
||||
for web_user in "${WEB_USERS[@]}"; do
|
||||
total_users=$((total_users + 1))
|
||||
|
||||
if id "$web_user" &>/dev/null; then
|
||||
echo "📝 处理Web用户: $web_user"
|
||||
|
||||
# 获取用户当前组信息(安全的变量处理)
|
||||
current_groups=$(id -Gn "$web_user" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//')
|
||||
echo " 当前所属组: ${current_groups:-无}"
|
||||
|
||||
# 尝试将用户加入统一组(使用-a参数保留现有组,只添加新组)
|
||||
if usermod -a -G "$WEB_GROUP" "$web_user" 2>/dev/null; then
|
||||
echo " ✅ 成功将 $web_user 添加到统一组 $WEB_GROUP"
|
||||
success_count=$((success_count + 1))
|
||||
else
|
||||
echo " ⚠️ 无法将 $web_user 添加到统一组,尝试设置主组"
|
||||
|
||||
# 备用方案:设置主组
|
||||
if usermod -g "$WEB_GROUP" "$web_user" 2>/dev/null; then
|
||||
echo " ✅ 成功将 $web_user 主组设置为 $WEB_GROUP"
|
||||
success_count=$((success_count + 1))
|
||||
else
|
||||
echo " ❌ 无法配置 $web_user 的组权限"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "⚭ Web用户 $web_user 不存在,跳过"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "📊 用户配置汇总: $success_count/$total_users 个Web用户配置成功"
|
||||
|
||||
# 至少要有一个用户配置成功
|
||||
if [ $success_count -eq 0 ]; then
|
||||
echo "⚠️ 没有Web用户被成功配置,但继续执行"
|
||||
fi
|
||||
|
||||
echo "统一Web组配置完成"
|
||||
}
|
||||
|
||||
# 错误处理:如果配置失败,不要终止整个脚本
|
||||
configure_web_users || echo "⚠️ Web用户配置出现问题,但继续执行权限设置"
|
||||
|
||||
echo "当前用户: $(whoami)"
|
||||
echo "UID: $(id -u), GID: $(id -g)"
|
||||
|
||||
# 修复目录所有权和权限
|
||||
fix_directory_permissions() {
|
||||
local dir=$1
|
||||
echo "修复PHP目录权限: $dir"
|
||||
# 修复所有目录权限(使用统一Web组,最高效的权限管理)
|
||||
if [ -d "$APP_ROOT" ]; then
|
||||
# 重新获取最终的WEB_GROUP(可能已被修改)
|
||||
FINAL_WEB_GROUP=""
|
||||
|
||||
# 确保目录存在
|
||||
mkdir -p "$dir"
|
||||
|
||||
# 设置所有权
|
||||
chown -R www-data:www-data "$dir"
|
||||
|
||||
# 设置权限
|
||||
chmod -R 775 "$dir"
|
||||
|
||||
# 设置setgid权限
|
||||
chmod g+s "$dir"
|
||||
|
||||
# 尝试设置ACL(如果支持)
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
setfacl -dR -m u:www-data:rwx "$dir"
|
||||
# 首选:使用创建的webaccess组
|
||||
if getent group "webaccess" &>/dev/null; then
|
||||
FINAL_WEB_GROUP="webaccess"
|
||||
echo "🎯 使用创建的统一Web组: $FINAL_WEB_GROUP"
|
||||
# 备选:使用www-data组
|
||||
elif getent group "www-data" &>/dev/null; then
|
||||
FINAL_WEB_GROUP="www-data"
|
||||
echo "🔄 回退到www-data组: $FINAL_WEB_GROUP"
|
||||
# 最后:使用当前用户的组
|
||||
else
|
||||
CURRENT_USER=$(whoami)
|
||||
CURRENT_GROUP=$(id -gn "$CURRENT_USER")
|
||||
FINAL_WEB_GROUP="$CURRENT_GROUP"
|
||||
echo "🔧 使用当前用户组: $FINAL_WEB_GROUP"
|
||||
fi
|
||||
|
||||
# 最终验证
|
||||
if [ -z "$FINAL_WEB_GROUP" ]; then
|
||||
echo "❌ 无法确定有效的Web组,跳过权限设置"
|
||||
echo "=== 启动应用 ==="
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
WEB_GROUP="$FINAL_WEB_GROUP"
|
||||
WEB_GROUP_GID=$(getent group "$WEB_GROUP" | cut -d: -f3)
|
||||
echo "✅ 最终使用Web组: $WEB_GROUP (GID: $WEB_GROUP_GID)"
|
||||
echo "🔒 统一组权限模式:所有Web用户通过组继承权限"
|
||||
|
||||
# 设置所有权为统一Web组(增强错误处理)
|
||||
echo "📁 设置应用目录所有权为统一Web组"
|
||||
CURRENT_USER=$(whoami)
|
||||
|
||||
if chown -R $CURRENT_USER:$WEB_GROUP "$APP_ROOT" 2>/dev/null; then
|
||||
echo "✅ 所有权设置成功: $CURRENT_USER:$WEB_GROUP"
|
||||
else
|
||||
echo "⚠️ 所有权设置失败,尝试只设置组权限"
|
||||
chgrp -R "$WEB_GROUP" "$APP_ROOT" 2>/dev/null || echo "❌ 组权限设置也失败"
|
||||
fi
|
||||
|
||||
# 设置目录权限为775(组权限为rwx,所有组内用户都有完整权限)
|
||||
echo "🔐 设置目录权限775,文件权限664"
|
||||
|
||||
# 使用更安全的权限设置方式,避免权限被拒绝
|
||||
dir_count=0
|
||||
file_count=0
|
||||
|
||||
# 设置目录权限(兼容性更好的方式)
|
||||
if command -v find >/dev/null 2>&1; then
|
||||
dir_count=$(find "$APP_ROOT" -type d -exec chmod 775 {} \; 2>/dev/null | wc -l)
|
||||
file_count=$(find "$APP_ROOT" -type f -exec chmod 664 {} \; 2>/dev/null | wc -l)
|
||||
find "$APP_ROOT" -type d -exec chmod g+s {} \; 2>/dev/null
|
||||
else
|
||||
# 备用方案:使用简单的循环
|
||||
echo "find命令不可用,跳过批量权限设置"
|
||||
dir_count=0
|
||||
file_count=0
|
||||
fi
|
||||
|
||||
echo "📊 权限设置完成: $dir_count个目录, $file_count个文件"
|
||||
|
||||
echo "✅ 统一组权限设置完成,所有Web用户通过组获得权限"
|
||||
|
||||
# 设置ACL(如果支持,只需设置统一组)
|
||||
if command -v setfacl >/dev/null 2>&1; then
|
||||
echo "🔒 设置ACL权限(只需设置统一Web组)"
|
||||
|
||||
acl_success=0
|
||||
|
||||
# 只为统一Web组设置ACL权限(限制处理深度)
|
||||
if setfacl -R -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null; then
|
||||
echo " ✅ 设置组ACL权限成功"
|
||||
acl_success=$((acl_success + 1))
|
||||
else
|
||||
echo " ❌ 设置组ACL权限失败"
|
||||
fi
|
||||
|
||||
# 设置默认ACL权限(新创建的文件自动继承权限)
|
||||
if setfacl -dR -m g:$WEB_GROUP:rwx "$APP_ROOT" 2>/dev/null; then
|
||||
echo " ✅ 设置默认ACL权限成功"
|
||||
acl_success=$((acl_success + 1))
|
||||
else
|
||||
echo " ❌ 设置默认ACL权限失败"
|
||||
fi
|
||||
|
||||
if [ $acl_success -eq 2 ]; then
|
||||
echo "🎉 统一组ACL设置完成,所有组内用户自动获得权限"
|
||||
elif [ $acl_success -eq 1 ]; then
|
||||
echo "⚠️ ACL部分设置成功,建议检查文件系统ACL支持"
|
||||
else
|
||||
echo "❌ ACL设置完全失败,文件系统可能不支持ACL"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ ACL不支持,依赖传统权限模式"
|
||||
echo "✅ 775权限已足够,所有组内用户都有rwx权限"
|
||||
fi
|
||||
|
||||
find "$dir" -type d -exec chmod 775 {} \;
|
||||
find "$dir" -type f -exec chmod 775 {} \;
|
||||
find "$dir" -type d -exec chmod g+s {} \;
|
||||
find "$dir" -type f -exec chmod g+s {} \;
|
||||
|
||||
# 设置umask
|
||||
umask 0002
|
||||
|
||||
echo "✅ 应用目录权限修复完成"
|
||||
|
||||
echo "✅ $dir 权限设置完成, 目录权限: $(stat -c '%a %n' "$dir"), setgid权限: $(stat -c '%a %n' "$dir" | grep 's')"
|
||||
}
|
||||
|
||||
# 处理所有需要权限的目录
|
||||
directories=("runtime" "upload" "runtime/log" "runtime/cache" "runtime/temp")
|
||||
for dir in "${directories[@]}"; do
|
||||
fix_directory_permissions "$APP_ROOT/$dir"
|
||||
done
|
||||
|
||||
|
||||
# 验证权限
|
||||
echo "=== 权限验证 ==="
|
||||
echo "当前用户: $(whoami)"
|
||||
echo "当前UID: $(id -u), GID: $(id -g)"
|
||||
echo "当前umask: $(umask)"
|
||||
|
||||
# 验证www-data用户是否可以在runtime和upload目录下新建子目录
|
||||
|
||||
# 方法1:使用sudo
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
echo "使用sudo测试..."
|
||||
if sudo -u www-data mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then
|
||||
echo "✅ sudo: runtime目录创建子目录成功 [使用www-data用户]"
|
||||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||||
# 验证文件权限是否足够(测试统一组权限效果)
|
||||
echo "=== 验证统一组权限效果 ==="
|
||||
|
||||
# 查找测试文件的更可靠方法
|
||||
test_file=""
|
||||
|
||||
# 方法1: 查找index.html
|
||||
if [ -f "$APP_ROOT/index.html" ]; then
|
||||
test_file="$APP_ROOT/index.html"
|
||||
fi
|
||||
|
||||
# 方法2: 查找任意HTML文件(更安全的方式)
|
||||
if [ -z "$test_file" ]; then
|
||||
first_html=$(find "$APP_ROOT" -maxdepth 2 -name "*.html" -type f 2>/dev/null | head -1)
|
||||
if [ -n "$first_html" ] && [ -f "$first_html" ]; then
|
||||
test_file="$first_html"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 方法3: 查找index.php
|
||||
if [ -z "$test_file" ] && [ -f "$APP_ROOT/index.php" ]; then
|
||||
test_file="$APP_ROOT/index.php"
|
||||
fi
|
||||
|
||||
# 方法4: 创建专用测试文件(最安全的选择)
|
||||
if [ -z "$test_file" ]; then
|
||||
test_file="$APP_ROOT/.permission_test.html"
|
||||
echo "创建专用权限测试文件"
|
||||
cat > "$test_file" << 'EOF'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Permission Test</title></head>
|
||||
<body><h1>Web Server Permission Test File</h1></body>
|
||||
</html>
|
||||
EOF
|
||||
# 设置正确的权限
|
||||
chown $(whoami):"$WEB_GROUP" "$test_file" 2>/dev/null || true
|
||||
chmod 664 "$test_file"
|
||||
fi
|
||||
|
||||
# 执行权限测试
|
||||
if [ -f "$test_file" ]; then
|
||||
echo "使用测试文件: $test_file"
|
||||
echo "文件权限: $(stat -c '%a %n' "$test_file")"
|
||||
echo "文件所有者: $(stat -c '%U:%G' "$test_file")"
|
||||
|
||||
# 测试所有Web用户的权限(通过组权限)
|
||||
for test_user in "www-data" "www" "apache" "nginx"; do
|
||||
if id "$test_user" &>/dev/null; then
|
||||
echo "🔍 测试 $test_user 用户权限(通过组权限):"
|
||||
|
||||
# 显示用户组信息(安全的变量处理)
|
||||
user_groups=$(id -Gn "$test_user" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//')
|
||||
echo " 📋 所属组: ${user_groups:-无}"
|
||||
|
||||
# 测试读权限(安全:只读不修改)
|
||||
if su -s /bin/sh -c "cat '$test_file' >/dev/null 2>&1" "$test_user" 2>/dev/null; then
|
||||
echo " ✅ 读权限: 通过组权限可读"
|
||||
else
|
||||
echo " ❌ 读权限: 不可读"
|
||||
fi
|
||||
|
||||
# 测试写权限(使用临时文件,避免污染原文件)
|
||||
temp_test_file="${test_file}.write_test_${test_user}"
|
||||
if su -s /bin/sh -c "echo 'permission_test' > '$temp_test_file' 2>/dev/null" "$test_user" 2>/dev/null; then
|
||||
echo " ✅ 写权限: 通过组权限可写"
|
||||
rm -f "$temp_test_file" 2>/dev/null
|
||||
else
|
||||
echo " ❌ 写权限: 不可写"
|
||||
fi
|
||||
|
||||
# 测试目录创建权限(使用临时目录)
|
||||
temp_test_dir="${APP_ROOT}/.perm_test_${test_user}"
|
||||
if su -s /bin/sh -c "mkdir -p '$temp_test_dir' 2>/dev/null" "$test_user" 2>/dev/null; then
|
||||
echo " ✅ 创建目录: 通过组权限可创建"
|
||||
rm -rf "$temp_test_dir" 2>/dev/null
|
||||
else
|
||||
echo " ❌ 创建目录: 不可创建"
|
||||
fi
|
||||
|
||||
echo " 🔗 权限来源: 统一Web组 ($WEB_GROUP) 775权限"
|
||||
break # 只测试第一个可用的用户即可验证效果
|
||||
fi
|
||||
done
|
||||
|
||||
# 清理专用测试文件(如果是创建的)
|
||||
if echo "$test_file" | grep -q "\.permission_test\.html$"; then
|
||||
rm -f "$test_file" 2>/dev/null
|
||||
echo "🧹 已清理临时测试文件"
|
||||
fi
|
||||
else
|
||||
echo "❌ sudo: runtime目录创建子目录失败 [使用www-data用户]"
|
||||
echo "❌ 无法找到或创建测试文件,跳过权限验证"
|
||||
fi
|
||||
|
||||
# 显示统一组和用户状态
|
||||
echo "=== 统一Web组状态检查 ==="
|
||||
if getent group "$WEB_GROUP" &>/dev/null; then
|
||||
echo "✅ 统一Web组 '$WEB_GROUP' 存在"
|
||||
echo "组信息: $(getent group "$WEB_GROUP" 2>/dev/null || echo '获取失败')"
|
||||
|
||||
# 检查哪些用户在统一组中
|
||||
echo "统一组成员检查:"
|
||||
for web_user in "www-data" "www" "apache" "nginx"; do
|
||||
if id "$web_user" &>/dev/null; then
|
||||
if id -Gn "$web_user" | grep -q "$WEB_GROUP"; then
|
||||
echo "✅ $web_user 在统一组 '$WEB_GROUP' 中"
|
||||
else
|
||||
echo "❌ $web_user 不在统一组 '$WEB_GROUP' 中"
|
||||
fi
|
||||
else
|
||||
echo "❌ $web_user 用户不存在"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "❌ 统一Web组 '$WEB_GROUP' 不存在"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 方法2:使用su
|
||||
echo "使用su测试..."
|
||||
if su -s /bin/sh -c "mkdir -p $APP_ROOT/runtime/log/test_dir" www-data 2>/dev/null; then
|
||||
echo "✅ su: runtime目录创建子目录成功 [使用www-data用户]"
|
||||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||||
else
|
||||
echo "❌ su: runtime目录创建子目录失败 [使用www-data用户]"
|
||||
fi
|
||||
|
||||
# 方法3:使用runuser
|
||||
if command -v runuser >/dev/null 2>&1; then
|
||||
echo "使用runuser测试..."
|
||||
if runuser -u www-data -- mkdir -p $APP_ROOT/runtime/log/test_dir 2>/dev/null; then
|
||||
echo "✅ runuser: runtime目录创建子目录成功 [使用www-data用户]"
|
||||
rm -rf $APP_ROOT/runtime/log/test_dir
|
||||
else
|
||||
echo "❌ runuser: runtime目录创建子目录失败 [使用www-data用户]"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查www-data用户和组
|
||||
echo "检查www-data用户..."
|
||||
id www-data
|
||||
groups www-data
|
||||
|
||||
# 检查目录的实际权限
|
||||
echo "检查目录权限..."
|
||||
ls -ld $APP_ROOT/runtime/log
|
||||
ls -ld $APP_ROOT/runtime/cache
|
||||
ls -ld $APP_ROOT/runtime/temp
|
||||
ls -ld $APP_ROOT/upload
|
||||
|
||||
echo "=== 启动应用 ==="
|
||||
|
||||
# 执行原有的启动命令
|
||||
|
||||
@@ -6,13 +6,6 @@ logfile_backups=10
|
||||
loglevel=info
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:chmod]
|
||||
command=/bin/bash -c "while true; do chmod -R 775 /var/www/html/runtime/ /var/www/html/upload/ 2>/dev/null || true; sleep 30; done"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
[program:php-fpm]
|
||||
command=php-fpm
|
||||
autostart=true
|
||||
@@ -42,4 +35,19 @@ stderr_logfile=/var/log/supervisor/think-cron-error.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=10
|
||||
startsecs=3
|
||||
stopwaitsecs=10
|
||||
stopwaitsecs=10
|
||||
|
||||
[program:websocket-server]
|
||||
command=/bin/bash -c "if [ -f /var/www/html/ws_server.php ]; then php ./ws_server.php; else echo 'ws_server.php not found, skipping websocket server'; fi"
|
||||
workdir=/var/www/html
|
||||
autostart=true
|
||||
autorestart=false
|
||||
startretries=0
|
||||
stdout_logfile=/var/log/supervisor/websocket-server.log
|
||||
stdout_logfile_maxbytes=10MB
|
||||
stdout_logfile_backups=10
|
||||
stderr_logfile=/var/log/supervisor/websocket-server-error.log
|
||||
stderr_logfile_maxbytes=10MB
|
||||
stderr_logfile_backups=10
|
||||
startsecs=3
|
||||
stopwaitsecs=10
|
||||
|
||||
BIN
docker/php/websocat
Normal file
BIN
docker/php/websocat
Normal file
Binary file not shown.
15
docker/redis_data/.gitignore
vendored
15
docker/redis_data/.gitignore
vendored
@@ -1,10 +1,9 @@
|
||||
# 忽略目录下所有文件和子目录
|
||||
# 忽略所有文件
|
||||
*
|
||||
# 忽略所有子目录
|
||||
*/
|
||||
# 但不忽略 .gitkeep 文件
|
||||
!.gitkeep
|
||||
# 不忽略 .gitignore 文件自身
|
||||
|
||||
# 只保留指定的 .gitkeep 文件
|
||||
!.gitignore
|
||||
# 不忽略 development/.gitkeep 文件
|
||||
!development/.gitkeep
|
||||
!development/.gitkeep
|
||||
!test/.gitkeep
|
||||
!production/.gitkeep
|
||||
!staging/.gitkeep
|
||||
@@ -10,7 +10,7 @@ default_lang = zh-cn
|
||||
[DATABASE]
|
||||
TYPE = mysql
|
||||
HOSTNAME = db
|
||||
DATABASE = shop_dev
|
||||
DATABASE = shop_mallnew
|
||||
USERNAME = shop_mallnew
|
||||
PASSWORD = shop_mallnew
|
||||
HOSTPORT = 3306
|
||||
24
src/.env.test
Normal file
24
src/.env.test
Normal file
@@ -0,0 +1,24 @@
|
||||
APP_DEBUG = true
|
||||
APP_TRACE = true
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||
|
||||
[LANG]
|
||||
default_lang = zh-cn
|
||||
|
||||
[DATABASE]
|
||||
TYPE = mysql
|
||||
HOSTNAME = db
|
||||
DATABASE = shop_mallnew
|
||||
USERNAME = shop_mallnew
|
||||
PASSWORD = shop_mallnew
|
||||
HOSTPORT = 3306
|
||||
CHARSET = utf8mb4
|
||||
DEBUG = true
|
||||
|
||||
[REDIS]
|
||||
HOST = redis
|
||||
PORT = 6379
|
||||
PASSWORD = 'luckyshop123!@#'
|
||||
EXPIRY = 604800
|
||||
@@ -120,9 +120,6 @@ class Config extends BaseApi
|
||||
$config_model = new ConfigModel();
|
||||
$default_img = $config_model->getDefaultImg($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||
|
||||
// 企业微信配置
|
||||
$wxwork_config = $config_model->getWxworkConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||
|
||||
// 版权信息
|
||||
$copyright = $config_model->getCopyright($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||
$map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||
@@ -149,8 +146,7 @@ class Config extends BaseApi
|
||||
'servicer' => $servicer_info,
|
||||
'shop_info'=>$shop_info,
|
||||
'store_config' => $this->store_data[ 'config' ],
|
||||
'map_config' => $map_config,
|
||||
'wxwork_config' => $wxwork_config
|
||||
'map_config' => $map_config
|
||||
];
|
||||
if (!empty($this->store_data[ 'store_info' ])) {
|
||||
$res[ 'store_info' ] = $this->store_data[ 'store_info' ];
|
||||
|
||||
@@ -847,63 +847,6 @@ class Config extends BaseModel
|
||||
// return $data;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 设置企业微信配置
|
||||
* @param $data
|
||||
* @param int $site_id
|
||||
* @param string $app_module
|
||||
* @return array
|
||||
*/
|
||||
public function setWxworkConfig($data, $site_id = 1, $app_module = 'shop')
|
||||
{
|
||||
// 只要提供了Secret,就自动生成时间戳、随机字符串和签名
|
||||
if (!empty($data['secret'])) {
|
||||
$data['timestamp'] = time();
|
||||
|
||||
// 生成16位随机字符串
|
||||
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
$nonceStr = '';
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$nonceStr .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
|
||||
}
|
||||
$data['nonceStr'] = $nonceStr;
|
||||
|
||||
// 生成SHA1签名
|
||||
$string = 'secret=' . $data['secret'] . '×tamp=' . $data['timestamp'] . '&nonceStr=' . $data['nonceStr'];
|
||||
$data['signature'] = sha1($string);
|
||||
}
|
||||
|
||||
$config = new ConfigModel();
|
||||
$res = $config->setConfig($data, '企业微信配置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'WXWORK_CONFIG' ] ]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业微信配置
|
||||
* @param int $site_id
|
||||
* @param string $app_module
|
||||
* @return array
|
||||
*/
|
||||
public function getWxworkConfig($site_id = 1, $app_module = 'shop')
|
||||
{
|
||||
$config = new ConfigModel();
|
||||
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'WXWORK_CONFIG' ] ]);
|
||||
if (empty($res[ 'data' ][ 'value' ])) {
|
||||
$res[ 'data' ][ 'value' ] = [
|
||||
'corp_id' => '',
|
||||
'agent_id' => '',
|
||||
'secret' => '',
|
||||
'contact_id' => '',
|
||||
'contact_url' => '',
|
||||
'timestamp' => '',
|
||||
'nonceStr' => '',
|
||||
'signature' => '',
|
||||
'enabled' => false
|
||||
];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置商品编码设置
|
||||
* @param $data
|
||||
|
||||
@@ -210,30 +210,6 @@ class Config extends BaseShop
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信配置
|
||||
*/
|
||||
public function wxwork()
|
||||
{
|
||||
$config_model = new ConfigModel();
|
||||
if (request()->isJson()) {
|
||||
$data = [
|
||||
'corp_id' => input('corp_id', ''),
|
||||
'agent_id' => input('agent_id', ''),
|
||||
'secret' => input('secret', ''),
|
||||
'contact_id' => input('contact_id', ''),
|
||||
'contact_url' => input('contact_url', ''),
|
||||
'enabled' => input('enabled', 0)
|
||||
];
|
||||
$this->addLog('修改企业微信配置');
|
||||
return $config_model->setWxworkConfig($data, $this->site_id, $this->app_module);
|
||||
} else {
|
||||
$config_result = $config_model->getWxworkConfig($this->site_id, $this->app_module);
|
||||
$this->assign('wxwork_config', $config_result[ 'data' ][ 'value' ]);
|
||||
return $this->fetch('config/wxwork');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 域名跳转配置
|
||||
*/
|
||||
|
||||
@@ -1,514 +0,0 @@
|
||||
<style type="text/css">
|
||||
.inline-block{display: inline-block;}
|
||||
.wxwork-form .layui-form-item{margin-bottom: 20px;}
|
||||
.wxwork-form .layui-input-block{margin-left: 120px;}
|
||||
.wxwork-help{color: #999; font-size: 12px; margin-top: 5px;}
|
||||
.wxwork-required{color: #ff5722; margin-right: 4px;}
|
||||
.wxwork-guide{background: #f8f9fa; border-left: 3px solid #007bff; padding: 15px; margin-top: 10px; border-radius: 4px;}
|
||||
.wxwork-guide h4{margin: 0 0 10px 0; color: #007bff;}
|
||||
.wxwork-guide ol{margin: 0; padding-left: 20px;}
|
||||
.wxwork-guide li{margin-bottom: 8px;}
|
||||
.wxwork-code{background: #f1f3f4; padding: 2px 6px; border-radius: 3px; font-family: monospace; font-size: 12px;}
|
||||
.wxwork-field-required .layui-form-label{color: #333;}
|
||||
.wxwork-link{color: #007bff; text-decoration: none;}
|
||||
.wxwork-link:hover{text-decoration: underline;}
|
||||
.wxwork-guide-toggle{margin-top: 30px;}
|
||||
.wxwork-guide-toggle .guide-toggle-btn{width: 100%; padding: 12px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; cursor: pointer; transition: all 0.3s; display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 14px; color: #333;}
|
||||
.wxwork-guide-toggle .guide-toggle-btn:hover{background: #e9ecef; border-color: #007bff;}
|
||||
.wxwork-guide-toggle .guide-toggle-btn.active{background: #007bff; color: white; border-color: #007bff;}
|
||||
.wxwork-guide-toggle .guide-content{margin-top: 15px; background: #f8f9fa; border-left: 3px solid #007bff; padding: 15px; border-radius: 4px; display: none;}
|
||||
.wxwork-guide-toggle .guide-content.show{display: block;}
|
||||
.guide-toggle-icon{transition: transform 0.3s;}
|
||||
.guide-toggle-icon.rotate{transform: rotate(180deg);}
|
||||
.password-wrapper{position: relative;}
|
||||
.password-toggle{position: absolute; right: 10px; top: 50%; transform: translateY(-50%); cursor: pointer; color: #999; font-size: 16px; user-select: none;}
|
||||
.password-toggle:hover{color: #007bff;}
|
||||
</style>
|
||||
|
||||
<div class="layui-form form-wrap wxwork-form">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">启用状态:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="enabled" value="1" lay-skin="switch" {if condition="$wxwork_config.enabled == 1" }checked {/if} lay-title="启用|关闭"/>
|
||||
</div>
|
||||
<div class="wxwork-help">开启后,企业微信相关功能将可用</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item wxwork-field-required">
|
||||
<label class="layui-form-label"><span class="wxwork-required">*</span>企业ID:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="corp_id" required autocomplete="off" value="{$wxwork_config.corp_id ?? ''}" class="layui-input len-long" placeholder="wwxxxxxxxxxxxx">
|
||||
</div>
|
||||
<div class="wxwork-help">
|
||||
<p><strong>获取方式</strong>:企业微信管理后台 → 我的企业 → 企业信息 → 企业ID</p>
|
||||
<p><strong>格式</strong>:通常以 "ww" 开头的18位字符串</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item wxwork-field-required">
|
||||
<label class="layui-form-label"><span class="wxwork-required">*</span>应用ID:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="agent_id" required autocomplete="off" value="{$wxwork_config.agent_id ?? ''}" class="layui-input len-long" placeholder="1000001">
|
||||
</div>
|
||||
<div class="wxwork-help">
|
||||
<p><strong>获取方式</strong>:应用管理 → 选择应用 → 查看应用详情 → AgentId</p>
|
||||
<p><strong>格式</strong>:数字字符串,如 1000001</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item wxwork-field-required">
|
||||
<label class="layui-form-label"><span class="wxwork-required">*</span>应用Secret:</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="password-wrapper">
|
||||
<input type="password" name="secret" id="secret-input" required autocomplete="off" value="{$wxwork_config.secret ?? ''}" class="layui-input len-long" placeholder="请输入应用Secret">
|
||||
<span class="password-toggle" onclick="togglePassword()">👁️</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wxwork-help" style="color: #ff5722;">
|
||||
<p><strong>获取方式</strong>:企业微信管理后台 → 应用管理 → 选择应用 → 查看Secret</p>
|
||||
<p><strong>说明</strong>:<strong style="color: #ff5722;">系统必需</strong>:用于自动生成签名,请妥善保管</p>
|
||||
<p><strong>安全提示</strong>:Secret仅在创建时可见,请立即复制保存</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item wxwork-field-required">
|
||||
<label class="layui-form-label"><span class="wxwork-required">*</span>客服ID:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="contact_id" required autocomplete="off" value="{$wxwork_config.contact_id ?? ''}" class="layui-input len-long" placeholder="kfc_xxxxx">
|
||||
</div>
|
||||
<div class="wxwork-help" style="color: #ff5722;">
|
||||
<p><strong>获取方式</strong>:企业微信管理后台 → 应用管理 → 客服 → 联系我</p>
|
||||
<p><strong>说明</strong>:<strong style="color: #ff5722;">系统必需功能</strong>,用于企业微信客服对接</p>
|
||||
<p><strong>格式</strong>:通常以 "kfc_" 开头的字符串</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item wxwork-field-required">
|
||||
<label class="layui-form-label"><span class="wxwork-required">*</span>活码链接:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="contact_url" required autocomplete="off" value="{$wxwork_config.contact_url ?? ''}" class="layui-input len-long" placeholder="https://work.weixin.qq.com/kf/...">
|
||||
</div>
|
||||
<div class="wxwork-help" style="color: #ff5722;">
|
||||
<p><strong>获取方式</strong>:企业微信管理后台 → 客服 → 联系我 → 生成活码</p>
|
||||
<p><strong>说明</strong>:<strong style="color: #ff5722;">系统必需功能</strong>,客服活码的完整链接地址</p>
|
||||
<p><strong>格式</strong>:完整的HTTPS链接,如 https://work.weixin.qq.com/kf/xxxx</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 隐藏的自动生成字段 -->
|
||||
<input type="hidden" name="timestamp" value="{$wxwork_config.timestamp ?? ''}">
|
||||
<input type="hidden" name="nonceStr" value="{$wxwork_config.nonceStr ?? ''}">
|
||||
<input type="hidden" name="signature" value="{$wxwork_config.signature ?? ''}">
|
||||
|
||||
<!-- 系统状态显示区域 -->
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<div class="wxwork-status-panel" style="border: 1px solid #e6e6e6; border-radius: 4px; padding: 15px; background: #fafafa; display: flex; flex-direction: column;">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span><strong>配置完整性:</strong></span>
|
||||
<span id="config-completeness" style="color: #999;">检查中...</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span><strong>签名生成状态:</strong></span>
|
||||
<span id="signature-status" style="color: #999;">点击保存配置,将自动生成</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span><strong>时间戳:</strong></span>
|
||||
<span id="timestamp-value" style="color: #666;">{if condition="$wxwork_config.timestamp"}{$wxwork_config.timestamp}{else /}未生成{/if}</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span><strong>随机字符串:</strong></span>
|
||||
<span id="nonce-str-value" style="color: #666;">{if condition="$wxwork_config.nonceStr"}{$wxwork_config.nonceStr}{else /}未生成{/if}</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span><strong>签名:</strong></span>
|
||||
<span id="signature-value" style="color: #52c41a; font-family: monospace; font-size: 12px; word-break: break-all;">{if condition="$wxwork_config.signature"}{$wxwork_config.signature}{else /}未生成{/if}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span><strong>最后更新时间:</strong></span>
|
||||
<span id="last-update-time" style="color: #666;">{if condition="$wxwork_config.timestamp"}<?php echo date('Y-m-d H:i:s', $wxwork_config['timestamp']); ?>{else /}从未生成{/if}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wxwork-help">
|
||||
<p><strong>说明</strong>:系统将在保存配置时自动生成时间戳、随机字符串和签名</p>
|
||||
<p><strong>生成规则</strong>:基于Secret使用SHA1算法生成,用于企业微信API验证</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存配置</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary" onclick="window.location.reload()">重置</button>
|
||||
<button type="button" class="layui-btn layui-btn-normal" onclick="window.open('https://work.weixin.qq.com/', '_blank')">企业微信管理后台</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 获取指南 -->
|
||||
<div class="wxwork-guide-toggle">
|
||||
<div class="guide-toggle-btn" onclick="toggleGuide()">
|
||||
<span>📋 企业微信配置获取指南</span>
|
||||
<span class="guide-toggle-icon">▼</span>
|
||||
</div>
|
||||
<div class="guide-content">
|
||||
<p style="color: #ff5722; font-weight: bold; margin-bottom: 15px;">⚠️ 注意:客服功能为系统必需功能,必须正确配置相关参数</p>
|
||||
<ol>
|
||||
<li><strong>登录企业微信管理后台</strong>:<a href="https://work.weixin.qq.com/" target="_blank" class="wxwork-link">https://work.weixin.qq.com/</a></li>
|
||||
<li><strong>获取企业ID</strong>:进入「我的企业」→「企业信息」→「企业ID」</li>
|
||||
<li><strong>创建应用</strong>:进入「应用管理」→「应用」→「创建应用」→「自建」</li>
|
||||
<li><strong>获取应用ID</strong>:创建完成后进入应用详情页,查看 <span class="wxwork-code">AgentId</span></li>
|
||||
<li><strong>获取Secret</strong>:在应用详情页查看 <span class="wxwork-code">Secret</span>(用于生成签名)</li>
|
||||
<li><strong>配置可信域名</strong>:在应用详情页设置可信域名,用于JS接口调用</li>
|
||||
<li><strong>开启客服功能</strong>:<strong style="color: #ff5722;">(必需)</strong>进入「应用管理」→「客服」→「联系我」→ 开启服务</li>
|
||||
<li><strong>获取客服参数</strong>:在客服页面获取客服ID和活码链接</li>
|
||||
</ol>
|
||||
|
||||
<h5 style="margin-top: 15px; color: #007bff;">🔧 参数获取方式说明</h5>
|
||||
<table style="width: 100%; border-collapse: collapse; margin-top: 10px;">
|
||||
<tr style="background: #f8f9fa;">
|
||||
<th style="border: 1px solid #dee2e6; padding: 8px; text-align: left;">参数名称</th>
|
||||
<th style="border: 1px solid #dee2e6; padding: 8px; text-align: left;">获取方式</th>
|
||||
<th style="border: 1px solid #dee2e6; padding: 8px; text-align: left;">说明</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业ID</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业微信管理后台 → 我的企业 → 企业信息 → 企业ID</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业唯一标识</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">应用ID</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业微信管理后台 → 应用管理 → 选择应用 → 查看应用详情 → AgentId</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">应用的AgentId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">应用Secret</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业微信管理后台 → 应用管理 → 选择应用 → 查看Secret</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px; color: #ff5722;"><strong>必需</strong>:用于生成签名的密钥</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">客服ID</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业微信管理后台 → 应用管理 → 客服 → 联系我</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px; color: #ff5722;"><strong>必需</strong>:客服功能的唯一标识</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">活码链接</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">企业微信管理后台 → 客服 → 联系我 → 生成活码</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px; color: #ff5722;"><strong>必需</strong>:客服活码的完整链接</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">时间戳</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;"><span class="wxwork-code">本系统自动生成</span></td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">Unix时间戳,无需手动填写</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">随机字符串</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;"><span class="wxwork-code">本系统自动生成</span></td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">16位随机字符,无需手动填写</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">签名</td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;"><span class="wxwork-code">本系统自动生成</span></td>
|
||||
<td style="border: 1px solid #dee2e6; padding: 8px;">SHA1签名,无需手动填写</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['form', 'layer'], function() {
|
||||
var form = layui.form,
|
||||
layer = layui.layer,
|
||||
repeat_flag = false; //防重复标识
|
||||
|
||||
form.render();
|
||||
|
||||
|
||||
|
||||
// 启用状态切换时的验证
|
||||
$('input[name="enabled"]').on('change', function() {
|
||||
if($(this).is(':checked')) {
|
||||
var corpId = $('input[name="corp_id"]').val().trim();
|
||||
var agentId = $('input[name="agent_id"]').val().trim();
|
||||
var secret = $('input[name="secret"]').val().trim();
|
||||
var contactId = $('input[name="contact_id"]').val().trim();
|
||||
var contactUrl = $('input[name="contact_url"]').val().trim();
|
||||
|
||||
if(!corpId) {
|
||||
layer.msg('请先填写企业ID(必填项)', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="corp_id"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!agentId) {
|
||||
layer.msg('请先填写应用ID(必填项)', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="agent_id"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!secret) {
|
||||
layer.msg('请先填写应用Secret(系统必需)', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="secret"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!contactId) {
|
||||
layer.msg('请先填写客服ID(系统必需功能)', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="contact_id"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!contactUrl) {
|
||||
layer.msg('请先填写活码链接(系统必需功能)', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="contact_url"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// 企业ID格式验证
|
||||
if(!/^ww[a-zA-Z0-9]{16}$/.test(corpId)) {
|
||||
layer.msg('企业ID格式不正确,应为ww开头的18位字符', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="corp_id"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用ID格式验证
|
||||
if(!/^\d+$/.test(agentId)) {
|
||||
layer.msg('应用ID格式不正确,应为纯数字', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="agent_id"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Secret格式验证
|
||||
if(secret.length < 10) {
|
||||
layer.msg('Secret格式不正确,长度至少10位字符', {icon: 2});
|
||||
$(this).prop('checked', false);
|
||||
form.render();
|
||||
$('input[name="secret"]').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
layer.msg('配置验证通过!企业微信功能已启用,系统将自动生成签名', {icon: 1});
|
||||
}
|
||||
});
|
||||
|
||||
// 更新配置完整性状态
|
||||
function updateConfigStatus() {
|
||||
var corpId = $('input[name="corp_id"]').val().trim();
|
||||
var agentId = $('input[name="agent_id"]').val().trim();
|
||||
var secret = $('input[name="secret"]').val().trim();
|
||||
var contactId = $('input[name="contact_id"]').val().trim();
|
||||
var contactUrl = $('input[name="contact_url"]').val().trim();
|
||||
var timestamp = $('input[name="timestamp"]').val();
|
||||
var nonceStr = $('input[name="nonceStr"]').val();
|
||||
var signature = $('input[name="signature"]').val();
|
||||
|
||||
// 更新配置完整性
|
||||
var requiredFields = [corpId, agentId, secret, contactId, contactUrl];
|
||||
var filledCount = requiredFields.filter(function(field) { return field.length > 0; }).length;
|
||||
var completeness = Math.round((filledCount / requiredFields.length) * 100);
|
||||
|
||||
var completenessElement = $('#config-completeness');
|
||||
if (completeness === 100) {
|
||||
completenessElement.text('完整 (100%)').css('color', '#52c41a');
|
||||
} else {
|
||||
completenessElement.text('不完整 (' + completeness + '%)').css('color', '#ff7875');
|
||||
}
|
||||
|
||||
// 更新签名状态和相关信息
|
||||
var signatureElement = $('#signature-status');
|
||||
var timestampElement = $('#timestamp-value');
|
||||
var nonceStrElement = $('#nonce-str-value');
|
||||
var signatureValueElement = $('#signature-value');
|
||||
|
||||
if (signature && timestamp) {
|
||||
// 显示已存在的签名信息
|
||||
signatureElement.text('已生成').css('color', '#52c41a');
|
||||
timestampElement.text(timestamp).css('color', '#52c41a');
|
||||
nonceStrElement.text(nonceStr || '未生成').css('color', '#52c41a');
|
||||
signatureValueElement.text(signature).css('color', '#52c41a');
|
||||
} else {
|
||||
// 显示生成提示
|
||||
if (completeness === 100) {
|
||||
signatureElement.text('配置完整,点击保存将生成').css('color', '#1890ff');
|
||||
} else {
|
||||
signatureElement.text('请完善必填配置信息').css('color', '#ff7875');
|
||||
}
|
||||
timestampElement.text('未生成').css('color', '#999');
|
||||
nonceStrElement.text('未生成').css('color', '#999');
|
||||
signatureValueElement.text('未生成').css('color', '#999');
|
||||
}
|
||||
}
|
||||
|
||||
// 监听所有输入框变化
|
||||
$('input[name="corp_id"], input[name="agent_id"], input[name="secret"], input[name="contact_id"], input[name="contact_url"]').on('input blur', function() {
|
||||
updateConfigStatus();
|
||||
});
|
||||
|
||||
// 初始化状态
|
||||
updateConfigStatus();
|
||||
|
||||
// 表单提交前的必填项验证
|
||||
form.on('submit(save)', function(data) {
|
||||
var corpId = data.field.corp_id.trim();
|
||||
var agentId = data.field.agent_id.trim();
|
||||
var secret = data.field.secret.trim();
|
||||
var contactId = data.field.contact_id.trim();
|
||||
var contactUrl = data.field.contact_url.trim();
|
||||
|
||||
// 验证企业ID
|
||||
if(!corpId) {
|
||||
layer.msg('企业ID为必填项', {icon: 2});
|
||||
$('input[name="corp_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证应用ID
|
||||
if(!agentId) {
|
||||
layer.msg('应用ID为必填项', {icon: 2});
|
||||
$('input[name="agent_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证Secret(必需)
|
||||
if(!secret) {
|
||||
layer.msg('应用Secret为系统必需参数,必须填写', {icon: 2});
|
||||
$('input[name="secret"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证客服ID(必需)
|
||||
if(!contactId) {
|
||||
layer.msg('客服ID为系统必需功能,必须填写', {icon: 2});
|
||||
$('input[name="contact_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证活码链接(必需)
|
||||
if(!contactUrl) {
|
||||
layer.msg('活码链接为系统必需功能,必须填写', {icon: 2});
|
||||
$('input[name="contact_url"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 企业ID格式验证
|
||||
if(!/^ww[a-zA-Z0-9]{16}$/.test(corpId)) {
|
||||
layer.msg('企业ID格式不正确,应为ww开头的18位字符', {icon: 2});
|
||||
$('input[name="corp_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 应用ID格式验证
|
||||
if(!/^\d+$/.test(agentId)) {
|
||||
layer.msg('应用ID格式不正确,应为纯数字', {icon: 2});
|
||||
$('input[name="agent_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Secret格式验证
|
||||
if(secret.length < 10) {
|
||||
layer.msg('Secret格式不正确,长度至少10位字符', {icon: 2});
|
||||
$('input[name="secret"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 客服ID格式验证
|
||||
if(!/^kfc_[a-zA-Z0-9]+$/.test(contactId)) {
|
||||
layer.msg('客服ID格式不正确,应以kfc_开头', {icon: 2});
|
||||
$('input[name="contact_id"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 活码链接格式验证
|
||||
if(!/^https:\/\/work\.weixin\.qq\.com\/kf\//.test(contactUrl)) {
|
||||
layer.msg('活码链接格式不正确,应为 https://work.weixin.qq.com/kf/... 格式', {icon: 2});
|
||||
$('input[name="contact_url"]').focus();
|
||||
repeat_flag = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 继续执行原有的AJAX提交逻辑
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
// 开关值处理
|
||||
data.field.enabled = data.field.enabled ? 1 : 0;
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("shop/config/wxwork"),
|
||||
data: data.field,
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res){
|
||||
if(res.code == 0){
|
||||
layer.msg('企业微信配置保存成功!系统已自动生成签名和时间戳', {icon: 1});
|
||||
// 刷新页面以显示更新后的状态
|
||||
setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 1500);
|
||||
}else{
|
||||
layer.msg(res.message, {icon: 2});
|
||||
}
|
||||
repeat_flag = false;
|
||||
},
|
||||
error: function(){
|
||||
layer.msg('服务器错误', {icon: 2});
|
||||
repeat_flag = false;
|
||||
}
|
||||
});
|
||||
return false; // 阻止默认提交
|
||||
});
|
||||
});
|
||||
|
||||
// 切换密码显示/隐藏
|
||||
function togglePassword() {
|
||||
var secretInput = $('#secret-input');
|
||||
var toggleBtn = $('.password-toggle');
|
||||
|
||||
if (secretInput.attr('type') === 'password') {
|
||||
secretInput.attr('type', 'text');
|
||||
toggleBtn.text('🙈');
|
||||
} else {
|
||||
secretInput.attr('type', 'password');
|
||||
toggleBtn.text('👁️');
|
||||
}
|
||||
}
|
||||
|
||||
// 切换指南显示/隐藏
|
||||
function toggleGuide() {
|
||||
var btn = $('.guide-toggle-btn');
|
||||
var content = $('.guide-content');
|
||||
var icon = $('.guide-toggle-icon');
|
||||
|
||||
if (content.hasClass('show')) {
|
||||
content.removeClass('show');
|
||||
btn.removeClass('active');
|
||||
icon.removeClass('rotate');
|
||||
} else {
|
||||
content.addClass('show');
|
||||
btn.addClass('active');
|
||||
icon.addClass('rotate');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,9 +1,5 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<div class="single-filter-box top">
|
||||
<div class="single-filter-box">
|
||||
<div class="layui-form">
|
||||
<div class="layui-input-inline">
|
||||
<label class="layui-form-label">发送状态:</label>
|
||||
@@ -46,7 +42,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
layui.use(['form', 'laytpl'], function() {
|
||||
var table,
|
||||
@@ -159,7 +154,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>通知内容</td>
|
||||
<td colspan="3">{{d.content}}</td>
|
||||
<td colspan="3">{{d.content}}{{d.var_parse}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>返回结果</td>
|
||||
|
||||
@@ -68,12 +68,11 @@ if ($appEnv) {
|
||||
if (is_file($envFile)) {
|
||||
$app->env->load($envFile);
|
||||
}
|
||||
} else {
|
||||
echo "⚠️ 警告:未设置APP_ENV环境变量,默认使用local环境。\n";
|
||||
// 3. 为了兼容性,如果存在.env.local也加载(优先级最高)
|
||||
if (is_file(__DIR__ . '/.env.local')) {
|
||||
$app->env->load(__DIR__ . '/.env.local');
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 为了兼容性,如果存在.env.local也加载(优先级最高)
|
||||
if (is_file(__DIR__ . '/.env.local')) {
|
||||
$app->env->load(__DIR__ . '/.env.local');
|
||||
}
|
||||
|
||||
// 执行HTTP应用并响应
|
||||
|
||||
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GDEFdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GDEFdata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GPOSdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GPOSdata.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[[{"1613":0,"1616":1,"1621":2}],[{"1557":0,"1611":1,"1612":2,"1614":3,"1615":4,"1617":5,"1618":6,"1619":7,"1620":8,"1623":9,"1626":10,"1648":11,"57990":12,"57991":13,"57992":14,"57993":15,"57994":16,"57995":17,"57996":18,"57997":19}],[{"3768":0,"3769":1}],[{"3784":0,"3785":1,"3786":2,"3787":3,"3788":4,"3789":5}],[{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"825":22,"826":23,"827":24,"828":25,"839":26,"840":27,"841":28,"845":29,"846":30,"851":31,"858":32},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"829":18,"831":19,"832":20,"833":21,"834":22,"836":23,"838":24,"842":25,"843":26,"844":27,"849":28,"850":29,"855":30,"7620":31,"7621":32,"7622":33,"7623":34,"7624":35,"7625":36,"8400":37,"8401":38,"8406":39,"8407":40,"8411":41,"8412":42,"8417":43,"57895":44,"57896":45,"57897":46,"57898":47,"57899":48,"57900":49,"57901":50,"57902":51,"57903":52,"57904":53,"57905":54,"58088":55}],[{"1456":0,"1457":1,"1458":2,"1459":3,"1460":4,"1461":5,"1462":6,"1463":7,"1464":8,"1467":9,"1469":10,"1479":11,"1613":12,"1616":13,"1621":14}],[{"1456":0,"1457":1,"1458":2,"1459":3,"1460":4,"1461":5,"1462":6,"1463":7,"1464":8,"1467":9,"1469":10,"1479":11,"1613":12,"1616":13,"1621":14,"2034":15}],[{"1468":0}],[{"1471":0,"1557":1,"1611":2,"1612":3,"1614":4,"1615":5,"1617":6,"1618":7,"1619":8,"1620":9,"1623":10,"1626":11,"1648":12,"64286":13,"57990":14,"57991":15,"57992":16,"57993":17,"57994":18,"57995":19,"57996":20,"57997":21}],[{"1471":0,"1557":1,"1611":2,"1612":3,"1614":4,"1615":5,"1617":6,"1618":7,"1619":8,"1620":9,"1623":10,"1626":11,"1648":12,"2027":13,"2028":14,"2029":15,"2030":16,"2031":17,"2032":18,"2033":19,"2035":20,"64286":21,"57990":22,"57991":23,"57992":24,"57993":25,"57994":26,"57995":27,"57996":28,"57997":29}],[{"3768":0,"3769":1,"3772":2}],[{"3761":0,"3764":1,"3765":2,"3766":3,"3767":4,"3771":5,"3784":6,"3785":7,"3786":8,"3787":9,"3788":10,"3789":11}],[{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34}],[{"65057":0,"65059":1},{"768":0,"769":1},{"807":0},{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"786":18,"787":19,"788":20,"829":21,"830":22,"831":23,"832":24,"833":25,"834":26,"836":27,"838":28,"842":29,"843":30,"844":31,"849":32,"850":33,"855":34,"1155":35,"1156":36,"1157":37,"1158":38,"1159":39,"7620":40,"7621":41,"7622":42,"7623":43,"7624":44,"7625":45,"8400":46,"8401":47,"8406":48,"8407":49,"8411":50,"8412":51,"8417":52,"57895":53,"57896":54,"57897":55,"57898":56,"57899":57,"57900":58,"57901":59,"57902":60,"57903":61,"57904":62,"57905":63,"58088":64},{"808":0}],[{"45":0,"65":1,"66":2,"67":3,"68":4,"70":5,"71":6,"72":7,"74":8,"75":9,"76":10,"79":11,"80":12,"81":13,"82":14,"83":15,"84":16,"85":17,"86":18,"87":19,"88":20,"89":21,"90":22,"101":23,"102":24,"107":25,"110":26,"111":27,"114":28,"118":29,"119":30,"120":31,"121":32,"171":33,"187":34,"192":35,"193":36,"194":37,"195":38,"196":39,"198":40,"199":41,"208":42,"210":43,"211":44,"212":45,"213":46,"214":47,"217":48,"218":49,"219":50,"220":51,"221":52,"222":53,"223":54,"232":55,"233":56,"234":57,"235":58,"240":59,"241":60,"242":61,"243":62,"244":63,"245":64,"246":65,"253":66,"255":67,"256":68,"258":69,"260":70,"262":71,"268":72,"270":73,"272":74,"283":75,"286":76,"313":77,"317":78,"320":79,"328":80,"340":81,"341":82,"344":83,"345":84,"350":85,"352":86,"356":87,"366":88,"376":89,"381":90,"8208":91,"8220":92,"8222":93,"42788":94,"42816":95,"42817":96}],[{"61185":0,"61186":1,"61187":2,"61188":3,"61189":4,"61191":5,"61192":6,"61193":7,"61194":8,"61195":9,"61197":10,"61198":11,"61199":12,"61200":13,"61201":14,"61203":15,"61204":16,"61205":17,"61206":18,"61207":19}]]
|
||||
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.DFLT.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.DFLT.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.KUR .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.KUR .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.SND .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.SND .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.URD .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.arab.URD .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.nko .DFLT.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUB.nko .DFLT.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rtlSUB":{"007CA":{"1":"0E28E","3":"0E28F","2":"0E290"},"007CB":{"1":"0E291","3":"0E292","2":"0E293"},"007CC":{"1":"0E294","3":"0E295","2":"0E296"},"007CD":{"1":"0E297","3":"0E298","2":"0E299"},"007CE":{"1":"0E29A","3":"0E29B","2":"0E29C"},"007CF":{"1":"0E29D","3":"0E29E","2":"0E29F"},"007D0":{"1":"0E2A0","3":"0E2A1","2":"0E2A2"},"007D1":{"1":"0E2A3","3":"0E2A4","2":"0E2A5"},"007D2":{"1":"0E2A6","3":"0E2A7","2":"0E2A8"},"007D3":{"1":"0E2A9","3":"0E2AA","2":"0E2AB"},"007D4":{"1":"0E2AC","3":"0E2AD","2":"0E2AE"},"007D5":{"1":"0E2AF","3":"0E2B0","2":"0E2B1"},"007D6":{"1":"0E2B2","3":"0E2B3","2":"0E2B4"},"007D7":{"1":"0E2B5","3":"0E2B6","2":"0E2B7"},"007D8":{"1":"0E2B8","3":"0E2B9","2":"0E2BA"},"007D9":{"1":"0E2BB","3":"0E2BC","2":"0E2BD"},"007DA":{"1":"0E2BE","3":"0E2BF","2":"0E2C0"},"007DB":{"1":"0E2C1","3":"0E2C2","2":"0E2C3"},"007DC":{"1":"0E2C4","3":"0E2C5","2":"0E2C6"},"007DD":{"1":"0E2C7","3":"0E2C8","2":"0E2C9"},"007DE":{"1":"0E2CA","3":"0E2CB","2":"0E2CC"},"007DF":{"1":"0E2CD","3":"0E2CE","2":"0E2CF"},"007E0":{"1":"0E2D0","3":"0E2D1","2":"0E2D2"},"007E1":{"1":"0E2D3","3":"0E2D4","2":"0E2D5"},"007E2":{"1":"0E2D6","3":"0E2D7","2":"0E2D8"},"007E3":{"1":"0E2D9","3":"0E2DA","2":"0E2DB"},"007E4":{"1":"0E2DC","3":"0E2DD","2":"0E2DE"},"007E5":{"1":"0E2DF","3":"0E2E0","2":"0E2E1"},"007E6":{"1":"0E2E2","3":"0E2E3","2":"0E2E4"},"007E7":{"1":"0E2E5","3":"0E2E6","2":"0E2E7"}},"finals":"0E28E 0E291 0E294 0E297 0E29A 0E29D 0E2A0 0E2A3 0E2A6 0E2A9 0E2AC 0E2AF 0E2B2 0E2B5 0E2B8 0E2BB 0E2BE 0E2C1 0E2C4 0E2C7 0E2CA 0E2CD 0E2D0 0E2D3 0E2D6 0E2D9 0E2DC 0E2DF 0E2E2 0E2E5 ","rphf":[],"half":[],"pref":[],"blwf":[],"pstf":[]}
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUBGPOStables.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUBGPOStables.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUBdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.GSUBdata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.cw.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.cw.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.cw127.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.cw127.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rangeid":122,"prevcid":126,"prevwidth":754,"interval":false,"range":{"32":[286,360,414,754,572,855,702,247],"40":{"0":351,"1":351,"interval":true},"42":[450,754,286,325,286,303],"48":{"0":572,"1":572,"interval":true,"2":572,"3":572,"4":572,"5":572,"6":572,"7":572,"8":572,"9":572},"58":{"0":303,"1":303,"interval":true},"60":{"0":754,"1":754,"interval":true,"2":754},"63":[478,900,615,617,628,693,568,518,697,677],"73":{"0":265,"1":265,"interval":true},"75":[590,501,776,673,708,542,708,625,571,549,659,615,890,616,549,616,351,303,351,754],"95":{"0":450,"1":450,"interval":true},"97":[551,571,495,571,554,316,571,570],"105":{"0":250,"1":250,"interval":true},"107":[521,250,876,570,550],"112":{"0":571,"1":571,"interval":true},"114":[370,469,353,570,532,736],"120":{"0":532,"1":532,"interval":true},"122":[472,572,303,572,754]}}
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.gid.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.gid.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.mtx.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensed.mtx.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GDEFdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GDEFdata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GPOSdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GPOSdata.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[[{"1613":0,"1616":1,"1621":2}],[{"1557":0,"1611":1,"1612":2,"1614":3,"1615":4,"1617":5,"1618":6,"1619":7,"1620":8,"1623":9,"1626":10,"1648":11,"57974":12,"57975":13,"57976":14,"57977":15,"57978":16,"57979":17,"57980":18,"57981":19}],[{"3768":0,"3769":1}],[{"3784":0,"3785":1,"3786":2,"3787":3,"3788":4,"3789":5}],[{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"829":18,"831":19,"832":20,"833":21,"834":22,"836":23,"838":24,"842":25,"843":26,"844":27,"849":28,"850":29,"855":30,"7620":31,"7621":32,"7622":33,"7623":34,"7624":35,"7625":36,"8400":37,"8401":38,"8406":39,"8407":40,"8411":41,"8412":42,"8417":43,"57879":44,"57880":45,"57881":46,"57882":47,"57883":48,"57884":49,"57885":50,"57886":51,"57887":52,"57888":53,"57926":54,"58072":55}],[{"1456":0,"1457":1,"1458":2,"1459":3,"1460":4,"1461":5,"1462":6,"1463":7,"1464":8,"1467":9,"1469":10,"1479":11,"1613":12,"1616":13,"1621":14}],[{"1456":0,"1457":1,"1458":2,"1459":3,"1460":4,"1461":5,"1462":6,"1463":7,"1464":8,"1467":9,"1469":10,"1479":11,"1613":12,"1616":13,"1621":14,"2034":15}],[{"1468":0}],[{"1465":0,"1471":1,"1557":2,"1611":3,"1612":4,"1614":5,"1615":6,"1617":7,"1618":8,"1619":9,"1620":10,"1623":11,"1626":12,"1648":13,"64286":14,"57974":15,"57975":16,"57976":17,"57977":18,"57978":19,"57979":20,"57980":21,"57981":22}],[{"1465":0,"1471":1,"1557":2,"1611":3,"1612":4,"1614":5,"1615":6,"1617":7,"1618":8,"1619":9,"1620":10,"1623":11,"1626":12,"1648":13,"2027":14,"2028":15,"2029":16,"2030":17,"2031":18,"2032":19,"2033":20,"2035":21,"64286":22,"57974":23,"57975":24,"57976":25,"57977":26,"57978":27,"57979":28,"57980":29,"57981":30}],[{"3768":0,"3769":1,"3772":2}],[{"3761":0,"3764":1,"3765":2,"3766":3,"3767":4,"3771":5,"3784":6,"3785":7,"3786":8,"3787":9,"3788":10,"3789":11}],[{"65057":0,"65059":1},{"768":0,"769":1},{"807":0},{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"786":18,"787":19,"788":20,"829":21,"830":22,"831":23,"832":24,"833":25,"834":26,"835":27,"836":28,"838":29,"842":30,"843":31,"844":32,"849":33,"850":34,"855":35,"1155":36,"1156":37,"1157":38,"1158":39,"1159":40,"7620":41,"7621":42,"7622":43,"7623":44,"7624":45,"7625":46,"8400":47,"8401":48,"8406":49,"8407":50,"8411":51,"8412":52,"8417":53,"57879":54,"57880":55,"57881":56,"57882":57,"57883":58,"57884":59,"57885":60,"57886":61,"57887":62,"57888":63,"57926":64,"58072":65},{"808":0}],[{"45":0,"65":1,"66":2,"67":3,"68":4,"70":5,"71":6,"75":7,"76":8,"79":9,"80":10,"81":11,"82":12,"83":13,"84":14,"85":15,"86":16,"87":17,"88":18,"89":19,"90":20,"97":21,"102":22,"107":23,"114":24,"118":25,"119":26,"121":27,"192":28,"193":29,"194":30,"195":31,"196":32,"198":33,"199":34,"208":35,"210":36,"211":37,"212":38,"213":39,"214":40,"216":41,"217":42,"218":43,"219":44,"220":45,"221":46,"224":47,"225":48,"226":49,"227":50,"228":51,"229":52,"253":53,"255":54,"256":55,"258":56,"260":57,"262":58,"264":59,"266":60,"268":61,"270":62,"272":63,"286":64,"313":65,"317":66,"320":67,"321":68,"340":69,"341":70,"344":71,"345":72,"350":73,"352":74,"356":75,"366":76,"376":77,"381":78,"699":79,"8208":80,"8216":81,"8218":82,"8220":83,"8222":84,"42788":85,"42816":86,"42817":87}],[{"61185":0,"61186":1,"61187":2,"61188":3,"61189":4,"61191":5,"61192":6,"61193":7,"61194":8,"61195":9,"61197":10,"61198":11,"61199":12,"61200":13,"61201":14,"61203":15,"61204":16,"61205":17,"61206":18,"61207":19}]]
|
||||
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.DFLT.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.DFLT.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.KUR .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.KUR .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.SND .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.SND .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.URD .json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.arab.URD .json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.nko .DFLT.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUB.nko .DFLT.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rtlSUB":{"007CA":{"1":"0E27E","3":"0E27F","2":"0E280"},"007CB":{"1":"0E281","3":"0E282","2":"0E283"},"007CC":{"1":"0E284","3":"0E285","2":"0E286"},"007CD":{"1":"0E287","3":"0E288","2":"0E289"},"007CE":{"1":"0E28A","3":"0E28B","2":"0E28C"},"007CF":{"1":"0E28D","3":"0E28E","2":"0E28F"},"007D0":{"1":"0E290","3":"0E291","2":"0E292"},"007D1":{"1":"0E293","3":"0E294","2":"0E295"},"007D2":{"1":"0E296","3":"0E297","2":"0E298"},"007D3":{"1":"0E299","3":"0E29A","2":"0E29B"},"007D4":{"1":"0E29C","3":"0E29D","2":"0E29E"},"007D5":{"1":"0E29F","3":"0E2A0","2":"0E2A1"},"007D6":{"1":"0E2A2","3":"0E2A3","2":"0E2A4"},"007D7":{"1":"0E2A5","3":"0E2A6","2":"0E2A7"},"007D8":{"1":"0E2A8","3":"0E2A9","2":"0E2AA"},"007D9":{"1":"0E2AB","3":"0E2AC","2":"0E2AD"},"007DA":{"1":"0E2AE","3":"0E2AF","2":"0E2B0"},"007DB":{"1":"0E2B1","3":"0E2B2","2":"0E2B3"},"007DC":{"1":"0E2B4","3":"0E2B5","2":"0E2B6"},"007DD":{"1":"0E2B7","3":"0E2B8","2":"0E2B9"},"007DE":{"1":"0E2BA","3":"0E2BB","2":"0E2BC"},"007DF":{"1":"0E2BD","3":"0E2BE","2":"0E2BF"},"007E0":{"1":"0E2C0","3":"0E2C1","2":"0E2C2"},"007E1":{"1":"0E2C3","3":"0E2C4","2":"0E2C5"},"007E2":{"1":"0E2C6","3":"0E2C7","2":"0E2C8"},"007E3":{"1":"0E2C9","3":"0E2CA","2":"0E2CB"},"007E4":{"1":"0E2CC","3":"0E2CD","2":"0E2CE"},"007E5":{"1":"0E2CF","3":"0E2D0","2":"0E2D1"},"007E6":{"1":"0E2D2","3":"0E2D3","2":"0E2D4"},"007E7":{"1":"0E2D5","3":"0E2D6","2":"0E2D7"}},"finals":"0E27E 0E281 0E284 0E287 0E28A 0E28D 0E290 0E293 0E296 0E299 0E29C 0E29F 0E2A2 0E2A5 0E2A8 0E2AB 0E2AE 0E2B1 0E2B4 0E2B7 0E2BA 0E2BD 0E2C0 0E2C3 0E2C6 0E2C9 0E2CC 0E2CF 0E2D2 0E2D5 ","rphf":[],"half":[],"pref":[],"blwf":[],"pstf":[]}
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUBGPOStables.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUBGPOStables.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUBdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.GSUBdata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.cw.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.cw.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.cw127.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.cw127.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rangeid":114,"prevcid":126,"prevwidth":754,"interval":false,"range":{"32":[313,410,469,754,626,901,785,275],"40":{"0":411,"1":411,"interval":true},"42":[470,754,342,374,342,329],"48":{"0":626,"1":626,"interval":true,"2":626,"3":626,"4":626,"5":626,"6":626,"7":626,"8":626,"9":626},"58":{"0":360,"1":360,"interval":true},"60":{"0":754,"1":754,"interval":true,"2":754},"63":[522,900,696,686,660,747],"69":{"0":615,"1":615,"interval":true},"71":[738,753],"73":{"0":334,"1":334,"interval":true},"75":[697,573,896,753,765,659,765,693,648,614,730,696,993,694,651,652,411,329,411,754],"95":{"0":450,"1":450,"interval":true},"97":[607,644,533,644,610,391,644,641],"105":{"0":308,"1":308,"interval":true},"107":[598,308,938,641,618],"112":{"0":644,"1":644,"interval":true},"114":[444,536,430,641,586,831,580,586,523,641,329,641,754]}}
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.gid.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.gid.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.mtx.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedB.mtx.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GDEFdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GDEFdata.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GPOSdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GPOSdata.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[[{"3784":0,"3785":1,"3786":2,"3787":3,"3788":4,"3789":5}],[{"3768":0,"3769":1}],[{"792":0,"793":1,"796":2,"797":3,"798":4,"799":5,"805":6,"809":7,"810":8,"812":9,"813":10,"825":11,"826":12,"827":13,"840":14,"851":15,"858":16},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"829":18,"831":19,"832":20,"833":21,"834":22,"836":23,"838":24,"842":25,"843":26,"844":27,"849":28,"850":29,"855":30,"7620":31,"7621":32,"7622":33,"7623":34,"7624":35,"7625":36,"8400":37,"8401":38,"8406":39,"8407":40,"8411":41,"8412":42,"8417":43,"57811":44,"57812":45,"57813":46,"57814":47,"57815":48,"57816":49,"57817":50,"57818":51,"57819":52,"57820":53,"57821":54,"57863":55}],[{"1456":0,"1457":1,"1458":2,"1459":3,"1460":4,"1461":5,"1462":6,"1463":7,"1464":8,"1467":9,"1469":10,"1479":11}],[{"1468":0}],[{"1471":0,"64286":1}],[{"3761":0,"3764":1,"3765":2,"3766":3,"3767":4,"3771":5,"3784":6,"3785":7,"3786":8,"3787":9,"3788":10,"3789":11}],[{"3768":0,"3769":1,"3772":2}],[{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34}],[{"808":0},{"65057":0,"65059":1},{"768":0,"769":1},{"807":0,"7698":1},{"790":0,"791":1,"792":2,"793":3,"796":4,"797":5,"798":6,"799":7,"800":8,"803":9,"804":10,"805":11,"806":12,"809":13,"810":14,"811":15,"812":16,"813":17,"814":18,"815":19,"816":20,"817":21,"818":22,"819":23,"825":24,"826":25,"827":26,"828":27,"839":28,"840":29,"841":30,"845":31,"846":32,"851":33,"858":34},{"768":0,"769":1,"770":2,"771":3,"772":4,"773":5,"774":6,"775":7,"776":8,"777":9,"778":10,"779":11,"780":12,"781":13,"782":14,"783":15,"784":16,"785":17,"786":18,"787":19,"788":20,"829":21,"830":22,"831":23,"832":24,"833":25,"834":26,"835":27,"836":28,"838":29,"842":30,"843":31,"844":32,"849":33,"850":34,"855":35,"1155":36,"1156":37,"1157":38,"1158":39,"1159":40,"7620":41,"7621":42,"7622":43,"7623":44,"7624":45,"7625":46,"8400":47,"8401":48,"8406":49,"8407":50,"8411":51,"8412":52,"8417":53,"57811":54,"57812":55,"57813":56,"57814":57,"57815":58,"57816":59,"57817":60,"57818":61,"57819":62,"57820":63,"57821":64,"57863":65}],[{"45":0,"65":1,"66":2,"67":3,"70":4,"75":5,"76":6,"79":7,"80":8,"81":9,"83":10,"84":11,"86":12,"87":13,"88":14,"89":15,"90":16,"102":17,"114":18,"118":19,"119":20,"121":21,"192":22,"193":23,"194":24,"195":25,"196":26,"198":27,"199":28,"208":29,"210":30,"211":31,"212":32,"213":33,"214":34,"216":35,"221":36,"222":37,"253":38,"255":39,"256":40,"258":41,"260":42,"262":43,"264":44,"266":45,"268":46,"313":47,"317":48,"321":49,"341":50,"345":51,"350":52,"352":53,"356":54,"376":55,"381":56,"699":57,"8208":58,"8216":59,"8218":60,"8220":61,"8222":62,"42788":63,"42816":64}],[{"61185":0,"61186":1,"61187":2,"61188":3,"61189":4,"61191":5,"61192":6,"61193":7,"61194":8,"61195":9,"61197":10,"61198":11,"61199":12,"61200":13,"61201":14,"61203":15,"61204":16,"61205":17,"61206":18,"61207":19}]]
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GSUBGPOStables.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GSUBGPOStables.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GSUBdata.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.GSUBdata.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[[{"1506":0}],[{"105":0,"106":1,"303":2,"585":3,"616":4,"669":5,"768":6,"769":7,"770":8,"771":9,"772":10,"773":11,"774":12,"775":13,"776":14,"777":15,"778":16,"779":17,"780":18,"781":19,"782":20,"783":21,"784":22,"785":23,"786":24,"787":25,"788":26,"829":27,"830":28,"831":29,"832":30,"833":31,"834":32,"835":33,"836":34,"838":35,"842":36,"843":37,"844":38,"849":39,"855":40,"1011":41,"1110":42,"1112":43,"1155":44,"1156":45,"1157":46,"1158":47,"7725":48,"7883":49,"8400":50,"8401":51,"8406":52,"8407":53,"8520":54,"8521":55}],[{"741":0,"742":1,"743":2,"744":3,"745":4},{"741":0,"742":1,"743":2,"744":3,"745":4},{"741":0,"742":1,"743":2,"744":3,"745":4},{"741":0,"742":1,"743":2,"744":3,"745":4},{"741":0,"742":1,"743":2,"744":3,"745":4},{"741":0},{"742":0},{"743":0},{"744":0},{"745":0}],[{"1497":0,"1522":1}],[{"1073":0}],[{"330":0}],[{"102":0}],[{"1488":0}],[{"1381":0,"1396":1,"1406":2}],[{"115":0}],[{"383":0}],[{"33":0,"63":1,"70":2,"82":3,"83":4,"84":5,"97":6,"99":7}],[{"1471":0}],[{"1471":0}],[{"910":0,"933":1,"939":2,"946":3,"952":4,"960":5,"966":6}],[{"910":0,"933":1,"939":2,"946":3,"952":4,"960":5,"966":6}],[{"73":0,"74":1,"97":2,"108":3,"330":4}],[{"73":0,"74":1,"97":2,"108":3,"121":4,"330":5}],[{"1506":0}],[{"768":0,"769":1,"770":2,"771":3,"774":4,"775":5,"776":6,"778":7,"779":8,"780":9,"783":10,"785":11}],[{"105":0,"106":1,"303":2,"585":3,"616":4,"669":5,"1011":6,"1110":7,"1112":8,"7725":9,"7883":10,"8520":11,"8521":12}],[{"742":0,"743":1,"744":2,"745":3}],[{"741":0,"742":1,"743":2,"744":3,"745":4}],[{"741":0,"742":1,"743":2,"744":3,"745":4}],[{"741":0,"742":1,"743":2,"744":3,"745":4}],[{"741":0,"742":1,"743":2,"744":3,"745":4}],[{"741":0,"742":1,"743":2,"744":3,"745":4}],[{"161":0,"191":1,"11800":2}]]
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.cw.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.cw.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.cw127.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.cw127.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rangeid":122,"prevcid":126,"prevwidth":754,"interval":false,"range":{"32":[286,360,414,754,572,855,702,247],"40":{"0":351,"1":351,"interval":true},"42":[450,754,286,325,286,303],"48":{"0":572,"1":572,"interval":true,"2":572,"3":572,"4":572,"5":572,"6":572,"7":572,"8":572,"9":572},"58":{"0":303,"1":303,"interval":true},"60":{"0":754,"1":754,"interval":true,"2":754},"63":[478,900,615,617,628,693,568,518,697,677],"73":{"0":265,"1":265,"interval":true},"75":[590,501,776,673,708,542,708,625,571,549,659,615,890,616,549,616,351,303,351,754],"95":{"0":450,"1":450,"interval":true},"97":[551,571,495,571,554,316,571,570],"105":{"0":250,"1":250,"interval":true},"107":[521,250,876,570,550],"112":{"0":571,"1":571,"interval":true},"114":[370,469,353,570,532,736],"120":{"0":532,"1":532,"interval":true},"122":[472,572,303,572,754]}}
|
||||
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.gid.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.gid.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.mtx.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavusanscondensedI.mtx.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.cw.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.cw.dat
vendored
Normal file
Binary file not shown.
0
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.gid.dat
vendored
Normal file
0
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.gid.dat
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.mtx.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/dejavuserifcondensed.mtx.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.cw.dat
vendored
Normal file
BIN
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.cw.dat
vendored
Normal file
Binary file not shown.
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.cw127.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.cw127.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"rangeid":1,"prevcid":127,"prevwidth":500,"interval":true,"range":{"1":{"0":500,"1":500,"interval":true,"2":500,"3":500,"4":500,"5":500,"6":500,"7":500,"8":500,"9":500,"10":500,"11":500,"12":500,"13":500,"14":500,"15":500,"16":500,"17":500,"18":500,"19":500,"20":500,"21":500,"22":500,"23":500,"24":500,"25":500,"26":500,"27":500,"28":500,"29":500,"30":500,"31":500,"32":500,"33":500,"34":500,"35":500,"36":500,"37":500,"38":500,"39":500,"40":500,"41":500,"42":500,"43":500,"44":500,"45":500,"46":500,"47":500,"48":500,"49":500,"50":500,"51":500,"52":500,"53":500,"54":500,"55":500,"56":500,"57":500,"58":500,"59":500,"60":500,"61":500,"62":500,"63":500,"64":500,"65":500,"66":500,"67":500,"68":500,"69":500,"70":500,"71":500,"72":500,"73":500,"74":500,"75":500,"76":500,"77":500,"78":500,"79":500,"80":500,"81":500,"82":500,"83":500,"84":500,"85":500,"86":500,"87":500,"88":500,"89":500,"90":500,"91":500,"92":500,"93":500,"94":500,"95":500,"96":500,"97":500,"98":500,"99":500,"100":500,"101":500,"102":500,"103":500,"104":500,"105":500,"106":500,"107":500,"108":500,"109":500,"110":500,"111":500,"112":500,"113":500,"114":500,"115":500,"116":500,"117":500,"118":500,"119":500,"120":500,"121":500,"122":500,"123":500,"124":500,"125":500,"126":500}}}
|
||||
0
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.gid.dat
vendored
Normal file
0
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.gid.dat
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.mtx.json
vendored
Normal file
1
src/vendor/mpdf/mpdf/tmp/mpdf/ttfontdata/sun-exta.mtx.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"Sun-ExtA","type":"TTF","desc":{"CapHeight":684,"XHeight":453,"FontBBox":"[-973 -301 2074 1078]","Flags":4,"Ascent":930,"Descent":-141,"Leading":0,"ItalicAngle":0,"StemV":87,"MissingWidth":1000},"unitsPerEm":256,"up":-86,"ut":47,"strp":254,"strs":47,"ttffile":"D:\\2024project\\myweb\\saas.cn\\vendor\\mpdf\\mpdf\\src\\Config\/..\/..\/ttfonts\/Sun-ExtA.ttf","TTCfontID":0,"originalsize":22993540,"sip":false,"smp":false,"BMPselected":false,"fontkey":"sun-exta","panose":" 0 0 2 1 6 0 3 1 1 1 1 1","haskerninfo":false,"haskernGPOS":false,"hassmallcapsGSUB":false,"fontmetrics":"win","useOTL":0,"rtlPUAstr":"","GSUBScriptLang":[],"GSUBFeatures":[],"GSUBLookups":[],"GPOSScriptLang":[],"GPOSFeatures":[],"GPOSLookups":[],"kerninfo":[]}
|
||||
Reference in New Issue
Block a user