作者 魏强

4.4

正在显示 31 个修改的文件 包含 1242 行增加674 行删除
... ... @@ -10,6 +10,9 @@ return [
// | 应用设置
// +----------------------------------------------------------------------
//wechat
'app_id' => 'wx610594b3642770b0',
'app_secret' => '399ab87a53d788e82eec2bc0b02e256e',
// 应用命名空间
'app_namespace' => 'api',
// 应用模式状态
... ...
... ... @@ -12,41 +12,6 @@ use api\home\service\AnswerService;
*/
class IndexController extends RestUserBaseController
{
/**
* @title 首页信息接口
* @description BannerTitle
* @author WeiQiang
* @url /home/index/index
* @method POST
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @return banner:顶部标语@
* @banner title:标语标题 content:标语列表@
* @content name:文字
* @return index_text:优惠券标语信息
* @return tpl:联系电话
*/
public function index()
{
$list = Db::name('banner')
->field('title ,content')
->order('id','DESC')
->select();
$array = [];
foreach ($list as $l){
$arr = explode('/',$l['content']);
$content_array = [];
for($i=0;$i<count($arr);$i++){
$content_array[] = ['name'=>$arr[$i]];
}
array_push($array , ['title'=>$l['title'],'content'=>$content_array]);
}
$PublicConfig = Db::name('public_config')->where('id',1)->find();
$index_text = $PublicConfig['index_text'];
$tpl = $PublicConfig['tpl'];
$this->success("SUCCESS", ['banner'=>$array,'tpl'=>$tpl,'index_text'=>$index_text]);
}
/**
* @title 判断用户是否保存手机接口
... ... @@ -121,12 +86,16 @@ class IndexController extends RestUserBaseController
* @method POST
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @return type:领取成功返回true
* @return type:领取成功返回true,返回40002为已经领取,40001数据库写入错误
* @return coupon_text:成功返回成功消息语
*/
public function couponPost(){
$user_id = $this->getUserId();
$coupon = Db::name('coupon')->where('type',1)->where('delete_time',0)->find();
$user_coupon = Db::name('user_coupon')->where('user_id',$user_id)->where('coupon_id',$coupon['id'])->count();
if($user_coupon > 0){
$this->error(['code'=>40002,'msg'=>'该优惠券一个用户仅限领取一次']);
}
if(Db::name('user_coupon')->insert([
'user_id' => $user_id,
'coupon_id' => $coupon['id'],
... ... @@ -151,11 +120,11 @@ class IndexController extends RestUserBaseController
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @return list:题目列表@
* @list id:题目id title:题目 content:选错提示 type:正确选项1为是2为否
* @list id:题目id title:题目 content:选错提示 type:正确选项1为是0为否 order_id:题目排序
*/
public function qualification(){
$list = Db::name('qualification')
->field('id,title,content,type')
->field('id,title,content,type ,order_id')
->where('delete_time',0)
->order('order_id')
->select();
... ... @@ -187,8 +156,8 @@ class IndexController extends RestUserBaseController
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @return list:题目列表@
* @list id:题目id title:题目 hint_type:是否有答题提示1为有0为没有 hint_title:答题提示标题 hint_content:答题提示内容 question:选项列表@
* @question id:选项列表 title:选项内容
* @list id:题目id title:题目 hint_type:是否有答题提示1为有0为没有 hint_text:答题提示标注 hint_title:答题提示标题 hint_content:答题提示内容 question:选项列表@ order_id:问题排序
* @question id:选项列表 title:选项内容 order_id:选项排序
*/
public function question(){
$list = Db::name('question')->where('delete_time',0)->where('parent_id',0)->order('order_id')->select();
... ... @@ -200,8 +169,10 @@ class IndexController extends RestUserBaseController
$arr['hint_type'] = $l['hint_type'];
$arr['hint_title'] = $l['hint_title'];
$arr['hint_content'] = $l['hint_content'];
$arr['hint_text'] = $l['hint_text'];
$arr['order_id'] = $l['order_id'];
$question = Db::name('question')
->field('id ,title')
->field('id ,title ,order_id')
->where('delete_time',0)
->where('parent_id',$l['id'])
->order('order_id')
... ... @@ -221,15 +192,24 @@ class IndexController extends RestUserBaseController
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @param name:questionStr type:string require:1 other:问题id-选项id,问题id-选项id desc:答题结果字符串
* @return fen:分数区间 content:分数评价 type:是否显示评星1为显示 start:评星数量@ question:题目单独评价列表@
* @start num:评星数量 title:解释文字 type:1为知识产权2为科技成果转化情况3为研发组织管理水平4为财务增长情况
* @return fen:分数区间
* @return content:分数评价
* @return type:是否显示评星1为显示
* @return start:评星数量@
* @return question:题目单独评价列表@
* @start text:类型内容 num:评星数量 title:解释文字 type:1为知识产权2为科技成果转化情况3为研发组织管理水平4为财务增长情况
* @question title:题目编号 content:单独评价题目内容
* @return all_fen:总分
*/
public function questionPost(){
$question_str = input('questionStr');
//结果采集
$Answer = new AnswerService();
$array = $Answer->answer($question_str);
if($array == false){
$this->error(['code'=>40001,'msg'=>'请完成所有题目']);
}
//保存结果
$user_id = $this->getUserId();
$user_answer = Db::name('user_answer')->where('user_id',$user_id)->find();
... ... @@ -271,9 +251,15 @@ class IndexController extends RestUserBaseController
* @method POST
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
* @return answer:有结果返回true无结果返回false fen:分数区间 content:分数评价 type:是否显示评星1为显示 start:评星数量@ question:题目单独评价列表@
* @start num:评星数量 title:解释文字 type:1为知识产权2为科技成果转化情况3为研发组织管理水平4为财务增长情况
* @return answer:有结果返回true无结果返回false
* @return fen:分数区间
* @return content:分数评价
* @return type:是否显示评星1为显示
* @return start:评星数量@
* @return question:题目单独评价列表@
* @start text:类型内容 num:评星数量 title:解释文字 type:1为知识产权2为科技成果转化情况3为研发组织管理水平4为财务增长情况
* @question title:题目编号 content:单独评价题目内容
* @return all_fen:总分
*/
public function MyAnswer(){
$user_id = $this->getUserId();
... ... @@ -296,10 +282,12 @@ class IndexController extends RestUserBaseController
* @method POST
* @header name:XX-Token require:1 default: desc:token
* @header name:XX-Device-Type require:1 default:wxapp desc:固定参数
*@param name:type type:int require:1 other:0为未使用,1为已使用,2为已过期 desc:优惠券类型
* @return list:优惠券列表@
* @list title:优惠券名称 start_time:开始时间 end_time:结束时间 money:金额 content:简介 status:优惠券状态0待使用1已使用2已过期
* @list title:优惠券名称 start_time:开始时间 end_time:结束时间 money:金额 content:简介 type:优惠券状态0待使用1已使用2已过期
*/
public function MyCoupon(){
$type = input('type');
$user_id = $this->getUserId();
$list = Db::name('user_coupon')
->alias('uc')
... ... @@ -317,7 +305,13 @@ class IndexController extends RestUserBaseController
$item['end_time'] = date('Y-m-d',$item['end_time']);
return $item;
});
$this->success('SUCCESS',$list);
$this_list = [];
foreach ($list as $l){
if($l['type'] == $type){
$this_list[] = $l;
}
}
$this->success('SUCCESS',$this_list);
}
/**
... ...
... ... @@ -10,6 +10,7 @@ use Think\Db;
class AnswerService
{
public function answer($str){
$str = trim(trim(htmlspecialchars_decode($str),'['),']');
$arr_str = explode(',',$str);
$question = [];
$start = [];
... ... @@ -18,7 +19,13 @@ class AnswerService
$score_2 = 0; //11
$score_3 = 0; //12-13
$score_4 = 0; //14-15
$question_title_count = Db::name('question')->where('delete_time',0)->where('parent_id',0)->count();
$question_this_count = count($arr_str);
if($question_this_count != $question_title_count){
return false;
}
for($i=0;$i<count($arr_str);$i++){
$arr_str[$i] = trim($arr_str[$i],'"');
$arr_q = explode('-',$arr_str[$i]);
if(!empty($arr_q[0]) && !empty($arr_q[1])){
//题目
... ... @@ -29,8 +36,8 @@ class AnswerService
$all_score +=$question_choose;
//查看题目是否需要单独评分
if($question_title['type'] == 1){
if(intval($question_title['min']) <= $question_choose && $question_choose <= intval($question_title['max'])){
array_push($question,['name'=>'第'.$question_title['order_id'].'题','content'=>$question_title['content']]);
if(intval($question_title['min']) <= $question_choose && $question_choose < intval($question_title['max'])){
array_push($question,['name'=>'','content'=>$question_title['content']]);
}
}
//评星分数
... ... @@ -54,50 +61,57 @@ class AnswerService
//分数归类
$answer = Db::name('answer')->where('delete_time',0)->select();
$fen = [];
$content = 0;
$content = '';
foreach ($answer as $an){
if(intval($an['min']) < $all_score && intval($an['max']) > $all_score ) {
if(intval($an['min']) <= $all_score && intval($an['max']) >= $all_score ) {
$fen = ['min'=>$an['min'] , 'max'=>$an['max']];
$content = $an['content'];
}
}
//评星
$type = 0;
if($all_score < 71){
//if($all_score < 71){
$type = 1;
if($score_1 < 18){
array_push($start,['num'=>1,'title'=>'知识产权情况较差','type'=>1]);
array_push($start,['text'=>'知识产权情况','num'=>1,'title'=>'知识产权情况较差','type'=>1]);
} elseif ($score_1 >= 18 && $score_1 < 21){
array_push($start,['num'=>2,'title'=>'知识产权情况差','type'=>1]);
array_push($start,['text'=>'知识产权情况','num'=>2,'title'=>'知识产权情况差','type'=>1]);
} elseif ($score_1 >= 21 && $score_1 < 24){
array_push($start,['num'=>3,'title'=>'知识产权情况一般','type'=>1]);
array_push($start,['text'=>'知识产权情况','num'=>3,'title'=>'知识产权情况一般','type'=>1]);
} elseif ($score_1 >= 24){
array_push($start,['num'=>4,'title'=>'知识产权情况优秀','type'=>1]);
array_push($start,['text'=>'知识产权情况','num'=>4,'title'=>'知识产权情况优秀','type'=>1]);
}
if($score_2 == 28){
if($score_2 == 28 || $score_2==27){
array_push($start,['text'=>'科技成果转化','num'=>4,'title'=>'科技成果转化优秀','type'=>2]);
} elseif ($score_2 == 22 || $score_2 == 16){
array_push($start,['text'=>'科技成果转化','num'=>3,'title'=>'科技成果转化一般','type'=>2]);
} elseif($score_2 == 10){
array_push($start,['text'=>'科技成果转化','num'=>2,'title'=>'科技成果转化较差','type'=>2]);
} elseif ($score_2 == 3 || $score_2 == 0){
array_push($start,['text'=>'科技成果转化','num'=>1,'title'=>'科技成果转化差','type'=>2]);
}
if($score_3 == 18){
array_push($start,['num'=>4,'title'=>'企业研发组织管理水平较好','type'=>3]);
array_push($start,['text'=>'企业研发组织管理水平','num'=>4,'title'=>'企业研发组织管理水平较好','type'=>3]);
} elseif ($score_3 == 15){
array_push($start,['num'=>3,'title'=>'企业研发组织管理水平好','type'=>3]);
array_push($start,['text'=>'企业研发组织管理水平','num'=>3,'title'=>'企业研发组织管理水平好','type'=>3]);
} elseif ( $score_3 == 3){
array_push($start,['num'=>2,'title'=>'企业研发组织管理水平差','type'=>3]);
array_push($start,['text'=>'企业研发组织管理水平','num'=>2,'title'=>'企业研发组织管理水平差','type'=>3]);
} elseif ($score_3 == 0){
array_push($start,['num'=>1,'title'=>'企业研发组织管理水平较差','type'=>3]);
array_push($start,['text'=>'企业研发组织管理水平','num'=>1,'title'=>'企业研发组织管理水平较差','type'=>3]);
}
if($score_4 >= 10){
array_push($start,['num'=>4,'title'=>'财务增长情况:优秀','type'=>4]);
array_push($start,['text'=>'财务增长情况','num'=>4,'title'=>'财务增长情况:优秀','type'=>4]);
} elseif ($score_4 <10 && $score_4 >=7) {
array_push($start,['num'=>3,'title'=>'财务增长情况:良好','type'=>4]);
array_push($start,['text'=>'财务增长情况','num'=>3,'title'=>'财务增长情况:良好','type'=>4]);
} elseif ($score_4 < 7 && $score_4 >= 5){
array_push($start,['num'=>2,'title'=>'财务增长情况:一般','type'=>4]);
array_push($start,['text'=>'财务增长情况','num'=>2,'title'=>'财务增长情况:一般','type'=>4]);
} elseif ($score_4 <5){
array_push($start,['num'=>1,'title'=>'财务增长情况:差','type'=>4]);
array_push($start,['text'=>'财务增长情况','num'=>1,'title'=>'财务增长情况:差','type'=>4]);
}
}
//}
return ['fen'=>$fen,'content'=>$content,'type'=>$type,'start'=>$start,'question'=>$question];
return ['fen'=>$fen,'content'=>$content,'type'=>$type,'start'=>$start,'question'=>$question,'all_fen'=>$all_score];
}
}
... ...
... ... @@ -18,6 +18,41 @@ use think\Validate;
*/
class PublicController extends RestBaseController
{
/**
* @title 首页信息接口
* @description BannerTitle
* @author WeiQiang
* @url /wxapp/public/index
* @method POST
* @return banner:顶部标语@
* @banner title:标语标题 content:标语列表@
* @content name:文字
* @return index_text:优惠券标语信息
* @return tpl:联系电话
*/
public function index()
{
$list = Db::name('banner')
->field('title ,content')
->order('id')
->select();
$array = [];
foreach ($list as $l){
$arr = explode('/',$l['content']);
$content_array = [];
for($i=0;$i<count($arr);$i++){
$content_array[] = ['name'=>$arr[$i]];
}
array_push($array , ['title'=>$l['title'],'content'=>$content_array]);
}
$PublicConfig = Db::name('public_config')->where('id',1)->find();
$index_text = $PublicConfig['index_text'];
$tpl = $PublicConfig['tpl'];
$this->success("SUCCESS", ['banner'=>$array,'tpl'=>$tpl,'index_text'=>$index_text]);
}
/**
* @title 获取sessionKey和openid
* @description 小程序登录注册
... ... @@ -51,6 +86,7 @@ class PublicController extends RestBaseController
$response = cmf_curl_get("https://api.weixin.qq.com/sns/jscode2session?appid=$appId&secret=$appSecret&js_code=$code&grant_type=authorization_code");
$response = json_decode($response, true);
if (!empty($response['errcode'])) {
$this->error(['code'=>'41001','msg'=>'操作失败:'.$response['errcode']]);
}
... ... @@ -133,7 +169,7 @@ class PublicController extends RestBaseController
->where('openid', $openid)
->where('app_id', $appId)
->update($userData);
$user_id = $this->getUserId();
$user_id = $findThirdPartyUser['user_id'];
Db::name("user")
->where('id',$user_id)
->update([
... ...
... ... @@ -177,8 +177,11 @@ class CouponController extends AdminBaseController
{
$rquest = $this->request->param();
$where = [];
if(!empty($rquest['nickname'])){
$where['u.user_nickname'] = ['like',"%$rquest[nickname]%"];
}
if(!empty($rquest['mobile'])){
$where['u.mobile'] = $rquest['mobile'];
$where['u.mobile'] = ['like',"%$rquest[mobile]%"];
}
$Coupon = new CouponModel();
$list = $Coupon->CouponUser($where,$rquest);
... ...
<?php
// +----------------------------------------------------------------------
// | 答题结果标星模块
// +----------------------------------------------------------------------
// | Author: 魏强
// +----------------------------------------------------------------------
namespace app\admin\controller;
use cmf\controller\AdminBaseController;
use think\Db;
/**
* Class StartController
* @package app\admin\controller
* @adminMenuRoot(
* 'name' => '标星规则',
* 'action' => 'index',
* 'parent' => '',
* 'display'=> true,
* 'order' => 100,
* 'icon' => 'star',
* 'remark' => '标星规则'
* )
*/
class StartController extends AdminBaseController
{
public function index()
{
return $this->fetch();
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | 用户答题结果模块
// +----------------------------------------------------------------------
// | Author: 魏强
// +----------------------------------------------------------------------
namespace app\admin\controller;
use cmf\controller\AdminBaseController;
use think\Db;
use func\func;
/**
* Class UserAnswerController
* @package app\admin\controller
* @adminMenuRoot(
* 'name' => '用户答题列表',
* 'action' => 'index',
* 'parent' => '',
* 'display'=> true,
* 'order' => 100,
* 'icon' => 'pencil',
* 'remark' => '用户答题列表'
* )
*/
class UserAnswerController extends AdminBaseController
{
public function index()
{
$request = $this->request->param();
$where = [];
if(!empty($request['mobile'])) {
$where['u.mobile'] = ['like', "%$request[mobile]%"];
}
!empty($request['start_time']) ? $start_time = $request['start_time'] : $start_time = 0;
!empty($request['end_time']) ? $end_time = $request['end_time'] : $end_time = time();
$list = Db::name('user_answer')
->alias('ua')
->field('ua.* ,u.user_nickname ,u.mobile')
->join('user u','ua.user_id = u.id')
->where($where)
->whereTime('ua.create_time','between',[$start_time,$end_time])
->order('ua.create_time','DESC')
->paginate(2,false,['query'=>$request])
->each(function ($item){
//用户当前优惠券情况
$user_coupon = Db::name('user_coupon')
->alias('uc')
->field('c.title ,uc.type')
->join('coupon c','uc.coupon_id = c.id')
->where('uc.user_id',$item['user_id'])
->where('uc.delete_time',0)
->select();
count($user_coupon) != 0 ? $item['user_coupon_text'] = '' : $item['user_coupon_text'] = '无优惠券';
foreach($user_coupon as $uc){
$uc['type'] == 0 ? $user_coupon_type_text = '未使用' : $user_coupon_type_text = '已使用';
$item['user_coupon_text'] .= $uc['title']."($user_coupon_type_text) ";
}
//获取题目信息
$str = trim(trim(htmlspecialchars_decode($item['str']),'['),']');
$arr_str = explode(',',$str);
$item['question_text'] = [];
$all_score = 0;
//循环查询每道题目的内容
for($i=0;$i<count($arr_str);$i++) {
$arr_str[$i] = trim($arr_str[$i], '"');
$arr_q = explode('-', $arr_str[$i]);
if (!empty($arr_q[0]) && !empty($arr_q[1])) {
//题目
$question_title = Db::name('question')->where('id', $arr_q[0])->find();
//选项
$question_choose = Db::name('question')->where('id', $arr_q[1])->find();
$all_score +=$question_choose['score'];
$item['question_text'][] = [
'order'=>$question_title['order_id'],
'title'=>$question_choose['title'],
'score'=>$question_choose['score']
];
}
}
$item['all_score'] = $all_score;
return $item;
});
$this->assign('page',$list->render());
$this->assign('list', $list);
return $this->fetch();
}
/**
* 导出答题结果
* @adminMenu(
* 'name' => '导出答题结果',
* 'parent' => 'index',
* 'display'=> false,
* 'hasView'=> false,
* 'order' => 1000,
* 'icon' => '',
* 'remark' => '导出答题结果',
* 'param' => ''
* )
*/
public function Exl(){
$request = $this->request->param();
$where = [];
if(!empty($request['mobile'])) {
$where['u.mobile'] = ['like', "%$request[mobile]%"];
}
!empty($request['start_time']) ? $start_time = $request['start_time'] : $start_time = 0;
!empty($request['end_time']) ? $end_time = $request['end_time'] : $end_time = time();
$list = Db::name('user_answer')
->alias('ua')
->field('ua.* ,u.user_nickname ,u.mobile')
->join('user u','ua.user_id = u.id')
->where($where)
->whereTime('ua.create_time','between',[$start_time,$end_time])
->order('u.create_time','DESC')
->select()
->each(function ($item){
//用户当前优惠券情况
$user_coupon = Db::name('user_coupon')
->alias('uc')
->field('c.title ,uc.type')
->join('coupon c','uc.coupon_id = c.id')
->where('uc.user_id',$item['user_id'])
->where('uc.delete_time',0)
->select();
count($user_coupon) != 0 ? $item['user_coupon_text'] = '' : $item['user_coupon_text'] = '无优惠券';
foreach($user_coupon as $uc){
$uc['type'] == 0 ? $user_coupon_type_text = '未使用' : $user_coupon_type_text = '已使用';
$item['user_coupon_text'] .= $uc['title']."($user_coupon_type_text) ";
}
//获取题目信息
$str = trim(trim(htmlspecialchars_decode($item['str']),'['),']');
$arr_str = explode(',',$str);
$item['question_text'] = [];
$all_score = 0;
for($i=0;$i<count($arr_str);$i++) {
$arr_str[$i] = trim($arr_str[$i], '"');
$arr_q = explode('-', $arr_str[$i]);
if (!empty($arr_q[0]) && !empty($arr_q[1])) {
//题目
$question_title = Db::name('question')->where('id', $arr_q[0])->find();
//选项
$question_choose = Db::name('question')->where('id', $arr_q[1])->find();
$all_score +=$question_choose['score'];
$item['question_text'][] = [
'order'=>$question_title['order_id'],
'title'=>$question_choose['title'],
'score'=>$question_choose['score']
];
}
}
$item['all_score'] = $all_score;
return $item;
});
$exl = new func();
$exl_title = ['用户昵称','用户电话','题目编号','用户答案','答题分数','答题总分数','当前优惠券信息','答题时间'];
$exl_dis = [];
foreach ($list as $li){
foreach ($li['question_text'] as $qt){
$exl_dis[] = [
$exl->filterEmoji($li['user_nickname']),
$li['mobile'],
$qt['order'],
$qt['title'],
$qt['score'],
$li['all_score'],
$li['user_coupon_text'],
date('Y-m-d H:i',$li['create_time'])
];
}
}
$exl->exportExcel($exl_title, $exl_dis, '用户答题列表', './', true);
}
}
\ No newline at end of file
... ...
... ... @@ -26,6 +26,8 @@ class QuestionValidate extends Validate
}
else if(empty($post['hint_content'])){
return '提示信息内容不能为空';
} elseif(empty($post['hint_text'])){
return '提示标注不能为空';
} else {
return true;
}
... ...
... ... @@ -74,6 +74,8 @@ return array (
'ADMIN_PUBLICCONFIG_PUBLICCONFIG' => '平台基本信息',
'ADMIN_PUBLICCONFIG_PUBLICCONFIGPOST' => '平台基本信息提交',
'ADMIN_QUESTION_DEFAULT' => '题目管理',
'ADMIN_QUESTION_IMAGES' => '问题背景图',
'ADMIN_QUESTION_IMAGESPOST' => '问题背景图提交',
'ADMIN_QUESTION_LISTORDER' => '评分题目排序',
'ADMIN_QUESTION_QUALIFICATION' => '资格题目',
'ADMIN_QUESTION_QUALIFICATIONADD' => '添加资格题目',
... ... @@ -147,6 +149,8 @@ return array (
'ADMIN_THEME_SETTINGPOST' => '模板文件编辑提交保存',
'ADMIN_THEME_UNINSTALL' => '卸载模板',
'ADMIN_THEME_UPDATE' => '模板更新',
'ADMIN_TICKLING_DELETE' => '删除反馈意见',
'ADMIN_TICKLING_INDEX' => '意见反馈列表',
'ADMIN_USER_ADD' => '管理员添加',
'ADMIN_USER_ADDPOST' => '管理员添加提交',
'ADMIN_USER_BAN' => '停用管理员',
... ...
... ... @@ -10,7 +10,7 @@
// [ 入口文件 ]
// 调试模式开关
define("APP_DEBUG", true);
define("APP_DEBUG", false);
// 定义CMF根目录,可更改此目录
define('CMF_ROOT', __DIR__ . '/../');
... ...
... ... @@ -6,6 +6,8 @@
<li class="active"><a href="#">用户优惠券列表</a></li>
</ul>
<form class="well form-inline margin-top-20" method="post" action="{:url('Coupon/user')}">
用户昵称:
<input type="text" class="form-control" name="nickname" style="width: 180px;" value="{:input('request.nickname/s','')}" placeholder="请输入用户昵称">
用户电话:
<input type="number" class="form-control" name="mobile" style="width: 180px;" value="{:input('request.mobile/s','')}" placeholder="请输入用户电话">
<input type="submit" class="btn btn-primary" value="搜索"/>
... ...
... ... @@ -8,9 +8,9 @@
</ul>
<form method="post" class="form-horizontal js-ajax-form margin-top-20" action="{:url('PublicConfig/bannerAddPost')}">
<div id="fen1" class="form-group">
<label class="col-sm-2 control-label"><span class="form-required">*</span>标题</label>
<label class="col-sm-2 control-label">标题</label>
<div class="col-md-6 col-sm-10">
<input type="text" class="form-control" name="title" required>
<input type="text" class="form-control" name="title" >
</div>
</div>
<div class="form-group">
... ...
... ... @@ -9,9 +9,9 @@
<form method="post" class="form-horizontal js-ajax-form margin-top-20" action="{:url('PublicConfig/bannerEditPost')}">
<input type="hidden" name="id" value="{$edit.id}">
<div id="fen1" class="form-group">
<label class="col-sm-2 control-label"><span class="form-required">*</span>标题</label>
<label class="col-sm-2 control-label">标题</label>
<div class="col-md-6 col-sm-10">
<input type="text" class="form-control" name="title" required value="{$edit.title}">
<input type="text" class="form-control" name="title" value="{$edit.title}">
</div>
</div>
<div class="form-group">
... ...
... ... @@ -43,6 +43,12 @@
</td>
</tr>
<tr>
<th width="100">客服电话<span class="form-required">*</span></th>
<td>
<input type="text" class="form-control" required name="mobile" value="{$mobile|default=''}">
</td>
</tr>
<tr>
<th width="100">客服QQ<span class="form-required">*</span></th>
<td>
<input type="text" class="form-control" required name="qq" value="{$qq|default=''}">
... ... @@ -99,7 +105,7 @@
</table>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary js-ajax-submit">{:lang('ADD')}</button>
<button type="submit" class="btn btn-primary js-ajax-submit">保存</button>
</div>
</div>
</div>
... ...
... ... @@ -14,8 +14,8 @@
<th width="50">ID</th>
<th>题目内容</th>
<th>选错提示信息</th>
<th>排序</th>
<th>正确选项</th>
<th width="50">题号</th>
<th width="80">正确选项</th>
<th width="130">{:lang('ACTIONS')}</th>
</tr>
</thead>
... ...
... ... @@ -27,7 +27,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><span class="form-required">*</span>排序</label>
<label class="col-sm-2 control-label"><span class="form-required">*</span>题号</label>
<div class="col-md-6 col-sm-10">
<input type="number" class="form-control" id="order_id" name="order_id" placeholder="由小到大排序">
</div>
... ...
... ... @@ -28,7 +28,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><span class="form-required">*</span>排序</label>
<label class="col-sm-2 control-label"><span class="form-required">*</span>题号</label>
<div class="col-md-6 col-sm-10">
<input type="number" class="form-control" id="order_id" name="order_id" value="{$edit.order_id}" placeholder="由小到大排序">
</div>
... ...
... ... @@ -52,6 +52,12 @@
<input type="radio" name="hint_type" value="1">有提示信息
</div>
</div>
<div id="ti3" class="form-group hidden">
<label class="col-sm-2 control-label"><span class="form-required">*</span>提示信息标题</label>
<div class="col-md-6 col-sm-10">
<input type="text" class="form-control" name="hint_text">
</div>
</div>
<div id="ti1" class="form-group hidden">
<label class="col-sm-2 control-label"><span class="form-required">*</span>提示信息标题</label>
<div class="col-md-6 col-sm-10">
... ... @@ -102,6 +108,7 @@
$('#ti').attr('class','form-group hidden');
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
}
//动态改变页面信息
$('#parent_id').on('change',function () {
... ... @@ -123,6 +130,7 @@
$('#ti').attr('class','form-group hidden');
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
$('input[type=radio]').removeAttr('checked');
$('#thishint').prop('checked',true);
$('#thistype').prop('checked',true);
... ... @@ -149,9 +157,11 @@
if(ti == 0){
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
} else {
$('#ti1').attr('class','form-group');
$('#ti2').attr('class','form-group');
$('#ti3').attr('class','form-group');
}
})
... ...
... ... @@ -53,6 +53,12 @@
<input type="radio" name="hint_type" value="1" <eq name="$edit.hint_type" value="1">checked</eq> >有提示信息
</div>
</div>
<div id="ti3" class="form-group <eq name="$edit.hint_type" value="0">hidden</eq> ">
<label class="col-sm-2 control-label"><span class="form-required">*</span>提示信息标注</label>
<div class="col-md-6 col-sm-10">
<input type="text" class="form-control" name="hint_text" value="{$edit.hint_text}">
</div>
</div>
<div id="ti1" class="form-group <eq name="$edit.hint_type" value="0">hidden</eq> ">
<label class="col-sm-2 control-label"><span class="form-required">*</span>提示信息标题</label>
<div class="col-md-6 col-sm-10">
... ... @@ -103,6 +109,7 @@
$('#ti').attr('class','form-group hidden');
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
}
//动态改变页面信息
$('#parent_id').on('change',function () {
... ... @@ -124,6 +131,7 @@
$('#ti').attr('class','form-group hidden');
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
$('input[type=radio]').removeAttr('checked');
$('#thishint').prop('checked',true);
$('#thistype').prop('checked',true);
... ... @@ -150,9 +158,11 @@
if(ti == 0){
$('#ti1').attr('class','form-group hidden');
$('#ti2').attr('class','form-group hidden');
$('#ti3').attr('class','form-group hidden');
} else {
$('#ti1').attr('class','form-group');
$('#ti2').attr('class','form-group');
$('#ti3').attr('class','form-group');
}
})
... ...
<include file="public@header" />
</head>
<body>
<div class="wrap js-check-wrap">
<ul class="nav nav-tabs">
<li class="active"><a href="#">标星规则</a></li>
</ul>
<!--<form class="well form-inline margin-top-20" method="post" action="{:url('User/index')}">-->
<!--</form>-->
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>标星分类</th>
<th>包含题目</th>
<th>分数区间</th>
<th>标星数量</th>
<th>提示内容</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="4">知识产权情况</td>
<td rowspan="4">第八题、第九题、第十题</td>
<td>大于等于24分</td>
<td>4星</td>
<td>知识产权情况优秀</td>
</tr>
<tr>
<td>小于24分并且大于等于21分</td>
<td>3星</td>
<td>知识产权情况一般</td>
</tr>
<tr>
<td>小于21分并且大于等于18分</td>
<td>2星</td>
<td>知识产权情况差</td>
</tr>
<tr>
<td>小于18分</td>
<td>1星</td>
<td>知识产权情况较差</td>
</tr>
<tr>
<td rowspan="4">科技成果转化</td>
<td rowspan="4">第十一题</td>
<td>等于28分或者等于27分</td>
<td>4星</td>
<td>科技成果转化优秀</td>
</tr>
<tr>
<td>等于22分或者等于16分</td>
<td>3星</td>
<td>科技成果转化一般</td>
</tr>
<tr>
<td>等于10分</td>
<td>2星</td>
<td>科技成果转化较差</td>
</tr>
<tr>
<td>等于3分或者等于0分</td>
<td>1星</td>
<td>科技成果转化差</td>
</tr>
<tr>
<td rowspan="4">企业研发组织管理水平</td>
<td rowspan="4">第十二题、第十三题</td>
<td>等于18分</td>
<td>4星</td>
<td>企业研发组织管理水平较好</td>
</tr>
<tr>
<td>等于15分</td>
<td>3星</td>
<td>企业研发组织管理水平好</td>
</tr>
<tr>
<td>等于3分</td>
<td>2星</td>
<td>企业研发组织管理水平差</td>
</tr>
<tr>
<td>等于0分</td>
<td>1星</td>
<td>企业研发组织管理水平较差</td>
</tr>
<tr>
<td rowspan="4">财务增长情况</td>
<td rowspan="4">第十四题、第十五题</td>
<td>大于等于10分</td>
<td>4星</td>
<td>财务增长情况:优秀</td>
</tr>
<tr>
<td>小于10分并且大于等于7分</td>
<td>3星</td>
<td>财务增长情况:良好</td>
</tr>
<tr>
<td>小于7分并且大于等于5分</td>
<td>2星</td>
<td>财务增长情况:一般</td>
</tr>
<tr>
<td>小于5分</td>
<td>1星</td>
<td>财务增长情况:差</td>
</tr>
</tbody>
</table>
</div>
<script src="__STATIC__/js/admin.js"></script>
</body>
</html>
\ No newline at end of file
... ...
... ... @@ -11,10 +11,10 @@
<thead>
<tr>
<th width="50">ID</th>
<th>用户昵称</th>
<th width="150">用户昵称</th>
<th>用户手机</th>
<th>留言内容</th>
<th>留言时间</th>
<th width="120">留言时间</th>
<th width="50">{:lang('ACTIONS')}</th>
</tr>
</thead>
... ... @@ -25,7 +25,7 @@
<td>{$vo.user_nickname}</td>
<td>{$vo.mobile}</td>
<td>{$vo.content}</td>
<td>{:date('Y-m-d',$vo.create_time)}</td>
<td>{:date('Y-m-d H:i',$vo.create_time)}</td>
<td>
<a class="js-ajax-delete" href="{:url('Tickling/delete',array('id'=>$vo['id']))}">{:lang('DELETE')}</a>
</td>
... ...
<include file="public@header" />
</head>
<body>
<div class="wrap js-check-wrap">
<ul class="nav nav-tabs">
<li class="active"><a href="###">用户答题列表</a></li>
</ul>
<form class="well form-inline margin-top-20" method="post" action="{:url('UserAnswer/index')}">
用户电话:
<input type="text" class="form-control" name="mobile" style="width: 140px;" value="{:input('mobile','')}" placeholder="请输入用户电话">
时间:
<input type="text" class="form-control js-bootstrap-datetime" name="start_time"
value="{:input('start_time','')}"
style="width: 140px;" autocomplete="off">-
<input type="text" class="form-control js-bootstrap-datetime" name="end_time"
value="{:input('end_time','')}"
style="width: 140px;" autocomplete="off"> &nbsp; &nbsp;
<input type="submit" class="btn btn-primary" value="搜索" />
<a class="btn btn-danger" href="{:url('UserAnswer/index')}">清空</a>
<a class="btn btn-primary" href="###" onclick="openexl()">导出</a>
</form>
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>用户昵称</th>
<th>用户电话</th>
<th>题目编号</th>
<th>用户答案</th>
<th>答题分数</th>
<th>答题总分数</th>
<th>当前优惠券信息</th>
<th>答题时间</th>
</tr>
</thead>
<tbody>
<foreach name="list" item="vo">
<foreach name="vo.question_text" item="qt">
<tr>
<td>{$vo.user_nickname}</td>
<td>{$vo.mobile}</td>
<td>{$qt.order}</td>
<td>{$qt.title}</td>
<td>{$qt.score}</td>
<td>{$vo.all_score}</td>
<td>{$vo.user_coupon_text}</td>
<td>{:date('Y-m-d H:i',$vo.create_time)}</td>
</tr>
</foreach>
</foreach>
</tbody>
</table>
<div class="pagination">{$page}</div>
</div>
<script src="__STATIC__/js/admin.js"></script>
<script>
function openexl() {
var mobile = $('input[name=mobile]').val();
var start_time = $('input[name=start_time]').val();
var end_time = $('input[name=end_time]').val();
window.location.href="{:url('UserAnswer/Exl')}?mobile="+mobile+"&start_time="+start_time+"&end_time="+end_time;
}
</script>
</body>
</html>
\ No newline at end of file
... ...
<?php
namespace func;
class func
{
/**
* 数据导出
* @param array $title 标题行名称
* @param array $data 导出数据
* @param string $fileName 文件名
* @param string $savePath 保存路径
* @param $type 是否下载 false--保存 true--下载
* @return string 返回文件全路径
* @throws PHPExcel_Exception
* @throws PHPExcel_Reader_Exception
* exportExcel(array('姓名','年龄'), array(array('a',21),array('b',23)), '档案', './', true);
*/
function exportExcel($title = array(), $data = array(), $fileName = '', $savePath = './', $isDown = false)
{
vendor('phpoffice.phpexcel.Classes.PHPExcel');
$obj = new \PHPExcel();
$objWrite = new \PHPExcel_Writer_Excel2007($obj);
$objWrite = new \PHPExcel_Writer_Excel5($obj);
//横向单元格标识
$cellName = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ');
$obj->getActiveSheet(0)->setTitle('sheet名称'); //设置sheet名称
$_row = 1; //设置纵向单元格标识
if ($title) {
$_cnt = count($title);
$obj->getActiveSheet(0)->mergeCells('A' . $_row . ':' . $cellName[$_cnt - 1] . $_row); //合并单元格
$obj->setActiveSheetIndex(0)->setCellValue('A' . $_row, '数据导出:' . date('Y-m-d H:i:s')); //设置合并后的单元格内容
$_row++;
$i = 0;
foreach ($title AS $v) { //设置列标题
$obj->setActiveSheetIndex(0)->setCellValue($cellName[$i] . $_row, $v);
$i++;
}
$_row++;
}
//填写数据
if ($data) {
$i = 0;
foreach ($data AS $_v) {
$j = 0;
foreach ($_v AS $_cell) {
$obj->getActiveSheet(0)->setCellValue($cellName[$j] . ($i + $_row), $_cell);
$j++;
}
$i++;
}
}
//文件名处理
if (!$fileName) {
$fileName = uniqid(time(), true);
}
//$objWrite = PHPExcel_IOFactory::createWriter($obj, 'Excel2007');
if ($isDown) { //网页下载
header('pragma:public');
header("Content-Disposition:attachment;filename=$fileName.xls");
$objWrite->save('php://output');
exit;
}
$_fileName = iconv("utf-8", "gb2312", $fileName); //转码
$_savePath = $savePath . $_fileName . '.xlsx';
$objWrite->save($_savePath);
return $savePath . $fileName . '.xlsx';
}
//协助数据导出,过滤特殊字符
public function filterEmoji($emojiStr){
$emojiStr = preg_replace_callback('/./u',function(array $match){
return strlen($match[0]) >= 4 ? '' : $match[0];
},$emojiStr);
return $emojiStr;
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\RouteNotFoundException;
/**
* App 应用管理
* @author liu21st <liu21st@gmail.com>
*/
class App
{
/**
* @var bool 是否初始化过
*/
protected static $init = false;
/**
* @var string 当前模块路径
*/
public static $modulePath;
/**
* @var bool 应用调试模式
*/
public static $debug = true;
/**
* @var string 应用类库命名空间
*/
public static $namespace = 'app';
/**
* @var bool 应用类库后缀
*/
public static $suffix = false;
/**
* @var bool 应用路由检测
*/
protected static $routeCheck;
/**
* @var bool 严格路由检测
*/
protected static $routeMust;
protected static $dispatch;
protected static $file = [];
/**
* 执行应用程序
* @access public
* @param Request $request Request对象
* @return Response
* @throws Exception
*/
public static function run(Request $request = null)
{
is_null($request) && $request = Request::instance();
try {
$config = self::initCommon();
if (defined('BIND_MODULE')) {
// 模块/控制器绑定
BIND_MODULE && Route::bind(BIND_MODULE);
} elseif ($config['auto_bind_module']) {
// 入口自动绑定
$name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
Route::bind($name);
}
}
$request->filter($config['default_filter']);
// 默认语言
Lang::range($config['default_lang']);
if ($config['lang_switch_on']) {
// 开启多语言机制 检测当前语言
Lang::detect();
}
$request->langset(Lang::range());
// 加载系统语言包
Lang::load([
THINK_PATH . 'lang' . DS . $request->langset() . EXT,
APP_PATH . 'lang' . DS . $request->langset() . EXT,
]);
// 获取应用调度信息
$dispatch = self::$dispatch;
if (empty($dispatch)) {
// 进行URL路由检测
$dispatch = self::routeCheck($request, $config);
}
// 记录当前调度信息
$request->dispatch($dispatch);
// 记录路由和请求信息
if (self::$debug) {
Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
}
// 监听app_begin
Hook::listen('app_begin', $dispatch);
// 请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
$data = self::exec($dispatch, $config);
} catch (HttpResponseException $exception) {
$data = $exception->getResponse();
}
// 清空类的实例化
Loader::clearInstance();
// 输出数据到客户端
if ($data instanceof Response) {
$response = $data;
} elseif (!is_null($data)) {
// 默认自动识别响应输出类型
$isAjax = $request->isAjax();
$type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
$response = Response::create($data, $type);
} else {
$response = Response::create();
}
// 监听app_end
Hook::listen('app_end', $response);
return $response;
}
/**
* 设置当前请求的调度信息
* @access public
* @param array|string $dispatch 调度信息
* @param string $type 调度类型
* @return void
*/
public static function dispatch($dispatch, $type = 'module')
{
self::$dispatch = ['type' => $type, $type => $dispatch];
}
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
* @param string|array|\Closure $function 函数或者闭包
* @param array $vars 变量
* @return mixed
*/
public static function invokeFunction($function, $vars = [])
{
$reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars);
// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs($args);
}
/**
* 调用反射执行类的方法 支持参数绑定
* @access public
* @param string|array $method 方法
* @param array $vars 变量
* @return mixed
*/
public static function invokeMethod($method, $vars = [])
{
if (is_array($method)) {
$class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
$reflect = new \ReflectionMethod($class, $method[1]);
} else {
// 静态方法
$reflect = new \ReflectionMethod($method);
}
$args = self::bindParams($reflect, $vars);
self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
return $reflect->invokeArgs(isset($class) ? $class : null, $args);
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public static function invokeClass($class, $vars = [])
{
$reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor();
if ($constructor) {
$args = self::bindParams($constructor, $vars);
} else {
$args = [];
}
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access private
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量
* @return array
*/
private static function bindParams($reflect, $vars = [])
{
if (empty($vars)) {
// 自动获取请求变量
if (Config::get('url_param_type')) {
$vars = Request::instance()->route();
} else {
$vars = Request::instance()->param();
}
}
$args = [];
if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters();
foreach ($params as $param) {
$args[] = self::getParamValue($param, $vars, $type);
}
}
return $args;
}
/**
* 获取参数值
* @access private
* @param \ReflectionParameter $param
* @param array $vars 变量
* @param string $type
* @return array
*/
private static function getParamValue($param, &$vars, $type)
{
$name = $param->getName();
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$result = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance());
}
}
$result = method_exists($className, 'instance') ? $className::instance() : new $className;
}
} elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$result = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$result = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
return $result;
}
protected static function exec($dispatch, $config)
{
switch ($dispatch['type']) {
case 'redirect':
// 执行重定向跳转
$data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
break;
case 'module':
// 模块/控制器/操作
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
break;
case 'controller':
// 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
break;
case 'method':
// 执行回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars);
break;
case 'function':
// 执行闭包
$data = self::invokeFunction($dispatch['function']);
break;
case 'response':
$data = $dispatch['response'];
break;
default:
throw new \InvalidArgumentException('dispatch type not support');
}
return $data;
}
/**
* 执行模块
* @access public
* @param array $result 模块/控制器/操作
* @param array $config 配置参数
* @param bool $convert 是否自动转换控制器和操作名
* @return mixed
*/
public static function module($result, $config, $convert = null)
{
if (is_string($result)) {
$result = explode('/', $result);
}
$request = Request::instance();
if ($config['app_multi_module']) {
// 多模块部署
$module = strip_tags(strtolower($result[0] ?: $config['default_module']));
$bind = Route::getBind('module');
$available = false;
if ($bind) {
// 绑定模块
list($bindModule) = explode('/', $bind);
if (empty($result[0])) {
$module = $bindModule;
$available = true;
} elseif ($module == $bindModule) {
$available = true;
}
} elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {
$available = true;
}
// 模块初始化
if ($module && $available) {
// 初始化模块
$request->module($module);
$config = self::init($module);
// 模块请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
} else {
throw new HttpException(404, 'module not exists:' . $module);
}
} else {
// 单一模块部署
$module = '';
$request->module($module);
}
// 当前模块路径
App::$modulePath = APP_PATH . ($module ? $module . DS : '');
// 是否自动转换控制器和操作名
$convert = is_bool($convert) ? $convert : $config['url_convert'];
// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);
$controller = $convert ? strtolower($controller) : $controller;
// 获取操作名
$actionName = strip_tags($result[2] ?: $config['default_action']);
$actionName = $convert ? strtolower($actionName) : $actionName;
// 设置当前请求的控制器、操作
$request->controller(Loader::parseName($controller, 1))->action($actionName);
// 监听module_init
Hook::listen('module_init', $request);
try {
$instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);
} catch (ClassNotFoundException $e) {
throw new HttpException(404, 'controller not exists:' . $e->getClass());
}
// 获取当前操作名
$action = $actionName . $config['action_suffix'];
$vars = [];
if (is_callable([$instance, $action])) {
// 执行操作方法
$call = [$instance, $action];
} elseif (is_callable([$instance, '_empty'])) {
// 空操作
$call = [$instance, '_empty'];
$vars = [$actionName];
} else {
// 操作不存在
throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
}
Hook::listen('action_begin', $call);
return self::invokeMethod($call, $vars);
}
/**
* 初始化应用
*/
public static function initCommon()
{
if (empty(self::$init)) {
if (defined('APP_NAMESPACE')) {
self::$namespace = APP_NAMESPACE;
}
Loader::addNamespace(self::$namespace, APP_PATH);
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Env::get('app_debug', Config::get('app_debug'));
if (!self::$debug) {
ini_set('display_errors', 'Off');
} elseif (!IS_CLI) {
//重新申请一块比较大的buffer
if (ob_get_level() > 0) {
$output = ob_get_clean();
}
ob_start();
if (!empty($output)) {
echo $output;
}
}
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
// 加载额外文件
if (!empty($config['extra_file_list'])) {
foreach ($config['extra_file_list'] as $file) {
$file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
if (is_file($file) && !isset(self::$file[$file])) {
include $file;
self::$file[$file] = true;
}
}
}
// 设置系统时区
date_default_timezone_set($config['default_timezone']);
// 监听app_init
Hook::listen('app_init');
self::$init = true;
}
return Config::get();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return array
*/
private static function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DS : '';
// 加载初始化文件
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
include RUNTIME_PATH . $module . 'init' . EXT;
} else {
$path = APP_PATH . $module;
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}
// 加载应用状态配置
if ($config['app_status']) {
$config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
}
// 加载行为扩展文件
if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
Hook::import(include CONF_PATH . $module . 'tags' . EXT);
}
// 加载公共文件
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
// 加载当前模块语言包
if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
}
}
return Config::get();
}
/**
* URL路由检测(根据PATH_INFO)
* @access public
* @param \think\Request $request
* @param array $config
* @return array
* @throws \think\Exception
*/
public static function routeCheck($request, array $config)
{
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 开启路由
if (is_file(RUNTIME_PATH . 'route.php')) {
// 读取路由缓存
$rules = include RUNTIME_PATH . 'route.php';
if (is_array($rules)) {
Route::rules($rules);
}
} else {
$files = $config['route_config_file'];
foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 导入路由配置
$rules = include CONF_PATH . $file . CONF_EXT;
if (is_array($rules)) {
Route::import($rules);
}
}
}
}
// 路由检测(根据路由定义返回不同的URL调度)
$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
$must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
if ($must && false === $result) {
// 路由无效
throw new RouteNotFoundException();
}
}
if (false === $result) {
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
$result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
}
return $result;
}
/**
* 设置应用的路由检测机制
* @access public
* @param bool $route 是否需要检测路由
* @param bool $must 是否强制检测路由
* @return void
*/
public static function route($route, $must = false)
{
self::$routeCheck = $route;
self::$routeMust = $must;
}
}
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\RouteNotFoundException;
/**
* App 应用管理
* @author liu21st <liu21st@gmail.com>
*/
class App
{
/**
* @var bool 是否初始化过
*/
protected static $init = false;
/**
* @var string 当前模块路径
*/
public static $modulePath;
/**
* @var bool 应用调试模式
*/
public static $debug = true;
/**
* @var string 应用类库命名空间
*/
public static $namespace = 'app';
/**
* @var bool 应用类库后缀
*/
public static $suffix = false;
/**
* @var bool 应用路由检测
*/
protected static $routeCheck;
/**
* @var bool 严格路由检测
*/
protected static $routeMust;
protected static $dispatch;
protected static $file = [];
/**
* 执行应用程序
* @access public
* @param Request $request Request对象
* @return Response
* @throws Exception
*/
public static function run(Request $request = null)
{
is_null($request) && $request = Request::instance();
try {
$config = self::initCommon();
if (defined('BIND_MODULE')) {
// 模块/控制器绑定
BIND_MODULE && Route::bind(BIND_MODULE);
} elseif ($config['auto_bind_module']) {
// 入口自动绑定
$name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
Route::bind($name);
}
}
$request->filter($config['default_filter']);
// 默认语言
Lang::range($config['default_lang']);
if ($config['lang_switch_on']) {
// 开启多语言机制 检测当前语言
Lang::detect();
}
$request->langset(Lang::range());
// 加载系统语言包
Lang::load([
THINK_PATH . 'lang' . DS . $request->langset() . EXT,
APP_PATH . 'lang' . DS . $request->langset() . EXT,
]);
// 获取应用调度信息
$dispatch = self::$dispatch;
if (empty($dispatch)) {
// 进行URL路由检测
$dispatch = self::routeCheck($request, $config);
}
// 记录当前调度信息
$request->dispatch($dispatch);
// 记录路由和请求信息
if (self::$debug) {
Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
}
// 监听app_begin
Hook::listen('app_begin', $dispatch);
// 请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
$data = self::exec($dispatch, $config);
} catch (HttpResponseException $exception) {
$data = $exception->getResponse();
}
// 清空类的实例化
Loader::clearInstance();
// 输出数据到客户端
if ($data instanceof Response) {
$response = $data;
} elseif (!is_null($data)) {
// 默认自动识别响应输出类型
$isAjax = $request->isAjax();
$type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
$response = Response::create($data, $type);
} else {
$response = Response::create();
}
// 监听app_end
Hook::listen('app_end', $response);
return $response;
}
/**
* 设置当前请求的调度信息
* @access public
* @param array|string $dispatch 调度信息
* @param string $type 调度类型
* @return void
*/
public static function dispatch($dispatch, $type = 'module')
{
self::$dispatch = ['type' => $type, $type => $dispatch];
}
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
* @param string|array|\Closure $function 函数或者闭包
* @param array $vars 变量
* @return mixed
*/
public static function invokeFunction($function, $vars = [])
{
$reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars);
// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs($args);
}
/**
* 调用反射执行类的方法 支持参数绑定
* @access public
* @param string|array $method 方法
* @param array $vars 变量
* @return mixed
*/
public static function invokeMethod($method, $vars = [])
{
if (is_array($method)) {
$class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
$reflect = new \ReflectionMethod($class, $method[1]);
} else {
// 静态方法
$reflect = new \ReflectionMethod($method);
}
$args = self::bindParams($reflect, $vars);
self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
return $reflect->invokeArgs(isset($class) ? $class : null, $args);
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public static function invokeClass($class, $vars = [])
{
$reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor();
if ($constructor) {
$args = self::bindParams($constructor, $vars);
} else {
$args = [];
}
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access private
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量
* @return array
*/
private static function bindParams($reflect, $vars = [])
{
if (empty($vars)) {
// 自动获取请求变量
if (Config::get('url_param_type')) {
$vars = Request::instance()->route();
} else {
$vars = Request::instance()->param();
}
}
$args = [];
if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters();
foreach ($params as $param) {
$args[] = self::getParamValue($param, $vars, $type);
}
}
return $args;
}
/**
* 获取参数值
* @access private
* @param \ReflectionParameter $param
* @param array $vars 变量
* @param string $type
* @return array
*/
private static function getParamValue($param, &$vars, $type)
{
$name = $param->getName();
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$result = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance());
}
}
$result = method_exists($className, 'instance') ? $className::instance() : new $className;
}
} elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$result = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$result = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
return $result;
}
protected static function exec($dispatch, $config)
{
switch ($dispatch['type']) {
case 'redirect':
// 执行重定向跳转
$data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
break;
case 'module':
// 模块/控制器/操作
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
break;
case 'controller':
// 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
break;
case 'method':
// 执行回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars);
break;
case 'function':
// 执行闭包
$data = self::invokeFunction($dispatch['function']);
break;
case 'response':
$data = $dispatch['response'];
break;
default:
throw new \InvalidArgumentException('dispatch type not support');
}
return $data;
}
/**
* 执行模块
* @access public
* @param array $result 模块/控制器/操作
* @param array $config 配置参数
* @param bool $convert 是否自动转换控制器和操作名
* @return mixed
*/
public static function module($result, $config, $convert = null)
{
if (is_string($result)) {
$result = explode('/', $result);
}
$request = Request::instance();
if ($config['app_multi_module']) {
// 多模块部署
$module = strip_tags(strtolower($result[0] ?: $config['default_module']));
$bind = Route::getBind('module');
$available = false;
if ($bind) {
// 绑定模块
list($bindModule) = explode('/', $bind);
if (empty($result[0])) {
$module = $bindModule;
$available = true;
} elseif ($module == $bindModule) {
$available = true;
}
} elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {
$available = true;
}
// 模块初始化
if ($module && $available) {
// 初始化模块
$request->module($module);
$config = self::init($module);
// 模块请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
} else {
throw new HttpException(404, 'module not exists:' . $module);
}
} else {
// 单一模块部署
$module = '';
$request->module($module);
}
// 当前模块路径
App::$modulePath = APP_PATH . ($module ? $module . DS : '');
// 是否自动转换控制器和操作名
$convert = is_bool($convert) ? $convert : $config['url_convert'];
// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);
$controller = $convert ? strtolower($controller) : $controller;
if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
// 获取操作名
$actionName = strip_tags($result[2] ?: $config['default_action']);
$actionName = $convert ? strtolower($actionName) : $actionName;
// 设置当前请求的控制器、操作
$request->controller(Loader::parseName($controller, 1))->action($actionName);
// 监听module_init
Hook::listen('module_init', $request);
try {
$instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);
} catch (ClassNotFoundException $e) {
throw new HttpException(404, 'controller not exists:' . $e->getClass());
}
// 获取当前操作名
$action = $actionName . $config['action_suffix'];
$vars = [];
if (is_callable([$instance, $action])) {
// 执行操作方法
$call = [$instance, $action];
} elseif (is_callable([$instance, '_empty'])) {
// 空操作
$call = [$instance, '_empty'];
$vars = [$actionName];
} else {
// 操作不存在
throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
}
Hook::listen('action_begin', $call);
return self::invokeMethod($call, $vars);
}
/**
* 初始化应用
*/
public static function initCommon()
{
if (empty(self::$init)) {
if (defined('APP_NAMESPACE')) {
self::$namespace = APP_NAMESPACE;
}
Loader::addNamespace(self::$namespace, APP_PATH);
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Env::get('app_debug', Config::get('app_debug'));
if (!self::$debug) {
ini_set('display_errors', 'Off');
} elseif (!IS_CLI) {
//重新申请一块比较大的buffer
if (ob_get_level() > 0) {
$output = ob_get_clean();
}
ob_start();
if (!empty($output)) {
echo $output;
}
}
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
// 加载额外文件
if (!empty($config['extra_file_list'])) {
foreach ($config['extra_file_list'] as $file) {
$file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
if (is_file($file) && !isset(self::$file[$file])) {
include $file;
self::$file[$file] = true;
}
}
}
// 设置系统时区
date_default_timezone_set($config['default_timezone']);
// 监听app_init
Hook::listen('app_init');
self::$init = true;
}
return Config::get();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return array
*/
private static function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DS : '';
// 加载初始化文件
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
include RUNTIME_PATH . $module . 'init' . EXT;
} else {
$path = APP_PATH . $module;
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}
// 加载应用状态配置
if ($config['app_status']) {
$config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
}
// 加载行为扩展文件
if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
Hook::import(include CONF_PATH . $module . 'tags' . EXT);
}
// 加载公共文件
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
// 加载当前模块语言包
if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
}
}
return Config::get();
}
/**
* URL路由检测(根据PATH_INFO)
* @access public
* @param \think\Request $request
* @param array $config
* @return array
* @throws \think\Exception
*/
public static function routeCheck($request, array $config)
{
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 开启路由
if (is_file(RUNTIME_PATH . 'route.php')) {
// 读取路由缓存
$rules = include RUNTIME_PATH . 'route.php';
if (is_array($rules)) {
Route::rules($rules);
}
} else {
$files = $config['route_config_file'];
foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 导入路由配置
$rules = include CONF_PATH . $file . CONF_EXT;
if (is_array($rules)) {
Route::import($rules);
}
}
}
}
// 路由检测(根据路由定义返回不同的URL调度)
$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
$must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
if ($must && false === $result) {
// 路由无效
throw new RouteNotFoundException();
}
}
if (false === $result) {
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
$result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
}
return $result;
}
/**
* 设置应用的路由检测机制
* @access public
* @param bool $route 是否需要检测路由
* @param bool $must 是否强制检测路由
* @return void
*/
public static function route($route, $must = false)
{
self::$routeCheck = $route;
self::$routeMust = $must;
}
}
... ...