feat: 公共表更名 common/member 前缀 + 插件命令自动加载 + 版本 1.1.1
- 18 张公共表更名(addon/attachment/configure/links/spider_log/spider_stat/sms/notice/ad/task/prop/medal/help/card -> common_*,member_wallets->member_wallet,score_rule/score_log -> member_*,addon_config->common_addonconf),模型全部对齐新表名,Db 直引用清零 - Attachment 模型补 表名绑定,修复富文本上传查 wxapp_attachment 1146 隐患 - install.sql + 迁移 SQL:backend_admin/backend_role delete_at 默认 0,修复软删除(NULL != 0)误过滤导致后台菜单为空 - AppService::boot() 支持插件 info.php 声明 commands 自动注册插件命令(psr-4 自动加载,坏类名自动跳过) - 各插件(haonav/mqttbroker/wxchat/articles/blog/forum 等)字段与配置同步调整 - 框架版本 1.1.0 -> 1.1.1
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace addon\download\controller;
|
||||
|
||||
use think\facade\Config;
|
||||
use think\facade\Lang;
|
||||
use think\facade\Cookie;
|
||||
use think\Response;
|
||||
use ywxapp\controller\FrontendBase;
|
||||
use addon\download\model\Category;
|
||||
use addon\download\model\Resource;
|
||||
use addon\download\service\DownloadService;
|
||||
|
||||
class Index extends FrontendBase
|
||||
{
|
||||
protected $noNeedLogin = ['*'];
|
||||
protected $noNeedVerify = ['*'];
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
// 多语言:支持 ?lang=zh-cn|en-us 切换并写 cookie;插件级 lang 显式加载兜底
|
||||
$lang = $this->request->param('lang', '');
|
||||
if (in_array($lang, ['zh-cn', 'en-us'], true)) {
|
||||
Lang::setLangSet($lang);
|
||||
Cookie::set('download_lang', $lang);
|
||||
} elseif ($cookie = Cookie::get('download_lang')) {
|
||||
Lang::setLangSet($cookie);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 固定页面文案注入模板
|
||||
$this->view->assign([
|
||||
'site_name' => lang('site_name'),
|
||||
'all_category_text' => lang('all_category'),
|
||||
'hot_text' => lang('hot'),
|
||||
'latest_text' => lang('latest'),
|
||||
'list_text' => lang('list'),
|
||||
'detail_text' => lang('detail'),
|
||||
'search_text' => lang('search'),
|
||||
'search_placeholder' => lang('search_placeholder'),
|
||||
'download_btn_text' => lang('download_btn'),
|
||||
]);
|
||||
|
||||
// 插件前台接入「全站动态布局」:视图只写正文,由核心 frontend 的
|
||||
// common/layout.html 包裹全站 header / footer(与开发文档约定一致)。
|
||||
// 注意:layout_name 必须带 .html 扩展名,否则 think-template 的
|
||||
// parseTemplateFile() 会把无扩展名的绝对路径里的盘符冒号(D:)当成
|
||||
// 模板分隔符替换成当前 viewPath,导致「模板文件不存在」。
|
||||
$this->view->config([
|
||||
'layout_on' => true,
|
||||
'layout_name' => $this->app->getRootPath() . 'app' . DIRECTORY_SEPARATOR
|
||||
. 'frontend' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR
|
||||
. 'common' . DIRECTORY_SEPARATOR . 'layout.html',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取本插件配置(运行时由 AppInit 注入 config('download'))
|
||||
*/
|
||||
protected function pluginConfig(): array
|
||||
{
|
||||
return Config::get('download', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页:分类导航 + 热门/最新(按 config 开关)
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$cfg = $this->pluginConfig();
|
||||
|
||||
$categories = Category::with(['resources' => function ($q) {
|
||||
$q->order('downloads', 'desc')->limit(8);
|
||||
}])
|
||||
->where('pid', 0)
|
||||
->where('status', 1)
|
||||
->order('sort', 'desc')
|
||||
->select();
|
||||
|
||||
$hot = [];
|
||||
$news = [];
|
||||
if (!empty($cfg['show_hot'])) {
|
||||
$hot = Resource::scope('visible')->order('downloads', 'desc')->limit(10)->select();
|
||||
}
|
||||
if (!empty($cfg['show_new'])) {
|
||||
$news = Resource::scope('visible')->order('id', 'desc')->limit(10)->select();
|
||||
}
|
||||
|
||||
$this->view->assign('categories', $categories);
|
||||
$this->view->assign('hot', $hot);
|
||||
$this->view->assign('news', $news);
|
||||
$this->view->assign('config', $cfg);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类列表页
|
||||
*/
|
||||
public function list()
|
||||
{
|
||||
$cid = $this->request->param('cid/d', 0);
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$cfg = $this->pluginConfig();
|
||||
$size = (int)($cfg['page_size'] ?? 20);
|
||||
|
||||
$cat = $cid ? Category::find($cid) : null;
|
||||
if ($cid && !$cat) {
|
||||
$this->error('分类不存在');
|
||||
}
|
||||
|
||||
$list = Resource::scope('visible');
|
||||
if ($cid) {
|
||||
$list = $list->where('cid', $cid);
|
||||
}
|
||||
$list = $list->order('downloads', 'desc')
|
||||
->paginate(['page' => $page, 'list_rows' => $size]);
|
||||
|
||||
$this->view->assign('cat', $cat);
|
||||
$this->view->assign('list', $list);
|
||||
$this->view->assign('pager', $list->render());
|
||||
$this->view->assign('config', $cfg);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情页
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$resource = Resource::scope('visible')->find($id);
|
||||
if (!$resource) {
|
||||
$this->error('资源不存在或已下架');
|
||||
}
|
||||
|
||||
// 查看计数(防刷交给 service 内的简单锁,此处仅点击+1)
|
||||
DownloadService::incClicks($id);
|
||||
|
||||
$cat = $resource['cid'] ? Category::find($resource['cid']) : null;
|
||||
|
||||
$this->view->assign('resource', $resource);
|
||||
$this->view->assign('cat', $cat);
|
||||
$this->view->assign('config', $this->pluginConfig());
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
public function search()
|
||||
{
|
||||
$q = $this->request->param('q', $this->request->param('kw', ''));
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$cfg = $this->pluginConfig();
|
||||
$size = (int)($cfg['page_size'] ?? 20);
|
||||
|
||||
$list = Resource::scope('visible');
|
||||
if ($q) {
|
||||
$list = $list->whereLike('title', "%{$q}%");
|
||||
}
|
||||
$list = $list->order('downloads', 'desc')
|
||||
->paginate(['page' => $page, 'list_rows' => $size]);
|
||||
|
||||
$this->view->assign('keyword', $q);
|
||||
$this->view->assign('list', $list);
|
||||
$this->view->assign('pager', $list->render());
|
||||
$this->view->assign('config', $cfg);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发下载:外链 302 跳转 / 本地文件流式输出
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$id = $this->request->param('id/d', 0);
|
||||
$ip = $this->request->ip();
|
||||
try {
|
||||
$ret = DownloadService::dispatch($id, $ip);
|
||||
} catch (\think\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if ($ret['type'] === 'redirect') {
|
||||
return redirect($ret['url']);
|
||||
}
|
||||
|
||||
// 本地文件流式输出(避免大文件占用内存)
|
||||
$path = $ret['path'];
|
||||
$name = ($ret['name'] ?? 'download') . '.' . pathinfo($path, PATHINFO_EXTENSION);
|
||||
return Response::create()->data(file_get_contents($path))->header([
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . rawurlencode($name) . '"',
|
||||
'Content-Length' => filesize($path),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user