chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use think\Request;
use ywxapp\controller\FrontendBase;
/**
* About 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class About extends FrontendBase
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
return view('index', [
'controller' => $this->request->controller(),
'email' => $this->request->controller(),
'latest_news' => [],
]);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id = null)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
declare (strict_types = 1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* 客户案例
*/
class Cases extends FrontendBase
{
protected $noNeedLogin = ['*'];
protected $noNeedVerify = ['*'];
public function index()
{
$cases = [
['title' => '某科技公司', 'brief' => '官网+电商一体化部署,3 天快速上线', 'logo' => '/static/frontend/img/case1.jpg'],
['title' => '某制造企业', 'brief' => '会员与订单系统打通,运营效率提升 40%', 'logo' => '/static/frontend/img/case2.jpg'],
['title' => '某教育机构', 'brief' => '表单引擎采集学员信息,转化率翻倍', 'logo' => '/static/frontend/img/case3.jpg'],
['title' => '某零售连锁', 'brief' => '多门店统一后台,数据实时汇总', 'logo' => '/static/frontend/img/case4.jpg'],
['title' => '某医疗平台', 'brief' => '在线预约与会员体系结合,服务更贴心', 'logo' => '/static/frontend/img/case5.jpg'],
['title' => '某金融企业', 'brief' => '插件化风控模块,按需启用安全合规', 'logo' => '/static/frontend/img/case6.jpg'],
['title' => '某物流公司', 'brief' => '订单追踪与支付打通,全程可视', 'logo' => '/static/frontend/img/case7.jpg'],
['title' => '某政务系统', 'brief' => '多应用隔离部署,权限分级清晰', 'logo' => '/static/frontend/img/case8.jpg'],
['title' => '某文创品牌', 'brief' => '精美模板 + 营销插件,品牌声量提升', 'logo' => '/static/frontend/img/case9.jpg'],
];
return view('case/index', [
'cases' => $cases,
]);
}
}
+102
View File
@@ -0,0 +1,102 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use think\Request;
use ywxapp\controller\FrontendBase;
/**
* Contact 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Contact extends FrontendBase
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
return view('index', [
'controller' => $this->request->controller(),
'email' => $this->request->controller(),
'latest_news' => [ ],
]);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id = null)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
declare (strict_types = 1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* 文档 / 示例入口(由 app/wxapp 合并至 app/frontend
*/
class Doc extends FrontendBase
{
protected $noNeedLogin = ['index'];
protected $noNeedVerify = ['*'];
public function index()
{
$docs = [
[
'title' => 'mqpay 支付钩子机制与时序图',
'desc' => '事件系统、订阅器注册、会员开通链路详解',
'path' => 'addon/mqpay/docs/payment_hooks.md',
'url' => '/addon/mqpay/docs/payment_hooks.md',
],
[
'title' => '安卓到账监听 App 接入指南',
'desc' => '免签监听 App 对接 notify-app 接口说明',
'path' => 'addon/mqpay/docs/listen_app_guide.md',
'url' => '/addon/mqpay/docs/listen_app_guide.md',
],
[
'title' => 'mqpay 插件总览',
'desc' => '插件能力、配置项、钩子速查表',
'path' => 'addon/mqpay/README.md',
'url' => '/addon/mqpay/README.md',
],
];
return view('doc/index', [
'controller' => $this->request->controller(),
'docs' => $docs,
]);
}
}
+106
View File
@@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* 特性详情(由 app/wxapp 合并至 app/frontend
*/
class Feature extends FrontendBase
{
protected $noNeedLogin = ['index', 'detail'];
protected $noNeedVerify = ['*'];
// 四大特性元数据
private $items = [
'plugin' => [
'title' => '插件机制',
'summary' => '基于 ThinkPHP 事件系统 + 订阅器的热插拔插件架构。',
'points' => [
'插件在 info.php 的 events.subscribe 声明订阅器类',
'AppService 启动时自动 loadEvent 注册,无需手动绑定',
'订阅方法 onXxx 自动监听对应事件,与业务完全解耦',
'后台可在线安装 / 启用 / 禁用 / 卸载',
],
'code' => "## 插件订阅器示例(mqpay
class Payment extends \\ywxapp\\addon {
// 监听支付方式列表事件
public function onPaymentMethods(\$event) {
return ['personal' => ['name'=>'免签支付','sort'=>10]];
}
// 监听支付创建事件,生成收款码
public function onPaymentCreate(\$event) { /* ... */ }
}",
],
'multi-app' => [
'title' => '多应用架构',
'summary' => 'app 目录下按业务域拆分多个独立应用,互不干扰。',
'points' => [
'api → 对外 JSON 接口(移动端 / 第三方)',
'backend → 管理后台(RBAC 权限)',
'member → 会员中心(支付 / 订单 / 会员)',
'frontend → 标准 Web 前端',
'site → 本展示官网',
],
'code' => "# route/app.php 按应用分组
Route::group('api', function () {
Route::get('user/info', 'api/v1.user/info');
});",
],
'member-pay' => [
'title' => '会员 / 支付',
'summary' => 'mqpay 免签支付 + 会员开通事件链,扫码到账自动开通。',
'points' => [
'免签支付:监听系统通知栏,到账自动确认',
'安卓调用 POST /mqpay/pay/notify-app 验签确认',
'confirmOrder() 触发 UserMemberActivate 事件',
'会员监听器顺延会员期限并写入权益',
],
'code' => "// confirmOrder 内触发会员开通
Event::trigger('UserMemberActivate', [
'uid' => \$order['uid'],
'plan_id' => \$order['plan_id'],
'order' => \$order,
'method' => 'personal',
]);",
],
'doc' => [
'title' => '文档 / 示例',
'summary' => '完善的开发文档、API 示例与快速开始指南。',
'points' => [
'插件 README + docs 文档体系',
'API 示例与请求 / 响应契约',
'快速开始指南降低上手成本',
'钩子 / 事件速查表一键索引',
],
'code' => "# 查看支付钩子文档
addon/mqpay/docs/payment_hooks.md
addon/mqpay/docs/listen_app_guide.md",
],
];
public function index()
{
return view('feature/index', [
'controller' => $this->request->controller(),
'items' => $this->items,
]);
}
public function detail($name = 'plugin')
{
if (!isset($this->items[$name])) {
$name = 'plugin';
}
$item = $this->items[$name];
return view('feature/detail', [
'controller' => $this->request->controller(),
'name' => $name,
'item' => $item,
'items' => $this->items,
]);
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace app\frontend\controller;
use think\facade\Db;
use ywxapp\controller\FrontendBase;
use ywxapp\model\Help as HelpModel;
/**
* 站点帮助中心(前台)
*/
class Help extends FrontendBase
{
/**
* 帮助中心首页:按分类分组列出所有启用项
*/
public function index()
{
$list = (new HelpModel())
->where('status', 1)
->order('sort', 'desc')
->order('id', 'desc')
->field('id,category,title,view_count')
->select()
->toArray();
$groups = [];
foreach ($list as $item) {
$cat = $item['category'] ?: '其他';
$groups[$cat][] = $item;
}
// 维护分类顺序(按首个条目出现顺序)
$categories = [];
foreach ($groups as $cat => $items) {
$categories[] = ['name' => $cat, 'items' => $items];
}
$this->assign('categories', $categories);
return $this->fetch();
}
/**
* 帮助详情
*/
public function read($id = null)
{
if (empty($id)) {
$this->error('参数错误');
}
$info = (new HelpModel())->where('id', $id)->where('status', 1)->find();
if (empty($info)) {
$this->error('帮助内容不存在或已下架');
}
// 浏览量自增
Db::name('help')->where('id', $id)->inc('view_count')->update();
$this->assign('info', $info);
return $this->fetch('read');
}
}
+84
View File
@@ -0,0 +1,84 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* Index 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Index extends FrontendBase
{
/**
* Summary of needLogin
* @var array
*/
protected $noNeedLogin = ["index", "hello"];
/**
* Summary of needRight
* @var array
*/
protected $noNeedVerify = [];
/**
* 控制器初始化 initialize
* @return void
*/
protected function initialize()
{
}
public function index()
{
// 模拟新闻数据(实际从数据库获取)
$latest_news = [
[
'id' => 1,
'title' => '公司荣获2023年度创新企业奖',
'description' => '在近日举办的行业峰会上...',
'create_at' => date('Y-m-d H:i:s'),
'views' => 128,
],
[
'id' => 2,
'title' => '智创科技发布新一代企业服务平台',
'description' => '全新平台整合了...',
'create_at' => date('Y-m-d H:i:s',
strtotime('-2 days')),
'views' => 256,
],
// ...更多数据
];
return view('index', [
'site_name' => '智创科技',
'seo_keywords' => '企业服务,数字化转型,软件开发',
'seo_description' => '智创科技专注企业数字化解决方案,10年行业经验,服务1000+企业客户',
'contact_phone' => '400-888-9999',
'contact_email' => 'service@zhichuang.com',
'company_address' => '北京市海淀区中关村大厦18层',
'icp_number' => '京ICP备12345678号',
'controller' => $this->request->controller(),
'latest_news' => $latest_news,
]);
}
public function hello($name = 'ThinkPHP8')
{
return 'hello,' . $name;
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use think\Request;
use ywxapp\controller\FrontendBase;
/**
* News 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class News extends FrontendBase
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
return view('index', [
'controller' => $this->request->controller(),
'email' => $this->request->controller(),
'latest_news' => [],
'news_list' => [],
]);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
return view('read', [
'controller' => $this->request->controller(),
'email' => $this->request->controller(),
'latest_news' => [],
]);
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id = null)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use think\facade\Db;
use think\facade\View;
use ywxapp\controller\FrontendBase;
use ywxapp\model\Notice as NoticeModel;
/**
* 前台站点公告(方案 B:列表 + 详情)
*/
class Notice extends FrontendBase
{
protected $noNeedLogin = ['index', 'read'];
/**
* 公告列表
*/
public function index()
{
$page = $this->request->param('page/d', 1);
$type = $this->request->param('type/d', 0);
$list = NoticeModel::getList($page, 10, $type);
// 附加类型文案
$typeList = NoticeModel::typeList();
$items = $list->items();
foreach ($items as &$it) {
$it['type_text'] = $typeList[$it['type']] ?? '公告';
}
unset($it);
View::assign('title', '站点公告 - YwxApp');
return view('index', [
'type' => $type,
'type_list' => $typeList,
'list' => $list,
'items' => $items,
]);
}
/**
* 公告详情
*/
public function read($id = null)
{
$id = $id ?: $this->request->param('id/d');
if (! $id) {
$this->redirect('notice/index');
}
$info = (new NoticeModel())->where('status', 1)->find($id);
if (! $info) {
$this->redirect('notice/index');
}
// 浏览量自增(模型 view_count 为 readonly,用 Db 原生 inc 绕过)
Db::name('notice')->where('id', $id)->inc('view_count')->update();
$info->view_count = ($info->view_count ?? 0) + 1;
$typeList = NoticeModel::typeList();
$info->type_text = $typeList[$info['type']] ?? '公告';
View::assign('title', ($info->title ?? '公告详情') . ' - YwxApp');
return view('read', [
'info' => $info,
]);
}
}
+73
View File
@@ -0,0 +1,73 @@
<?php
declare (strict_types = 1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* 插件机制展示页(由 app/wxapp 合并至 app/frontend
*/
class Plugin extends FrontendBase
{
protected $noNeedLogin = ['*'];
protected $noNeedVerify = ['*'];
public function index()
{
// 展示应用市场在线插件列表(中心站读本地库 / 客户机代理中心站 API)
$items = [];
$categories = [];
$errMsg = '';
try {
if (is_market_client()) {
// 客户机:经 RemoteAppmallService 拉取中心站列表
$resp = \ywxapp\service\RemoteAppmallService::instance()->lists([
'page' => 1,
'page_size' => 24,
]);
if (!empty($resp['success']) && !empty($resp['data']['list'])) {
$items = $resp['data']['list'];
} else {
$errMsg = $resp['message'] ?? '暂无插件';
}
} else {
// 中心站:直接读本地市场库(appmall_addon_list
$catalog = \addon\appmall\service\MarketService::instance()->catalog();
$items = $catalog['list'] ?? [];
$categories = $catalog['categories'] ?? [];
}
} catch (\Throwable $e) {
$errMsg = '市场列表加载失败:' . $e->getMessage();
}
$plugins = [];
foreach ($items as $it) {
$price = (float) ($it['price'] ?? 0);
$plugins[] = [
'id' => $it['id'] ?? 0,
'name' => $it['name'] ?? '',
'title' => $it['title'] ?? ($it['name'] ?? ''),
'desc' => $it['intro'] ?? '',
'version' => $it['version'] ?? '',
'author' => $it['author'] ?? '',
'logo' => $it['logo'] ?? '',
'price' => $price,
'price_text' => $price > 0 ? '¥' . number_format($price, 2) : '免费',
'rating' => (float) ($it['rating'] ?? 0),
'downloads' => (int) ($it['download_count'] ?? 0),
'category' => $it['category'] ?? '',
'type' => $it['type'] ?? 'addon',
];
}
return view('plugin/index', [
'title' => '插件市场',
'controller' => 'Plugin',
'plugins' => $plugins,
'categories' => $categories,
'err_msg' => $errMsg,
'hooks' => [],
]);
}
}
+98
View File
@@ -0,0 +1,98 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app\frontend\controller;
use think\Request;
use ywxapp\controller\FrontendBase;
/**
* Product 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class Product extends FrontendBase
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
return $this->view->fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id = null)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php
declare (strict_types = 1);
namespace app\frontend\controller;
use ywxapp\controller\FrontendBase;
/**
* 展示官网首页(由 app/wxapp 合并至 app/frontend
*/
class Site extends FrontendBase
{
protected $noNeedLogin = ['*'];
protected $noNeedVerify = ['*'];
public function index()
{
// 已启用插件数(扫描 addon 目录 + info.php
$plugins = $this->scanaddon();
$pluginCount = count(array_filter($plugins, fn($p) => ($p['state'] ?? 0) == 1));
// 应用模块数(app 目录下)
$appDir = root_path() . 'app';
$apps = array_filter(scandir($appDir), function ($d) use ($appDir) {
return $d !== '.' && $d !== '..' && is_dir($appDir . DIRECTORY_SEPARATOR . $d);
});
$features = [
[
'icon' => 'plugin',
'title' => '插件机制',
'desc' => '基于事件订阅器的热插拔插件,钩子自动注册,与业务完全解耦。',
'url' => url('feature/detail', ['name' => 'plugin']),
],
[
'icon' => 'app',
'title' => '多应用架构',
'desc' => 'api / backend / member / frontend 多应用隔离,路由分组清晰。',
'url' => url('feature/detail', ['name' => 'multi-app']),
],
[
'icon' => 'vip',
'title' => '会员 / 支付',
'desc' => 'mqpay 免签支付 + 会员开通事件链,扫码即到帐自动开通。',
'url' => url('feature/detail', ['name' => 'member-pay']),
],
[
'icon' => 'doc',
'title' => '文档 / 示例',
'desc' => '完善的开发文档、API 示例与快速开始指南,开箱即用。',
'url' => url('feature/detail', ['name' => 'doc']),
],
];
return view('site/index', [
'controller' => $this->request->controller(),
'features' => $features,
'pluginCount' => $pluginCount,
'appCount' => count($apps),
]);
}
/**
* 扫描 addon 目录,读取各插件 info.php
*/
private function scanaddon(): array
{
$dir = root_path() . 'addon';
$list = [];
if (!is_dir($dir)) {
return $list;
}
foreach (scandir($dir) as $name) {
if ($name === '.' || $name === '..' || !is_dir($dir . DIRECTORY_SEPARATOR . $name)) {
continue;
}
$infoFile = $dir . DIRECTORY_SEPARATOR . $name . DIRECTORY_SEPARATOR . 'info.php';
if (!is_file($infoFile)) {
continue;
}
$info = include $infoFile;
if (is_array($info)) {
$list[] = $info;
}
}
return $list;
}
}