feat(fsgx): 完成全部24项开发任务 Phase1-7

Phase1 后端核心:
- 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess)
- SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机)
- StoreOrderCreateServices 周期循环佣金计算
- StoreOrderTakeServices 佣金发放后同步冻结积分
- StoreProductServices/StoreProduct 保存 is_queue_goods

Phase2 后端接口:
- GET /api/hjf/brokerage/progress 佣金周期进度
- GET /api/hjf/assets/overview 资产总览
- HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务
- PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口
- GET /adminapi/hjf/points/release_log 积分日志接口

Phase3 前端清理:
- hjfCustom.js 路由精简(仅保留 points/log)
- hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口
- pages.json 公排→推荐佣金/佣金记录/佣金规则

Phase4-5 前端改造:
- queue/status.vue 推荐佣金进度页整体重写
- 商品详情/订单确认/支付结果页文案与逻辑改造
- 个人中心/资产页/引导页/规则页文案改造
- HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造
- 推广中心嵌入佣金进度摘要
- hjfMockData.js 全量更新(公排字段→佣金字段)

Phase6 Admin 增强:
- 用户列表新增 frozen_points/available_points 列及不考核操作按钮
- hjfPoints.js USE_MOCK=false 对接真实积分日志接口

Phase7 配置文档:
- docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单

Made-with: Cursor
This commit is contained in:
apple
2026-03-23 22:32:19 +08:00
parent 788ee0c0c0
commit 434aa8c69d
13098 changed files with 2008990 additions and 961 deletions

View File

@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
use \Fastknife\Service\BlockPuzzleCaptchaService;
class BlockPuzzleController
{
public function get(){
$config = require '../src/config.php';
$service = new BlockPuzzleCaptchaService($config);
$data = $service->get();
echo json_encode([
'error' => false,
'repCode' => '0000',
'repData' => $data,
'repMsg' => null,
'success' => true,
]);
}
/**
* 一次验证
*/
public function check()
{
$config = require '../src/config.php';
$service = new BlockPuzzleCaptchaService($config);
$data = $_REQUEST;
$msg = null;
$error = false;
$repCode = '0000';
try {
$service->check($data['token'], $data['pointJson']);
} catch (\Exception $e) {
$msg = $e->getMessage();
$error = true;
$repCode = '6111';
}
echo json_encode([
'error' => $error,
'repCode' => $repCode,
'repData' => null,
'repMsg' => $msg,
'success' => ! $error,
]);
}
/**
* 二次验证
*/
public function verification()
{
$config = require '../src/config.php';
$service = new BlockPuzzleCaptchaService($config);
$data = $_REQUEST;
$msg = null;
$error = false;
$repCode = '0000';
try {
if(isset($data['captchaVerification'])){
$service->verificationByEncryptCode($data['captchaVerification']);
}else if (isset($data['token']) && isset($data['pointJson'])){
$service->verification($data['token'], $data['pointJson']);
} else {
throw new \Exception('参数错误!');
}
} catch (\Exception $e) {
$msg = $e->getMessage();
$error = true;
$repCode = '6111';
}
echo json_encode([
'error' => $error,
'repCode' => $repCode,
'repData' => null,
'repMsg' => $msg,
'success' => ! $error,
]);
}
}

View File

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
use Fastknife\Utils\RandomUtils;
use Fastknife\Service\ClickWordCaptchaService;
class ClickWordController
{
public function get()
{
$config = require '../src/config.php';
$service = new ClickWordCaptchaService($config);
$data = $service->get();
echo json_encode([
'error' => false,
'repCode' => '0000',
'repData' => $data,
'repMsg' => null,
'success' => true,
]);
}
/**
* 一次验证
*/
public function check()
{
$config = require '../src/config.php';
$service = new ClickWordCaptchaService($config);
$data = $_REQUEST;
$msg = null;
$error = false;
$repCode = '0000';
try {
$service->check($data['token'], $data['pointJson']);
} catch (\Exception $e) {
$msg = $e->getMessage();
$error = true;
$repCode = '6111';
}
echo json_encode([
'error' => $error,
'repCode' => $repCode,
'repData' => null,
'repMsg' => $msg,
'success' => ! $error,
]);
}
/**
* 二次验证
*/
public function verification()
{
$config = require '../src/config.php';
$service = new ClickWordCaptchaService($config);
$data = $_REQUEST;
$msg = null;
$error = false;
$repCode = '0000';
try {
if(isset($data['captchaVerification'])){
$service->verificationByEncryptCode($data['captchaVerification']);
}else if (isset($data['token']) && isset($data['pointJson'])){
$service->verification($data['token'], $data['pointJson']);
} else {
throw new \Exception('参数错误!');
}
} catch (\Exception $e) {
$msg = $e->getMessage();
$error = true;
$repCode = '6111';
}
echo json_encode([
'error' => $error,
'repCode' => $repCode,
'repData' => null,
'repMsg' => $msg,
'success' => ! $error,
]);
}
}

