自动推广
This commit is contained in:
493
application/api/controller/ExpertManage.php
Normal file
493
application/api/controller/ExpertManage.php
Normal file
@@ -0,0 +1,493 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\Db;
|
||||
|
||||
class ExpertManage extends Base
|
||||
{
|
||||
private $stateMap = [
|
||||
0 => '待联系',
|
||||
1 => '已发邮件',
|
||||
2 => '已回复',
|
||||
3 => '已投稿',
|
||||
4 => '退信/无效',
|
||||
5 => '黑名单(退订)',
|
||||
];
|
||||
|
||||
public function __construct(\think\Request $request = null)
|
||||
{
|
||||
parent::__construct($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 专家列表(支持多条件筛选 + 分页)
|
||||
*
|
||||
* 参数:
|
||||
* keyword - 搜索姓名/邮箱/单位
|
||||
* field - 按领域关键词筛选
|
||||
* major_id - 按学科ID筛选
|
||||
* state - 状态筛选 (0-5, 传-1或不传则不过滤)
|
||||
* source - 来源筛选
|
||||
* pageIndex - 页码 (默认1)
|
||||
* pageSize - 每页条数 (默认20)
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
$data = $this->request->param();
|
||||
$keyword = trim(isset($data['keyword']) ? $data['keyword'] : '');
|
||||
$field = trim(isset($data['field']) ? $data['field'] : '');
|
||||
$majorId = intval(isset($data['major_id']) ? $data['major_id'] : 0);
|
||||
$state = isset($data['state']) ? $data['state'] : '-1';
|
||||
$source = trim(isset($data['source']) ? $data['source'] : '');
|
||||
$page = max(1, intval(isset($data['pageIndex']) ? $data['pageIndex'] : 1));
|
||||
$pageSize = max(1, intval(isset($data['pageSize']) ? $data['pageSize'] : 20));
|
||||
|
||||
$query = Db::name('expert')->alias('e');
|
||||
$needJoin = ($field !== '' || $majorId > 0);
|
||||
|
||||
if ($needJoin) {
|
||||
$query->join('t_expert_field ef', 'ef.expert_id = e.expert_id AND ef.state = 0', 'inner');
|
||||
if ($field !== '') {
|
||||
$query->where('ef.field', 'like', '%' . $field . '%');
|
||||
}
|
||||
if ($majorId > 0) {
|
||||
$query->where('ef.major_id', $majorId);
|
||||
}
|
||||
$query->group('e.expert_id');
|
||||
}
|
||||
|
||||
if ($state !== '-1' && $state !== '') {
|
||||
$query->where('e.state', intval($state));
|
||||
}
|
||||
if ($keyword !== '') {
|
||||
$query->where('e.name|e.email|e.affiliation', 'like', '%' . $keyword . '%');
|
||||
}
|
||||
if ($source !== '') {
|
||||
$query->where('e.source', $source);
|
||||
}
|
||||
|
||||
$countQuery = clone $query;
|
||||
$total = $countQuery->distinct('e.expert_id')->count();
|
||||
|
||||
$list = $query
|
||||
->field('e.*')
|
||||
->order('e.ctime desc')
|
||||
->page($page, $pageSize)
|
||||
->select();
|
||||
|
||||
foreach ($list as &$item) {
|
||||
$item['fields'] = Db::name('expert_field')
|
||||
->where('expert_id', $item['expert_id'])
|
||||
->where('state', 0)
|
||||
->select();
|
||||
$item['state_text'] = isset($this->stateMap[$item['state']]) ? $this->stateMap[$item['state']] : '未知';
|
||||
$item['ctime_text'] = $item['ctime'] ? date('Y-m-d H:i:s', $item['ctime']) : '';
|
||||
$item['ltime_text'] = $item['ltime'] ? date('Y-m-d H:i:s', $item['ltime']) : '';
|
||||
}
|
||||
|
||||
return jsonSuccess([
|
||||
'list' => $list,
|
||||
'total' => $total,
|
||||
'pageIndex' => $page,
|
||||
'pageSize' => $pageSize,
|
||||
'totalPages' => $total > 0 ? ceil($total / $pageSize) : 0,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取专家详情(含所有领域)
|
||||
*/
|
||||
public function getDetail()
|
||||
{
|
||||
$expertId = intval($this->request->param('expert_id', 0));
|
||||
if (!$expertId) {
|
||||
return jsonError('expert_id is required');
|
||||
}
|
||||
|
||||
$expert = Db::name('expert')->where('expert_id', $expertId)->find();
|
||||
if (!$expert) {
|
||||
return jsonError('专家不存在');
|
||||
}
|
||||
|
||||
$expert['fields'] = Db::name('expert_field')
|
||||
->where('expert_id', $expertId)
|
||||
->where('state', 0)
|
||||
->select();
|
||||
$expert['state_text'] = isset($this->stateMap[$expert['state']]) ? $this->stateMap[$expert['state']] : '未知';
|
||||
$expert['ctime_text'] = $expert['ctime'] ? date('Y-m-d H:i:s', $expert['ctime']) : '';
|
||||
$expert['ltime_text'] = $expert['ltime'] ? date('Y-m-d H:i:s', $expert['ltime']) : '';
|
||||
|
||||
return jsonSuccess($expert);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加专家
|
||||
*/
|
||||
public function addExpert()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$name = trim(isset($data['name']) ? $data['name'] : '');
|
||||
$email = trim(isset($data['email']) ? $data['email'] : '');
|
||||
|
||||
if ($name === '' || $email === '') {
|
||||
return jsonError('name和email不能为空');
|
||||
}
|
||||
|
||||
$exists = Db::name('expert')->where('email', $email)->find();
|
||||
if ($exists) {
|
||||
return jsonError('该邮箱已存在,expert_id=' . $exists['expert_id']);
|
||||
}
|
||||
|
||||
$insert = [
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'affiliation' => trim(isset($data['affiliation']) ? $data['affiliation'] : ''),
|
||||
'source' => trim(isset($data['source']) ? $data['source'] : 'manual'),
|
||||
'ctime' => time(),
|
||||
'ltime' => 0,
|
||||
'state' => 0,
|
||||
];
|
||||
|
||||
$expertId = Db::name('expert')->insertGetId($insert);
|
||||
|
||||
if (!empty($data['fields'])) {
|
||||
$this->saveExpertFields($expertId, $data['fields']);
|
||||
}
|
||||
|
||||
return jsonSuccess(['expert_id' => $expertId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑专家
|
||||
*/
|
||||
public function editExpert()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$expertId = intval(isset($data['expert_id']) ? $data['expert_id'] : 0);
|
||||
if (!$expertId) {
|
||||
return jsonError('expert_id is required');
|
||||
}
|
||||
|
||||
$expert = Db::name('expert')->where('expert_id', $expertId)->find();
|
||||
if (!$expert) {
|
||||
return jsonError('专家不存在');
|
||||
}
|
||||
|
||||
$update = [];
|
||||
if (isset($data['name'])) $update['name'] = trim($data['name']);
|
||||
if (isset($data['email'])) $update['email'] = trim($data['email']);
|
||||
if (isset($data['affiliation'])) $update['affiliation'] = trim($data['affiliation']);
|
||||
if (isset($data['source'])) $update['source'] = trim($data['source']);
|
||||
if (isset($data['state'])) $update['state'] = intval($data['state']);
|
||||
|
||||
if (!empty($update)) {
|
||||
Db::name('expert')->where('expert_id', $expertId)->update($update);
|
||||
}
|
||||
|
||||
if (isset($data['fields'])) {
|
||||
Db::name('expert_field')->where('expert_id', $expertId)->where('state', 0)->update(['state' => 1]);
|
||||
if (!empty($data['fields'])) {
|
||||
$this->saveExpertFields($expertId, $data['fields']);
|
||||
}
|
||||
}
|
||||
|
||||
return jsonSuccess(['expert_id' => $expertId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量修改状态
|
||||
*
|
||||
* 参数:
|
||||
* expert_ids - 逗号分隔的ID列表 "1,2,3"
|
||||
* state - 目标状态 0-5
|
||||
*/
|
||||
public function updateState()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$expertIds = isset($data['expert_ids']) ? $data['expert_ids'] : '';
|
||||
$state = intval(isset($data['state']) ? $data['state'] : -1);
|
||||
|
||||
if (empty($expertIds)) {
|
||||
return jsonError('expert_ids is required');
|
||||
}
|
||||
if ($state < 0 || $state > 5) {
|
||||
return jsonError('state取值范围0-5');
|
||||
}
|
||||
|
||||
$ids = array_map('intval', explode(',', $expertIds));
|
||||
$count = Db::name('expert')->where('expert_id', 'in', $ids)->update(['state' => $state]);
|
||||
|
||||
return jsonSuccess(['updated' => $count]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除专家(软删除,设为黑名单状态5)
|
||||
*
|
||||
* 参数:
|
||||
* expert_ids - 逗号分隔的ID列表
|
||||
* hard - 传1则物理删除
|
||||
*/
|
||||
public function deleteExpert()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$expertIds = isset($data['expert_ids']) ? $data['expert_ids'] : '';
|
||||
$hard = intval(isset($data['hard']) ? $data['hard'] : 0);
|
||||
|
||||
if (empty($expertIds)) {
|
||||
return jsonError('expert_ids is required');
|
||||
}
|
||||
|
||||
$ids = array_map('intval', explode(',', $expertIds));
|
||||
|
||||
if ($hard) {
|
||||
Db::name('expert_field')->where('expert_id', 'in', $ids)->delete();
|
||||
$count = Db::name('expert')->where('expert_id', 'in', $ids)->delete();
|
||||
} else {
|
||||
$count = Db::name('expert')->where('expert_id', 'in', $ids)->update(['state' => 5]);
|
||||
}
|
||||
|
||||
return jsonSuccess(['affected' => $count]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给专家添加领域
|
||||
*/
|
||||
public function addField()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$expertId = intval(isset($data['expert_id']) ? $data['expert_id'] : 0);
|
||||
$majorId = intval(isset($data['major_id']) ? $data['major_id'] : 0);
|
||||
$field = trim(isset($data['field']) ? $data['field'] : '');
|
||||
|
||||
if (!$expertId || $field === '') {
|
||||
return jsonError('expert_id和field不能为空');
|
||||
}
|
||||
|
||||
$exists = Db::name('expert_field')
|
||||
->where('expert_id', $expertId)
|
||||
->where('field', $field)
|
||||
->where('state', 0)
|
||||
->find();
|
||||
if ($exists) {
|
||||
return jsonError('该领域已存在');
|
||||
}
|
||||
|
||||
$id = Db::name('expert_field')->insertGetId([
|
||||
'expert_id' => $expertId,
|
||||
'major_id' => $majorId,
|
||||
'field' => $field,
|
||||
'state' => 0,
|
||||
]);
|
||||
|
||||
return jsonSuccess(['expert_field_id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除领域(软删除)
|
||||
*/
|
||||
public function removeField()
|
||||
{
|
||||
$efId = intval($this->request->param('expert_field_id', 0));
|
||||
if (!$efId) {
|
||||
return jsonError('expert_field_id is required');
|
||||
}
|
||||
|
||||
Db::name('expert_field')->where('expert_field_id', $efId)->update(['state' => 1]);
|
||||
|
||||
return jsonSuccess([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有不重复的领域列表(用于筛选下拉框)
|
||||
*/
|
||||
public function getFieldOptions()
|
||||
{
|
||||
$list = Db::name('expert_field')
|
||||
->where('state', 0)
|
||||
->group('field')
|
||||
->column('field');
|
||||
|
||||
return jsonSuccess($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有来源列表(用于筛选下拉框)
|
||||
*/
|
||||
public function getSourceOptions()
|
||||
{
|
||||
$list = Db::name('expert')
|
||||
->where('source', '<>', '')
|
||||
->group('source')
|
||||
->column('source');
|
||||
|
||||
return jsonSuccess($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出某个领域的专家为Excel
|
||||
*
|
||||
* 参数:
|
||||
* field - 领域关键词(必填)
|
||||
* major_id - 学科ID(可选)
|
||||
* state - 状态筛选(可选,默认不过滤)
|
||||
* keyword - 搜索姓名/邮箱/单位
|
||||
* source - 来源筛选
|
||||
*/
|
||||
public function exportExcel()
|
||||
{
|
||||
$data = $this->request->param();
|
||||
$field = trim(isset($data['field']) ? $data['field'] : '');
|
||||
$majorId = intval(isset($data['major_id']) ? $data['major_id'] : 0);
|
||||
$state = isset($data['state']) ? $data['state'] : '-1';
|
||||
$keyword = trim(isset($data['keyword']) ? $data['keyword'] : '');
|
||||
$source = trim(isset($data['source']) ? $data['source'] : '');
|
||||
|
||||
$query = Db::name('expert')->alias('e');
|
||||
|
||||
if ($field !== '' || $majorId > 0) {
|
||||
$query->join('t_expert_field ef', 'ef.expert_id = e.expert_id AND ef.state = 0', 'inner');
|
||||
if ($field !== '') {
|
||||
$query->where('ef.field', 'like', '%' . $field . '%');
|
||||
}
|
||||
if ($majorId > 0) {
|
||||
$query->where('ef.major_id', $majorId);
|
||||
}
|
||||
$query->group('e.expert_id');
|
||||
}
|
||||
|
||||
if ($state !== '-1' && $state !== '') {
|
||||
$query->where('e.state', intval($state));
|
||||
}
|
||||
if ($keyword !== '') {
|
||||
$query->where('e.name|e.email|e.affiliation', 'like', '%' . $keyword . '%');
|
||||
}
|
||||
if ($source !== '') {
|
||||
$query->where('e.source', $source);
|
||||
}
|
||||
|
||||
$list = $query->field('e.*')->order('e.ctime desc')->select();
|
||||
|
||||
if (empty($list)) {
|
||||
return jsonError('没有符合条件的数据可导出');
|
||||
}
|
||||
|
||||
$expertIds = array_column($list, 'expert_id');
|
||||
$allFields = Db::name('expert_field')
|
||||
->where('expert_id', 'in', $expertIds)
|
||||
->where('state', 0)
|
||||
->select();
|
||||
|
||||
$fieldMap = [];
|
||||
foreach ($allFields as $f) {
|
||||
$fieldMap[$f['expert_id']][] = $f['field'];
|
||||
}
|
||||
|
||||
vendor("PHPExcel.PHPExcel");
|
||||
|
||||
$objPHPExcel = new \PHPExcel();
|
||||
$sheet = $objPHPExcel->getActiveSheet();
|
||||
$sheet->setTitle('Expert List');
|
||||
|
||||
$headers = [
|
||||
'A' => '#',
|
||||
'B' => 'Name',
|
||||
'C' => 'Email',
|
||||
'D' => 'Affiliation',
|
||||
'E' => 'Source',
|
||||
'F' => 'Fields',
|
||||
'G' => 'State',
|
||||
'H' => 'Add Time',
|
||||
'I' => 'Last Promotion',
|
||||
];
|
||||
foreach ($headers as $col => $header) {
|
||||
$sheet->setCellValue($col . '1', $header);
|
||||
}
|
||||
|
||||
$headerStyle = [
|
||||
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
|
||||
'fill' => ['type' => \PHPExcel_Style_Fill::FILL_SOLID, 'startcolor' => ['rgb' => '4472C4']],
|
||||
'alignment' => ['horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_CENTER],
|
||||
];
|
||||
$sheet->getStyle('A1:I1')->applyFromArray($headerStyle);
|
||||
|
||||
foreach ($list as $i => $item) {
|
||||
$row = $i + 2;
|
||||
$fields = isset($fieldMap[$item['expert_id']]) ? implode(', ', $fieldMap[$item['expert_id']]) : '';
|
||||
$stateText = isset($this->stateMap[$item['state']]) ? $this->stateMap[$item['state']] : '未知';
|
||||
|
||||
$sheet->setCellValue('A' . $row, $i + 1);
|
||||
$sheet->setCellValue('B' . $row, $item['name']);
|
||||
$sheet->setCellValueExplicit('C' . $row, $item['email'], \PHPExcel_Cell_DataType::TYPE_STRING);
|
||||
$sheet->setCellValue('D' . $row, $item['affiliation']);
|
||||
$sheet->setCellValue('E' . $row, $item['source']);
|
||||
$sheet->setCellValue('F' . $row, $fields);
|
||||
$sheet->setCellValue('G' . $row, $stateText);
|
||||
$sheet->setCellValue('H' . $row, $item['ctime'] ? date('Y-m-d H:i:s', $item['ctime']) : '');
|
||||
$sheet->setCellValue('I' . $row, $item['ltime'] ? date('Y-m-d H:i:s', $item['ltime']) : '');
|
||||
}
|
||||
|
||||
$sheet->getColumnDimension('A')->setWidth(6);
|
||||
$sheet->getColumnDimension('B')->setWidth(25);
|
||||
$sheet->getColumnDimension('C')->setWidth(35);
|
||||
$sheet->getColumnDimension('D')->setWidth(40);
|
||||
$sheet->getColumnDimension('E')->setWidth(15);
|
||||
$sheet->getColumnDimension('F')->setWidth(50);
|
||||
$sheet->getColumnDimension('G')->setWidth(15);
|
||||
$sheet->getColumnDimension('H')->setWidth(20);
|
||||
$sheet->getColumnDimension('I')->setWidth(20);
|
||||
|
||||
$label = $field !== '' ? preg_replace('/[^a-zA-Z0-9_\x{4e00}-\x{9fa5}]/u', '_', $field) : 'all';
|
||||
$filename = 'expert_' . $label . '_' . date('Ymd_His') . '.xlsx';
|
||||
|
||||
$dir = ROOT_PATH . 'public' . DS . 'exports';
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
|
||||
$filepath = $dir . DS . $filename;
|
||||
$writer = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
|
||||
$writer->save($filepath);
|
||||
|
||||
return jsonSuccess([
|
||||
'file_url' => '/exports/' . $filename,
|
||||
'file_name' => $filename,
|
||||
'count' => count($list),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存专家领域
|
||||
* @param int $expertId
|
||||
* @param array $fields [{"major_id":1,"field":"xxx"}, ...]
|
||||
*/
|
||||
private function saveExpertFields($expertId, $fields)
|
||||
{
|
||||
if (is_string($fields)) {
|
||||
$fields = json_decode($fields, true);
|
||||
}
|
||||
if (!is_array($fields)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($fields as $f) {
|
||||
$majorId = intval(isset($f['major_id']) ? $f['major_id'] : 0);
|
||||
$fieldName = trim(isset($f['field']) ? $f['field'] : '');
|
||||
if ($fieldName === '') continue;
|
||||
|
||||
$exists = Db::name('expert_field')
|
||||
->where('expert_id', $expertId)
|
||||
->where('field', $fieldName)
|
||||
->where('state', 0)
|
||||
->find();
|
||||
if ($exists) continue;
|
||||
|
||||
Db::name('expert_field')->insert([
|
||||
'expert_id' => $expertId,
|
||||
'major_id' => $majorId,
|
||||
'field' => $fieldName,
|
||||
'state' => 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user