diff --git a/application/admin/controller/home/Encyclopedia.php b/application/admin/controller/home/Encyclopedia.php index f4b24c1..93b534a 100644 --- a/application/admin/controller/home/Encyclopedia.php +++ b/application/admin/controller/home/Encyclopedia.php @@ -18,6 +18,8 @@ class Encyclopedia extends Backend */ protected $model = null; + protected $searchFields = ["id","title","subtitle","source"]; + public function _initialize() { parent::_initialize(); diff --git a/application/admin/controller/home/Information.php b/application/admin/controller/home/Information.php index b853b41..085717d 100644 --- a/application/admin/controller/home/Information.php +++ b/application/admin/controller/home/Information.php @@ -17,6 +17,7 @@ class Information extends Backend * @var \app\admin\model\home\Information */ protected $model = null; + protected $searchFields = ["id","title","subtitle","source"]; public function _initialize() { diff --git a/application/admin/controller/home/LeaveWord.php b/application/admin/controller/home/LeaveWord.php index d6d4ab1..b885691 100644 --- a/application/admin/controller/home/LeaveWord.php +++ b/application/admin/controller/home/LeaveWord.php @@ -3,6 +3,10 @@ namespace app\admin\controller\home; use app\common\controller\Backend; +use think\Db; +use think\exception\DbException; +use think\exception\PDOException; +use think\exception\ValidateException; /** * 网站留言 @@ -23,6 +27,7 @@ class LeaveWord extends Backend parent::_initialize(); $this->model = new \app\admin\model\home\LeaveWord; $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("showList", $this->model->getShowList()); } @@ -34,4 +39,105 @@ class LeaveWord extends Backend */ + + /** + * 添加 + * + * @return string + * @throws \think\Exception + */ + public function add() + { + if (false === $this->request->isPost()) { + return $this->view->fetch(); + } + $params = $this->request->post('row/a'); + if (empty($params)) { + $this->error(__('Parameter %s can not be empty', '')); + } + $params = $this->preExcludeFields($params); + + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { + $params[$this->dataLimitField] = $this->auth->id; + } + $result = false; + Db::startTrans(); + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate; + $this->model->validateFailException()->validate($validate); + } + if($params["status"]=='2' && !$params["answer"]) { + $this->error("已处理,请填写回复内容!"); + } + + + $result = $this->model->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException|PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($result === false) { + $this->error(__('No rows were inserted')); + } + $this->success(); + } + + /** + * 编辑 + * + * @param $ids + * @return string + * @throws DbException + * @throws \think\Exception + */ + public function edit($ids = null) + { + $row = $this->model->get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + $adminIds = $this->getDataLimitAdminIds(); + if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) { + $this->error(__('You have no permission')); + } + if (false === $this->request->isPost()) { + $this->view->assign('row', $row); + return $this->view->fetch(); + } + $params = $this->request->post('row/a'); + if (empty($params)) { + $this->error(__('Parameter %s can not be empty', '')); + } + $params = $this->preExcludeFields($params); + $result = false; + Db::startTrans(); + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate; + $row->validateFailException()->validate($validate); + } + if($params["status"]=='2' && !$params["answer"]) { + $this->error("已处理,请填写回复内容!"); + } + + + $result = $row->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException|PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if (false === $result) { + $this->error(__('No rows were updated')); + } + $this->success(); + } + + } diff --git a/application/admin/controller/home/News.php b/application/admin/controller/home/News.php index 6579fe0..4c4fa21 100644 --- a/application/admin/controller/home/News.php +++ b/application/admin/controller/home/News.php @@ -2,7 +2,15 @@ namespace app\admin\controller\home; +use app\admin\library\Auth; use app\common\controller\Backend; +use PhpOffice\PhpSpreadsheet\Cell\Coordinate; +use PhpOffice\PhpSpreadsheet\Reader\Csv; +use PhpOffice\PhpSpreadsheet\Reader\Xls; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx; +use think\db\exception\BindParamException; +use think\Exception; +use think\exception\PDOException; /** * 新闻 @@ -44,6 +52,9 @@ class News extends Backend { //当前是否为关联查询 $this->relationSearch = true; + + $this->searchFields = ["id","title","subtitle","source","cate.name","cate.flag"]; + //设置过滤方法 $this->request->filter(['strip_tags', 'trim']); if ($this->request->isAjax()) { @@ -71,4 +82,230 @@ class News extends Backend return $this->view->fetch(); } + + + + /** + * 导入 + */ + public function import() + { + $file = $this->request->request('file'); + if (!$file) { + $this->error(__('Parameter %s can not be empty', 'file')); + } + $filePath = ROOT_PATH . DS . 'public' . DS . $file; + if (!is_file($filePath)) { + $this->error(__('No results were found')); + } + + + //实例化reader + $ext = pathinfo($filePath, PATHINFO_EXTENSION); + if (!in_array($ext, ['csv', 'xls', 'xlsx'])) { + $this->error(__('Unknown data format')); + } + if ($ext === 'csv') { + $file = fopen($filePath, 'r'); + $filePath = tempnam(sys_get_temp_dir(), 'import_csv'); + $fp = fopen($filePath, "w"); + $n = 0; + while ($line = fgets($file)) { + $line = rtrim($line, "\n\r\0"); + $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']); + if ($encoding != 'utf-8') { + $line = mb_convert_encoding($line, 'utf-8', $encoding); + } + if ($n == 0 || preg_match('/^".*"$/', $line)) { + fwrite($fp, $line . "\n"); + } else { + fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n"); + } + $n++; + } + fclose($file) || fclose($fp); + + $reader = new Csv(); + } elseif ($ext === 'xls') { + $reader = new Xls(); + } else { + $reader = new Xlsx(); + } + + //导入文件首行类型,默认是注释,如果需要使用字段名称请使用name + $importHeadType = isset($this->importHeadType) ? $this->importHeadType : 'comment'; + + $table = $this->model->getQuery()->getTable(); + $database = \think\Config::get('database.database'); +// $fieldArr = []; +// $list = db()->query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]); +// foreach ($list as $k => $v) { +// if ($importHeadType == 'comment') { +// $fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME']; +// } else { +// $fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_NAME']; +// } +// } + + //加载文件 + $insert = []; + try { + if (!$PHPExcel = $reader->load($filePath)) { + $this->error(__('Unknown data format')); + } + $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表 + $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号 + $allRow = $currentSheet->getHighestRow(); //取得一共有多少行 + $maxColumnNumber = Coordinate::columnIndexFromString($allColumn); + $fields = []; //遍历得到第一行的字段内容 + for ($currentRow = 1; $currentRow <= 1; $currentRow++) { + for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { + $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); + $fields[] = $val; + } + } + //遍历余下所有行(具体数据) + for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) { + $values = []; //得到当前行数据 + for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) { + $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); + $values[] = is_null($val) ? '' : $val; + } + if(!$values[0] && !$values[0])continue; + + $row = []; + $temp = array_combine($fields, $values); + + //拼接提交参数 + foreach ($temp as $k => $v) { + if(!$k)throw new Exception("异常的格式或存在空列,请检查!"); + //保留原始数据 + $raw_v = $v; + $v = str_replace('"','',trim(strip_tags(htmlspecialchars_decode($v)))); + switch ($k) + { + case "新闻标题": + case "文章标题": + case "标题": + if (!$v)throw new Exception("{$k}项有的行并未填写内容请检查!"); + + $row['title'] = $v; + break; + case "新闻副标题": + case "文章副标题": + case "副标题": + $row['subtitle'] = $v; + break; + case "发布时间": + case "时间": + $row['release_time'] = $v; + //转换时间2025/5/20 成时间戳 + $row['release_time'] = strtotime($row['release_time']); + + break; + case "内容" : + case "文章内容" : + +// var_dump($v);die; + + $row['content'] = $raw_v; + break; + case "新闻类目" : + case "类目" : + case "分类" : + case "分类ID" : + case "分类id" : + + //根据name查询分类表id + if($v){ + $cate = \app\admin\model\home\NewsCate::where('name',$v)->find(); + if ($cate) { + $row['cate_id'] = $cate['id']; + }else{ + //创建分类 + $cate = \app\admin\model\home\NewsCate::create([ + 'name' => $v, + 'status' => 1, + 'weigh' => 0, + ]); + $row['cate_id'] = $cate['id']; + } + }else{ + //无分类默认第一个 + $row['cate_id'] = \app\admin\model\home\NewsCate::where('status',1)->order('weigh desc')->value('id'); + + } + + break; + case "来源" : + $row['source'] = $v; // 来源 + break; + case "浏览量" : + case "点击数" : + $row['views'] = $v; // 来源 + break; + case "来源复合数据" : + //$v = "来源:新华社 发布日期:2025-05-20 点击数:15"; + if (!$v)throw new Exception("{$k}项有的行并未填写内容请检查!"); + + // 转换编码为 UTF-8 + $v = mb_convert_encoding($v, 'UTF-8', 'UTF-8,GBK,GB2312,ASCII'); + + if (preg_match('/来源:(.+?)[\\s ]+发布日期:(\d{4}-\d{2}-\d{2})[\\s ]+点击数:(\d+)/is', $v, $matches)) { + $source = isset($matches[1]) ? trim(mb_convert_encoding($matches[1], 'UTF-8', 'auto')) : ''; + $releaseDate = isset($matches[2]) ? strtotime(trim($matches[2])) : null; + $clicks = isset($matches[3]) ? intval(trim($matches[3])) : 0; + + $row['source'] = $source; // 来源 + $row['release_time'] = $releaseDate ?: time(); // 默认当前时间 + $row['views'] = $clicks; // 点击数 +// var_dump($row);die; + } else { + $this->error("来源复合数据格式异常,请检查字段内容: {$v}"); + } + + + break; + } + } + if ($row) { + //查询是否存在一样的,如果存在,忽略 + $where = [ + 'title' => $row['title'], + ]; +// unset($where['title']); + if(! \app\admin\model\home\News::where($where)->find()){ + $row["weigh"] = 0; + $insert[] = $row; + } + } + } +// var_dump($values);die; + } catch (Exception $exception) { + $this->error($exception->getMessage()); + } + if (!$insert) { + $this->error(__('No rows were updated')); + } + + try { + //$insert倒序插入 + $insert = array_reverse($insert); + + $this->model->saveAll($insert); + } catch (PDOException $exception) { + $msg = $exception->getMessage(); + if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $msg, $matches)) { + $msg = "导入失败,包含【{$matches[1]}】的记录已存在"; + }; + var_dump($exception->getData()); + $this->error($msg); + } catch (Exception $e) { + $this->error($e->getMessage()); + } + + $this->success(); + } + + } diff --git a/application/admin/lang/zh-cn/home/leave_word.php b/application/admin/lang/zh-cn/home/leave_word.php index 64a7477..df0573c 100644 --- a/application/admin/lang/zh-cn/home/leave_word.php +++ b/application/admin/lang/zh-cn/home/leave_word.php @@ -4,12 +4,18 @@ return [ 'Name' => '提交者姓名', 'Mobile' => '联系电话', 'Emil' => '邮箱地址', - 'Message' => '留言内容', + 'Question' => '问题', + 'Message' => '描述', 'Status' => '状态', 'Status 1' => '未处理', 'Set status to 1'=> '设为未处理', 'Status 2' => '已处理', 'Set status to 2'=> '设为已处理', + 'Answer' => '回复', + 'Show' => '精选展示', + 'Show 0' => '否', + 'Show 1' => '是', + 'Weigh' => '权重', 'Createtime' => '创建时间', 'Updatetime' => '修改时间' ]; diff --git a/application/admin/model/home/LeaveWord.php b/application/admin/model/home/LeaveWord.php index 374cfc5..ea05298 100644 --- a/application/admin/model/home/LeaveWord.php +++ b/application/admin/model/home/LeaveWord.php @@ -25,16 +25,32 @@ class LeaveWord extends Model // 追加属性 protected $append = [ - 'status_text' + 'status_text', + 'show_text' ]; + protected static function init() + { + self::afterInsert(function ($row) { + if (!$row['weigh']) { + $pk = $row->getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + } + }); + } + public function getStatusList() { return ['1' => __('Status 1'), '2' => __('Status 2')]; } + public function getShowList() + { + return ['0' => __('Show 0'), '1' => __('Show 1')]; + } + public function getStatusTextAttr($value, $data) { @@ -44,6 +60,14 @@ class LeaveWord extends Model } + public function getShowTextAttr($value, $data) + { + $value = $value ?: ($data['show'] ?? ''); + $list = $this->getShowList(); + return $list[$value] ?? ''; + } + + } diff --git a/application/admin/view/home/leave_word/add.html b/application/admin/view/home/leave_word/add.html index 7ad7a40..6246223 100644 --- a/application/admin/view/home/leave_word/add.html +++ b/application/admin/view/home/leave_word/add.html @@ -18,10 +18,16 @@ +
+ +
+ +
+
- +
@@ -36,6 +42,30 @@
+
+ +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
- +
@@ -36,6 +42,30 @@
+
+ +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+ +
+
Headers
+
+ 无 +
+
+
+
参数
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型必选描述
namestring提交者姓名
mobilestring联系电话
emilstring邮箱地址
questionstring问题
messagestring描述
+
+
+
+
正文
+
+ 无
+
+ + +
+
+
+
+
参数 +
+ 追加 +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
响应输出
+
+
+
+

+                                                            

+                                                        
+
+
+
+
+
返回参数
+
+ 无 +
+
+
+
+
+ +
+
+
+
{
+     *
+     *}
+
+
+
+ + + + + +
+
+

+ GET + 留言列表 /api/home.leave_word/index +

+
+
+
+ + + + + +
+ +
+
+ 留言列表
+
+
权限
+
+ + + + + + + + + + + +
登录
鉴权
+
+
+
+
Headers
+
+ 无 +
+
+
+
参数
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型必选描述
keywordsstring搜索关键字
pagestring页数
limitstring条数
statusstring状态:1=未处理,2=已处理
showstring精选展示:0=否,1=是
+
+
+
+
正文
+
+ 无
+
+
+ +
+
+
+
+
参数 +
+ 追加 +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
响应输出
+
+
+
+

+                                                            

+                                                        
+
+
+
+
+
返回参数
+
+ 无 +
+
+
+
+
+ +
+
+
+
{
+     *
+     *}
+
+
+
+ +
+
+
+
+

新闻接口

+
+
+
+

+ GET + 新闻列表 /api/home.news/index +

+
+
+
+ + + + + +
+ +
新闻列表
@@ -2294,7 +2651,7 @@
-
+
@@ -2304,7 +2661,7 @@
-
+
@@ -2334,8 +2691,8 @@
- - + +
@@ -2345,8 +2702,8 @@
-

-                                                            

+                                                            

+                                                            

                                                         
@@ -2361,10 +2718,10 @@
-
+
-
{
+                                            
{
      *
      *}
@@ -2376,26 +2733,26 @@
-
+ -
+
-