Compare commits
6 Commits
main
...
feat-wxwor
| Author | SHA1 | Date | |
|---|---|---|---|
| d7221dc3f9 | |||
| 28b12b3dfe | |||
| 3aab5b9c75 | |||
| 09c859750e | |||
| 157ea7f46d | |||
| 572b4c4a00 |
27
.env.development
Normal file
27
.env.development
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# 项目配置, 请根据实际情况修改
|
||||||
|
PROJECT_NAME=newshop
|
||||||
|
|
||||||
|
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||||
|
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=%
|
||||||
|
MYSQL_DATABASE=shop_mallnew
|
||||||
|
MYSQL_USER=shop_mallnew
|
||||||
|
MYSQL_PASSWORD=shop_mallnew
|
||||||
|
MYSQL_PORT=3326
|
||||||
|
|
||||||
|
# Redis 绑定端口及密码
|
||||||
|
REDIS_PASSWORD=luckyshop123!@#
|
||||||
|
REDIS_PORT=6499
|
||||||
|
|
||||||
|
# Nginx 暴漏端口
|
||||||
|
NGINX_PORT=8050
|
||||||
|
NGINX_SSL_PORT=8052
|
||||||
|
|
||||||
16
.env.example
16
.env.example
@@ -1,24 +1,26 @@
|
|||||||
# 项目配置, 请根据实际情况修改
|
# 项目配置, 请根据实际情况修改
|
||||||
PROJECT_NAME=newshop
|
PROJECT_NAME=newshop
|
||||||
|
|
||||||
|
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||||
|
APP_ENV=development
|
||||||
|
|
||||||
# PHP/PHP-FPM 配置
|
# PHP/PHP-FPM 配置
|
||||||
PHP_VERSION=7.4
|
PHP_VERSION=7.4
|
||||||
PHP_FPM_VERSION=7.4-fpm
|
PHP_FPM_VERSION=7.4-fpm
|
||||||
PHP_FPM_PORT=9000
|
PHP_FPM_PORT=9100
|
||||||
XDEBUG_POST=9003
|
XDEBUG_POST=9103
|
||||||
|
|
||||||
# 数据库配置
|
# 数据库配置
|
||||||
MYSQL_ROOT_HOST=%
|
MYSQL_ROOT_HOST=%
|
||||||
MYSQL_DATABASE=shop_mallnew
|
MYSQL_DATABASE=shop_mallnew
|
||||||
MYSQL_USER=shop_mallnew
|
MYSQL_USER=shop_mallnew
|
||||||
MYSQL_PASSWORD=shop_mallnew
|
MYSQL_PASSWORD=shop_mallnew
|
||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3316
|
||||||
|
|
||||||
# Redis 配置
|
# Redis 配置
|
||||||
REDIS_PASSWORD=luckyshop123!@#
|
REDIS_PASSWORD=luckyshop123!@#
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6399
|
||||||
|
|
||||||
# Nginx 配置
|
# Nginx 配置
|
||||||
NGINX_PORT=80
|
NGINX_PORT=8010
|
||||||
NGINX_SSL_PORT=443
|
NGINX_SSL_PORT=8012
|
||||||
|
|
||||||
|
|||||||
27
.env.local
Normal file
27
.env.local
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# 项目配置, 请根据实际情况修改
|
||||||
|
PROJECT_NAME=newshop
|
||||||
|
|
||||||
|
# ThinkPHP 6.x 配置, 请根据实际情况修改
|
||||||
|
APP_ENV=local
|
||||||
|
|
||||||
|
# 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_USER=shop_mallnew
|
||||||
|
MYSQL_PASSWORD=shop_mallnew
|
||||||
|
MYSQL_PORT=3316
|
||||||
|
|
||||||
|
# Redis 配置
|
||||||
|
REDIS_PASSWORD=luckyshop123!@#
|
||||||
|
REDIS_PORT=6399
|
||||||
|
|
||||||
|
# Nginx 配置
|
||||||
|
NGINX_PORT=8010
|
||||||
|
NGINX_SSL_PORT=8012
|
||||||
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -18,6 +18,9 @@ __pycache__
|
|||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# 环境变量
|
||||||
|
.env
|
||||||
|
|
||||||
# 源码结构
|
# 源码结构
|
||||||
debug.txt
|
debug.txt
|
||||||
.travis.yml
|
.travis.yml
|
||||||
|
|||||||
138
README.md
Normal file
138
README.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# 在线商城PHP项目
|
||||||
|
|
||||||
|
## Git 分支策略
|
||||||
|
|
||||||
|
| 环境 | 推荐分支 | 备选分支 | 说明 |
|
||||||
|
|------|----------|----------|------|
|
||||||
|
| local | `dev` | `develop` | 本地开发环境 |
|
||||||
|
| development | `dev` | `development` | 开发测试环境 |
|
||||||
|
| test | `test` | `staging` | 测试环境 |
|
||||||
|
| staging | `staging` | `pre-release` | 预发布环境 |
|
||||||
|
| production | `master` | `main` | 生产环境 |
|
||||||
|
|
||||||
|
**部署建议**:
|
||||||
|
- 每个环境部署前请先切换到对应的Git分支
|
||||||
|
- 确保代码版本与目标环境匹配
|
||||||
|
- 生产环境部署前建议先在staging环境验证
|
||||||
|
|
||||||
|
## Docker 部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env.development
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意**
|
||||||
|
|
||||||
|
- 在同一目录下面,执行 `docker-compose` 命令时,需要指定项目名称。用来区分不同的环境。如 `shop_local`、`shop_dev` 等。
|
||||||
|
- 本地部署时,需要将 `APP_ENV` 设置为 `local`。
|
||||||
|
- 开发环境部署时,需要将 `APP_ENV` 设置为 `development`。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
- `APP_ENV`: 应用环境,默认值为 `development`。
|
||||||
|
|
||||||
|
## 开发环境-local 部署
|
||||||
|
|
||||||
|
**对应Git分支**: `main` 或 `develop`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到本地开发分支
|
||||||
|
git checkout main # 或 develop
|
||||||
|
|
||||||
|
# 本地部署时,需要将 APP_ENV 设置为 local, 并指定 docker-compose.local.yml 文件
|
||||||
|
docker-compose --env-file .env.local -f docker-compose.local.yml up -d
|
||||||
|
# docker-compose --project-name shop_local --env-file .env.local -f docker-compose.local.yml up -d
|
||||||
|
|
||||||
|
# docker-compose down 命令,用来停止并删除容器
|
||||||
|
docker-compose -f docker-compose.local.yml down -v
|
||||||
|
# docker-compose --project-name shop_local down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 开发环境-development 部署
|
||||||
|
|
||||||
|
**对应Git分支**: `dev` 或 `development`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到开发分支
|
||||||
|
git checkout dev # 或 development
|
||||||
|
|
||||||
|
# 默认使用 docker-compose.yml 文件
|
||||||
|
docker-compose --project-name shop_development --env-file .env.development up -d
|
||||||
|
|
||||||
|
# docker-compose down 命令,用来停止并删除容器
|
||||||
|
docker-compose --project-name shop_development down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发环境-test 部署 (测试环境)
|
||||||
|
|
||||||
|
**对应Git分支**: `test` 或 `staging`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到测试分支
|
||||||
|
git checkout test # 或 staging
|
||||||
|
|
||||||
|
# 默认使用 docker-compose.yml 文件
|
||||||
|
docker-compose --project-name shop_test --env-file .env.test up -d
|
||||||
|
|
||||||
|
# docker-compose down 命令,用来停止并删除容器
|
||||||
|
docker-compose --project-name shop_test down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发环境-staging 部署(预发布环境)
|
||||||
|
|
||||||
|
**对应Git分支**: `staging` 或 `pre-release`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到预发布分支
|
||||||
|
git checkout staging # 或 pre-release
|
||||||
|
|
||||||
|
# 默认使用 docker-compose.yml 文件
|
||||||
|
docker-compose --project-name shop_staging --env-file .env.staging up -d
|
||||||
|
|
||||||
|
# docker-compose down 命令,用来停止并删除容器
|
||||||
|
docker-compose --project-name shop_staging down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## 生产环境-production 部署
|
||||||
|
|
||||||
|
**对应Git分支**: `master` 或 `main` 或 `production`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到生产分支
|
||||||
|
git checkout main
|
||||||
|
|
||||||
|
# 确保代码是最新的生产版本
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 默认使用 docker-compose.yml 文件
|
||||||
|
docker-compose --project-name shop_production --env-file .env.production up -d
|
||||||
|
|
||||||
|
# docker-compose down 命令,用来停止并删除容器
|
||||||
|
docker-compose --project-name shop_production down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## 便捷部署脚本
|
||||||
|
|
||||||
|
### 环境切换与部署脚本
|
||||||
|
|
||||||
|
- `deploy.sh` 脚本:
|
||||||
|
|
||||||
|
|
||||||
|
### 使用方法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 赋予执行权限
|
||||||
|
chmod +x deploy.sh
|
||||||
|
|
||||||
|
# 部署到开发环境
|
||||||
|
./deploy.sh development
|
||||||
|
|
||||||
|
# 部署到测试环境
|
||||||
|
./deploy.sh test
|
||||||
|
|
||||||
|
# 部署到生产环境
|
||||||
|
./deploy.sh production
|
||||||
|
```
|
||||||
100
deploy.sh
Normal file
100
deploy.sh
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# deploy.sh - 环境切换与部署脚本
|
||||||
|
# 使用方法: ./deploy.sh <environment>
|
||||||
|
# 示例: ./deploy.sh development
|
||||||
|
|
||||||
|
ENVIRONMENT=$1
|
||||||
|
PROJECT_NAME="shop_${ENVIRONMENT}"
|
||||||
|
BRANCH=""
|
||||||
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
|
ENV_FILE=".env.${ENVIRONMENT}"
|
||||||
|
|
||||||
|
# 现实运行中的服务器网站,数据库备份目录
|
||||||
|
RUN_SERVER_WEB_ROOT="/data/wwwroot/shop-projects"
|
||||||
|
RUN_SERVER_DB_BACKUP_DIR="/data/backup/shop-projects"
|
||||||
|
|
||||||
|
case $ENVIRONMENT in
|
||||||
|
"local")
|
||||||
|
BRANCH="dev"
|
||||||
|
COMPOSE_FILE="docker-compose.local.yml"
|
||||||
|
ENV_FILE=".env.local"
|
||||||
|
;;
|
||||||
|
"development")
|
||||||
|
BRANCH="dev"
|
||||||
|
;;
|
||||||
|
"test")
|
||||||
|
BRANCH="test"
|
||||||
|
;;
|
||||||
|
"staging")
|
||||||
|
BRANCH="staging"
|
||||||
|
;;
|
||||||
|
"production")
|
||||||
|
BRANCH="main"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "错误: 不支持的环境 '$ENVIRONMENT'"
|
||||||
|
echo "支持的环境: local, development, test, staging, production"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "部署环境: $ENVIRONMENT"
|
||||||
|
echo "项目名称: $PROJECT_NAME"
|
||||||
|
echo "Git分支: $BRANCH"
|
||||||
|
echo "配置文件: $COMPOSE_FILE"
|
||||||
|
echo "环境文件: $ENV_FILE"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# 切换分支
|
||||||
|
echo "切换到Git分支: $BRANCH"
|
||||||
|
git checkout $BRANCH
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "错误: 无法切换到分支 $BRANCH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 拉取最新代码
|
||||||
|
echo "拉取最新代码..."
|
||||||
|
git pull origin $BRANCH
|
||||||
|
|
||||||
|
# 根据不同的环境,执行不同的操作
|
||||||
|
# 预发布环境、生产环境都需要使用运行服务上的用户文件,将用户文件复制到指定目录
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 根据不同的环境,执行不同的操作
|
||||||
|
# 预发布环境、生产环境都需要还原数据库,使用数据库备份文件,并尝试使用数据库升级
|
||||||
|
if [ "$ENVIRONMENT" = "local" ]; then
|
||||||
|
echo "本地环境,跳过数据库还原"
|
||||||
|
else
|
||||||
|
echo "还原数据库..."
|
||||||
|
# 还原数据库
|
||||||
|
docker-compose --project-name $PROJECT_NAME exec -T db bash -c "mysql -uroot -p$DB_ROOT_PASSWORD shop < $DB_BACKUP_DIR/shop.sql"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "错误: 数据库还原失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 尝试使用数据库升级脚本
|
||||||
|
echo "尝试使用数据库升级..."
|
||||||
|
docker-compose --project-name $PROJECT_NAME exec -T db bash -c "php artisan migrate --force"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "数据库升级失败"
|
||||||
|
else
|
||||||
|
echo "数据库升级成功"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建并启动容器
|
||||||
|
echo "构建并启动Docker容器..."
|
||||||
|
if [ "$ENVIRONMENT" = "local" ]; then
|
||||||
|
docker-compose --env-file $ENV_FILE -f $COMPOSE_FILE up -d
|
||||||
|
else
|
||||||
|
docker-compose --project-name $PROJECT_NAME --env-file $ENV_FILE up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "部署完成!"
|
||||||
|
echo "查看容器状态: docker-compose --project-name $PROJECT_NAME ps"
|
||||||
|
echo "查看日志: docker-compose --project-name $PROJECT_NAME logs -f"
|
||||||
120
docker-compose.local.yml
Normal file
120
docker-compose.local.yml
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# 特别说明,本地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
|
||||||
@@ -14,7 +14,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ./docker/php
|
context: ./docker/php
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: ${PROJECT_NAME}_php
|
container_name: ${PROJECT_NAME}_${APP_ENV}_php
|
||||||
restart: always
|
restart: always
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway" # 支持主机名解析
|
- "host.docker.internal:host-gateway" # 支持主机名解析
|
||||||
@@ -25,23 +25,18 @@ services:
|
|||||||
# 不然,ThinkPHP 6.x 系列,会只加载 .env 文件,而不会加载 .env.local 文件,导致 .env.local 文件中的配置不会生效
|
# 不然,ThinkPHP 6.x 系列,会只加载 .env 文件,而不会加载 .env.local 文件,导致 .env.local 文件中的配置不会生效
|
||||||
APP_ENV: ${APP_ENV:-development}
|
APP_ENV: ${APP_ENV:-development}
|
||||||
APP_DEBUG: ${APP_DEBUG:-true}
|
APP_DEBUG: ${APP_DEBUG:-true}
|
||||||
XDEBUG_CONFIG: ${XDEBUG_CONFIG:-client_host=host.docker.internal client_port=9003}
|
|
||||||
PHP_IDE_CONFIG: serverName=docker-php
|
|
||||||
ports:
|
ports:
|
||||||
- "${PHP_FPM_PORT:-9000}:9000" # PHP-FPM
|
- "${PHP_FPM_PORT:-9000}:9000" # PHP-FPM
|
||||||
- "${XDEBUG_POST:-9003}:9003" # Xdebug
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/var/www/all_source
|
- ./:/var/www/all_source
|
||||||
- ./src:/var/www/html
|
- ./src:/var/www/html
|
||||||
# 更新下载源列表以加速apt-get
|
# 更新下载源列表以加速apt-get
|
||||||
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
||||||
- ./docker/php/php.ini:/usr/local/etc/php/php.ini:ro
|
- ./docker/php/php.ini:/usr/local/etc/php/php.ini:ro
|
||||||
- ./docker/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini
|
|
||||||
- xdebug_logs:/tmp # Xdebug 日志目录
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "bash", "-c", "curl -f http://localhost:9000/status && ps aux | grep '[p]hp think cron:schedule'"]
|
test: ["CMD", "bash", "-c", "curl -f http://localhost:9000/status"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
@@ -49,18 +44,19 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- sass-platform-net
|
- sass-platform-net
|
||||||
labels:
|
labels:
|
||||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
- "com.docker.compose.project.working_dir=${PROJECT_NAME}_${APP_ENV}"
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
build:
|
build:
|
||||||
context: ./docker/nginx
|
context: ./docker/nginx
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: ${PROJECT_NAME}_nginx
|
container_name: ${PROJECT_NAME}_${APP_ENV}_nginx
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "${NGINX_PORT:-80}:80"
|
- "${NGINX_PORT:-80}:80"
|
||||||
- "${NGINX_SSL_PORT:-443}:443"
|
- "${NGINX_SSL_PORT:-443}:443"
|
||||||
volumes:
|
volumes:
|
||||||
|
# 挂载项目代码到 Nginx 容器中
|
||||||
- ./src:/var/www/html:rw
|
- ./src:/var/www/html:rw
|
||||||
# 更新下载源列表以加速apt-get
|
# 更新下载源列表以加速apt-get
|
||||||
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
- ./docker/debian/sources.list:/etc/apt/sources.list:ro
|
||||||
@@ -72,11 +68,11 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- sass-platform-net
|
- sass-platform-net
|
||||||
labels:
|
labels:
|
||||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
- "com.docker.compose.project.working_dir=${PROJECT_NAME}_${APP_ENV}"
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mysql:5.7.44
|
image: mysql:5.7.44
|
||||||
container_name: ${PROJECT_NAME}_mysql
|
container_name: ${PROJECT_NAME}_${APP_ENV}_mysql
|
||||||
environment:
|
environment:
|
||||||
<<: *shared-api-env
|
<<: *shared-api-env
|
||||||
volumes:
|
volumes:
|
||||||
@@ -93,12 +89,12 @@ services:
|
|||||||
- --collation-server=utf8mb4_unicode_ci
|
- --collation-server=utf8mb4_unicode_ci
|
||||||
- --innodb_buffer_pool_size=256M
|
- --innodb_buffer_pool_size=256M
|
||||||
labels:
|
labels:
|
||||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
- "com.docker.compose.project.working_dir=${PROJECT_NAME}_${APP_ENV}"
|
||||||
|
|
||||||
# Redis 服务(可选)
|
# Redis 服务(可选)
|
||||||
redis:
|
redis:
|
||||||
image: redis:8.2
|
image: redis:8.2
|
||||||
container_name: ${PROJECT_NAME}_redis
|
container_name: ${PROJECT_NAME}_${APP_ENV}_redis
|
||||||
environment:
|
environment:
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-luckyshop123!@#}
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-luckyshop123!@#}
|
||||||
REDISCLI_AUTH: ${REDIS_PASSWORD:-luckyshop123!@#}
|
REDISCLI_AUTH: ${REDIS_PASSWORD:-luckyshop123!@#}
|
||||||
@@ -111,13 +107,27 @@ services:
|
|||||||
- sass-platform-net
|
- sass-platform-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
labels:
|
labels:
|
||||||
- "com.docker.compose.project.working_dir=${PROJECT_NAME}"
|
- "com.docker.compose.project.working_dir=${PROJECT_NAME}_${APP_ENV}"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql_db_data:
|
mysql_db_data:
|
||||||
|
name: ${PROJECT_NAME}_${APP_ENV}_mysql_db_data
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./docker/mysql_db_data/${APP_ENV}
|
||||||
redis_data:
|
redis_data:
|
||||||
xdebug_logs:
|
name: ${PROJECT_NAME}_${APP_ENV}_redis_data
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./docker/redis_data/${APP_ENV}
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
sass-platform-net:
|
sass-platform-net:
|
||||||
|
name: ${PROJECT_NAME}_${APP_ENV}_net
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
external: true
|
||||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,8 @@
|
|||||||
# 字符集设置
|
# 字符集设置
|
||||||
character-set-server=utf8mb4
|
character-set-server=utf8mb4
|
||||||
collation-server=utf8mb4_unicode_ci
|
collation-server=utf8mb4_unicode_ci
|
||||||
|
init_connect='SET NAMES utf8mb4'
|
||||||
|
|
||||||
|
|
||||||
# 连接设置
|
# 连接设置
|
||||||
max_connections=100
|
max_connections=100
|
||||||
@@ -22,6 +24,3 @@ sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
|
|||||||
|
|
||||||
[client]
|
[client]
|
||||||
default-character-set=utf8mb4
|
default-character-set=utf8mb4
|
||||||
|
|
||||||
[mysql]
|
|
||||||
default-character-set=utf8mb4
|
|
||||||
10
docker/mysql_db_data/.gitignore
vendored
Normal file
10
docker/mysql_db_data/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 忽略目录下所有文件和子目录
|
||||||
|
*
|
||||||
|
# 忽略所有子目录
|
||||||
|
*/
|
||||||
|
# 但不忽略 .gitkeep 文件
|
||||||
|
!.gitkeep
|
||||||
|
# 不忽略 .gitignore 文件自身
|
||||||
|
!.gitignore
|
||||||
|
# 不忽略 development/.gitkeep 文件
|
||||||
|
!development/.gitkeep
|
||||||
0
docker/mysql_db_data/.gitkeep
Normal file
0
docker/mysql_db_data/.gitkeep
Normal file
@@ -1,10 +0,0 @@
|
|||||||
# 使用官方PHP镜像
|
|
||||||
FROM php:7.4.33-fpm-dev-newshop
|
|
||||||
|
|
||||||
# 设置工作目录
|
|
||||||
WORKDIR /var/www/html
|
|
||||||
|
|
||||||
# 暴露端口
|
|
||||||
EXPOSE 9000 9003
|
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
|
||||||
@@ -27,6 +27,7 @@ RUN apt-get update && apt-get install -y \
|
|||||||
libfreetype6-dev \
|
libfreetype6-dev \
|
||||||
libjpeg62-turbo-dev \
|
libjpeg62-turbo-dev \
|
||||||
libpng-dev \
|
libpng-dev \
|
||||||
|
iputils-ping \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 安装 PHP 扩展
|
# 安装 PHP 扩展
|
||||||
@@ -45,9 +46,6 @@ RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
|
|||||||
# 安装 Redis 扩展
|
# 安装 Redis 扩展
|
||||||
RUN pecl install redis-5.3.7 && docker-php-ext-enable redis
|
RUN pecl install redis-5.3.7 && docker-php-ext-enable redis
|
||||||
|
|
||||||
# 安装 Xdebug(兼容 PHP 7.4 的版本)
|
|
||||||
RUN pecl install xdebug-3.1.6 && docker-php-ext-enable xdebug
|
|
||||||
|
|
||||||
# 安装Composer
|
# 安装Composer
|
||||||
COPY --from=composer:2.2.25 /usr/bin/composer /usr/bin/composer
|
COPY --from=composer:2.2.25 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
@@ -59,27 +57,12 @@ 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 "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 "post_max_size=50M" >> /usr/local/etc/php/conf.d/uploads.ini
|
||||||
|
|
||||||
# 创建 Xdebug 配置
|
|
||||||
RUN echo "zend_extension=xdebug.so" > /usr/local/etc/php/conf.d/xdebug.ini
|
|
||||||
|
|
||||||
# # 使用Composer安装项目依赖(可选,根据需要启用, 更多的时候,会出错,要在容器中执行操作)
|
# # 使用Composer安装项目依赖(可选,根据需要启用, 更多的时候,会出错,要在容器中执行操作)
|
||||||
# RUN composer config -g repo.packagist composer https://mirrors.aliyun.com/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
|
# RUN composer install --no-dev --optimize-autoloader --working-dir=/var/www/html
|
||||||
|
|
||||||
# # 创建非 root 用户
|
|
||||||
# RUN useradd -m -u 1000 phpuser && chown -R phpuser:phpuser /var/www/html
|
|
||||||
|
|
||||||
# 设置权限, 防止以下目录无法写入的问题
|
|
||||||
RUN chmod -R a+rw /var/www/html/runtime
|
|
||||||
RUN chmod -R a+rw /var/www/html/uploads
|
|
||||||
RUN chmod -R a+rw /var/www/html/tmp
|
|
||||||
RUN chmod -R a+rw /var/www/html/temp
|
|
||||||
|
|
||||||
# USER phpuser
|
|
||||||
|
|
||||||
# 暴露端口
|
# 暴露端口
|
||||||
EXPOSE 9000 9003
|
EXPOSE 9000
|
||||||
|
|
||||||
|
|
||||||
############ 查看 cron 进程
|
############ 查看 cron 进程
|
||||||
## 查看 cron 进程
|
## 查看 cron 进程
|
||||||
@@ -95,4 +78,10 @@ EXPOSE 9000 9003
|
|||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
# 启动Supervisor
|
# 启动Supervisor
|
||||||
|
# 添加在Dockerfile末尾,CMD命令之前
|
||||||
|
COPY ./entrypoint.sh /usr/local/bin/
|
||||||
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
|
||||||
|
# 修改CMD命令
|
||||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||||
113
docker/php/entrypoint.sh
Normal file
113
docker/php/entrypoint.sh
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== ThinkPHP Docker权限初始化 ==="
|
||||||
|
|
||||||
|
# 定义应用根目录
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "当前用户: $(whoami)"
|
||||||
|
echo "UID: $(id -u), GID: $(id -g)"
|
||||||
|
|
||||||
|
# 修复目录所有权和权限
|
||||||
|
fix_directory_permissions() {
|
||||||
|
local dir=$1
|
||||||
|
echo "修复PHP目录权限: $dir"
|
||||||
|
|
||||||
|
# 确保目录存在
|
||||||
|
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"
|
||||||
|
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 "✅ $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
|
||||||
|
else
|
||||||
|
echo "❌ sudo: runtime目录创建子目录失败 [使用www-data用户]"
|
||||||
|
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 "=== 启动应用 ==="
|
||||||
|
|
||||||
|
# 执行原有的启动命令
|
||||||
|
exec "$@"
|
||||||
@@ -6,25 +6,40 @@ logfile_backups=10
|
|||||||
loglevel=info
|
loglevel=info
|
||||||
pidfile=/var/run/supervisord.pid
|
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]
|
[program:php-fpm]
|
||||||
command=php-fpm
|
command=php-fpm
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
startretries=3
|
startretries=3
|
||||||
startsecs=1
|
startsecs=1
|
||||||
stdout_logfile=/dev/stdout
|
stopasgroup=true
|
||||||
stdout_logfile_maxbytes=0
|
killasgroup=true
|
||||||
stderr_logfile=/dev/stderr
|
stdout_logfile=/var/log/supervisor/php-fpm.log
|
||||||
stderr_logfile_maxbytes=0
|
stdout_logfile_maxbytes=10MB
|
||||||
|
stdout_logfile_backups=10
|
||||||
|
stderr_logfile=/var/log/supervisor/php-fpm-error.log
|
||||||
|
stderr_logfile_maxbytes=10MB
|
||||||
|
stderr_logfile_backups=10
|
||||||
|
|
||||||
[program:think-cron]
|
[program:think-cron]
|
||||||
command=php /var/www/html/think cron:schedule
|
command=php /var/www/html/think cron:schedule
|
||||||
environment=APP_ENV=local
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
numprocs=1
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
startretries=5
|
startretries=3
|
||||||
startsecs=2
|
stdout_logfile=/var/log/supervisor/think-cron.log
|
||||||
stdout_logfile=/dev/stdout
|
stdout_logfile_maxbytes=10MB
|
||||||
stdout_logfile_maxbytes=0
|
stdout_logfile_backups=10
|
||||||
stderr_logfile=/dev/stderr
|
stderr_logfile=/var/log/supervisor/think-cron-error.log
|
||||||
stderr_logfile_maxbytes=0
|
stderr_logfile_maxbytes=10MB
|
||||||
|
stderr_logfile_backups=10
|
||||||
|
startsecs=3
|
||||||
|
stopwaitsecs=10
|
||||||
10
docker/redis_data/.gitignore
vendored
Normal file
10
docker/redis_data/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 忽略目录下所有文件和子目录
|
||||||
|
*
|
||||||
|
# 忽略所有子目录
|
||||||
|
*/
|
||||||
|
# 但不忽略 .gitkeep 文件
|
||||||
|
!.gitkeep
|
||||||
|
# 不忽略 .gitignore 文件自身
|
||||||
|
!.gitignore
|
||||||
|
# 不忽略 development/.gitkeep 文件
|
||||||
|
!development/.gitkeep
|
||||||
0
docker/redis_data/.gitkeep
Normal file
0
docker/redis_data/.gitkeep
Normal file
10
docker/xdebug_logs/.gitignore
vendored
Normal file
10
docker/xdebug_logs/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 忽略目录下所有文件和子目录
|
||||||
|
*
|
||||||
|
# 忽略所有子目录
|
||||||
|
*/
|
||||||
|
# 但不忽略 .gitkeep 文件
|
||||||
|
!.gitkeep
|
||||||
|
# 不忽略 .gitignore 文件自身
|
||||||
|
!.gitignore
|
||||||
|
# 不忽略 development/.gitkeep 文件
|
||||||
|
!development/.gitkeep
|
||||||
0
docker/xdebug_logs/.gitkeep
Normal file
0
docker/xdebug_logs/.gitkeep
Normal file
@@ -3,23 +3,22 @@ APP_TRACE = true
|
|||||||
|
|
||||||
[APP]
|
[APP]
|
||||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||||
ENV_MODE = development
|
|
||||||
|
|
||||||
[LANG]
|
[LANG]
|
||||||
default_lang = zh-cn
|
default_lang = zh-cn
|
||||||
|
|
||||||
[DATABASE]
|
[DATABASE]
|
||||||
TYPE = mysql
|
TYPE = mysql
|
||||||
HOSTNAME = 127.0.0.1
|
HOSTNAME = db
|
||||||
DATABASE = shop_mallnew_dev
|
DATABASE = shop_mallnew
|
||||||
USERNAME = root
|
USERNAME = shop_mallnew
|
||||||
PASSWORD = root
|
PASSWORD = shop_mallnew
|
||||||
HOSTPORT = 3306
|
HOSTPORT = 3306
|
||||||
CHARSET = utf8
|
CHARSET = utf8mb4
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
|
|
||||||
[redis]
|
[REDIS]
|
||||||
HOST = 127.0.0.1
|
HOST = redis
|
||||||
PORT = 6379
|
PORT = 6379
|
||||||
PASSWORD = ''
|
PASSWORD = 'luckyshop123!@#'
|
||||||
EXPIRY = 604800
|
EXPIRY = 604800
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
APP_DEBUG = true
|
APP_DEBUG = true
|
||||||
APP_TRACE = true
|
APP_TRACE = true
|
||||||
|
|
||||||
[APP]
|
[APP]
|
||||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||||
|
|
||||||
[LANG]
|
[LANG]
|
||||||
default_lang = zh-cn
|
default_lang = zh-cn
|
||||||
|
|
||||||
[DATABASE]
|
[DATABASE]
|
||||||
TYPE = mysql
|
TYPE = mysql
|
||||||
HOSTNAME = newshop_mysql
|
HOSTNAME = db
|
||||||
DATABASE = shop_dev
|
DATABASE = shop_dev
|
||||||
USERNAME = shop_mallnew
|
USERNAME = shop_mallnew
|
||||||
PASSWORD = shop_mallnew
|
PASSWORD = shop_mallnew
|
||||||
HOSTPORT = 3306
|
HOSTPORT = 3306
|
||||||
CHARSET = utf8
|
CHARSET = utf8mb4
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
[RRDATABASE]
|
|
||||||
HOSTNAME = 192.168.2.64
|
[REDIS]
|
||||||
[redis]
|
HOST = redis
|
||||||
HOST = newshop_redis
|
|
||||||
PORT = 6379
|
PORT = 6379
|
||||||
PASSWORD = 'luckyshop123!@#'
|
PASSWORD = 'luckyshop123!@#'
|
||||||
EXPIRY = 604800
|
EXPIRY = 604800
|
||||||
@@ -10,16 +10,16 @@ default_lang = zh-cn
|
|||||||
|
|
||||||
[DATABASE]
|
[DATABASE]
|
||||||
TYPE = mysql
|
TYPE = mysql
|
||||||
HOSTNAME = production_mysql_host
|
HOSTNAME = db
|
||||||
DATABASE = shop_mallnew_prod
|
DATABASE = shop_mallnew
|
||||||
USERNAME = prod_user
|
USERNAME = shop_mallnew
|
||||||
PASSWORD = prod_password
|
PASSWORD = shop_mallnew
|
||||||
HOSTPORT = 3306
|
HOSTPORT = 3306
|
||||||
CHARSET = utf8
|
CHARSET = utf8mb4
|
||||||
DEBUG = false
|
DEBUG = false
|
||||||
|
|
||||||
[redis]
|
[REDIS]
|
||||||
HOST = production_redis_host
|
HOST = redis
|
||||||
PORT = 6379
|
PORT = 6379
|
||||||
PASSWORD = production_redis_password
|
PASSWORD = 'luckyshop123!@#'
|
||||||
EXPIRY = 86400
|
EXPIRY = 604800
|
||||||
@@ -120,6 +120,9 @@ class Config extends BaseApi
|
|||||||
$config_model = new ConfigModel();
|
$config_model = new ConfigModel();
|
||||||
$default_img = $config_model->getDefaultImg($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
$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' ];
|
$copyright = $config_model->getCopyright($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||||
$map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
$map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
|
||||||
@@ -146,7 +149,8 @@ class Config extends BaseApi
|
|||||||
'servicer' => $servicer_info,
|
'servicer' => $servicer_info,
|
||||||
'shop_info'=>$shop_info,
|
'shop_info'=>$shop_info,
|
||||||
'store_config' => $this->store_data[ 'config' ],
|
'store_config' => $this->store_data[ 'config' ],
|
||||||
'map_config' => $map_config
|
'map_config' => $map_config,
|
||||||
|
'wxwork_config' => $wxwork_config
|
||||||
];
|
];
|
||||||
if (!empty($this->store_data[ 'store_info' ])) {
|
if (!empty($this->store_data[ 'store_info' ])) {
|
||||||
$res[ 'store_info' ] = $this->store_data[ 'store_info' ];
|
$res[ 'store_info' ] = $this->store_data[ 'store_info' ];
|
||||||
|
|||||||
@@ -847,6 +847,63 @@ class Config extends BaseModel
|
|||||||
// return $data;
|
// 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
|
* @param $data
|
||||||
|
|||||||
@@ -210,6 +210,30 @@ 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 域名跳转配置
|
* 域名跳转配置
|
||||||
*/
|
*/
|
||||||
|
|||||||
514
src/app/shop/view/config/wxwork.html
Normal file
514
src/app/shop/view/config/wxwork.html
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
<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>
|
||||||
147
src/config/database.php
Normal file
147
src/config/database.php
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<?php
|
||||||
|
use think\facade\Env;
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 默认使用的数据库连接配置
|
||||||
|
'default' => 'mysql',
|
||||||
|
|
||||||
|
// 自定义时间查询规则
|
||||||
|
'time_query_rule' => [],
|
||||||
|
|
||||||
|
// 自动写入时间戳字段
|
||||||
|
// true为自动识别类型 false关闭
|
||||||
|
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
|
||||||
|
'auto_timestamp' => true,
|
||||||
|
|
||||||
|
// 时间字段取出后的默认时间格式
|
||||||
|
'datetime_format' => 'Y-m-d H:i:s',
|
||||||
|
|
||||||
|
// 数据库连接配置信息
|
||||||
|
'connections' => [
|
||||||
|
'mysql' => [
|
||||||
|
// 数据库类型
|
||||||
|
'type' => 'mysql',
|
||||||
|
// 服务器地址
|
||||||
|
'hostname' => env('database.hostname', 'localhost'),
|
||||||
|
// 数据库名
|
||||||
|
'database' => env('database.database', 'shop_mallnew'),
|
||||||
|
// 用户名
|
||||||
|
'username' => env('database.username', 'shop_mallnew'),
|
||||||
|
// 密码
|
||||||
|
'password' => env('database.password', 'shop_mallnew'),
|
||||||
|
// 端口
|
||||||
|
'hostport' => env('database.hostport', '3306'),
|
||||||
|
// 数据库连接参数
|
||||||
|
'params' => [],
|
||||||
|
// 数据库编码默认采用utf8
|
||||||
|
'charset' => env('database.charset', 'utf8mb4'),
|
||||||
|
// 数据库表前缀
|
||||||
|
'prefix' => 'lucky_',
|
||||||
|
|
||||||
|
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||||
|
'deploy' => 0,
|
||||||
|
// 数据库读写是否分离 主从式有效
|
||||||
|
'rw_separate' => false,
|
||||||
|
// 读写分离后 主服务器数量
|
||||||
|
'master_num' => 1,
|
||||||
|
// 指定从服务器序号
|
||||||
|
'slave_no' => '',
|
||||||
|
// 是否严格检查字段是否存在
|
||||||
|
'fields_strict' => false,
|
||||||
|
// 是否需要断线重连
|
||||||
|
'break_reconnect' => false,
|
||||||
|
// 监听SQL
|
||||||
|
'trigger_sql' => true,
|
||||||
|
// 开启字段缓存
|
||||||
|
'fields_cache' => false,
|
||||||
|
// 字段缓存路径
|
||||||
|
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||||
|
],
|
||||||
|
'rrdata' => [//旧版人人商城数据库
|
||||||
|
// 数据库类型
|
||||||
|
'type' => 'mysql',
|
||||||
|
|
||||||
|
/*新服务器*/
|
||||||
|
'hostname' => env('rrdatabase.hostname', 'localhost'),
|
||||||
|
/*旧服务器*/
|
||||||
|
// 'hostname' => '47.110.82.193',
|
||||||
|
// 数据库名
|
||||||
|
'database' => '5g',
|
||||||
|
// 用户名
|
||||||
|
'username' => '5g',
|
||||||
|
// 密码
|
||||||
|
'password' => '123456',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 端口
|
||||||
|
'hostport' => '3306',
|
||||||
|
// 数据库连接参数
|
||||||
|
'params' => [],
|
||||||
|
// 数据库编码默认采用utf8
|
||||||
|
'charset' => 'utf8',
|
||||||
|
// 数据库表前缀
|
||||||
|
'prefix' => 'ims_',
|
||||||
|
|
||||||
|
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||||
|
'deploy' => 0,
|
||||||
|
// 数据库读写是否分离 主从式有效
|
||||||
|
'rw_separate' => false,
|
||||||
|
// 读写分离后 主服务器数量
|
||||||
|
'master_num' => 1,
|
||||||
|
// 指定从服务器序号
|
||||||
|
'slave_no' => '',
|
||||||
|
// 是否严格检查字段是否存在
|
||||||
|
'fields_strict' => false,
|
||||||
|
// 是否需要断线重连
|
||||||
|
'break_reconnect' => false,
|
||||||
|
// 监听SQL
|
||||||
|
'trigger_sql' => false,
|
||||||
|
// 开启字段缓存
|
||||||
|
'fields_cache' => false,
|
||||||
|
// 字段缓存路径
|
||||||
|
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||||
|
],
|
||||||
|
/* 'v3' => [
|
||||||
|
// 数据库类型
|
||||||
|
'type' => 'mysql',
|
||||||
|
// 服务器地址
|
||||||
|
'hostname' => '',
|
||||||
|
// 数据库名
|
||||||
|
'database' => '',
|
||||||
|
// 用户名
|
||||||
|
'username' => '',
|
||||||
|
// 密码
|
||||||
|
'password' => '',
|
||||||
|
// 端口
|
||||||
|
'hostport' => '3306',
|
||||||
|
// 数据库连接参数
|
||||||
|
'params' => [],
|
||||||
|
// 数据库编码默认采用utf8
|
||||||
|
'charset' => 'utf8',
|
||||||
|
// 数据库表前缀
|
||||||
|
'prefix' => '',
|
||||||
|
|
||||||
|
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||||
|
'deploy' => 0,
|
||||||
|
// 数据库读写是否分离 主从式有效
|
||||||
|
'rw_separate' => false,
|
||||||
|
// 读写分离后 主服务器数量
|
||||||
|
'master_num' => 1,
|
||||||
|
// 指定从服务器序号
|
||||||
|
'slave_no' => '',
|
||||||
|
// 是否严格检查字段是否存在
|
||||||
|
'fields_strict' => false,
|
||||||
|
// 是否需要断线重连
|
||||||
|
'break_reconnect' => false,
|
||||||
|
// 监听SQL
|
||||||
|
'trigger_sql' => false,
|
||||||
|
// 开启字段缓存
|
||||||
|
'fields_cache' => true,
|
||||||
|
// 字段缓存路径
|
||||||
|
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||||
|
],*/
|
||||||
|
// 更多的数据库配置信息
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
@@ -68,11 +68,12 @@ if ($appEnv) {
|
|||||||
if (is_file($envFile)) {
|
if (is_file($envFile)) {
|
||||||
$app->env->load($envFile);
|
$app->env->load($envFile);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
echo "⚠️ 警告:未设置APP_ENV环境变量,默认使用local环境。\n";
|
||||||
// 3. 为了兼容性,如果存在.env.local也加载(优先级最高)
|
// 3. 为了兼容性,如果存在.env.local也加载(优先级最高)
|
||||||
if (is_file(__DIR__ . '/.env.local')) {
|
if (is_file(__DIR__ . '/.env.local')) {
|
||||||
$app->env->load(__DIR__ . '/.env.local');
|
$app->env->load(__DIR__ . '/.env.local');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行HTTP应用并响应
|
// 执行HTTP应用并响应
|
||||||
|
|||||||
10
src/think
10
src/think
@@ -21,12 +21,14 @@ if ($appEnv) {
|
|||||||
if (is_file($envFile)) {
|
if (is_file($envFile)) {
|
||||||
$app->env->load($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');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用初始化
|
// 应用初始化
|
||||||
$app->console->run();
|
$app->console->run();
|
||||||
Reference in New Issue
Block a user