diff --git a/.env b/.env index f484ee3..5b3a718 100644 --- a/.env +++ b/.env @@ -5,7 +5,8 @@ DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql -HOSTNAME = 121.36.243.179 +HOSTNAME = 43.133.71.191 +#HOSTNAME = 127.0.0.1 DATABASE = yunzertest USERNAME = yunzertest PASSWORD = zKMDMEs7YP3SLDEF diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/.htaccess @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.user.ini b/.user.ini new file mode 100644 index 0000000..de850c7 --- /dev/null +++ b/.user.ini @@ -0,0 +1 @@ +open_basedir=/www/wwwroot/yunzer/:/tmp/ \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..6f17eaf --- /dev/null +++ b/404.html @@ -0,0 +1,7 @@ + +404 Not Found + +

404 Not Found

+
nginx
+ + \ No newline at end of file diff --git a/app/admin/controller/ResourcesController.php b/app/admin/controller/ResourcesController.php index 75b282e..1c32770 100644 --- a/app/admin/controller/ResourcesController.php +++ b/app/admin/controller/ResourcesController.php @@ -119,6 +119,7 @@ class ResourcesController extends BaseController $data = [ 'title' => input('post.title'), 'cate' => input('post.cate'), + 'desc' => input('post.desc'), 'icon' => input('post.icon'), 'images' => input('post.images'), 'url' => input('post.url'), @@ -126,7 +127,6 @@ class ResourcesController extends BaseController 'code' => input('post.code'), 'zipcode' => input('post.zipcode'), 'uploader' => input('post.uploader'), - 'desc' => input('post.desc'), 'content' => input('post.content'), 'number' => input('post.number'), 'status' => input('post.status', 1), @@ -136,7 +136,7 @@ class ResourcesController extends BaseController $insert = Resource::insert($data); if (empty($insert)) { Log::record('添加资源', 0, '添加资源失败', '资源管理'); - return json(['code' => 1, 'msg' => '添加失败', 'data' => []]); + $this->error('添加失败'); } Log::record('添加资源', 1, '', '资源管理'); return json(['code' => 0, 'msg' => '添加成功', 'data' => []]); @@ -154,7 +154,11 @@ class ResourcesController extends BaseController View::assign([ 'categories' => $categories ]); + return View::fetch(); + } catch (\Exception $e) { + Log::record('添加资源页面加载', 0, $e->getMessage(), '资源管理'); + $this->error('页面加载失败:' . $e->getMessage()); } } @@ -218,9 +222,9 @@ class ResourcesController extends BaseController if (!empty($resource['images'])) { $domain = request()->domain(); $images = explode(',', $resource['images']); - $images = array_map(function ($image) use ($domain) { - return $domain . $image; - }, $images); + // $images = array_map(function ($image) use ($domain) { + // return $domain . $image; + // }, $images); $resource['images'] = implode(',', $images); } diff --git a/app/admin/controller/YunzeradminController.php b/app/admin/controller/YunzeradminController.php index 44b55a7..b35ea19 100644 --- a/app/admin/controller/YunzeradminController.php +++ b/app/admin/controller/YunzeradminController.php @@ -28,7 +28,10 @@ use app\admin\model\AdminUser; use app\admin\model\User\Users; use app\admin\model\User\UsersGroup; use app\admin\model\Banner; -use app\admin\model\ContentPush; +use app\admin\model\ContentPush\ContentPush; +use app\admin\model\ContentPush\ContentPushSetting; +use app\admin\model\Resource\Resource; +use app\admin\model\Article\Articles; class YunzeradminController extends Base @@ -684,32 +687,57 @@ class YunzeradminController extends Base public function contentpushlist() { if (Request::isGet()) { - $page = intval(input('post.page', 1)); - $limit = intval(input('post.limit', 10)); + // 获取分页参数 + $page = (int) input('get.page', 1); + $limit = (int) input('get.limit', 10); - $query = ContentPush::where('delete_time', null) - ->field('id, title, type, status, sort, create_time, update_time'); - - // 获取总记录数 - $count = $query->count(); - - // 获取分页数据 - $lists = $query->order(['sort DESC', 'id DESC']) - ->page($page, $limit) + // 1. 获取 Articles 表(delete_time为空,status=2) + $articles = Articles::where('delete_time', null) + ->where('status', 2) + ->field('id, title, push, create_time') ->select() ->toArray(); - - // 处理数据 - foreach ($lists as &$item) { - $item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time']; - $item['update_time'] = is_numeric($item['update_time']) ? date('Y-m-d H:i:s', $item['update_time']) : $item['update_time']; + foreach ($articles as &$a) { + $a['type'] = 'article'; + $a['create_time'] = is_numeric($a['create_time']) ? date('Y-m-d H:i:s', $a['create_time']) : $a['create_time']; } + unset($a); + + // 2. 获取 Resource 表(delete_time为空,status=1) + $resources = Resource::where('delete_time', null) + ->where('status', 1) + ->field('id, title, push, create_time') + ->select() + ->toArray(); + foreach ($resources as &$r) { + $r['type'] = 'resource'; + $r['create_time'] = is_numeric($r['create_time']) ? date('Y-m-d H:i:s', $r['create_time']) : $r['create_time']; + } + unset($r); + + // 3. 合并 + $lists = array_merge($articles, $resources); + + // 4. 优先显示push为0的数据,再按create_time倒序排序 + usort($lists, function ($a, $b) { + // push为0的排在前面 + if ($a['push'] != $b['push']) { + return $a['push'] - $b['push']; + } + // push相同则按create_time倒序 + return strtotime($b['create_time']) <=> strtotime($a['create_time']); + }); + + // 5. 分页 + $total = count($lists); + $offset = ($page - 1) * $limit; + $data = array_slice($lists, $offset, $limit); return json([ 'code' => 0, 'msg' => '', - 'count' => $count, - 'data' => $lists + 'count' => $total, + 'data' => $data ]); } return json(['code' => 1, 'msg' => '请求方法无效']); @@ -737,8 +765,9 @@ class YunzeradminController extends Base } Log::record('添加内容推送', 1, '', '内容推送管理'); return json(['code' => 0, 'msg' => '添加成功']); + } else { + return View::fetch(); } - return json(['code' => 1, 'msg' => '请求方法无效']); } // 编辑内容推送 @@ -817,6 +846,137 @@ class YunzeradminController extends Base return json(['code' => 1, 'msg' => '请求方法无效']); } + //推送配置列表(渲染列表) + public function contentpushsetting() + { + if (Request::isAjax() || Request::isPost()) { + $page = intval(input('get.page', 1)); + $limit = intval(input('get.limit', 10)); + + $query = ContentPushSetting::where('delete_time', null) + ->field('id, title, value, platformType, status, sort, create_time'); + + $count = $query->count(); + + $lists = $query->order(['sort' => 'DESC', 'id' => 'DESC']) + ->page($page, $limit) + ->select() + ->toArray(); + + foreach ($lists as &$item) { + $item['create_time'] = is_numeric($item['create_time']) ? date('Y-m-d H:i:s', $item['create_time']) : $item['create_time']; + } + + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $lists + ]); + } else { + return View::fetch(); + } + } + + //选择列出推送内容列表 + public function selectpushcontent() + { + $pushcate = strtolower(trim(input('get.pushcate', ''))); + $where = ['push' => 0]; + + $modelMap = [ + 'article' => Articles::class, + 'resource' => Resource::class, + ]; + + if (!isset($modelMap[$pushcate])) { + return json(['code' => 1, 'msg' => '参数错误: pushcate']); + } + + $model = $modelMap[$pushcate]; + + $query = $model::where($where)->field('title,id'); + $count = $query->count(); + $list = $query->order('id', 'desc')->select()->toArray(); + + // 判断是接口请求还是页面请求 + if (request()->isAjax() || request()->isJson()) { + return json([ + 'code' => 0, + 'msg' => '获取成功', + 'count' => $count, + 'data' => $list + ]); + } else { + // 这里传递变量到模板 + return View::fetch('', [ + 'data' => $list + ]); + } + } + + //推送配置添加和编辑通用方法 + public function contentpushsettingadd() + { + if (Request::isPost()) { + $params = input('post.'); + $id = isset($params['id']) ? intval($params['id']) : 0; + + if ($id > 0) { + // 编辑 + $res = ContentPushSetting::update($params, ['id' => $id]); + if ($res === false) { + Log::record('编辑推送配置', 0, '编辑推送配置失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '编辑推送配置失败']); + } + Log::record('编辑推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '编辑成功']); + } else { + // 添加 + $res = ContentPushSetting::create($params); + if (!$res) { + Log::record('添加推送配置', 0, '添加推送配置失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '添加推送配置失败']); + } + Log::record('添加推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '添加成功']); + } + } else { + $id = input('get.id', 0); + $info = []; + if ($id) { + $info = ContentPushSetting::where('id', $id)->find(); + if ($info) { + $info = $info->toArray(); + } + } + return View::fetch('', ['info' => $info]); + } + } + + //推送配置软删除 + public function contentpushsettingdel() + { + if (Request::isPost()) { + $id = intval(input('post.id', 0)); + if (!$id) { + return json(['code' => 1, 'msg' => '参数错误']); + } + $setting = ContentPushSetting::where('id', $id)->find(); + if (!$setting) { + return json(['code' => 1, 'msg' => '配置不存在']); + } + $res = ContentPushSetting::where('id', $id)->update(['delete_time' => date('Y-m-d H:i:s')]); + if ($res === false) { + Log::record('删除推送配置', 0, '删除失败', '推送配置管理'); + return json(['code' => 1, 'msg' => '删除失败']); + } + Log::record('删除推送配置', 1, '', '推送配置管理'); + return json(['code' => 0, 'msg' => '删除成功']); + } + return json(['code' => 1, 'msg' => '请求方式错误']); + } + //素材中心 public function materialcenter() { @@ -957,4 +1117,93 @@ class YunzeradminController extends Base } return json(['code' => 1, 'msg' => '请求方法无效']); } + + + public function gopush() + { + $platformType = input('post.platformType'); + $urls = input('post.urls/a', []); + + if (empty($platformType)) { + return json(['code' => 1, 'msg' => '平台参数缺失']); + } + if (empty($urls)) { + return json(['code' => 1, 'msg' => '推送内容url为空']); + } + + // 查找推送平台配置 + $setting = ContentPushSetting::where('platformType', $platformType)->find(); + if (!$setting) { + return json(['code' => 1, 'msg' => '未找到该平台的推送配置']); + } + if ($setting['status'] == 0) { + return json(['code' => 1, 'msg' => '该平台推送已禁用']); + } + $api = $setting['value']; + if (empty($api)) { + return json(['code' => 1, 'msg' => '推送API地址未配置']); + } + + // 推送 + $ch = curl_init(); + $options = array( + CURLOPT_URL => $api, + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POSTFIELDS => implode("\n", $urls), // 多行文本,每行一个url + CURLOPT_HTTPHEADER => array('Content-Type: text/plain'), + ); + curl_setopt_array($ch, $options); + $result = curl_exec($ch); + $error = curl_error($ch); + curl_close($ch); + + if ($error) { + return json(['code' => 1, 'msg' => $error, 'result' => $result]); + } + + // 解析推送返回结果 + $resultArr = json_decode($result, true); + + // 判断返回是否有error字段 + if (is_array($resultArr) && isset($resultArr['error'])) { + return json([ + 'code' => 1, + 'msg' => '推送失败: ' . (isset($resultArr['message']) ? $resultArr['message'] : '未知错误'), + 'result' => $resultArr + ]); + } + + // 判断是否有success字段,只有有success字段才认为推送成功 + if (is_array($resultArr) && isset($resultArr['success'])) { + // 推送成功后,更新对应数据的push字段为1 + // 解析urls,分别更新Articles或Resource表 + foreach ($urls as $url) { + // 匹配文章 + if (preg_match('/\/index\/articles\/detail\?id=(\d+)/', $url, $matches)) { + $id = intval($matches[1]); + if ($id > 0) { + Articles::where('id', $id)->update(['push' => 1]); + } + } + // 匹配资源 + elseif (preg_match('/\/index\/resources\/detail\?id=(\d+)/', $url, $matches)) { + $id = intval($matches[1]); + if ($id > 0) { + Resource::where('id', $id)->update(['push' => 1]); + } + } + } + return json(['code' => 0, 'msg' => '推送成功', 'result' => $resultArr]); + } else { + // 没有success字段,视为推送失败,把失败的result反馈给前端 + return json([ + 'code' => 1, + 'msg' => '推送失败', + 'result' => $resultArr !== null ? $resultArr : $result + ]); + } + } + + } \ No newline at end of file diff --git a/app/admin/model/ContentPush.php b/app/admin/model/ContentPush/ContentPush.php similarity index 95% rename from app/admin/model/ContentPush.php rename to app/admin/model/ContentPush/ContentPush.php index abe4a10..652375d 100644 --- a/app/admin/model/ContentPush.php +++ b/app/admin/model/ContentPush/ContentPush.php @@ -16,7 +16,7 @@ * 3. 禁止转售或分发 */ -namespace app\admin\model; +namespace app\admin\model\ContentPush; use think\Model; diff --git a/app/admin/model/ContentPush/ContentPushSetting.php b/app/admin/model/ContentPush/ContentPushSetting.php new file mode 100644 index 0000000..224b763 --- /dev/null +++ b/app/admin/model/ContentPush/ContentPushSetting.php @@ -0,0 +1,34 @@ + response.json()) .then(res => { - console.log('用户统计接口返回数据:', res); + // console.log('用户统计接口返回数据:', res); if (res.code === 0 && res.data) { // 更新用户总数 document.querySelector('.stat-card:nth-child(1) .stat-value').textContent = res.data.total.toLocaleString(); @@ -353,7 +353,7 @@ function getArticleCounts() { fetch('{:url("articles/counts")}') .then(response => response.json()) .then(res => { - console.log('文章统计接口返回数据:', res); + // console.log('文章统计接口返回数据:', res); if (res.code === 0 && res.data) { // 更新文章总数 document.querySelector('.stat-card:nth-child(3) .stat-value').textContent = res.data.total.toLocaleString(); @@ -389,7 +389,7 @@ function getResourcesCounts() { fetch('{:url("resources/counts")}') .then(response => response.json()) .then(res => { - console.log('资源统计接口返回数据:', res); + // console.log('资源统计接口返回数据:', res); if (res.code === 0 && res.data) { // 更新资源总数 document.querySelector('.stat-card:nth-child(4) .stat-value').textContent = res.data.total.toLocaleString(); diff --git a/app/admin/view/resources/edit.php b/app/admin/view/resources/edit.php index 5ad9f4c..27bb18d 100644 --- a/app/admin/view/resources/edit.php +++ b/app/admin/view/resources/edit.php @@ -97,29 +97,41 @@
{if condition="isset($resource.images) && !empty($resource.images)"} - {if condition="strpos($resource.images, ',') !== false"} - {volist name="resource.images|explode=',',true" id="image"} -
- 已上传图片 -
- -
-

{$image|basename}

+
+ + + + + + + + + {php} + // 处理图片字符串,正确拆分逗号分隔的路径 + $imageArray = []; + if (isset($resource['images']) && !empty($resource['images'])) { + $imageArray = explode(',', $resource['images']); + $imageArray = array_map('trim', $imageArray); // 去除每个路径的前后空格 + $imageArray = array_filter($imageArray); // 过滤空值 + } + {/php} + {volist name="imageArray" id="image"} + + + + + {/volist} + +
缩略图操作
+
+ 缩略图 +
+
+ +
- {/volist} - {else} -
- 已上传图片 -
- -
-

{$resource.images|basename}

-
- {/if} {/if}
- +
@@ -685,6 +697,19 @@ updateImagesInput(); } }); + + // 图片预览功能 + window.previewImage = function(imageUrl) { + layer.photos({ + photos: { + "data": [{ + "src": imageUrl, + "alt": "图片预览" + }] + }, + anim: 5 + }); + }; }); @@ -820,4 +845,28 @@ .container-right { width: 65%; } + + /* 图片列表表格样式 */ + .image-list-table { + margin-top: 15px; + } + + .image-thumbnail { + width: 60px; + height: 60px; + border-radius: 4px; + overflow: hidden; + cursor: pointer; + transition: transform 0.2s; + } + + .image-thumbnail:hover { + transform: scale(1.05); + } + + .image-thumbnail img { + width: 100%; + height: 100%; + object-fit: cover; + } \ No newline at end of file diff --git a/app/admin/view/yunzer/menuedit.php b/app/admin/view/yunzer/menuedit.php index 3c94d40..cd130ac 100644 --- a/app/admin/view/yunzer/menuedit.php +++ b/app/admin/view/yunzer/menuedit.php @@ -50,8 +50,10 @@
{include file="component/foot" /} \ No newline at end of file diff --git a/app/index/view/resources/detail.php b/app/index/view/resources/detail.php index 52f6dda..f71c60f 100644 --- a/app/index/view/resources/detail.php +++ b/app/index/view/resources/detail.php @@ -1,17 +1,22 @@ {include file="component/head" /} + + + + + {include file="component/header-simple" /}
- +
首页 > - +
@@ -20,69 +25,160 @@
-
-
-
- - -
-
-
-
-
- -
-
- -
-
-
-
-
Free
-
-
更新时间:
-
所属分类:
-
程序编号:
-
查看:
-
下载:
+
+
+
+
+
+
+ {php} + // 兼容字符串和数组 + $images = isset($resources['images']) ? $resources['images'] : []; + if (is_string($images)) { + $images = explode(',', $images); + } + $images = array_filter($images); // 移除空值 + if (empty($images) && !empty($resources['icon'])) { + $images = [$resources['icon']]; + } + {/php} + {volist name="images" id="image"} +
+ + <?php echo $resources['title']; ?> + +
+ {/volist} +
+
+
+
-
-
-
- + +
+
+
+
+
+
+ 作者头像 +
+
+
{$authorInfo.name}
+
+
+
+
+ +
+
资源
+ {$authorInfo.resource_count} +
+
+
文章
+ {$authorInfo.article_count} +
+
+
粉丝
+ + 0 + +
+
+
+
+
+ + +
+
-
-
-
-
- +
+
+
+
+
-
+
@@ -97,27 +193,27 @@
-
-
+
+
-
+
- - -