View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
(function () {
foreach ([
'vendor/autoload.php',
'../vendor/autoload.php',
'../../vendor/autoload.php',
'../../../vendor/autoload.php',
'../../../../vendor/autoload.php'
] as $file) {
if (is_file($file)) {
/** @noinspection PhpIncludeInspection */
include $file;
}
}
})();

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
require 'autoload.php';
$captchaType = @$_REQUEST['captchaType'];
if (!in_array($captchaType, ['clickWord', 'blockPuzzle'])) {
throw new Exception('缺少参数:captchaType');
}
$controllerName = ucfirst($captchaType) . 'Controller';
require $controllerName . '.php';
$controller = new $controllerName;
$controller->check();

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
require 'autoload.php';
$captchaType = @$_REQUEST['captchaType'];
if (!in_array($captchaType, ['clickWord', 'blockPuzzle'])) {
throw new Exception('缺少参数:captchaType');
}
$controllerName = ucfirst($captchaType) . 'Controller';
require $controllerName . '.php';
$controller = new $controllerName;
$controller->get();

View File

@@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use Fastknife\Exception\ParamException;
use Fastknife\Service\BlockPuzzleCaptchaService;
use Fastknife\Service\ClickWordCaptchaService;
use Fastknife\Service\Service;
use Illuminate\Support\Facades\Request;
class IndexController
{
public function index()
{
try {
$service = $this->getCaptchaService();
$data = $service->get();
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
return $this->success($data);
}
/**
* 一次验证
* @return array
*/
public function check()
{
try {
$data = $this->validate();
$service = $this->getCaptchaService();
$service->check($data['token'], $data['pointJson']);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
return $this->success([]);
}
/**
* 二次验证
* @return array
*/
public function verification()
{
try {
$data = $this->validate();
$service = $this->getCaptchaService();
$service->verification($data['token'], $data['pointJson']);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
return $this->success([]);
}
protected function getCaptchaService()
{
$captchaType = request()->post('captchaType', null);
$config = config('captcha');
switch ($captchaType) {
case "clickWord":
$service = new ClickWordCaptchaService($config);
break;
case "blockPuzzle":
$service = new BlockPuzzleCaptchaService($config);
break;
default:
throw new ParamException('captchaType参数不正确');
}
return $service;
}
protected function validate()
{
return Request::instance()->validate([
'token' => 'bail|required',
'pointJson' => 'required',
]);
}
protected function success($data)
{
return [
'error' => false,
'repCode' => '0000',
'repData' => $data,
'repMsg' => null,
'success' => true,
];
}
protected function error($msg)
{
return [
'error' => true,
'repCode' => '6111',
'repData' => null,
'repMsg' => $msg,
'success' => false,
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
/**
* 请将该文件放置于config目录
*/
return [
'font_file' => '', //自定义字体包路径, 不填使用默认值
//文字验证码
'click_world' => [
'backgrounds' => []
],
//滑动验证码
'block_puzzle' => [
'backgrounds' => [], //背景图片路径, 不填使用默认值
'templates' => [], //模板图
'offset' => 10, //容错偏移量
],
//水印
'watermark' => [
'fontsize' => 12,
'color' => '#ffffff',
'text' => '我的水印'
],
'cache' => [
'constructor' => [\Illuminate\Support\Facades\Cache::class, 'store'],
'method' => [
'get' => 'get', //获取
'set' => 'set', //设置
'delete' => 'delete',//删除
'has' => 'has' //key是否存在
]
]
];

View File

@@ -0,0 +1,3 @@
#### 这个是一个demo测试目录。
* 当前目录下的php文件是不基于任何框架的demo
* thinkphp 目录是基于thinkphp框架的demo

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
require "autoload.php";
use \Fastknife\Utils\AesUtils;
$key = "oc7ygju8xf03ov4ttd5ito7qnuapyp6s";
$point = [
['x' => 135, 'y' => 58],
['x' => 82, 'y' => 72],
['x' => 56, 'y' => 112]
];
$point = json_encode($point);
//[{"x":135,"y":58},{"x":82,"y":72},{"x":56,"y":112}]
//var_dump();
//print_r(AesUtils::encrypt($point,$key));
//php w2GGF3+0q0K0AdTysBEKynRo9hXBbXBPUZU1GPWJKlM4SwtrbmV17CFcTq/T53Kvlk0FWSbFzfCC1NuAA6wsmw==
//js FOl3kz52f4xptJ/Zf7MoZYQmYa7C1pjQaWP8QqhcX8FH43SvpCBPhaSqqMbE8D55ufhgjBVor01UZRH3uE6DNw==
//js +5s4V1MeDYk1jpvfwJACJA==
//php C01B0oArq8aMhlMmSdRbDA==

View File

@@ -0,0 +1,21 @@
<?php
use Fastknife\Domain\Logic\Cache;
include '../src/Domain/Logic/Cache.php';
include '../src/Utils/CacheUtils.php';
$config = include '../src/config.php';
$cacheEntity = new Cache($config['cache']);
var_dump($cacheEntity->get('haha'));
$cacheEntity->set('haha', 1, 60);
var_dump($cacheEntity->has('haha'));
var_dump($cacheEntity->get('haha'));
$cacheEntity->delete('haha');
var_dump($cacheEntity->get('haha'));

View File

@@ -0,0 +1,28 @@
<?php
use Fastknife\Domain\Factory;
require 'autoload.php';
$config = require '../src/config.php';
function showBlock()
{
global $config;
$factory = new Factory($config);
$blockImage = $factory->makeBlockImage();
$blockImage->run();
$blockImage->echo();
}
function showWord()
{
global $config;
$factory = new Factory($config);
$blockImage = $factory->makeWordImage();
$blockImage->run();
$blockImage->echo();
}
showWord();

View File

@@ -0,0 +1,116 @@
<?php
namespace app\controller;
use Fastknife\Exception\ParamException;
use Fastknife\Service\ClickWordCaptchaService;
use Fastknife\Service\BlockPuzzleCaptchaService;
use Fastknife\Service\Service;
use think\exception\HttpResponseException;
use think\facade\Validate;
use think\Response;
/**
* 该文件位于controller目录下
* Class Index
* @package app\controller
*/
class Index
{
public function index()
{
try {
$service = $this->getCaptchaService();
$data = $service->get();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success($data);
}
/**
* 一次验证
*/
public function check()
{
$data = request()->post();
try {
$this->validate($data);
$service = $this->getCaptchaService();
$service->check($data['token'], $data['pointJson']);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success([]);
}
/**
* 二次验证
*/
public function verification()
{
$data = request()->post();
try {
$this->validate($data);
$service = $this->getCaptchaService();
$service->verification($data['token'], $data['pointJson']);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success([]);
}
protected function getCaptchaService()
{
$captchaType = request()->post('captchaType', null);
$config = config('captcha');
switch ($captchaType) {
case "clickWord":
$service = new ClickWordCaptchaService($config);
break;
case "blockPuzzle":
$service = new BlockPuzzleCaptchaService($config);
break;
default:
throw new ParamException('captchaType参数不正确');
}
return $service;
}
protected function validate($data)
{
$rules = [
'token' => ['require'],
'pointJson' => ['require']
];
$validate = Validate::rule($rules)->failException(true);
$validate->check($data);
}
protected function success($data)
{
$response = [
'error' => false,
'repCode' => '0000',
'repData' => $data,
'repMsg' => null,
'success' => true,
];
throw new HttpResponseException(Response::create($response, 'json'));
}
protected function error($msg)
{
$response = [
'error' => true,
'repCode' => '6111',
'repData' => null,
'repMsg' => $msg,
'success' => false,
];
throw new HttpResponseException(Response::create($response, 'json'));
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
/**
* 请将该文件放置于config目录
*/
return [
'font_file' => '', //自定义字体包路径, 不填使用默认值
//文字验证码
'click_world' => [
'backgrounds' => []
],
//滑动验证码
'block_puzzle' => [
'backgrounds' => [], //背景图片路径, 不填使用默认值
'templates' => [], //模板图
'offset' => 10, //容错偏移量
],
//水印
'watermark' => [
'fontsize' => 12,
'color' => '#ffffff',
'text' => '我的水印'
],
'cache' => [
'constructor' => [\think\facade\Cache::class, 'instance']
]
];

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
require 'autoload.php';
$captchaType = @$_REQUEST['captchaType'];
if (!in_array($captchaType, ['clickWord', 'blockPuzzle'])) {
throw new Exception('缺少参数:captchaType');
}
$controllerName = ucfirst($captchaType) . 'Controller';
require $controllerName . '.php';
$controller = new $controllerName;
$controller->verification();