This commit is contained in:
youda 2025-06-22 19:12:07 +08:00
parent 7fd0401d98
commit c9bdd07cf2
16 changed files with 1636 additions and 122 deletions

View File

@ -22,16 +22,17 @@ abstract class MyController extends BaseController
if ($platform == "APP_ANDROID" || $platform == "APP_IOS") {
// 密钥和加密算法
$secretKey = 'g6R@9!zB2fL#1cVm'; // 必须是 16/24/32 位
$cipher = 'AES-128-CBC';
$iv = substr(md5($secretKey), 0, 16); // IV 长度必须是 16 字节
// $secretKey = 'g6R@9!zB2fL#1cVm'; // 必须是 16/24/32 位
// $cipher = 'AES-128-CBC';
// $iv = substr(md5($secretKey), 0, 16); // IV 长度必须是 16 字节
// 对 $data 进行加密处理
$dataString = json_encode($data, JSON_UNESCAPED_UNICODE);
$encrypted = openssl_encrypt($dataString, $cipher, $secretKey, 0, $iv);
// $dataString = json_encode($data, JSON_UNESCAPED_UNICODE);
// $encrypted = openssl_encrypt($dataString, $cipher, $secretKey, 0, $iv);
return [
'ret' => $status,
'payload' => $encrypted,
// 'payload' => $data,//$encrypted,
'data' => $data,
'note' => $msg,
'ts' => time(), // 当前时间戳
];
@ -39,6 +40,17 @@ abstract class MyController extends BaseController
$request = request();
return compact('status', 'msg', 'data');
}
protected function encryption($data)
{
$secretKey = 'g6R@9!zB2fL#1cVm'; // 必须是 16/24/32 位
$cipher = 'AES-128-CBC';
$iv = substr(md5($secretKey), 0, 16); // IV 长度必须是 16 字节
// 对 $data 进行加密处理
$dataString = json_encode($data, JSON_UNESCAPED_UNICODE);
$encrypted = openssl_encrypt($dataString, $cipher, $secretKey, 0, $iv);
return $encrypted;
}
/**
* 返回操作成功json

View File

@ -0,0 +1,185 @@
<?php
namespace app\admin\controller;
use think\facade\View;
use think\facade\Db;
use app\common\model\News;
class NewsController extends Base
{
/**
* 资讯列表
*/
public function index()
{
if (request()->isAjax()) {
$limit = input('param.limit', 15);
$page = input('param.page', 1);
$offset = ($page - 1) * $limit;
$title = input('param.title', '');
$status = input('param.status', '');
$where = [];
if ($title) {
$where[] = ['title', 'like', "%{$title}%"];
}
if ($status !== '') {
$where[] = ['status', '=', $status];
}
$res = News::where($where)
->order('id', 'desc')
->limit($offset, $limit)
->select();
$total = News::where($where)->count();
return $this->renderTable('获取成功', $total, $res, 0);
}
return View::fetch('News/index');
}
/**
* 添加资讯
*/
public function add()
{
if (request()->isPost()) {
$param = input('post.');
$validate = $this->validate($param, [
'title' => 'require',
// 'author_id' => 'require|number',
]);
if (true !== $validate) {
return $this->renderError($validate);
}
$param['author_id'] = 1;
// 如果状态为发布,确保有发布时间
if (isset($param['status']) && $param['status'] == 1 && empty($param['publish_time'])) {
$param['publish_time'] = date('Y-m-d H:i:s');
}
$res = News::create($param);
if ($res) {
return $this->renderSuccess('添加成功', ['url' => (string) url('news')]);
} else {
return $this->renderError('添加失败');
}
}
return View::fetch('News/add');
}
/**
* 编辑资讯
*/
public function edit()
{
$id = input('param.id', 0);
$info = News::where('id', $id)->find();
if (empty($info)) {
return $this->renderError('数据不存在');
}
if (request()->isPost()) {
$param = input('post.');
$validate = $this->validate($param, [
'title' => 'require',
// 'author_id' => 'require|number',
]);
if (true !== $validate) {
return $this->renderError($validate);
}
$param['author_id'] = 1;
// 如果状态为发布,确保有发布时间
if (isset($param['status']) && $param['status'] == 1 && empty($param['publish_time'])) {
$param['publish_time'] = date('Y-m-d H:i:s');
}
$res = News::update($param, ['id' => $id]);
if ($res) {
return $this->renderSuccess('编辑成功', ['url' => (string) url('news')]);
} else {
return $this->renderError('编辑失败');
}
}
View::assign('info', $info);
return View::fetch('News/edit');
}
/**
* 修改资讯状态(发布/草稿)
*/
public function status()
{
$id = input('param.id', 0);
$status = input('param.status', 0);
// 如果状态为发布,确保有发布时间
$update = ['status' => $status];
if ($status == 1) {
$info = News::where('id', $id)->find();
if (!$info->publish_time) {
$update['publish_time'] = date('Y-m-d H:i:s');
}
}
$res = News::update($update, ['id' => $id]);
if ($res) {
return $this->renderSuccess('操作成功');
} else {
return $this->renderError('操作失败');
}
}
/**
* 修改热榜状态
*/
public function hot()
{
$id = input('param.id', 0);
$is_hot = input('param.is_hot', 0);
$res = News::update(['is_hot' => $is_hot], ['id' => $id]);
if ($res) {
return $this->renderSuccess('操作成功');
} else {
return $this->renderError('操作失败');
}
}
/**
* 修改精选状态
*/
public function featured()
{
$id = input('param.id', 0);
$is_featured = input('param.is_featured', 0);
$res = News::update(['is_featured' => $is_featured], ['id' => $id]);
if ($res) {
return $this->renderSuccess('操作成功');
} else {
return $this->renderError('操作失败');
}
}
/**
* 删除资讯
*/
public function del()
{
$id = input('param.id', 0);
$res = News::destroy($id);
if ($res) {
return $this->renderSuccess('删除成功');
} else {
return $this->renderError('删除失败');
}
}
}

View File

