496 lines
20 KiB
PHP
496 lines
20 KiB
PHP
<?php
|
|
declare (strict_types = 1);
|
|
|
|
namespace app\controller\backend;
|
|
|
|
use app\exception\ModelException;
|
|
use app\model\Attachment;
|
|
use app\model\Category;
|
|
use app\model\CategoryCheck;
|
|
use app\model\Route;
|
|
use app\model\ThemeFile;
|
|
use app\model\Website;
|
|
use app\service\ApiService;
|
|
use app\service\CacheService;
|
|
use app\service\CategoryService;
|
|
use app\service\StaticFileService;
|
|
use app\validate\CategoryValidate;
|
|
use Overtrue\Pinyin\Pinyin;
|
|
use think\exception\ValidateException;
|
|
use think\facade\Cache;
|
|
use think\facade\Db;
|
|
use think\facade\Lang;
|
|
|
|
class CategoryController extends BaseController
|
|
{
|
|
|
|
protected $cacheKeyArr = 'hc_module_cate_arr';
|
|
|
|
/**
|
|
* 栏目列表
|
|
*
|
|
* @return \think\response\Json
|
|
* @throws \app\exception\ModelException
|
|
* @throws \app\exception\ModelEmptyException
|
|
*/
|
|
public function index(Category $category): \think\response\Json
|
|
{
|
|
$websiteId = (int)input('param.website_id');
|
|
if(!$websiteId){
|
|
return jsonReturn(-1,Lang::get('网站ID不能为空'));
|
|
}
|
|
$where = [
|
|
['seller_id','=', $this->admin['seller_id']],
|
|
['website_id','=',$websiteId],
|
|
];
|
|
$lang = input('lang');
|
|
if(empty($lang)){
|
|
$lang = config('lang.default_lang');
|
|
}
|
|
$Website = new Website();
|
|
$website = $Website -> getCustomArrayData(['id'=>$websiteId,'seller_id'=>$this->admin['seller_id']])['data'];
|
|
$domain = $website['domain'];
|
|
if($lang != config('lang.default_lang')){
|
|
$domain = $domain .'/'.$lang;
|
|
}
|
|
$title = $this->request->param('title','');
|
|
if(!empty($title)) {
|
|
$where[] = ['title', 'like', '%' . $title . '%'];
|
|
}
|
|
$where[] = ['lang','=',$lang];
|
|
$with = [
|
|
'thumbnail' => function($query){
|
|
$query->field('id,name,url');
|
|
}
|
|
];
|
|
|
|
//栏目管理搜索栏目名称
|
|
$categoryTitle = $this->request->param("category_title/s",'','trim,strip_tags');
|
|
if(!empty($categoryTitle)){
|
|
$categoryIdPath = $category->where([
|
|
['seller_id','=', $this->admin['seller_id']],
|
|
['website_id','=',$websiteId],
|
|
['lang','=',$lang],
|
|
['title','like',"%{$categoryTitle}%"],
|
|
])->column('path','id');
|
|
if(empty($categoryIdPath)){
|
|
return jsonReturn(0,'内容不存在');
|
|
}
|
|
$selectIds = [];
|
|
foreach ($categoryIdPath as $pathId => $paths){
|
|
$paths = explode('-',$paths);
|
|
for ($i=1;$i<count($paths)-1;$i++){
|
|
$selectIds[$paths[$i]] = $paths[$i];
|
|
}
|
|
$selectIds[$pathId] = $pathId;
|
|
}
|
|
$where[] = ['id','in',$selectIds];
|
|
}
|
|
|
|
|
|
$themeFileModel = new ThemeFile();
|
|
$designFileList = $themeFileModel->getAllCustomArrayData([['is_design', '=', 1]])['data'];
|
|
$newDesignFileList = [];
|
|
foreach ($designFileList as $value) {
|
|
$value['file_name'] = str_replace('.html', '', $value['file']);
|
|
$newDesignFileList[$value['file']] = $value;
|
|
$newDesignFileList[$value['file_name']] = $value;
|
|
}
|
|
$categoryList = $category->getAllCustomArrayData($where,'id asc','id,seller_id,parent_id,title,lang,alias,type,path,thumbnail,sort,status,list_tpl',$with)['data'];
|
|
foreach($categoryList as &$item){
|
|
if($item['type'] == 1 || $item['type'] == 4){
|
|
if(!empty($item['alias'])){
|
|
if($item['alias'] == '/'){
|
|
$item['fullUrl'] = '//' . $domain;
|
|
}else{
|
|
$item['fullUrl'] = '//' . $domain . $item['alias'].'.'.config('route.url_html_suffix');
|
|
}
|
|
}else{
|
|
$item['fullUrl'] = '//' . $domain . '/list/index/'.$item['id'].'.'.config('route.url_html_suffix');
|
|
}
|
|
}else if($item['type'] == 3){
|
|
$item['fullUrl'] = $item['alias'];
|
|
}else{
|
|
$item['fullUrl'] = 'javascript:;';
|
|
}
|
|
|
|
$item['is_design'] = 0;
|
|
$item['design_path'] = '';
|
|
if (isset($newDesignFileList[$item['list_tpl']])) {
|
|
$item['is_design'] = 1;
|
|
$item['design_path'] = $newDesignFileList[$item['list_tpl']]['design_path'];
|
|
}
|
|
}
|
|
$categoryList = makeTree($categoryList);
|
|
return jsonReturn(0,'success',$categoryList);
|
|
}
|
|
|
|
/**
|
|
* 保存新建的资源
|
|
*
|
|
* @return \think\response\Json
|
|
* @throws \app\exception\ModelException
|
|
* @throws \app\exception\ModelEmptyException
|
|
*/
|
|
public function save(CategoryService $categoryService,Category $Category): \think\response\Json
|
|
{
|
|
if(request()->isPost()){
|
|
$param = input('post.');
|
|
$param['alias'] = $param['alias'] ?? '';
|
|
$param['module_id'] = $param['module_id'] ?? 1;
|
|
// 数据验证
|
|
try{
|
|
if(!empty($param['parent_map'])){
|
|
$param = $this->getMapCateData($param);
|
|
}
|
|
validate(CategoryValidate::class)->scene('save')->check($param);
|
|
}catch(ValidateException $e){
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
if (in_array($param['alias'], StaticFileService::$forbidNames)) {
|
|
return jsonReturn(-2,lang('别名已被系统占用,请修改别名'));
|
|
}
|
|
$param['seller_id'] = $this->admin['seller_id'];
|
|
$category = $Category->existCategory(['title'=>$param['title'],'seller_id'=>$param['seller_id'],'website_id'=>$param['website_id'],'lang'=>$param['lang'],'parent_id'=>$param['parent_id']])['data'];
|
|
if(!empty($category)){
|
|
return jsonReturn(-2,'栏目已经存在');
|
|
}
|
|
if(in_array($param['type'],[1,4]) && empty($param['alias'])){
|
|
if($param['list_tpl'] == 'index'){
|
|
$param['alias'] = '/';
|
|
}else{
|
|
$param['alias'] = $this->getAlias($param['title'],$param['website_id'],$param['lang'],$param['seller_id']);
|
|
}
|
|
}
|
|
if(!empty($param['alias']) && $param['alias'] != 'javascript:;'){
|
|
$category = $Category->existCategory(['title'=>$param['alias'],'seller_id'=>$param['seller_id'],'website_id'=>$param['website_id'],'lang'=>$param['lang']])['data'];
|
|
}
|
|
if(!empty($category)){
|
|
return jsonReturn(-3,lang('栏目别名已经存在'));
|
|
}
|
|
if ($param['need_check'] == 1 && (empty($param['check_list']) || !is_array($param['check_list']))) {
|
|
return jsonReturn(-3,'请设置审核人员!');
|
|
}
|
|
if (!empty($param['field_list'])) {
|
|
$keyArr = [];
|
|
foreach ($param['field_list'] as $value) {
|
|
if (isset($keyArr[$value['key']])) {
|
|
return jsonReturn(-5,lang('自定义字段名称重复:') . $value['key']);
|
|
}
|
|
$keyArr[$value['key']] = $value;
|
|
}
|
|
$param['field_list'] = json_encode($param['field_list'], JSON_UNESCAPED_UNICODE);
|
|
}
|
|
return $categoryService -> createCategory($param);
|
|
}
|
|
return jsonReturn(-3,Lang::get(lang('请求方法错误')));
|
|
}
|
|
|
|
/**
|
|
* 栏目详情
|
|
*
|
|
* @return \think\response\Json
|
|
* @throws \app\exception\ModelException
|
|
* @throws \app\exception\ModelEmptyException
|
|
*/
|
|
public function read(Category $category,Attachment $attachment): \think\response\Json
|
|
{
|
|
$param = input('param.');
|
|
try {
|
|
validate(CategoryValidate::class)->scene('read')->check($param);
|
|
} catch (ValidateException $e) {
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
$param['seller_id']= $this->admin['seller_id'];
|
|
$with = [
|
|
'thumbnail' => function($query){
|
|
$query->field('id,name,url');
|
|
},'banner' => function($query){
|
|
$query->field('id,name,url');
|
|
}
|
|
];
|
|
$res = $category->getCategory($param,$with);
|
|
|
|
if (!empty($res['data']['content'])) {
|
|
$res['data']['content'] = htmlspecialchars_decode($res['data']['content']);
|
|
}
|
|
$res['data']['check_list'] = [];
|
|
if ($res['data']['need_check'] == 1) {
|
|
$checkModel = new CategoryCheck();
|
|
$checkList = $checkModel->where([
|
|
['category_id', '=', $res['data']['id']],
|
|
['status', '=', 1]
|
|
])->select()->toArray();
|
|
|
|
$res['data']['check_list'] = $checkList;
|
|
}
|
|
if (!empty($res['data']['field_list'])) {
|
|
$res['data']['field_list'] = json_decode($res['data']['field_list'], true);
|
|
}
|
|
return json($res);
|
|
}
|
|
|
|
/**
|
|
* 保存更新的资源
|
|
* @return \think\response\Json
|
|
* @throws \app\exception\ModelException
|
|
* @throws \app\exception\ModelEmptyException
|
|
*/
|
|
public function update(CategoryService $categoryService,Category $Category): \think\response\Json
|
|
{
|
|
if(request()->isPost()){
|
|
$param = input('post.');
|
|
try {
|
|
if(!empty($param['parent_map'])){
|
|
$param = $this->getMapCateData($param);
|
|
}
|
|
validate(CategoryValidate::class)->scene('update')->check($param);
|
|
} catch (ValidateException $e) {
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
if (in_array($param['alias'], StaticFileService::$forbidNames)) {
|
|
return jsonReturn(-2,lang('别名已被系统占用,请修改别名'));
|
|
}
|
|
$param['seller_id'] = $this->admin['seller_id'];
|
|
if(in_array($param['type'],[1,4]) && empty($param['alias'])){
|
|
if($param['list_tpl'] == 'index'){
|
|
$param['alias'] = '/';
|
|
}else{
|
|
$param['alias'] = $this->getAlias($param['title'],$param['website_id'],$param['lang'],$param['seller_id']);
|
|
}
|
|
}
|
|
$category = $Category->existCategory(['title'=>$param['title'],'seller_id'=>$param['seller_id'],'website_id'=>$param['website_id'],'lang'=>$param['lang'],'parent_id'=>$param['parent_id']])['data'];
|
|
if(!empty($category) && $category['id'] != $param['id']){
|
|
return jsonReturn(-2,lang('栏目已经存在'));
|
|
}
|
|
$category = $Category->existCategory(['title'=>$param['alias'],'seller_id'=>$param['seller_id'],'website_id'=>$param['website_id']])['data'];
|
|
if(!empty($category) && $category['id'] != $param['id']){
|
|
return jsonReturn(-3,lang('栏目别名已经存在'));
|
|
}
|
|
if (isset($param['need_check']) && $param['need_check'] == 1 && (empty($param['check_list']) || !is_array($param['check_list']))) {
|
|
return jsonReturn(-3,lang('请设置审核人员'));
|
|
}
|
|
if (!empty($param['field_list'])) {
|
|
$keyArr = [];
|
|
foreach ($param['field_list'] as $value) {
|
|
if (isset($keyArr[$value['key']])) {
|
|
return jsonReturn(-5,lang('自定义字段名称重复:') . $value['key']);
|
|
}
|
|
$keyArr[$value['key']] = $value;
|
|
}
|
|
$param['field_list'] = json_encode($param['field_list'], JSON_UNESCAPED_UNICODE);
|
|
}
|
|
$this->deleteCateCacheKey($param['website_id'],$param['lang']);
|
|
return $categoryService -> updateCategory($param);
|
|
}
|
|
return jsonReturn(-3,Lang::get('请求方法错误'));
|
|
}
|
|
|
|
/**
|
|
* 删除栏目
|
|
* @param Category $category
|
|
* @param Route $route
|
|
* @return \think\response\Json
|
|
*/
|
|
public function delete(Category $category,Route $route): \think\response\Json
|
|
{
|
|
if(request()->isPost()){
|
|
$param = input('post.');
|
|
try {
|
|
validate(CategoryValidate::class)->scene('delete')->check($param);
|
|
} catch (ValidateException $e) {
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
$where = [
|
|
'id' => $param['id'],
|
|
'seller_id' => $this->admin['seller_id'],
|
|
'website_id' => $param['website_id'],
|
|
'lang' => $param['lang']
|
|
];
|
|
Db::startTrans();
|
|
try {
|
|
$subCate = $category -> getAllCustomArrayData(['seller_id'=>$this->admin['seller_id'],'parent_id'=>$param['id']])['data'];
|
|
$this->deleteCateCacheKey($param['website_id'],$param['lang']);
|
|
if(!empty($subCate)){
|
|
return jsonReturn(-1,lang('栏目下面有子栏目,不能直接删除'));
|
|
}
|
|
$res = $category->delCategory($where);
|
|
$route->delRoute(['seller_id' => $this->admin['seller_id'],'category_id'=>$param['id']]);
|
|
$route->getRoutes($param['website_id'], $this->admin['seller_id'], $param['lang']);
|
|
CacheService::deleteRelationCacheByObject($route);
|
|
CacheService::deleteRelationCacheByObject($category);
|
|
$optAdmin = request()->admin;
|
|
event("AdminOptLog",[
|
|
'admin_id' => $optAdmin['uid'],
|
|
'admin_name' => $optAdmin['name'],
|
|
'title'=>lang("栏目管理"),
|
|
"content"=>lang("删除栏目,栏目ID为").$param['id'],
|
|
]);
|
|
Db::commit();
|
|
Cache::clear();
|
|
}catch (ModelException $me){
|
|
Db::rollback();
|
|
return jsonReturn(50023,$me->getMessage());
|
|
}catch (\Exception $e){
|
|
Db::rollback();
|
|
return jsonReturn(50024,$e->getMessage());
|
|
}
|
|
return json($res);
|
|
}
|
|
return jsonReturn(-3,Lang::get('请求方法错误'));
|
|
}
|
|
|
|
|
|
/**
|
|
* 分组获取栏目列表
|
|
* @param Category $Category
|
|
* @return \think\response\Json
|
|
*/
|
|
public function getModuleCate(Category $Category): \think\response\Json
|
|
{
|
|
$param = input('get.');
|
|
try {
|
|
validate(CategoryValidate::class)->scene('getModuleCate')->check($param);
|
|
} catch (ValidateException $e) {
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
|
|
$Website = new Website();
|
|
$website = $Website->getAllCustomArrayData([['id','in',$param['site_id']],['seller_id','=',$this->admin['seller_id']]]
|
|
,'id asc','id,seller_id,title,domain')['data'];
|
|
$website = getColumnForKeyArray($website,'id');
|
|
|
|
$category = $Category -> getAllCustomArrayData([['website_id','in',$param['site_id']],['seller_id','=',$this->admin['seller_id']],['lang','=',$param['lang']]],'id asc')['data'];
|
|
$category = getArrayGroupBy($category,'website_id');
|
|
$response = [];
|
|
foreach($category as $key => $cate){
|
|
$tmpCategory = $this->makeTree($cate);
|
|
$tmpCategory = $this->imp($tmpCategory);
|
|
$tmpCate = $website[$key];
|
|
$tmpCate['category'] = $tmpCategory;
|
|
$response[] = $tmpCate;
|
|
}
|
|
|
|
return jsonReturn(0,lang('成功'),$response);
|
|
}
|
|
|
|
public function makeTree($data, int $pid=0, int $level=0): array
|
|
{
|
|
$tree = array();
|
|
$tmpTree = [];
|
|
foreach ($data as $key => &$value) {
|
|
$str = str_repeat('--',$level);
|
|
$value['title'] = $str . $value['title'];
|
|
if ($value['parent_id'] == $pid) {
|
|
$value['level'] = $level;
|
|
unset($data[$key]);
|
|
$tmpTree[] = $value;
|
|
$value['children'] = $this->makeTree($data, $value['id'],$level+1);
|
|
$tree[] = $value;
|
|
}else{
|
|
$tmpTree[] = $value;
|
|
}
|
|
}
|
|
return $tree;
|
|
}
|
|
|
|
public function imp($tree, $children='children'): array
|
|
{
|
|
$impArr = array();
|
|
foreach($tree as $w) {
|
|
if(isset($w[$children])) {
|
|
$t = $w[$children];
|
|
unset($w[$children]);
|
|
$impArr[] = $w;
|
|
if(is_array($t)) $impArr = array_merge($impArr, $this->imp($t, $children));
|
|
} else {
|
|
$impArr[] = $w;
|
|
}
|
|
}
|
|
return $impArr;
|
|
}
|
|
|
|
/**
|
|
* 栏目复制
|
|
* @throws ModelException
|
|
* @throws \Exception
|
|
*/
|
|
public function copy(CategoryService $categoryService): \think\response\Json
|
|
{
|
|
set_time_limit(300);
|
|
$param = input('post.');
|
|
try {
|
|
validate(CategoryValidate::class)->scene('copy')->check($param);
|
|
} catch (ValidateException $e) {
|
|
return jsonReturn(-1, $e->getError());
|
|
}
|
|
foreach ($param['target_site'] as $val){
|
|
if(empty($val) || !is_numeric($val)){
|
|
return jsonReturn(-1,lang('目标站点数据异常,请检查'));
|
|
}
|
|
}
|
|
$res = $categoryService -> copyCate($param['original_site'],$param['target_site'],$param['lang'],$this->admin['seller_id']);
|
|
return json($res);
|
|
}
|
|
|
|
/**
|
|
* @throws \app\exception\ModelEmptyException
|
|
* @throws ModelException
|
|
*/
|
|
public function getMapCateData(&$param)
|
|
{
|
|
$Category = new Category();
|
|
$param['parent_path'] = json_encode($param['parent_map']);
|
|
$param['parent_map'] = array_pop($param['parent_map']);
|
|
$mapCate = $Category->getCategory(['id'=>$param['parent_map'],'seller_id'=>$this->admin['seller_id']])['data']->toArray();
|
|
foreach($mapCate as $k => $v){
|
|
if($k == 'parent_id'){
|
|
continue;
|
|
}
|
|
if(empty($param[$k]) && !in_array($k,['id','create_time','update_time'])){
|
|
$param[$k] = $v;
|
|
}
|
|
}
|
|
return $param;
|
|
}
|
|
|
|
public function deleteCateCacheKey($siteId,$lang)
|
|
{
|
|
$cateCacheKey = 'hc_cate_' . $this->admin['seller_id'] . '_' . $siteId .'_' . $lang;
|
|
Cache::delete($cateCacheKey);
|
|
$moduleCateArr = Cache::get($this->cacheKeyArr);
|
|
if(!empty($moduleCateArr)){
|
|
foreach ($moduleCateArr as $cate){
|
|
$tmpCate = explode('_',str_replace('hc_module_cate_' . $this->admin['seller_id'] . '_' . $lang .'_','',$cate));
|
|
if(in_array($siteId,$tmpCate)){
|
|
$moduleCateCacheKey = 'hc_module_cate_' . $this->admin['seller_id'] . '_' . $lang .'_' . $siteId;
|
|
Cache::delete($moduleCateCacheKey);
|
|
unset($moduleCateArr[$cate]);
|
|
}
|
|
}
|
|
Cache::set($this->cacheKeyArr,$moduleCateArr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws ModelException
|
|
* @throws \app\exception\ModelEmptyException
|
|
*/
|
|
public function getAlias($title, $siteId, $lang, $sellerId): string
|
|
{
|
|
$pinyin = new Pinyin();
|
|
$cacheKey = $sellerId .'_'.$siteId .'_'. $lang . '_website_cache_key';
|
|
$settingData = Cache::get($cacheKey);
|
|
if(empty($settingData)){
|
|
$settingData = ApiService::setWebsiteSetting($sellerId,$siteId,$lang);
|
|
}
|
|
|
|
if(!empty($settingData['alias_rule']) && $settingData['alias_rule'] == 1){
|
|
$alias = strtolower('/' . $pinyin -> abbr($title));
|
|
}else{
|
|
$alias = strtolower('/' . $pinyin -> permalink($title,''));
|
|
}
|
|
return $alias;
|
|
}
|
|
}
|