@ -37,7 +37,7 @@ class Upload extends Base
}
// 文件格式校验
$ext = ['jpg', 'png', 'jpeg', 'JPG', 'PNG', 'JPEG', 'gif', 'apk', 'mp3'];
$ext = ['jpg', 'png', 'jpeg', 'JPG', 'PNG', 'JPEG', 'gif', 'apk', 'mp3','webp'];
$type = substr($_FILES['file']['name'], strrpos($_FILES['file']['name'], '.') + 1);
if (!in_array($type, $ext)) {
return $this->renderError("文件格式错误");

View File

@ -400,6 +400,17 @@ Route::rule('float_ball_edit', 'FloatBall/edit', 'GET|POST');
Route::rule('float_ball_del', 'FloatBall/del', 'POST');
Route::rule('float_ball_status', 'FloatBall/status', 'POST');
#============================
#NewsController.php资讯管理
#============================
Route::rule('news', 'NewsController/index', 'GET|POST');
Route::rule('news_add', 'NewsController/add', 'GET|POST');
Route::rule('news_edit', 'NewsController/edit', 'GET|POST');
Route::rule('news_del', 'NewsController/del', 'POST');
Route::rule('news_status', 'NewsController/status', 'POST');
Route::rule('news_hot', 'NewsController/hot', 'POST');
Route::rule('news_featured', 'NewsController/featured', 'POST');
#============================
#Reward.php奖励管理
#============================
@ -457,7 +468,7 @@ Route::rule('Statistics/getCurrencyInfoData', 'Statistics/getCurrencyInfoData',
// 盒子下架日志相关路由
Route::post('goods_offshelf_read', 'GoodsOffshelfController/read');
Route::get('goods_offshelf_unread_count', 'GoodsOffshelfController/getUnreadCount');
#============================
# dynamicJs
@ -484,4 +495,8 @@ Route::rule('diamond_get_max_sort', 'Diamond/get_max_sort', 'GET');
#VerificationCode.php 验证码管理
#============================
Route::rule('verification_code', 'VerificationCode/index', 'GET|POST');
#============================
#News.php 新闻管理
#============================
Route::rule('news', 'News/index', 'GET|POST');

View File

@ -0,0 +1,218 @@
{include file="Public/header3" /}
<link href="https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css" rel="stylesheet" />
<style>
#editor—wrapper {
border: 1px solid #ccc;
z-index: 100;
/* 按需定义 */
}
#toolbar-container {
border-bottom: 1px solid #ccc;
}
#editor-container {
height: 500px;
}
</style>
<div class="layui-form" style="width: 90%; margin: 0 auto; padding-top: 20px;">
<div class="layui-form-item">
</div>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" id="title" autocomplete="off" placeholder="请输入资讯标题" class="layui-input"
lay-verify="required">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">封面图</label>
<div class="layui-input-block">
<button type="button" class="layui-btn" id="uploadCover">上传封面图</button>
<div class="layui-upload-list">
<img class="layui-upload-img" id="coverPreview" style="max-width: 200px; max-height: 150px;">
</div>
<input type="hidden" name="cover_image" id="cover_image" value="">
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">热榜</label>
<div class="layui-input-inline">
<input type="radio" name="is_hot" value="0" title="否" checked>
<input type="radio" name="is_hot" value="1" title="是">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">精选</label>
<div class="layui-input-inline">
<input type="radio" name="is_featured" value="0" title="否">
<input type="radio" name="is_featured" value="1" title="是" checked>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容详情</label>
<div class="layui-input-block">
<div id="editor—wrapper">
<div id="toolbar-container"><!-- 工具栏 --></div>
<div id="editor-container"><!-- 编辑器 --></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">作者姓名</label>
<div class="layui-input-inline">
<input type="text" name="author_name" id="author_name" placeholder="请输入作者姓名" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-inline">
<input type="radio" name="status" value="0" title="草稿">
<input type="radio" name="status" value="1" title="发布" checked>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布时间</label>
<div class="layui-input-block">
<input type="text" name="publish_time" id="publish_time" autocomplete="off" placeholder="请选择发布时间"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="saveBtn">保存</button>
</div>
</div>
</div>
{include file="Public/footer" /}
<script src="https://unpkg.com/@wangeditor/editor@latest/dist/index.js"></script>
<script>
const { createEditor, createToolbar } = window.wangEditor
const editorConfig = {
placeholder: 'Type here...',
onChange(editor) {
const html = editor.getHtml()
console.log('editor content', html)
// 也可以同步到 <textarea>
},
MENU_CONF: {}
}
editorConfig.MENU_CONF['uploadImage'] = {
customUpload: async (file, insertFn) => {
console.log(file);
// 模拟上传到 COS 的过程
const formData = new FormData();
formData.append('file', file);
const res = await fetch('/admin/picture?dir=news', {
method: 'POST',
body: formData
});
console.log("resresresresres", res);
const result = await res.json();
// // 成功后插入图片
insertFn(result.data.imgurl, '图片描述', result.data.imgurl);
}
}
const editor = createEditor({
selector: '#editor-container',
html: '<p><br></p>',
config: editorConfig,
mode: 'default', // or 'simple'
})
const toolbarConfig = {}
const toolbar = createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default', // or 'simple'
})
layui.use(['form', 'upload', 'layer', 'laydate'], function () {
var form = layui.form,
layer = layui.layer,
upload = layui.upload,
laydate = layui.laydate,
// layedit = layui.layedit,
$ = layui.jquery;
// 初始化日期选择器
laydate.render({
elem: '#publish_time',
type: 'datetime',
value: new Date()
});
// 上传封面图
upload.render({
elem: '#uploadCover',
url: '/admin/picture',
accept: "file",
done: function (res) {
if (res.status == 1) {
layer.msg("上传成功", { icon: 1, time: 1000 }, function () {
$("#coverPreview").attr("src", res.data.path);
$("#cover_image").val(res.data.imgurl);
});
} else {
layer.msg(res.msg, { icon: 2, anim: 6, time: 1500 });
}
},
error: function () {
layer.msg('服务繁忙,请稍后再试', { icon: 2, anim: 6, time: 1500 });
}
});
// 表单提交
form.on('submit(saveBtn)', function (data) {
// 同步富文本编辑器内容
data.field.content = editor.getHtml();
if (!data.field.title) {
layer.msg('标题不能为空', { icon: 2 });
return false;
}
// 如果发布状态为"发布"且未设置发布时间,则设置为当前时间
if (data.field.status == 1 && !data.field.publish_time) {
data.field.publish_time = layui.util.toDateString(new Date(), 'yyyy-MM-dd HH:mm:ss');
}
$.ajax({
url: '{:url("/admin/news_add")}',
type: 'POST',
data: data.field,
success: function (res) {
if (res.status) {
layer.msg(res.msg, { icon: 1, time: 1000 }, function () {
parent.layui.table.reload('tableList');
var iframeIndex = parent.layer.getFrameIndex(window.name);
parent.layer.close(iframeIndex);
});
} else {
layer.msg(res.msg, { icon: 2 });
}
}
});
return false;
});
});
</script>

View File

@ -0,0 +1,225 @@
{include file="Public/header3" /}
<link href="https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css" rel="stylesheet" />
<style>
#editor—wrapper {
border: 1px solid #ccc;
z-index: 100;
/* 按需定义 */
}
#toolbar-container {
border-bottom: 1px solid #ccc;
}
#editor-container {
height: 500px;
}
</style>
<div class="layui-form" style="width: 90%; margin: 0 auto; padding-top: 20px;">
<input type="hidden" name="id" value="{$info.id}">
<div class="layui-form-item">
</div>
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" id="title" autocomplete="off" placeholder="请输入资讯标题" class="layui-input"
lay-verify="required" value="{$info.title}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">封面图</label>
<div class="layui-input-block">
<button type="button" class="layui-btn" id="uploadCover">上传封面图</button>
<div class="layui-upload-list">
<img class="layui-upload-img" id="coverPreview" style="max-width: 200px; max-height: 150px;"
src="{$info.cover_image}">
</div>
<input type="hidden" name="cover_image" id="cover_image" value="{$info.cover_image}">
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">热榜</label>
<div class="layui-input-inline">
<input type="radio" name="is_hot" value="0" title="否" {if $info.is_hot eq 0}checked{/if}>
<input type="radio" name="is_hot" value="1" title="是" {if $info.is_hot eq 1}checked{/if}>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">精选</label>
<div class="layui-input-inline">
<input type="radio" name="is_featured" value="0" title="否" {if $info.is_featured eq 0}checked{/if}>
<input type="radio" name="is_featured" value="1" title="是" {if $info.is_featured eq 1}checked{/if}>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容详情</label>
<div class="layui-input-block">
<div id="editor—wrapper">
<div id="toolbar-container"><!-- 工具栏 --></div>
<div id="editor-container"><!-- 编辑器 --></div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">作者姓名</label>
<div class="layui-input-inline">
<input type="text" name="author_name" id="author_name" placeholder="请输入作者姓名" class="layui-input"
value="{$info.author_name}">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-inline">
<input type="radio" name="status" value="0" title="草稿" {if $info.status eq 0}checked{/if}>
<input type="radio" name="status" value="1" title="发布" {if $info.status eq 1}checked{/if}>
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发布时间</label>
<div class="layui-input-block">
<input type="text" name="publish_time" id="publish_time" autocomplete="off" placeholder="请选择发布时间"
class="layui-input" value="{$info.publish_time}">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="saveBtn">保存</button>
</div>
</div>
</div>
{include file="Public/footer" /}
<script src="https://unpkg.com/@wangeditor/editor@latest/dist/index.js"></script>
<script>
const { createEditor, createToolbar } = window.wangEditor
const editorConfig = {
placeholder: 'Type here...',
onChange(editor) {
const html = editor.getHtml()
console.log('editor content', html)
// 也可以同步到 <textarea>
},
MENU_CONF: {}
}
editorConfig.MENU_CONF['uploadImage'] = {
customUpload: async (file, insertFn) => {
console.log(file);
// 模拟上传到 COS 的过程
const formData = new FormData();
formData.append('file', file);
const res = await fetch('/admin/picture?dir=news', {
method: 'POST',
body: formData
});
console.log("resresresresres", res);
const result = await res.json();
// // 成功后插入图片
insertFn(result.data.imgurl, '图片描述', result.data.imgurl);
}
}
const editor = createEditor({
selector: '#editor-container',
html: '{$info.content|raw}',
config: editorConfig,
mode: 'default', // or 'simple'
})
const toolbarConfig = {}
const toolbar = createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default', // or 'simple'
})
layui.use(['form', 'upload', 'layer', 'laydate'], function () {
var form = layui.form,
layer = layui.layer,
upload = layui.upload,
laydate = layui.laydate,
$ = layui.jquery;
// 初始化日期选择器
laydate.render({
elem: '#publish_time',
type: 'datetime',
value: new Date()
});
// 上传封面图
upload.render({
elem: '#uploadCover',
accept: "file",
url: '/admin/picture',
done: function (res) {
if (res.status == 1) {
layer.msg("上传成功", { icon: 1, time: 1000 }, function () {
$("#coverPreview").attr("src", res.data.path);
$("#cover_image").val(res.data.imgurl);
});
} else {
layer.msg(res.msg, { icon: 2, anim: 6, time: 1500 });
}
},
error: function () {
layer.msg('服务繁忙,请稍后再试', { icon: 2, anim: 6, time: 1500 });
}
});
// 表单提交
form.on('submit(saveBtn)', function (data) {
// 同步富文本编辑器内容
data.field.content = editor.getHtml();
if (!data.field.title) {
layer.msg('标题不能为空', { icon: 2 });
return false;
}
// 如果发布状态为"发布"且未设置发布时间,则设置为当前时间
if (data.field.status == 1 && !data.field.publish_time) {
data.field.publish_time = layui.util.toDateString(new Date(), 'yyyy-MM-dd HH:mm:ss');
}
$.ajax({
url: '{:url("/admin/news_edit")}',
type: 'POST',
data: data.field,
success: function (res) {
if (res.status) {
layer.msg(res.msg, { icon: 1, time: 1000 }, function () {
parent.layui.table.reload('tableList');
var iframeIndex = parent.layer.getFrameIndex(window.name);
parent.layer.close(iframeIndex);
});
} else {
layer.msg(res.msg, { icon: 2 });
}
}
});
return false;
});
});
</script>

View File

@ -0,0 +1,245 @@
{include file="Public:header3"/}
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">资讯管理</div>
<div class="layui-card-body">
<div class="layui-form toolbar">
<div class="layui-form-item">
<div class="layui-inline">
<input type="text" id="searchTitle" placeholder="请输入标题关键词" class="layui-input">
</div>
<div class="layui-inline">
<select id="searchStatus">
<option value="">全部状态</option>
<option value="0">草稿</option>
<option value="1">已发布</option>
</select>
</div>
<div class="layui-inline">
<button class="layui-btn layui-btn-sm" id="btnSearch"><i
class="layui-icon">&#xe615;</i>搜索</button>
<button class="layui-btn layui-btn-sm" id="btnAdd"><i class="layui-icon">&#xe654;</i>添加</button>
</div>
</div>
</div>
<table id="tableList" lay-filter="tableList"></table>
</div>
</div>
</div>
<!-- 表格操作列 -->
<script type="text/html" id="tableBar">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
{{# if(d.status == 0){ }}
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="publish">发布</a>
{{# }else{ }}
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="draft">下架</a>
{{# } }}
{{# if(d.is_hot == 0){ }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="setHot">设为热榜</a>
{{# }else{ }}
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="cancelHot">取消热榜</a>
{{# } }}
{{# if(d.is_featured == 0){ }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="setFeatured">设为精选</a>
{{# }else{ }}
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="cancelFeatured">取消精选</a>
{{# } }}
</script>
<!-- 状态模板 -->
<script type="text/html" id="statusTpl">
{{# if(d.status == 1){ }}
<span class="layui-badge layui-bg-green">已发布</span>
{{# }else{ }}
<span class="layui-badge">草稿</span>
{{# } }}
</script>
<!-- 热榜模板 -->
<script type="text/html" id="hotTpl">
{{# if(d.is_hot == 1){ }}
<span class="layui-badge layui-bg-orange"></span>
{{# }else{ }}
<span></span>
{{# } }}
</script>
<!-- 精选模板 -->
<script type="text/html" id="featuredTpl">
{{# if(d.is_featured == 1){ }}
<span class="layui-badge layui-bg-blue"></span>
{{# }else{ }}
<span></span>
{{# } }}
</script>
{include file="Public/footer3" /}
<script>
layui.use(['table', 'form', 'jquery', 'layer', 'laydate'], function () {
var $ = layui.jquery;
var table = layui.table;
var form = layui.form;
var layer = layui.layer;
var laydate = layui.laydate;
// 渲染表格
var tableIns = table.render({
elem: '#tableList',
url: '{:url("/admin/news")}',
page: true,
cols: [[
{ type: 'numbers', title: '序号', width: 60 },
{ field: 'title', title: '标题', width: 200 },
{
field: 'cover_image', title: '封面图', width: 100, templet: function (d) {
return d.cover_image ? '<img src="' + d.cover_image + '" style="max-height: 50px;">' : '';
}
},
{ field: 'author_name', title: '作者', width: 100 },
{
field: 'publish_time', title: '发布时间', width: 160, templet: function (d) {
return d.publish_time ? layui.util.toDateString(new Date(d.publish_time).getTime(), 'yyyy-MM-dd HH:mm:ss') : '';
}
},
{ field: 'is_hot', title: '热榜', width: 80, templet: '#hotTpl' },
{ field: 'is_featured', title: '精选', width: 80, templet: '#featuredTpl' },
{ field: 'status', title: '状态', width: 80, templet: '#statusTpl' },
{
field: 'create_time', title: '创建时间', width: 160, templet: function (d) {
return layui.util.toDateString(new Date(d.create_time).getTime(), 'yyyy-MM-dd HH:mm:ss');
}
},
{ title: '操作', toolbar: '#tableBar', width: 380 }
]],
limits: [10, 15, 20, 25, 50, 100],
limit: 15,
text: {
none: '暂无相关数据'
}
});
// 搜索按钮点击事件
$('#btnSearch').click(function () {
tableIns.reload({
where: {
title: $('#searchTitle').val(),
status: $('#searchStatus').val()
},
page: {
curr: 1
}
});
});
// 添加按钮点击事件
$('#btnAdd').click(function () {
layer.open({
type: 2,
title: '添加资讯',
area: ['90%', '90%'],
shade: 0.4,
shadeClose: true,
content: '{:url("/admin/news_add")}'
});
});
// 表格工具条点击事件
table.on('tool(tableList)', function (obj) {
var data = obj.data;
var layEvent = obj.event;
if (layEvent === 'edit') {
layer.open({
type: 2,
title: '编辑资讯',
area: ['90%', '90%'],
shade: 0.4,
shadeClose: true,
content: '{:url("/admin/news_edit")}?id=' + data.id
});
} else if (layEvent === 'del') {
layer.confirm('确定要删除该资讯吗?', function (i) {
layer.close(i);
layer.load(2);
$.post('{:url("/admin/news_del")}', { id: data.id }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
});
} else if (layEvent === 'publish') {
layer.load(2);
$.post('{:url("/admin/news_status")}', { id: data.id, status: 1 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
} else if (layEvent === 'draft') {
layer.load(2);
$.post('{:url("/admin/news_status")}', { id: data.id, status: 0 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
} else if (layEvent === 'setHot') {
layer.load(2);
$.post('{:url("/admin/news_hot")}', { id: data.id, is_hot: 1 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
} else if (layEvent === 'cancelHot') {
layer.load(2);
$.post('{:url("/admin/news_hot")}', { id: data.id, is_hot: 0 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
} else if (layEvent === 'setFeatured') {
layer.load(2);
$.post('{:url("/admin/news_featured")}', { id: data.id, is_featured: 1 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
} else if (layEvent === 'cancelFeatured') {
layer.load(2);
$.post('{:url("/admin/news_featured")}', { id: data.id, is_featured: 0 }, function (res) {
layer.closeAll('loading');
if (res.status) {
layer.msg(res.msg, { icon: 1 });
tableIns.reload();
} else {
layer.msg(res.msg, { icon: 2 });
}
}, 'json');
}
});
});
</script>

View File

@ -1,5 +1,5 @@
<?php
declare (strict_types = 1);
declare(strict_types=1);
namespace app\api\controller;
use app\api\controller\Base;
@ -18,7 +18,7 @@ use \think\Request;
class Coupon extends Base
{
/**
/**
* 首页优惠券列表
* @param Request $request [description]
* @param [type] 类型 1 推荐 2 预售 3 现货 4 一番赏 5 双随机 6售罄
@ -26,72 +26,74 @@ class Coupon extends Base
public function index(Request $request)
{
$is_use_coupon = $this->getUserid1();
if(!$is_use_coupon){
#领过,之后不再弹出
$data['status'] = 2;
return $this->renderSuccess("",$data);
if (!$is_use_coupon) {
#领过,之后不再弹出
$data['status'] = 2;
return $this->renderSuccess("", $data);
}
$whe = [];
$whe[]=['status','=',0];
$whe[]=['type','=',1];
$whe[] = ['status', '=', 0];
$whe[] = ['type', '=', 1];
$field = "id,title,price,man_price,effective_day";
$order = "id desc";
$goods = Couponmodel::getList($whe,$field,$order,1000);
return $this->renderSuccess('请求成功',compact('goods'));
$goods = Couponmodel::getList($whe, $field, $order, 1000);
return $this->renderSuccess('请求成功', compact('goods'));
}
/*
一键领取
*/
public function receive(Request $request){
$user = $this->getUser();
$coupon_id = $request->param('coupon_id');
if(empty($coupon_id)){
public function receive(Request $request)
{
$user = $this->getUser();
$coupon_id = $request->param('coupon_id');
if (empty($coupon_id)) {
return $this->renderError("缺少必要参数");
}
$is_find = CouponReceivemodel::where(['user_id'=>$user->id])->whereIn('coupon_id',$coupon_id)->find();
if(!empty($is_find)){
return $this->renderError("已经领取过了,无法在领取");
}
$coupon_id = explode(',',$coupon_id);
$coupon_id = array_filter($coupon_id);
$num = count($coupon_id);
for($i=0;$i<$num;$i++){
$coupon_info = Couponmodel::find($coupon_id[$i]);
if(!empty($coupon_info)){
}
$is_find = CouponReceivemodel::where(['user_id' => $user->id])->whereIn('coupon_id', $coupon_id)->find();
if (!empty($is_find)) {
return $this->renderError("已经领取过了,无法在领取");
}
$coupon_id = explode(',', $coupon_id);
$coupon_id = array_filter($coupon_id);
$num = count($coupon_id);
for ($i = 0; $i < $num; $i++) {
$coupon_info = Couponmodel::find($coupon_id[$i]);
if (!empty($coupon_info)) {
$res[] = CouponReceivemodel::insert(
[
'user_id'=>$user->id,
'title'=>$coupon_info['title'],
'price'=>$coupon_info['price'],
'man_price'=>$coupon_info['man_price'],
'end_time'=>$coupon_info['effective_day']*86400 + time(),
'addtime'=>time(),
'coupon_id'=>$coupon_info['id'],
'state'=> $coupon_info['ttype']
]
[
'user_id' => $user->id,
'title' => $coupon_info['title'],
'price' => $coupon_info['price'],
'man_price' => $coupon_info['man_price'],
'end_time' => $coupon_info['effective_day'] * 86400 + time(),
'addtime' => time(),
'coupon_id' => $coupon_info['id'],
'state' => $coupon_info['ttype']
]
);
}
}
#user表里is_use_coupon 值为1说明是领过优惠券
$res[] = User::where(['id'=>$user['id'],'is_use_coupon'=>0])->update(['is_use_coupon'=>1]);
if(resCheck($res)){
return $this->renderSuccess("领取成功");
}else{
return $this->renderError("购买失败,请刷新重试");
}
}
}
#user表里is_use_coupon 值为1说明是领过优惠券
$res[] = User::where(['id' => $user['id'], 'is_use_coupon' => 0])->update(['is_use_coupon' => 1]);
if (resCheck($res)) {
return $this->renderSuccess("领取成功");
} else {
return $this->renderError("购买失败,请刷新重试");
}
}
//可使用的优惠券
public function used(Request $request){
public function used(Request $request)
{
$user = $this->getUser();
$total_price = $request->param('total_price');
$type = $request->param('type');
@ -99,69 +101,134 @@ class Coupon extends Base
$status = $request->param('status');
$state = $request->param('state');
$page = $request->param('page');
CouponReceivemodel::where(['user_id'=>$user->id,'status'=>0])->where('end_time','<=',time())->update(['status'=>2]);
CouponReceivemodel::where(['user_id' => $user->id, 'status' => 0])->where('end_time', '<=', time())->update(['status' => 2]);
#根据有效期时间改变一下状态
if($type == 1){
if ($type == 1) {
#从个人中心进
if($type1 == 1){
#可用
$whe[] = ['status', '=', $status];
}else{
#不可用
$whe[] = ['status', '>', 0];
if ($type1 == 1) {
#可用
$whe[] = ['status', '=', $status];
} else {
#不可用
$whe[] = ['status', '>', 0];
}
$coupon_receive = CouponReceivemodel::where(['user_id'=>$user->id])->where($whe)->paginate(10)->each(function ($itme) {
$itme['end_time'] = date('Y-m-d',$itme['end_time']);
if($itme['status']== 1){
$itme['mark']= "已使用";
}elseif($itme['status']== 2){
$itme['mark']= "已过期";
}elseif($itme['status']== 0){
$itme['mark']= "去使用";
$coupon_receive = CouponReceivemodel::where(['user_id' => $user->id])->where($whe)->paginate(10)->each(function ($itme) {
$itme['end_time'] = date('Y-m-d', $itme['end_time']);
if ($itme['status'] == 1) {
$itme['mark'] = "已使用";
} elseif ($itme['status'] == 2) {
$itme['mark'] = "已过期";
} elseif ($itme['status'] == 0) {
$itme['mark'] = "去使用";
}
return $itme;
return $itme;
});
}else{
} else {
#从计算金额里面进
if(empty($total_price)){
if (empty($total_price)) {
return $this->renderError("缺少必要参数");
}
if($type1 == 1){
$whe = 'user_id='.$user->id.' and status=0 and man_price<='.$total_price;
if ($type1 == 1) {
$whe = 'user_id=' . $user->id . ' and status=0 and man_price<=' . $total_price;
$whe1 = '';
}else{
$whe = 'user_id='.$user->id.' and status>0';
$whe1 = 'user_id='.$user->id.' and status=0 and man_price>'.$total_price;
} else {
$whe = 'user_id=' . $user->id . ' and status>0';
$whe1 = 'user_id=' . $user->id . ' and status=0 and man_price>' . $total_price;
}
#不可用(包括 已使用,未使用(金额不足,已过期))
$coupon_receive = CouponReceivemodel::where($whe)->whereOr($whe1)
->paginate(10)->each(function ($val) use ($total_price){
$val['end_time'] = date('Y-m-d',$val['end_time']);
if($val['status']== 1){
$val['mark']= "已使用";
}elseif($val['status']== 2){
$val['mark']= "已过期";
}elseif($val['status']== 0){
if($val['man_price'] > $total_price){
$val['mark']= "未满足";
}else{
$val['mark']= "去使用";
->paginate(10)->each(function ($val) use ($total_price) {
$val['end_time'] = date('Y-m-d', $val['end_time']);
if ($val['status'] == 1) {
$val['mark'] = "已使用";
} elseif ($val['status'] == 2) {
$val['mark'] = "已过期";
} elseif ($val['status'] == 0) {
if ($val['man_price'] > $total_price) {
$val['mark'] = "未满足";
} else {
$val['mark'] = "去使用";
}
}
}
return $val;
});
return $val;
});
}
$new_data = [
'data' => $coupon_receive->items(),
'last_page' => $coupon_receive->lastPage(),
];
return $this->renderSuccess('请求成功',$new_data);
return $this->renderSuccess('请求成功', $new_data);
}
public function get_coupon_list(Request $request)
{
$user = $this->getUser();
$total_price = $request->param('total_price');
$type = $request->param('type');
$status = $request->param('status');
$page = $request->param('page');
$limit = $this->request->param('limit', 10);
CouponReceivemodel::where(['user_id' => $user->id, 'status' => 0])->where('end_time', '<=', time())->update(['status' => 2]);
#根据有效期时间改变一下状态
if ($type == 1) {
#从个人中心进
$whe[] = ['status', '=', $status];
$coupon_receive = CouponReceivemodel::where(['user_id' => $user->id])->where($whe)
->field('id,title,price,man_price,status,end_time,coupon_id')
->paginate(['list_rows' => $limit, 'query' => request()->param()])->
each(function ($itme) {
$itme['end_time'] = date('Y-m-d', $itme['end_time']);
if ($itme['status'] == 1) {
$itme['mark'] = "已使用";
} elseif ($itme['status'] == 2) {
$itme['mark'] = "已过期";
} elseif ($itme['status'] == 0) {
$itme['mark'] = "去使用";
}
return $itme;
});
} else {
#从计算金额里面进
if (empty($total_price)) {
return $this->renderError("缺少必要参数");
}
$whe = 'user_id=' . $user->id . ' and status=0 and man_price<=' . $total_price;
$whe1 = '';
#不可用(包括 已使用,未使用(金额不足,已过期))
$coupon_receive = CouponReceivemodel::where($whe)->whereOr($whe1)
->paginate(10)->each(function ($val) use ($total_price) {
$val['end_time'] = date('Y-m-d', $val['end_time']);
if ($val['status'] == 1) {
$val['mark'] = "已使用";
} elseif ($val['status'] == 2) {
$val['mark'] = "已过期";
} elseif ($val['status'] == 0) {
if ($val['man_price'] > $total_price) {
$val['mark'] = "未满足";
} else {
$val['mark'] = "去使用";
}
}
return $val;
});
}
$new_data = [
'list' => $coupon_receive->items(),
'last_page' => $coupon_receive->lastPage(),
];
return $this->renderSuccess('请求成功', $new_data);
}
}

259
app/api/controller/News.php Normal file
View File

@ -0,0 +1,259 @@
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\controller\Base;
use app\common\model\News as NewsModel;
use app\common\model\UserNewsFavorite;
class News extends Base
{
/**
* 获取精选新闻列表
* @return \think\Response
*/
public function getFeaturedNewsList()
{
$where = [];
$where['status'] = 1;
$where['is_featured'] = 1;
$limit = $this->request->param('limit', 10);
$title = $this->request->param('title', '');
if ($title) {
$where[] = ['title', 'like', '%' . $title . '%'];
}
$newsList = NewsModel::getList($where, 'id,title,cover_image,publish_time', 'publish_time desc', $limit);
return $this->renderSuccess('', $newsList);
}
/**
* 获取热榜新闻列表
* @return \think\Response
*/
public function getHotNewsList()
{
$where = [];
$where['status'] = 1;
$where['is_hot'] = 1;
$title = $this->request->param('title', '');
if ($title) {
$where[] = ['title', 'like', '%' . $title . '%'];
}
$limit = $this->request->param('limit', 10);
$newsList = NewsModel::getList($where, 'id,title,cover_image,publish_time,is_hot', 'publish_time desc', $limit);
return $this->renderSuccess('', $newsList);
}
/**
* 获取用户关注的新闻列表
* @return \think\Response
*/
public function getFollowNewsList()
{
$title = $this->request->param('title', '');
$limit = intval($this->request->param('limit', 10));
$page = intval($this->request->param('page', 1));
$userId = $this->getUserId();
if ($userId == 0) {
return $this->renderSuccess('', ['list' => [], 'count' => 0]);
}
// 构建查询
$model = NewsModel::alias('n')
->join('user_news_favorite u', 'n.id=u.news_id')
->where('u.user_id', '=', $userId)
->where('u.is_canceled', '=', 0)
->where('n.status', '=', 1);
// 如果有标题搜索条件
if ($title) {
$model = $model->where('n.title', 'like', '%' . $title . '%');
}
// 获取总数
$count = $model->count();
// 查询数据并分页
$list = $model->field('n.id, n.title, n.cover_image, n.publish_time, n.author_name')
->order('u.create_time', 'desc')
->page($page, $limit)
->select()
->toArray();
return $this->renderSuccess('', [
'list' => $list,
'count' => $count,
'limit' => $limit,
'page' => $page
]);
}
/**
* 获取新闻详情
* @return \think\Response
*/
public function getNewsDetail()
{
$id = $this->request->param('id', 0);
//来源 0: 热榜1精选2关注
$current = $this->request->param('current', 0);
$newsInfo = NewsModel::getInfo(['id' => $id], 'id,title,cover_image,publish_time,content,author_name');
if (!$newsInfo) {
return $this->renderError('新闻不存在');
}
$newsInfo['content'] = htmlspecialchars_decode($newsInfo['content']);
// 获取上下篇数据
$condition = $this->getCondition($current);
if ($condition) {
// 获取上一篇(发布时间小于当前文章)
$newsInfo['next_data'] = $this->getAdjacentNews($id, $newsInfo['publish_time'], $condition, '<', 'desc');
// 获取下一篇(发布时间大于当前文章)
$newsInfo['prev_data'] = $this->getAdjacentNews($id, $newsInfo['publish_time'], $condition, '>', 'asc');
} else {
$newsInfo['next_data'] = null;
$newsInfo['prev_data'] = null;
}
$newsInfo['user_follow'] = false;
$userId = $this->getUserId();
if ($userId > 0) {
$newsInfo['user_follow'] = UserNewsFavorite::isFavorite($userId, $id);
}
// 随机查询5条新闻数据
$re = NewsModel::where('status', 1)
->where($condition, '=', 1)
->where('cover_image', '!=', '')
->field('id,title,cover_image,publish_time,author_name,is_hot,is_featured')
->orderRaw('rand()')
->limit(5)
->select()
->toArray();
$newsInfo['recommend_news'] = $re;
// $newsInfo['publish_time'] = date('Y-m-d H:i:s', $newsInfo['publish_time']);
return $this->renderSuccess('', $newsInfo);
}
/**
* 根据来源类型获取条件
* @param int $current 来源类型 0: 热榜1精选2关注
* @return string|null 对应的条件字段
*/
private function getCondition($current)
{
switch ($current) {
case 0:
return 'is_hot';
case 1:
return 'is_featured';
case 2:
// 可以根据需求扩展
// return 'is_follow';
return null;
default:
return null;
}
}
/**
* 获取相邻的新闻
* @param int $id 当前新闻ID
* @param int $publishTime 当前发布时间
* @param string $condition 条件字段
* @param string $comparison 比较符号
* @param string $orderType 排序方式
* @return mixed 查询结果
*/
private function getAdjacentNews($id, $publishTime, $condition, $comparison, $orderType)
{
return NewsModel::where('id', '!=', $id)
->where($condition, '=', 1)
->where('status', '=', 1)
->where('publish_time', $comparison, $publishTime)
->field('id,title,cover_image,publish_time,is_hot,is_featured')
->order('publish_time ' . $orderType)
->find();
}
/**
* 收藏新闻
* @return \think\Response
*/
public function addFavorite()
{
$newsId = $this->request->param('news_id', 0);
if (empty($newsId)) {
return $this->renderError('参数错误');
}
// 检查新闻是否存在
$newsInfo = NewsModel::getInfo(['id' => $newsId], 'id');
if (!$newsInfo) {
return $this->renderError('新闻不存在');
}
// 获取当前用户ID
$userId = $this->getUserId();
if (!$userId) {
return $this->renderError('请先登录');
}
// 添加收藏
$result = UserNewsFavorite::addFavorite($userId, $newsId);
if ($result) {
return $this->renderSuccess('收藏成功');
}
return $this->renderError('收藏失败');
}
/**
* 取消收藏新闻
* @return \think\Response
*/
public function cancelFavorite()
{
$newsId = $this->request->param('news_id', 0);
if (empty($newsId)) {
return $this->renderError('参数错误');
}
// 获取当前用户ID
$userId = $this->getUserId();
if (!$userId) {
return $this->renderError('请先登录');
}
// 取消收藏
$result = UserNewsFavorite::cancelFavorite($userId, $newsId);
if ($result) {
return $this->renderSuccess('取消收藏成功');
}
return $this->renderError('取消收藏失败或未收藏该新闻');
}
/**
* 检查新闻是否已收藏
* @return \think\Response
*/
public function checkFavorite()
{
$newsId = $this->request->param('news_id', 0);
if (empty($newsId)) {
return $this->renderError('参数错误');
}
// 获取当前用户ID
$userId = $this->getUserId();
if (!$userId) {
return $this->renderError('请先登录');
}
// 检查是否已收藏
$favorite = UserNewsFavorite::isFavorite($userId, $newsId);
return $this->renderSuccess('', ['is_favorite' => $favorite ? true : false]);
}
}

View File

@ -959,7 +959,7 @@ class User extends Base
/*
海报生成器
*/
public function product_img()
{
@ -1274,18 +1274,23 @@ class User extends Base
return $this->renderError("用户不存在");
}
$userinfo['id'] = $user['id'];
$userinfo['ID'] = $user['id'];
$userinfo['mobile_is'] = $user['mobile'] ? 1 : 0;
$userinfo['nickname'] = $user['nickname'];
$userinfo['headimg'] = imageUrl($user['headimg']);
$userinfo['username'] = $user['nickname'];
$userinfo['userIcon'] = imageUrl($user['headimg']);
$userinfo['mobile'] = $user['mobile'] ? substr_replace($user['mobile'], '****', 3, 4) : '';
$userinfo['money'] = $user['money'];//钻石
$userinfo['money2'] = $user['money2'];//达达券
$userinfo['integral'] = $user['integral'];//UU币
$userinfo['uid'] = $user['uid'] ? $user['uid'] : $user['id'];
$other = [
'uid' => $user['uid'] ? $user['uid'] : $user['id'],
'pid' => $user['pid'],
'a' => $user['money'],//钻石
'b' => $user['money2'],//达达券
'c' => $user['integral'],//UU币
];
$userinfo['other'] = $this->encryption($other);
$day = floor(abs(time() - $user['addtime']) / 86400);
$userinfo['day'] = $day;
$userinfo['pid'] = $user['pid'];
$userinfo['days'] = $day;
return $this->renderSuccess("请求成功", $userinfo);
}

View File

@ -30,7 +30,7 @@ Route::any('user_yaoqing', 'Index/get_user_yaoqing');
// Route::any('yushourili', 'Index/yushourili');
Route::any('danye', 'Index/danye');
Route::any('getDanye', 'Index/getDanye');
Route::any('getAgreement', 'Index/getDanye');
#============================
#User.php个人中心
#============================
@ -55,6 +55,7 @@ Route::any('recharge', 'User/recharge');
Route::any('item_card_list', 'User/item_card_list');
Route::any('bind_invite_code', 'User/bind_invite_code');
Route::any('user_log_off', 'User/user_log_off');
Route::any('deleteAccount', 'User/user_log_off');
#Rank.php排行榜
#============================
Route::any('rank_week', 'Rank/rank_week');
@ -90,7 +91,7 @@ Route::any('getGoodExtend', 'Goods/getGoodExtend');
Route::any('coupon', 'Coupon/index');
Route::any('receive', 'Coupon/receive');
Route::any('used', 'Coupon/used');
Route::any('get_coupon_list', 'Coupon/get_coupon_list');
#============================
#Infinite.php 无限赏管理
#============================
@ -230,6 +231,15 @@ Route::any('get_diamond_list', 'Mall/get_diamond_list');
Route::any('createOrderProducts', 'Mall/createOrderProducts');
Route::any('get_diamond_order_log', 'Mall/get_diamond_order_log');
#============================
# 新闻管理
#============================
Route::any('get_featured_news_list', 'News/getFeaturedNewsList');
Route::any('get_hot_news_list', 'News/getHotNewsList');
Route::any('get_news_detail', 'News/getNewsDetail');
Route::any('get_follow_news_list', 'News/getFollowNewsList');
Route::any('user_favorite_news', 'News/addFavorite');
Route::any('user_cancel_favorite_news', 'News/cancelFavorite');
#============================APP使用的路由 ============================#
Route::any('V5Vx6qHOM5Ks9HqH', 'Login/login');

110
app/common/model/News.php Normal file
View File

@ -0,0 +1,110 @@
<?php
namespace app\common\model;
use think\Model;
class News extends Base
{
// 设置当前模型对应的完整数据表名称
protected $table = 'news';
// 设置字段自动写入时间戳
protected $autoWriteTimestamp = true;
// 定义时间戳字段名
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
/**
* 获取列表(分页)
*/
public static function getList($where, $field = '*', $order = 'publish_time desc', $pageSize = "15")
{
$list = self::where($where)
->field($field)
->order($order)
->paginate(['list_rows' => $pageSize, 'query' => request()->param()]);
$page = $list->render();
$data['list'] = $list->toArray()['data'];
$data['count'] = $list->total();
$data['last_page'] = $list->toArray()['last_page'];
// $data['page'] = $page;
return $data;
}
/**
* 获取全部列表(不分页)
*/
public static function getAllList($where = [], $field = '*', $order = 'publish_time desc', $limit = '0')
{
$data = self::where($where)
->field($field)
->order($order)
->limit($limit)
->select();
return $data;
}
/**
* 获取单条数据
*/
public static function getInfo($where = [], $field = '*')
{
$data = self::where($where)
->field($field)
->find();
return $data;
}
/**
* 获取热榜资讯
*/
public static function getHotNews($limit = 10, $field = '*')
{
return self::where('status', 1)
->where('is_hot', 1)
->field($field)
->order('publish_time desc')
->limit($limit)
->select();
}
/**
* 获取精选资讯
*/
public static function getFeaturedNews($limit = 10, $field = '*')
{
return self::where('status', 1)
->where('is_featured', 1)
->field($field)
->order('publish_time desc')
->limit($limit)
->select();
}
/**
* 根据作者ID获取资讯
*/
public static function getNewsByAuthor($authorId, $limit = 10, $field = '*')
{
return self::where('status', 1)
->where('author_id', $authorId)
->field($field)
->order('publish_time desc')
->limit($limit)
->select();
}
/**
* 搜索资讯
*/
public static function searchNews($keyword, $field = '*', $pageSize = 15)
{
return self::where('status', 1)
->where('title', 'like', '%' . $keyword . '%')
->field($field)
->order('publish_time desc')
->paginate(['list_rows' => $pageSize, 'query' => request()->param()]);
}
}

View File

@ -0,0 +1,141 @@
<?php
declare(strict_types=1);
namespace app\common\model;
use think\Model;
/**
* 用户收藏资讯模型
* Class UserNewsFavorite
* @package app\common\model
*/
class UserNewsFavorite extends Model
{
// 设置表名
protected $name = 'user_news_favorite';
// 设置主键
protected $pk = 'id';
// 自动写入时间戳字段
protected $autoWriteTimestamp = true;
// 定义时间戳字段名
protected $createTime = 'create_time';
protected $updateTime = false; // 不使用更新时间
/**
* 查询用户是否收藏了指定新闻
* @param int $userId 用户ID
* @param int $newsId 新闻ID
* @return bool|array false表示未收藏array表示收藏信息
*/
public static function isFavorite($userId, $newsId)
{
$where = [
'user_id' => $userId,
'news_id' => $newsId,
'is_canceled' => 0, // 未取消收藏
];
$favorite = self::where($where)->find();
return $favorite ? $favorite->toArray() : false;
}
/**
* 添加收藏
* @param int $userId 用户ID
* @param int $newsId 新闻ID
* @return bool|array 收藏结果
*/
public static function addFavorite($userId, $newsId)
{
// 检查是否已收藏
$favorite = self::where([
'user_id' => $userId,
'news_id' => $newsId,
])->find();
if ($favorite) {
// 已收藏但被取消,则恢复收藏
if ($favorite['is_canceled'] == 1) {
$favorite->is_canceled = 0;
$favorite->cancel_time = null;
$favorite->create_time = date('Y-m-d H:i:s');
$favorite->save();
return $favorite->toArray();
}
// 已收藏未取消,返回已存在
return $favorite->toArray();
}
// 新增收藏
$model = new self();
$model->user_id = $userId;
$model->news_id = $newsId;
$model->is_canceled = 0;
$model->save();
return $model->toArray();
}
/**
* 取消收藏
* @param int $userId 用户ID
* @param int $newsId 新闻ID
* @return bool 取消结果
*/
public static function cancelFavorite($userId, $newsId)
{
$favorite = self::where([
'user_id' => $userId,
'news_id' => $newsId,
'is_canceled' => 0,
])->find();
if (!$favorite) {
return false;
}
$favorite->is_canceled = 1;
$favorite->cancel_time = date('Y-m-d H:i:s');
return $favorite->save() !== false;
}
/**
* 获取用户收藏列表
* @param int $userId 用户ID
* @param int $page 页码
* @param int $limit 每页条数
* @return array 收藏列表
*/
public static function getUserFavoriteList($userId, $page = 1, $limit = 10)
{
$where = [
'user_id' => $userId,
'is_canceled' => 0,
];
$list = self::where($where)
->with(['news' => function ($query) {
$query->field('id,title,cover_image,publish_time,author_name');
}])
->page($page, $limit)
->order('create_time', 'desc')
->select()
->toArray();
return $list;
}
/**
* 关联新闻表
* @return \think\model\relation\HasOne
*/
public function news()
{
return $this->hasOne(News::class, 'id', 'news_id');
}
}

View File

@ -36,7 +36,7 @@ return [
'url' => '/admin/sign_config',
'name' => '用户签到设置',
],
// [
// 'url' => '/admin/user_loginStat',
// 'name' => '用户登录统计',
@ -96,7 +96,7 @@ return [
'url' => '/admin/diamond',
'name' => '钻石商品配置',
],
],
],
[
@ -217,6 +217,15 @@ return [
],
],
],
[
'name' => '审核页面管理',
'son' => [
[
'url' => '/admin/news',
'name' => '新闻列表',
],
],
],
[
'name' => '管理员管理',
'son' => [
@ -277,7 +286,7 @@ return [
// 'url' => '/admin/wechatofficialaccount',
// 'name' => '公众号设置',
// ],
],
],

3
public/js/quill/quill.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long