2861 changed files with 436995 additions and 0 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,134 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong; |
|||
|
|||
use app\admin\model\AuthRule; |
|||
use app\common\library\Menu; |
|||
use think\Addons; |
|||
use think\Exception; |
|||
use think\exception\PDOException; |
|||
|
|||
|
|||
/** |
|||
* 插件 |
|||
*/ |
|||
class Qingdong extends Addons |
|||
{ |
|||
|
|||
/** |
|||
* 插件安装方法 |
|||
* @return bool |
|||
*/ |
|||
public function install() |
|||
{ |
|||
$menu = self::getMenu(); |
|||
Menu::create($menu['new']); |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 插件卸载方法 |
|||
* @return bool |
|||
*/ |
|||
public function uninstall() |
|||
{ |
|||
Menu::delete('qingdong'); |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 插件启用方法 |
|||
* @return bool |
|||
*/ |
|||
public function enable() |
|||
{ |
|||
Menu::enable('qingdong'); |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 插件禁用方法 |
|||
* @return bool |
|||
*/ |
|||
public function disable() |
|||
{ |
|||
Menu::disable('qingdong'); |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 插件更新方法 |
|||
*/ |
|||
public function upgrade() |
|||
{ |
|||
$menu = self::getMenu(); |
|||
if (method_exists(Menu::class, 'upgrade')) { |
|||
Menu::upgrade('qingdong', $menu['new']); |
|||
} else { |
|||
self::menuCreateOrUpdate($menu['new'], $menu['old']); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private static function getMenu() |
|||
{ |
|||
$newMenu = []; |
|||
$config_file = ADDON_PATH . "qingdong" . DS . 'config' . DS . "menu.php"; |
|||
if (is_file($config_file)) { |
|||
$newMenu = include $config_file; |
|||
} |
|||
$oldMenu = AuthRule::where('name', 'like', "qingdong%")->select(); |
|||
$oldMenu = array_column($oldMenu, null, 'name'); |
|||
return ['new' => $newMenu, 'old' => $oldMenu]; |
|||
} |
|||
|
|||
private static function menuCreateOrUpdate($newMenu, $oldMenu, $parent = 0) |
|||
{ |
|||
if (!is_numeric($parent)) { |
|||
$parentRule = AuthRule::getByName($parent); |
|||
$pid = $parentRule ? $parentRule['id'] : 0; |
|||
} else { |
|||
$pid = $parent; |
|||
} |
|||
$allow = array_flip(['file', 'name', 'title', 'icon', 'condition', 'remark', 'ismenu', 'weigh']); |
|||
foreach ($newMenu as $k => $v) { |
|||
$hasChild = isset($v['sublist']) && $v['sublist'] ? true : false; |
|||
$data = array_intersect_key($v, $allow); |
|||
$data['ismenu'] = isset($data['ismenu']) ? $data['ismenu'] : ($hasChild ? 1 : 0); |
|||
$data['icon'] = isset($data['icon']) ? $data['icon'] : ($hasChild ? 'fa fa-list' : 'fa fa-circle-o'); |
|||
$data['pid'] = $pid; |
|||
$data['status'] = 'normal'; |
|||
try { |
|||
if (!isset($oldMenu[$data['name']])) { |
|||
$menu = AuthRule::create($data); |
|||
} else { |
|||
$menu = $oldMenu[$data['name']]; |
|||
} |
|||
if ($hasChild) { |
|||
self::menuCreateOrUpdate($v['sublist'], $oldMenu, $menu['id']); |
|||
} |
|||
} catch (PDOException $e) { |
|||
throw new Exception($e->getMessage()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 应用初始化 |
|||
*/ |
|||
public function appInit() |
|||
{ |
|||
// 公共方法 |
|||
require_once __DIR__ . '/helper.php'; |
|||
if(!class_exists("\dingding\TopSdk")){ |
|||
\think\Loader::addNamespace('dingding', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'dingding' . DS); |
|||
} |
|||
if(!class_exists("\WeWork\App")){ |
|||
\think\Loader::addNamespace('WeWork', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'wework' . DS); |
|||
} |
|||
if(!class_exists("\PhpOffice\PhpWord\PhpWord")){ |
|||
\think\Loader::addNamespace('PhpOffice\PhpWord', ADDON_PATH . 'qingdong' . DS . 'library' . DS . 'PhpWord' . DS); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
<?php |
|||
|
|||
return [ |
|||
[ |
|||
//配置名称,该值在当前数组配置中确保唯一 |
|||
'name' => 'mobile_name', |
|||
//配置标题 |
|||
'title' => '网站名称', |
|||
//配置类型,支持string/text/number/datetime/array/select/selects/image/images/file/files/checkbox/radio/bool |
|||
'type' => 'string', |
|||
//分组选项卡 |
|||
'group' => '分组1', |
|||
//配置值 |
|||
'value' => 'CRM', |
|||
//配置验证规则,更之规则可参考nice-validator文件 |
|||
'rule' => 'required', |
|||
'msg' => '请输入网站名称', |
|||
'tip' => 'h5或小程序登录页标题', |
|||
'ok' => '验证成功', |
|||
'extend' => '' |
|||
], |
|||
|
|||
]; |
|||
@ -0,0 +1,209 @@ |
|||
<?php |
|||
return array ( |
|||
'table_name' => 'fa_qingdong_achievement,fa_qingdong_achievement_records,fa_qingdong_admin_config,fa_qingdong_approval,fa_qingdong_attendance,fa_qingdong_attendance_address,fa_qingdong_attendance_card,fa_qingdong_attendance_leave,fa_qingdong_attendance_rule,fa_qingdong_attendance_statisc,fa_qingdong_attendance_time,fa_qingdong_business,fa_qingdong_business_other,fa_qingdong_business_product,fa_qingdong_business_status,fa_qingdong_comment,fa_qingdong_consume,fa_qingdong_contacts,fa_qingdong_contacts_file,fa_qingdong_contacts_other,fa_qingdong_contract,fa_qingdong_contract_file,fa_qingdong_contract_other,fa_qingdong_contract_product,fa_qingdong_contract_ratio,fa_qingdong_customer,fa_qingdong_customer_file,fa_qingdong_customer_other,fa_qingdong_daily,fa_qingdong_daily_draft,fa_qingdong_daily_read,fa_qingdong_ding_contacts,fa_qingdong_ding_customer,fa_qingdong_ding_record,fa_qingdong_ding_staff,fa_qingdong_event,fa_qingdong_examine_record,fa_qingdong_fauser,fa_qingdong_feedback,fa_qingdong_field,fa_qingdong_file,fa_qingdong_flow,fa_qingdong_form,fa_qingdong_form_approval,fa_qingdong_form_field,fa_qingdong_goods,fa_qingdong_ku_customer,fa_qingdong_leads,fa_qingdong_leads_file,fa_qingdong_leads_other,fa_qingdong_login_token,fa_qingdong_message,fa_qingdong_notice,fa_qingdong_notice_template,fa_qingdong_operation_log,fa_qingdong_product,fa_qingdong_product_part,fa_qingdong_product_type,fa_qingdong_push_reload,fa_qingdong_receivables,fa_qingdong_receivables_other,fa_qingdong_receivables_plan,fa_qingdong_record,fa_qingdong_record_file,fa_qingdong_record_read,fa_qingdong_remind,fa_qingdong_seas_type,fa_qingdong_send_template,fa_qingdong_staff,fa_qingdong_staff_collect,fa_qingdong_staff_department,fa_qingdong_staff_ratio,fa_qingdong_staff_role,fa_qingdong_staff_rule,fa_qingdong_staff_sign_in', |
|||
'self_path' => '', |
|||
'update_data' => 'INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (1, \'seas\', \'auto\', \'1\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (2, \'seas\', \'genjing\', \'1\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (3, \'seas\', \'genjing_success\', \'1\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (4, \'seas\', \'genjing_day\', \'0\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (5, \'seas\', \'chengjiao\', \'0\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (6, \'seas\', \'chengjiao_day\', \'0\', 1631875558, 1631875558, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (7, \'wechat\', \'mini_appid\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (8, \'wechat\', \'mini_secret\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (9, \'wechat\', \'appid\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (10, \'wechat\', \'secret\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (11, \'wechat\', \'examine_template\', \'0\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (12, \'wechat\', \'record_template\', \'0\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (13, \'wechat\', \'map_key\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (14, \'wechat\', \'web_url\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (15, \'dingding\', \'ding_key\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_admin_config` |
|||
VALUES (16, \'dingding\', \'ding_secret\', \'\', 1631875559, 1631875559, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (138, \'leads\', \'线索来源\', \'[\\"电话营销\\",\\"拜访\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (139, \'leads\', \'客户行业\', \'[\\"互联网\\",\\"信息化\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (141, \'examine\', \'回款方式\', \'[\\"微信\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (147, \'contacts\', \'角色\', |
|||
\'[\\"普通员工\\",\\"决策人\\",\\"分项决策人\\",\\"商务决策\\",\\"财务决策\\",\\"使用人\\",\\"意见影响人\\",\\"采购\\",\\"老板\\",\\"股东\\",\\"职业经理人\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (148, \'other\', \'跟进类型\', \'[\\"到访\\",\\"电话\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (149, \'other\', \'消费方式\', \'[\\"吃饭\\",\\"住酒店\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (151, \'customer\', \'客户所属\', \'[\\"重点客户\\",\\"普通客户\\",\\"非优先客户\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (152, \'customer\', \'客户状态\', \'[\\"初次接触\\",\\"正在跟进\\",\\"准备购买\\",\\"准备付款\\",\\"已经购买\\",\\"暂时搁置\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (153, \'customer\', \'客户来源\', \'[\\"行业活动\\",\\"搜索引擎\\",\\"客户转介绍\\",\\"展会\\",\\"朋友介绍\\",\\"市场推广\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_field` |
|||
VALUES (158, \'daily\', \'报告类型\', \'[\\"日报\\",\\"周报\\",\\"月报\\",\\"季报\\",\\"年报\\"]\'); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (11, \'线索管理\', \'leads\', \'{\\"data\\":[{\\"id\\":\\"name\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"线索名称\\",\\"readonly\\":false,\\"placeholder\\":\\"线索名称\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"source\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"线索来源\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"电话营销\\",\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"电话营销\\",\\"children\\":[],\\"expand\\":true,\\"__label\\":\\"电话营销\\",\\"__value\\":[\\"电话营销\\"]},{\\"key\\":\\"\\",\\"value\\":\\"主动来电\\",\\"__label\\":\\"拜访\\",\\"__value\\":[\\"主动来电\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"拜访\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请选择线索来源\\"}},{\\"id\\":\\"industry\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"客户行业\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"行业1\\",\\"__label\\":\\"互联网\\",\\"__value\\":[\\"行业1\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"互联网\\"},{\\"key\\":\\"\\",\\"value\\":\\"行业2\\",\\"__value\\":[\\"行业2\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"信息化\\",\\"__label\\":\\"信息化\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请选择客户行业\\"}},{\\"id\\":\\"mobile\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"手机号\\",\\"readonly\\":false,\\"placeholder\\":\\"手机号\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"level\\",\\"name\\":\\"评分\\",\\"type\\":1,\\"component\\":\\"Rate\\",\\"config\\":{\\"label\\":\\"客户级别\\",\\"allowHalf\\":true,\\"disabled\\":false,\\"type\\":\\"default\\",\\"is_delete\\":true}},{\\"id\\":\\"telephone\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"电话\\",\\"readonly\\":false,\\"placeholder\\":\\"电话\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"address_detail\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"地址\\",\\"readonly\\":false,\\"row\\":2,\\"placeholder\\":\\"请输入地址\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"next_time\\",\\"name\\":\\"时间选择框\\",\\"type\\":1,\\"component\\":\\"TimePicker\\",\\"config\\":{\\"label\\":\\"下次联系时间\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"time\\",\\"format\\":\\"YYYY-MM-DD HH:mm:ss\\",\\"confirm\\":true,\\"required\\":false,\\"readonly\\":false,\\"is_delete\\":true}},{\\"id\\":\\"remarks\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"备注信息\\",\\"readonly\\":false,\\"row\\":2,\\"placeholder\\":\\"备注信息\\",\\"required\\":false,\\"is_delete\\":true}}]}\', 1619592288, 1655433791, NULL); |
|||
|
|||
|
|||
INSERT INTO `__PREFIX__qingdong_form` |
|||
VALUES (12, \'客户管理\', \'customer\', |
|||
\'{\\"data\\":[{\\"id\\":\\"name\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"客户名称\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入客户名称\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"subname\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"助记名称\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入助记名称\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"industry\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"客户所属\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"终端客户\\",\\"__label\\":\\"重点客户\\",\\"__value\\":[\\"终端客户\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"重点客户\\"},{\\"key\\":\\"\\",\\"value\\":\\"代理商\\",\\"__label\\":\\"普通客户\\",\\"__value\\":[\\"代理商\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"普通客户\\"},{\\"key\\":\\"\\",\\"value\\":\\"同行\\",\\"__value\\":[\\"同行\\"],\\"nodeKey\\":3,\\"isEdit\\":false,\\"label\\":\\"非优先客户\\",\\"__label\\":\\"非优先客户\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请输入客户所属\\"}},{\\"id\\":\\"follow\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"客户状态\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"初次接触\\",\\"__label\\":\\"初次接触\\",\\"__value\\":[\\"初次接触\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"初次接触\\"},{\\"key\\":\\"\\",\\"value\\":\\"正在跟进\\",\\"__label\\":\\"正在跟进\\",\\"__value\\":[\\"正在跟进\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"正在跟进\\"},{\\"key\\":\\"\\",\\"value\\":\\"准备购买\\",\\"__label\\":\\"准备购买\\",\\"__value\\":[\\"准备购买\\"],\\"nodeKey\\":3,\\"isEdit\\":false,\\"label\\":\\"准备购买\\"},{\\"key\\":\\"\\",\\"value\\":\\"准备付款\\",\\"__label\\":\\"准备付款\\",\\"__value\\":[\\"准备付款\\"],\\"nodeKey\\":4,\\"isEdit\\":false,\\"label\\":\\"准备付款\\"},{\\"key\\":\\"\\",\\"value\\":\\"已经购买\\",\\"__label\\":\\"已经购买\\",\\"__value\\":[\\"已经购买\\"],\\"nodeKey\\":5,\\"isEdit\\":false,\\"label\\":\\"已经购买\\"},{\\"key\\":\\"\\",\\"value\\":\\"暂时搁置\\",\\"__label\\":\\"暂时搁置\\",\\"__value\\":[\\"暂时搁置\\"],\\"nodeKey\\":6,\\"isEdit\\":false,\\"label\\":\\"暂时搁置\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请输入客户状态\\"}},{\\"id\\":\\"level\\",\\"name\\":\\"评分\\",\\"type\\":1,\\"component\\":\\"Rate\\",\\"config\\":{\\"label\\":\\"客户星级\\",\\"allowHalf\\":true,\\"disabled\\":false,\\"type\\":\\"default\\",\\"is_delete\\":true,\\"placeholder\\":\\"客户星级\\"}},{\\"id\\":\\"source\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"客户来源\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"行业活动\\",\\"__label\\":\\"行业活动\\",\\"__value\\":[\\"行业活动\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"行业活动\\"},{\\"key\\":\\"\\",\\"value\\":\\"搜索引擎\\",\\"__label\\":\\"搜索引擎\\",\\"__value\\":[\\"搜索引擎\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"搜索引擎\\"},{\\"key\\":\\"\\",\\"value\\":\\"客户转介绍\\",\\"__label\\":\\"客户转介绍\\",\\"__value\\":[\\"客户转介绍\\"],\\"nodeKey\\":3,\\"isEdit\\":false,\\"label\\":\\"客户转介绍\\"},{\\"key\\":\\"\\",\\"value\\":\\"展会\\",\\"__label\\":\\"展会\\",\\"__value\\":[\\"展会\\"],\\"nodeKey\\":4,\\"isEdit\\":false,\\"label\\":\\"展会\\"},{\\"key\\":\\"\\",\\"value\\":\\"朋友介绍\\",\\"__label\\":\\"朋友介绍\\",\\"__value\\":[\\"朋友介绍\\"],\\"nodeKey\\":5,\\"isEdit\\":false,\\"label\\":\\"朋友介绍\\"},{\\"key\\":\\"\\",\\"value\\":\\"市场推广\\",\\"__value\\":[\\"市场推广\\"],\\"nodeKey\\":6,\\"isEdit\\":false,\\"label\\":\\"市场推广\\",\\"__label\\":\\"市场推广\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"客户来源\\"}},{\\"id\\":\\"other_12771\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"备注信息\\",\\"row\\":2,\\"placeholder\\":\\"请输入备注信息\\",\\"required\\":false,\\"is_delete\\":true}}]}\', |
|||
1619592291, 1646217144, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` |
|||
VALUES (13, \'联系人管理\', \'contacts\', |
|||
\'{\\"data\\":[{\\"id\\":\\"name\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"联系人姓名\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入联系人姓名\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"subname\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"尊称\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入尊称\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_21517\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"电话\\",\\"placeholder\\":\\"请输入联系人电话\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"mobile\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"手机号\\",\\"placeholder\\":\\"请输入联系人手机号\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"role\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"角色\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"普通员工\\",\\"__label\\":\\"普通员工\\",\\"__value\\":[\\"普通员工\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"普通员工\\"},{\\"key\\":\\"\\",\\"value\\":\\"决策人\\",\\"__label\\":\\"决策人\\",\\"__value\\":[\\"决策人\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"决策人\\"},{\\"key\\":\\"\\",\\"value\\":\\"分项决策人\\",\\"__label\\":\\"分项决策人\\",\\"__value\\":[\\"分项决策人\\"],\\"nodeKey\\":3,\\"isEdit\\":false,\\"label\\":\\"分项决策人\\"},{\\"key\\":\\"\\",\\"value\\":\\"商务决策\\",\\"__label\\":\\"商务决策\\",\\"__value\\":[\\"商务决策\\"],\\"nodeKey\\":4,\\"isEdit\\":false,\\"label\\":\\"商务决策\\"},{\\"key\\":\\"\\",\\"value\\":\\"财务决策\\",\\"__label\\":\\"财务决策\\",\\"__value\\":[\\"财务决策\\"],\\"nodeKey\\":5,\\"isEdit\\":false,\\"label\\":\\"财务决策\\"},{\\"key\\":\\"\\",\\"value\\":\\"使用人\\",\\"__label\\":\\"使用人\\",\\"__value\\":[\\"使用人\\"],\\"nodeKey\\":6,\\"isEdit\\":false,\\"label\\":\\"使用人\\"},{\\"key\\":\\"\\",\\"value\\":\\"意见影响人\\",\\"__label\\":\\"意见影响人\\",\\"__value\\":[\\"意见影响人\\"],\\"nodeKey\\":7,\\"isEdit\\":false,\\"label\\":\\"意见影响人\\"},{\\"key\\":\\"\\",\\"value\\":\\"采购\\",\\"__label\\":\\"采购\\",\\"__value\\":[\\"采购\\"],\\"nodeKey\\":8,\\"isEdit\\":false,\\"label\\":\\"采购\\"},{\\"key\\":\\"\\",\\"value\\":\\"老板\\",\\"__label\\":\\"老板\\",\\"__value\\":[\\"老板\\"],\\"nodeKey\\":9,\\"isEdit\\":false,\\"label\\":\\"老板\\"},{\\"key\\":\\"\\",\\"value\\":\\"股东\\",\\"__label\\":\\"股东\\",\\"__value\\":[\\"股东\\"],\\"nodeKey\\":10,\\"isEdit\\":false,\\"label\\":\\"股东\\"},{\\"key\\":\\"\\",\\"value\\":\\"职业经理人\\",\\"__value\\":[\\"职业经理人\\"],\\"nodeKey\\":11,\\"isEdit\\":false,\\"label\\":\\"职业经理人\\",\\"__label\\":\\"职业经理人\\"}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请选择角色\\"}},{\\"id\\":\\"post\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"部门职务\\",\\"placeholder\\":\\"请输入部门职务\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_4367\\",\\"name\\":\\"日期选择框\\",\\"type\\":1,\\"component\\":\\"DatePicker\\",\\"config\\":{\\"label\\":\\"生日\\",\\"placeholder\\":\\"请输入联系人生日\\",\\"type\\":\\"date\\",\\"value\\":\\"\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"email\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"邮箱\\",\\"placeholder\\":\\"请输入邮箱\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_17344\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"微信\\",\\"placeholder\\":\\"请输入联系人微信\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_23536\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"备注信息\\",\\"row\\":2,\\"placeholder\\":\\"请输入备注信息\\",\\"required\\":false,\\"is_delete\\":true}}]}\', |
|||
1619592291, 1643096926, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` |
|||
VALUES (14, \'合同管理\', \'contract\', |
|||
\'{\\"data\\":[{\\"id\\":\\"num\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"合同编号\\",\\"readonly\\":false,\\"placeholder\\":\\"输入合同编号\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"name\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"合同名称\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入合同名称\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"money\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"合同金额\\",\\"readonly\\":false,\\"placeholder\\":\\"请输入合同金额\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"order_date\\",\\"name\\":\\"时间选择框\\",\\"type\\":1,\\"component\\":\\"TimePicker\\",\\"config\\":{\\"label\\":\\"下单时间\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"time\\",\\"format\\":\\"HH:mm:ss\\",\\"confirm\\":true,\\"required\\":true,\\"readonly\\":false,\\"is_delete\\":true}},{\\"id\\":\\"start_time\\",\\"name\\":\\"日期选择框\\",\\"type\\":1,\\"component\\":\\"DatePicker\\",\\"config\\":{\\"label\\":\\"合同开始时间\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"date\\",\\"format\\":\\"\\",\\"value\\":\\"\\",\\"required\\":true,\\"readonly\\":false,\\"is_delete\\":true}},{\\"id\\":\\"end_time\\",\\"name\\":\\"日期选择框\\",\\"type\\":1,\\"component\\":\\"DatePicker\\",\\"config\\":{\\"label\\":\\"合同结束时间\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"date\\",\\"format\\":\\"\\",\\"value\\":\\"\\",\\"required\\":true,\\"readonly\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_47006\\",\\"name\\":\\"单选框\\",\\"type\\":1,\\"component\\":\\"radio\\",\\"config\\":{\\"label\\":\\"是否含税\\",\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"含税\\"},{\\"key\\":\\"\\",\\"value\\":\\"不含税\\"}],\\"placeholder\\":\\"请输入\\",\\"required\\":false,\\"is_delete\\":true}}]}\', |
|||
1619592291, 1643020154, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` |
|||
VALUES (15, \'回款管理\', \'examine\', |
|||
\'{\\"data\\":[{\\"id\\":\\"number\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"回款编号\\",\\"placeholder\\":\\"请输入回款编号\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"return_time\\",\\"name\\":\\"日期选择框\\",\\"type\\":1,\\"component\\":\\"DatePicker\\",\\"config\\":{\\"label\\":\\"回款日期\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"date\\",\\"value\\":\\"\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"money\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"回款金额\\",\\"placeholder\\":\\"请输入回款金额\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"return_type\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"回款方式\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"微信\\",\\"__label\\":\\"微信\\",\\"__value\\":[\\"微信\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"微信\\"}],\\"required\\":true,\\"is_delete\\":true}}]}\', |
|||
1619592291, 1643020163, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (16, \'日报管理\', \'daily\', \'{\\"data\\":[{\\"id\\":\\"other_43472\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.1.完成了哪些工作\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_48871\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.2.取得了哪些成绩\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_33048\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.3.当前进展如何\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_82389\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.4.计划实施情况\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}}]}\', 1619491859, 1640141699, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (17, \'周报管理\', \'weekly\', \'{\\"data\\":[{\\"id\\":\\"other_72263\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.1.完成了哪些工作\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_22415\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.2.取得了哪些成绩\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_41856\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.3.当前进展如何\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}}]}\', 1643020163, 1643020163, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (18, \'月报管理\', \'monthly\', \'{\\"data\\":[{\\"id\\":\\"other_79661\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.1.完成了哪些工作\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_52344\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.2.取得了哪些成绩\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_15457\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.3.当前进展如何\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}}]}\', 1643020163, 1643020163, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (19, \'季报管理\', \'quarterly\', \'{\\"data\\":[{\\"id\\":\\"other_43472\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.1.完成了哪些工作\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_48871\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.2.取得了哪些成绩\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_33048\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.3.当前进展如何\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_82389\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.4.计划实施情况\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}}]}\', 1619491859, 1640141727, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (20, \'年报管理\', \'yearly\', \'{\\"data\\":[{\\"id\\":\\"other_43472\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.1.完成了哪些工作\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_48871\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.2.取得了哪些成绩\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_33048\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.3.当前进展如何\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_82389\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"1.4.计划实施情况\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_90392\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"2.1 面临哪些挑战\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_72126\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"2.2 什么原因导致的\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_39787\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"2.3 有何改进措施\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"other_66752\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"3.1 节约了哪些成本\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_62312\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"3.2 提升了哪些效率\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_62889\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"3.3 优化了哪些步骤\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_98365\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"3.4 拓宽了哪些渠道\\",\\"row\\":2,\\"placeholder\\":\\"请输入内容\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_80726\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"4.1 下一步的安排\\",\\"row\\":2,\\"placeholder\\":\\"请输入下一步的安排\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_15038\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"4.2 需要的资源支持\\",\\"row\\":2,\\"placeholder\\":\\"请输入需要的资源支持\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_970\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"4.3 预计达到的结果\\",\\"row\\":2,\\"placeholder\\":\\"请输入预计达到的结果\\",\\"required\\":false,\\"is_delete\\":true}}]}\', 1643020163, 1643020163, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (21, \'外勤签到\', \'signin\', \'{\\"data\\":[{\\"id\\":\\"other_35260\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"备注\\",\\"row\\":2,\\"placeholder\\":\\"请输入备注\\",\\"required\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_65453\\",\\"name\\":\\"图片上传\\",\\"type\\":1,\\"component\\":\\"uploadImage\\",\\"config\\":{\\"label\\":\\"图片上传\\",\\"value\\":[],\\"required\\":false,\\"placeholder\\":\\"请上传图片\\",\\"maxnum\\":1,\\"is_delete\\":true,\\"format\\":[\\"jpg\\",\\"jpeg\\",\\"png\\"],\\"maxSize\\":5000}}],\\"isAddContact\\":true}\', 1643020163, 1657163099, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_form` VALUES (22, \'商机管理\', \'business\', \'{\\"data\\":[{\\"id\\":\\"name\\",\\"name\\":\\"单行输入框\\",\\"type\\":1,\\"component\\":\\"input\\",\\"config\\":{\\"type\\":\\"text\\",\\"label\\":\\"商机名称\\",\\"readonly\\":false,\\"placeholder\\":\\"商机名称\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"money\\",\\"name\\":\\"数字框\\",\\"type\\":1,\\"component\\":\\"input-number\\",\\"config\\":{\\"label\\":\\"商机金额\\",\\"placeholder\\":\\"请输入商机金额\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"status\\",\\"name\\":\\"下拉选择框\\",\\"type\\":1,\\"component\\":\\"select\\",\\"config\\":{\\"label\\":\\"商机状态\\",\\"type\\":null,\\"content\\":[{\\"key\\":\\"\\",\\"value\\":\\"行业1\\",\\"__label\\":\\"验证客户\\",\\"__value\\":[\\"行业1\\"],\\"nodeKey\\":1,\\"isEdit\\":false,\\"label\\":\\"验证客户\\"},{\\"key\\":\\"\\",\\"value\\":\\"行业2\\",\\"__value\\":[\\"行业2\\"],\\"nodeKey\\":2,\\"isEdit\\":false,\\"label\\":\\"需求分析\\",\\"__label\\":\\"需求分析\\"},{\\"label\\":\\"方案/报价\\",\\"expand\\":true,\\"value\\":\\"0-0\\",\\"isEdit\\":false,\\"__label\\":\\"方案/报价\\",\\"__value\\":[\\"0-0\\"],\\"nodeKey\\":3},{\\"label\\":\\"赢单\\",\\"expand\\":true,\\"value\\":\\"0-0\\",\\"isEdit\\":false,\\"__label\\":\\"赢单\\",\\"__value\\":[\\"0-0\\"],\\"nodeKey\\":4},{\\"label\\":\\"输单\\",\\"expand\\":true,\\"value\\":\\"0-0\\",\\"isEdit\\":false,\\"__label\\":\\"输单\\",\\"__value\\":[\\"0-0\\"],\\"nodeKey\\":5}],\\"required\\":true,\\"multiple\\":false,\\"is_delete\\":true,\\"placeholder\\":\\"请选择商机状态\\"}},{\\"id\\":\\"expect_time\\",\\"name\\":\\"日期选择框\\",\\"type\\":1,\\"component\\":\\"DatePicker\\",\\"config\\":{\\"label\\":\\"预计成交时间\\",\\"placeholder\\":\\"请输入预计成交时间\\",\\"type\\":\\"date\\",\\"value\\":\\"\\",\\"required\\":true,\\"is_delete\\":true}},{\\"id\\":\\"next_time\\",\\"name\\":\\"时间选择框\\",\\"type\\":1,\\"component\\":\\"TimePicker\\",\\"config\\":{\\"label\\":\\"下次跟进时间\\",\\"placeholder\\":\\"点击选择\\",\\"type\\":\\"time\\",\\"format\\":\\"YYYY-MM-DD HH:mm:ss\\",\\"confirm\\":true,\\"required\\":false,\\"readonly\\":false,\\"is_delete\\":true}},{\\"id\\":\\"other_48629\\",\\"name\\":\\"图片上传\\",\\"type\\":1,\\"component\\":\\"uploadImage\\",\\"config\\":{\\"label\\":\\"图片上传\\",\\"value\\":[],\\"required\\":false,\\"placeholder\\":\\"请上传图片\\",\\"maxnum\\":1,\\"is_delete\\":true,\\"format\\":[\\"jpg\\",\\"jpeg\\",\\"png\\"],\\"maxSize\\":5000}},{\\"id\\":\\"remark\\",\\"name\\":\\"文本框\\",\\"type\\":1,\\"component\\":\\"textarea\\",\\"config\\":{\\"label\\":\\"备注信息\\",\\"readonly\\":false,\\"row\\":2,\\"placeholder\\":\\"备注信息\\",\\"required\\":false,\\"is_delete\\":true}}],\\"isAddContact\\":true}\', 1619592288, 1659082152, NULL); |
|||
|
|||
|
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (1, \'审批通知\', \'examine\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"{{staff_name}}\\\\u53d1\\\\u8d77\\\\u4e00\\\\u4e2a\\\\u300a\\\\u5ba1\\\\u6279\\\\u300b\\\\u6307\\\\u5b9a\\\\u7531\\\\u60a8\\\\u5904\\\\u7406\\",\\"keyword1\\":\\"{{examine_type}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{date}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u5904\\\\u7406\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (3, \'新建跟进记录通知\', \'record\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"{{staff_name}}\\\\u521a\\\\u521a\\\\u65b0\\\\u5efa\\\\u4e86\\\\u4e00\\\\u6761\\\\u300a\\\\u8ddf\\\\u8fdb\\\\u8bb0\\\\u5f55\\\\u300b\\\\u6307\\\\u5b9a\\\\u7531\\\\u60a8\\\\u5ba1\\\\u9605\\",\\"keyword1\\":\\"{{customer_name}}{{staff_department}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{customer_follow}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{{date}}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u5904\\\\u7406\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (4, \'新建工作报告通知\', \'daily\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"{{staff_name}}\\\\u521a\\\\u521a\\\\u65b0\\\\u5efa\\\\u4e86\\\\u4e00\\\\u6761\\\\u300a\\\\u5de5\\\\u4f5c\\\\u62a5\\\\u544a\\\\u300b\\\\u6307\\\\u5b9a\\\\u7531\\\\u60a8\\\\u5ba1\\\\u9605\\",\\"keyword1\\":\\"{staff_name}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{daily_type}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{date}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (5, \'回收客户到公海通知\', \'seas\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u60a8\\\\u7684\\\\u5ba2\\\\u6237\\\\u957f\\\\u65f6\\\\u95f4\\\\u672a\\\\u8ddf\\\\u8fdb\\\\uff0c\\\\u5df2\\\\u88ab\\\\u7cfb\\\\u7edf\\\\u81ea\\\\u52a8\\\\u56de\\\\u6536\\\\u5230\\\\u516c\\\\u6d77\\\\u6c60\\\\u5185\\\\u3002\\",\\"keyword1\\":\\"{{customer_name}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{day}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{{date}}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u5efa\\\\u8bae\\\\u5ba2\\\\u6237\\\\u53ca\\\\u65f6\\\\u8ddf\\\\u8fdb\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (6, \'出差签到通知\', \'sign\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"{{staff_name}}\\\\u63d0\\\\u4ea4\\\\u4e86\\\\u4e00\\\\u4e2a\\\\u51fa\\\\u5dee\\\\u7b7e\\\\u5230\\\\uff0c\\\\u7531\\\\u60a8\\\\u5ba1\\\\u9605\\\\uff01\\",\\"keyword1\\":\\"{{address}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{date}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{{customer_name}}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u5ba1\\\\u9605\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (7, \'审批通过通知\', \'examine_adopt\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u60a8\\\\u63d0\\\\u4ea4\\\\u7684\\\\u5ba1\\\\u6279\\\\u5df2\\\\u5ba1\\\\u6838\\\\u901a\\\\u8fc7\\\\uff01\\",\\"keyword1\\":\\"{{check_name}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{examine_type}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{submit_time}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u5ba1\\\\u6838\\\\u901a\\\\u8fc7\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (8, \'审批拒绝通知\', \'examine_refuse\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u60a8\\\\u63d0\\\\u4ea4\\\\u7684\\\\u5ba1\\\\u6279\\\\u88ab\\\\u62d2\\\\u7edd\\\\uff01\\",\\"keyword1\\":\\"{{staff_name}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{check_name}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{examine_type}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"{{examine_desc}}\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u5ba1\\\\u6838\\\\u62d2\\\\u7edd\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (9, \'合同到期通知\', \'contract_expire\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u5408\\\\u540c\\\\u5373\\\\u5c06\\\\u5230\\\\u671f\\\\uff0c\\\\u8bf7\\\\u5c3d\\\\u5feb\\\\u8ddf\\\\u8fdb\\\\u56de\\\\u6b3e\\",\\"keyword1\\":\\"{customer_name}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{money}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u8ddf\\\\u8fdb\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (10, \'回款计划到期通知\', \'plan_expire\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u5df2\\\\u5230\\\\u8ba1\\\\u5212\\\\u56de\\\\u6b3e\\\\u7ea6\\\\u5b9a\\\\u65f6\\\\u95f4\\\\uff0c\\\\u8bf7\\\\u5c3d\\\\u5feb\\\\u8ddf\\\\u8fdb\\\\u56de\\\\u6b3e\\",\\"keyword1\\":\\"{{customer_name}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{plan_money}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{{plan_time}}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u8ddf\\\\u8fdb\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (11, \'评论通知\', \'comment\', |
|||
\'{\\"template_id\\":\\"\\",\\"first\\":\\"\\\\u8bc4\\\\u8bba\\\\u4e86\\\\u60a8\\\\u63d0\\\\u4ea4\\\\u7684\\\\u8ddf\\\\u8fdb\\\\u8bb0\\\\u5f55\\\\uff01\\",\\"keyword1\\":\\"{{staff_name}}\\",\\"keyword1_color\\":\\"#666\\",\\"keyword2\\":\\"{{content}}\\",\\"keyword2_color\\":\\"#666\\",\\"keyword3\\":\\"{{date}}\\",\\"keyword3_color\\":\\"#666\\",\\"keyword4\\":\\"\\",\\"keyword4_color\\":\\"#666\\",\\"keyword5\\":\\"\\",\\"keyword5_color\\":\\"#666\\",\\"remark\\":\\"\\\\u8bf7\\\\u53ca\\\\u65f6\\\\u5904\\\\u7406\\\\uff01\\",\\"remark_color\\":\\"#666\\"}\'); |
|||
INSERT INTO `__PREFIX__qingdong_notice_template` |
|||
VALUES (12, \'日程通知\', \'event\', |
|||
\'{"template_id":"","first":"{{event_title}}日程即将开始","keyword1":"","keyword1_color":"#666","keyword2":"","keyword2_color":"#666","keyword3":"","keyword3_color":"#666","keyword4":"","keyword4_color":"#666","keyword5":"","keyword5_color":"#666","remark":"请及时处理!","remark_color":"#666"}\'); |
|||
|
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (1, \'费用 \', \'[{}]\', 0, \'\', \'consume\', \'\', NULL, 1657014906, 1, 1657014906, 1657014906, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (2, \'业绩\', \'[{}]\', 0, \'\', \'achievement\', \'\', NULL, 1657767346, 1, 1657767346, 1657767346, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (3, \'回款\', \'[{}]\', 0, \'\', \'receivables\', \'\', NULL, 1658388920, 1, 1658388920, 1658388920, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (4, \'合同\', \'[{}]\', 0, \'\', \'contract\', \'\', NULL, 1658388928, 1, 1658388928, 1658388928, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (5, \'补卡\', \'[{}]\', 0, \'\', \'card\', \'\', NULL, 1658388928, 1, 1658388928, 1658388928, NULL); |
|||
INSERT INTO `__PREFIX__qingdong_flow` VALUES (6, \'请假\', \'[{}]\', 0, \'\', \'leave\', \'\', NULL, 1658388928, 1, 1658388928, 1658388928, NULL); |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_achievement_records` |
|||
ADD COLUMN `flow_id` int(11) NULL COMMENT \'审核流程ID\' AFTER `flow_staff_ids`, |
|||
ADD COLUMN `order_id` int(11) NULL COMMENT \'审批流程步骤id\' AFTER `flow_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_approval` |
|||
ADD COLUMN `flow_id` int(11) NULL COMMENT \'审核流程ID\' AFTER `check_status`, |
|||
ADD COLUMN `order_id` int(11) NULL COMMENT \'审批流程步骤id\' AFTER `flow_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_consume` |
|||
ADD COLUMN `flow_id` int(11) NULL COMMENT \'审核流程ID\' AFTER `flow_staff_ids`, |
|||
ADD COLUMN `order_id` int(11) NULL COMMENT \'审批流程步骤id\' AFTER `flow_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_contract` |
|||
ADD COLUMN `flow_id` int(11) NULL COMMENT \'审核流程ID\' AFTER `remarks`, |
|||
ADD COLUMN `order_id` int(11) NULL COMMENT \'审批流程步骤id\' AFTER `flow_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_contract` |
|||
ADD COLUMN `ratios` varchar(255) NULL DEFAULT NULL COMMENT \'业绩比例\' AFTER `order_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_contract` ADD COLUMN `business_id` int(11) NULL COMMENT \'商机ID\' AFTER `order_staff_id`; |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_contract` |
|||
ADD COLUMN `ratio_id` int(11) NULL COMMENT \'绩效ID\' AFTER `order_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_customer` |
|||
ADD COLUMN `ro_staff_id` varchar(255) NULL DEFAULT \'\' COMMENT \'只读权限\' AFTER `owner_staff_id`, |
|||
ADD COLUMN `rw_staff_id` varchar(255) NULL DEFAULT \'\' COMMENT \'读写权限\' AFTER `ro_staff_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_customer` MODIFY COLUMN `address_detail` varchar(255) NULL DEFAULT NULL COMMENT \'详细地址\' AFTER `address`; |
|||
ALTER TABLE `__PREFIX__qingdong_customer` MODIFY COLUMN `remarks` text NULL COMMENT \'备注信息\' AFTER `lat`; |
|||
ALTER TABLE `__PREFIX__qingdong_file` |
|||
MODIFY COLUMN `types` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT \'类型(file、image)\' AFTER `id`; |
|||
ALTER TABLE `__PREFIX__qingdong_flow` |
|||
ADD COLUMN `status` tinyint(1) DEFAULT NULL COMMENT \'1 固定审批 0 授权审批\' AFTER `examine_ids`, |
|||
ADD COLUMN `remark` varchar(255) DEFAULT NULL COMMENT \'备注\' AFTER `status`, |
|||
ADD COLUMN `relation_type` varchar(255) DEFAULT NULL COMMENT \'关联类型\' AFTER `remark`, |
|||
ADD COLUMN `group_ids` varchar(255) DEFAULT NULL COMMENT \'关联角色组\' AFTER `relation_type`, |
|||
ADD COLUMN `weight` tinyint(4) DEFAULT NULL COMMENT \'权重\' AFTER `group_ids`, |
|||
ADD COLUMN `last_modified` int(11) DEFAULT NULL COMMENT \'最后修改时间\' AFTER `weight`, |
|||
ADD COLUMN `last_admin_id` int(11) DEFAULT NULL COMMENT \'最后修改人\' AFTER `last_modified`, |
|||
ADD COLUMN `deletetime` int(11) DEFAULT NULL AFTER `updatetime`; |
|||
ALTER TABLE `__PREFIX__qingdong_form_approval` |
|||
ADD COLUMN `examine_ids` text COMMENT \'默认审核人id\' AFTER `form_id`, |
|||
ADD COLUMN `status` tinyint(1) DEFAULT NULL COMMENT \'1 固定审批 0 授权审批\' AFTER `examine_ids`; |
|||
ALTER TABLE `__PREFIX__qingdong_product` |
|||
ADD COLUMN `cost_price` decimal(10,2) DEFAULT NULL COMMENT \'成本价\' AFTER `min_price`, |
|||
MODIFY COLUMN `description` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT \'产品描述\' AFTER `status`; |
|||
ALTER TABLE `__PREFIX__qingdong_product_part` |
|||
MODIFY COLUMN `description` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT \'产品描述\' AFTER `img`; |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_receivables` |
|||
ADD COLUMN `flow_id` int(11) NULL COMMENT \'审核流程ID\' AFTER `check_status`, |
|||
ADD COLUMN `order_id` int(11) NULL COMMENT \'审批流程步骤id\' AFTER `flow_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_staff_sign_in` ADD COLUMN `other` text NULL COMMENT \'表单信息\' AFTER `file_ids`; |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_customer` ADD COLUMN `seas_id` varchar(128) NULL DEFAULT NULL COMMENT \'所属公海\' AFTER `parent_id`; |
|||
ALTER TABLE `__PREFIX__qingdong_staff` MODIFY COLUMN `role` int(11) NULL DEFAULT NULL COMMENT \'角色id\' AFTER `group_ids`; |
|||
ALTER TABLE `__PREFIX__qingdong_customer` ADD COLUMN `sea_time` int(11) NULL COMMENT \'放入公海时间\' AFTER `rw_staff_id`; |
|||
INSERT INTO `__PREFIX__qingdong_seas_type` VALUES (1, \'默认公海\', \'客户不满足其他公海规则时,会移入当前公海\', NULL, NULL, NULL, NULL); |
|||
|
|||
INSERT INTO `__PREFIX__qingdong_staff_rule` VALUES (1, \'menus\', 0, \'seas\', \'公海客户\', \'\', 1, \'\'); |
|||
INSERT INTO `__PREFIX__qingdong_staff_rule` VALUES (2, \'data\', 1, 1, \'默认公海\', \'\', 0, \'\'); |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_notice_template` |
|||
MODIFY COLUMN `data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT \'微信公众号\' AFTER `type`, |
|||
ADD COLUMN `wechat` text NULL COMMENT \'企业微信\' AFTER `data`, |
|||
ADD COLUMN `createtime` int(11) NULL COMMENT \'创建时间\' AFTER `wechat`, |
|||
ADD COLUMN `updatetime` int(11) NULL COMMENT \'修改时间\' AFTER `createtime`, |
|||
ADD COLUMN `deletetime` int(11) NULL COMMENT \'删除时间\' AFTER `updatetime`; |
|||
ALTER TABLE `__PREFIX__qingdong_staff` |
|||
ADD COLUMN `touser` varchar(50) NULL COMMENT \'企业微信userid\' AFTER `wx_openid`; |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_leads` |
|||
ADD COLUMN `receive_time` int(11) NULL COMMENT \'分配时间\' AFTER `follow`; |
|||
|
|||
ALTER TABLE `__PREFIX__qingdong_notice_template` |
|||
ADD COLUMN `enterprise_data` text NULL COMMENT \'企业微信通知\' AFTER `data`; |
|||
ALTER TABLE `__PREFIX__qingdong_product` |
|||
ADD COLUMN `goods_id` int(11) NULL DEFAULT NULL COMMENT \'商品ID\' AFTER `id`, |
|||
ADD COLUMN `type` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT \'规格\' AFTER `name`; |
|||
ALTER TABLE `__PREFIX__qingdong_product_type` |
|||
ADD COLUMN `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT \'内容\' AFTER `image`, |
|||
ADD COLUMN `status` tinyint(1) NULL DEFAULT NULL COMMENT \'状态\' AFTER `content`; |
|||
ALTER TABLE `__PREFIX__qingdong_record` |
|||
ADD COLUMN `location` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT \'定位信息\' AFTER `deletetime`, |
|||
ADD COLUMN `lng` double(16, 12) NULL DEFAULT NULL COMMENT \'地理位置经度\' AFTER `location`, |
|||
ADD COLUMN `lat` double(16, 12) NULL DEFAULT NULL COMMENT \'地理位置维度\' AFTER `lng`; |
|||
|
|||
', |
|||
); |
|||
File diff suppressed because it is too large
@ -0,0 +1,361 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Achievement as AchievementModel; |
|||
use addons\qingdong\model\AchievementRecords; |
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\Flow; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\StaffDepartment; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 业绩管理接口 |
|||
*/ |
|||
class Achievement extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
/** |
|||
* 部门列表 |
|||
*/ |
|||
public function getDepartment() { |
|||
$department = StaffDepartment::where([])->field('id,name')->select(); |
|||
$department = array_merge([['id' => 0, 'name' => '全部']], $department); |
|||
|
|||
$this->success('请求成功', ['department' => $department, 'years' => getYears()]); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取员工业绩目标 |
|||
*/ |
|||
public function getStaffList() { |
|||
$department_id = input('department_id'); |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1); |
|||
$where = []; |
|||
if ($department_id) { |
|||
$where['department_id'] = $department_id; |
|||
} |
|||
$where['status'] = 1; |
|||
$staffModel = new Staff(); |
|||
$staffs = $staffModel->where($where)->field('id,name,img,post')->with([ |
|||
'achievement' => function ($query) use ($year, $status) { |
|||
$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id'); |
|||
}, |
|||
'department' |
|||
])->select(); |
|||
|
|||
foreach ($staffs as $k => $v) { |
|||
if (empty($v['achievement'])) { |
|||
$v['achievement'] = ['yeartarget' => 0]; |
|||
} |
|||
$staffs[$k] = $v; |
|||
} |
|||
|
|||
$this->success('请求成功', $staffs); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取部门业绩列表 |
|||
*/ |
|||
public function getDepartmentList() { |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1); |
|||
|
|||
$departmentModel = new StaffDepartment(); |
|||
$staffs = $departmentModel->where([])->field('id,name')->with([ |
|||
'achievement' => function ($query) use ($year, $status) { |
|||
$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id'); |
|||
}, |
|||
])->select(); |
|||
|
|||
foreach ($staffs as $k => $v) { |
|||
if (empty($v['achievement'])) { |
|||
$v['achievement'] = ['yeartarget' => 0]; |
|||
} |
|||
$staffs[$k] = $v; |
|||
} |
|||
|
|||
$this->success('请求成功', $staffs); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取团队业绩 |
|||
*/ |
|||
public function getTeamList() { |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1); |
|||
|
|||
$staffModel = new Staff(); |
|||
//1最高管理员 2公司管理员 3部门经理 4部门主管 5组长 6员工 |
|||
$staffs = $staffModel->where([ |
|||
'role' => ['in', [1, 2, 3, 4, 5]] |
|||
])->field('id,name,img,post')->with([ |
|||
'teamAchievement' => function ($query) use ($year, $status) { |
|||
//团队 |
|||
$query->where(['year' => $year, 'status' => $status])->field('yeartarget,obj_id'); |
|||
}, |
|||
])->select(); |
|||
$staffs = collection($staffs)->toArray(); |
|||
foreach ($staffs as $k => $v) { |
|||
$v['achievement'] = $v['team_achievement'] ?? ['yeartarget' => 0]; |
|||
unset($v['team_achievement']); |
|||
$staffs[$k] = $v; |
|||
} |
|||
|
|||
$this->success('请求成功', $staffs); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取公司目标 |
|||
*/ |
|||
public function getCompanyAchievement() { |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1);//1销售(目标)2回款(目标) |
|||
$model = new AchievementModel(); |
|||
$achievements = $model->where([ |
|||
'type' => 1, |
|||
'obj_id' => 1, |
|||
'year' => $year, |
|||
'status' => $status |
|||
])->find(); |
|||
if (empty($achievements)) { |
|||
$model->save(['type' => 1, 'year' => $year, 'status' => $status]); |
|||
$achievements = $model->where(['type' => 1, 'year' => $year, 'status' => $status])->find(); |
|||
} |
|||
|
|||
$this->success('请求成功', $achievements); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取目标 |
|||
*/ |
|||
public function getMyAchievementDetail() { |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1);//1销售(目标)2回款(目标) |
|||
|
|||
$model = new AchievementModel(); |
|||
$row = $model->where([ |
|||
'obj_id' => $this->auth->id, |
|||
'type' => 3, |
|||
'year' => $year, |
|||
'status' => $status |
|||
])->find(); |
|||
$this->success('请求成功', $row); |
|||
} |
|||
|
|||
/** |
|||
* 获取目标详情 |
|||
*/ |
|||
public function getAchievementDetail() { |
|||
$type = input('type'); |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1);//1销售(目标)2回款(目标) |
|||
$ids = input('ids'); |
|||
if (empty($ids)) { |
|||
$this->error('参数不能为空'); |
|||
} |
|||
$ids = explode(',', $ids); |
|||
$model = new AchievementModel(); |
|||
$row = $model->where([ |
|||
'obj_id' => $ids[0], |
|||
'type' => $type, |
|||
'year' => $year, |
|||
'status' => $status |
|||
])->find(); |
|||
$this->success('请求成功', $row); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加或修改目标 |
|||
*/ |
|||
public function addAchievement() { |
|||
$type = input('type'); |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1);//1销售(目标)2回款(目标) |
|||
$achievements = input('achievements/a'); |
|||
$ids = input('ids'); |
|||
$yeartarget = input('yeartarget',0); |
|||
$model = new AchievementModel(); |
|||
$ids = explode(',', $ids); |
|||
$insertAll = []; |
|||
foreach ($ids as $id) { |
|||
$insertAll[] = [ |
|||
'type' => $type, |
|||
'year' => $year, |
|||
'status' => $status, |
|||
'obj_id' => $id, |
|||
'january' => $achievements['january'] ?? 0, |
|||
'february' => $achievements['february'] ?? 0, |
|||
'march' => $achievements['march'] ?? 0, |
|||
'april' => $achievements['april'] ?? 0, |
|||
'june' => $achievements['june'] ?? 0, |
|||
'may' => $achievements['may'] ?? 0, |
|||
'july' => $achievements['july'] ?? 0, |
|||
'august' => $achievements['august'] ?? 0, |
|||
'september' => $achievements['september'] ?? 0, |
|||
'october' => $achievements['october'] ?? 0, |
|||
'november' => $achievements['november'] ?? 0, |
|||
'december' => $achievements['december'] ?? 0, |
|||
'yeartarget' => $yeartarget, |
|||
'createtime' => time(), |
|||
'updatetime' => time() |
|||
]; |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$model->where([ |
|||
'obj_id' => ['in', $ids], |
|||
'type' => $type, |
|||
'year' => $year, |
|||
'status' => $status |
|||
])->delete(); |
|||
|
|||
if ($model->insertAll($insertAll) == false) { |
|||
throw new Exception('提交失败'); |
|||
} |
|||
Db::commit();; |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
$this->success('提交成功!'); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取目标详情 |
|||
*/ |
|||
public function staffEditAchievement() { |
|||
$type = 3;//员工 |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1);//1销售(目标)2回款(目标) |
|||
$achievements = input('achievements/a'); |
|||
$flow_staff_id = input('flow_staff_ids'); |
|||
$yeartarget = input('yeartarget',0); |
|||
|
|||
$model = new AchievementRecords(); |
|||
$id = $this->auth->id; |
|||
$params = [ |
|||
'type' => $type, |
|||
'year' => $year, |
|||
'status' => $status, |
|||
'obj_id' => $id, |
|||
'january' => $achievements['january'] ?? 0, |
|||
'february' => $achievements['february'] ?? 0, |
|||
'march' => $achievements['march'] ?? 0, |
|||
'april' => $achievements['april'] ?? 0, |
|||
'june' => $achievements['june'] ?? 0, |
|||
'may' => $achievements['may'] ?? 0, |
|||
'july' => $achievements['july'] ?? 0, |
|||
'august' => $achievements['august'] ?? 0, |
|||
'september' => $achievements['september'] ?? 0, |
|||
'october' => $achievements['october'] ?? 0, |
|||
'november' => $achievements['november'] ?? 0, |
|||
'december' => $achievements['december'] ?? 0, |
|||
'flow_staff_ids' => $flow_staff_id, |
|||
'owner_staff_id'=> $this->auth->id, |
|||
'check_status' => 0, |
|||
'yeartarget' => $yeartarget, |
|||
'createtime' => time(), |
|||
'updatetime' => time() |
|||
]; |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
|
|||
$flow = Flow::getsteplist(Flow::ACHIEVEMENT_STATUS); |
|||
$params['flow_id'] = $flow['flow_id']; |
|||
$params['order_id'] = $flow['order_id']; |
|||
|
|||
if ($flow['status'] == 0) {//发起人自选 |
|||
if (empty($params['flow_staff_ids'])) { |
|||
throw new Exception('审批人必须选择'); |
|||
} |
|||
$params['flow_staff_ids'] = trim($params['flow_staff_ids']); |
|||
} else { |
|||
if (empty($flow['flow_staff_ids'])) { |
|||
throw new Exception('没有直属上级无法审批,请联系管理员!'); |
|||
} |
|||
$params['flow_staff_ids'] = trim($flow['flow_staff_ids']); |
|||
} |
|||
|
|||
if ($model->insert($params) === false) { |
|||
throw new Exception('添加失败'); |
|||
} |
|||
$lastId = $model->getLastInsID(); |
|||
|
|||
if ($flow['status'] == 1) {//固定审批 |
|||
//发送审批通知 |
|||
Flow::sendStepRecord($flow,Flow::ACHIEVEMENT_STATUS, $lastId); |
|||
} else {//发起人自选 依次审批 |
|||
$staff_id = explode(',', $params['flow_staff_ids'])[0]; |
|||
if ($staff_id) { |
|||
ExamineRecord::addExaminse(ExamineRecord::ACHIEVEMENT_TYPE, $lastId, $staff_id); |
|||
} |
|||
} |
|||
Db::commit();; |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
$this->success('提交成功,等待审核!'); |
|||
} |
|||
|
|||
/** |
|||
* 员工自己修改目标 |
|||
*/ |
|||
public function editRecords(){ |
|||
$department_id = input('department_id'); |
|||
$year = input('year', date('Y'), 'intval'); |
|||
$status = input('status', 1); |
|||
$limit = input("limit/d", 10); |
|||
$where = []; |
|||
if ($department_id) { |
|||
$where['department_id'] = $department_id; |
|||
} |
|||
$where['year'] = $year; |
|||
$where['status'] = $status; |
|||
|
|||
$model = new AchievementRecords(); |
|||
|
|||
$list = $model->where(['type'=>3,'obj_id'=>$this->auth->id])->where($where)->with(['staff'])->order('id desc')->paginate($limit); |
|||
|
|||
$this->success('请求成功',$list); |
|||
} |
|||
|
|||
/** |
|||
* 获取业绩详情表 |
|||
*/ |
|||
public function getRecordsDetail(){ |
|||
$id=input('id'); |
|||
$model = new AchievementRecords(); |
|||
|
|||
$records = $model->where(['id'=>$id])->with(['staff'])->find(); |
|||
if (empty($records)) { |
|||
$this->error('业绩目标不存在'); |
|||
} |
|||
|
|||
if ($records['check_status'] == 0 || $records['check_status'] == 1) { |
|||
$records['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::ACHIEVEMENT_TYPE, $id); |
|||
} else { |
|||
$records['is_examine'] = 0; |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::ACHIEVEMENT_TYPE, $id, $this->auth->id); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
} |
|||
@ -0,0 +1,216 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
|
|||
use addons\qingdong\model\Approval as ApprovalModel; |
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\File; |
|||
use addons\qingdong\model\FormApproval; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Form; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 工作审批 |
|||
*/ |
|||
class Approval extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
/** |
|||
* 审核审核记录 |
|||
*/ |
|||
public function examineApprovalList(){ |
|||
$check_status=input('check_status');//1审核中、2审核通过、3审核未通过 |
|||
$formapproval_id=input('formapproval_id');// |
|||
$times=input('times');// |
|||
$where=[]; |
|||
if($formapproval_id){ |
|||
$where['formapproval_id']=$formapproval_id; |
|||
} |
|||
if($times){ |
|||
$times = explode(',', $times); |
|||
$where['createtime']=['between',[strtotime($times[0]),strtotime($times[1])+86400-1]]; |
|||
} |
|||
if ($check_status) { |
|||
//0待审核、1审核中、2审核通过、3审核未通过、4撤销 |
|||
if ($check_status == 1) { |
|||
$where['check_status'] = ['in', [0, 1]]; |
|||
} elseif ($check_status == 2) { |
|||
$where['check_status'] = 2; |
|||
} elseif ($check_status == 3) { |
|||
$where['check_status'] = 3; |
|||
} elseif ($check_status == 4) { |
|||
$where['check_status'] = 4; |
|||
} elseif ($check_status == 9) { |
|||
$where['check_status'] = 9; |
|||
} |
|||
} |
|||
$type = input('type', 0);// 0 全部 1 我创建 2 下属创建 |
|||
if ($type == 1) {//我的客户 |
|||
$where['create_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$where['create_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
}else{ |
|||
$where['create_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
|
|||
$staff_id=$this->auth->id; |
|||
$approvals= ApprovalModel::where($where)->where(function ($query) use ($staff_id){ |
|||
$query->where('create_staff_id',$staff_id) |
|||
->whereOr('','exp', Db::raw('FIND_IN_SET(' . $staff_id. ',flow_staff_ids)')); |
|||
})->with(['createStaff','formapproval'])->order('id desc')->paginate(); |
|||
|
|||
$this->success('请求成功',$approvals); |
|||
} |
|||
|
|||
/** |
|||
* 获取工作列表 |
|||
*/ |
|||
public function getList() { |
|||
$list = FormApproval::where([])->field('id,name,img')->select(); |
|||
|
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取form表单 |
|||
*/ |
|||
public function getFormapproval() { |
|||
$id = input('id'); |
|||
$form = FormApproval::where(['id' => $id])->find(); |
|||
$staff = Staff::where(['id' => ['in',explode(',', $form['flow_staff_ids'])]])->field('id,name,img')->select(); |
|||
$forminfo = Form::where(array('id'=>$form['form_id']))->find(); |
|||
$data=json_decode($forminfo['data'], true)['data']??[]; |
|||
$this->success('请求成功',['data'=>$data,'staff'=>$staff] ); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加审批 |
|||
*/ |
|||
public function addApproval() { |
|||
$params = $this->request->post(); |
|||
if(empty( $params['data'])){ |
|||
$this->error('数据不能为空'); |
|||
} |
|||
if(empty( $params['formapproval_id'])){ |
|||
$this->error('表单id不能为空'); |
|||
} |
|||
|
|||
$result = ApprovalModel::createApproval($params); |
|||
|
|||
$this->success('保存成功'); |
|||
} |
|||
|
|||
/** |
|||
* 获取审批详情 |
|||
*/ |
|||
public function getDetail(){ |
|||
$id = input('id'); |
|||
if(empty($id)){ |
|||
$this->error('参数不能为空'); |
|||
} |
|||
$approval=ApprovalModel::where(['id'=>$id])->with(['formapproval'])->find()->toArray(); |
|||
$type = Form::where(array('id'=>$approval['formapproval']['form_id']))->value('type'); |
|||
|
|||
$form = Form::getDataValue($type,$approval['content']); |
|||
foreach($form as $k=>$v){ |
|||
if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){ |
|||
if(key_exists($v['id'],$approval['content'])){ |
|||
if(isset($approval['content'][$v['id']]) && $approval['content'][$v['id']]){ |
|||
$whereT['id'] = array('in',$approval['content'][$v['id']]); |
|||
$fileinfo = File::where($whereT)->field('id,name,file_path')->select(); |
|||
if($fileinfo){ |
|||
$approval['content'][$v['id']] = $fileinfo; |
|||
} |
|||
} |
|||
} |
|||
}elseif($v['component'] == 'select'){ |
|||
if(isset($v['config']['multiple']) && $v['config']['multiple'] == true){ |
|||
if(key_exists($v['id'],$approval['content'])){ |
|||
if(is_array($approval['content'][$v['id']]) && $approval['content'][$v['id']]){ |
|||
$approval['content'][$v['id']] = implode(',',$approval['content'][$v['id']]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if ($approval['check_status'] == 0 || $approval['check_status'] == 1) { |
|||
$approval['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::APPROVAL_TYPE, $id); |
|||
} else { |
|||
$approval['is_examine'] = 0; |
|||
} |
|||
$approval['is_operation']=0; |
|||
if($approval['create_staff_id'] == $this->auth->id){ |
|||
//是否可以操作 |
|||
$approval['is_operation']=1; |
|||
} |
|||
Message::setRead(Message::APPROVAL_TYPE,$id,$this->auth->id); |
|||
$this->success('请求成功',$approval); |
|||
} |
|||
|
|||
/** |
|||
* 修改审批 |
|||
*/ |
|||
public function editApproval(){ |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = ApprovalModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find(); |
|||
if (empty($row)) { |
|||
$this->error('审批信息不存在'); |
|||
} |
|||
if(empty( $params['data'])){ |
|||
$this->error('数据不能为空'); |
|||
} |
|||
if(empty( $params['formapproval_id'])){ |
|||
$this->error('表单id不能为空'); |
|||
} |
|||
if(empty( $params['relation_type'])){ |
|||
$this->error('关联类型不能为空'); |
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
$result = ApprovalModel::updateApproval($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('修改信息成功'); |
|||
} |
|||
|
|||
/** |
|||
* 撤回审批 |
|||
*/ |
|||
public function cancel(){ |
|||
$id = input('id'); |
|||
$customer = ApprovalModel::where(['id' => $id, 'check_status' => ['in', [0, 1]]])->find(); |
|||
if (empty($customer)) { |
|||
$this->error('信息不存在'); |
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
|
|||
ApprovalModel::where(['id' => $id])->update(['check_status' => 4]); |
|||
|
|||
ExamineRecord::cancelExaminse(ExamineRecord::APPROVAL_TYPE,$id); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback();; |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
|
|||
$this->success('撤回成功'); |
|||
} |
|||
|
|||
|
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,293 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\AdminConfig; |
|||
use addons\qingdong\model\AttendanceRule; |
|||
use addons\qingdong\model\AttendanceStatisc; |
|||
use addons\qingdong\model\AttendanceTime; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\Event; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Leads; |
|||
use addons\qingdong\model\Attendance; |
|||
use think\Db; |
|||
use think\Exception; |
|||
use think\Log; |
|||
|
|||
/** |
|||
* 定时任务 |
|||
*/ |
|||
class Autotask extends \think\addons\Controller |
|||
{ |
|||
protected $noNeedLogin = ["*"]; |
|||
protected $layout = ''; |
|||
|
|||
public function _initialize() |
|||
{ |
|||
parent::_initialize(); |
|||
|
|||
if (!$this->request->isCli()) { |
|||
$this->error('只允许在终端进行操作!'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 合同 |
|||
*/ |
|||
public function contract() |
|||
{ |
|||
$endDate = date('Y-m-d', strtotime('+3 day')); |
|||
$contracts = \addons\qingdong\model\Contract::where(['check_status' => 2, 'contract_status' => 0, 'end_time' => ['lt', $endDate]])->select(); |
|||
try { |
|||
//合同即将到期通知 |
|||
foreach ($contracts as $v) { |
|||
Message::addMessage(Message::CONTRACT_EXPIRE_TYPE, $v['id'], $v['owner_staff_id'], ''); |
|||
} |
|||
} catch (Exception $e) { |
|||
return $e->getMessage(); |
|||
} |
|||
$this->plan(); |
|||
return 'success'; |
|||
} |
|||
|
|||
/** |
|||
* 回款计划通知 |
|||
*/ |
|||
public function plan() |
|||
{ |
|||
$endDate = date('Y-m-d', strtotime('+1 day')); |
|||
//进行中 -- 待回款 |
|||
$plans = \addons\qingdong\model\ReceivablesPlan::where(['status' => 0, 'remind_date' => ['lt', $endDate]])->select(); |
|||
|
|||
try { |
|||
//回款计划即将到期通知 |
|||
foreach ($plans as $v) { |
|||
Message::addMessage(Message::PLAN_EXPIRE_TYPE, $v['contract_id'], $v['owner_staff_id'], ''); |
|||
} |
|||
} catch (Exception $e) { |
|||
return $e->getMessage(); |
|||
} |
|||
|
|||
return 'success'; |
|||
} |
|||
|
|||
/** |
|||
* 公海 |
|||
*/ |
|||
public function seas() |
|||
{ |
|||
|
|||
if (AdminConfig::getConfigValue('auto', AdminConfig::TYPE_SEAS)) {//自动回收客户 |
|||
if (AdminConfig::getConfigValue('genjing', AdminConfig::TYPE_SEAS) == 1) {//未跟进客户回收 |
|||
$day = AdminConfig::getConfigValue('genjing_day', AdminConfig::TYPE_SEAS); |
|||
$where = ['receivetime' => ['<', strtotime('-' . $day . ' day')]]; |
|||
if (AdminConfig::getConfigValue('genjing_success', AdminConfig::TYPE_SEAS) == 1) { |
|||
$where['contract_status'] = 0; |
|||
} |
|||
$customers = Customer::where($where)->field('id,name,owner_staff_id')->select(); |
|||
try { |
|||
foreach ($customers as $c) { |
|||
Customer::moveSeas($c['id']); |
|||
Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0); |
|||
} |
|||
} catch (Exception $e) { |
|||
Log::error($e->getMessage()); |
|||
} |
|||
} |
|||
if (AdminConfig::getConfigValue('chengjiao', AdminConfig::TYPE_SEAS) == 1) {//未成交客户回收 |
|||
$day = AdminConfig::getConfigValue('chengjiao_day', AdminConfig::TYPE_SEAS); |
|||
$where = [ |
|||
'receivetime' => ['<', strtotime('-' . $day . ' day')], |
|||
'contract_status' => 0 |
|||
]; |
|||
$customers = Customer::where($where)->field('id,name,owner_staff_id')->select(); |
|||
try { |
|||
foreach ($customers as $c) { |
|||
Customer::moveSeas($c['id']); |
|||
Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0); |
|||
} |
|||
} catch (Exception $e) { |
|||
Log::error($e->getMessage()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 'success'; |
|||
} |
|||
|
|||
/** |
|||
* 日程提醒 |
|||
* @return string |
|||
*/ |
|||
public function event() |
|||
{ |
|||
$endDate = date('Y-m-d H:i:s'); |
|||
$events = Event::where(['status' => 0, 'remind_time' => ['lt', $endDate]])->select(); |
|||
|
|||
$endIds = Event::where([ |
|||
'status' => ['in', [0, 1]], |
|||
'auto_end' => 1, |
|||
'end_time' => ['lt', $endDate] |
|||
])->column('id'); |
|||
|
|||
try { |
|||
//日程自动结束 |
|||
Event::where(['id' => ['in', $endIds]])->update(['status' => 2]); |
|||
|
|||
//日程时间提醒 |
|||
foreach ($events as $v) { |
|||
if (Message::where([ |
|||
'relation_type' => Message::EVENT_TYPE, |
|||
'relation_id' => $v['id'], |
|||
'to_staff_id' => $v['staff_id'] |
|||
])->count()) { |
|||
//已经提醒过了 |
|||
continue; |
|||
} |
|||
Message::addMessage(Message::EVENT_TYPE, $v['id'], $v['staff_id'], 0); |
|||
} |
|||
} catch (Exception $e) { |
|||
return $e->getMessage(); |
|||
} |
|||
return 'success'; |
|||
} |
|||
|
|||
/** |
|||
* 打卡定时任务 |
|||
*/ |
|||
public function attendance() |
|||
{ |
|||
$w = date('w'); |
|||
$date = [ |
|||
1 => 'monday', |
|||
2 => 'tuesday', |
|||
3 => 'wednesday', |
|||
4 => 'thursday', |
|||
5 => 'friday', |
|||
6 => 'saturday', |
|||
0 => 'weekday', |
|||
]; |
|||
$weekname = $date[$w]; |
|||
$times = AttendanceTime::where([$weekname => 1])->select(); |
|||
if (empty($times)) { |
|||
return '未设置规则'; |
|||
} |
|||
$row = AttendanceStatisc::where(['time' => date('Y-m-d')])->find(); |
|||
if (!empty($row)) { |
|||
return '规则已生成'; |
|||
} |
|||
$times = collection($times)->toArray(); |
|||
$rule = AttendanceRule::where([])->find(); |
|||
|
|||
$statiscs = AttendanceStatisc::where(['time' => date('Y-m-d', strtotime('-1 day'))])->select(); |
|||
foreach ($statiscs as $v) { |
|||
$update = []; |
|||
if (empty($t['clock_in']) && !empty($t['clock_out'])) {//缺卡 |
|||
$update['clock_in_status'] = 1; |
|||
} |
|||
if (empty($t['clock_out']) && !empty($t['clock_in'])) {//缺卡 |
|||
$update['clock_out_status'] = 1; |
|||
} |
|||
if (empty($t['clock_in']) && empty($t['clock_out'])) {//旷工 |
|||
$update['clock_in_status'] = 2; |
|||
$update['clock_out_status'] = 2; |
|||
} |
|||
if ($update) { |
|||
$statiscModel = new AttendanceStatisc(); |
|||
$statiscModel->save($update, ['id' => $v['id']]); |
|||
} |
|||
|
|||
} |
|||
$staff_ids = explode(',', $rule['staff_id']); |
|||
|
|||
$statisc = []; |
|||
foreach ($staff_ids as $sid) { |
|||
foreach ($times as $t) { |
|||
$statisc[] = [ |
|||
'staff_id' => $sid, |
|||
'number' => $t['number'], |
|||
'time' => date('Y-m-d'), |
|||
'start_time' => $t['start_time'], |
|||
'end_time' => $t['end_time'], |
|||
'ustart_time' => $t['ustart_time'], |
|||
'uend_time' => $t['uend_time'], |
|||
'dstart_time' => $t['dstart_time'], |
|||
'dend_time' => $t['dend_time'], |
|||
'start_status' => $t['start_status'], |
|||
'end_status' => $t['end_status'], |
|||
]; |
|||
} |
|||
} |
|||
$statiscModel = new AttendanceStatisc(); |
|||
$result = $statiscModel->allowField(true)->saveAll($statisc); |
|||
if (empty($result)) { |
|||
return '生成规则失败'; |
|||
} |
|||
return '生成规则成功'; |
|||
} |
|||
|
|||
/* |
|||
* 线索池分配 |
|||
*/ |
|||
public function leadpool(){ |
|||
if(AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD)){ |
|||
$leadauto = AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD); |
|||
$lead_day = AdminConfig::getConfigValue('lead_day', AdminConfig::TYPE_LEAD); |
|||
$attendance = AdminConfig::getConfigValue('leadcard', AdminConfig::TYPE_LEAD); |
|||
$department = AdminConfig::getConfigValue('department', AdminConfig::TYPE_LEAD); |
|||
|
|||
//开启分配 |
|||
if($leadauto == 1 && $lead_day>0 && $department){ |
|||
$leadpool = Leads::where('owner_staff_id is null or owner_staff_id = 0')->order('id desc')->limit(100)->column('id'); |
|||
if($leadpool){ |
|||
$department = explode(',',$department); |
|||
$staffinfo = array(); |
|||
foreach($department as $k=>$v){ |
|||
$staffids = Staff::where('', 'exp', Db::raw('FIND_IN_SET(' . $v . ',group_ids)'))->where(['status'=>1])->column('id'); |
|||
$staffinfo[] = $staffids; |
|||
} |
|||
if(!$staffinfo){ |
|||
return '无数据'; |
|||
} |
|||
$staffinfos =[]; |
|||
foreach($staffinfo as $k=>$v){ |
|||
foreach($v as $ks=>$vs){ |
|||
$staffinfos[] = $vs; |
|||
} |
|||
} |
|||
$staff = array_unique($staffinfos); |
|||
foreach($leadpool as $ks=>$vs){ |
|||
$stafflead =[]; |
|||
foreach($staff as $k=>$v){ |
|||
if($attendance == 1){ //打卡 |
|||
$whereC['staff_id']= $v; |
|||
$whereC['createtime'] = array(array('egt',strtotime(date('Y-m-d 00:00:00'))),array('elt',strtotime(date('Y-m-d 23:59:59')))); |
|||
$leadcard = Attendance::where($whereC)->find(); |
|||
if(!$leadcard){//未打卡不分配 |
|||
continue; |
|||
} |
|||
} |
|||
$wherelead['owner_staff_id'] = $v; |
|||
$wherelead['receive_time'] = array(array('egt',strtotime('-'.$lead_day.' days',time())),array('elt',time())); |
|||
$lead = Leads::where($wherelead)->count(); |
|||
$stafflead[] = array( |
|||
'id'=>$v, |
|||
'num'=>$lead |
|||
); |
|||
} |
|||
if($stafflead){ |
|||
$num_count = array_column($stafflead,'num');//返回数组中指定的一列 |
|||
array_multisort($num_count,SORT_ASC,$stafflead); |
|||
Leads::where(array('id'=>$vs))->update(array('owner_staff_id'=>$stafflead[0]['id'],'receive_time'=>time())); |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
} |
|||
return 'success'; |
|||
} |
|||
} |
|||
@ -0,0 +1,298 @@ |
|||
<?php |
|||
namespace addons\qingdong\controller; |
|||
use addons\qingdong\model\Business as BusinessModel; |
|||
use addons\qingdong\model\BusinessOther; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\BusinessStatus; |
|||
use addons\qingdong\model\File; |
|||
use think\Db; |
|||
use think\Exception; |
|||
/** |
|||
* 商机接口 |
|||
*/ |
|||
class Business extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//创建商机 |
|||
public function addBusiness() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
$result = FormField::checkFields(FormField::BUSINESS_TYPE, $params); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
|
|||
$result = BusinessModel::createBusiness($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加商机成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取商机列表 |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$customer_id = input('customer_id'); |
|||
$params = $this->request->post(); |
|||
|
|||
$where= FormField::updateWhereField(FormField::BUSINESS_TYPE,$params); |
|||
|
|||
if (isset($params['createtime']) && $params['createtime']) {// |
|||
$createtime = $params['createtime']; |
|||
$createtime = explode(',', $createtime); |
|||
$where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1]) + 86400 - 1]]; |
|||
} |
|||
if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选 |
|||
$where['owner_staff_id'] = $params['staff_id']; |
|||
} else { |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
if (isset($params['type']) && $params['type']) {//客户分类 |
|||
if ($params['type'] == 1) {//我的创建 |
|||
$where['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($params['type'] == 2) {//下属创建 |
|||
$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} |
|||
} |
|||
} |
|||
$wheres =[]; |
|||
if (isset($params['contract_status']) && $params['contract_status']) { |
|||
if($params['contract_status'] == 1){ |
|||
$wheres['contract_status'] = 0; |
|||
} |
|||
if($params['contract_status'] == 2){ |
|||
$wheres['contract_status'] = 1; |
|||
} |
|||
} |
|||
|
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
$records = BusinessModel::where($where)->where($wheres)->with([ |
|||
'customer', |
|||
'ownerStaff', |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
$data=[]; |
|||
foreach($records['data'] as $k=>$v){ |
|||
$types = BusinessStatus::where(array('business_id'=>$v['id']))->order('id desc')->value('type'); |
|||
if($types){ |
|||
$v['type'] = (int)$types; |
|||
}else{ |
|||
$v['type'] = 0; |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
$allMoney = BusinessModel::where($where)->where($wheres)->sum('money'); |
|||
$moneyinfo['repayment_money'] = BusinessModel::where($where)->where(array('contract_status'=>1))->sum('money'); //成交金额 |
|||
$moneyinfo['no_money'] = sprintf("%.2f",$allMoney)-sprintf("%.2f",$moneyinfo['repayment_money']);//未成交金额 |
|||
$moneyinfo['allmoney'] = $allMoney;//合同总金额 |
|||
$this->success('请求成功', ['moneyinfo' => $moneyinfo, 'total' => $records['total'], 'per_page' => $records['per_page'], 'current_page' => $records['current_page'], 'last_page' => $records['last_page'], 'data' => $data]); |
|||
|
|||
} |
|||
|
|||
//获取商机详情 |
|||
public function getDetail() |
|||
{ |
|||
$id = input('id'); |
|||
$contract = BusinessModel::where(['id' => $id])->with([ |
|||
'customer', |
|||
'ownerStaff', |
|||
'product', |
|||
])->find(); |
|||
if (empty($contract)) { |
|||
$this->error('商机不存在'); |
|||
} |
|||
$contract = $contract->toArray(); |
|||
$contract = BusinessOther::getOther($contract); |
|||
$type = BusinessStatus::where(array('business_id'=>$contract['id']))->order('id desc')->value('type'); |
|||
$contract['type'] = $type ? (int)$type : 0; |
|||
//产品删除不显示 |
|||
if(isset($contract['product']) && $contract['product']){ |
|||
foreach($contract['product'] as $k=>$v){ |
|||
if(!$v['name'] && !$v['num']){ |
|||
unset($contract['product'][$k]); |
|||
} |
|||
} |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::BUSINESS_TYPE, $id, $this->auth->id); |
|||
|
|||
$this->success('请求成功', $contract); |
|||
} |
|||
|
|||
//修改商机 |
|||
public function editBusiness() |
|||
{ |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = BusinessModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('商机信息不存在'); |
|||
} |
|||
|
|||
$result = FormField::checkFields(FormField::BUSINESS_TYPE, $params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = BusinessModel::updateBusiness($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('修改商机成功'); |
|||
} |
|||
|
|||
/** |
|||
* 转移商机 |
|||
*/ |
|||
public function batch_change() |
|||
{ |
|||
$ids = input('id'); |
|||
$staff_id = input('owner_staff_id'); |
|||
if(!$ids || !$staff_id){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$ids = BusinessModel::where([ |
|||
'id' => $ids |
|||
])->column('id'); |
|||
if (empty($ids)) { |
|||
$this->error('商机不存在'); |
|||
} |
|||
$result = BusinessModel::batchTransfer($ids, $staff_id); |
|||
if(!$result){ |
|||
$this->error('操作失败'); |
|||
} |
|||
$this->success('操作成功'); |
|||
} |
|||
//删除商机 |
|||
public function delete() |
|||
{ |
|||
$ids = input('id'); |
|||
if(!$ids){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$data = BusinessModel::where([ |
|||
'id' => $ids |
|||
])->column('id'); |
|||
if (empty($data)) { |
|||
$this->error('商机不存在'); |
|||
} |
|||
$result = BusinessModel::where(array('id'=>$ids))->update(array('updatetime'=>time(),'deletetime'=>time())); |
|||
if(!$result){ |
|||
$this->error('删除失败'); |
|||
} |
|||
$this->success('删除成功'); |
|||
} |
|||
//关联商机列表 |
|||
public function business_list(){ |
|||
$ids = input('customer_id'); |
|||
if(!$ids){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$data= BusinessModel::where(['customer_id'=>$ids,'owner_staff_id'=>['in',Staff::getMyStaffIds()]])->field('id,name')->select(); |
|||
|
|||
$this->success('请求成功',$data); |
|||
} |
|||
//商机合同 |
|||
public function contract(){ |
|||
$limit = input("limit/d", 10); |
|||
$ids = input('id'); |
|||
if(!$ids){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$contract = Contract::where(array('business_id'=>$ids))->with([ |
|||
'customer', |
|||
'contacts', |
|||
'ownerStaff', |
|||
'orderStaff', |
|||
'receivables' |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
$data = isset($contract['data'])?$contract['data']:[]; |
|||
if($data){ |
|||
foreach ($data as $k => $v) { |
|||
if (empty($v['receivables'])) { |
|||
$v['receivables'] = [ |
|||
'repayment_money' => 0, |
|||
'be_money' => $v['money'], |
|||
'ratio' => 0 |
|||
]; |
|||
} else { |
|||
$be_money = $v['money'] - $v['receivables']['repayment_money']; |
|||
$be_money = ($be_money > 0) ? $be_money : 0; |
|||
$v['receivables'] = [ |
|||
'repayment_money' => $v['receivables']['repayment_money'], |
|||
'be_money' =>$be_money, |
|||
'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2) |
|||
]; |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
} |
|||
$this->success('请求成功', ['total' => $contract['total'], 'per_page' => $contract['per_page'], 'current_page' => $contract['current_page'], 'last_page' => $contract['last_page'], 'data' => $data]); |
|||
|
|||
} |
|||
//商机状态 |
|||
public function business_status(){ |
|||
$id = input('id'); |
|||
$type = input('type',0); |
|||
$remark = input('remark'); |
|||
$file = input('file'); |
|||
if(!$id){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$data = array( |
|||
'id'=>$id, |
|||
'type'=>$type, |
|||
'remark'=>$remark, |
|||
'file'=>$file, |
|||
); |
|||
$business =BusinessModel::batchStatus($data); |
|||
if(!$business){ |
|||
$this->error('操作失败'); |
|||
} |
|||
$this->success('操作成功'); |
|||
} |
|||
//商机历史 |
|||
public function business_history(){ |
|||
$id = input('id'); |
|||
if(!$id){ |
|||
$this->error('参数不正确'); |
|||
} |
|||
$business = BusinessStatus::where(array('business_id'=>$id))->order('id desc')->select(); |
|||
foreach($business as $k=>$v){ |
|||
$business[$k]['createtime'] = date('Y-m-d H:i:s',$v['createtime']); |
|||
if($v['file']){ |
|||
$business[$k]['file'] = File::where(array('id'=>['in',$v['file']]))->field('id,types,name,save_name,size,file_path')->select(); |
|||
} |
|||
} |
|||
$this->success('请求成功',$business); |
|||
} |
|||
//查询商机列表 |
|||
public function get_select_list(){ |
|||
$limit = input("limit/d", 10); |
|||
$params = $this->request->post(); |
|||
$where = []; |
|||
if(isset($params['name']) && $params['name']){ |
|||
$where['name'] = array('like','%'.$params['name'].'%'); |
|||
} |
|||
$data= BusinessModel::where(['owner_staff_id'=>['in',Staff::getMyStaffIds()]])->where($where)->field('id,name')->order('id desc')->paginate($limit)->toArray();; |
|||
$this->success('请求成功',$data); |
|||
} |
|||
} |
|||
@ -0,0 +1,172 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
use addons\qingdong\model\AdminConfig; |
|||
use addons\qingdong\model\FormField; |
|||
use app\common\library\Upload; |
|||
use app\common\exception\UploadException; |
|||
use app\common\model\Area; |
|||
use addons\qingdong\model\Field; |
|||
use addons\qingdong\model\Form; |
|||
use app\common\model\Version; |
|||
use think\Config; |
|||
use think\Hook; |
|||
|
|||
/** |
|||
* * 操作文档:https://doc.fastadmin.net/qingdong |
|||
* 软件介绍:https://www.fastadmin.net/store/qingdong.html |
|||
* 售后微信:qingdong_crm |
|||
* 公共接口 |
|||
*/ |
|||
class Common extends StaffApi { |
|||
protected $noNeedLogin = ['init','getConfig']; |
|||
protected $noNeedRight = '*'; |
|||
|
|||
|
|||
/** |
|||
* 加载初始化 |
|||
* @param string $version 版本号 |
|||
* @param string $lng 经度 |
|||
* @param string $lat 纬度 |
|||
*/ |
|||
public function init() { |
|||
if ($version = $this->request->request('version')) { |
|||
$lng = $this->request->request('lng'); |
|||
$lat = $this->request->request('lat'); |
|||
|
|||
//配置信息 |
|||
$upload = Config::get('upload'); |
|||
//如果非服务端中转模式需要修改为中转 |
|||
if ($upload['storage'] != 'local' && isset($upload['uploadmode']) && $upload['uploadmode'] != 'server') { |
|||
//临时修改上传模式为服务端中转 |
|||
set_addon_config($upload['storage'], ["uploadmode" => "server"], false); |
|||
|
|||
$upload = \app\common\model\Config::upload(); |
|||
// 上传信息配置后 |
|||
Hook::listen("upload_config_init", $upload); |
|||
|
|||
$upload = Config::set('upload', array_merge(Config::get('upload'), $upload)); |
|||
} |
|||
|
|||
$upload['cdnurl'] = $upload['cdnurl'] ? $upload['cdnurl'] : cdnurl('', true); |
|||
$upload['uploadurl'] = preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $upload['uploadurl']) ? $upload['uploadurl'] : url($upload['storage'] == 'local' ? '/api/common/upload' : $upload['uploadurl'], '', false, true); |
|||
|
|||
$content = [ |
|||
'citydata' => Area::getCityFromLngLat($lng, $lat), |
|||
'versiondata' => Version::check($version), |
|||
'uploaddata' => $upload, |
|||
'coverdata' => Config::get("cover"), |
|||
]; |
|||
$this->success('', $content); |
|||
} else { |
|||
$this->error(__('Invalid parameters')); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 上传文件 |
|||
* @ApiMethod (POST) |
|||
* @param File $file 文件流 |
|||
*/ |
|||
public function upload() { |
|||
|
|||
$attachment = null; |
|||
//默认普通上传文件 |
|||
$file = $this->request->file('file'); |
|||
$name = input('name',''); |
|||
try { |
|||
$upload = new Upload($file); |
|||
$attachment = $upload->upload(); |
|||
$info = $attachment->toArray(); |
|||
$file = new \addons\qingdong\model\File(); |
|||
$params = [ |
|||
'name' => $name ? $name :$info['filename'], |
|||
'save_name' => $info['url'], |
|||
'size' => isset($info['filesize']) ? $info['filesize'] : 0, |
|||
'types' => $info['mimetype'], |
|||
'file_path' => $info['url'], |
|||
'create_staff_id' => empty($staff)?0:$staff->id, |
|||
]; |
|||
$file->data(array_filter($params)); |
|||
$file->save(); |
|||
$fileId = $file->id; |
|||
|
|||
} catch (UploadException $e) { |
|||
return json_encode(['code' => 0, 'msg' => $e->getMessage()]); |
|||
} |
|||
$this->success(__('Uploaded successful'), [ |
|||
'id' => $fileId, |
|||
'flie_url' => $params['file_path'], |
|||
'url' => cdnurl($params['file_path'], true) |
|||
]); |
|||
} |
|||
|
|||
|
|||
//select 字段表 |
|||
public function selectOption() { |
|||
|
|||
$fields = Field::where([])->select(); |
|||
$data = []; |
|||
foreach ($fields as $v) { |
|||
$data[$v['name']] = json_decode($v['data'],true); |
|||
} |
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
|
|||
//获取form表单 |
|||
public function getForm() { |
|||
$type = input('type', 'leads');//leads 线索 customer 客户 contacts 联系人 contract 合同 examine回款 product产品 |
|||
$form = Form::where(['type' => $type])->find(); |
|||
|
|||
$this->success('请求成功', json_decode($form['data'], true)); |
|||
} |
|||
|
|||
|
|||
//获取员工 |
|||
public function getSelectStaff() { |
|||
$name = input('name'); |
|||
$where = ['status' => 1]; |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
|
|||
$staffs = \addons\qingdong\model\Staff::where($where)->with(['department'])->field('id,name,department_id,nickname,post,img')->select(); |
|||
|
|||
$this->success('请求成功', $staffs); |
|||
} |
|||
|
|||
/** |
|||
* 获取后台配置 |
|||
*/ |
|||
public function getConfig(){ |
|||
$config=get_addon_config('qingdong'); |
|||
$data=[ |
|||
'map_key'=>AdminConfig::getConfigValue('map_key','wechat'), |
|||
'appid'=>AdminConfig::getConfigValue('appid','wechat'), |
|||
'mobile_name'=>$config['mobile_name']??'CRM' |
|||
]; |
|||
$this->success('请求成功',$data); |
|||
} |
|||
|
|||
/** |
|||
* 获取时间 |
|||
*/ |
|||
public function getTimes() |
|||
{ |
|||
$times = input('times'); |
|||
$times = setTimes($times, 'date'); |
|||
$this->success('请求成功', ['times' => $times]); |
|||
} |
|||
|
|||
/** |
|||
* 获取搜索字段 |
|||
*/ |
|||
public function getSearchFields(){ |
|||
$type=input('type');//leads |
|||
$fields=FormField::where(['types'=>$type,'field'=>['like',"main_%"],'list_show'=>1,'info_type'=>'main'])->select(); |
|||
$this->success('请求成功',$fields); |
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\Consume as ConsumeModel; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\File; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 费用接口 |
|||
*/ |
|||
class Consume extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//添加费用 |
|||
public function addConsume() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = ConsumeModel::createConsume($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加费用成功'); |
|||
} |
|||
} |
|||
|
|||
//编辑费用 |
|||
public function editConsume() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = ConsumeModel::updateConsume($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加费用成功'); |
|||
} |
|||
} |
|||
|
|||
//获取费用列表 |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$customer_id = input('customer_id', '', 'intval'); |
|||
$times = input('times', ''); |
|||
$status = input('check_status',0); |
|||
$where = []; |
|||
|
|||
$params = $this->request->post(); |
|||
if ($times) {// |
|||
$times = explode(',', $times); |
|||
$where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]]; |
|||
} |
|||
if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选 |
|||
$where['staff_id'] = $params['staff_id']; |
|||
} else { |
|||
$where['staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
if (isset($params['type']) && $params['type']) {//客户分类 |
|||
if ($params['type'] == 1) {//我的客户 |
|||
$where['staff_id'] = $this->auth->id; |
|||
} elseif ($params['type'] == 2) {//下属负责的客户 |
|||
$where['staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ($status) { |
|||
if($status == 1){//待审核 |
|||
$where['check_status']=['in',[0,1]]; |
|||
}elseif($status == 2){//通过 |
|||
$where['check_status']=2; |
|||
}elseif($status == 3){//审核拒绝 |
|||
$where['contract_status']=['in',[3,4]]; |
|||
} |
|||
} |
|||
if($customer_id){ |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
$records = ConsumeModel::where($where)->with(['staff','customer'])->order('id desc')->paginate($limit)->toArray(); |
|||
$remoney = ConsumeModel::where(['staff_id'=>$where['staff_id']]) |
|||
->where(array('check_status'=>2))->sum('money'); |
|||
$inmoney = ConsumeModel::where(['staff_id'=>$where['staff_id']]) |
|||
->where(array('check_status'=>['in',[0,1]]))->sum('money'); |
|||
$nomoney = ConsumeModel::where(['staff_id'=>$where['staff_id']]) |
|||
->where(array('check_status'=>['in',[3,4]]))->sum('money'); |
|||
$moneyinfo['remoney'] = $remoney;//已回款 |
|||
$moneyinfo['inmoney'] = $inmoney;//回款中 |
|||
$moneyinfo['nomoney'] = $nomoney;//未回款 |
|||
$moneyinfo['allmoney'] = $remoney+$inmoney+$nomoney;//总金额 |
|||
$records['moneyinfo']=$moneyinfo; |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取费用详情 |
|||
public function getDetail() |
|||
{ |
|||
$id = input('id', '', 'intval'); |
|||
$consume = ConsumeModel::where(['id' => $id])->with(['staff','customer'])->find(); |
|||
if(empty($consume)){ |
|||
$this->error('数据不存在'); |
|||
} |
|||
$consume['files'] = File::where(['id' => ['in', explode(',', $consume['file_ids'])]])->field('id,types,name,file_path')->select(); |
|||
|
|||
if ($consume['check_status'] == 0 || $consume['check_status'] == 1) { |
|||
$consume['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::CONSUME_TYPE, $id); |
|||
} else { |
|||
$consume['is_examine'] = 0; |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::CONSUME_TYPE, $id, $this->auth->id); |
|||
|
|||
$this->success('请求成功', $consume); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Contacts as ContactsModel; |
|||
use addons\qingdong\model\ContactsFile; |
|||
use addons\qingdong\model\ContactsOther; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\Record; |
|||
use addons\qingdong\model\Event as EventModel; |
|||
use addons\qingdong\model\OperationLog; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 联系人接口 |
|||
*/ |
|||
class Contacts extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//创建联系人 |
|||
public function addContacts() { |
|||
$params = $this->request->post(); |
|||
if (empty($params['contacts'])) { |
|||
$this->error('联系人信息不能为空'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params['contacts'], get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CONTACTS_TYPE,$params['contacts']); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (ContactsModel::where([ |
|||
'mobile' => $params['contacts']['mobile'], |
|||
'customer_id' => $params['contacts']['customer_id'] |
|||
])->find()) { |
|||
$this->error('联系人手机号已存在'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$mobile =$params['contacts']['mobile']; |
|||
$email =$params['contacts']['email']??''; |
|||
if(empty($mobile) && empty($email)){ |
|||
$this->error('手机号码和邮箱至少填写一项!'); |
|||
} |
|||
$rule = '^1(3|4|5|7|8)[0-9]\d{8}$^'; |
|||
$rule2 = '^[0-9]+$^'; |
|||
if (preg_match($rule, $mobile) == false && preg_match($rule2, $mobile) ==false) { |
|||
$this->error('手机号格式错误,国外手机号请填写区号,例如 86XXXX'); |
|||
} |
|||
|
|||
$contactsId = ContactsModel::createContacts($params['contacts']); |
|||
if (isset($params['is_event']) && $params['is_event'] == 1) {//跟进任务 |
|||
$event = $params['event']; |
|||
$event['type'] = 2;//任务 |
|||
$event['relation_type'] = EventModel::CONTACTS_TYPE;//联系人 |
|||
$event['relation_id'] = $contactsId; |
|||
$event['end_time'] = $event['start_time']; |
|||
$event['level'] = 1; |
|||
$result = EventModel::createEvent($event); |
|||
} |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('创建联系人成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//编辑联系人 |
|||
public function editContacts() { |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = ContactsModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('客户信息不存在'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'edit')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CONTACTS_TYPE,$params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (ContactsModel::where([ |
|||
'mobile' => $params['mobile'], |
|||
'customer_id' => $row['customer_id'], |
|||
'id' => ['neq', $params['id']] |
|||
])->find()) { |
|||
$this->error('联系人手机号已存在'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = ContactsModel::updateContacts($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
$this->success('编辑联系人成功'); |
|||
} |
|||
|
|||
|
|||
//删除联系人 |
|||
public function delContacts() { |
|||
$id = input('id'); |
|||
|
|||
$row = ContactsModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('您不是客户归属人,无法删除当前联系人'); |
|||
} |
|||
$model = new ContactsModel(); |
|||
if ($model->destroy(['id' => $id])) { |
|||
$this->success('删除成功'); |
|||
} |
|||
Record::quickCreateRecord(Record::CUSTOMER_TYPE, $row['customer_id'], |
|||
'删除联系人:' . $row['name']); |
|||
OperationLog::createLog(OperationLog::CUSTOMER_TYPE, $row['customer_id'], '删除联系人:' . $row['name']); |
|||
$this->error('删除失败'); |
|||
} |
|||
|
|||
|
|||
//获取联系人列表 |
|||
public function getList() { |
|||
$limit = input("limit/d", 10); |
|||
$customer_id = input('customer_id'); |
|||
$name = input('name'); |
|||
|
|||
$params = input(); |
|||
$where = FormField::updateWhereField(FormField::CONTACTS_TYPE, $params); |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
}else{ |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
$records = ContactsModel::where($where)->with(['customer'])->order('id desc')->paginate($limit); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取select联系人列表 |
|||
public function getSelectList() { |
|||
$customer_id = input('customer_id'); |
|||
$name = input('name',''); |
|||
$where = []; |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($name) { |
|||
$where['name'] = ['like',"%$name%"]; |
|||
} |
|||
$list = ContactsModel::where($where)->with(['customer'])->field('id,customer_id,name,mobile')->select(); |
|||
$list = collection($list)->toArray(); |
|||
foreach ($list as $k => $v) { |
|||
$v['new_mobile'] = $v['mobile']; |
|||
$list[$k] = $v; |
|||
} |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//获取联系人详情 |
|||
public function getDetail() { |
|||
$id = input('id'); |
|||
$contract = ContactsModel::where(['id' => $id])->with([ |
|||
'customer', |
|||
'ownerStaff' |
|||
])->find(); |
|||
|
|||
if (empty($contract)) { |
|||
$this->error('信息不存在'); |
|||
} |
|||
$contract = $contract->toArray(); |
|||
$contract=ContactsOther::getOther($contract); |
|||
|
|||
$this->success('请求成功', $contract); |
|||
} |
|||
|
|||
|
|||
//获取附件列表 |
|||
public function getFilesList() { |
|||
$id = input('contacts_id'); |
|||
|
|||
$files = ContactsFile::where(['contacts_id' => $id])->field('file_id')->with(['file'])->select(); |
|||
$this->success('请求成功', $files); |
|||
} |
|||
} |
|||
@ -0,0 +1,362 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Contract as ContractModel; |
|||
use addons\qingdong\model\ContractFile; |
|||
use addons\qingdong\model\ContractOther; |
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\Ratio; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 合同接口 |
|||
*/ |
|||
class Contract extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//创建合同 |
|||
public function addContract() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CONTRACT_TYPE, $params); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (isset($params['num'])) { |
|||
if (empty($params['num'])) { |
|||
$params['num'] = ContractModel::getNum(); |
|||
} |
|||
$contract = ContractModel::where(['num' => $params['num']])->find(); |
|||
if ($contract) { |
|||
$this->error('合同编号已存在'); |
|||
} |
|||
} else { |
|||
$params['num'] = ContractModel::getNum(); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
|
|||
$result = ContractModel::createContract($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加合同成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取select合同列表 |
|||
public function getSelectList() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
$name = input('name',''); |
|||
$where = []; |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($name) { |
|||
$where['name'] = ["like","%$name%"]; |
|||
} |
|||
$records = ContractModel::where($where)->where(['check_status'=>2])->with(['ownerStaff'])->field('id,name,num,order_date,money')->order('id desc')->select(); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取合同列表 |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$customer_id = input('customer_id'); |
|||
$contacts_id = input('contacts_id'); |
|||
$status = input('status',0); |
|||
|
|||
$params = $this->request->post(); |
|||
|
|||
$whereT =[]; |
|||
$where= FormField::updateWhereField(FormField::CONTRACT_TYPE,$params); |
|||
if (isset($params['createtime']) && $params['createtime']) {//跟进状态 |
|||
$createtime = $params['createtime']; |
|||
$createtime = explode(',', $createtime); |
|||
$where['order_date'] = ['between', [date('Y-m-d 00:00:00',strtotime($createtime[0])), date('Y-m-d 23:59:59',strtotime($createtime[1]) + 86400 - 1)]]; |
|||
} |
|||
if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选 |
|||
$where['owner_staff_id'] = $params['staff_id']; |
|||
} else { |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
if (isset($params['type']) && $params['type']) {//客户分类 |
|||
if ($params['type'] == 1) {//我的客户 |
|||
$where['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($params['type'] == 2) {//下属负责的客户 |
|||
$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ($status) { |
|||
if($status == 1){//待审核 |
|||
$where['check_status']=['in',[0,1]]; |
|||
}elseif($status == 2){//待回款 |
|||
$where['check_status']=2; |
|||
$where['contract_status']=0; |
|||
}elseif($status == 3){//已回款 |
|||
$where['check_status']=2; |
|||
$where['contract_status']=1; |
|||
} |
|||
} |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($contacts_id) { |
|||
$where['contacts_id'] = $contacts_id; |
|||
} |
|||
$records = ContractModel::where($where)->with([ |
|||
'customer', |
|||
'contacts', |
|||
'ownerStaff', |
|||
'orderStaff', |
|||
'receivables' |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
$data = $records['data']; |
|||
|
|||
foreach ($data as $k => $v) { |
|||
if (empty($v['receivables'])) { |
|||
$v['receivables'] = [ |
|||
'repayment_money' => 0, |
|||
'be_money' => $v['money'], |
|||
'ratio' => 0 |
|||
]; |
|||
} else { |
|||
$be_money = $v['money'] - $v['receivables']['repayment_money']; |
|||
$be_money = ($be_money > 0) ? $be_money : 0; |
|||
$ratio_m = 0; |
|||
if($v['money'] >0){ |
|||
$ratio_m = round($v['receivables']['repayment_money'] / $v['money'] * 100, 2); |
|||
} |
|||
$v['receivables'] = [ |
|||
'repayment_money' => $v['receivables']['repayment_money'], |
|||
'be_money' =>$be_money, |
|||
'ratio' => $ratio_m |
|||
]; |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
|
|||
$whereT['owner_staff_id']=$where['owner_staff_id']; |
|||
$noMoney = ContractModel::where($whereT)->where(array('check_status'=>2))->sum('money'); |
|||
$moneyinfo['repayment_money'] = Receivables::where($whereT)->where(array('check_status'=>2))->sum('money'); //已回款 |
|||
$moneyinfo['be_money'] = sprintf("%.2f",$noMoney)-sprintf("%.2f",$moneyinfo['repayment_money']);//未回款 |
|||
$moneyinfo['allmoney'] = $noMoney;//合同总金额 |
|||
$this->success('请求成功', ['moneyinfo' => $moneyinfo, 'total' => $records['total'], 'per_page' => $records['per_page'], 'current_page' => $records['current_page'], 'last_page' => $records['last_page'], 'data' => $data]); |
|||
} |
|||
|
|||
|
|||
//获取客户相关合同列表 |
|||
public function getCustomerContacts() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
$contacts_id = input('contacts_id'); |
|||
$where = []; |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($contacts_id) { |
|||
$where['contacts_id'] = $contacts_id; |
|||
} |
|||
$records = ContractModel::where($where)->with(['receivables'])->field('id,name,money,num,check_status,order_date')->order('id desc')->select(); |
|||
$records = collection($records)->toArray(); |
|||
foreach ($records as $k => $v) { |
|||
if (empty($v['receivables'])) { |
|||
$v['receivables'] = [ |
|||
'repayment_money' => 0, |
|||
'be_money' => $v['money'], |
|||
'ratio' => 0 |
|||
]; |
|||
} else { |
|||
$be_money = $v['money'] - $v['receivables']['repayment_money']; |
|||
$v['receivables'] = [ |
|||
'repayment_money' => $v['receivables']['repayment_money'], |
|||
'be_money' => ($be_money > 0) ? $be_money : 0, |
|||
'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2) |
|||
]; |
|||
} |
|||
$records[$k] = $v; |
|||
} |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取合同详情 |
|||
public function getDetail() |
|||
{ |
|||
$id = input('id'); |
|||
$contract = ContractModel::where(['id' => $id])->with([ |
|||
'customer', |
|||
'contacts', |
|||
'ownerStaff', |
|||
'orderStaff', |
|||
'product', |
|||
'receivables', |
|||
'business' |
|||
])->find(); |
|||
if (empty($contract)) { |
|||
//标记通知已读 |
|||
Message::setRead(Message::CONTRACT_TYPE, $id); |
|||
$this->error('合同不存在'); |
|||
} |
|||
$contract = $contract->toArray(); |
|||
$contract = ContractOther::getOther($contract); |
|||
$receivablesMoney = Receivables::where(['contract_id' => $contract['id'], 'check_status' => 2])->sum('money'); |
|||
//回款金额 |
|||
$contract['receivables_money'] = $receivablesMoney; |
|||
$contract['ratios'] = json_decode($contract['ratios'],true); |
|||
if($contract['ratios']){ |
|||
foreach ($contract['ratios'] as $k => $v) { |
|||
$v['staff'] = Staff::where(['id' => $v['staff_id']])->field('id,name,img,post')->find()->toArray(); |
|||
$v['money'] = $contract['money'] * ($v['ratio'] / 100); |
|||
$contract['ratios'][$k] = $v; |
|||
} |
|||
} |
|||
if (empty($contract['receivables'])) { |
|||
$contract['receivables'] = [ |
|||
'repayment_money' => 0, |
|||
'be_money' => $contract['money'], |
|||
'ratio' => 0 |
|||
]; |
|||
} else { |
|||
$be_money = $contract['money'] - $contract['receivables']['repayment_money']; |
|||
$be_ratio = 0; |
|||
if($contract['money'] > 0){ |
|||
$be_ratio =round($contract['receivables']['repayment_money'] / $contract['money'] * 100, 2); |
|||
} |
|||
|
|||
$contract['receivables'] = [ |
|||
'repayment_money' => $contract['receivables']['repayment_money'], |
|||
'be_money' => ($be_money > 0) ? $be_money : 0, |
|||
'ratio' => $be_ratio |
|||
]; |
|||
} |
|||
//产品删除不显示 |
|||
if(isset($contract['product']) && $contract['product']){ |
|||
foreach($contract['product'] as $k=>$v){ |
|||
if(!$v['name'] && !$v['num']){ |
|||
unset($contract['product'][$k]); |
|||
} |
|||
} |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::CONTRACT_TYPE, $id, $this->auth->id); |
|||
|
|||
$this->success('请求成功', $contract); |
|||
} |
|||
|
|||
|
|||
//获取附件列表 |
|||
public function getFilesList() |
|||
{ |
|||
$id = input('contract_id'); |
|||
|
|||
$files = ContractFile::where(['contract_id' => $id])->field('file_id')->with(['file'])->select(); |
|||
$this->success('请求成功', $files); |
|||
} |
|||
|
|||
|
|||
//撤回审核 |
|||
public function cancel() |
|||
{ |
|||
$id = input('id'); |
|||
$customer = ContractModel::where(['id' => $id, 'check_status' => ['in', [0, 1]]])->find(); |
|||
if (empty($customer)) { |
|||
$this->error('合同信息不存在'); |
|||
} |
|||
$record = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONTRACT_TYPE, |
|||
'relation_id' => $id, |
|||
'status' => 0 |
|||
])->find(); |
|||
Db::startTrans(); |
|||
try { |
|||
if ($message = Message::where(['relation_type' => 'examine', 'relation_id' => $record['id'], 'from_staff_id' => $this->auth->id])->find()) { |
|||
Message::where(['id' => $message['id']])->update(['status' => 1, 'read_time' => time()]); |
|||
} |
|||
ContractModel::where(['id' => $id])->update(['check_status' => 4]); |
|||
ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONTRACT_TYPE, |
|||
'relation_id' => $id, |
|||
'status' => 0 |
|||
])->update(['status' => 3]); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback();; |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
|
|||
$this->success('撤回成功'); |
|||
} |
|||
|
|||
|
|||
//修改合同 |
|||
public function editContract() |
|||
{ |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = ContractModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find(); |
|||
if (empty($row)) { |
|||
$this->error('合同信息不存在'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CONTRACT_TYPE, $params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$params['owner_staff_id'] = $row['owner_staff_id']; |
|||
$result = ContractModel::updateContract($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('修改合同信息成功'); |
|||
} |
|||
//获取合同编号 |
|||
public function getContractNumber() |
|||
{ |
|||
$this->success('请求成功', ['number' => ContractModel::getNum()]); |
|||
} |
|||
|
|||
/** |
|||
* 获取业绩分割比例 |
|||
*/ |
|||
public function getRatio() |
|||
{ |
|||
$ratios = Ratio::where(['status' => 1])->field('name,ratio')->select(); |
|||
$ratios = collection($ratios)->toArray(); |
|||
foreach ($ratios as $k => $v) { |
|||
$v['ratio'] = json_decode($v['ratio'], true); |
|||
$ratios[$k] = $v; |
|||
} |
|||
$this->success('请求成功', $ratios); |
|||
} |
|||
} |
|||
@ -0,0 +1,564 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Contacts; |
|||
use addons\qingdong\model\Customer as CustomerModel; |
|||
use addons\qingdong\model\CustomerFile; |
|||
use addons\qingdong\model\CustomerOther; |
|||
use addons\qingdong\model\Business; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\StaffSignIn; |
|||
use addons\qingdong\model\Consume; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\OperationLog; |
|||
use addons\qingdong\model\Form; |
|||
use addons\qingdong\model\Record; |
|||
use addons\qingdong\model\Record as RecordModel; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\StaffCollect; |
|||
use addons\qingdong\model\Message; |
|||
use think\Db; |
|||
use think\Exception; |
|||
use function EasyWeChat\Kernel\Support\get_client_ip; |
|||
|
|||
/** |
|||
* 操作文档:https://doc.fastadmin.net/qingdong |
|||
* 软件介绍:https://www.fastadmin.net/store/qingdong.html |
|||
* 售后微信:qingdong_crm |
|||
* 客户接口 |
|||
*/ |
|||
class Customer extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//获取select客户列表 |
|||
public function getSelectList() |
|||
{ |
|||
$name = input('name'); |
|||
$where = []; |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
|
|||
$staff_id=$this->auth->id; |
|||
$list = CustomerModel::where($where)->where(function ($query) use ($staff_id) { |
|||
$query->where('ro_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('rw_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds()); |
|||
})->with(['ownerStaff'])->field('id,name,owner_staff_id,follow')->select(); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
//获取客户列表 |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$params = $this->request->post(); |
|||
|
|||
$where= FormField::updateWhereField(FormField::CUSTOMER_TYPE,$params); |
|||
|
|||
$whereStaff = []; |
|||
if (isset($params['name']) && $params['name']) {//客户名称 |
|||
if(is_numeric($params['name'])){ |
|||
$whereContact['mobile'] = ['like', "%".$params['name']."%"]; |
|||
$customer_id= Contacts::where($whereContact)->column('customer_id'); |
|||
$where['id'] = array('in',$customer_id); |
|||
}else{ |
|||
$where['name|subname'] = ['like', "%{$params['name']}%"]; |
|||
} |
|||
} |
|||
if (isset($params['level']) && $params['level']) {//客户星级 |
|||
$where['level'] = $params['level']; |
|||
} |
|||
if (isset($params['source']) && $params['source']) {//客户来源 |
|||
$where['source'] = $params['source']; |
|||
} |
|||
if (isset($params['follow']) && $params['follow']) {//跟进状态 |
|||
$where['follow'] = $params['follow']; |
|||
} |
|||
if (isset($params['group_id']) && $params['group_id']) {//角色组 |
|||
$ids = Staff::getGroupStaffIds($params['group_id']); |
|||
$where['id'] = ['in', $ids]; |
|||
} |
|||
if (isset($params['createtime']) && $params['createtime']) {// |
|||
$createtime = $params['createtime']; |
|||
$createtime = explode(',', $createtime); |
|||
$where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1]) + 86400 - 1]]; |
|||
} |
|||
$order = 'id desc'; |
|||
if (isset($params['sort']) && $params['sort']) { |
|||
switch ($params['sort']) { |
|||
case 1://名称正序 |
|||
$order = 'name asc'; |
|||
break; |
|||
case 2://名称倒序 |
|||
$order = 'name desc'; |
|||
break; |
|||
case 3://创建时间正序 |
|||
$order = 'createtime asc'; |
|||
break; |
|||
case 4://创建时间倒序 |
|||
$order = 'createtime desc'; |
|||
break; |
|||
case 5://下次跟进时间正序 |
|||
$order = 'next_time asc'; |
|||
break; |
|||
case 6://下次跟进时间倒序 |
|||
$order = 'next_time desc'; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (isset($params['next_time']) && $params['next_time']) {//下次联系时间 |
|||
$next_time = $params['next_time']; |
|||
$next_time = explode(',', $next_time); |
|||
$where['next_time'] = ['between', [$next_time[0], $next_time[1]]]; |
|||
} |
|||
if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选 |
|||
$where['owner_staff_id'] = $params['staff_id']; |
|||
} else { |
|||
$staff_id = $this->auth->id; |
|||
$type = $params['type'] ?? 0; |
|||
if ($type == 1) {//我的客户 |
|||
$whereStaff['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} elseif ($type == 3) {//我参与的客户 |
|||
$whereStaff = function ($query) use ($staff_id) { |
|||
$query->where('ro_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('rw_staff_id', 'like', "%,{$staff_id},%"); |
|||
}; |
|||
}else{ |
|||
$whereStaff = function ($query) use ($staff_id) { |
|||
$query->where(['ro_staff_id' => ['like', "%,{$staff_id},%"]]) |
|||
->whereOr('rw_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr(['owner_staff_id' => ['in', Staff::getMyStaffIds()]]); |
|||
}; |
|||
} |
|||
|
|||
} |
|||
$whereSeas = ['owner_staff_id' => ['neq', 0]]; |
|||
if (isset($params['is_seas']) && $params['is_seas'] == 1) {//公海 |
|||
//公海权限 |
|||
$whereSeas=[]; |
|||
$where['owner_staff_id'] = 0; |
|||
//公海权限 |
|||
$rules=Staff::getStaffRule('seas'); |
|||
$whereStaff = function ($query) use ($rules) { |
|||
foreach ($rules as $rule) { |
|||
$query->whereOr(['seas_id' => ['like', "%,{$rule},%"]]); |
|||
} |
|||
}; |
|||
$order = 'sea_time desc'; |
|||
} |
|||
if(is_array($whereStaff)){ |
|||
//查询会冲突 |
|||
$whereSeas=[]; |
|||
} |
|||
|
|||
if (isset($params['contract_status']) && $params['contract_status'] !== "") { |
|||
$where['contract_status'] = $params['contract_status']; |
|||
} |
|||
$list = CustomerModel::where($where)->where($whereStaff)->where($whereSeas)->with([ |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->field('id,name,next_time,owner_staff_id,level,follow')->order($order)->paginate($limit); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//查重客户名称 |
|||
public function selectName() |
|||
{ |
|||
$name = input('name'); |
|||
if (CustomerModel::where(['name' => $name])->find()) { |
|||
$this->error('客户名称已存在'); |
|||
} |
|||
$this->success('当前客户名称可使用'); |
|||
} |
|||
|
|||
|
|||
//新增客户 |
|||
public function addCustomer() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if (empty($params['customer'])) { |
|||
$this->error('客户信息不能为空'); |
|||
} |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params['customer'], get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params['customer']); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (CustomerModel::where(['name' => $params['customer']['name']])->find()) { |
|||
$this->error('客户名称已存在'); |
|||
} |
|||
|
|||
if (isset($params['is_event']) && $params['is_event'] == 1) {//是否创建跟进任务 |
|||
if (empty($params['event'])) { |
|||
$this->error('跟进任务信息不能为空'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params['event'], str_replace(ucwords($this->request->controller()), 'Event', get_class()), 'create_task')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
|
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
//线索转化 |
|||
$leads_id = ''; |
|||
if(isset($params['leads_id'])){ |
|||
$leads_id=$params['leads_id']; |
|||
} |
|||
$customerId = CustomerModel::createCustomer($params['customer'],$leads_id,$params['record']); |
|||
if(isset($params['customer']['mobile']) && $params['customer']['mobile']){ |
|||
$retC = array( |
|||
'customer_id'=>$customerId, |
|||
'is_major'=>1, |
|||
'name'=>$params['customer']['name'], |
|||
'mobile'=>$params['customer']['mobile'], |
|||
'next_time'=>date('Y-m-d H:i:s'), |
|||
); |
|||
Contacts::createContacts($retC); |
|||
} |
|||
|
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('新增客户成功',array('id'=>$customerId)); |
|||
} |
|||
} |
|||
|
|||
|
|||
//编辑客户 |
|||
public function editCustomer() |
|||
{ |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = CustomerModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('客户信息不存在'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'edit')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = CustomerModel::updateCustomer($params); |
|||
if(isset($params['mobile']) && $params['mobile']){ |
|||
Contacts::where(array('customer_id'=>$id,'is_major'=>1))->update(array('mobile'=>$params['mobile'],'updatetime'=>time())); |
|||
} |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('修改客户成功'); |
|||
} |
|||
|
|||
|
|||
//获取子公司 |
|||
public function getLowerCustomer() |
|||
{ |
|||
$id = input('id'); |
|||
$customers = CustomerModel::where(['parent_id' => $id])->with([ |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->field('id,name,next_time,owner_staff_id,level,follow')->select(); |
|||
|
|||
$this->success('请求成功', $customers); |
|||
} |
|||
|
|||
|
|||
//客户详情 |
|||
public function customerDetail() |
|||
{ |
|||
$id = input('id'); |
|||
$customer = CustomerModel::where(['id' => $id])->with([ |
|||
'createStaff', |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->find(); |
|||
if (empty($customer)) { |
|||
$this->error('信息不存在'); |
|||
} |
|||
$customer = $customer->toArray(); |
|||
$customer['is_collect'] = StaffCollect::isCollect(StaffCollect::CUSTOMER_TYPE, $customer['id']) ? 1 : 0; |
|||
|
|||
if ($customer['owner_staff_id'] == $this->auth->id || |
|||
in_array($customer['owner_staff_id'],Staff::getLowerStaffId()) || |
|||
in_array($this->auth->id, explode(',', $customer['rw_staff_id'])) ) { |
|||
$customer['operation'] = 'update';//修改权限 |
|||
} else { |
|||
$customer['operation'] = 'read';//只读权限 |
|||
} |
|||
|
|||
$customer = CustomerOther::getOther($customer); |
|||
$form = Form::getDataValue('customer',$customer); |
|||
foreach($form as $ks=>$vs){ |
|||
//备注显示 |
|||
if($vs['component'] == 'textarea' && ($vs['config']['label'] == '备注信息' || $vs['config']['label'] == '备注')){ |
|||
$customer[$vs['id']] = isset($customer[$vs['id']]) ? $customer[$vs['id']] :$customer['remarks']; |
|||
} |
|||
} |
|||
//商机数量 |
|||
$customer['bussinessCount'] = Business::where(['customer_id'=>$id])->count(); |
|||
//联系人数量 |
|||
$customer['contactsCount'] = Contacts::where(['customer_id'=>$id])->count(); |
|||
//签到数量 |
|||
$customer['signCount'] = StaffSignIn::where(['customer_id'=>$id])->count(); |
|||
//合同数量 |
|||
$customer['contractCount'] = Contract::where(['customer_id'=>$id])->count(); |
|||
//费用数量 |
|||
$customer['consumeCount'] = Consume::where(['customer_id'=>$id])->count(); |
|||
//回款数量 |
|||
$customer['receivalbleCount'] = Receivables::where(['customer_id'=>$id])->count(); |
|||
//子公司 |
|||
$customer['companyCount'] = CustomerModel::where(['parent_id'=>$id])->count(); |
|||
//团队 |
|||
$ro_staff_id = []; |
|||
if($customer['ro_staff_id']){ |
|||
$ro_staff_id = array_unique(array_filter(explode(',',$customer['ro_staff_id']))); |
|||
} |
|||
$rw_staff_id = []; |
|||
if($customer['rw_staff_id']){ |
|||
$rw_staff_id = array_unique(array_filter(explode(',',$customer['rw_staff_id']))); |
|||
} |
|||
$customer['teamCount'] = count($ro_staff_id)+count($rw_staff_id); |
|||
//附件 |
|||
$customer['fileCount'] = CustomerFile::where(['customer_id'=>$id])->count(); |
|||
//操作记录 |
|||
$customer['operateCount'] = OperationLog::where(['relation_id'=>$id,'relation_type'=>1,'operation_type' => 1])->count(); |
|||
//标记通知已读 |
|||
Message::setRead(Message::CUSTOMER_TYPE, $id, $this->auth->id); |
|||
$this->success('请求成功', $customer); |
|||
} |
|||
|
|||
|
|||
//移入公海 |
|||
public function moveSeas() |
|||
{ |
|||
$id = input('id'); |
|||
$row = CustomerModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('您不是负责人暂无权限移除'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
CustomerModel::moveSeas($id); |
|||
|
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('放入成功'); |
|||
} |
|||
|
|||
|
|||
//转移客户 |
|||
public function transfer() |
|||
{ |
|||
$id = input('id'); |
|||
$staff_id = input('staff_id'); |
|||
if (empty($staff_id)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$staff = Staff::get($staff_id); |
|||
if (empty($staff)) { |
|||
$this->error('接收对象不存在'); |
|||
} |
|||
$row = CustomerModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('客户不存在'); |
|||
} |
|||
try { |
|||
CustomerModel::transfer($id, $staff_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('转移客户成功'); |
|||
} |
|||
|
|||
|
|||
//领取公海客户 |
|||
public function receive() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
$where = ['owner_staff_id' => 0]; |
|||
if ($customer_id) { |
|||
$where['id'] = $customer_id; |
|||
} |
|||
$customers = CustomerModel::where($where)->count(); |
|||
if ($customers == 0) { |
|||
$this->error('公海内暂无客户'); |
|||
} |
|||
try { |
|||
$id = CustomerModel::receive($customer_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('领取成功', ['id' => $id]); |
|||
} |
|||
|
|||
|
|||
//重点关注客户 |
|||
public function collect() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
try { |
|||
StaffCollect::addCollect(StaffCollect::CUSTOMER_TYPE, $customer_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('重点关注成功'); |
|||
} |
|||
|
|||
|
|||
//取消重点关注 |
|||
public function cancelCollect() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
try { |
|||
StaffCollect::cancel(StaffCollect::CUSTOMER_TYPE, $customer_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('取消重点关注成功'); |
|||
} |
|||
|
|||
|
|||
//重点关注客户列表 |
|||
public function collectList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$ids = StaffCollect::where(['staff_id' => $this->auth->id, 'relation_type' => 1])->column('relation_id'); |
|||
$list = CustomerModel::where(['id' => ['in', $ids]])->with([ |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->field('id,name,next_time,owner_staff_id,level,follow')->order('id desc')->paginate($limit); |
|||
|
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//获取附件列表 |
|||
public function getFilesList() |
|||
{ |
|||
$id = input('customer_id'); |
|||
|
|||
$files = CustomerFile::where(['customer_id' => $id])->field('file_id')->with(['file'])->select(); |
|||
$this->success('请求成功', $files); |
|||
} |
|||
|
|||
|
|||
//周围客户 |
|||
public function nearby() |
|||
{ |
|||
$lng = input('lng'); |
|||
$lat = input('lat'); |
|||
//我的客户 |
|||
$type = input('type',0); |
|||
//距离 |
|||
$distance = input('distance', 5, 'intval'); |
|||
$name = input('name', '', 'trim'); |
|||
|
|||
if (empty($lng) && empty($lat)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
|
|||
$range = 180 / pi() * $distance / 6372.797; //里面的 1 就代表搜索 1km 之内,单位km |
|||
$lngR = $range / cos($lat * pi() / 180); |
|||
$maxLat = $lat + $range; //最大纬度 |
|||
$minLat = $lat - $range; //最小纬度 |
|||
$maxLng = $lng + $lngR; //最大经度 |
|||
$minLng = $lng - $lngR; //最小经度 |
|||
$where = ['lng' => ['between', [$minLng, $maxLng]], 'lat' => ['between', [$minLat, $maxLat]]]; |
|||
//客户分类 |
|||
$whereStaff=[]; |
|||
$staff_id=$this->auth->id; |
|||
if ($type == 1) {//我的客户 |
|||
$whereStaff['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} elseif ($type == 3) {//我参与的客户 |
|||
$whereStaff = function ($query) use ($staff_id) { |
|||
$query->where('ro_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('rw_staff_id', 'like', ",{$staff_id},"); |
|||
}; |
|||
}else{ |
|||
$whereStaff = function ($query) use ($staff_id) { |
|||
$query->where('ro_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('rw_staff_id', 'like', "%,{$staff_id},%") |
|||
->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds()); |
|||
}; |
|||
} |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
$customers = CustomerModel::where($where)->where($whereStaff)->field('id,owner_staff_id,name,location,next_time,lng,lat,address_detail,follow')->with('ownerStaff')->select(); |
|||
$data = []; |
|||
//所属员工列表 |
|||
$myStaffIds = Staff::getMyStaffIds(); |
|||
foreach ($customers as $k => $v) { |
|||
if ($v['owner_staff_id'] == 0) { |
|||
$v['type'] = 0;//公海 |
|||
} elseif ($v['owner_staff_id'] == $this->auth->id) { |
|||
$v['type'] = 1;//自己的 |
|||
} elseif (in_array($v['owner_staff_id'], $myStaffIds)) { |
|||
$v['type'] = 2;//团队的 |
|||
} else { |
|||
$v['type'] = 3;//其他人 |
|||
} |
|||
$v['juli_num'] = getdistance($lng, $lat, $v['lng'], $v['lat']); |
|||
$v['juli'] = float_number($v['juli_num']); |
|||
$data[$v['juli']][] = $v; |
|||
} |
|||
ksort($data); |
|||
|
|||
|
|||
$result = []; |
|||
foreach ($data as $v) { |
|||
|
|||
$result = array_merge($result, array_values($v)); |
|||
} |
|||
$this->success('请求成功', $result); |
|||
} |
|||
|
|||
|
|||
//获取搜索员工列表 |
|||
public function getSearchStaffList() |
|||
{ |
|||
$name = input('name',''); |
|||
$where = []; |
|||
if($name){ |
|||
$where['name'] = ['like',"%$name%"]; |
|||
} |
|||
$ids = Staff::getMyStaffIds(); |
|||
|
|||
$staff = Staff::where([ |
|||
'id' => ['in', $ids], |
|||
'status' => 1 |
|||
])->where($where)->field('id,name,img,post')->select(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,327 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Daily as DailyModel; |
|||
use addons\qingdong\model\DailyRead; |
|||
use addons\qingdong\model\File; |
|||
use addons\qingdong\model\Form; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\DailyDraft; |
|||
use think\Db; |
|||
use think\Exception; |
|||
/** |
|||
* 工作报告接口 |
|||
*/ |
|||
class Daily extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//创建 |
|||
public function createDaily() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
$params['create_staff_id'] = $this->auth->id; |
|||
$dailyId = DailyModel::createDaily($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('创建工作报告成功'); |
|||
} |
|||
|
|||
|
|||
//获取 |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
$is_read = input('is_read', 0); |
|||
$staff_ids = input('staff_id', 0); |
|||
$type = input('type', 0); |
|||
$times = input('times', ''); |
|||
|
|||
$where = []; |
|||
$where['create_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
|
|||
if ($staff_ids) { |
|||
$where['create_staff_id'] = $staff_ids; |
|||
} |
|||
|
|||
if ($type) { |
|||
$where['type'] = $type; |
|||
} |
|||
if ($times) {//筛选时间 |
|||
$times = explode(',', $times); |
|||
$where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]]; |
|||
} |
|||
$staff_id = $this->auth->id; |
|||
if ($is_read == 1) {//已读 |
|||
$ids = DailyRead::where(['staff_id' => $staff_id])->column('daily_id'); |
|||
$where['id'] = ['in', $ids]; |
|||
} elseif ($is_read == 2) {//未读 |
|||
$ids = DailyRead::where(['staff_id' => $staff_id])->column('daily_id'); |
|||
$where['id'] = ['not in', $ids]; |
|||
} |
|||
$followWhere = []; |
|||
$elseWhere = []; |
|||
if (!$staff_ids) { |
|||
$followWhere[] = ['exp', Db::raw('FIND_IN_SET(' . $this->auth->id . ',reminds_id)')]; |
|||
if ($type) { |
|||
$elseWhere['type'] = ['eq', $type]; |
|||
} |
|||
if ($is_read == 1) {//已读 |
|||
$elseWhere['id'] = ['in', $ids]; |
|||
} elseif ($is_read == 2) {//未读 |
|||
$elseWhere['id'] = ['not in', $ids]; |
|||
} |
|||
} |
|||
|
|||
|
|||
$records = DailyModel::where($where)->whereOr(function ($query) use ($followWhere, $elseWhere) { |
|||
$query->where($followWhere)->where($elseWhere); |
|||
})->with([ |
|||
'staff', |
|||
'read' => function ($query) use ($staff_id) { |
|||
$query->where(['staff_id' => $staff_id]); |
|||
} |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
|
|||
$data = $records['data']; |
|||
foreach ($data as $k => $v) { |
|||
if (!empty($v['read'])) { |
|||
$v['is_read'] = 1; |
|||
} else { |
|||
$v['is_read'] = 0; |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
$this->success('请求成功', [ |
|||
'total' => $records['total'], |
|||
'per_page' => $records['per_page'], |
|||
'current_page' => $records['current_page'], |
|||
'last_page' => $records['last_page'], |
|||
'data' => $data |
|||
]); |
|||
|
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取详情 |
|||
public function getDailyDetail() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('参数不能为空'); |
|||
} |
|||
$record = DailyModel::where(['id' => $id])->with([ |
|||
'staff', |
|||
])->find(); |
|||
if (empty($record)) { |
|||
$this->error('记录不存在'); |
|||
} |
|||
|
|||
$record = $record->toArray(); |
|||
$reminds_id = $record['reminds_id']; |
|||
$reminds_id = explode(',', $reminds_id); |
|||
$names = Staff::where(['id' => ['in', $reminds_id]])->column('name'); |
|||
$record['staff_name'] = implode(',', $names); |
|||
if ($record['other']) { |
|||
if(is_array($record['other'])){ |
|||
$other = $record['other']; |
|||
}else{ |
|||
$other = json_decode($record['other'], true); |
|||
} |
|||
} else { |
|||
$other = []; |
|||
} |
|||
$record = array_merge($record, $other); |
|||
switch($record['type']){ |
|||
case '日报': |
|||
$type = 'daily'; |
|||
break; |
|||
case '周报': |
|||
$type ='weekly'; |
|||
break; |
|||
case '月报': |
|||
$type = 'monthly'; |
|||
break; |
|||
case '季报': |
|||
$type = 'quarterly'; |
|||
break; |
|||
case '年报': |
|||
$type = 'yearly'; |
|||
break; |
|||
default: |
|||
$type = 'daily'; |
|||
break; |
|||
} |
|||
|
|||
$form = Form::getDataValue($type,$record); |
|||
foreach($form as $k=>$v){ |
|||
if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){ |
|||
if(key_exists($v['id'],$record)){ |
|||
if(isset($record[$v['id']]) && $record[$v['id']]){ |
|||
$whereT['id'] = array('in',$record[$v['id']]); |
|||
$fileinfo = File::where($whereT)->field('id,name,file_path')->select(); |
|||
if($fileinfo){ |
|||
$record[$v['id']] = $fileinfo; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::DAILY_TYPE, $id, $this->auth->id); |
|||
//添加阅读记录 |
|||
DailyRead::addRead($id, $this->auth->id); |
|||
|
|||
$this->success('请求成功', $record); |
|||
} |
|||
|
|||
|
|||
//获取工作报告已读 未读 |
|||
public function getDailyRead() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$daily = DailyModel::where(['id' => $id])->find(); |
|||
if (empty($daily)) { |
|||
$this->error('记录不存在'); |
|||
} |
|||
$create_staff_id = $daily['create_staff_id']; |
|||
|
|||
$read = DailyRead::where(['daily_id' => $id])->group('staff_id')->field('id,staff_id')->with(['staff'])->select(); |
|||
$staffIds = []; |
|||
foreach ($read as $v) { |
|||
$staffIds[] = $v['staff_id']; |
|||
} |
|||
//全部可看数据的人 |
|||
$allids = explode(',', $daily->reminds_id); |
|||
$not_ids = array_diff($allids, $staffIds); |
|||
|
|||
$notRead = Staff::where(['id' => ['in', $not_ids]]) |
|||
->field('id,name,img')->select(); |
|||
$this->success('请求成功', ['read' => $read, 'not_read' => $notRead]); |
|||
} |
|||
|
|||
//草稿创建 |
|||
public function daily_draft() |
|||
{ |
|||
$params = $this->request->post(); |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
$params['create_staff_id'] = $this->auth->id; |
|||
//自定义字段 |
|||
$other = []; |
|||
foreach ($params as $name => $val) { |
|||
if (strstr($name, 'other_') !== false) { |
|||
if(is_array($val)){ |
|||
$other[$name] = implode(',',$val); |
|||
}else{ |
|||
$other[$name] = $val; |
|||
} |
|||
unset($params[$name]); |
|||
} |
|||
} |
|||
$params['other'] = json_encode($other); |
|||
$where['create_staff_id'] = $this->auth->id; |
|||
$where['type'] = $params['type']; |
|||
$info = DailyDraft::where($where)->find(); |
|||
if ($info) { |
|||
$result = DailyDraft::where(array('id' => $info['id']))->update($params); |
|||
} else { |
|||
$result = DailyDraft::create($params); |
|||
} |
|||
|
|||
if (false === $result) { |
|||
// 验证失败 输出错误信息 |
|||
throw new Exception('草稿保存失败'); |
|||
} |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('草稿保存成功'); |
|||
} |
|||
|
|||
//获取详情 |
|||
public function getDailyDraftDetail() |
|||
{ |
|||
$type = input('type'); |
|||
if (!$type) { |
|||
$this->error('参数不正确'); |
|||
} |
|||
$where['create_staff_id'] = $this->auth->id; |
|||
$where['type'] = $type; |
|||
$record = DailyDraft::where($where)->find(); |
|||
if (empty($record)) { |
|||
$this->success('记录不存在'); |
|||
} |
|||
switch ($record['type']) { |
|||
case '日报': |
|||
$record['type_index'] = 0; |
|||
break; |
|||
case '周报': |
|||
$record['type_index'] = 1; |
|||
break; |
|||
case '月报': |
|||
$record['type_index'] = 2; |
|||
break; |
|||
case '季报': |
|||
$record['type_index'] = 3; |
|||
break; |
|||
case '年报': |
|||
$record['type_index'] = 4; |
|||
break; |
|||
default: |
|||
$record['type_index'] = 0; |
|||
break; |
|||
} |
|||
$record = $record->toArray(); |
|||
$reminds_id = $record['reminds_id']; |
|||
$reminds_id = explode(',', $reminds_id); |
|||
$names = Staff::where(['id' => ['in', $reminds_id]])->field('id,img,name,post')->select(); |
|||
$record['staff_info'] = $names; |
|||
if ($record['other']) { |
|||
$other = json_decode($record['other'], true); |
|||
} else { |
|||
$other = []; |
|||
} |
|||
$record = array_merge($record, $other); |
|||
|
|||
$this->success('请求成功', $record); |
|||
} |
|||
|
|||
|
|||
|
|||
//修改工作报告 |
|||
public function updateDaily() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if(empty($params['id'])){ |
|||
$this->error('参数不能为空'); |
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
$dailyId = DailyModel::updateDaily($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('创建工作报告成功'); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
<?php |
|||
namespace addons\qingdong\controller; |
|||
/** |
|||
* error code 说明. |
|||
* <ul> |
|||
|
|||
* <li>-41001: encodingAesKey 非法</li> |
|||
* <li>-41003: aes 解密失败</li> |
|||
* <li>-41004: 解密后得到的buffer非法</li> |
|||
* <li>-41005: base64加密失败</li> |
|||
* <li>-41016: base64解密失败</li> |
|||
* </ul> |
|||
*/ |
|||
class ErrorCode |
|||
{ |
|||
public static $OK = 0; |
|||
public static $IllegalAesKey = -41001; |
|||
public static $IllegalIv = -41002; |
|||
public static $IllegalBuffer = -41003; |
|||
public static $DecodeBase64Error = -41004; |
|||
} |
|||
|
|||
?> |
|||
@ -0,0 +1,206 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Event as EventModel; |
|||
use addons\qingdong\model\File; |
|||
use addons\qingdong\model\Form; |
|||
use addons\qingdong\model\StaffSignIn; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 日程接口 |
|||
*/ |
|||
class Event extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//获取日程 |
|||
public function getEvent() |
|||
{ |
|||
//开始时间 |
|||
$start_day = input('start_day'); |
|||
//结束时间 |
|||
$end_day = input('end_day');; |
|||
if (empty($start_day) || empty($end_day)) { |
|||
$this->error('开始时间或结束时间不能为空'); |
|||
} |
|||
if ($end_day < $start_day) { |
|||
$this->error('开始时间不能小于结束时间'); |
|||
} |
|||
$this->success('请求成功', EventModel::getTimeList($start_day, $end_day)); |
|||
} |
|||
|
|||
|
|||
//添加日程 |
|||
public function addEvent() |
|||
{ |
|||
$params = $this->request->post(); |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$params['type'] = 1;//日程 |
|||
$result = EventModel::createEvent($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加日程成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//变更状态 |
|||
public function changeStatus() |
|||
{ |
|||
$id = input('id'); |
|||
$status = input('status', 0); |
|||
if (empty($id)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
EventModel::changeStatus($id, $status); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('变更成功'); |
|||
} |
|||
|
|||
|
|||
// |
|||
public function getList() |
|||
{ |
|||
$relation_type = input('relation_type', '', 'intval');// 1客户 2联系人 3合同 4线索 |
|||
$relation_id = input('relation_id', '', 'intval'); |
|||
$limit = input("limit/d", 10); |
|||
$where = []; |
|||
$where['relation_type'] = $relation_type; |
|||
$where['relation_id'] = $relation_id; |
|||
$where['staff_id'] = $this->auth->id; |
|||
$records = EventModel::where($where)->with(['staff'])->field('id,staff_id,type,title,start_time,end_time,status,auto_end,level,remindtype,remark,color,createtime')->order('id desc')->paginate($limit); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//添加签到 |
|||
public function addSign() |
|||
{ |
|||
$params = $this->request->post(); |
|||
$location = input('location'); |
|||
$lng = input('lng'); |
|||
$lat = input('lat'); |
|||
$files = input('file_ids'); |
|||
$customer_id = input('customer_id'); |
|||
$content = input('content'); |
|||
if (empty($lng) || empty($lat)) { |
|||
$this->error('地理位置不能为空'); |
|||
} |
|||
|
|||
//自定义字段 |
|||
$other = []; |
|||
foreach ($params as $name => $val) { |
|||
if (strstr( $name,'other_') !== false) { |
|||
if(is_array($val)){ |
|||
$other[$name] = implode(',',$val); |
|||
}else{ |
|||
$other[$name] = $val; |
|||
} |
|||
unset($params[$name]); |
|||
} |
|||
} |
|||
|
|||
$data = [ |
|||
'location' => $location, |
|||
'lng' => $lng, |
|||
'lat' => $lat, |
|||
'file_ids' => $files, |
|||
'customer_id' => $customer_id, |
|||
'staff_id' => $this->auth->id, |
|||
'other' => json_encode($other, JSON_UNESCAPED_UNICODE) |
|||
]; |
|||
$model = new StaffSignIn(); |
|||
if ($result = $model->save($data)) { |
|||
$lastId = $model->getLastInsID(); |
|||
//通知上级 |
|||
Message::addMessage(Message::SIGN_TYPE, $lastId, $this->auth->parent_id, $this->auth->id); |
|||
$this->success('签到成功'); |
|||
} |
|||
$this->error('签到失败'); |
|||
} |
|||
|
|||
|
|||
//获取签到信息 |
|||
public function getSign() |
|||
{ |
|||
$customer_id = input('customer_id', 0, 'intval'); |
|||
$limit = input("limit/d", 10); |
|||
$where = []; |
|||
$type = input('type', 0);// 0 全部 1 我创建 2 下属创建 |
|||
|
|||
if ($type == 1) {//我的客户 |
|||
$where['staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$where['staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
}else{ |
|||
$where['staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
$staffSign = StaffSignIn::where($where)->with(['staff', 'customer']) |
|||
->order('id desc')->paginate($limit); |
|||
//标记通知已读 |
|||
Message::setRead(Message::SIGN_TYPE,0, $this->auth->id); |
|||
$this->success('请求成功', $staffSign); |
|||
} |
|||
|
|||
/** |
|||
* 获取签到详情 |
|||
*/ |
|||
public function getSignDetail(){ |
|||
$id = input('id', 0, 'intval'); |
|||
|
|||
$staffSign = StaffSignIn::where(['id'=>$id])->with(['staff', 'customer'])->find(); |
|||
if(empty($staffSign)){ |
|||
$this->error('数据不存在'); |
|||
} |
|||
if($staffSign['other']){ |
|||
$other = json_decode($staffSign['other'],true); |
|||
$form = Form::getDataValue('signin'); |
|||
foreach($form as $k=>$v){ |
|||
if($v['component'] == 'uploadImage' || $v['component'] == 'uploadFile'){ |
|||
$other[$v['id'].'_str'] = ''; |
|||
if(key_exists($v['id'],$other)){ |
|||
if(isset($other[$v['id']]) && $other[$v['id']]){ |
|||
$whereT['id'] = array('in',$other[$v['id']]); |
|||
$fileinfo = File::where($whereT)->field('id,name,file_path,save_name')->select(); |
|||
if($fileinfo){ |
|||
$other[$v['id']] = $fileinfo; |
|||
$fileinfodata = ''; |
|||
foreach($fileinfo as $kss=>$vss){ |
|||
$fileinfodata = $vss['save_name'].','.$fileinfodata; |
|||
} |
|||
$other[$v['id'].'_str'] = rtrim($fileinfodata,','); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
$staffSign['other'] = $other; |
|||
} |
|||
$this->success('请求成功',$staffSign); |
|||
} |
|||
} |
|||
@ -0,0 +1,257 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\AchievementRecords; |
|||
use addons\qingdong\model\AttendanceStatisc; |
|||
use addons\qingdong\model\Business; |
|||
use addons\qingdong\model\BusinessStatus; |
|||
use addons\qingdong\model\Flow; |
|||
use addons\qingdong\model\FormApproval; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Consume; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\Achievement; |
|||
use addons\qingdong\model\Approval; |
|||
use addons\qingdong\model\ExamineRecord as ExamineRecordModel; |
|||
use think\Cache; |
|||
use think\Db; |
|||
use think\Exception; |
|||
use think\Log; |
|||
|
|||
/** |
|||
* 审批记录 |
|||
*/ |
|||
class ExamineRecord extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//审批记录 |
|||
public function getList() { |
|||
$relation_type = input('relation_type'); |
|||
$relation_id = input('relation_id'); |
|||
|
|||
$list = ExamineRecordModel::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id |
|||
])->with('checkStaff')->select(); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//审核 |
|||
public function examine() { |
|||
$relation_type = input('relation_type'); |
|||
$relation_id = input('relation_id'); |
|||
$content = input('content'); |
|||
$status = input('status'); |
|||
$record = ExamineRecordModel::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->find(); |
|||
if (empty($record)) { |
|||
$this->error('没有待审核数据'); |
|||
} |
|||
$staff = Staff::info(); |
|||
Db::startTrans(); |
|||
try { |
|||
$model = new ExamineRecordModel(); |
|||
if ($model->isUpdate(true)->save([ |
|||
'status' => $status, |
|||
'content' => $content, |
|||
'check_time' => time() |
|||
], ['id' => $record['id']]) == false) { |
|||
throw new Exception('修改失败'); |
|||
} |
|||
switch ($relation_type) { |
|||
case $model::CONSUME_TYPE://费用 |
|||
$rowModel = new \addons\qingdong\model\Consume(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find(); |
|||
break; |
|||
case $model::CONTRACT_TYPE://合同 |
|||
$rowModel = new \addons\qingdong\model\Contract(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find(); |
|||
break; |
|||
case $model::RECEIVABLES_TYPE://回款 |
|||
$rowModel = new \addons\qingdong\model\Receivables(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find(); |
|||
break; |
|||
case $model::ACHIEVEMENT_TYPE://业绩目标 |
|||
$rowModel = new \addons\qingdong\model\AchievementRecords(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find()->toArray(); |
|||
break; |
|||
case $model::APPROVAL_TYPE://审批 |
|||
$rowModel = new \addons\qingdong\model\Approval(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find()->toArray(); |
|||
$row['staff_id'] = $row['create_staff_id']; |
|||
break; |
|||
case $model::CARD_TYPE://补卡审核 |
|||
$rowModel = new \addons\qingdong\model\AttendanceCard(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find()->toArray(); |
|||
$row['staff_id'] = $row['create_staff_id']; |
|||
break; |
|||
case $model::LEAVE_TYPE://请假 |
|||
$rowModel = new \addons\qingdong\model\Leave(); |
|||
$row = $rowModel->where(['id' => $relation_id])->find()->toArray(); |
|||
$row['staff_id'] = $row['create_staff_id']; |
|||
break; |
|||
default: |
|||
throw new Exception('参数错误'); |
|||
} |
|||
if ($message = Message::where(['relation_type' => 'examine', 'relation_id' => $record['id'],'to_staff_id'=>$this->auth->id])->find()) { |
|||
Message::where(['id' => $message['id']])->update(['status' => 1, 'read_time' => time()]); |
|||
} |
|||
$check_staff_ids = explode(',', trim($row['check_staff_ids'], ',')); |
|||
$check_staff_ids[] = $staff->id; |
|||
if ($status == 1) {//审核通过 |
|||
$flow= Flow::getstepdetail($relation_type,$relation_id); |
|||
//给下一审核人发送通知 |
|||
$result=Flow::sendStepRecord($flow,$relation_type, $relation_id,$check_staff_ids,$staff->id); |
|||
|
|||
//已完成审核 |
|||
if ($result['status']== true) { |
|||
$rowModel->save([ |
|||
'check_status' => 2, |
|||
'check_staff_ids' => implode(',', $check_staff_ids), |
|||
'order_id'=>$result['order_id'] |
|||
], ['id' => $relation_id]); |
|||
switch ($relation_type) { |
|||
case $model::CONTRACT_TYPE://合同 |
|||
\addons\qingdong\model\Customer::where(['id'=>$row['customer_id']])->update(['contract_status'=>1]); |
|||
//合同签署成功后商机变为赢单 |
|||
if($row['business_id']){ |
|||
BusinessStatus::create(array('business_id'=>$row['business_id'],'type'=>4,'remark'=>'合同签署')); |
|||
Business::where(array('id'=>$row['business_id']))->update(array('contract_status'=>1,'updatetime'=>time())); |
|||
} |
|||
break; |
|||
case $model::ACHIEVEMENT_TYPE://业绩目标 |
|||
$m=new \addons\qingdong\model\Achievement(); |
|||
$m->where(['type'=>$row['type'],'status'=>$row['status'],'obj_id'=>$row['obj_id']])->delete(); |
|||
unset($row['id']); |
|||
unset($row['createtime']); |
|||
unset($row['updatetime']); |
|||
unset($row['deletetime']); |
|||
$m->allowField(true)->save($row); |
|||
$row['staff_id']=$row['obj_id']; |
|||
break; |
|||
case $model::RECEIVABLES_TYPE://回款 |
|||
$m=new \addons\qingdong\model\Contract(); |
|||
$contract=$m->where(['id'=>$row['contract_id']])->with(['receivables'])->find(); |
|||
if($contract['receivables']['repayment_money'] >= $contract['money']){ |
|||
$m->save(['contract_status'=>1],['id'=>$row['contract_id']]);//已完成 |
|||
} |
|||
break; |
|||
case $model::CARD_TYPE://补卡 |
|||
if($row['type'] == 1){//早退 |
|||
$name='clock_out_status'; |
|||
$name_time='clock_out'; |
|||
}else{//迟到 |
|||
$name='clock_in_status'; |
|||
$name_time='clock_in'; |
|||
} |
|||
AttendanceStatisc::where(['id'=>$row['statisc_id']])->update([$name=>5,$name_time=>$row['time']]); |
|||
break; |
|||
case $model::LEAVE_TYPE://请假 |
|||
break; |
|||
} |
|||
|
|||
Message::addMessage(Message::EXAMINE_ADOPT_TYPE,$record['id'],$row['owner_staff_id']?? $row['staff_id'],$staff->id); |
|||
|
|||
//删除 或签的待审批通知 |
|||
Message::setRead(Message::EXAMINE_TYPE,$record['id']); |
|||
ExamineRecordModel::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id, |
|||
'status' => 0, |
|||
])->update(['status'=>3]); |
|||
} else { |
|||
$rowModel->save([ |
|||
'check_staff_ids' => implode(',', $check_staff_ids), |
|||
'order_id'=>$result['order_id'] |
|||
], ['id' => $relation_id]); |
|||
} |
|||
} else { |
|||
//审核未通过 |
|||
$rowModel->save(['check_status' => 3, 'check_staff_ids' => ''], ['id' => $relation_id]); |
|||
Message::addMessage(Message::EXAMINE_REFUSE_TYPE,$record['id'],$row['owner_staff_id']?? $row['staff_id'],$staff->id,''); |
|||
|
|||
//删除待审批通知 |
|||
$ids = ExamineRecordModel::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id, |
|||
'status' => 0, |
|||
])->column('id'); |
|||
Message::where(['relation_type' => Message::EXAMINE_TYPE, 'relation_id' => ['in', $ids], 'status' => 0])->update(['read_time' => time(), 'status' => 1]); |
|||
|
|||
ExamineRecordModel::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id, |
|||
'status' => 0, |
|||
])->update(['status'=>3]); |
|||
} |
|||
|
|||
|
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
Log::record($e->getMessage()); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
|
|||
$this->success('审核成功'); |
|||
} |
|||
|
|||
/** |
|||
* 获取审批列表 |
|||
*/ |
|||
public function get_examine_list() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
//合同审批,回款审批、业绩目标审批、办公审批 费用 |
|||
$relation_type = input('type'); |
|||
$status = input('status',0); |
|||
if($status == 1){ |
|||
$status = array('in','1,2'); |
|||
} |
|||
$data = ExamineRecordModel::where(['relation_type' => $relation_type, |
|||
'status' => $status, |
|||
'check_staff_id' => $this->auth->id])->order('id desc')->paginate($limit)->toArray(); |
|||
if($data['data']){ |
|||
foreach($data['data'] as $k=>$v){ |
|||
$data['data'][$k]['content_info'] = Message::where(array('relation_id'=>$v['id'],'relation_type'=>'examine'))->value('content'); |
|||
if ($v['relation_type'] == ExamineRecordModel::CONSUME_TYPE) { |
|||
$data['data'][$k]['relation_name'] = Consume::where(['id' => $v['relation_id']])->value('consume_type'); |
|||
} elseif ($v['relation_type'] == ExamineRecordModel::CONTRACT_TYPE) { |
|||
$data['data'][$k]['relation_name'] = Contract::where(['id' => $v['relation_id']])->value('name'); |
|||
} elseif ($v['relation_type'] == ExamineRecordModel::RECEIVABLES_TYPE) { |
|||
$data['data'][$k]['relation_name'] = Receivables::where(['id' => $v['relation_id']])->value('number'); |
|||
} elseif($v['relation_type'] == ExamineRecordModel::ACHIEVEMENT_TYPE) { |
|||
$data['data'][$k]['relation_name'] = $acchieve = AchievementRecords::where(['id' => $v['relation_id']])->value('year');; |
|||
} elseif($v['relation_type'] == ExamineRecordModel::APPROVAL_TYPE) { |
|||
$approval = Approval::where(['id' => $v['relation_id']])->value('formapproval_id'); |
|||
$data['data'][$k]['relation_name'] = ''; |
|||
if($approval){ |
|||
$data['data'][$k]['relation_name'] = FormApproval::where(['id'=>$approval])->value('name'); |
|||
} |
|||
|
|||
}elseif($v['relation_type'] == ExamineRecordModel::CARD_TYPE) { |
|||
$data['data'][$k]['relation_name'] = '补卡'; |
|||
}elseif($v['relation_type'] == ExamineRecordModel::LEAVE_TYPE) { |
|||
$data['data'][$k]['relation_name'] = '请假'; |
|||
} |
|||
else{ |
|||
$data['data'][$k]['relation_name']=''; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\File as FileModel; |
|||
|
|||
/** |
|||
* 附件接口 |
|||
*/ |
|||
class File extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//修改附件名称 |
|||
public function editName() { |
|||
$id = input("id", 0); |
|||
$name = input('name', ''); |
|||
$filemodel = new FileModel(); |
|||
$row = $filemodel->get($id); |
|||
if (empty($row)) { |
|||
$this->error('附件不存在'); |
|||
} |
|||
if ($row->save(['name' => $name])) { |
|||
$this->success('修改成功'); |
|||
} else { |
|||
$this->error('修改失败'); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,463 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Contract as ContractModel; |
|||
use addons\qingdong\model\Event; |
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\Feedback; |
|||
use addons\qingdong\model\ReceivablesPlan; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\Contacts; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Leads; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Record; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Business; |
|||
|
|||
/** |
|||
* * 操作文档:https://doc.fastadmin.net/qingdong |
|||
* 软件介绍:https://www.fastadmin.net/store/qingdong.html |
|||
* 售后微信:qingdong_crm |
|||
* 首页接口 |
|||
*/ |
|||
class Index extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = ['*']; |
|||
|
|||
public function index() |
|||
{ |
|||
$this->error("当前插件暂无前台页面"); |
|||
} |
|||
|
|||
//搜索 |
|||
public function search() |
|||
{ |
|||
$keywords = input('keywords'); |
|||
$type = input('type'); |
|||
if (empty($keywords)) { |
|||
$this->error('筛选字段不能为空'); |
|||
} |
|||
//客户 |
|||
$customer = Customer::where([ |
|||
'name' => ['like', "%$keywords%"], |
|||
'owner_staff_id' => ['in', Staff::getMyStaffIds()], |
|||
])->with([ |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->field('id,name,next_time,owner_staff_id,level,follow')->select(); |
|||
//联系人 |
|||
$contacts = Contacts::where([ |
|||
'name' => ['like', "%$keywords%"], |
|||
'owner_staff_id' => ['in', Staff::getMyStaffIds()], |
|||
])->with(['customer'])->field('id,name,mobile,customer_id')->select(); |
|||
//线索 |
|||
$leads = Leads::where([ |
|||
'name' => ['like', "%$keywords%"], |
|||
'owner_staff_id' => ['in', Staff::getMyStaffIds()], |
|||
])->with(['ownerStaff'])->field('id,owner_staff_id,name,follow,level,next_time,mobile')->select(); |
|||
|
|||
$this->success('请求成功', [ |
|||
'customer' => $customer, |
|||
'contacts' => $contacts, |
|||
'leads' => $leads |
|||
]); |
|||
} |
|||
|
|||
|
|||
//反馈 |
|||
public function feedback() |
|||
{ |
|||
$content = input('content', '', 'trim'); |
|||
$file = input('file', '', 'trim'); |
|||
if (empty($content)) { |
|||
$this->error('请输入反馈内容!'); |
|||
} |
|||
$model = new Feedback(); |
|||
$model->save([ |
|||
'staff_id' => $this->auth->id, |
|||
'content' => $content, |
|||
'file_ids' => $file |
|||
]); |
|||
$this->success('反馈成功'); |
|||
} |
|||
|
|||
|
|||
//待办事项 |
|||
public function agent() |
|||
{ |
|||
$where['create_staff_id'] = $this->auth->id; |
|||
$where['next_time'] = array(array('egt', date('Y-m-d 00:00:00')), array('lt', date('Y-m-d 23:59:59'))); |
|||
$where['follow_type'] = ['neq', '其它']; |
|||
$where['status'] = 0; |
|||
// 待跟进客户 |
|||
$where1['relation_type'] = 1; |
|||
$customerlist = Record::where($where)->where($where1)->column('id'); |
|||
$customerlist1 = 0; |
|||
if ($customerlist) { |
|||
$whereExit['id'] = array('in', $customerlist); |
|||
$whereExit['next_time'] = array('gt', date('Y-m-d 23:59:59')); |
|||
$customerlist1 = Record::where($whereExit)->count(); |
|||
} |
|||
$customer = count($customerlist) - $customerlist1; |
|||
|
|||
//待跟进合同 |
|||
$where2['relation_type'] = 3; |
|||
$contractlist = Record::where($where)->where($where2)->column('id'); |
|||
$contractlist1 = 0; |
|||
if ($contractlist) { |
|||
$whereExitC['id'] = array('in', $contractlist); |
|||
$whereExitC['next_time'] = array('gt', date('Y-m-d 23:59:59')); |
|||
$contractlist1 = Record::where($whereExitC)->count(); |
|||
} |
|||
$contract = count($contractlist) - $contractlist1; |
|||
//待跟进线索 |
|||
$where3['relation_type'] = 4; |
|||
$leadlist = Record::where($where)->where($where3)->column('id'); |
|||
$leadlist1 = 0; |
|||
if ($leadlist) { |
|||
$whereExitL['id'] = array('in', $leadlist); |
|||
$whereExitL['next_time'] = array('gt', date('Y-m-d 23:59:59')); |
|||
$leadlist1 = Record::where($whereExitL)->count(); |
|||
} |
|||
$lead = count($leadlist) - $leadlist1; |
|||
//待跟进联系人 |
|||
$where4['relation_type'] = 2; |
|||
$contactslist = Record::where($where)->where($where4)->column('id'); |
|||
$contactslist1 = 0; |
|||
if ($contactslist1) { |
|||
$whereExitCs['id'] = array('in', $contactslist); |
|||
$whereExitCs['next_time'] = array('gt', date('Y-m-d 23:59:59')); |
|||
$contactslist1 = Record::where($whereExitCs)->count(); |
|||
} |
|||
$contacts = count($contactslist) - $contactslist1; |
|||
//待跟进商机 |
|||
$where5['relation_type'] = 5; |
|||
$businesslist = Record::where($where)->where($where5)->column('id'); |
|||
$businesslist1 = 0; |
|||
if ($businesslist1) { |
|||
$whereExitB['id'] = array('in', $businesslist); |
|||
$whereExitB['next_time'] = array('gt', date('Y-m-d 23:59:59')); |
|||
$businesslist1 = Record::where($whereExitB)->count(); |
|||
} |
|||
$business = count($businesslist) - $businesslist1; |
|||
|
|||
//待审核合同 |
|||
$examine = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONTRACT_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//待审核回款 |
|||
$receivables = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::RECEIVABLES_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//待回款提醒 |
|||
$receivablesPlan = ReceivablesPlan::where([ |
|||
'remind_date' => ['elt', date('Y-m-d')], |
|||
'status' => 0, |
|||
'owner_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//待处理日程 |
|||
$eventOne = Event::where([ |
|||
'type' => 1, |
|||
'status' => ['in', [0, 1]], |
|||
'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'staff_id|owner_staff_id' => $this->auth->id, |
|||
])->count(); |
|||
$this->success('请求成功', [ |
|||
'customer' => $customer, |
|||
'business' => $business, |
|||
'contract' => $contract, |
|||
'lead' => $lead, |
|||
'contacts' => $contacts, |
|||
'event_one' => $eventOne, |
|||
'examine' => $examine, |
|||
'receivables' => $receivables, |
|||
'receivables_plan' => $receivablesPlan |
|||
]); |
|||
} |
|||
|
|||
//待处理日程 |
|||
public function event_one() |
|||
{ |
|||
// 待处理日程 |
|||
$eventTask = Event::where([ |
|||
'type' => 1, |
|||
'status' => ['in', [0, 1]], |
|||
'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'staff_id|owner_staff_id' => $this->auth->id, |
|||
])->order('id desc')->select(); |
|||
//标记通知已读 |
|||
Message::where([ |
|||
'relation_type' => Message::EVENT_TYPE, |
|||
'to_staff_id' => $this->auth->id, |
|||
'status' => 0 |
|||
])->update(['read_time' => time(), 'status' => 1]); |
|||
foreach ($eventTask as &$ves) { |
|||
$ves['start_time'] = date('Y-m-d H:i', strtotime($ves['start_time'])); |
|||
$ves['end_time'] = date('Y-m-d H:i', strtotime($ves['end_time'])); |
|||
} |
|||
$this->success('请求成功', $eventTask); |
|||
} |
|||
|
|||
//跟进任务 |
|||
public function event_task() |
|||
{ |
|||
// 待跟进任务 |
|||
$eventTask = Event::where([ |
|||
'type' => 2, |
|||
'status' => ['in', [0, 1]], |
|||
'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'staff_id' => $this->auth->id |
|||
])->select(); |
|||
foreach ($eventTask as &$ves) { |
|||
$ves['start_time'] = date('Y-m-d H:i', strtotime($ves['start_time'])); |
|||
$ves['end_time'] = date('Y-m-d H:i', strtotime($ves['end_time'])); |
|||
} |
|||
$this->success('请求成功', $eventTask); |
|||
} |
|||
|
|||
|
|||
//待审核合同 |
|||
public function examine_contract() |
|||
{ |
|||
//待审核合同 |
|||
$ids = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONTRACT_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->column('relation_id'); |
|||
$contracts = ContractModel::where(['id' => ['in', $ids]])->with([ |
|||
'customer', |
|||
'contacts', |
|||
'ownerStaff', |
|||
'orderStaff', |
|||
'receivables' |
|||
])->order('id desc')->select(); |
|||
$contracts = collection($contracts)->toArray(); |
|||
foreach ($contracts as $k => $v) { |
|||
if (empty($v['receivables'])) { |
|||
$v['receivables'] = [ |
|||
'repayment_money' => 0, |
|||
'be_money' => $v['money'], |
|||
'ratio' => 0 |
|||
]; |
|||
} else { |
|||
$be_money = $v['money'] - $v['receivables']['repayment_money']; |
|||
$v['receivables'] = [ |
|||
'repayment_money' => $v['receivables']['repayment_money'], |
|||
'be_money' => ($be_money > 0) ? $be_money : 0, |
|||
'ratio' => round($v['receivables']['repayment_money'] / $v['money'] * 100, 2) |
|||
]; |
|||
} |
|||
$contracts[$k] = $v; |
|||
} |
|||
|
|||
$this->success('请求成功', $contracts); |
|||
} |
|||
|
|||
|
|||
//待审核回款 |
|||
public function examine_receivables() |
|||
{ |
|||
//待审核回款 |
|||
$ids = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::RECEIVABLES_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id, |
|||
])->column('relation_id'); |
|||
$receivables = Receivables::where(['id' => ['in', $ids]])->with([ |
|||
'contract', |
|||
'createStaff' |
|||
])->order('id desc')->select(); |
|||
|
|||
$this->success('请求成功', $receivables); |
|||
} |
|||
|
|||
|
|||
//待回款提醒 |
|||
public function examine_receivables_plan() |
|||
{ |
|||
//待回款提醒 |
|||
$receivablesPlan = ReceivablesPlan::where([ |
|||
'remind_date' => ['elt', date('Y-m-d')], |
|||
'status' => 0, |
|||
'owner_staff_id' => $this->auth->id, |
|||
])->order('id desc')->with(['contract', 'customer'])->select(); |
|||
|
|||
$this->success('请求成功', $receivablesPlan); |
|||
} |
|||
|
|||
|
|||
//数据简报 |
|||
public function briefing() |
|||
{ |
|||
$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属 |
|||
$times = input('times', ''); |
|||
$times = explode(',', $times); |
|||
if (empty($times)) { |
|||
$this->error('参数不能为空'); |
|||
} |
|||
|
|||
$startDate=strtotime($times[0]); |
|||
$endDate=strtotime($times[1])+86400-1; |
|||
|
|||
$where = [ |
|||
'createtime' => ['between', [$startDate, $endDate]] |
|||
]; |
|||
$whereC = [ |
|||
'order_date' => ['between', [date('Y-m-d 00:00:00',$startDate), date('Y-m-d 23:59:59',$endDate)]] |
|||
]; |
|||
$whereR = [ |
|||
'return_time' => ['between', [date('Y-m-d 00:00:00',$startDate), date('Y-m-d 23:59:59',$endDate)]] |
|||
]; |
|||
if ($type == 1) { |
|||
$where['owner_staff_id'] = $this->auth->id; |
|||
$whereC['owner_staff_id'] = $this->auth->id; |
|||
$whereR['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) { |
|||
$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
$whereC['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
$whereR['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
} else { |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
$whereC['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
$whereR['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
|
|||
//客户 线索 联系人 合同 回款 跟进次数 处理审批 |
|||
$leads = Leads::where($where)->count(); |
|||
$customer = Customer::where($where)->count(); |
|||
$contacts = Contacts::where($where)->count(); |
|||
$contract = Contract::where([])->where($whereC)->count(); |
|||
$contract_money = Contract::where(['check_status'=>2])->where($whereC)->sum('money'); |
|||
$receivables_money = Receivables::where(['check_status'=>2])->where($whereR)->sum('money'); |
|||
$record = Record::where([ |
|||
'create_staff_id' => $where['owner_staff_id'], |
|||
'createtime' => $where['createtime'] |
|||
])->where(['follow_type' => ['neq', '其它']])->count(); |
|||
$examine = ExamineRecord::where([ |
|||
'check_staff_id' => $where['owner_staff_id'], |
|||
'createtime' => $where['createtime'] |
|||
])->count(); |
|||
//商机总数 |
|||
$business = Business::where($where)->count(); |
|||
//客户成交量 |
|||
$customer_complate = Customer::where($where)->where(['contract_status' => 1])->count(); |
|||
//客户未成交量 |
|||
$customer_nocomplate = Customer::where($where)->where(['contract_status' => 0])->count(); |
|||
//商机成交总数 |
|||
$business_complate = Business::where($where)->where(['contract_status' => 1])->count(); |
|||
//商机未成交总数 |
|||
$business_nocomplate = Business::where($where)->where(['contract_status' => 0])->count(); |
|||
//商机成交金额 |
|||
$business_complate_money = Business::where($where)->where(['contract_status' => 1])->sum('money'); |
|||
//商机未成交金额 |
|||
$business_nocomplate_money = Business::where($where)->where(['contract_status' => 0])->sum('money'); |
|||
$this->success('请求成功', [ |
|||
'leads' => $leads, |
|||
'customer' => $customer, |
|||
'contacts' => $contacts, |
|||
'contract' => $contract, |
|||
'contract_money' => $contract_money, |
|||
'receivables' => $receivables_money, |
|||
'record' => $record, |
|||
'business' => $business, |
|||
'examine' => $examine, |
|||
'customer_complate' => $customer_complate, |
|||
'customer_nocomplate' => $customer_nocomplate, |
|||
'business_complate' => $business_complate, |
|||
'business_nocomplate' => $business_nocomplate, |
|||
'business_complate_money' => $business_complate_money, |
|||
'business_nocomplate_money' => $business_nocomplate_money, |
|||
]); |
|||
} |
|||
|
|||
|
|||
/** |
|||
*交易额排行 |
|||
*/ |
|||
public function contractRanding() |
|||
{ |
|||
$date = input('date', date('Y-m')); |
|||
|
|||
$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属 |
|||
|
|||
|
|||
//月底 |
|||
$endDate = date('Y-m-d', strtotime('+1 month', strtotime(date($date . '-1'))) - 1); |
|||
$where = [ |
|||
'order_date' => ['between', [$date . '-1', $endDate]], |
|||
'check_status' => 2, |
|||
]; |
|||
|
|||
$contracts = Contract::where($where)->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select(); |
|||
$list = []; |
|||
foreach ($contracts as $v) { |
|||
$list[$v['owner_staff_id']] = $v['money']; |
|||
} |
|||
$contracts = $list; |
|||
$data = []; |
|||
$staffs = Staff::getList(); |
|||
foreach ($staffs as $v) { |
|||
if (isset($contracts[$v['id']])) { |
|||
$data[$v['id']] = $contracts[$v['id']]; |
|||
} else { |
|||
$data[$v['id']] = 0; |
|||
} |
|||
} |
|||
arsort($data); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$oneMoney = 0; |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
} |
|||
|
|||
foreach ($data as $id => $money) { |
|||
if ($i == 1) { |
|||
$oneMoney = $money; |
|||
} |
|||
$val = $staffs[$id]; |
|||
$val['money'] = $money; |
|||
$val['ratio'] = $oneMoney ? sprintf("%.2f", $money / $oneMoney * 100) : 0; |
|||
$val['rank'] = $i; |
|||
$i++; |
|||
if (in_array($id, $showStaffIds)) { |
|||
$result[] = $val; |
|||
} |
|||
} |
|||
|
|||
if (count($result) >= 10) { |
|||
$top = array_slice($result, 0, 3); |
|||
$bottom = array_slice($result, -3, 3); |
|||
$middle = array_slice($result, 3, 4); |
|||
$result = array_merge($top, $bottom, $middle); |
|||
} |
|||
|
|||
|
|||
$this->success('请求成功', $result); |
|||
} |
|||
|
|||
|
|||
//服务协议 |
|||
public function serviceContent() |
|||
{ |
|||
$this->success('请求成功', [ |
|||
'content' => "<h1>用户服务协议</h1>", |
|||
'name' => '青动时代', |
|||
'logo' => '' |
|||
]); |
|||
} |
|||
} |
|||
@ -0,0 +1,258 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Event; |
|||
use addons\qingdong\model\Form; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\Leads as LeadsModel; |
|||
use addons\qingdong\model\LeadsFile; |
|||
use addons\qingdong\model\LeadsOther; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Record; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 线索接口 |
|||
*/ |
|||
class Leads extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
public function _initialize() |
|||
{ |
|||
parent::_initialize(); |
|||
try{ |
|||
\think\Db::execute("SET @@sql_mode='';"); |
|||
}catch (Exception $e){ |
|||
|
|||
} |
|||
} |
|||
|
|||
//添加线索 |
|||
public function addLeads() { |
|||
$params = $this->request->post(); |
|||
if (empty($params['leads'])) { |
|||
$this->error('线索信息不能为空'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params['leads'], get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::LEADS_TYPE, $params['leads']); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
try { |
|||
$params['leads'] = Form::updateFormParams(Form::LEADS_TYPE, $params['leads']); |
|||
$leadsId = LeadsModel::createLeads($params['leads']); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('添加线索成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取线索列表 |
|||
public function getList() { |
|||
$name = input('name', '', 'trim'); |
|||
$mobile = input('mobile', '', 'trim'); |
|||
$limit = input("limit/d", 10); |
|||
$params = $this->request->post(); |
|||
|
|||
$where= FormField::updateWhereField(FormField::LEADS_TYPE,$params); |
|||
|
|||
if (isset($params['createtime']) && $params['createtime']) {//跟进状态 |
|||
$createtime = $params['createtime']; |
|||
$createtime = explode(',', $createtime); |
|||
$where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1])+86400-1]]; |
|||
} |
|||
$wheres=[]; |
|||
//0:全部 1:我负责的 2:下属负责的 3:今日待跟进 4:今日已跟进 5:从未跟进的 |
|||
$team = input('team',0); |
|||
switch($team){ |
|||
case 1: |
|||
$staff = Staff::info(); |
|||
$wheres['owner_staff_id'] = $staff->id; |
|||
break; |
|||
case 2: |
|||
$wheres['owner_staff_id'] = array('in',Staff::getLowerStaffId()); |
|||
break; |
|||
case 3: |
|||
$start = date('Y-m-d 00:00:00'); |
|||
$end = date('Y-m-d 23:59:59'); |
|||
$record = collection(Record::where(array('status'=>0,'relation_type'=>4,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray(); |
|||
$relationId = []; |
|||
foreach($record as $k=>$v){ |
|||
$whereRe['id'] = array('gt',$v['id']); |
|||
$whereRe['relation_id'] = $v['relation_id']; |
|||
$recordData = Record::where($whereRe)->count(); |
|||
if($recordData == 0){ |
|||
$relationId[] = $v['relation_id']; |
|||
} |
|||
|
|||
} |
|||
$wheres['id'] = array('in',$relationId); |
|||
$staff = Staff::info(); |
|||
$wheres['owner_staff_id'] = $staff->id; |
|||
break; |
|||
case 4: |
|||
$start = date('Y-m-d 00:00:00'); |
|||
$end = date('Y-m-d 23:59:59'); |
|||
$relationId = Record::where(array('status'=>1,'relation_type'=>4,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->column('relation_id'); |
|||
$wheres['id'] = array('in',$relationId); |
|||
$staff = Staff::info(); |
|||
$wheres['owner_staff_id'] = $staff->id; |
|||
break; |
|||
case 5: |
|||
$record = collection(Record::where(array('relation_type'=>4))->column('relation_id'))->toArray(); |
|||
$wheres['id'] = array('not in',$record); |
|||
$staff = Staff::info(); |
|||
$wheres['owner_staff_id'] = $staff->id; |
|||
break; |
|||
default: |
|||
$wheres['owner_staff_id'] = array('in',Staff::getMyStaffIds()); |
|||
break; |
|||
|
|||
} |
|||
if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选 |
|||
$wheres['owner_staff_id'] = $params['staff_id']; |
|||
} |
|||
|
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
if ($mobile) { |
|||
$where['mobile'] = ['like', "%{$mobile}%"]; |
|||
} |
|||
$where['is_transform']=0; |
|||
$records = LeadsModel::where($where)->where($wheres)->with(['ownerStaff'])->field('id,owner_staff_id,name,follow,mobile,level,next_time,source')->order('id desc')->paginate($limit); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取线索详情 |
|||
public function getDetail() { |
|||
$id = input('id', '', 'intval'); |
|||
$leads = LeadsModel::where(['id' => $id])->with([ |
|||
'createStaff', |
|||
'ownerStaff', |
|||
'tranferStaff' |
|||
])->find(); |
|||
if(empty($leads)){ |
|||
$this->error('信息不存在'); |
|||
} |
|||
$leads=$leads->toArray(); |
|||
$leads=LeadsOther::getOther($leads); |
|||
$this->success('请求成功', $leads); |
|||
} |
|||
|
|||
|
|||
//获取选择列表 |
|||
public function getSelectList() { |
|||
$name = input('name',''); |
|||
|
|||
$where = ['owner_staff_id' => $this->auth->id,'is_transform'=>0]; |
|||
if ($name) { |
|||
$where['name'] = ['like',"%$name%"]; |
|||
} |
|||
|
|||
$records = LeadsModel::where($where)->field('id,owner_staff_id,name,follow,mobile')->order('id desc')->select(); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//转移线索 |
|||
public function transfer() |
|||
{ |
|||
$id = input('id'); |
|||
$staff_id = input('staff_id'); |
|||
if (!$staff_id || !$id) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$staff = Staff::get($staff_id); |
|||
if (empty($staff)) { |
|||
$this->error('接收对象不存在'); |
|||
} |
|||
$row = LeadsModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('线索不存在'); |
|||
} |
|||
try { |
|||
LeadsModel::transfer($id, $staff_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('转移线索成功'); |
|||
} |
|||
|
|||
|
|||
//修改线索 |
|||
public function editLeads() { |
|||
|
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = LeadsModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('您不是线索负责人无法修改信息'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::LEADS_TYPE, $params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
try { |
|||
$params= Form::updateFormParams(Form::LEADS_TYPE, $params); |
|||
LeadsModel::updateLeads($params); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('修改线索成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//删除线索 |
|||
public function delLeads() { |
|||
$id = input('id'); |
|||
$model = new LeadsModel(); |
|||
$row = $model->where(['owner_staff_id' => $this->auth->id, 'id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('您没有权限删除线索'); |
|||
} |
|||
if($row->owner_staff_id != $this->auth->id){ |
|||
$this->error('您没有权限删除线索'); |
|||
} |
|||
Db::startTrans(); |
|||
try{ |
|||
$model->where(['id' => $id])->delete(); |
|||
$enentWhere = [ |
|||
'relation_id' => $id, |
|||
'type' => 2, |
|||
'relation_type' => Event::LEADS_TYPE, |
|||
]; |
|||
Event::where($enentWhere)->delete(); |
|||
Db::commit(); |
|||
}catch (Exception $e){ |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('删除成功'); |
|||
} |
|||
|
|||
|
|||
//获取附件列表 |
|||
public function getFilesList() { |
|||
$id = input('leads_id'); |
|||
|
|||
$files = LeadsFile::where(['leads_id' => $id])->field('file_id')->with(['file'])->select(); |
|||
$this->success('请求成功', $files); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Event; |
|||
use addons\qingdong\model\Leads as LeadsModel; |
|||
use addons\qingdong\model\LeadsFile; |
|||
use addons\qingdong\model\LeadsOther; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Record; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 线索池接口 |
|||
*/ |
|||
class Leadspool extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
public function _initialize() |
|||
{ |
|||
parent::_initialize(); |
|||
try{ |
|||
\think\Db::execute("SET @@sql_mode='';"); |
|||
}catch (Exception $e){ |
|||
|
|||
} |
|||
} |
|||
|
|||
//添加线索 |
|||
public function addLeads() { |
|||
$params = $this->request->post(); |
|||
if (empty($params['leads'])) { |
|||
$this->error('线索信息不能为空'); |
|||
} |
|||
|
|||
try { |
|||
$leadsId = LeadsModel::createLeads($params['leads'],1); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($leadsId) { |
|||
$this->success('添加线索成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取线索列表 |
|||
public function getList() { |
|||
$name = input('name', '', 'trim'); |
|||
$mobile = input('mobile', '', 'trim'); |
|||
$limit = input("limit/d", 10); |
|||
$params = $this->request->post(); |
|||
$where = []; |
|||
|
|||
if (isset($params['createtime']) && $params['createtime']) {//跟进状态 |
|||
$createtime = $params['createtime']; |
|||
$createtime = explode(',', $createtime); |
|||
$where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1])+86400-1]]; |
|||
} |
|||
|
|||
|
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
if ($mobile) { |
|||
$where['mobile'] = ['like', "%{$mobile}%"]; |
|||
} |
|||
$records = LeadsModel::where($where)->where('owner_staff_id is null or owner_staff_id = 0')->with(['createStaff'])->field('id,create_staff_id,name,follow,mobile,level,next_time,source')->order('id desc')->paginate($limit); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取线索详情 |
|||
public function getDetail() { |
|||
$id = input('id', '', 'intval'); |
|||
$leads = LeadsModel::where(['id' => $id])->with([ |
|||
'createStaff', |
|||
])->find(); |
|||
if(empty($leads)){ |
|||
$this->error('信息不存在'); |
|||
} |
|||
$leads=$leads->toArray(); |
|||
$leads=LeadsOther::getOther($leads); |
|||
$this->success('请求成功', $leads); |
|||
} |
|||
|
|||
|
|||
//获取选择列表 |
|||
public function getSelectList() { |
|||
$name = input('name',''); |
|||
|
|||
$where = ['owner_staff_id' => $this->auth->id,'is_transform'=>0]; |
|||
if ($name) { |
|||
$where['name'] = ['like',"%$name%"]; |
|||
} |
|||
|
|||
$records = LeadsModel::where($where)->field('id,owner_staff_id,name,follow,mobile')->order('id desc')->select(); |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//转移线索 |
|||
public function transfer() |
|||
{ |
|||
$id = input('id'); |
|||
$staff_id = input('staff_id'); |
|||
if (!$staff_id && !$id) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$row = LeadsModel::where(['id' =>['in',$id] ])->find(); |
|||
if (empty($row)) { |
|||
$this->error('线索不存在'); |
|||
} |
|||
$id = explode(',',$id); |
|||
try { |
|||
LeadsModel::transfer($id, $staff_id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('转移成功'); |
|||
} |
|||
|
|||
|
|||
//修改线索 |
|||
public function editLeads() { |
|||
|
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = LeadsModel::where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('线索信息不存在'); |
|||
} |
|||
|
|||
try { |
|||
$result = LeadsModel::updateLeads($params); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('修改线索成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//删除线索 |
|||
public function delLeads() { |
|||
$id = input('id'); |
|||
$model = new LeadsModel(); |
|||
$row = $model->where(['id' => $id])->find(); |
|||
if (empty($row)) { |
|||
$this->error('线索不存在'); |
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try{ |
|||
$model->where(['id' => $id])->delete(); |
|||
$enentWhere = [ |
|||
'relation_id' => $id, |
|||
'type' => 2, |
|||
'relation_type' => Event::LEADS_TYPE, |
|||
]; |
|||
Event::where($enentWhere)->delete(); |
|||
Db::commit(); |
|||
}catch (Exception $e){ |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('删除成功'); |
|||
} |
|||
|
|||
|
|||
//获取附件列表 |
|||
public function getFilesList() { |
|||
$id = input('leads_id'); |
|||
|
|||
$files = LeadsFile::where(['leads_id' => $id])->field('file_id')->with(['file'])->select(); |
|||
$this->success('请求成功', $files); |
|||
} |
|||
//领取线索 |
|||
public function achieve() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$row = LeadsModel::where(['id' =>$id ])->find(); |
|||
if (empty($row)) { |
|||
$this->error('线索不存在'); |
|||
} |
|||
try { |
|||
LeadsModel::transfer($id, $this->auth->id); |
|||
} catch (Exception $e) { |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('领取成功'); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,250 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Event; |
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\Message as MessageModel; |
|||
use addons\qingdong\model\Notice; |
|||
use addons\qingdong\model\ReceivablesPlan; |
|||
use addons\qingdong\model\Record; |
|||
|
|||
/** |
|||
* 通知接口 |
|||
*/ |
|||
class Message extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
/** |
|||
* 获取通知列表 |
|||
*/ |
|||
public function getList() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
|
|||
$where = ['to_staff_id' => $this->auth->id ,'relation_type'=>['neq',MessageModel::EXAMINE_TYPE]]; |
|||
$records = MessageModel::where($where)->with(['fromStaff', 'examine'])->order('status asc,id desc')->paginate($limit); |
|||
|
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
/** |
|||
* 获取审批列表 |
|||
*/ |
|||
public function getExamineRecord() |
|||
{ |
|||
$limit = input("limit/d", 10); |
|||
//合同审批,回款审批、业绩目标审批、办公审批 费用 |
|||
$relation_type = input('type'); |
|||
$status = input('status',0); |
|||
if($status == 1){ |
|||
$status = array('in','2,3'); |
|||
} |
|||
$ids = ExamineRecord::where(['relation_type' => $relation_type, |
|||
'status' => $status, |
|||
'check_staff_id' => $this->auth->id])->column('id'); |
|||
$where = ['to_staff_id' => $this->auth->id, 'relation_id' => ['in', $ids], 'relation_type' => MessageModel::EXAMINE_TYPE]; |
|||
|
|||
$records = MessageModel::where($where)->with(['fromStaff', 'examine'])->order('status asc,id desc')->paginate($limit); |
|||
|
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
/** |
|||
* 获取审批通知详情 |
|||
*/ |
|||
public function getExamineInfo() |
|||
{ |
|||
|
|||
$data = [ |
|||
ExamineRecord::CONTRACT_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::CONSUME_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::RECEIVABLES_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::APPROVAL_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::ACHIEVEMENT_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::CARD_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
ExamineRecord::LEAVE_TYPE => ['count' => 0, 'msg' => '暂无消息'], |
|||
]; |
|||
foreach ($data as $type=>$v) { |
|||
$ids = ExamineRecord::where(['status' => 0, 'check_staff_id' => $this->auth->id, |
|||
'relation_type' => $type |
|||
])->column('id'); |
|||
$count = MessageModel::where(['to_staff_id' => $this->auth->id,'relation_id' => ['in', $ids], |
|||
'relation_type' => MessageModel::EXAMINE_TYPE]) |
|||
->count(); |
|||
if ($count) { |
|||
$msg = MessageModel::where(['to_staff_id' => $this->auth->id, 'relation_id' => ['in', $ids], |
|||
'relation_type' => MessageModel::EXAMINE_TYPE]) |
|||
->order('id desc') |
|||
->value('content'); |
|||
$data[$type] = ['count' => $count, 'msg' => $msg]; |
|||
} |
|||
} |
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
/** |
|||
* 获取通知详情 |
|||
*/ |
|||
public function getInfo() |
|||
{ |
|||
$leadsCount = MessageModel::where(['to_staff_id' => $this->auth->id, |
|||
'relation_type' => ['neq', MessageModel::EXAMINE_TYPE], 'status' => 0])->count(); |
|||
if ($leadsCount > 0) {//其他提醒消息 |
|||
$leadsDetail = MessageModel::where([ |
|||
'relation_type' => ['neq', MessageModel::EXAMINE_TYPE], |
|||
'to_staff_id' => $this->auth->id, |
|||
'status' => 0 |
|||
])->order('id desc')->find(); |
|||
} |
|||
|
|||
$noticeWhere['read_staff_ids'] = ['not like', "%,{$this->auth->id},%"]; |
|||
|
|||
$noticeCount = Notice::where($noticeWhere)->count(); |
|||
if ($noticeCount > 0) { |
|||
$noticeDetail = Notice::where(['read_staff_ids' => ['not like', "%,{$this->auth->id},%"]])->order('id desc')->find(); |
|||
} |
|||
|
|||
$eventOne = Event::where([ |
|||
'type' => 1, |
|||
'status' => ['in', [0, 1]], |
|||
'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'staff_id|owner_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//合同审批 |
|||
$contract = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONTRACT_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//回款审批 |
|||
$receivables = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::RECEIVABLES_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//费用审批 |
|||
$consume = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CONSUME_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//业绩目标审批 |
|||
$achievement = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::ACHIEVEMENT_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//办公审批 |
|||
$approval = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::APPROVAL_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//补卡审批 |
|||
$card = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::CARD_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
//请假审批 |
|||
$leave = ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::LEAVE_TYPE, |
|||
'status' => 0, |
|||
'check_staff_id' => $this->auth->id |
|||
])->count(); |
|||
$receivablesPlan = ReceivablesPlan::where([ |
|||
'remind_date' => ['elt', date('Y-m-d')], |
|||
'status' => 0, |
|||
'owner_staff_id' => $this->auth->id |
|||
])->count(); |
|||
|
|||
$eventsCount = Event::where([ |
|||
'start_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'end_time' => ['lt', date('Y-m-d', strtotime('+1 day'))], |
|||
'status' => ['in', [0, 1]], |
|||
'staff_id' => $this->auth->id, |
|||
])->count(); |
|||
|
|||
$where['create_staff_id'] = $this->auth->id; |
|||
$where['next_time'] = array(array('egt',date('Y-m-d 00:00:00')),array('lt',date('Y-m-d 23:59:59'))); |
|||
$where['follow_type'] = ['neq', '其它']; |
|||
$where['status'] = 0; |
|||
// 待跟进客户 |
|||
$where1['relation_type'] = 1; |
|||
$customerlist = Record::where($where)->where($where1)->column('id'); |
|||
$customerlist1 = 0; |
|||
if($customerlist){ |
|||
$whereExit['id'] = array('in',$customerlist); |
|||
$whereExit['next_time'] = array('gt',date('Y-m-d 23:59:59')); |
|||
$customerlist1 = Record::where($whereExit)->count(); |
|||
} |
|||
$customer = count($customerlist) - $customerlist1; |
|||
|
|||
//待跟进合同 |
|||
$where2['relation_type'] = 3; |
|||
$contractlist = Record::where($where)->where($where2)->column('id'); |
|||
$contractlist1 = 0; |
|||
if($contractlist){ |
|||
$whereExitC['id'] = array('in',$contractlist); |
|||
$whereExitC['next_time'] = array('gt',date('Y-m-d 23:59:59')); |
|||
$contractlist1 = Record::where($whereExitC)->count(); |
|||
} |
|||
$contracts = count($contractlist)-$contractlist1; |
|||
//待跟进线索 |
|||
$where3['relation_type'] = 4; |
|||
$leadlist = Record::where($where)->where($where3)->column('id'); |
|||
$leadlist1 = 0; |
|||
if($leadlist){ |
|||
$whereExitL['id'] = array('in',$leadlist); |
|||
$whereExitL['next_time'] = array('gt',date('Y-m-d 23:59:59')); |
|||
$leadlist1 = Record::where($whereExitL)->count(); |
|||
} |
|||
$lead = count($leadlist)-$leadlist1; |
|||
//待跟进联系人 |
|||
$where4['relation_type'] = 2; |
|||
$contactslist = Record::where($where)->where($where4)->column('id'); |
|||
$contactslist1 = 0; |
|||
if($contactslist1){ |
|||
$whereExitCs['id'] = array('in',$contactslist); |
|||
$whereExitCs['next_time'] = array('gt',date('Y-m-d 23:59:59')); |
|||
$contactslist1 = Record::where($whereExitCs)->count(); |
|||
} |
|||
$contacts = count($contactslist)-$contactslist1; |
|||
//待跟进商机 |
|||
$where5['relation_type'] = 5; |
|||
$businesslist = Record::where($where)->where($where5)->column('id'); |
|||
$businesslist1 = 0; |
|||
if($businesslist1){ |
|||
$whereExitB['id'] = array('in',$businesslist); |
|||
$whereExitB['next_time'] = array('gt',date('Y-m-d 23:59:59')); |
|||
$businesslist1 = Record::where($whereExitB)->count(); |
|||
} |
|||
$business = count($businesslist)-$businesslist1; |
|||
//提醒消息 |
|||
$data = [ |
|||
'leads' => ['count' => $leadsCount, 'msg' => $leadsDetail['content'] ?? '暂无消息'],//提醒消息 |
|||
'examine' => ['count' => $contract + $receivables+$consume+$achievement+$approval+$card+$leave, |
|||
'msg' => '审批消息提醒'],//提醒消息 |
|||
'notice' => ['count' => $noticeCount, 'msg' => $noticeDetail['title'] ?? '暂无消息'],//系统公告 |
|||
'agent' => [ |
|||
'count' => $eventOne + $receivablesPlan+ $customer + $contracts + $lead + $contacts + $business, |
|||
'msg' => '您有新的待办事项需要处理!' |
|||
],//待办事项 |
|||
'task' => [ |
|||
'count' => $eventsCount, |
|||
'msg' => '即将超时的任务提醒!' |
|||
],//超时任务 |
|||
'total' => $leadsCount + $noticeCount + $eventOne + $contract + $receivables + $receivablesPlan + $eventsCount+ $customer + $contracts + $lead + $contacts + $business+$consume+$achievement+$approval+$card+$leave, |
|||
|
|||
'userinfo' => $this->auth->getUserinfo() |
|||
]; |
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Notice as NoticeModel; |
|||
|
|||
/** |
|||
* 公告接口 |
|||
*/ |
|||
class Notice extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//公告列表 |
|||
public function getList() { |
|||
$limit = input("limit/d", 10); |
|||
|
|||
|
|||
$records = NoticeModel::where([])->order('id desc')->paginate($limit); |
|||
$items = $records->items(); |
|||
foreach ($items as $k => $v) { |
|||
$read_staff_ids = explode(',', $v['read_staff_ids']); |
|||
$v['is_show'] = in_array($this->auth->id, $read_staff_ids); |
|||
$items[$k] = $v; |
|||
} |
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
//获取公告详情 |
|||
public function getDetail() { |
|||
$id = input('id', '', 'intval'); |
|||
$notice = NoticeModel::where(['id' => $id,])->find(); |
|||
if (empty($notice)) { |
|||
$this->error('公告不存在'); |
|||
} |
|||
preg_match_all('/<img.+src=\"?(.+\.(jpg|gif|bmp|bnp|png))\"?.+>/i',$notice['content'],$match); |
|||
foreach ($match[1] as $v){ |
|||
$notice['content']=str_replace($v,cdnurl($v,true),$notice['content']); |
|||
} |
|||
$read_staff_ids = explode(',', $notice['read_staff_ids']); |
|||
if (!in_array($this->auth->id, $read_staff_ids)) { |
|||
$read_staff_ids[] = $this->auth->id; |
|||
NoticeModel::where(['id' => $notice['id']])->update(['read_staff_ids' => implode(',', $read_staff_ids).',']); |
|||
} |
|||
|
|||
$this->success('请求成功', $notice); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\OperationLog; |
|||
/** |
|||
* 操作记录 |
|||
*/ |
|||
class Operation extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
// |
|||
public function getList() { |
|||
$relation_type = input('relation_type', '');//1客户 2联系人 3合同 |
|||
$relation_id = input('relation_id', ''); |
|||
if(empty($relation_type) || empty($relation_id)){ |
|||
$this->error('参数不能为空'); |
|||
} |
|||
//操作记录 |
|||
$logs=OperationLog::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $relation_id, |
|||
'operation_type' => 1 |
|||
])->field('id,content,operation_id,createtime')->with(['staff'])->select(); |
|||
$this->success('请求成功',$logs); |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Product as ProductModel; |
|||
use addons\qingdong\model\ProductPart; |
|||
use addons\qingdong\model\Producttype; |
|||
|
|||
|
|||
/** |
|||
* 产品 |
|||
*/ |
|||
class Product extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
/** |
|||
* 获取select产品列表 |
|||
*/ |
|||
public function getSelectList() |
|||
{ |
|||
$name = input('name'); |
|||
$type_id = input('type_id'); |
|||
$where = []; |
|||
if ($name) { |
|||
$where['name|num'] = ['like', "%{$name}%"]; |
|||
} |
|||
if ($type_id) { |
|||
$where['type_id'] = $type_id; |
|||
} |
|||
$list = ProductModel::where($where)->field('id,name,type,num,img,unit,price,min_price,status,cost_price,wholesale')->select(); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
/** |
|||
* 获取产品分类列表 |
|||
*/ |
|||
public function getProducttypeList() |
|||
{ |
|||
$name = input('name'); |
|||
$where=[]; |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
$list = Producttype::where($where)->field('id,name')->select(); |
|||
|
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
/** |
|||
* 获取产品配置列表 |
|||
*/ |
|||
public function getPartList() |
|||
{ |
|||
$product_id = input('product_id'); |
|||
$name = input('name'); |
|||
$where = []; |
|||
if ($name) { |
|||
$where['name'] = ['like', "%{$name}%"]; |
|||
} |
|||
$where['product_id'] = $product_id; |
|||
$list = ProductPart::where($where)->field('id,name,img,description')->select(); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
/** |
|||
* 获取产品详情 |
|||
*/ |
|||
public function getProductDetail() |
|||
{ |
|||
$id = input('id'); |
|||
$product = ProductModel::where(['id' => $id])->find(); |
|||
if (empty($product)) { |
|||
$this->error('产品不存在'); |
|||
} |
|||
preg_match_all("/(<img .*?src=\")(.*?)(\".*?>)/is", $product['description'], $matchpic); |
|||
foreach ($matchpic[2] as $url) { |
|||
$img = cdnurl($url, true); |
|||
$product['description'] = str_replace($url, $img, $product['description']); |
|||
} |
|||
$this->success('请求成功', $product); |
|||
} |
|||
|
|||
/** |
|||
* 添加产品 |
|||
*/ |
|||
public function addProduct() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if ($params) { |
|||
$parts = $params['parts'] ?? []; |
|||
|
|||
$model = new ProductModel(); |
|||
$model->allowField(true)->save($params); |
|||
$lastid = $model->getLastInsID(); |
|||
$partModel = new ProductPart(); |
|||
foreach ($parts as &$v) { |
|||
$v['product_id'] = $lastid; |
|||
} |
|||
$partModel->allowField(true)->saveAll($parts); |
|||
$this->success('添加产品成功'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 添加产品配件 |
|||
*/ |
|||
public function addProductPart() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if ($params) { |
|||
$partModel = new ProductPart(); |
|||
|
|||
$partModel->save($params); |
|||
$this->success('添加产品配置成功'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 修改产品信息 |
|||
*/ |
|||
public function editProduct() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if ($params) { |
|||
$model = new ProductModel(); |
|||
$row = $model->get($params['id']); |
|||
if (empty($row)) { |
|||
$this->error('产品不存在'); |
|||
} |
|||
$row->allowField(true)->save($params); |
|||
|
|||
$this->success('添加产品成功'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 修改产品配件 |
|||
*/ |
|||
public function editProductPart() |
|||
{ |
|||
$params = $this->request->post(); |
|||
if ($params) { |
|||
$partModel = new ProductPart(); |
|||
$row = $partModel->get($params['id']); |
|||
if (empty($row)) { |
|||
$this->error('产品配置不存在'); |
|||
} |
|||
$row->allowField(true)->save($params); |
|||
|
|||
$this->success('修改产品配置成功'); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,207 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\ExamineRecord; |
|||
use addons\qingdong\model\FormField; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Receivables as ReceivablesModel; |
|||
use addons\qingdong\model\ReceivablesOther; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 回款详情 |
|||
*/ |
|||
class Receivables extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//新增回款 |
|||
public function addReceivables() { |
|||
$params = $this->request->post(); |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
|
|||
$result = FormField::checkFields(FormField::RECEIVABLES_TYPE, $params); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (ReceivablesModel::where(['number' => $params['number'], 'contract_id' => $params['contract_id']])->find()) { |
|||
$this->error('回款编号已存在'); |
|||
} |
|||
$contract=Contract::where(['id'=>$params['contract_id']])->find(); |
|||
if(empty($contract)){ |
|||
$this->error('合同不存在'); |
|||
} |
|||
if($contract['check_status'] != 2){ |
|||
$this->error('当前合同未审核通过'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$params['owner_staff_id'] = $contract['owner_staff_id']; |
|||
|
|||
ReceivablesModel::createReceivables($params); |
|||
|
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('新增回款成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取回款列表 |
|||
public function getList() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
$contract_id = input('contract_id'); |
|||
$times = input('times'); |
|||
$staff_id = input('staff_id'); |
|||
$check_status = input('check_status'); |
|||
$limit = input('limit'); |
|||
$type = input('type',0); |
|||
$params=input(); |
|||
$where= FormField::updateWhereField(FormField::RECEIVABLES_TYPE,$params); |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($contract_id) { |
|||
$where['contract_id'] = $contract_id; |
|||
} |
|||
if ($staff_id) { |
|||
$where['owner_staff_id'] = $staff_id; |
|||
} else { |
|||
|
|||
if ($type == 1) {//我的客户 |
|||
$where['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
}else{ |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
} |
|||
|
|||
if ($times) {//回款日期 |
|||
$times = explode(',', $times); |
|||
$where['return_time'] = ['between', [$times[0], $times[1]]]; |
|||
} |
|||
if ($check_status) { |
|||
if ($check_status == 1) {//审核中 |
|||
$where['check_status'] = ['in', [0, 1]]; |
|||
} elseif ($check_status == 2) {//审核通过 |
|||
$where['check_status'] = 2; |
|||
} elseif ($check_status == 3) {//其他 |
|||
$where['check_status'] = ['in', [3, 4]]; |
|||
} |
|||
} |
|||
$list = ReceivablesModel::where($where)->with(['contract'])->order('id desc')->paginate($limit)->toArray(); |
|||
|
|||
$remoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']]) |
|||
->where(array('check_status'=>2))->sum('money'); |
|||
$inmoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']]) |
|||
->where(array('check_status'=>['in',[0,1]]))->sum('money'); |
|||
$nomoney = ReceivablesModel::where(['owner_staff_id'=>$where['owner_staff_id']]) |
|||
->where(array('check_status'=>['in',[3,4]]))->sum('money'); |
|||
$moneyinfo['remoney'] = $remoney;//已回款 |
|||
$moneyinfo['inmoney'] = $inmoney;//回款中 |
|||
$moneyinfo['nomoney'] = $nomoney;//未回款 |
|||
$moneyinfo['allmoney'] = $remoney+$inmoney+$nomoney;//总金额 |
|||
$list['moneyinfo']=$moneyinfo; |
|||
$this->success('请求成功',$list); |
|||
} |
|||
|
|||
|
|||
//回款详情 |
|||
public function getDetail() { |
|||
$id = input('id'); |
|||
$receivables = ReceivablesModel::where(['id' => $id])->with([ |
|||
'customer', |
|||
'contract', |
|||
'plan', |
|||
'ownerStaff', |
|||
'createStaff' |
|||
])->find(); |
|||
|
|||
if (empty($receivables)) { |
|||
//标记通知已读 |
|||
Message::setRead(Message::RECEIVABLES_TYPE, $id, $this->auth->id); |
|||
$this->error('信息不存在'); |
|||
} |
|||
$receivables=$receivables->toArray(); |
|||
|
|||
$receivables=ReceivablesOther::getOther($receivables); |
|||
//标记通知已读 |
|||
Message::setRead(Message::RECEIVABLES_TYPE, $id, $this->auth->id); |
|||
$this->success('请求成功', $receivables); |
|||
} |
|||
|
|||
|
|||
//撤回审核 |
|||
public function cancel() { |
|||
$id = input('id'); |
|||
$customer = ReceivablesModel::where(['id' => $id, 'check_status' => 1])->find(); |
|||
if (empty($customer)) { |
|||
$this->error('回款信息不存在'); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
|
|||
ReceivablesModel::where(['id' => $id])->update(['check_status' => 4]); |
|||
ExamineRecord::where([ |
|||
'relation_type' => ExamineRecord::RECEIVABLES_TYPE, |
|||
'relation_id' => $id, |
|||
'status' => 0 |
|||
])->update(['status' => 3]); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback();; |
|||
$this->error($e->getMessage()); |
|||
} |
|||
|
|||
|
|||
$this->success('撤回成功'); |
|||
} |
|||
|
|||
|
|||
//修改回款 |
|||
public function editReceivables() { |
|||
$id = input('id'); |
|||
$params = $this->request->post(); |
|||
$row = ReceivablesModel::where(['id' => $id, 'check_status' => ['in', [3, 4]]])->find(); |
|||
if (empty($row)) { |
|||
$this->error('回款信息不存在'); |
|||
} |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
$result = FormField::checkFields(FormField::RECEIVABLES_TYPE, $params,$id); |
|||
if ($result !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
ReceivablesModel::updateReceivables($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
$this->success('修改回款信息成功'); |
|||
} |
|||
//获取回款编号 |
|||
public function getReceivablesNumber() |
|||
{ |
|||
$this->success('请求成功', ['number' => ReceivablesModel::getNum()]); |
|||
} |
|||
} |
|||
@ -0,0 +1,112 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\ReceivablesPlan as ReceivablesPlanModel; |
|||
use addons\qingdong\model\Staff; |
|||
use think\Db; |
|||
use think\Exception; |
|||
|
|||
/** |
|||
* 回款计划 |
|||
*/ |
|||
class ReceivablesPlan extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
//新增回款计划 |
|||
public function addPlan() { |
|||
$params = $this->request->post(); |
|||
|
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
if (ReceivablesPlanModel::where([ |
|||
'num' => $params['num'], |
|||
'contract_id' => $params['contract_id'] |
|||
])->find()) { |
|||
$this->error('计划回款期数已存在'); |
|||
} |
|||
|
|||
Db::startTrans(); |
|||
try { |
|||
ReceivablesPlanModel::createPlan($params); |
|||
|
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('新增回款计划成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取回款计划列表 |
|||
public function getList() |
|||
{ |
|||
$customer_id = input('customer_id'); |
|||
$contract_id = input('contract_id'); |
|||
$times = input('times'); |
|||
$staff_id = input('staff_id'); |
|||
$status = input('status', null); |
|||
$limit = input('limit'); |
|||
$type = input('type',0); |
|||
$where = []; |
|||
if ($customer_id) { |
|||
$where['customer_id'] = $customer_id; |
|||
} |
|||
if ($contract_id) { |
|||
$where['contract_id'] = $contract_id; |
|||
} |
|||
if ($staff_id) { |
|||
$where['owner_staff_id'] = $staff_id; |
|||
} else { |
|||
|
|||
if ($type == 1) {//我的客户 |
|||
$where['owner_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$where['owner_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
}else{ |
|||
$where['owner_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
|
|||
} |
|||
if ($times) {//计划回款日期 |
|||
$times = explode(',', $times); |
|||
$where['return_date'] = ['between', [$times[0], $times[1]]]; |
|||
} |
|||
if($status !== null){ |
|||
$where['status'] = $status; |
|||
} |
|||
|
|||
$list = ReceivablesPlanModel::where($where)->with(['contract', 'customer', 'createStaff']) |
|||
->order('id desc')->paginate($limit); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//获取select回款计划列表 |
|||
public function getSelectList() { |
|||
$contract_id = input('contract_id'); |
|||
$where = []; |
|||
$where['contract_id'] = $contract_id; |
|||
$where['status'] = 0; |
|||
$list = ReceivablesPlanModel::where($where)->field('id,num')->select(); |
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
|
|||
//回款详情 |
|||
public function getDetail() { |
|||
$id = input('id'); |
|||
$customer = ReceivablesPlanModel::where(['id' => $id])->with(['contract', 'customer', 'createStaff'])->find(); |
|||
//标记通知已读 |
|||
Message::setRead(Message::PLAN_TYPE, $id, $this->auth->id); |
|||
$this->success('请求成功', $customer); |
|||
} |
|||
} |
|||
@ -0,0 +1,368 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Comment; |
|||
use addons\qingdong\model\Contacts; |
|||
use addons\qingdong\model\Message; |
|||
use addons\qingdong\model\Record as RecordModel; |
|||
use addons\qingdong\model\RecordRead; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Leads; |
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\Business; |
|||
use think\Db; |
|||
use think\Exception; |
|||
use function EasyWeChat\Kernel\Support\get_client_ip; |
|||
|
|||
/** |
|||
* 跟进记录 |
|||
*/ |
|||
class Record extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
/** |
|||
* 获取跟进记录 |
|||
*/ |
|||
public function getList() { |
|||
$relation_type = input('relation_type', '', 'intval');// 1客户 2联系人 3合同 5商机 |
|||
$relation_id = input('relation_id', '', 'intval'); |
|||
$limit = input("limit/d", 10); |
|||
$is_read = input('is_read', 0); |
|||
$type = input('type', 0);// 0 全部 1 我创建 2 下属创建 |
|||
$follow_type = input('follow_type', ''); |
|||
$times = input('times',''); |
|||
$where = []; |
|||
if ($relation_type) { |
|||
$where['relation_type'] = $relation_type; |
|||
if($relation_id){ |
|||
$where['relation_id'] = $relation_id; |
|||
} |
|||
|
|||
} |
|||
if ($type == 1) {//我的客户 |
|||
$where['create_staff_id'] = $this->auth->id; |
|||
} elseif ($type == 2) {//下属负责的客户 |
|||
$where['create_staff_id'] = ['in', Staff::getLowerStaffId()]; |
|||
}else{ |
|||
$where['create_staff_id'] = ['in', Staff::getMyStaffIds()]; |
|||
} |
|||
|
|||
if($follow_type){ |
|||
$where['follow_type'] = $follow_type; |
|||
}else{ |
|||
$where['follow_type'] = ['neq', '其它']; |
|||
} |
|||
if ($times) { |
|||
$times = explode(',', $times); |
|||
$where['createtime'] = ['between', [strtotime($times[0]), strtotime($times[1]) + 86400 - 1]]; |
|||
} |
|||
$staff_id = $this->auth->id; |
|||
if ($is_read == 1) {//已读 |
|||
$ids = RecordRead::where(['staff_id' => $staff_id])->column('record_id'); |
|||
$where['id'] = ['in', $ids]; |
|||
} elseif ($is_read == 2) {//未读 |
|||
$ids = RecordRead::where(['staff_id' => $staff_id])->column('record_id'); |
|||
$where['id'] = ['not in', $ids]; |
|||
} |
|||
$records = RecordModel::where($where)->with([ |
|||
'staff', |
|||
'file', |
|||
'read' => function ($query) use ($staff_id) { |
|||
$query->where(['staff_id' => $staff_id]); |
|||
} |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
|
|||
$data = $records['data']; |
|||
foreach ($data as $k => $v) { |
|||
$customerWhere['id'] = $v['relation_id']?? ''; |
|||
$v['comment_num'] =0;//评论数 |
|||
|
|||
if($v['relation_type'] == RecordModel::CUSTOMER_TYPE) { |
|||
$v['comment_num'] =Comment::where(array('relation_type'=>1,'relation_id'=>$v['id']))->count(); |
|||
$v['relation_name'] = Customer::where(['id' => $v['relation_id']])->value('name'); |
|||
}elseif($v['relation_type'] == RecordModel::CONTACTS_TYPE) { |
|||
$v['comment_num'] =Comment::where(array('relation_type'=>2,'relation_id'=>$v['id']))->count(); |
|||
$v['relation_name'] = Contacts::where(['id' => $v['relation_id']])->value('name'); |
|||
}elseif($v['relation_type'] == RecordModel::CONTRACT_TYPE) { |
|||
$v['comment_num'] =Comment::where(array('relation_type'=>3,'relation_id'=>$v['id']))->count(); |
|||
$v['relation_name'] = Contract::where(['id' => $v['relation_id']])->value('name'); |
|||
}elseif($v['relation_type'] == RecordModel::LEADS_TYPE) { |
|||
$v['comment_num'] =Comment::where(array('relation_type'=>4,'relation_id'=>$v['id']))->count(); |
|||
$v['relation_name'] = Leads::where(['id' => $v['relation_id']])->value('name'); |
|||
} elseif($v['relation_type'] == RecordModel::BUSINESS_TYPE) { |
|||
$v['comment_num'] =Comment::where(array('relation_type'=>5,'relation_id'=>$v['id']))->count(); |
|||
$v['relation_name'] = Business::where(['id' => $v['relation_id']])->value('name'); |
|||
}else{ |
|||
$v['customer'] = []; |
|||
} |
|||
if (!empty($v['read'])) { |
|||
$v['is_read'] = 1; |
|||
} else { |
|||
$v['is_read'] = 0; |
|||
} |
|||
if($v['staff_id']){ |
|||
$v['staff'] = Staff::where(['id'=>$v['staff_id']])->field('id,img,name,post')->find(); |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
$this->success('请求成功', [ |
|||
'total' => $records['total'], |
|||
'per_page' => $records['per_page'], |
|||
'current_page' => $records['current_page'], |
|||
'last_page' => $records['last_page'], |
|||
'data' => $data |
|||
]); |
|||
|
|||
$this->success('请求成功', $records); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 创建跟进记录 |
|||
*/ |
|||
public function createRecord() { |
|||
$params = $this->request->post(); |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
Db::startTrans(); |
|||
try { |
|||
$result = RecordModel::createRecord($params); |
|||
Db::commit(); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
if ($result) { |
|||
$this->success('创建跟进记录成功'); |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取根据记录详情 |
|||
*/ |
|||
public function getRecordDetail() { |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('参数不能为空'); |
|||
} |
|||
$record = RecordModel::where(['id' => $id])->with([ |
|||
'staff', |
|||
'file' |
|||
])->find(); |
|||
if (empty($record)) { |
|||
$this->error('根据记录不存在'); |
|||
} |
|||
$record = $record->toArray(); |
|||
|
|||
if ($record['relation_type'] == RecordModel::CUSTOMER_TYPE) { |
|||
$record['relation_name'] = Customer::where(['id' => $record['relation_id']])->value('name'); |
|||
} elseif ($record['relation_type'] == RecordModel::CONTACTS_TYPE) { |
|||
$record['relation_name'] = Contacts::where(['id' => $record['relation_id']])->value('name'); |
|||
} elseif ($record['relation_type'] == RecordModel::CONTRACT_TYPE) { |
|||
$record['relation_name'] = Contract::where(['id' => $record['relation_id']])->value('name'); |
|||
} elseif($record['relation_type'] == RecordModel::LEADS_TYPE) { |
|||
$record['relation_name'] = Leads::where(['id' => $record['relation_id']])->value('name'); |
|||
} elseif($record['relation_type'] == RecordModel::BUSINESS_TYPE) { |
|||
$record['relation_name'] = Business::where(['id' => $record['relation_id']])->value('name'); |
|||
}else{ |
|||
$record['relation_name']=''; |
|||
} |
|||
|
|||
$reminds_id = $record['reminds_id']; |
|||
$reminds_id = explode(',', $reminds_id); |
|||
$names = Staff::where(['id' => ['in', $reminds_id]])->column('name'); |
|||
$record['staff_name'] = implode(',', $names); |
|||
if($record['staff_id']){ |
|||
$record['staff'] = Staff::where(['id'=>$record['staff_id']])->field('id,img,name,post')->find(); |
|||
} |
|||
//标记通知已读 |
|||
Message::setRead(Message::RECORD_TYPE, $id, $this->auth->id); |
|||
//添加阅读记录 |
|||
RecordRead::addRead($id, $this->auth->id); |
|||
|
|||
$this->success('请求成功', $record); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 添加评论 |
|||
*/ |
|||
public function addComment() { |
|||
$content = input('content'); |
|||
$record_id = input('record_id'); |
|||
$relation_type = input('relation_type'); |
|||
if (empty($content)) { |
|||
$this->error('评论内容不能为空'); |
|||
} |
|||
$data = [ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $record_id, |
|||
'staff_id' => $this->auth->id, |
|||
'content' => $content, |
|||
'status' => 1, |
|||
'ip' => get_client_ip(), |
|||
]; |
|||
|
|||
|
|||
$commentModel = new Comment(); |
|||
$commentModel->save($data); |
|||
|
|||
$record = RecordModel::get($record_id); |
|||
Message::addMessage(Message::COMMENT_TYPE,$record_id,$record['create_staff_id'],$this->auth->id); |
|||
|
|||
$staff_ids=$commentModel->where(['relation_type'=>$relation_type,'relation_id'=>$record_id])->group('staff_id')->column('staff_id'); |
|||
foreach ($staff_ids as $staff_id) { |
|||
//发送通知 |
|||
if($staff_id != $this->auth->id){ |
|||
Message::addMessage(Message::COMMENT_TYPE,$record_id,$staff_id,$this->auth->id); |
|||
} |
|||
} |
|||
$this->success('评论成功'); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 评论列表 |
|||
*/ |
|||
public function commentList() { |
|||
$record_id = input('record_id'); |
|||
$relation_type = input('relation_type'); |
|||
$comments = Comment::where([ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $record_id, |
|||
'status' => 1 |
|||
])->field('id,staff_id,content,createtime')->with(['staff'])->select(); |
|||
$this->success('请求成功', $comments); |
|||
} |
|||
|
|||
/** |
|||
* 获取跟进客户 |
|||
*/ |
|||
public function getcustomerList() { |
|||
$limit = input("limit/d", 10); |
|||
$time = input('time', 0); |
|||
$type = input('type', 1); |
|||
|
|||
$where['create_staff_id'] = $this->auth->id; |
|||
if($type == 6){ |
|||
$where['relation_type'] = 3; |
|||
}elseif($type == 7){ |
|||
$where['relation_type'] = 4; |
|||
}elseif($type == 8){ |
|||
$where['relation_type'] = 2; |
|||
}elseif($type == 9){ |
|||
$where['relation_type'] = 5; |
|||
}else{ |
|||
$where['relation_type'] = 1; |
|||
} |
|||
$where['follow_type'] = ['neq', '其它']; |
|||
$staff_id = $this->auth->id; |
|||
if ($time == 1) {//7天 |
|||
$where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-7 day'))),array('lt',date('Y-m-d', strtotime('+1 day')))); |
|||
} elseif ($time == 2) {//14天 |
|||
$where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-14 day'))),array('lt',date('Y-m-d', strtotime('+1 day')))); |
|||
}elseif($time == 3){ |
|||
$where['next_time'] = array(array('egt',date('Y-m-d', strtotime('-30 day'))),array('lt',date('Y-m-d', strtotime('+1 day')))); |
|||
}elseif($time == 4){ //今日 |
|||
$where['next_time'] = array(array('egt',date('Y-m-d 00:00:00')),array('elt',date('Y-m-d 23:59:59'))); |
|||
} |
|||
$where['status'] = 0; |
|||
$records = RecordModel::where($where)->with([ |
|||
'staff', |
|||
'file', |
|||
'read' => function ($query) use ($staff_id) { |
|||
$query->where(['staff_id' => $staff_id]); |
|||
} |
|||
])->order('id desc')->paginate($limit)->toArray(); |
|||
|
|||
$data = $records['data']; |
|||
foreach ($data as $k => $v) { |
|||
$customerWhere['id'] = $v['relation_id']?? ''; |
|||
if($type == 6){ |
|||
//合同 |
|||
$v['customer'] = Contract::where($customerWhere)->find(); |
|||
}elseif($type == 7){ |
|||
//线索 |
|||
$v['customer'] = Leads::where($customerWhere)->find(); |
|||
}elseif($type == 8){ |
|||
//联系人 |
|||
$v['customer'] = Contacts::where($customerWhere)->find(); |
|||
}elseif($type == 9){ |
|||
//商机 |
|||
$v['customer'] = Business::where($customerWhere)->find(); |
|||
} |
|||
else{ |
|||
$v['customer'] = Customer::where($customerWhere)->find(); |
|||
} |
|||
if (!empty($v['read'])) { |
|||
$v['is_read'] = 1; |
|||
} else { |
|||
$v['is_read'] = 0; |
|||
} |
|||
$data[$k] = $v; |
|||
} |
|||
$this->success('请求成功', [ |
|||
'total' => $records['total'], |
|||
'per_page' => $records['per_page'], |
|||
'current_page' => $records['current_page'], |
|||
'last_page' => $records['last_page'], |
|||
'data' => $data |
|||
]); |
|||
|
|||
$this->success('请求成功', $records); |
|||
} |
|||
/* |
|||
*待办跟进 |
|||
*/ |
|||
public function record_add(){ |
|||
$type = input('type',0); |
|||
$content = input('remarks'); |
|||
$record_id = input('record_id'); |
|||
$relation_type = input('relation_type'); |
|||
if (empty($content)) { |
|||
$this->error('备注不能为空'); |
|||
} |
|||
$data = [ |
|||
'relation_type' => $relation_type, |
|||
'relation_id' => $record_id, |
|||
'staff_id' => $this->auth->id, |
|||
'content' => $content, |
|||
'status' => 1, |
|||
'ip' => get_client_ip(), |
|||
]; |
|||
Db::startTrans(); |
|||
$commentModel = new Comment(); |
|||
$resultC = $commentModel->save($data); |
|||
$recordU = RecordModel::where(array('id'=>$record_id))->update(array('status'=>1,'updatetime'=>time())); |
|||
$resultR= true; |
|||
if($type ==1){ |
|||
|
|||
$params = $this->request->post(); |
|||
// 表单验证 |
|||
if (($result = $this->qingdongValidate($params, get_class(), 'create')) !== true) { |
|||
$this->error($result); |
|||
} |
|||
try { |
|||
unset($params['type']); |
|||
unset($params['remarks']); |
|||
unset($params['record_id']); |
|||
$resultR = RecordModel::createRecord($params); |
|||
} catch (Exception $e) { |
|||
Db::rollback(); |
|||
$this->error($e->getMessage()); |
|||
} |
|||
} |
|||
if(!$resultC || !$resultR || !$recordU){ |
|||
Db::rollback(); |
|||
$this->error('跟进失败'); |
|||
} |
|||
Db::commit(); |
|||
$this->success('跟进成功'); |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
<?php |
|||
// +---------------------------------------------------------------------- |
|||
// | Description: 客户模块设置 |
|||
// +---------------------------------------------------------------------- |
|||
// | Author: Michael_xu | gengxiaoxu@5kcrm.com |
|||
// +---------------------------------------------------------------------- |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\Staff; |
|||
|
|||
/** |
|||
* 客户模块设置 |
|||
*/ |
|||
class Setting extends StaffApi |
|||
{ |
|||
|
|||
|
|||
/** |
|||
* 获取团队成员 |
|||
*/ |
|||
public function team() |
|||
{ |
|||
$id = input('id'); |
|||
$customer = Customer::get($id); |
|||
if (empty($customer)) { |
|||
$this->error('客户不存在'); |
|||
} |
|||
$owner_staff = Staff::where(['id' => $customer->owner_staff_id])->find(); |
|||
$rw_staffs = Staff::where(['id' => ['in', explode(',', $customer->rw_staff_id)]])->select(); |
|||
$ro_staffs = Staff::where(['id' => ['in', explode(',', $customer->ro_staff_id)]])->select(); |
|||
|
|||
$staffs = []; |
|||
if ($owner_staff) { |
|||
$staffs[] = [ |
|||
'id' => $owner_staff->id, |
|||
'name' => $owner_staff->name, |
|||
'img' => $owner_staff->img, |
|||
'post' => $owner_staff->post, |
|||
'mobile' => $owner_staff->mobile, |
|||
'roles' => 1, |
|||
'is_edit' => 1, |
|||
]; |
|||
} |
|||
foreach ($rw_staffs as $v) { |
|||
$staffs[] = [ |
|||
'id' => $v->id, |
|||
'name' => $v->name, |
|||
'img' => $v->img, |
|||
'post' => $v->post, |
|||
'mobile' => $v->mobile, |
|||
'roles' => 2, |
|||
'is_edit' => 1, |
|||
]; |
|||
} |
|||
foreach ($ro_staffs as $v) { |
|||
$staffs[] = [ |
|||
'id' => $v->id, |
|||
'name' => $v->name, |
|||
'img' => $v->img, |
|||
'post' => $v->post, |
|||
'mobile' => $v->mobile, |
|||
'roles' => 2, |
|||
'is_edit' => 0, |
|||
]; |
|||
} |
|||
|
|||
$this->success('请求成功', $staffs); |
|||
} |
|||
|
|||
/** |
|||
* 修改团队成员 |
|||
*/ |
|||
public function editShowStaff() |
|||
{ |
|||
$id = input('id'); |
|||
$staff = input('staff/a'); |
|||
$model = Customer::get($id); |
|||
if (empty($model)) { |
|||
$this->error('客户不存在'); |
|||
} |
|||
$ro_staff_id = []; |
|||
$rw_staff_id = []; |
|||
foreach ($staff as $v) { |
|||
if ($v['is_edit'] == 1) { |
|||
$rw_staff_id[] = $v['id']; |
|||
} else { |
|||
$ro_staff_id[] = $v['id']; |
|||
} |
|||
} |
|||
$ro_staff_id = array_diff($ro_staff_id, $rw_staff_id); |
|||
$rw_staff_id=implode(',', $rw_staff_id); |
|||
$ro_staff_id=implode(',', $ro_staff_id); |
|||
$result = $model->save(['rw_staff_id' => ",{$rw_staff_id},", |
|||
'ro_staff_id' => ",{$ro_staff_id},"]); |
|||
if ($result === false) { |
|||
$this->error('修改失败'); |
|||
} |
|||
$this->success('修改成功'); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,595 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
|
|||
use addons\qingdong\model\Contacts; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\Flow; |
|||
use addons\qingdong\model\Leads; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\Remind; |
|||
use addons\qingdong\model\Staff as StaffModel; |
|||
use addons\qingdong\model\StaffDepartment; |
|||
use addons\qingdong\library\Wechat; |
|||
use addons\qingdong\model\Achievement; |
|||
use addons\qingdong\model\Record; |
|||
use fast\Http; |
|||
use think\Exception; |
|||
use think\Log; |
|||
use think\Validate; |
|||
|
|||
/** |
|||
* * 操作文档:https://doc.fastadmin.net/qingdong |
|||
* 软件介绍:https://www.fastadmin.net/store/qingdong.html |
|||
* 售后微信:qingdong_crm |
|||
* 员工登录 注册接口 |
|||
*/ |
|||
class Staff extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = ['test', 'wxLogin', 'login','logintest']; |
|||
protected $noNeedRight = ['getInfo', 'editInfo', "use_phone"]; |
|||
|
|||
|
|||
public function _initialize() |
|||
{ |
|||
parent::_initialize(); |
|||
} |
|||
|
|||
//是否登录 |
|||
public function isLogin() |
|||
{ |
|||
$this->success('已登录', ['userinfo' => $this->auth->getUserinfo()]); |
|||
} |
|||
|
|||
|
|||
|
|||
/** |
|||
* 会员登录 |
|||
* |
|||
* @ApiMethod (POST) |
|||
* @param string $account 账号 |
|||
* @param string $password 密码 |
|||
*/ |
|||
public function login() |
|||
{ |
|||
$account = $this->request->post('account'); |
|||
$password = $this->request->post('password'); |
|||
if (!$account || !$password) { |
|||
$this->error(__('Invalid parameters')); |
|||
} |
|||
$ret = $this->auth->login($account, $password); |
|||
if ($ret) { |
|||
$data = ['userinfo' => $this->auth->getUserinfo()]; |
|||
$this->success(__('Logged in successful'), $data); |
|||
} else { |
|||
$this->error($this->auth->getError()); |
|||
} |
|||
} |
|||
|
|||
//获取个人基本信息 |
|||
public function getInfo() |
|||
{ |
|||
$staff = StaffModel::where(['id' => $this->auth->id])->with(['department', 'parent'])->find(); |
|||
$group_ids=explode(',',$staff['group_ids']); |
|||
$staff['role_type'] = 1;//基础和团队 |
|||
if (in_array(1, $group_ids)) {//超级管理员 |
|||
$staff['role_type'] = 9; |
|||
} |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
//员工绑定信息 |
|||
public function staffBind(){ |
|||
$staff=StaffModel::get($this->auth->id); |
|||
$data=[ |
|||
'is_bind_wechat'=>$staff['openid']?1:($staff['wx_openid']?1:0) |
|||
]; |
|||
$this->success('请求成功',$data); |
|||
} |
|||
|
|||
//绑定微信 |
|||
public function wechatBind(){ |
|||
$type=input('type');//applet小程序 web 网页授权 |
|||
$code = input('code'); |
|||
if($type == 'web'){ |
|||
$wechat = new Wechat('wxOfficialAccount'); |
|||
if(empty($wechat->config['app_id'])){ |
|||
$this->error('微信公众号appid未设置'); |
|||
} |
|||
if(empty($wechat->config['secret'])){ |
|||
$this->error('微信公众号secret未设置'); |
|||
} |
|||
$decryptSession = $wechat->getOfficialAccessToken($code); |
|||
|
|||
if (isset($decryptSession['errcode']) && $decryptSession['errcode'] != 0) { |
|||
$this->error(__('解析失败!')); |
|||
} |
|||
$openid = $decryptSession['openid']; |
|||
$unionid = $decryptSession['unionid'] ?? ''; |
|||
|
|||
Log::info(json_encode($decryptSession,JSON_UNESCAPED_UNICODE)); |
|||
//判断用户是否存在 |
|||
$staff = StaffModel::where(['wx_openid' => $openid])->find(); |
|||
if($staff){ |
|||
$this->error('该微信号已绑定账号'); |
|||
} |
|||
$staffModel=new StaffModel(); |
|||
$result=$staffModel->save(['wx_openid'=>$openid,'unionid'=>$unionid],['id'=>$this->auth->id]); |
|||
if($result){ |
|||
$this->success('绑定成功'); |
|||
} |
|||
$this->error('绑定失败'); |
|||
}elseif($type == 'applet'){ |
|||
$wechat = new Wechat('wxMiniProgram'); |
|||
if(empty($wechat->config['app_id'])){ |
|||
$this->error('微信小程序appid未设置'); |
|||
} |
|||
if(empty($wechat->config['secret'])){ |
|||
$this->error('微信小程序secret未设置'); |
|||
} |
|||
$decryptSession = $wechat->code($code); |
|||
|
|||
if (isset($decryptSession['errcode']) && $decryptSession['errcode'] != 0) { |
|||
$this->error(__('解析失败!')); |
|||
} |
|||
$openid = $decryptSession['openid']; |
|||
$unionid = $decryptSession['unionid'] ?? ''; |
|||
//判断用户是否存在 |
|||
$staff = StaffModel::where(['openid' => $openid])->find(); |
|||
if($staff){ |
|||
$this->error('该微信号已绑定账号'); |
|||
} |
|||
$staffModel=new StaffModel(); |
|||
$result=$staffModel->save(['openid'=>$openid,'unionid'=>$unionid],['id'=>$this->auth->id]); |
|||
if($result){ |
|||
$this->success('绑定成功'); |
|||
} |
|||
$this->error('绑定失败'); |
|||
} |
|||
} |
|||
|
|||
//解绑微信 |
|||
public function unboundWechat() |
|||
{ |
|||
$staffId = $this->auth->id; |
|||
$model = new StaffModel(); |
|||
$staff = $model->where(['id' => $staffId])->find(); |
|||
if (empty($staff)) { |
|||
$this->error('员工不存在'); |
|||
} |
|||
if ($model->isUpdate(true)->save(['id' => $staffId, 'wx_openid' => null, |
|||
'unionid' => null, 'openid' => null])) { |
|||
$this->success('解绑微信成功'); |
|||
} |
|||
$this->error('操作失败'); |
|||
} |
|||
//修改个人基本信息 |
|||
public function editInfo() |
|||
{ |
|||
$name = input('name'); |
|||
$img = input('img'); |
|||
$email = input('email'); |
|||
$sex = input('sex'); |
|||
$num = input('num'); |
|||
$post = input('post'); |
|||
$mobile = input('mobile'); |
|||
$staffs = StaffModel::where(array('id' => $this->auth->id))->find(); |
|||
$staffs->mobile = $mobile; |
|||
$staffs->img = $img; |
|||
$staffs->email = $email; |
|||
$staffs->sex = $sex; |
|||
$staffs->num = $num; |
|||
$staffs->post = $post; |
|||
$staffs->updatetime = time(); |
|||
$result = $staffs->save(); |
|||
if (!$result) { |
|||
$this->error('修改失败'); |
|||
} |
|||
$this->success('修改成功'); |
|||
} |
|||
|
|||
|
|||
//授权手机号 |
|||
public function use_phone() |
|||
{ |
|||
$code = $this->request->post('code','',null); |
|||
$encryptedData = $this->request->post('encryptedData','',null); |
|||
$iv = $this->request->post('iv','',null); |
|||
$config = new Wechat('wxMiniProgram'); |
|||
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $config->config['app_id'] . "&secret=" . $config->config['secret'] . "&js_code=" . $code . "&grant_type=authorization_code"; |
|||
$user = curl_getinfo($url); |
|||
$arr = json_decode($user, true); |
|||
if (isset($arr['errcode']) && $arr['errcode'] != 0) { |
|||
$this->error('操作失败!'); |
|||
} |
|||
if (!isset($arr['openid']) || !isset($arr['session_key'])) { |
|||
$this->error('授权失败,请重新授权!'); |
|||
} |
|||
$openId = $arr['openid']; |
|||
$pc = new Wxbizdatacrypt($config->config['app_id'], $arr['session_key']); |
|||
$errCode = $pc->decryptData($encryptedData, $iv, $data); |
|||
if ($errCode != 0) { |
|||
$this->error('授权失败,请重新授权!'); |
|||
} |
|||
$decryptUserInfo = json_decode($data, true); |
|||
if (isset($decryptUserInfo['phoneNumber']) && !empty($decryptUserInfo['phoneNumber'])) { |
|||
$user_id = $this->auth->id; |
|||
$userInfo = StaffModel::where(array('id' => $user_id))->update(array('mobile' => $decryptUserInfo['phoneNumber'])); |
|||
if ($userInfo === false) { |
|||
$this->error('绑定失败!'); |
|||
} |
|||
$data = ['mobile' => $decryptUserInfo['phoneNumber']]; |
|||
$this->success('绑定成功', $data); |
|||
} else { |
|||
$this->error('授权失败!'); |
|||
} |
|||
} |
|||
|
|||
|
|||
//获取下级员工列表 |
|||
public function getStaffList() |
|||
{ |
|||
$ids = StaffModel::getLowerStaffId(); |
|||
$staff = StaffModel::where([ |
|||
'id' => ['in', $ids], |
|||
'status' => 1 |
|||
])->with(['parent'])->field('id,name,nickname,img,num,mobile,post,parent_id')->select(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
|
|||
//获取员工详情 |
|||
public function getStaffDetail() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('员工不存在'); |
|||
} |
|||
$staff = StaffModel::with(['department', 'parent'])->where([ |
|||
'id' => $id, |
|||
])->find(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
|
|||
//待审核员工列表 |
|||
public function getCheckStaffList() |
|||
{ |
|||
$staff = StaffModel::where([ |
|||
'status' => 0, |
|||
'name' => ['neq', ''] |
|||
])->field('id,name,nickname,img,num,mobile,post,status')->select(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
//修改员工信息 |
|||
public function updateStaff() |
|||
{ |
|||
$name = input('name', ''); |
|||
$img = input('img', ''); |
|||
$email = input('email', ''); |
|||
$sex = input('sex', 0); |
|||
$num = input('num', ''); |
|||
$post = input('post', ''); |
|||
$parent_id = input('parent_id', 0); |
|||
$id = input('id', 0, 'intval'); |
|||
if (StaffModel::where(['id' => $id])->update([ |
|||
'name' => $name, |
|||
'img' => $img, |
|||
'email' => $email, |
|||
'sex' => $sex, |
|||
'num' => $num, |
|||
'post' => $post, |
|||
'parent_id' => $parent_id, |
|||
'updatetime' => time() |
|||
]) == false) { |
|||
$this->error('修改失败'); |
|||
} |
|||
$this->success('修改成功'); |
|||
} |
|||
|
|||
//审核员工成功 |
|||
public function checkStaffSuccess() |
|||
{ |
|||
$name = input('name', ''); |
|||
$img = input('img', ''); |
|||
$email = input('email', ''); |
|||
$sex = input('sex', 0); |
|||
$role = input('role', 0); |
|||
$num = input('num', ''); |
|||
$post = input('post', ''); |
|||
$mobile = input('mobile', ''); |
|||
$department_id = input('department_id', 0); |
|||
$parent_id = input('parent_id', 0); |
|||
$id = input('id', 0, 'intval'); |
|||
if (StaffModel::where(['id' => $id, 'status' => 0])->find() == false) { |
|||
$this->error('待审核员工不存在'); |
|||
} |
|||
if (empty($department_id)) { |
|||
$this->error('请选择员工部门!'); |
|||
} |
|||
if (StaffModel::where(['id' => $id])->update([ |
|||
'name' => $name, |
|||
'img' => $img, |
|||
'email' => $email, |
|||
'sex' => $sex, |
|||
'num' => $num, |
|||
'role' => $role, |
|||
'mobile' => $mobile, |
|||
'post' => $post, |
|||
'parent_id' => $parent_id, |
|||
'department_id' => $department_id, |
|||
'status' => 1, |
|||
'updatetime' => time() |
|||
]) == false) { |
|||
$this->error('审核失败'); |
|||
} |
|||
$this->success('审核成功'); |
|||
} |
|||
|
|||
//审核员工拒绝 |
|||
public function checkStaffError(){ |
|||
$id = input('id'); |
|||
if (StaffModel::where(['id' => $id, 'status' => 0])->find() == false) { |
|||
$this->error('待审核员工不存在'); |
|||
} |
|||
if (StaffModel::where(['id' => $id, 'status' => 0])->update(['deletetime' => time()]) == false) { |
|||
$this->error('拒绝失败'); |
|||
} |
|||
$this->success('审核成功'); |
|||
} |
|||
|
|||
//获取员工统计 |
|||
public function getStaffStatistics() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('员工不存在'); |
|||
} |
|||
$date = input('date', date('Y-m')); |
|||
//月底 |
|||
$endDate = strtotime('+1 month', strtotime(date($date . '-1'))); |
|||
$date = strtotime($date); |
|||
//客户 线索 联系人 合同 回款 跟进次数 处理审批 |
|||
$leads = Leads::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
])->count(); |
|||
$customer = Customer::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
])->count(); |
|||
$contacts = Contacts::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
])->count(); |
|||
$contract = Contract::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
'check_status' => 2 |
|||
])->count(); |
|||
$contract_money = Contract::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
'check_status' => 2 |
|||
])->sum('money'); |
|||
$receivables = Receivables::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
'check_status' => 2 |
|||
])->count(); |
|||
$receivables_money = Receivables::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
'check_status' => 2 |
|||
])->sum('money'); |
|||
$record = Record::where([ |
|||
'create_staff_id' => $id, |
|||
'createtime' => ['between', [$date, $endDate]], |
|||
])->count(); |
|||
|
|||
$field = Achievement::getMonthField(date('Y-m', $date)); |
|||
$contractAchievement = Achievement::where([ |
|||
'year' => date('Y', $date), |
|||
'type' => 3, |
|||
'obj_id' => $id, |
|||
'status' => 1 |
|||
])->value($field); |
|||
|
|||
$receivablesAchievement = Achievement::where([ |
|||
'year' => date('Y', $date), |
|||
'type' => 3, |
|||
'obj_id' => $id, |
|||
'status' => 2 |
|||
])->value($field); |
|||
|
|||
$this->success('请求成功', [ |
|||
'leads' => $leads, |
|||
'customer' => $customer, |
|||
'contacts' => $contacts, |
|||
'contract' => $contract, |
|||
'contract_money' => $contract_money, |
|||
'receivables' => $receivables, |
|||
'receivables_money' => $receivables_money, |
|||
'record' => $record, |
|||
'contractAchievement' => $contractAchievement ?: 0, |
|||
'receivablesAchievement' => $receivablesAchievement ?: 0, |
|||
]); |
|||
} |
|||
|
|||
//获取员工所属客户 |
|||
public function getStaffCustomer() |
|||
{ |
|||
$id = input('id'); |
|||
$limit = input("limit/d", 10); |
|||
$row = StaffModel::get($id); |
|||
if (empty($row)) { |
|||
$this->error('员工不存在'); |
|||
} |
|||
$where = []; |
|||
$where['owner_staff_id'] = $id; |
|||
$list = Customer::where($where)->with([ |
|||
'ownerStaff', |
|||
'contacts' |
|||
])->field('id,name,next_time,owner_staff_id,level,follow')->order('id desc')->paginate($limit); |
|||
|
|||
$this->success('请求成功', $list); |
|||
} |
|||
|
|||
//获取部门列表 |
|||
public function getDepartment() |
|||
{ |
|||
|
|||
$this->success('请求成功', StaffDepartment::getDepartmentList()); |
|||
} |
|||
|
|||
//获取上级列表 |
|||
public function getParentList() |
|||
{ |
|||
$id = input('id'); |
|||
if (empty($id)) { |
|||
$this->error('参数错误'); |
|||
} |
|||
$this->success('请求成功', StaffModel::getList([$id])); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取用户上级IDs |
|||
*/ |
|||
public function getStaffIds() |
|||
{ |
|||
// record 跟进 contract 合同 consume 费用 receivables 回款 |
|||
$type = input('type'); |
|||
$remind=Remind::where(['type'=>$type])->find(); |
|||
if($remind){ |
|||
$staff = StaffModel::where(['id' => ['in', $remind['staff_ids']]])->field('id,name,img')->select(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
$pid = StaffModel::where(['id' => $this->auth->id])->value('parent_id'); |
|||
$pids = [$pid]; |
|||
$staff = StaffModel::where(['id' => ['in', $pids]])->field('id,name,img')->select(); |
|||
$this->success('请求成功', $staff); |
|||
} |
|||
|
|||
/** |
|||
* 获取审批列表 |
|||
*/ |
|||
public function getsteplist() |
|||
{ |
|||
// record 跟进 contract 合同 consume 费用 receivables 回款 formapproval_1 审批 |
|||
$type = input('type'); |
|||
|
|||
//获取审批 |
|||
$data = Flow::getsteplist($type); |
|||
if (empty($data)) { |
|||
$this->error('无可用审批流,请联系管理员'); |
|||
} |
|||
$this->success('请求成功', $data); |
|||
} |
|||
/** |
|||
* 获取审批详情 |
|||
*/ |
|||
public function getstepdetail() |
|||
{ |
|||
// record 跟进 contract 合同 consume 费用 receivables 回款 |
|||
$type = input('type'); |
|||
$relation_id=input('relation_id'); |
|||
$data = Flow::getstepdetail($type,$relation_id); |
|||
if (empty($data)) { |
|||
$this->error('无可用审批流,请联系管理员'); |
|||
} |
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
|
|||
//禁用账号 |
|||
public function disable_user() |
|||
{ |
|||
$id = input('id'); |
|||
$status = 2; |
|||
$model = new StaffModel(); |
|||
$staff = $model->where(['id' => $id])->find(); |
|||
if (empty($staff)) { |
|||
$this->error('员工不存在'); |
|||
} |
|||
if ($model->isUpdate(true)->save(['id' => $id, 'status' => $status])) { |
|||
$this->success('操作成功'); |
|||
} |
|||
$this->error('操作失败'); |
|||
} |
|||
/** |
|||
* 退出登录 |
|||
* @ApiMethod (POST) |
|||
*/ |
|||
public function logout() |
|||
{ |
|||
if (!$this->request->isPost()) { |
|||
$this->error(__('Invalid parameters')); |
|||
} |
|||
$this->auth->logout(); |
|||
$this->success(__('Logout successful')); |
|||
} |
|||
/** |
|||
* 修改密码 |
|||
*/ |
|||
public function changepwd() |
|||
{ |
|||
if ($this->request->isPost()) { |
|||
$oldpassword = $this->request->post("oldpassword"); |
|||
$newpassword = $this->request->post("newpassword"); |
|||
$renewpassword = $this->request->post("renewpassword"); |
|||
$rule = [ |
|||
'oldpassword' => 'require|length:6,30', |
|||
'newpassword' => 'require|length:6,30', |
|||
'renewpassword' => 'require|length:6,30|confirm:newpassword', |
|||
]; |
|||
|
|||
$msg = [ |
|||
'renewpassword.confirm' =>'两次输入的密码不一致' |
|||
]; |
|||
$data = [ |
|||
'oldpassword' => $oldpassword, |
|||
'newpassword' => $newpassword, |
|||
'renewpassword' => $renewpassword, |
|||
]; |
|||
$field = [ |
|||
'oldpassword' => '旧密码', |
|||
'newpassword' => '新密码', |
|||
'renewpassword' => '确认密码' |
|||
]; |
|||
$validate = new Validate($rule, $msg, $field); |
|||
$result = $validate->check($data); |
|||
if (!$result) { |
|||
$this->error(__($validate->getError())); |
|||
return false; |
|||
} |
|||
|
|||
$ret = $this->auth->changepwd($newpassword, $oldpassword); |
|||
if ($ret) { |
|||
$this->success('修改密码成功'); |
|||
} else { |
|||
$this->error($this->auth->getError()); |
|||
} |
|||
} |
|||
} |
|||
//直接体验 |
|||
public function logintest() |
|||
{ |
|||
$staff = StaffModel::where([])->order('id asc')->find(); |
|||
if(!$staff){ |
|||
$this->error('员工不存在'); |
|||
} |
|||
$stafflogin= $this->auth->direct($staff['id']); |
|||
if ($stafflogin) { |
|||
$data = ['userinfo' => $this->auth->getUserinfo()]; |
|||
$this->success(__('Logged in successful'), $data); |
|||
} else { |
|||
$this->error('登录失败'); |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,325 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\library\StaffAuth; |
|||
use think\Config; |
|||
use think\exception\HttpResponseException; |
|||
use think\exception\ValidateException; |
|||
use think\Hook; |
|||
use think\Lang; |
|||
use think\Loader; |
|||
use think\Request; |
|||
use think\Response; |
|||
use think\Validate; |
|||
|
|||
/** |
|||
* API控制器基类 |
|||
*/ |
|||
class StaffApi { |
|||
/** |
|||
* @var Request Request 实例 |
|||
*/ |
|||
protected $request; |
|||
/** |
|||
* @var bool 验证失败是否抛出异常 |
|||
*/ |
|||
protected $failException = false; |
|||
/** |
|||
* @var bool 是否批量验证 |
|||
*/ |
|||
protected $batchValidate = false; |
|||
/** |
|||
* @var array 前置操作方法列表 |
|||
*/ |
|||
protected $beforeActionList = []; |
|||
/** |
|||
* 无需登录的方法,同时也就不需要鉴权了 |
|||
* @var array |
|||
*/ |
|||
protected $noNeedLogin = []; |
|||
/** |
|||
* 无需鉴权的方法,但需要登录 |
|||
* @var array |
|||
*/ |
|||
protected $noNeedRight = []; |
|||
/** |
|||
* 权限Auth |
|||
* @var StaffAuth |
|||
*/ |
|||
protected $auth = null; |
|||
|
|||
/** |
|||
* 默认响应输出类型,支持json/xml |
|||
* @var string |
|||
*/ |
|||
protected $responseType = 'json'; |
|||
|
|||
|
|||
/** |
|||
* 构造方法 |
|||
* @access public |
|||
* @param Request $request Request 对象 |
|||
*/ |
|||
public function __construct(Request $request = null) { |
|||
$this->request = is_null($request) ? Request::instance() : $request; |
|||
|
|||
// 控制器初始化 |
|||
$this->_initialize(); |
|||
|
|||
// 前置操作方法 |
|||
if ($this->beforeActionList) { |
|||
foreach ($this->beforeActionList as $method => $options) { |
|||
is_numeric($method) ? $this->beforeAction($options) : $this->beforeAction($method, $options); |
|||
} |
|||
} |
|||
$controllername = strtolower($this->request->controller()); |
|||
|
|||
} |
|||
|
|||
|
|||
/** |
|||
* 初始化操作 |
|||
* @access protected |
|||
*/ |
|||
protected function _initialize() { |
|||
//跨域请求检测 |
|||
check_cors_request(); |
|||
|
|||
//移除HTML标签 |
|||
$this->request->filter('trim,strip_tags,htmlspecialchars'); |
|||
|
|||
$this->auth = StaffAuth::instance(['type'=>'Mysqlstaff']); |
|||
|
|||
$modulename = $this->request->module(); |
|||
$controllername = Loader::parseName($this->request->controller()); |
|||
$actionname = strtolower($this->request->action()); |
|||
|
|||
// token |
|||
$token = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token'))); |
|||
$path = str_replace('.', '/', $controllername) . '/' . $actionname; |
|||
// 设置当前请求的URI |
|||
$this->auth->setRequestUri($path); |
|||
// 检测是否需要验证登录 |
|||
if (!$this->auth->match($this->noNeedLogin)) { |
|||
|
|||
//初始化 |
|||
$this->auth->init($token); |
|||
//检测是否登录 |
|||
if (!$this->auth->isLogin()) { |
|||
$this->error(__('Please login first'), null, 401); |
|||
} |
|||
if (!$this->auth->match($this->noNeedRight)) { |
|||
//检测是否完善用户信息 |
|||
if (!$this->auth->mobile || !$this->auth->name) { |
|||
$this->error('请先完善用户信息', null, 402); |
|||
} |
|||
//状态错误 |
|||
if ($this->auth->status != 1) { |
|||
$this->error('等待管理员审核', null, 405); |
|||
} |
|||
} |
|||
} else { |
|||
// 如果有传递token才验证是否登录状态 |
|||
if ($token) { |
|||
$this->auth->init($token); |
|||
} |
|||
} |
|||
|
|||
$upload = \app\common\model\Config::upload(); |
|||
|
|||
// 上传信息配置后 |
|||
Hook::listen("upload_config_init", $upload); |
|||
|
|||
Config::set('upload', array_merge(Config::get('upload'), $upload)); |
|||
// 加载当前控制器语言包 |
|||
$this->loadlang($controllername); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 加载语言文件 |
|||
* @param string $name |
|||
*/ |
|||
protected function loadlang($name) { |
|||
$name = Loader::parseName($name); |
|||
Lang::load(ADDON_PATH . 'qingdong/lang/' . $this->request->langset() . '/' . str_replace('.', '/', $name) . '.php'); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 操作成功返回的数据 |
|||
* @param string $msg 提示信息 |
|||
* @param mixed $data 要返回的数据 |
|||
* @param int $code 错误码,默认为1 |
|||
* @param string $type 输出类型 |
|||
* @param array $header 发送的 Header 信息 |
|||
*/ |
|||
protected function success($msg = '', $data = null, $code = 1, $type = null, array $header = []) { |
|||
$this->result($msg, $data, $code, $type, $header); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 操作失败返回的数据 |
|||
* @param string $msg 提示信息 |
|||
* @param mixed $data 要返回的数据 |
|||
* @param int $code 错误码,默认为0 |
|||
* @param string $type 输出类型 |
|||
* @param array $header 发送的 Header 信息 |
|||
*/ |
|||
protected function error($msg = '', $data = null, $code = 0, $type = null, array $header = []) { |
|||
$this->result($msg, $data, $code, $type, $header); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 返回封装后的 API 数据到客户端 |
|||
* @access protected |
|||
* @param mixed $msg 提示信息 |
|||
* @param mixed $data 要返回的数据 |
|||
* @param int $code 错误码,默认为0 |
|||
* @param string $type 输出类型,支持json/xml/jsonp |
|||
* @param array $header 发送的 Header 信息 |
|||
* @return void |
|||
* @throws HttpResponseException |
|||
*/ |
|||
protected function result($msg, $data = null, $code = 0, $type = null, array $header = []) { |
|||
$result = [ |
|||
'code' => $code, |
|||
'msg' => $msg, |
|||
'time' => Request::instance()->server('REQUEST_TIME'), |
|||
'data' => $data, |
|||
]; |
|||
// 如果未设置类型则自动判断 |
|||
$type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType); |
|||
|
|||
if (isset($header['statuscode'])) { |
|||
$code = $header['statuscode']; |
|||
unset($header['statuscode']); |
|||
} else { |
|||
//未设置状态码,根据code值判断 |
|||
$code = $code >= 1000 || $code < 200 ? 200 : $code; |
|||
} |
|||
$response = Response::create($result, $type, $code)->header($header); |
|||
throw new HttpResponseException($response); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 前置操作 |
|||
* @access protected |
|||
* @param string $method 前置操作方法名 |
|||
* @param array $options 调用参数 ['only'=>[...]] 或者 ['except'=>[...]] |
|||
* @return void |
|||
*/ |
|||
protected function beforeAction($method, $options = []) { |
|||
if (isset($options['only'])) { |
|||
if (is_string($options['only'])) { |
|||
$options['only'] = explode(',', $options['only']); |
|||
} |
|||
|
|||
if (!in_array($this->request->action(), $options['only'])) { |
|||
return; |
|||
} |
|||
} elseif (isset($options['except'])) { |
|||
if (is_string($options['except'])) { |
|||
$options['except'] = explode(',', $options['except']); |
|||
} |
|||
|
|||
if (in_array($this->request->action(), $options['except'])) { |
|||
return; |
|||
} |
|||
} |
|||
|
|||
call_user_func([$this, $method]); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 设置验证失败后是否抛出异常 |
|||
* @access protected |
|||
* @param bool $fail 是否抛出异常 |
|||
* @return $this |
|||
*/ |
|||
protected function validateFailException($fail = true) { |
|||
$this->failException = $fail; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 验证数据 |
|||
* @access protected |
|||
* @param array $data 数据 |
|||
* @param string|array $validate 验证器名或者验证规则数组 |
|||
* @param array $message 提示信息 |
|||
* @param bool $batch 是否批量验证 |
|||
* @param mixed $callback 回调方法(闭包) |
|||
* @return array|string|true |
|||
* @throws ValidateException |
|||
*/ |
|||
protected function validate($data, $validate, $message = [], $batch = false, $callback = null) { |
|||
if (is_array($validate)) { |
|||
$v = Loader::validate(); |
|||
$v->rule($validate); |
|||
} else { |
|||
// 支持场景 |
|||
if (strpos($validate, '.')) { |
|||
list($validate, $scene) = explode('.', $validate); |
|||
} |
|||
|
|||
$v = Loader::validate($validate); |
|||
|
|||
!empty($scene) && $v->scene($scene); |
|||
} |
|||
|
|||
// 批量验证 |
|||
if ($batch || $this->batchValidate) { |
|||
$v->batch(true); |
|||
} |
|||
// 设置错误信息 |
|||
if (is_array($message)) { |
|||
$v->message($message); |
|||
} |
|||
// 使用回调验证 |
|||
if ($callback && is_callable($callback)) { |
|||
call_user_func_array($callback, [$v, &$data]); |
|||
} |
|||
|
|||
if (!$v->check($data)) { |
|||
if ($this->failException) { |
|||
throw new ValidateException($v->getError()); |
|||
} |
|||
|
|||
return $v->getError(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 刷新Token |
|||
*/ |
|||
protected function token() { |
|||
$token = $this->request->param('__token__'); |
|||
|
|||
//验证Token |
|||
if (!Validate::make()->check(['__token__' => $token], ['__token__' => 'require|token'])) { |
|||
$this->error(__('Token verification error'), ['__token__' => $this->request->token()]); |
|||
} |
|||
|
|||
//刷新Token |
|||
$this->request->token(); |
|||
} |
|||
|
|||
protected function qingdongValidate($params, $class, $scene, $rules = []) { |
|||
$validate = validate(str_replace('controller', 'validate', $class)); |
|||
if (!$validate->check($params, $rules, $scene)) { |
|||
return $validate->getError(); |
|||
} |
|||
return true; |
|||
} |
|||
} |
|||
@ -0,0 +1,906 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Achievement; |
|||
use addons\qingdong\model\Achievement as AchievementModel; |
|||
use addons\qingdong\model\ContractRatio; |
|||
use addons\qingdong\model\Receivables; |
|||
use addons\qingdong\model\Contract; |
|||
use addons\qingdong\model\Leads; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\ReceivablesPlan; |
|||
use addons\qingdong\model\Record; |
|||
use addons\qingdong\model\Staff; |
|||
|
|||
|
|||
/** |
|||
* 统计接口 |
|||
*/ |
|||
class Statistics extends StaffApi { |
|||
protected $noNeedLogin = []; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
/** |
|||
*成交排行 |
|||
*/ |
|||
public function contractRanding() { |
|||
// $date = input('date', date('Y-m')); |
|||
$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属 3公司 |
|||
$status=input('status',1);//1 合同 2 回款 |
|||
$times=input('times',''); |
|||
$times=explode(',',$times); |
|||
if(empty($times)){ |
|||
$this->error('参数不能为空'); |
|||
} |
|||
$startDate=date("Y-m",strtotime($times[0])); |
|||
$endDate=date("Y-m",strtotime($times[1])); |
|||
$between=[$times[0],$times[1]]; |
|||
if($status == 1){ |
|||
$contracts = Contract::where([ |
|||
'order_date' => ['between', $between], |
|||
'check_status' => 2, |
|||
])->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select(); |
|||
$list = []; |
|||
foreach ($contracts as $v) { |
|||
$list[$v['owner_staff_id']] = $v['money']; |
|||
} |
|||
}else{ |
|||
$receivables = Receivables::where([ |
|||
'return_time' => ['between', $between], |
|||
'check_status' => 2, |
|||
])->group('owner_staff_id')->field('owner_staff_id,sum(money) as money')->order('money desc')->select(); |
|||
$list = []; |
|||
foreach ($receivables as $v) { |
|||
$list[$v['owner_staff_id']] = $v['money']; |
|||
} |
|||
} |
|||
|
|||
$data = []; |
|||
$staffs = Staff::getList(); |
|||
foreach ($staffs as $v) { |
|||
if (isset($list[$v['id']])) { |
|||
$data[$v['id']] = $list[$v['id']]; |
|||
} else { |
|||
$data[$v['id']] = 0; |
|||
} |
|||
} |
|||
arsort($data); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$oneMoney = 0; |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} elseif ($type == 3) {//公司 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
} |
|||
|
|||
|
|||
foreach ($data as $id => $money) { |
|||
if ($i == 1) { |
|||
$oneMoney = $money; |
|||
} |
|||
$val = $staffs[$id]; |
|||
$val['money'] = $money; |
|||
$val['ratio'] = ($money && $oneMoney) ? sprintf("%.2f", $money / $oneMoney * 100) : 0; |
|||
$val['rank'] = $i; |
|||
$i++; |
|||
if(in_array($id,$showStaffIds)){ |
|||
$result[] = $val; |
|||
} |
|||
} |
|||
|
|||
if (count($result) >= 10) { |
|||
$top = array_slice($result, 0, 3); |
|||
$bottom = array_slice($result, -3, 3); |
|||
$middle = array_slice($result, 3, 4); |
|||
$result = array_merge($top, $bottom, $middle); |
|||
} |
|||
|
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
//业绩目标完成情况 |
|||
$data = Achievement::getStaffAchievement($startDate,$endDate,$status); |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
//业绩目标完成情况 |
|||
$data = Achievement::getStaffAchievement($startDate,$endDate,$status); |
|||
} elseif ($type == 3) {//公司 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
//业绩目标完成情况 |
|||
$data = Achievement::getCompanyAchievement($startDate,$endDate,$status); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
//业绩目标完成情况 |
|||
$data = Achievement::getStaffAchievement($startDate,$endDate,$status); |
|||
} |
|||
|
|||
$achievement=$data['achievement']??0; |
|||
if($status == 1){ |
|||
$totalMoneys = Contract::where([ |
|||
'order_date' => ['between', $between], |
|||
'check_status' => 2, |
|||
'owner_staff_id' => ['in',$showStaffIds], |
|||
])->sum('money'); |
|||
}else{ |
|||
$totalMoneys = Receivables::where([ |
|||
'return_time' => ['between', $between], |
|||
'check_status' => 2, |
|||
'owner_staff_id' => ['in',$showStaffIds], |
|||
])->sum('money'); |
|||
} |
|||
|
|||
$ratio = ($totalMoneys && intval($achievement)) ? (intval($achievement) == 0) ? 100 : round($totalMoneys / $achievement * 100, 2) : 0; |
|||
$data = [ |
|||
'achievement' => $achievement, |
|||
'contract_moneys' => $totalMoneys, |
|||
'completion_status' => ($ratio >= 100) ? 1 : 0,//完成状态 |
|||
'ratio' => $ratio, |
|||
'ranking' => $result |
|||
]; |
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 合同排行 机型排行 |
|||
*/ |
|||
public function contractRanking() { |
|||
|
|||
$date = input('date', date('Y-m')); |
|||
$type = input('type', 0);//0 本人及下属 1 仅本人 2 仅下属 |
|||
//月底 |
|||
$endDate = date('Y-m-d', strtotime('+1 month', strtotime($date . '-1')) - 1); |
|||
|
|||
$contracts = Contract::where([ |
|||
'order_date' => ['between', [$date . '-1', $endDate]], |
|||
'check_status' => 2, |
|||
])->group('owner_staff_id')->field('owner_staff_id,count(*) as contract_number')->order('contract_number desc')->select(); |
|||
$list = []; |
|||
foreach ($contracts as $v) { |
|||
$list[$v['owner_staff_id']] = $v['contract_number']; |
|||
} |
|||
$contracts = $list; |
|||
|
|||
$data = []; |
|||
$staffs = Staff::getList(); |
|||
foreach ($staffs as $v) { |
|||
if (isset($contracts[$v['id']])) { |
|||
$data[$v['id']] = $contracts[$v['id']]; |
|||
} else { |
|||
$data[$v['id']] = 0; |
|||
} |
|||
} |
|||
arsort($data); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$oneNumber = 0; |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
} |
|||
foreach ($data as $id => $number) { |
|||
if ($i == 1) { |
|||
$oneNumber = $number; |
|||
} |
|||
$val = $staffs[$id]; |
|||
$val['number'] = $number; |
|||
$val['ratio'] = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0; |
|||
$val['rank'] = $i; |
|||
$i++; |
|||
if(in_array($id,$showStaffIds)){ |
|||
$result[] = $val; |
|||
} |
|||
} |
|||
if (count($result) >= 10) { |
|||
|
|||
$top = array_slice($result, 0, 3); |
|||
$bottom = array_slice($result, -3, 3); |
|||
$middle = array_slice($result, 3, 4); |
|||
$result = array_merge($top, $bottom, $middle); |
|||
} |
|||
|
|||
$this->success('请求成功', $result); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 回款统计 |
|||
*/ |
|||
public function receivablesStatistics() { |
|||
$type = input('type',0); //0:全部 1:我负责的 2:下属负责的 |
|||
switch($type){ |
|||
case 1: |
|||
$wheres['owner_staff_id'] = $this->auth->id; |
|||
break; |
|||
case 2: |
|||
$wheres['owner_staff_id'] = array('in',Staff::getLowerStaffId()); |
|||
break; |
|||
default: |
|||
$wheres['owner_staff_id'] = array('in',Staff::getMyStaffIds()); |
|||
break; |
|||
|
|||
} |
|||
$contract_moneys = Contract::where(['owner_staff_id' => $this->auth->id, 'check_status' => 2])->sum('money'); |
|||
$receivables_moneys = Receivables::where($wheres)->where([ |
|||
'check_status' => 2, |
|||
])->sum('money'); |
|||
$plan_moneys = ReceivablesPlan::where($wheres)->where([ |
|||
'status' => 0, |
|||
])->sum('money'); |
|||
$no_moneys = $contract_moneys - $receivables_moneys; |
|||
$startDate = date('Y-01'); |
|||
$endDate = date('Y-m'); |
|||
|
|||
$plans = ReceivablesPlan::where($wheres)->group('dates')->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_date),"%Y-%m") as dates')->select(); |
|||
$plans_list = []; |
|||
foreach ($plans as $item) { |
|||
$plans_list[$item['dates']] = $item['money']; |
|||
} |
|||
$receivables = Receivables::where($wheres)->group('dates')->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_time),"%Y-%m") as dates')->select(); |
|||
$receivables_list = []; |
|||
foreach ($receivables as $item) { |
|||
$receivables_list[$item['dates']] = $item['money']; |
|||
} |
|||
$data = []; |
|||
for ($startDate; strtotime($startDate) <= strtotime($endDate); $startDate = date('Y-m', strtotime($startDate . ' +1 month'))) { |
|||
$row = [ |
|||
'date' => $startDate, |
|||
'plan' => $plans_list[$startDate] ?? 0, |
|||
'receivables' => $receivables_list[$startDate] ?? 0, |
|||
]; |
|||
$row['no'] = ($row['plan'] - $row['receivables']) > 0 ? $row['plan'] - $row['receivables'] : 0; |
|||
$data[] = $row; |
|||
} |
|||
|
|||
$this->success('请求成功', [ |
|||
'contract_moneys' => $contract_moneys, |
|||
'receivables_moneys' => $receivables_moneys, |
|||
'plan_moneys' => $plan_moneys, |
|||
'no_moneys' => $no_moneys, |
|||
'data' => $data |
|||
]); |
|||
} |
|||
|
|||
/** |
|||
* 所属员工回款统计 |
|||
*/ |
|||
public function staffReceivablesStatistics() { |
|||
$ids = Staff::getMyStaffIds(); |
|||
|
|||
|
|||
$contract_moneys = Contract::where([ |
|||
'owner_staff_id' => ['in', $ids], |
|||
'check_status' => 2, |
|||
])->sum('money'); |
|||
$receivables_moneys = Receivables::where([ |
|||
'owner_staff_id' => ['in', $ids], |
|||
'check_status' => 2, |
|||
])->sum('money'); |
|||
$plan_moneys = ReceivablesPlan::where([ |
|||
'owner_staff_id' => ['in', $ids], |
|||
'status' => 0, |
|||
])->sum('money'); |
|||
$no_moneys = $contract_moneys - $receivables_moneys; |
|||
|
|||
$contracts = Contract::where([ |
|||
'owner_staff_id' => [ |
|||
'in', |
|||
$ids |
|||
], |
|||
'check_status' => 2, |
|||
])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select(); |
|||
$contracts_list = []; |
|||
foreach ($contracts as $item) { |
|||
$contracts_list[$item['owner_staff_id']] = $item['money']; |
|||
} |
|||
|
|||
$plans = ReceivablesPlan::where([ |
|||
'owner_staff_id' => [ |
|||
'in', |
|||
$ids |
|||
], |
|||
'status' => 0, |
|||
])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select(); |
|||
$plans_list = []; |
|||
foreach ($plans as $item) { |
|||
$plans_list[$item['owner_staff_id']] = $item['money']; |
|||
} |
|||
|
|||
$receivables = Receivables::where([ |
|||
'owner_staff_id' => [ |
|||
'in', |
|||
$ids |
|||
], |
|||
'check_status' => 2, |
|||
])->group('owner_staff_id')->field('sum(money) as money,owner_staff_id')->select(); |
|||
$receivables_list = []; |
|||
foreach ($receivables as $item) { |
|||
$receivables_list[$item['owner_staff_id']] = $item['money']; |
|||
} |
|||
$data = []; |
|||
$ids = Staff::getMyStaffIds(); |
|||
$staffs = Staff::where(['id' => ['in', $ids]])->field('id,name')->select(); |
|||
foreach ($staffs as $v) { |
|||
$row = [ |
|||
'id' => $v['id'], |
|||
'name' => $v['name'], |
|||
'contracts' => $contracts_list[$v['id']] ?? 0, |
|||
'plan' => $plans_list[$v['id']] ?? 0, |
|||
'receivables' => $receivables_list[$v['id']] ?? 0, |
|||
]; |
|||
$row['no'] = ($row['contracts'] - $row['receivables']) > 0 ? $row['contracts'] - $row['receivables'] : 0; |
|||
$data[] = $row; |
|||
} |
|||
$this->success('请求成功', [ |
|||
'contract_moneys' => $contract_moneys, |
|||
'receivables_moneys' => $receivables_moneys, |
|||
'plan_moneys' => $plan_moneys, |
|||
'no_moneys' => $no_moneys, |
|||
'data' => $data |
|||
]); |
|||
} |
|||
|
|||
/** |
|||
* 我的业绩目标完成度 |
|||
*/ |
|||
public function staffAchievementStatistics() { |
|||
$year = input('year', date('Y')); |
|||
$type = input('type', 0); |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
$yearAchievement = Achievement::getStaffYearAchievement($year); |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
$yearAchievement = Achievement::getTeamYearAchievement($year); |
|||
} elseif ($type == 3) {//公司 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
$yearAchievement = Achievement::getCompanyYearAchievement($year); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
$yearAchievement = Achievement::getTeamYearAchievement($year); |
|||
} |
|||
$contracts=ContractRatio::where([ |
|||
'contract.check_status'=>2, 'contract_ratio.staff_id' => ['in',$showStaffIds], |
|||
'contract.order_date'=>['like', $year . '%'] |
|||
])->with(['contract'])->select(); |
|||
$contracts=collection($contracts)->toArray(); |
|||
$contractData=[]; |
|||
foreach ($contracts as $v) { |
|||
$order_date = $v['contract']['order_date']; |
|||
$month = date('Y-m', strtotime($order_date)); |
|||
$contractData[$month]['money'][] = $v['ratio_money']; |
|||
$contractData[$month]['contract_id'][] = $v['contract_id']; |
|||
} |
|||
|
|||
$contracts_list = []; |
|||
foreach ($contractData as $month=>$v) { |
|||
$contracts_list[$month] = ['money'=>array_sum($v['money']),'count'=>count($v['contract_id'])]; |
|||
} |
|||
|
|||
$data = []; |
|||
foreach ($yearAchievement as $k => $v) { |
|||
if ($month = Achievement::getFieldMonth($k)) { |
|||
$month = $year . '-' . $month; |
|||
$row = [ |
|||
'month' => $month, |
|||
'achievement' => $v, |
|||
'money' => isset($contracts_list[$month]) ? $contracts_list[$month]['money'] : 0, |
|||
'count' => isset($contracts_list[$month]) ? $contracts_list[$month]['count'] : 0, |
|||
]; |
|||
$row['ratio'] = ($row['money'] && intval($row['achievement'])) ? sprintf("%.2f", $row['money'] / $row['achievement'] * 100) : 0; |
|||
$row['unit_price'] = ($row['money'] && $row['count']) ? sprintf("%.2f", $row['money'] / $row['count']) : 0; |
|||
|
|||
$data[] = $row; |
|||
} |
|||
} |
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 回款数据排行 |
|||
*/ |
|||
public function receivablesRanking() { |
|||
$year = input('year', date('Y')); |
|||
$type = input('type', 0); |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
} |
|||
|
|||
$receivables = Receivables::where([ |
|||
'check_status' => 2, |
|||
'return_time' => ['like', $year . '%'], |
|||
])->group('owner_staff_id')->with(['staff'])->order('money desc')->field('owner_staff_id,sum(money) as money,count(*) as count')->select(); |
|||
|
|||
$receivablesData = []; |
|||
$list = []; |
|||
$i=1; |
|||
foreach ($receivables as $k => $v) { |
|||
$v['ranking'] = $i; |
|||
if(in_array($v['owner_staff_id'],$showStaffIds)){ |
|||
$i++; |
|||
$receivablesData[] = $v; |
|||
} |
|||
$list[$v['owner_staff_id']] = $v['money']; |
|||
} |
|||
|
|||
$contracts = $list; |
|||
|
|||
$data = []; |
|||
$staffs = Staff::getList(); |
|||
foreach ($staffs as $v) { |
|||
if (isset($contracts[$v['id']])) { |
|||
$data[$v['id']] = $contracts[$v['id']]; |
|||
} else { |
|||
$data[$v['id']] = 0; |
|||
} |
|||
} |
|||
arsort($data); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$oneNumber = 0; |
|||
foreach ($data as $id => $number) { |
|||
if ($i == 1) { |
|||
$oneNumber = $number; |
|||
} |
|||
$val = $staffs[$id]; |
|||
$val['number'] = $number; |
|||
$val['ratio'] = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0; |
|||
$val['rank'] = $i; |
|||
if(in_array($id,$showStaffIds)){ |
|||
$result[] = $val; |
|||
$i++; |
|||
} |
|||
} |
|||
|
|||
if (count($result) >= 10) { |
|||
|
|||
$top = array_slice($result, 0, 3); |
|||
$bottom = array_slice($result, -3, 3); |
|||
$middle = array_slice($result, 3, 4); |
|||
$result = array_merge($top, $bottom, $middle); |
|||
} |
|||
|
|||
|
|||
$this->success('请求成功', ['ranking' => $result, 'data' => $receivablesData]); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 成交数据排行 |
|||
*/ |
|||
public function contractMoneyRanking() { |
|||
$date = input('year', date('Y')); |
|||
$type = input('type', 0); |
|||
if ($type == 1) {//本人 |
|||
$showStaffIds = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$showStaffIds = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$showStaffIds = Staff::getMyStaffIds(); |
|||
} |
|||
$contracts=ContractRatio::where([ |
|||
'contract.check_status'=>2, 'contract_ratio.staff_id' => ['in',$showStaffIds], |
|||
'contract.order_date'=>['like', $date . '%'] |
|||
])->with(['contract','staff'])->select(); |
|||
$contracts=collection($contracts)->toArray(); |
|||
$contractData=[]; |
|||
foreach ($contracts as $v) { |
|||
$contractData[$v['staff_id']]['money'][] = $v['ratio_money']; |
|||
$contractData[$v['staff_id']]['contract_id'][] = $v['contract_id']; |
|||
$contractData[$v['staff_id']]['staff'] = $v['staff']; |
|||
$contractData[$v['staff_id']]['staff_id'] = $v['staff_id']; |
|||
} |
|||
|
|||
$receivables = []; |
|||
foreach ($contractData as $v) { |
|||
$receivables[] = [ |
|||
'money'=>array_sum($v['money']), |
|||
'count'=>count($v['contract_id']), |
|||
'staff'=>$v['staff'], |
|||
'owner_staff_id'=>$v['staff_id'], |
|||
]; |
|||
} |
|||
$this->arraySortByOneField($receivables,'money',SORT_DESC); |
|||
$receivablesData = []; |
|||
$list = []; |
|||
foreach ($receivables as $k => $v) { |
|||
$v['ranking'] = $k + 1; |
|||
$v['unit_price'] = ($v['money'] && $v['count']) ? sprintf("%.2f", $v['money'] / $v['count']) : 0; |
|||
if(in_array($v['owner_staff_id'],$showStaffIds)){ |
|||
$receivablesData[] = $v; |
|||
} |
|||
$list[$v['owner_staff_id']] = $v['money']; |
|||
} |
|||
|
|||
$contracts = $list; |
|||
|
|||
$data = []; |
|||
$staffs = Staff::getList(); |
|||
foreach ($staffs as $v) { |
|||
if (isset($contracts[$v['id']])) { |
|||
$data[$v['id']] = $contracts[$v['id']]; |
|||
} else { |
|||
$data[$v['id']] = 0; |
|||
} |
|||
} |
|||
arsort($data); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$oneNumber = 0; |
|||
foreach ($data as $id => $number) { |
|||
if ($i == 1) { |
|||
$oneNumber = $number; |
|||
} |
|||
$val = $staffs[$id]; |
|||
$val['number'] = $number; |
|||
$val['ratio'] = $oneNumber ? sprintf("%.2f", $number / $oneNumber * 100) : 0; |
|||
$val['rank'] = $i; |
|||
$i++; |
|||
if(in_array($id,$showStaffIds)){ |
|||
$result[] = $val; |
|||
} |
|||
} |
|||
|
|||
if (count($result) >= 10) { |
|||
|
|||
$top = array_slice($result, 0, 3); |
|||
$bottom = array_slice($result, -3, 3); |
|||
$middle = array_slice($result, 3, 4); |
|||
$result = array_merge($top, $bottom, $middle); |
|||
} |
|||
|
|||
|
|||
$this->success('请求成功', ['ranking' => $result, 'data' => $receivablesData]); |
|||
} |
|||
|
|||
/** |
|||
* 新增排行 |
|||
*/ |
|||
public function newRanking() { |
|||
$year = input('date', date('Y')); |
|||
$between = [strtotime($year . '-01-01'), strtotime($year.'-1-1 +1 year')]; |
|||
$betweenC = [date('Y-m-d 00:00:00',strtotime($year . '-01-01')), date('Y-m-d 23:59:59',strtotime($year.'-1-1 +1 year'))]; |
|||
$customers = Customer::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => $this->auth->id |
|||
])->group('month')->field("FROM_UNIXTIME(createtime,'%Y-%m') as month,count(*) as count")->select(); |
|||
|
|||
$customers_list = []; |
|||
foreach ($customers as $v) { |
|||
$customers_list[$v['month']] = $v['count']; |
|||
} |
|||
$contracts = Contract::where([ |
|||
'order_date' => [ |
|||
'between', |
|||
$betweenC |
|||
], |
|||
'owner_staff_id' => $this->auth->id, |
|||
'check_status'=>2 |
|||
])->group('month')->field('FROM_UNIXTIME(createtime,"%Y-%m") as month,count(*) as count')->select(); |
|||
|
|||
$contracts_list = []; |
|||
foreach ($contracts as $v) { |
|||
$contracts_list[$v['month']] = $v['count']; |
|||
} |
|||
$leads = Leads::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => $this->auth->id |
|||
])->group('month')->field('FROM_UNIXTIME(createtime,"%Y-%m") as month,count(*) as count')->select(); |
|||
$leads_list = []; |
|||
foreach ($leads as $v) { |
|||
$leads_list[$v['month']] = $v['count']; |
|||
} |
|||
$data = []; |
|||
for ($i = 1; $i <= 12; $i++) { |
|||
$month = date('Y-m', strtotime($year . '-' . $i)); |
|||
$data[] = [ |
|||
'month' => $month, |
|||
'customers' => $customers_list[$month] ?? 0, |
|||
'contracts' => $contracts_list[$month] ?? 0, |
|||
'leads' => $leads_list[$month] ?? 0, |
|||
]; |
|||
} |
|||
|
|||
$this->success('请求成功', $data); |
|||
} |
|||
|
|||
/** |
|||
* 获取团队新增统计 |
|||
*/ |
|||
public function addCustomerStatistics() { |
|||
$date = input('date', date('Y-m')); |
|||
if(strlen($date) == 4){ |
|||
$between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1]; |
|||
}else{ |
|||
$between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1]; |
|||
} |
|||
|
|||
|
|||
$ids = Staff::getMyStaffIds(); |
|||
$staffs = Staff::where(['id' => ['in', $ids]])->field('id,name,post,img')->select(); |
|||
|
|||
$c = Customer::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => ['in', $ids] |
|||
])->group('owner_staff_id')->order('count desc')->field("owner_staff_id,count(*) as count")->select(); |
|||
$customers = []; |
|||
foreach ($c as $v) { |
|||
$customers[$v['owner_staff_id']] = $v['count']; |
|||
} |
|||
$l = Leads::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => ['in', $ids] |
|||
])->group('owner_staff_id')->field("owner_staff_id,count(*) as count")->select(); |
|||
$leads = []; |
|||
foreach ($l as $v) { |
|||
$leads[$v['owner_staff_id']] = $v['count']; |
|||
} |
|||
$t = Contract::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => ['in', $ids] |
|||
])->group('owner_staff_id')->field("owner_staff_id,count(*) as count")->select(); |
|||
$contracts = []; |
|||
foreach ($t as $v) { |
|||
$contracts[$v['owner_staff_id']] = $v['count']; |
|||
} |
|||
$total=[]; |
|||
$total[0]=[ |
|||
'name'=>'数据汇总', |
|||
'id'=>0, |
|||
'leads'=>0, |
|||
'customers'=>0, |
|||
'contracts'=>0, |
|||
]; |
|||
$sort=[]; |
|||
foreach ($staffs as $k => $v) { |
|||
|
|||
$v['leads'] = $leads[$v['id']] ?? 0; |
|||
$v['customers'] = $customers[$v['id']] ?? 0; |
|||
$v['contracts'] = $contracts[$v['id']] ?? 0; |
|||
$sort[$v['id']] = $v['leads'] + $v['customers'] + $v['contracts']; |
|||
$total[0]['leads'] += $v['leads']; |
|||
$total[0]['customers'] += $v['customers']; |
|||
$total[0]['contracts'] += $v['contracts']; |
|||
$staffs[$v['id']] = $v; |
|||
} |
|||
arsort($sort); |
|||
$result=[]; |
|||
foreach ($sort as $id=>$v){ |
|||
$result[]=$staffs[$id]; |
|||
} |
|||
$staffs=array_merge($total,$result); |
|||
$this->success('请求成功',$staffs); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 客户新增排行 |
|||
*/ |
|||
public function newCustomer() { |
|||
$date = input('date', date('Y-m')); |
|||
$type = input('type', 0); |
|||
|
|||
if(strlen($date) == 4){ |
|||
$between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1]; |
|||
}else{ |
|||
$between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1]; |
|||
} |
|||
if ($type == 1) {//本人 |
|||
$ids = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$ids = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$ids = Staff::getMyStaffIds(); |
|||
} |
|||
$c = Customer::where([ |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
], |
|||
'owner_staff_id' => ['in', $ids] |
|||
])->group('owner_staff_id')->order('count desc')->field("owner_staff_id,count(*) as count")->select(); |
|||
$customers = []; |
|||
foreach ($c as $v) { |
|||
$customers[$v['owner_staff_id']] = $v['count']; |
|||
} |
|||
|
|||
arsort($customers); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$i = 1; |
|||
$data=[]; |
|||
foreach ($customers as $id => $number) { |
|||
$val = $staffs[$id]; |
|||
$val['number'] = $number; |
|||
$val['rank'] = $i; |
|||
$data[]=[ |
|||
'name'=>$val['name'], |
|||
'number'=>$number |
|||
]; |
|||
$i++; |
|||
$result[] = $val; |
|||
} |
|||
|
|||
$this->success('请求成功',['ranking' => $result, 'data' => $data]); |
|||
} |
|||
|
|||
/** |
|||
* 客户跟进排行 |
|||
*/ |
|||
public function newRecord() { |
|||
$date = input('date', date('Y-m')); |
|||
$type = input('type', 0); |
|||
|
|||
if(strlen($date) == 4){ |
|||
$between = [strtotime($date . '-01-01'), strtotime($date.'-1-1 +1 year') - 1]; |
|||
}else{ |
|||
$between = [strtotime($date), strtotime('+1 month', strtotime($date)) - 1]; |
|||
} |
|||
if ($type == 1) {//本人 |
|||
$ids = [$this->auth->id]; |
|||
} elseif ($type == 2) {//下属 |
|||
$ids = Staff::getLowerStaffId(); |
|||
} else {//全部 |
|||
$ids = Staff::getMyStaffIds(); |
|||
} |
|||
//跟进次数 |
|||
$r= Record::where([ |
|||
'create_staff_id' => ['in',$ids], |
|||
'relation_type' =>1, |
|||
'createtime' => [ |
|||
'between', |
|||
$between |
|||
] |
|||
])->field("create_staff_id,count(*) as count")->group('create_staff_id')->select(); |
|||
|
|||
$records = []; |
|||
foreach ($r as $v) { |
|||
$records[$v['create_staff_id']] = $v['count']; |
|||
} |
|||
|
|||
arsort($records); |
|||
$staffs = Staff::getKeyList(); |
|||
$result = []; |
|||
$data = []; |
|||
$i = 1; |
|||
foreach ($records as $id => $number) { |
|||
$val = $staffs[$id]; |
|||
$val['number'] = $number; |
|||
$val['rank'] = $i; |
|||
$data[]=[ |
|||
'name'=>$val['name'], |
|||
'number'=>$number |
|||
]; |
|||
$i++; |
|||
$result[] = $val; |
|||
} |
|||
|
|||
$this->success('请求成功',['ranking' => $result, 'data' => $data]); |
|||
} |
|||
|
|||
/** |
|||
* 获取业绩详情 |
|||
*/ |
|||
public function getAchievementDetail() |
|||
{ |
|||
$year = input('year', date('Y')); |
|||
$status = input('status', 1); |
|||
$staff_id = input('staff_id', ''); |
|||
if (empty($staff_id)) { |
|||
$this->error('员工不能为空'); |
|||
} |
|||
|
|||
$ids = $staff_id; |
|||
|
|||
$achievements = AchievementModel::where(['type' => 3, 'obj_id' => ['in', $ids], 'year' => $year, 'status' => $status]) |
|||
->field('sum(january) as january,sum(february) as february,sum(march) as march,sum(april) as april,sum(may) as may,sum(june) as june,sum(july) as july,sum(august) as august,sum(september) as september,sum(october) as october,sum(november) as november,sum(december) as december,sum(yeartarget) as yeartarget')->find()->toArray(); |
|||
if ($status == 1) {//合同金额 |
|||
$contracts = ContractRatio::where([ |
|||
'contract.check_status' => 2, 'contract_ratio.staff_id' => ['in', $ids], |
|||
'contract.order_date' => ['like', $year . '%'] |
|||
])->with(['contract'])->select(); |
|||
$contracts = collection($contracts)->toArray(); |
|||
$contractData = []; |
|||
foreach ($contracts as $v) { |
|||
$order_date = $v['contract']['order_date']; |
|||
$month = date('Y-m', strtotime($order_date)); |
|||
$contractData[$month]['money'][] = $v['ratio_money']; |
|||
$contractData[$month]['contract_id'][] = $v['contract_id']; |
|||
} |
|||
|
|||
$list = []; |
|||
foreach ($contractData as $month => $v) { |
|||
$list[$month] = ['money' => array_sum($v['money']), 'count' => count($v['contract_id'])]; |
|||
} |
|||
} else { |
|||
$receivables = Receivables::where([ |
|||
'owner_staff_id' => ['in', $ids], |
|||
'check_status' => 2, |
|||
'return_time' => ['like', $year . '%'], |
|||
])->group('month') |
|||
->field('sum(money) as money,FROM_UNIXTIME(UNIX_TIMESTAMP(return_time),"%Y-%m") as month,count(*) as count')->select(); |
|||
$list = []; |
|||
foreach ($receivables as $v) { |
|||
$list[$v['month']] = $v; |
|||
} |
|||
} |
|||
$data = []; |
|||
$echartdata = []; |
|||
foreach ($achievements as $k => $v) { |
|||
if ($month = AchievementModel::getFieldMonth($k)) { |
|||
$month = $year . '-' . $month; |
|||
$row = [ |
|||
'month' => $month, |
|||
'achievement' => $v ?? 0, |
|||
'money' => isset($list[$month]) ? $list[$month]['money'] : 0, |
|||
'count' => isset($list[$month]) ? $list[$month]['count'] : 0, |
|||
]; |
|||
$row['ratio'] = ($row['money'] && intval($row['achievement'])) ? sprintf("%.2f", $row['money'] / $row['achievement'] * 100) : 0; |
|||
$row['unit_price'] = ($row['money'] && $row['count']) ? sprintf("%.2f", $row['money'] / $row['count']) : 0; |
|||
|
|||
$echartdata['month'][] = $row['month']; |
|||
$echartdata['achievement'][] = $row['achievement']??0; |
|||
$echartdata['money'][] = $row['money']; |
|||
$data[] = $row; |
|||
} |
|||
} |
|||
$money = isset($echartdata['money']) ? array_sum($echartdata['money']) : 0; |
|||
$ratio = ($money && intval($achievements['yeartarget'])) ? sprintf("%.2f", $money / $achievements['yeartarget'] * 100) : 0; |
|||
$yeartarget = [ |
|||
'year' => $year, |
|||
'money' => $money, |
|||
'achievement' => $achievements['yeartarget'] ?? 0, |
|||
'ratio' => $ratio |
|||
]; |
|||
$this->success('请求成功', ['data' => $data, 'echartdata' => $echartdata, 'yeartarget' => $yeartarget]); |
|||
} |
|||
|
|||
/** |
|||
* 排序 |
|||
* @param $data |
|||
* @param $field |
|||
* @param int $sort |
|||
* @return mixed |
|||
*/ |
|||
public function arraySortByOneField($data, $field, $sort = SORT_ASC) |
|||
{ |
|||
$field = array_column($data, $field); |
|||
array_multisort($field, $sort, $data); |
|||
return $data; |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
|
|||
use addons\qingdong\model\Staff; |
|||
use addons\qingdong\model\AdminConfig; |
|||
use think\Log; |
|||
use WeWork\Crypt\WXBizMsgCrypt; |
|||
|
|||
/** |
|||
* * 操作文档:https://doc.fastadmin.net/qingdong |
|||
* 软件介绍:https://www.fastadmin.net/store/qingdong.html |
|||
* 售后微信:qingdong_crm |
|||
* 企业微信接口 |
|||
*/ |
|||
class Wx extends StaffApi |
|||
{ |
|||
protected $noNeedLogin = ['userid','template','token']; |
|||
protected $noNeedRight = []; |
|||
|
|||
|
|||
public function _initialize() |
|||
{ |
|||
parent::_initialize(); |
|||
} |
|||
|
|||
//验证 |
|||
public function token() |
|||
{ |
|||
$corpId = AdminConfig::getConfigValue('wechat', 'corpid'); |
|||
$token = ''; |
|||
$encodingAesKey = ''; |
|||
Log::write('a---' . json_encode($_GET)); |
|||
|
|||
$sVerifyMsgSig = input('msg_signature'); |
|||
$sVerifyTimeStamp = input('timestamp'); |
|||
$sVerifyNonce = input('nonce'); |
|||
$sVerifyEchoStr = input('echostr'); |
|||
|
|||
if (empty($sVerifyMsgSig) || empty($sVerifyTimeStamp) || empty($sVerifyNonce) || empty($sVerifyEchoStr)) { |
|||
$this->error('参数不正确'); |
|||
} |
|||
|
|||
$sEchoStr = ""; |
|||
$wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId); |
|||
$errCode = $wxcpt->VerifyURL($sVerifyMsgSig, $sVerifyTimeStamp, $sVerifyNonce, $sVerifyEchoStr, $sEchoStr); |
|||
if ($errCode == 0) { |
|||
return $sEchoStr; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\controller; |
|||
/** |
|||
* 对微信小程序用户加密数据的解密示例代码. |
|||
* |
|||
* @copyright Copyright (c) 1998-2014 Tencent Inc. |
|||
*/ |
|||
|
|||
|
|||
|
|||
class Wxbizdatacrypt |
|||
{ |
|||
private $appid; |
|||
private $sessionKey; |
|||
|
|||
/** |
|||
* 构造函数 |
|||
* @param $sessionKey string 用户在小程序登录后获取的会话密钥 |
|||
* @param $appid string 小程序的appid |
|||
*/ |
|||
public function __construct( $appid, $sessionKey) |
|||
{ |
|||
$this->sessionKey = $sessionKey; |
|||
$this->appid = $appid; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 检验数据的真实性,并且获取解密后的明文. |
|||
* @param $encryptedData string 加密的用户数据 |
|||
* @param $iv string 与用户数据一同返回的初始向量 |
|||
* @param $data string 解密后的原文 |
|||
* |
|||
* @return int 成功0,失败返回对应的错误码 |
|||
*/ |
|||
public function decryptData( $encryptedData, $iv, &$data ) |
|||
{ |
|||
if (strlen($this->sessionKey) != 24) { |
|||
return ErrorCode::$IllegalAesKey; |
|||
} |
|||
$aesKey=base64_decode($this->sessionKey); |
|||
|
|||
|
|||
if (strlen($iv) != 24) { |
|||
return ErrorCode::$IllegalIv; |
|||
} |
|||
$aesIV=base64_decode($iv); |
|||
|
|||
$aesCipher=base64_decode($encryptedData); |
|||
|
|||
$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV); |
|||
|
|||
$dataObj=json_decode( $result ); |
|||
if( $dataObj == NULL ) |
|||
{ |
|||
return ErrorCode::$IllegalBuffer; |
|||
} |
|||
if( $dataObj->watermark->appid != $this->appid ) |
|||
{ |
|||
return ErrorCode::$IllegalBuffer; |
|||
} |
|||
$data = $result; |
|||
return ErrorCode::$OK; |
|||
} |
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,532 @@ |
|||
<?php |
|||
|
|||
|
|||
// 公共助手函数 |
|||
|
|||
use Symfony\Component\VarExporter\VarExporter; |
|||
|
|||
/** |
|||
* 求两个已知经纬度之间的距离,单位为米 |
|||
* @param lng1 $ ,lng2 经度 |
|||
* @param lat1 $ ,lat2 纬度 |
|||
* @return float 距离,单位米 |
|||
* @author www.Alixixi.com |
|||
*/ |
|||
function getdistance($lng1, $lat1, $lng2, $lat2) |
|||
{ |
|||
// 将角度转为狐度 |
|||
$radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度 |
|||
$radLat2 = deg2rad($lat2); |
|||
$radLng1 = deg2rad($lng1); |
|||
$radLng2 = deg2rad($lng2); |
|||
$a = $radLat1 - $radLat2; |
|||
$b = $radLng1 - $radLng2; |
|||
$s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000; |
|||
|
|||
return $s; |
|||
} |
|||
|
|||
function float_number($number) |
|||
{ |
|||
$number = intval($number); |
|||
$length = strlen(intval($number)); //数字长度 |
|||
if ($length > 3) { //万单位 |
|||
//截取前俩为 |
|||
$str = substr_replace(strstr($number, substr($number, -2), ' '), '.', -1, 0) . "公里"; |
|||
} else { |
|||
return $number . '米'; |
|||
} |
|||
|
|||
return $str . '米'; |
|||
} |
|||
|
|||
function build_field_option($name = null, $selected = null,$type = null) |
|||
{ |
|||
//获取选项列表 |
|||
$fields = \addons\qingdong\model\Field::getField($name,$type); |
|||
$html = '<option value="">请选择'.$name.'</option>'; |
|||
foreach ($fields as $v) { |
|||
if ($selected == $v) { |
|||
$html .= "<option value='{$v}' selected='selected'>{$v}</option>"; |
|||
} else { |
|||
$html .= "<option value='{$v}'>{$v}</option>"; |
|||
} |
|||
} |
|||
|
|||
return $html; |
|||
} |
|||
|
|||
//修改多维数组为一位数组 |
|||
function modify_array($arr, $field1, $field2) |
|||
{ |
|||
$data = []; |
|||
foreach ($arr as $v) { |
|||
$data[$v[$field1] ?? ''] = $v[$field2] ?? ''; |
|||
} |
|||
|
|||
return $data; |
|||
} |
|||
|
|||
//显示文件夹 |
|||
function showdir($path) |
|||
{ |
|||
$dh = opendir($path);//打开目录 |
|||
$arr = []; |
|||
while (($d = readdir($dh)) != false) { |
|||
//逐个文件读取,添加!=false条件,是为避免有文件或目录的名称为0 |
|||
if ($d == '.' || $d == '..') {//判断是否为.或..,默认都会有 |
|||
continue; |
|||
} |
|||
if (is_dir($path . '/' . $d)) {//如果为目录 |
|||
$lowers = showdir($path . '/' . $d);//继续读取该目录下的目录或文件 |
|||
if ($lowers) { |
|||
$arr = array_merge($arr, $lowers); |
|||
} |
|||
} else { |
|||
$arr[] = $path . '/' . $d; |
|||
} |
|||
} |
|||
|
|||
return $arr; |
|||
} |
|||
//获取年度列表 |
|||
function getYears(){ |
|||
|
|||
$start=2020; |
|||
$years=[]; |
|||
$toYear=date('Y'); |
|||
$end=date('Y')+1; |
|||
for ($start;$start<=$end;$start++){ |
|||
if($start == $toYear){ |
|||
$years[]=[ |
|||
'id'=>$start, |
|||
'name'=>$start.'年', |
|||
'selected'=>'selected' |
|||
]; |
|||
}else{ |
|||
$years[]=[ |
|||
'id'=>$start, |
|||
'name'=>$start.'年', |
|||
]; |
|||
} |
|||
} |
|||
return $years; |
|||
} |
|||
|
|||
///随机字符串,字母+数字 |
|||
function genRandomString($len,$t=0) |
|||
{ |
|||
$chars = array( |
|||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", |
|||
"l", "m", "n", "p", "q", "r", "s", "t", "u", "v", |
|||
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", |
|||
"H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", |
|||
"S", "T", "U", "V", "W", "X", "Y", "Z" |
|||
); |
|||
|
|||
$chars1= array( |
|||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", |
|||
"l", "m", "n", "p", "q", "r", "s", "t", "u", "v", |
|||
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", |
|||
"H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", |
|||
"S", "T", "U", "V", "W", "X", "Y", "Z" |
|||
); |
|||
|
|||
$chars2 = array( |
|||
"1", "2", |
|||
"3", "4", "5", "6", "7", "8", "9" |
|||
); |
|||
$chars3 = array( |
|||
"A", "B", "C", "D", "E", "F", "G", "O" , |
|||
"H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", |
|||
"S", "T", "U", "V", "W", "X", "Y", "Z" |
|||
); |
|||
$chars4 = array( |
|||
"A", "B", "C", "D", "E", "F", "G", |
|||
"H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", |
|||
"S", "T", "U", "V", "W", "X", "Y", "Z", "1","2", |
|||
"3", "4", "5", "6", "7", "8", "9" |
|||
); |
|||
|
|||
if($t==1){ |
|||
|
|||
$charsLen = count($chars1) - 1; |
|||
|
|||
shuffle($chars1); // 将数组打乱 |
|||
|
|||
$output = ""; |
|||
for ($i=0; $i<$len; $i++) |
|||
{ |
|||
$output .= $chars1[mt_rand(0, $charsLen)]; |
|||
} |
|||
|
|||
}elseif($t==2){ |
|||
|
|||
$charsLen = count($chars2) - 1; |
|||
|
|||
shuffle($chars2); // 将数组打乱 |
|||
|
|||
$output = ""; |
|||
for ($i=0; $i<$len; $i++) |
|||
{ |
|||
$output .= $chars2[mt_rand(0, $charsLen)]; |
|||
} |
|||
|
|||
}elseif($t==3){ |
|||
|
|||
$charsLen = count($chars3) - 1; |
|||
|
|||
shuffle($chars3); // 将数组打乱 |
|||
|
|||
$output = ""; |
|||
for ($i=0; $i<$len; $i++) |
|||
{ |
|||
$output .= $chars3[mt_rand(0, $charsLen)]; |
|||
} |
|||
|
|||
}elseif($t==4){ |
|||
|
|||
$charsLen = count($chars4) - 1; |
|||
|
|||
shuffle($chars4); // 将数组打乱 |
|||
|
|||
$output = ""; |
|||
for ($i=0; $i<$len; $i++) |
|||
{ |
|||
$output .= $chars4[mt_rand(0, $charsLen)]; |
|||
} |
|||
}else{ |
|||
|
|||
$charsLen = count($chars) - 1; |
|||
|
|||
shuffle($chars); // 将数组打乱 |
|||
|
|||
$output = ""; |
|||
for ($i=0; $i<$len; $i++) |
|||
{ |
|||
$output .= $chars[mt_rand(0, $charsLen)]; |
|||
} |
|||
} |
|||
|
|||
return $output; |
|||
|
|||
} |
|||
|
|||
//将表情进行转义 用于存储的时候 |
|||
function emoji_encode($str){ |
|||
if(!is_string($str)) return $str; |
|||
|
|||
if(!$str || $str=='undefined') return ''; |
|||
|
|||
|
|||
|
|||
$text = json_encode($str); //暴露出unicode |
|||
|
|||
$text = preg_replace_callback("/(\\\u[2def][0-9a-f]{3})/i",function($str){ |
|||
|
|||
return addslashes($str[0]); |
|||
|
|||
},$text); //将emoji的unicode留下,其他不动,这里的正则比原答案增加了d,因为我发现我很多emoji实际上是\ud开头的,反而暂时没发现有\ue开头。 |
|||
|
|||
return json_decode($text); |
|||
} |
|||
//将表情进行反转义 用于读取的时候 |
|||
function emoji_decode($str){ |
|||
$text = json_encode($str); //暴露出unicode |
|||
|
|||
$text = preg_replace_callback('/\\\\\\\\/i',function($str){ |
|||
|
|||
return '\\'; |
|||
|
|||
},$text); //将两条斜杠变成一条,其他不动 |
|||
|
|||
return json_decode($text); |
|||
} |
|||
//过滤emoji |
|||
function filter_Emoji($str) |
|||
{ |
|||
$str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换 |
|||
'/./u', |
|||
function (array $match) { |
|||
return strlen($match[0]) >= 4 ? '' : $match[0]; |
|||
}, |
|||
$str); |
|||
|
|||
return $str; |
|||
} |
|||
//获取编号 |
|||
function get_num($type) |
|||
{ |
|||
return 'R' . date('Ymd') . rand(10000, 99999); |
|||
} |
|||
|
|||
|
|||
if (!function_exists('setTimes')) { |
|||
|
|||
/** |
|||
* @param $times |
|||
* @param string $type date|datetime|time |
|||
* @return array|string |
|||
*/ |
|||
function setTimes($times, $type = 'date') |
|||
{ |
|||
switch ($times) { |
|||
case 'today': |
|||
$today = date('Y-m-d'); |
|||
$todayend = date('Y-m-d'); |
|||
$result = [$today, $todayend]; |
|||
break; |
|||
case 'yesterday': |
|||
$yesterday = date('Y-m-d', strtotime('-1 day')); |
|||
$result = [$yesterday, $yesterday]; |
|||
break; |
|||
case 'tomorrow': |
|||
$tomorrow = date('Y-m-d', strtotime('+1 day')); |
|||
$result = [$tomorrow, $tomorrow]; |
|||
break; |
|||
case 'thisweek': |
|||
$thisweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1, date("Y"))); |
|||
$thisweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7, date("Y"))); |
|||
$result = [$thisweek_start, $thisweek_end]; |
|||
break; |
|||
case 'lastweek': |
|||
$lastweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1 - 7, date("Y"))); |
|||
$lastweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7 - 7, date("Y"))); |
|||
$result = [$lastweek_start, $lastweek_end]; |
|||
break; |
|||
case 'nextweek': |
|||
$lastweek_start = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - date("w") + 1 + 7, date("Y"))); |
|||
$lastweek_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("d") - date("w") + 7 + 7, date("Y"))); |
|||
$result = [$lastweek_start, $lastweek_end]; |
|||
break; |
|||
case 'thismonth': |
|||
$thismonth_start = date("Y-m-d", mktime(0, 0, 0, date("m"), 1, date("Y"))); |
|||
$thismonth_end = date("Y-m-d", mktime(23, 59, 59, date("m"), date("t"), date("Y"))); |
|||
$result = [$thismonth_start, $thismonth_end]; |
|||
break; |
|||
case 'lastmonth': |
|||
$lastmonth_start = date("Y-m-d", mktime(0, 0, 0, date("m") - 1, 1, date("Y"))); |
|||
$lastmonth_end = date("Y-m-d", mktime(23, 59, 59, date("m"), 0, date("Y"))); |
|||
$result = [$lastmonth_start, $lastmonth_end]; |
|||
break; |
|||
case 'nextmonth': |
|||
$nextmonth_start = date("Y-m-d", mktime(0, 0, 0, date("m") + 1, 1, date("Y"))); |
|||
$nextmonth_end = date("Y-m-d", mktime(23, 59, 59, date("m") + 1, date("t"), date("Y"))); |
|||
$result = [$nextmonth_start, $nextmonth_end]; |
|||
break; |
|||
case 'thisquarter': |
|||
//本季度未最后一月天数 |
|||
$getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3, 1, date("Y"))); |
|||
//本季度/ |
|||
$thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3, 1, date('Y'))); |
|||
$thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3, $getMonthDays, date('Y'))); |
|||
|
|||
$result = [$thisquarter_start, $thisquarter_end]; |
|||
break; |
|||
case 'lastquarter': |
|||
//上季度未最后一月天数 |
|||
$getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3 - 3, 1, date("Y"))); |
|||
$thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3 - 3, 1, date('Y'))); |
|||
$thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3 - 3, $getMonthDays, date('Y'))); |
|||
|
|||
$result = [$thisquarter_start, $thisquarter_end]; |
|||
break; |
|||
case 'nextquarter': |
|||
//下季度未最后一月天数 |
|||
$getMonthDays = date("t", mktime(0, 0, 0, date('n') + (date('n') - 1) % 3 + 3, 1, date("Y"))); |
|||
$thisquarter_start = date('Y-m-d', mktime(0, 0, 0, date('n') - (date('n') - 1) % 3 + 3, 1, date('Y'))); |
|||
$thisquarter_end = date('Y-m-d', mktime(23, 59, 59, date('n') + (date('n') - 1) % 3 + 3, $getMonthDays, date('Y'))); |
|||
|
|||
$result = [$thisquarter_start, $thisquarter_end]; |
|||
break; |
|||
case 'thisyear': |
|||
//今年 |
|||
$thisyear_start = date('Y') . '-1-1'; |
|||
$thisquarter_end = date('Y') . '-12-31'; |
|||
|
|||
$result = [$thisyear_start, $thisquarter_end]; |
|||
break; |
|||
case 'lastyear': |
|||
//去年 |
|||
$lastyear_start = date('Y') . '-1-1'; |
|||
$lastyear_end = date('Y') . '-12-31'; |
|||
|
|||
$result = [$lastyear_start, $lastyear_end]; |
|||
break; |
|||
case 'nextyear': |
|||
//下一年 |
|||
$nextyear_start = date('Y') . '-1-1'; |
|||
$nextyear_end = date('Y') . '-12-31'; |
|||
|
|||
$result = [$nextyear_start, $nextyear_end]; |
|||
break; |
|||
default: |
|||
$times = explode(',', $times); |
|||
$result = [$times[0] ?? date('Y-m-d'), $times[1] ?? date('Y-m-d')]; |
|||
break; |
|||
|
|||
} |
|||
if ($type == 'date') { |
|||
return $result; |
|||
} elseif ($type == 'datetime') { |
|||
$result[0] = date('Y-m-d H:i:s', strtotime($result[0])); |
|||
$result[1] = date('Y-m-d H:i:s', strtotime($result[1]) + 86400 - 1); |
|||
return $result; |
|||
} elseif ($type == 'time') { |
|||
$result[0] =strtotime($result[0]); |
|||
$result[1] =strtotime($result[1]) + 86400 - 1; |
|||
return $result; |
|||
} else { |
|||
return $result; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
if (!function_exists('export_excel')){ |
|||
|
|||
//导出excel |
|||
function export_excel($title, $expTableData, $excel = 'export') |
|||
{ |
|||
|
|||
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); |
|||
header('Content-Disposition: attachment;filename=' . $excel . '.xlsx'); |
|||
header('Cache-Control: max-age=0'); |
|||
|
|||
$obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); |
|||
// 以下内容是excel文件的信息描述信息 |
|||
$obj->getProperties()->setTitle('导出文件'); //设置标题 |
|||
$obj->setActiveSheetIndex(0); |
|||
$obj->getActiveSheet()->setTitle('导出文件'); |
|||
/* 循环读取每个单元格的数据 */ |
|||
$a = 'A'; |
|||
$currentSheet = $obj->getActiveSheet(); |
|||
foreach ($title as $key => $value) { |
|||
//读取工作表1 |
|||
|
|||
// 设置第一行加粗 |
|||
$obj->getActiveSheet()->getStyle($a . '1')->getFont()->setBold(true); |
|||
//这里是设置单元格的内容 |
|||
$currentSheet->getCell($a . '1')->setValue($value); |
|||
$a++; |
|||
} |
|||
|
|||
//行数循环 |
|||
$b = 2; |
|||
foreach ($expTableData as $k => $row) { |
|||
$a = 'A'; |
|||
foreach ($row as $key => $value) { |
|||
//这里是设置单元格的内容 |
|||
$currentSheet->getCell($a . $b)->setValue($value); |
|||
$a++; |
|||
} |
|||
$b++; |
|||
} |
|||
|
|||
$PHPWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($obj); |
|||
$fileName = $excel . date('YmdHis') . '.xlsx'; |
|||
|
|||
$file_path = ROOT_PATH . 'public' . '/export/' . date('Y-m-d') . '/' . $fileName; |
|||
// 创建文件夹 |
|||
$path_info = pathinfo($file_path); |
|||
if ($path_info['dirname'] && !is_dir($path_info['dirname'])) { |
|||
$result = create_dir($path_info['dirname']); |
|||
if (false === $result) { |
|||
return false; |
|||
} |
|||
} |
|||
$PHPWriter->save($file_path); |
|||
$datas['filePath'] = '/' . 'export/' . date('Y-m-d') . '/' . $fileName; |
|||
$datas['fileName'] = $fileName; |
|||
$datas['size'] = filesize('./' . 'export/' . date('Y-m-d') . '/' . $fileName); |
|||
return $datas; |
|||
} |
|||
} |
|||
if (!function_exists('create_dir')){ |
|||
/** |
|||
* 创建文件夹,可以多级创建 |
|||
* @param string $filename 需要创建的文件夹路径 |
|||
* @return boolean |
|||
*/ |
|||
function create_dir($filename) { |
|||
if (!is_dir($filename)) { |
|||
create_dir(dirname($filename)); |
|||
|
|||
return mkdir($filename, 0777); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
} |
|||
|
|||
if (!function_exists('convertAmountToCn')){ |
|||
|
|||
/** |
|||
* 将数值金额转换为中文大写金额 |
|||
* @param $amount float 金额(支持到分) |
|||
* @param $type int 补整类型,0:到角补整;1:到元补整 |
|||
* @return mixed 中文大写金额 |
|||
*/ |
|||
function convertAmountToCn($amount, $type = 1) |
|||
{ |
|||
|
|||
// 判断输出的金额是否为数字或数字字符串 |
|||
if (!is_numeric($amount)) { |
|||
return "要转换的金额只能为数字!"; |
|||
} |
|||
// 金额为0,则直接输出"零元整" |
|||
|
|||
if ($amount == 0) { |
|||
return "人民币零元整"; |
|||
} |
|||
// 金额不能为负数 |
|||
if ($amount < 0) { |
|||
return "要转换的金额不能为负数!"; |
|||
} |
|||
// 金额不能超过万亿,即12位 |
|||
if (strlen($amount) > 12) { |
|||
return "要转换的金额不能为万亿及更高金额!"; |
|||
} |
|||
// 预定义中文转换的数组 |
|||
$digital = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'); |
|||
// 预定义单位转换的数组 |
|||
$position = array('仟', '佰', '拾', '亿', '仟', '佰', '拾', '万', '仟', '佰', '拾', '元'); |
|||
// 将金额的数值字符串拆分成数组 |
|||
$amountArr = explode('.', $amount); |
|||
// 将整数位的数值字符串拆分成数组 |
|||
$integerArr = str_split($amountArr[0], 1); |
|||
// 将整数部分替换成大写汉字 |
|||
$result = ''; |
|||
$integerArrLength = count($integerArr); // 整数位数组的长度 |
|||
$positionLength = count($position); // 单位数组的长度 |
|||
for ($i = 0; $i < $integerArrLength; $i++) { |
|||
// 如果数值不为0,则正常转换 |
|||
if ($integerArr[$i] != 0) { |
|||
$result = $result . $digital[$integerArr[$i]] . $position[$positionLength - $integerArrLength + $i]; |
|||
} else { |
|||
// 如果数值为0, 且单位是亿,万,元这三个的时候,则直接显示单位 |
|||
if (($positionLength - $integerArrLength + $i + 1) % 4 == 0) { |
|||
$result = $result . $position[$positionLength - $integerArrLength + $i]; |
|||
} |
|||
} |
|||
} |
|||
// 如果小数位也要转换 |
|||
if ($type == 0) { |
|||
// 将小数位的数值字符串拆分成数组 |
|||
$decimalArr = str_split($amountArr[1], 1); |
|||
// 将角替换成大写汉字. 如果为0,则不替换 |
|||
if ($decimalArr[0] != 0) { |
|||
$result = $result . $digital[$decimalArr[0]] . '角'; |
|||
} |
|||
// 将分替换成大写汉字. 如果为0,则不替换 |
|||
if ($decimalArr[1] != 0) { |
|||
$result = $result . $digital[$decimalArr[1]] . '分'; |
|||
} |
|||
} else { |
|||
$result = $result . '整'; |
|||
} |
|||
return $result; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
name = qingdong |
|||
title = 青动CRM |
|||
intro = 青动CRM客户关系管理系统 |
|||
author = qingdong |
|||
website = http://www.qingdong.vip |
|||
version = 3.1.0 |
|||
state = 1 |
|||
url = /addons/qingdong |
|||
license = extended |
|||
licenseto = 48387 |
|||
File diff suppressed because it is too large
@ -0,0 +1,3 @@ |
|||
<?php |
|||
|
|||
return []; |
|||
@ -0,0 +1,38 @@ |
|||
<?php |
|||
|
|||
return [ |
|||
'User center' => '会员中心', |
|||
'Register' => '注册', |
|||
'Login' => '登录', |
|||
'Sign up successful' => '注册成功', |
|||
'Username can not be empty' => '用户名不能为空', |
|||
'Username must be 6 to 30 characters' => '用户名必须6-30个字符', |
|||
'Password can not be empty' => '密码不能为空', |
|||
'Password must be 6 to 30 characters' => '密码必须6-30个字符', |
|||
'Mobile is incorrect' => '手机格式不正确', |
|||
'Username already exist' => '用户名已经存在', |
|||
'Nickname already exist' => '昵称已经存在', |
|||
'Email already exist' => '邮箱已经存在', |
|||
'Mobile already exist' => '手机号已经存在', |
|||
'Username is incorrect' => '用户名不正确', |
|||
'Email is incorrect' => '邮箱不正确', |
|||
'Account is locked' => '账户已经被锁定', |
|||
'Password is incorrect' => '密码不正确', |
|||
'Account is incorrect' => '账户不正确', |
|||
'Account not exist' => '账户不存在', |
|||
'Account can not be empty' => '账户不能为空', |
|||
'Username or password is incorrect' => '用户名或密码不正确', |
|||
'You are not logged in' => '你当前还未登录', |
|||
'You\'ve logged in, do not login again' => '你已经存在,请不要重复登录', |
|||
'Profile' => '个人资料', |
|||
'Verify email' => '邮箱验证', |
|||
'Change password' => '修改密码', |
|||
'Captcha is incorrect' => '验证码不正确', |
|||
'Logged in successful' => '登录成功', |
|||
'Logout successful' => '退出成功', |
|||
'Operation failed' => '操作失败', |
|||
'Invalid parameters' => '参数不正确', |
|||
'Change password failure' => '修改密码失败', |
|||
'Change password successful' => '修改密码成功', |
|||
'Reset password successful' => '重置密码成功', |
|||
]; |
|||
@ -0,0 +1,100 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\library; |
|||
|
|||
use dingding\TopSdk; |
|||
use think\Cache; |
|||
use think\Log; |
|||
use think\Model; |
|||
use addons\qingdong\model\AdminConfig; |
|||
|
|||
/** |
|||
* |
|||
*/ |
|||
class Ding extends Model |
|||
{ |
|||
public $config; |
|||
protected $app; |
|||
|
|||
|
|||
public function __construct() |
|||
{ |
|||
$this->config = [ |
|||
]; |
|||
$sdk=new TopSdk(); |
|||
return parent::__construct(); |
|||
} |
|||
|
|||
//获取accessToken |
|||
public function getAccessToken() |
|||
{ |
|||
$config = AdminConfig::where(array('type'=>'dingding'))->find(); |
|||
$tokenRequest = new \OapiGettokenRequest(); |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_GET, \DingTalkConstant::$FORMAT_JSON); |
|||
$accessKey = AdminConfig::where(array('type'=>'dingding','field'=>'ding_key'))->value('value'); |
|||
$accessSecret = AdminConfig::where(array('type'=>'dingding','field'=>'ding_secret'))->value('value'); |
|||
$tokenRequest->setAppkey($accessKey); |
|||
$tokenRequest->setAppsecret($accessSecret); |
|||
$token= $this->app->execute($tokenRequest, null, "https://oapi.dingtalk.com/gettoken"); |
|||
return $token; |
|||
} |
|||
//获取部门 |
|||
public function departmentInfo($access_token=null,$dept_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiV2DepartmentListsubRequest(); |
|||
if($dept_id){ |
|||
$req->setDeptId($dept_id); |
|||
} |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/v2/department/listsub"); |
|||
return $resp; |
|||
} |
|||
//获取员工 |
|||
public function staffInfo($access_token=null,$dept_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiUserListsimpleRequest(); |
|||
$req->setDeptId($dept_id); |
|||
$req->setCursor("0"); |
|||
$req->setSize("80"); |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/user/listsimple"); |
|||
return $resp; |
|||
} |
|||
//获取员工详情 |
|||
public function staffInfoDetail($access_token=null,$user_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiV2UserGetRequest(); |
|||
$req->setUserid($user_id); |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/v2/user/get"); |
|||
return $resp; |
|||
} |
|||
//批量获取客户 |
|||
public function customerBatch($access_token=null,$user_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiCrmObjectdataCustomerQueryRequest(); |
|||
$req->setCurrentOperatorUserid($user_id); |
|||
$req->setCursor("0"); |
|||
$req->setPageSize("100"); |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/customer/query"); |
|||
return $resp; |
|||
} |
|||
//批量获取联系人 |
|||
public function contactsBatch($access_token=null,$user_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiCrmObjectdataCustomerQueryRequest(); |
|||
$req->setCurrentOperatorUserid($user_id); |
|||
$req->setCursor("0"); |
|||
$req->setPageSize("100"); |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/contact/query"); |
|||
return $resp; |
|||
} |
|||
//批量获取跟进记录 |
|||
public function recordBatch($access_token=null,$user_id=null){ |
|||
$this->app = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON); |
|||
$req = new \OapiCrmObjectdataCustomerQueryRequest(); |
|||
$req->setCurrentOperatorUserid($user_id); |
|||
$req->setCursor("0"); |
|||
$req->setPageSize("100"); |
|||
$resp = $this->app->execute($req, $access_token, "https://oapi.dingtalk.com/topapi/crm/objectdata/followrecord/query"); |
|||
return $resp; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,113 @@ |
|||
<?php |
|||
|
|||
namespace addons\qingdong\library; |
|||
|
|||
use addons\qingdong\model\AdminConfig; |
|||
use addons\qingdong\model\Contacts; |
|||
use addons\qingdong\model\Customer; |
|||
use addons\qingdong\model\KuCustomer; |
|||
use think\Model; |
|||
use fast\Http; |
|||
|
|||
/** |
|||
* |
|||
*/ |
|||
class Ku extends Model |
|||
{ |
|||
|
|||
//客户增加 |
|||
public function addCustomer($params=null){ |
|||
$ku = AdminConfig::where(['type'=>AdminConfig::TYPE_KU])->column('field,value'); |
|||
if(isset($ku) && $ku && $params){ |
|||
if($ku['status'] == 1 && $ku['account'] && $ku['key']){ |
|||
$info = KuCustomer::where(array('customer_id'=>$params['customer_id']))->find(); |
|||
if($info){ |
|||
return true; |
|||
} |
|||
$customer = Customer::where(array('id'=>$params['customer_id']))->find(); |
|||
$url =$ku['url'].'api/kuerp/third/customers/joinCustomers'; |
|||
$sign = md5('account='.$ku['account'].'&mobile='.$params['mobile'].'&name='.$customer['name'].'key='.$ku['key']); |
|||
$data = array( |
|||
'account'=>$ku['account'], |
|||
'sign'=>$sign, |
|||
'request_time'=>time(), |
|||
'name'=>$customer['name'], |
|||
'mobile'=>$params['mobile'], |
|||
'address'=>$customer['address'], |
|||
'note'=>$customer['remarks'], |
|||
); |
|||
$result = $this->http_post($url,$data); |
|||
$result = json_decode($result,true); |
|||
if($result['code'] == 1){ |
|||
$ress = array( |
|||
'customer_id'=>$params['customer_id'], |
|||
'contacts_id'=>$params['contacts_id'], |
|||
'ku_id'=>$result['data']['id'], |
|||
'code'=>$result['data']['customer_code'], |
|||
'createtime'=>time() |
|||
); |
|||
KuCustomer::create($ress); |
|||
} |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
//客户修改 |
|||
public function editCustomer($params=null){ |
|||
|
|||
$ku = AdminConfig::where(['type'=>AdminConfig::TYPE_KU])->column('field,value'); |
|||
if(isset($ku) && $ku && $params){ |
|||
if($ku['status'] == 1 && $ku['account'] && $ku['key']){ |
|||
$info = KuCustomer::where(array('customer_id'=>$params['id']))->find(); |
|||
if(!$info){ |
|||
return true; |
|||
} |
|||
$contacts = Contacts::where(array('id'=>$info['contacts_id']))->value('mobile'); |
|||
$url =$ku['url'].'api/kuerp/third/customers/editCustomers'; |
|||
$sign = md5('account='.$ku['account'].'&code='.$info['code'].'&mobile='.$contacts.'&name='.$params['name'].'key='.$ku['key']); |
|||
$data = array( |
|||
'account'=>$ku['account'], |
|||
'sign'=>$sign, |
|||
'request_time'=>time(), |
|||
'code'=>$info['code'], |
|||
'name'=>$params['name'], |
|||
'mobile'=>$contacts, |
|||
'address'=>$params['address'], |
|||
); |
|||
$result = $this->http_post($url,$data); |
|||
$result = json_decode($result,true); |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
public function http_post($url,$param,$post_file=false){ |
|||
$oCurl = curl_init(); |
|||
if(stripos($url,"https://")!==FALSE){ |
|||
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE); |
|||
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false); |
|||
curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 |
|||
} |
|||
if (is_string($param) || $post_file) { |
|||
$strPOST = $param; |
|||
} else { |
|||
$aPOST = array(); |
|||
foreach($param as $key=>$val){ |
|||
$aPOST[] = $key."=".urlencode($val); |
|||
} |
|||
$strPOST = join("&", $aPOST); |
|||
} |
|||
curl_setopt($oCurl, CURLOPT_URL, $url); |
|||
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 ); |
|||
curl_setopt($oCurl, CURLOPT_POST,true); |
|||
curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST); |
|||
$sContent = curl_exec($oCurl); |
|||
$aStatus = curl_getinfo($oCurl); |
|||
curl_close($oCurl); |
|||
if(intval($aStatus["http_code"])==200){ |
|||
return $sContent; |
|||
}else{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Collection abstract class |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
abstract class AbstractCollection |
|||
{ |
|||
/** |
|||
* Items |
|||
* |
|||
* @var \PhpOffice\PhpWord\Element\AbstractContainer[] |
|||
*/ |
|||
private $items = array(); |
|||
|
|||
/** |
|||
* Get items |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\AbstractContainer[] |
|||
*/ |
|||
public function getItems() |
|||
{ |
|||
return $this->items; |
|||
} |
|||
|
|||
/** |
|||
* Get item by index |
|||
* |
|||
* @param int $index |
|||
* @return \PhpOffice\PhpWord\Element\AbstractContainer |
|||
*/ |
|||
public function getItem($index) |
|||
{ |
|||
if (array_key_exists($index, $this->items)) { |
|||
return $this->items[$index]; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* Set item. |
|||
* |
|||
* @param int $index |
|||
* @param \PhpOffice\PhpWord\Element\AbstractContainer $item |
|||
*/ |
|||
public function setItem($index, $item) |
|||
{ |
|||
if (array_key_exists($index, $this->items)) { |
|||
$this->items[$index] = $item; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Add new item |
|||
* |
|||
* @param \PhpOffice\PhpWord\Element\AbstractContainer $item |
|||
* @return int |
|||
*/ |
|||
public function addItem($item) |
|||
{ |
|||
$index = $this->countItems() + 1; |
|||
$this->items[$index] = $item; |
|||
|
|||
return $index; |
|||
} |
|||
|
|||
/** |
|||
* Get item count |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function countItems() |
|||
{ |
|||
return count($this->items); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Bookmarks collection |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class Bookmarks extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Charts collection |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class Charts extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Comments collection |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class Comments extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Endnotes collection |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
class Endnotes extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Footnotes collection |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
class Footnotes extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Collection; |
|||
|
|||
/** |
|||
* Titles collection |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
class Titles extends AbstractCollection |
|||
{ |
|||
} |
|||
@ -0,0 +1,181 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\ComplexType; |
|||
|
|||
use PhpOffice\PhpWord\SimpleType\NumberFormat; |
|||
|
|||
/** |
|||
* Footnote properties |
|||
* |
|||
* @see http://www.datypic.com/sc/ooxml/e-w_footnotePr-1.html |
|||
*/ |
|||
final class FootnoteProperties |
|||
{ |
|||
const RESTART_NUMBER_CONTINUOUS = 'continuous'; |
|||
const RESTART_NUMBER_EACH_SECTION = 'eachSect'; |
|||
const RESTART_NUMBER_EACH_PAGE = 'eachPage'; |
|||
|
|||
const POSITION_PAGE_BOTTOM = 'pageBottom'; |
|||
const POSITION_BENEATH_TEXT = 'beneathText'; |
|||
const POSITION_SECTION_END = 'sectEnd'; |
|||
const POSITION_DOC_END = 'docEnd'; |
|||
|
|||
/** |
|||
* Footnote Positioning Location |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $pos; |
|||
|
|||
/** |
|||
* Footnote Numbering Format w:numFmt, one of PhpOffice\PhpWord\SimpleType\NumberFormat |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $numFmt; |
|||
|
|||
/** |
|||
* Footnote and Endnote Numbering Starting Value |
|||
* |
|||
* @var float |
|||
*/ |
|||
private $numStart; |
|||
|
|||
/** |
|||
* Footnote and Endnote Numbering Restart Location |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $numRestart; |
|||
|
|||
/** |
|||
* Get the Footnote Positioning Location |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getPos() |
|||
{ |
|||
return $this->pos; |
|||
} |
|||
|
|||
/** |
|||
* Set the Footnote Positioning Location (pageBottom, beneathText, sectEnd, docEnd) |
|||
* |
|||
* @param string $pos |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setPos($pos) |
|||
{ |
|||
$position = array( |
|||
self::POSITION_PAGE_BOTTOM, |
|||
self::POSITION_BENEATH_TEXT, |
|||
self::POSITION_SECTION_END, |
|||
self::POSITION_DOC_END, |
|||
); |
|||
|
|||
if (in_array($pos, $position)) { |
|||
$this->pos = $pos; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $position) . ' possible'); |
|||
} |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get the Footnote Numbering Format |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getNumFmt() |
|||
{ |
|||
return $this->numFmt; |
|||
} |
|||
|
|||
/** |
|||
* Set the Footnote Numbering Format |
|||
* |
|||
* @param string $numFmt One of NumberFormat |
|||
* @return self |
|||
*/ |
|||
public function setNumFmt($numFmt) |
|||
{ |
|||
NumberFormat::validate($numFmt); |
|||
$this->numFmt = $numFmt; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get the Footnote Numbering Format |
|||
* |
|||
* @return float |
|||
*/ |
|||
public function getNumStart() |
|||
{ |
|||
return $this->numStart; |
|||
} |
|||
|
|||
/** |
|||
* Set the Footnote Numbering Format |
|||
* |
|||
* @param float $numStart |
|||
* @return self |
|||
*/ |
|||
public function setNumStart($numStart) |
|||
{ |
|||
$this->numStart = $numStart; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get the Footnote and Endnote Numbering Starting Value |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getNumRestart() |
|||
{ |
|||
return $this->numRestart; |
|||
} |
|||
|
|||
/** |
|||
* Set the Footnote and Endnote Numbering Starting Value (continuous, eachSect, eachPage) |
|||
* |
|||
* @param string $numRestart |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setNumRestart($numRestart) |
|||
{ |
|||
$restartNumbers = array( |
|||
self::RESTART_NUMBER_CONTINUOUS, |
|||
self::RESTART_NUMBER_EACH_SECTION, |
|||
self::RESTART_NUMBER_EACH_PAGE, |
|||
); |
|||
|
|||
if (in_array($numRestart, $restartNumbers)) { |
|||
$this->numRestart = $numRestart; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid value, on of ' . implode(', ', $restartNumbers) . ' possible'); |
|||
} |
|||
|
|||
return $this; |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\ComplexType; |
|||
|
|||
/** |
|||
* Spelling and Grammatical Checking State |
|||
* |
|||
* @see http://www.datypic.com/sc/ooxml/e-w_proofState-1.html |
|||
*/ |
|||
final class ProofState |
|||
{ |
|||
/** |
|||
* Check Completed |
|||
*/ |
|||
const CLEAN = 'clean'; |
|||
|
|||
/** |
|||
* Check Not Completed |
|||
*/ |
|||
const DIRTY = 'dirty'; |
|||
|
|||
/** |
|||
* Spell Checking State |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $spelling; |
|||
|
|||
/** |
|||
* Grammatical Checking State |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $grammar; |
|||
|
|||
/** |
|||
* Set the Spell Checking State (dirty or clean) |
|||
* |
|||
* @param string $spelling |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setSpelling($spelling) |
|||
{ |
|||
if ($spelling == self::CLEAN || $spelling == self::DIRTY) { |
|||
$this->spelling = $spelling; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid value, dirty or clean possible'); |
|||
} |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get the Spell Checking State |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getSpelling() |
|||
{ |
|||
return $this->spelling; |
|||
} |
|||
|
|||
/** |
|||
* Set the Grammatical Checking State (dirty or clean) |
|||
* |
|||
* @param string $grammar |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setGrammar($grammar) |
|||
{ |
|||
if ($grammar == self::CLEAN || $grammar == self::DIRTY) { |
|||
$this->grammar = $grammar; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid value, dirty or clean possible'); |
|||
} |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get the Grammatical Checking State |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getGrammar() |
|||
{ |
|||
return $this->grammar; |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\ComplexType; |
|||
|
|||
use PhpOffice\PhpWord\SimpleType\TblWidth as TblWidthSimpleType; |
|||
|
|||
/** |
|||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_TblWidth.html |
|||
*/ |
|||
final class TblWidth |
|||
{ |
|||
/** @var string */ |
|||
private $type; |
|||
|
|||
/** @var int */ |
|||
private $value; |
|||
|
|||
/** |
|||
* @param int $value If omitted, then its value shall be assumed to be 0 |
|||
* @param string $type If omitted, then its value shall be assumed to be dxa |
|||
*/ |
|||
public function __construct($value = 0, $type = TblWidthSimpleType::TWIP) |
|||
{ |
|||
$this->value = $value; |
|||
TblWidthSimpleType::validate($type); |
|||
$this->type = $type; |
|||
} |
|||
|
|||
/** |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* @return int |
|||
*/ |
|||
public function getValue() |
|||
{ |
|||
return $this->value; |
|||
} |
|||
} |
|||
@ -0,0 +1,166 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\ComplexType; |
|||
|
|||
/** |
|||
* Visibility of Annotation Types |
|||
* |
|||
* @see http://www.datypic.com/sc/ooxml/e-w_revisionView-1.html |
|||
*/ |
|||
final class TrackChangesView |
|||
{ |
|||
/** |
|||
* Display Visual Indicator Of Markup Area |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $markup; |
|||
|
|||
/** |
|||
* Display Comments |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $comments; |
|||
|
|||
/** |
|||
* Display Content Revisions |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $insDel; |
|||
|
|||
/** |
|||
* Display Formatting Revisions |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $formatting; |
|||
|
|||
/** |
|||
* Display Ink Annotations |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $inkAnnotations; |
|||
|
|||
/** |
|||
* Get Display Visual Indicator Of Markup Area |
|||
* |
|||
* @return bool True if markup is shown |
|||
*/ |
|||
public function hasMarkup() |
|||
{ |
|||
return $this->markup; |
|||
} |
|||
|
|||
/** |
|||
* Set Display Visual Indicator Of Markup Area |
|||
* |
|||
* @param bool $markup |
|||
* Set to true to show markup |
|||
*/ |
|||
public function setMarkup($markup) |
|||
{ |
|||
$this->markup = $markup === null ? true : $markup; |
|||
} |
|||
|
|||
/** |
|||
* Get Display Comments |
|||
* |
|||
* @return bool True if comments are shown |
|||
*/ |
|||
public function hasComments() |
|||
{ |
|||
return $this->comments; |
|||
} |
|||
|
|||
/** |
|||
* Set Display Comments |
|||
* |
|||
* @param bool $comments |
|||
* Set to true to show comments |
|||
*/ |
|||
public function setComments($comments) |
|||
{ |
|||
$this->comments = $comments === null ? true : $comments; |
|||
} |
|||
|
|||
/** |
|||
* Get Display Content Revisions |
|||
* |
|||
* @return bool True if content revisions are shown |
|||
*/ |
|||
public function hasInsDel() |
|||
{ |
|||
return $this->insDel; |
|||
} |
|||
|
|||
/** |
|||
* Set Display Content Revisions |
|||
* |
|||
* @param bool $insDel |
|||
* Set to true to show content revisions |
|||
*/ |
|||
public function setInsDel($insDel) |
|||
{ |
|||
$this->insDel = $insDel === null ? true : $insDel; |
|||
} |
|||
|
|||
/** |
|||
* Get Display Formatting Revisions |
|||
* |
|||
* @return bool True if formatting revisions are shown |
|||
*/ |
|||
public function hasFormatting() |
|||
{ |
|||
return $this->formatting; |
|||
} |
|||
|
|||
/** |
|||
* Set Display Formatting Revisions |
|||
* |
|||
* @param bool|null $formatting |
|||
* Set to true to show formatting revisions |
|||
*/ |
|||
public function setFormatting($formatting = null) |
|||
{ |
|||
$this->formatting = $formatting === null ? true : $formatting; |
|||
} |
|||
|
|||
/** |
|||
* Get Display Ink Annotations |
|||
* |
|||
* @return bool True if ink annotations are shown |
|||
*/ |
|||
public function hasInkAnnotations() |
|||
{ |
|||
return $this->inkAnnotations; |
|||
} |
|||
|
|||
/** |
|||
* Set Display Ink Annotations |
|||
* |
|||
* @param bool $inkAnnotations |
|||
* Set to true to show ink annotations |
|||
*/ |
|||
public function setInkAnnotations($inkAnnotations) |
|||
{ |
|||
$this->inkAnnotations = $inkAnnotations === null ? true : $inkAnnotations; |
|||
} |
|||
} |
|||
@ -0,0 +1,316 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Container abstract class |
|||
* |
|||
* @method Text addText(string $text, mixed $fStyle = null, mixed $pStyle = null) |
|||
* @method TextRun addTextRun(mixed $pStyle = null) |
|||
* @method Bookmark addBookmark(string $name) |
|||
* @method Link addLink(string $target, string $text = null, mixed $fStyle = null, mixed $pStyle = null, boolean $internal = false) |
|||
* @method PreserveText addPreserveText(string $text, mixed $fStyle = null, mixed $pStyle = null) |
|||
* @method void addTextBreak(int $count = 1, mixed $fStyle = null, mixed $pStyle = null) |
|||
* @method ListItem addListItem(string $txt, int $depth = 0, mixed $font = null, mixed $list = null, mixed $para = null) |
|||
* @method ListItemRun addListItemRun(int $depth = 0, mixed $listStyle = null, mixed $pStyle = null) |
|||
* @method Footnote addFootnote(mixed $pStyle = null) |
|||
* @method Endnote addEndnote(mixed $pStyle = null) |
|||
* @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null) |
|||
* @method Title addTitle(mixed $text, int $depth = 1) |
|||
* @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9) |
|||
* @method PageBreak addPageBreak() |
|||
* @method Table addTable(mixed $style = null) |
|||
* @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false, $name = null) |
|||
* @method OLEObject addOLEObject(string $source, mixed $style = null) |
|||
* @method TextBox addTextBox(mixed $style = null) |
|||
* @method Field addField(string $type = null, array $properties = array(), array $options = array(), mixed $text = null) |
|||
* @method Line addLine(mixed $lineStyle = null) |
|||
* @method Shape addShape(string $type, mixed $style = null) |
|||
* @method Chart addChart(string $type, array $categories, array $values, array $style = null, $seriesName = null) |
|||
* @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) |
|||
* @method SDT addSDT(string $type) |
|||
* |
|||
* @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
abstract class AbstractContainer extends AbstractElement |
|||
{ |
|||
/** |
|||
* Elements collection |
|||
* |
|||
* @var \PhpOffice\PhpWord\Element\AbstractElement[] |
|||
*/ |
|||
protected $elements = array(); |
|||
|
|||
/** |
|||
* Container type Section|Header|Footer|Footnote|Endnote|Cell|TextRun|TextBox|ListItemRun|TrackChange |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $container; |
|||
|
|||
/** |
|||
* Magic method to catch all 'addElement' variation |
|||
* |
|||
* This removes addText, addTextRun, etc. When adding new element, we have to |
|||
* add the model in the class docblock with `@method`. |
|||
* |
|||
* Warning: This makes capitalization matters, e.g. addCheckbox or addcheckbox won't work. |
|||
* |
|||
* @param mixed $function |
|||
* @param mixed $args |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement |
|||
*/ |
|||
public function __call($function, $args) |
|||
{ |
|||
$elements = array( |
|||
'Text', 'TextRun', 'Bookmark', 'Link', 'PreserveText', 'TextBreak', |
|||
'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'OLEObject', |
|||
'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field', |
|||
'Line', 'Shape', 'Title', 'TOC', 'PageBreak', |
|||
'Chart', 'FormField', 'SDT', 'Comment', |
|||
); |
|||
$functions = array(); |
|||
foreach ($elements as $element) { |
|||
$functions['add' . strtolower($element)] = $element == 'Object' ? 'OLEObject' : $element; |
|||
} |
|||
|
|||
// Run valid `add` command |
|||
$function = strtolower($function); |
|||
if (isset($functions[$function])) { |
|||
$element = $functions[$function]; |
|||
|
|||
// Special case for TextBreak |
|||
// @todo Remove the `$count` parameter in 1.0.0 to make this element similiar to other elements? |
|||
if ($element == 'TextBreak') { |
|||
list($count, $fontStyle, $paragraphStyle) = array_pad($args, 3, null); |
|||
if ($count === null) { |
|||
$count = 1; |
|||
} |
|||
for ($i = 1; $i <= $count; $i++) { |
|||
$this->addElement($element, $fontStyle, $paragraphStyle); |
|||
} |
|||
} else { |
|||
// All other elements |
|||
array_unshift($args, $element); // Prepend element name to the beginning of args array |
|||
|
|||
return call_user_func_array(array($this, 'addElement'), $args); |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* Add element |
|||
* |
|||
* Each element has different number of parameters passed |
|||
* |
|||
* @param string $elementName |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement |
|||
*/ |
|||
protected function addElement($elementName) |
|||
{ |
|||
$elementClass = __NAMESPACE__ . '\\' . $elementName; |
|||
$this->checkValidity($elementName); |
|||
|
|||
// Get arguments |
|||
$args = func_get_args(); |
|||
$withoutP = in_array($this->container, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field')); |
|||
if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) { |
|||
$args[3] = null; // Remove paragraph style for texts in textrun |
|||
} |
|||
|
|||
// Create element using reflection |
|||
$reflection = new \ReflectionClass($elementClass); |
|||
$elementArgs = $args; |
|||
array_shift($elementArgs); // Shift the $elementName off the beginning of array |
|||
|
|||
/** @var \PhpOffice\PhpWord\Element\AbstractElement $element Type hint */ |
|||
$element = $reflection->newInstanceArgs($elementArgs); |
|||
|
|||
// Set parent container |
|||
$element->setParentContainer($this); |
|||
$element->setElementIndex($this->countElements() + 1); |
|||
$element->setElementId(); |
|||
|
|||
$this->elements[] = $element; |
|||
|
|||
return $element; |
|||
} |
|||
|
|||
/** |
|||
* Get all elements |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement[] |
|||
*/ |
|||
public function getElements() |
|||
{ |
|||
return $this->elements; |
|||
} |
|||
|
|||
/** |
|||
* Returns the element at the requested position |
|||
* |
|||
* @param int $index |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement|null |
|||
*/ |
|||
public function getElement($index) |
|||
{ |
|||
if (array_key_exists($index, $this->elements)) { |
|||
return $this->elements[$index]; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* Removes the element at requested index |
|||
* |
|||
* @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove |
|||
*/ |
|||
public function removeElement($toRemove) |
|||
{ |
|||
if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) { |
|||
unset($this->elements[$toRemove]); |
|||
} elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) { |
|||
foreach ($this->elements as $key => $element) { |
|||
if ($element->getElementId() === $toRemove->getElementId()) { |
|||
unset($this->elements[$key]); |
|||
|
|||
return; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Count elements |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function countElements() |
|||
{ |
|||
return count($this->elements); |
|||
} |
|||
|
|||
/** |
|||
* Check if a method is allowed for the current container |
|||
* |
|||
* @param string $method |
|||
* |
|||
* @throws \BadMethodCallException |
|||
* @return bool |
|||
*/ |
|||
private function checkValidity($method) |
|||
{ |
|||
$generalContainers = array( |
|||
'Section', 'Header', 'Footer', 'Footnote', 'Endnote', 'Cell', 'TextRun', 'TextBox', 'ListItemRun', 'TrackChange', |
|||
); |
|||
|
|||
$validContainers = array( |
|||
'Text' => $generalContainers, |
|||
'Bookmark' => $generalContainers, |
|||
'Link' => $generalContainers, |
|||
'TextBreak' => $generalContainers, |
|||
'Image' => $generalContainers, |
|||
'OLEObject' => $generalContainers, |
|||
'Field' => $generalContainers, |
|||
'Line' => $generalContainers, |
|||
'Shape' => $generalContainers, |
|||
'FormField' => $generalContainers, |
|||
'SDT' => $generalContainers, |
|||
'TrackChange' => $generalContainers, |
|||
'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'), |
|||
'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), |
|||
'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), |
|||
'Table' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), |
|||
'CheckBox' => array('Section', 'Header', 'Footer', 'Cell', 'TextRun'), |
|||
'TextBox' => array('Section', 'Header', 'Footer', 'Cell'), |
|||
'Footnote' => array('Section', 'TextRun', 'Cell', 'ListItemRun'), |
|||
'Endnote' => array('Section', 'TextRun', 'Cell'), |
|||
'PreserveText' => array('Section', 'Header', 'Footer', 'Cell'), |
|||
'Title' => array('Section', 'Cell'), |
|||
'TOC' => array('Section'), |
|||
'PageBreak' => array('Section'), |
|||
'Chart' => array('Section', 'Cell'), |
|||
); |
|||
|
|||
// Special condition, e.g. preservetext can only exists in cell when |
|||
// the cell is located in header or footer |
|||
$validSubcontainers = array( |
|||
'PreserveText' => array(array('Cell'), array('Header', 'Footer', 'Section')), |
|||
'Footnote' => array(array('Cell', 'TextRun'), array('Section')), |
|||
'Endnote' => array(array('Cell', 'TextRun'), array('Section')), |
|||
); |
|||
|
|||
// Check if a method is valid for current container |
|||
if (isset($validContainers[$method])) { |
|||
if (!in_array($this->container, $validContainers[$method])) { |
|||
throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); |
|||
} |
|||
} |
|||
|
|||
// Check if a method is valid for current container, located in other container |
|||
if (isset($validSubcontainers[$method])) { |
|||
$rules = $validSubcontainers[$method]; |
|||
$containers = $rules[0]; |
|||
$allowedDocParts = $rules[1]; |
|||
foreach ($containers as $container) { |
|||
if ($this->container == $container && !in_array($this->getDocPart(), $allowedDocParts)) { |
|||
throw new \BadMethodCallException("Cannot add {$method} in {$this->container}."); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* Create textrun element |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @param mixed $paragraphStyle |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\TextRun |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function createTextRun($paragraphStyle = null) |
|||
{ |
|||
return $this->addTextRun($paragraphStyle); |
|||
} |
|||
|
|||
/** |
|||
* Create footnote element |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @param mixed $paragraphStyle |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\Footnote |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function createFootnote($paragraphStyle = null) |
|||
{ |
|||
return $this->addFootnote($paragraphStyle); |
|||
} |
|||
} |
|||
@ -0,0 +1,507 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Media; |
|||
use PhpOffice\PhpWord\PhpWord; |
|||
|
|||
/** |
|||
* Element abstract class |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
abstract class AbstractElement |
|||
{ |
|||
/** |
|||
* PhpWord object |
|||
* |
|||
* @var \PhpOffice\PhpWord\PhpWord |
|||
*/ |
|||
protected $phpWord; |
|||
|
|||
/** |
|||
* Section Id |
|||
* |
|||
* @var int |
|||
*/ |
|||
protected $sectionId; |
|||
|
|||
/** |
|||
* Document part type: Section|Header|Footer|Footnote|Endnote |
|||
* |
|||
* Used by textrun and cell container to determine where the element is |
|||
* located because it will affect the availability of other element, |
|||
* e.g. footnote will not be available when $docPart is header or footer. |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $docPart = 'Section'; |
|||
|
|||
/** |
|||
* Document part Id |
|||
* |
|||
* For header and footer, this will be = ($sectionId - 1) * 3 + $index |
|||
* because the max number of header/footer in every page is 3, i.e. |
|||
* AUTO, FIRST, and EVEN (AUTO = ODD) |
|||
* |
|||
* @var int |
|||
*/ |
|||
protected $docPartId = 1; |
|||
|
|||
/** |
|||
* Index of element in the elements collection (start with 1) |
|||
* |
|||
* @var int |
|||
*/ |
|||
protected $elementIndex = 1; |
|||
|
|||
/** |
|||
* Unique Id for element |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $elementId; |
|||
|
|||
/** |
|||
* Relation Id |
|||
* |
|||
* @var int |
|||
*/ |
|||
protected $relationId; |
|||
|
|||
/** |
|||
* Depth of table container nested level; Primarily used for RTF writer/reader |
|||
* |
|||
* 0 = Not in a table; 1 = in a table; 2 = in a table inside another table, etc. |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $nestedLevel = 0; |
|||
|
|||
/** |
|||
* A reference to the parent |
|||
* |
|||
* @var AbstractElement|null |
|||
*/ |
|||
private $parent; |
|||
|
|||
/** |
|||
* changed element info |
|||
* |
|||
* @var TrackChange |
|||
*/ |
|||
private $trackChange; |
|||
|
|||
/** |
|||
* Parent container type |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $parentContainer; |
|||
|
|||
/** |
|||
* Has media relation flag; true for Link, Image, and Object |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $mediaRelation = false; |
|||
|
|||
/** |
|||
* Is part of collection; true for Title, Footnote, Endnote, Chart, and Comment |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = false; |
|||
|
|||
/** |
|||
* The start position for the linked comment |
|||
* |
|||
* @var Comment |
|||
*/ |
|||
protected $commentRangeStart; |
|||
|
|||
/** |
|||
* The end position for the linked comment |
|||
* |
|||
* @var Comment |
|||
*/ |
|||
protected $commentRangeEnd; |
|||
|
|||
/** |
|||
* Get PhpWord |
|||
* |
|||
* @return \PhpOffice\PhpWord\PhpWord |
|||
*/ |
|||
public function getPhpWord() |
|||
{ |
|||
return $this->phpWord; |
|||
} |
|||
|
|||
/** |
|||
* Set PhpWord as reference. |
|||
* |
|||
* @param \PhpOffice\PhpWord\PhpWord $phpWord |
|||
*/ |
|||
public function setPhpWord(PhpWord $phpWord = null) |
|||
{ |
|||
$this->phpWord = $phpWord; |
|||
} |
|||
|
|||
/** |
|||
* Get section number |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getSectionId() |
|||
{ |
|||
return $this->sectionId; |
|||
} |
|||
|
|||
/** |
|||
* Set doc part. |
|||
* |
|||
* @param string $docPart |
|||
* @param int $docPartId |
|||
*/ |
|||
public function setDocPart($docPart, $docPartId = 1) |
|||
{ |
|||
$this->docPart = $docPart; |
|||
$this->docPartId = $docPartId; |
|||
} |
|||
|
|||
/** |
|||
* Get doc part |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getDocPart() |
|||
{ |
|||
return $this->docPart; |
|||
} |
|||
|
|||
/** |
|||
* Get doc part Id |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getDocPartId() |
|||
{ |
|||
return $this->docPartId; |
|||
} |
|||
|
|||
/** |
|||
* Return media element (image, object, link) container name |
|||
* |
|||
* @return string section|headerx|footerx|footnote|endnote |
|||
*/ |
|||
private function getMediaPart() |
|||
{ |
|||
$mediaPart = $this->docPart; |
|||
if ($mediaPart == 'Header' || $mediaPart == 'Footer') { |
|||
$mediaPart .= $this->docPartId; |
|||
} |
|||
|
|||
return strtolower($mediaPart); |
|||
} |
|||
|
|||
/** |
|||
* Get element index |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getElementIndex() |
|||
{ |
|||
return $this->elementIndex; |
|||
} |
|||
|
|||
/** |
|||
* Set element index. |
|||
* |
|||
* @param int $value |
|||
*/ |
|||
public function setElementIndex($value) |
|||
{ |
|||
$this->elementIndex = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get element unique ID |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getElementId() |
|||
{ |
|||
return $this->elementId; |
|||
} |
|||
|
|||
/** |
|||
* Set element unique ID from 6 first digit of md5. |
|||
*/ |
|||
public function setElementId() |
|||
{ |
|||
$this->elementId = substr(md5(rand()), 0, 6); |
|||
} |
|||
|
|||
/** |
|||
* Get relation Id |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getRelationId() |
|||
{ |
|||
return $this->relationId; |
|||
} |
|||
|
|||
/** |
|||
* Set relation Id. |
|||
* |
|||
* @param int $value |
|||
*/ |
|||
public function setRelationId($value) |
|||
{ |
|||
$this->relationId = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get nested level |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getNestedLevel() |
|||
{ |
|||
return $this->nestedLevel; |
|||
} |
|||
|
|||
/** |
|||
* Get comment start |
|||
* |
|||
* @return Comment |
|||
*/ |
|||
public function getCommentRangeStart() |
|||
{ |
|||
return $this->commentRangeStart; |
|||
} |
|||
|
|||
/** |
|||
* Set comment start |
|||
* |
|||
* @param Comment $value |
|||
*/ |
|||
public function setCommentRangeStart(Comment $value) |
|||
{ |
|||
if ($this instanceof Comment) { |
|||
throw new \InvalidArgumentException('Cannot set a Comment on a Comment'); |
|||
} |
|||
$this->commentRangeStart = $value; |
|||
$this->commentRangeStart->setStartElement($this); |
|||
} |
|||
|
|||
/** |
|||
* Get comment end |
|||
* |
|||
* @return Comment |
|||
*/ |
|||
public function getCommentRangeEnd() |
|||
{ |
|||
return $this->commentRangeEnd; |
|||
} |
|||
|
|||
/** |
|||
* Set comment end |
|||
* |
|||
* @param Comment $value |
|||
*/ |
|||
public function setCommentRangeEnd(Comment $value) |
|||
{ |
|||
if ($this instanceof Comment) { |
|||
throw new \InvalidArgumentException('Cannot set a Comment on a Comment'); |
|||
} |
|||
$this->commentRangeEnd = $value; |
|||
$this->commentRangeEnd->setEndElement($this); |
|||
} |
|||
|
|||
/** |
|||
* Get parent element |
|||
* |
|||
* @return AbstractElement|null |
|||
*/ |
|||
public function getParent() |
|||
{ |
|||
return $this->parent; |
|||
} |
|||
|
|||
/** |
|||
* Set parent container |
|||
* |
|||
* Passed parameter should be a container, except for Table (contain Row) and Row (contain Cell) |
|||
* |
|||
* @param \PhpOffice\PhpWord\Element\AbstractElement $container |
|||
*/ |
|||
public function setParentContainer(self $container) |
|||
{ |
|||
$this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1); |
|||
$this->parent = $container; |
|||
|
|||
// Set nested level |
|||
$this->nestedLevel = $container->getNestedLevel(); |
|||
if ($this->parentContainer == 'Cell') { |
|||
$this->nestedLevel++; |
|||
} |
|||
|
|||
// Set phpword |
|||
$this->setPhpWord($container->getPhpWord()); |
|||
|
|||
// Set doc part |
|||
if (!$this instanceof Footnote) { |
|||
$this->setDocPart($container->getDocPart(), $container->getDocPartId()); |
|||
} |
|||
|
|||
$this->setMediaRelation(); |
|||
$this->setCollectionRelation(); |
|||
} |
|||
|
|||
/** |
|||
* Set relation Id for media elements (link, image, object; legacy of OOXML) |
|||
* |
|||
* - Image element needs to be passed to Media object |
|||
* - Icon needs to be set for Object element |
|||
*/ |
|||
private function setMediaRelation() |
|||
{ |
|||
if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) { |
|||
return; |
|||
} |
|||
|
|||
$elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); |
|||
if ($elementName == 'OLEObject') { |
|||
$elementName = 'Object'; |
|||
} |
|||
$mediaPart = $this->getMediaPart(); |
|||
$source = $this->getSource(); |
|||
$image = null; |
|||
if ($this instanceof Image) { |
|||
$image = $this; |
|||
} |
|||
$rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image); |
|||
$this->setRelationId($rId); |
|||
|
|||
if ($this instanceof OLEObject) { |
|||
$icon = $this->getIcon(); |
|||
$rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon)); |
|||
$this->setImageRelationId($rId); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Set relation Id for elements that will be registered in the Collection subnamespaces. |
|||
*/ |
|||
private function setCollectionRelation() |
|||
{ |
|||
if ($this->collectionRelation === true && $this->phpWord instanceof PhpWord) { |
|||
$elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); |
|||
$addMethod = "add{$elementName}"; |
|||
$rId = $this->phpWord->$addMethod($this); |
|||
$this->setRelationId($rId); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Check if element is located in Section doc part (as opposed to Header/Footer) |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isInSection() |
|||
{ |
|||
return $this->docPart == 'Section'; |
|||
} |
|||
|
|||
/** |
|||
* Set new style value |
|||
* |
|||
* @param mixed $styleObject Style object |
|||
* @param mixed $styleValue Style value |
|||
* @param bool $returnObject Always return object |
|||
* @return mixed |
|||
*/ |
|||
protected function setNewStyle($styleObject, $styleValue = null, $returnObject = false) |
|||
{ |
|||
if (!is_null($styleValue) && is_array($styleValue)) { |
|||
$styleObject->setStyleByArray($styleValue); |
|||
$style = $styleObject; |
|||
} else { |
|||
$style = $returnObject ? $styleObject : $styleValue; |
|||
} |
|||
|
|||
return $style; |
|||
} |
|||
|
|||
/** |
|||
* Sets the trackChange information |
|||
* |
|||
* @param TrackChange $trackChange |
|||
*/ |
|||
public function setTrackChange(TrackChange $trackChange) |
|||
{ |
|||
$this->trackChange = $trackChange; |
|||
} |
|||
|
|||
/** |
|||
* Gets the trackChange information |
|||
* |
|||
* @return TrackChange |
|||
*/ |
|||
public function getTrackChange() |
|||
{ |
|||
return $this->trackChange; |
|||
} |
|||
|
|||
/** |
|||
* Set changed |
|||
* |
|||
* @param string $type INSERTED|DELETED |
|||
* @param string $author |
|||
* @param null|int|\DateTime $date allways in UTC |
|||
*/ |
|||
public function setChangeInfo($type, $author, $date = null) |
|||
{ |
|||
$this->trackChange = new TrackChange($type, $author, $date); |
|||
} |
|||
|
|||
/** |
|||
* Set enum value |
|||
* |
|||
* @param string|null $value |
|||
* @param string[] $enum |
|||
* @param string|null $default |
|||
* |
|||
* @throws \InvalidArgumentException |
|||
* @return string|null |
|||
* |
|||
* @todo Merge with the same method in AbstractStyle |
|||
*/ |
|||
protected function setEnumVal($value = null, $enum = array(), $default = null) |
|||
{ |
|||
if ($value !== null && trim($value) != '' && !empty($enum) && !in_array($value, $enum)) { |
|||
throw new \InvalidArgumentException("Invalid style value: {$value}"); |
|||
} elseif ($value === null || trim($value) == '') { |
|||
$value = $default; |
|||
} |
|||
|
|||
return $value; |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
|
|||
/** |
|||
* Bookmark element |
|||
*/ |
|||
class Bookmark extends AbstractElement |
|||
{ |
|||
/** |
|||
* Bookmark Name |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $name; |
|||
|
|||
/** |
|||
* Is part of collection |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = true; |
|||
|
|||
/** |
|||
* Create a new Bookmark Element |
|||
* |
|||
* @param string $name |
|||
*/ |
|||
public function __construct($name = '') |
|||
{ |
|||
$this->name = SharedText::toUTF8($name); |
|||
} |
|||
|
|||
/** |
|||
* Get Bookmark name |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getName() |
|||
{ |
|||
return $this->name; |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Cell as CellStyle; |
|||
|
|||
/** |
|||
* Table cell element |
|||
*/ |
|||
class Cell extends AbstractContainer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Cell'; |
|||
|
|||
/** |
|||
* Cell width |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $width = null; |
|||
|
|||
/** |
|||
* Cell style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Cell |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param int $width |
|||
* @param array|\PhpOffice\PhpWord\Style\Cell $style |
|||
*/ |
|||
public function __construct($width = null, $style = null) |
|||
{ |
|||
$this->width = $width; |
|||
$this->style = $this->setNewStyle(new CellStyle(), $style, true); |
|||
} |
|||
|
|||
/** |
|||
* Get cell style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Cell |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get cell width |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getWidth() |
|||
{ |
|||
return $this->width; |
|||
} |
|||
} |
|||
@ -0,0 +1,129 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Chart as ChartStyle; |
|||
|
|||
/** |
|||
* Chart element |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class Chart extends AbstractElement |
|||
{ |
|||
/** |
|||
* Is part of collection |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = true; |
|||
|
|||
/** |
|||
* Type |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $type = 'pie'; |
|||
|
|||
/** |
|||
* Series |
|||
* |
|||
* @var array |
|||
*/ |
|||
private $series = array(); |
|||
|
|||
/** |
|||
* Chart style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Chart |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string $type |
|||
* @param array $categories |
|||
* @param array $values |
|||
* @param array $style |
|||
* @param null|mixed $seriesName |
|||
*/ |
|||
public function __construct($type, $categories, $values, $style = null, $seriesName = null) |
|||
{ |
|||
$this->setType($type); |
|||
$this->addSeries($categories, $values, $seriesName); |
|||
$this->style = $this->setNewStyle(new ChartStyle(), $style, true); |
|||
} |
|||
|
|||
/** |
|||
* Get type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Set type. |
|||
* |
|||
* @param string $value |
|||
*/ |
|||
public function setType($value) |
|||
{ |
|||
$enum = array('pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter'); |
|||
$this->type = $this->setEnumVal($value, $enum, 'pie'); |
|||
} |
|||
|
|||
/** |
|||
* Add series |
|||
* |
|||
* @param array $categories |
|||
* @param array $values |
|||
* @param null|mixed $name |
|||
*/ |
|||
public function addSeries($categories, $values, $name = null) |
|||
{ |
|||
$this->series[] = array( |
|||
'categories' => $categories, |
|||
'values' => $values, |
|||
'name' => $name, |
|||
); |
|||
} |
|||
|
|||
/** |
|||
* Get series |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getSeries() |
|||
{ |
|||
return $this->series; |
|||
} |
|||
|
|||
/** |
|||
* Get chart style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Chart |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
|
|||
/** |
|||
* Check box element |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
class CheckBox extends Text |
|||
{ |
|||
/** |
|||
* Name content |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $name; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string $name |
|||
* @param string $text |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($name = null, $text = null, $fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
$this->setName($name); |
|||
parent::__construct($text, $fontStyle, $paragraphStyle); |
|||
} |
|||
|
|||
/** |
|||
* Set name content |
|||
* |
|||
* @param string $name |
|||
* @return self |
|||
*/ |
|||
public function setName($name) |
|||
{ |
|||
$this->name = SharedText::toUTF8($name); |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get name content |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getName() |
|||
{ |
|||
return $this->name; |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Comment element |
|||
* @see http://datypic.com/sc/ooxml/t-w_CT_Comment.html |
|||
*/ |
|||
class Comment extends TrackChange |
|||
{ |
|||
/** |
|||
* Initials |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $initials; |
|||
|
|||
/** |
|||
* The Element where this comment starts |
|||
* |
|||
* @var AbstractElement |
|||
*/ |
|||
private $startElement; |
|||
|
|||
/** |
|||
* The Element where this comment ends |
|||
* |
|||
* @var AbstractElement |
|||
*/ |
|||
private $endElement; |
|||
|
|||
/** |
|||
* Is part of collection |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = true; |
|||
|
|||
/** |
|||
* Create a new Comment Element |
|||
* |
|||
* @param string $author |
|||
* @param null|\DateTime $date |
|||
* @param string $initials |
|||
*/ |
|||
public function __construct($author, $date = null, $initials = null) |
|||
{ |
|||
parent::__construct(null, $author, $date); |
|||
$this->initials = $initials; |
|||
} |
|||
|
|||
/** |
|||
* Get Initials |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getInitials() |
|||
{ |
|||
return $this->initials; |
|||
} |
|||
|
|||
/** |
|||
* Sets the element where this comment starts |
|||
* |
|||
* @param \PhpOffice\PhpWord\Element\AbstractElement $value |
|||
*/ |
|||
public function setStartElement(AbstractElement $value) |
|||
{ |
|||
$this->startElement = $value; |
|||
if ($value->getCommentRangeStart() == null) { |
|||
$value->setCommentRangeStart($this); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get the element where this comment starts |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement |
|||
*/ |
|||
public function getStartElement() |
|||
{ |
|||
return $this->startElement; |
|||
} |
|||
|
|||
/** |
|||
* Sets the element where this comment ends |
|||
* |
|||
* @param \PhpOffice\PhpWord\Element\AbstractElement $value |
|||
*/ |
|||
public function setEndElement(AbstractElement $value) |
|||
{ |
|||
$this->endElement = $value; |
|||
if ($value->getCommentRangeEnd() == null) { |
|||
$value->setCommentRangeEnd($this); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get the element where this comment ends |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\AbstractElement |
|||
*/ |
|||
public function getEndElement() |
|||
{ |
|||
return $this->endElement; |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Endnote element |
|||
* |
|||
* @since 0.10.0 |
|||
*/ |
|||
class Endnote extends Footnote |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Endnote'; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle |
|||
*/ |
|||
public function __construct($paragraphStyle = null) |
|||
{ |
|||
parent::__construct($paragraphStyle); |
|||
} |
|||
} |
|||
@ -0,0 +1,299 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Font; |
|||
|
|||
/** |
|||
* Field element |
|||
* |
|||
* @since 0.11.0 |
|||
* @see http://www.schemacentral.com/sc/ooxml/t-w_CT_SimpleField.html |
|||
*/ |
|||
class Field extends AbstractElement |
|||
{ |
|||
/** |
|||
* Field properties and options. Depending on type, a field can have different properties |
|||
* and options |
|||
* |
|||
* @var array |
|||
*/ |
|||
protected $fieldsArray = array( |
|||
'PAGE' => array( |
|||
'properties' => array( |
|||
'format' => array('Arabic', 'ArabicDash', 'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN'), |
|||
), |
|||
'options' => array('PreserveFormat'), |
|||
), |
|||
'NUMPAGES' => array( |
|||
'properties' => array( |
|||
'format' => array('Arabic', 'ArabicDash', 'CardText', 'DollarText', 'Ordinal', 'OrdText', |
|||
'alphabetic', 'ALPHABETIC', 'roman', 'ROMAN', 'Caps', 'FirstCap', 'Lower', 'Upper', ), |
|||
'numformat' => array('0', '0,00', '#.##0', '#.##0,00', '€ #.##0,00(€ #.##0,00)', '0%', '0,00%'), |
|||
), |
|||
'options' => array('PreserveFormat'), |
|||
), |
|||
'DATE' => array( |
|||
'properties' => array( |
|||
'dateformat' => array( |
|||
/* Generic formats */ |
|||
'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss', |
|||
/* Day-Month-Year formats */ |
|||
'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy', |
|||
'd-M-yy', 'd-M-yy h:mm', 'd-M-yy h:mm:ss', 'd-M-yy h:mm am/pm', 'd-M-yy h:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss', |
|||
'd/M/yy', 'd/M/yy h:mm', 'd/M/yy h:mm:ss', 'd/M/yy h:mm am/pm', 'd/M/yy h:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss', |
|||
'd-M-yyyy', 'd-M-yyyy h:mm', 'd-M-yyyy h:mm:ss', 'd-M-yyyy h:mm am/pm', 'd-M-yyyy h:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss', |
|||
'd/M/yyyy', 'd/M/yyyy h:mm', 'd/M/yyyy h:mm:ss', 'd/M/yyyy h:mm am/pm', 'd/M/yyyy h:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss', |
|||
/* Month-Day-Year formats */ |
|||
'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy', |
|||
'M-d-yy', 'M-d-yy h:mm', 'M-d-yy h:mm:ss', 'M-d-yy h:mm am/pm', 'M-d-yy h:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss', |
|||
'M/d/yy', 'M/d/yy h:mm', 'M/d/yy h:mm:ss', 'M/d/yy h:mm am/pm', 'M/d/yy h:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss', |
|||
'M-d-yyyy', 'M-d-yyyy h:mm', 'M-d-yyyy h:mm:ss', 'M-d-yyyy h:mm am/pm', 'M-d-yyyy h:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss', |
|||
'M/d/yyyy', 'M/d/yyyy h:mm', 'M/d/yyyy h:mm:ss', 'M/d/yyyy h:mm am/pm', 'M/d/yyyy h:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss', |
|||
), |
|||
), |
|||
'options' => array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'), |
|||
), |
|||
'MACROBUTTON' => array( |
|||
'properties' => array('macroname' => ''), |
|||
), |
|||
'XE' => array( |
|||
'properties' => array(), |
|||
'options' => array('Bold', 'Italic'), |
|||
), |
|||
'INDEX' => array( |
|||
'properties' => array(), |
|||
'options' => array('PreserveFormat'), |
|||
), |
|||
'STYLEREF' => array( |
|||
'properties' => array('StyleIdentifier' => ''), |
|||
'options' => array('PreserveFormat'), |
|||
), |
|||
); |
|||
|
|||
/** |
|||
* Field type |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $type; |
|||
|
|||
/** |
|||
* Field text |
|||
* |
|||
* @var TextRun|string |
|||
*/ |
|||
protected $text; |
|||
|
|||
/** |
|||
* Field properties |
|||
* |
|||
* @var array |
|||
*/ |
|||
protected $properties = array(); |
|||
|
|||
/** |
|||
* Field options |
|||
* |
|||
* @var array |
|||
*/ |
|||
protected $options = array(); |
|||
|
|||
/** |
|||
* Font style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
protected $fontStyle; |
|||
|
|||
/** |
|||
* Set Font style |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Font $style |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function setFontStyle($style = null) |
|||
{ |
|||
if ($style instanceof Font) { |
|||
$this->fontStyle = $style; |
|||
} elseif (is_array($style)) { |
|||
$this->fontStyle = new Font('text'); |
|||
$this->fontStyle->setStyleByArray($style); |
|||
} elseif (null === $style) { |
|||
$this->fontStyle = null; |
|||
} else { |
|||
$this->fontStyle = $style; |
|||
} |
|||
|
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Font style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function getFontStyle() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Create a new Field Element |
|||
* |
|||
* @param string $type |
|||
* @param array $properties |
|||
* @param array $options |
|||
* @param TextRun|string|null $text |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Font $fontStyle |
|||
*/ |
|||
public function __construct($type = null, $properties = array(), $options = array(), $text = null, $fontStyle = null) |
|||
{ |
|||
$this->setType($type); |
|||
$this->setProperties($properties); |
|||
$this->setOptions($options); |
|||
$this->setText($text); |
|||
$this->setFontStyle($fontStyle); |
|||
} |
|||
|
|||
/** |
|||
* Set Field type |
|||
* |
|||
* @param string $type |
|||
* |
|||
* @throws \InvalidArgumentException |
|||
* @return string |
|||
*/ |
|||
public function setType($type = null) |
|||
{ |
|||
if (isset($type)) { |
|||
if (isset($this->fieldsArray[$type])) { |
|||
$this->type = $type; |
|||
} else { |
|||
throw new \InvalidArgumentException("Invalid type '$type'"); |
|||
} |
|||
} |
|||
|
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Get Field type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Set Field properties |
|||
* |
|||
* @param array $properties |
|||
* |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setProperties($properties = array()) |
|||
{ |
|||
if (is_array($properties)) { |
|||
foreach (array_keys($properties) as $propkey) { |
|||
if (!(isset($this->fieldsArray[$this->type]['properties'][$propkey]))) { |
|||
throw new \InvalidArgumentException("Invalid property '$propkey'"); |
|||
} |
|||
} |
|||
$this->properties = array_merge($this->properties, $properties); |
|||
} |
|||
|
|||
return $this->properties; |
|||
} |
|||
|
|||
/** |
|||
* Get Field properties |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getProperties() |
|||
{ |
|||
return $this->properties; |
|||
} |
|||
|
|||
/** |
|||
* Set Field options |
|||
* |
|||
* @param array $options |
|||
* |
|||
* @throws \InvalidArgumentException |
|||
* @return self |
|||
*/ |
|||
public function setOptions($options = array()) |
|||
{ |
|||
if (is_array($options)) { |
|||
foreach (array_keys($options) as $optionkey) { |
|||
if (!(isset($this->fieldsArray[$this->type]['options'][$optionkey])) && substr($optionkey, 0, 1) !== '\\') { |
|||
throw new \InvalidArgumentException("Invalid option '$optionkey', possible values are " . implode(', ', $this->fieldsArray[$this->type]['options'])); |
|||
} |
|||
} |
|||
$this->options = array_merge($this->options, $options); |
|||
} |
|||
|
|||
return $this->options; |
|||
} |
|||
|
|||
/** |
|||
* Get Field properties |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getOptions() |
|||
{ |
|||
return $this->options; |
|||
} |
|||
|
|||
/** |
|||
* Set Field text |
|||
* |
|||
* @param string|TextRun $text |
|||
* |
|||
* @throws \InvalidArgumentException |
|||
* @return null|string|TextRun |
|||
*/ |
|||
public function setText($text = null) |
|||
{ |
|||
if (isset($text)) { |
|||
if (is_string($text) || $text instanceof TextRun) { |
|||
$this->text = $text; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid text'); |
|||
} |
|||
} |
|||
|
|||
return $this->text; |
|||
} |
|||
|
|||
/** |
|||
* Get Field text |
|||
* |
|||
* @return string|TextRun |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->text; |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Footer element |
|||
*/ |
|||
class Footer extends AbstractContainer |
|||
{ |
|||
/** |
|||
* Header/footer types constants |
|||
* |
|||
* @var string |
|||
* @see http://www.datypic.com/sc/ooxml/t-w_ST_HdrFtr.html Header or Footer Type |
|||
*/ |
|||
const AUTO = 'default'; // default and odd pages |
|||
const FIRST = 'first'; |
|||
const EVEN = 'even'; |
|||
|
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Footer'; |
|||
|
|||
/** |
|||
* Header type |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $type = self::AUTO; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param int $sectionId |
|||
* @param int $containerId |
|||
* @param string $type |
|||
*/ |
|||
public function __construct($sectionId, $containerId = 1, $type = self::AUTO) |
|||
{ |
|||
$this->sectionId = $sectionId; |
|||
$this->setType($type); |
|||
$this->setDocPart($this->container, ($sectionId - 1) * 3 + $containerId); |
|||
} |
|||
|
|||
/** |
|||
* Set type. |
|||
* |
|||
* @since 0.10.0 |
|||
* |
|||
* @param string $value |
|||
*/ |
|||
public function setType($value = self::AUTO) |
|||
{ |
|||
if (!in_array($value, array(self::AUTO, self::FIRST, self::EVEN))) { |
|||
$value = self::AUTO; |
|||
} |
|||
$this->type = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get type |
|||
* |
|||
* @return string |
|||
* @since 0.10.0 |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Reset type to default |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function resetType() |
|||
{ |
|||
return $this->type = self::AUTO; |
|||
} |
|||
|
|||
/** |
|||
* First page only header |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function firstPage() |
|||
{ |
|||
return $this->type = self::FIRST; |
|||
} |
|||
|
|||
/** |
|||
* Even numbered pages only |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function evenPage() |
|||
{ |
|||
return $this->type = self::EVEN; |
|||
} |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
class Footnote extends AbstractContainer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Footnote'; |
|||
|
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
protected $paragraphStyle; |
|||
|
|||
/** |
|||
* Is part of collection |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = true; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle |
|||
*/ |
|||
public function __construct($paragraphStyle = null) |
|||
{ |
|||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); |
|||
$this->setDocPart($this->container); |
|||
} |
|||
|
|||
/** |
|||
* Get paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Footnote Reference ID |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* @codeCoverageIgnore |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getReferenceId() |
|||
{ |
|||
return $this->getRelationId(); |
|||
} |
|||
|
|||
/** |
|||
* Set Footnote Reference ID |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* @codeCoverageIgnore |
|||
* |
|||
* @param int $rId |
|||
*/ |
|||
public function setReferenceId($rId) |
|||
{ |
|||
$this->setRelationId($rId); |
|||
} |
|||
} |
|||
@ -0,0 +1,195 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Form field element |
|||
* |
|||
* @since 0.12.0 |
|||
* @see http://www.datypic.com/sc/ooxml/t-w_CT_FFData.html |
|||
*/ |
|||
class FormField extends Text |
|||
{ |
|||
/** |
|||
* Form field type: textinput|checkbox|dropdown |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $type = 'textinput'; |
|||
|
|||
/** |
|||
* Form field name |
|||
* |
|||
* @var string|bool|int |
|||
*/ |
|||
private $name; |
|||
|
|||
/** |
|||
* Default value |
|||
* |
|||
* - TextInput: string |
|||
* - CheckBox: bool |
|||
* - DropDown: int Index of entries (zero based) |
|||
* |
|||
* @var string|bool|int |
|||
*/ |
|||
private $default; |
|||
|
|||
/** |
|||
* Value |
|||
* |
|||
* @var string|bool|int |
|||
*/ |
|||
private $value; |
|||
|
|||
/** |
|||
* Dropdown entries |
|||
* |
|||
* @var array |
|||
*/ |
|||
private $entries = array(); |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string $type |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($type, $fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
parent::__construct(null, $fontStyle, $paragraphStyle); |
|||
$this->setType($type); |
|||
} |
|||
|
|||
/** |
|||
* Get type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Set type |
|||
* |
|||
* @param string $value |
|||
* @return self |
|||
*/ |
|||
public function setType($value) |
|||
{ |
|||
$enum = array('textinput', 'checkbox', 'dropdown'); |
|||
$this->type = $this->setEnumVal($value, $enum, $this->type); |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get name |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getName() |
|||
{ |
|||
return $this->name; |
|||
} |
|||
|
|||
/** |
|||
* Set name |
|||
* |
|||
* @param string|bool|int $value |
|||
* @return self |
|||
*/ |
|||
public function setName($value) |
|||
{ |
|||
$this->name = $value; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get default |
|||
* |
|||
* @return string|bool|int |
|||
*/ |
|||
public function getDefault() |
|||
{ |
|||
return $this->default; |
|||
} |
|||
|
|||
/** |
|||
* Set default |
|||
* |
|||
* @param string|bool|int $value |
|||
* @return self |
|||
*/ |
|||
public function setDefault($value) |
|||
{ |
|||
$this->default = $value; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get value |
|||
* |
|||
* @return string|bool|int |
|||
*/ |
|||
public function getValue() |
|||
{ |
|||
return $this->value; |
|||
} |
|||
|
|||
/** |
|||
* Set value |
|||
* |
|||
* @param string|bool|int $value |
|||
* @return self |
|||
*/ |
|||
public function setValue($value) |
|||
{ |
|||
$this->value = $value; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get entries |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getEntries() |
|||
{ |
|||
return $this->entries; |
|||
} |
|||
|
|||
/** |
|||
* Set entries |
|||
* |
|||
* @param array $value |
|||
* @return self |
|||
*/ |
|||
public function setEntries($value) |
|||
{ |
|||
$this->entries = $value; |
|||
|
|||
return $this; |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Header element |
|||
*/ |
|||
class Header extends Footer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Header'; |
|||
|
|||
/** |
|||
* Add a Watermark Element |
|||
* |
|||
* @param string $src |
|||
* @param mixed $style |
|||
* @return Image |
|||
*/ |
|||
public function addWatermark($src, $style = null) |
|||
{ |
|||
return $this->addImage($src, $style, true); |
|||
} |
|||
} |
|||
@ -0,0 +1,602 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Exception\CreateTemporaryFileException; |
|||
use PhpOffice\PhpWord\Exception\InvalidImageException; |
|||
use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException; |
|||
use PhpOffice\PhpWord\Settings; |
|||
use PhpOffice\PhpWord\Shared\ZipArchive; |
|||
use PhpOffice\PhpWord\Style\Image as ImageStyle; |
|||
|
|||
/** |
|||
* Image element |
|||
*/ |
|||
class Image extends AbstractElement |
|||
{ |
|||
/** |
|||
* Image source type constants |
|||
*/ |
|||
const SOURCE_LOCAL = 'local'; // Local images |
|||
const SOURCE_GD = 'gd'; // Generated using GD |
|||
const SOURCE_ARCHIVE = 'archive'; // Image in archives zip://$archive#$image |
|||
const SOURCE_STRING = 'string'; // Image from string |
|||
|
|||
/** |
|||
* Image source |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $source; |
|||
|
|||
/** |
|||
* Source type: local|gd|archive |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $sourceType; |
|||
|
|||
/** |
|||
* Image style |
|||
* |
|||
* @var ImageStyle |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Is watermark |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $watermark; |
|||
|
|||
/** |
|||
* Name of image |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $name; |
|||
|
|||
/** |
|||
* Image type |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $imageType; |
|||
|
|||
/** |
|||
* Image create function |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $imageCreateFunc; |
|||
|
|||
/** |
|||
* Image function |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $imageFunc; |
|||
|
|||
/** |
|||
* Image extension |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $imageExtension; |
|||
|
|||
/** |
|||
* Is memory image |
|||
* |
|||
* @var bool |
|||
*/ |
|||
private $memoryImage; |
|||
|
|||
/** |
|||
* Image target file name |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $target; |
|||
|
|||
/** |
|||
* Image media index |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $mediaIndex; |
|||
|
|||
/** |
|||
* Has media relation flag; true for Link, Image, and Object |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $mediaRelation = true; |
|||
|
|||
/** |
|||
* Create new image element |
|||
* |
|||
* @param string $source |
|||
* @param mixed $style |
|||
* @param bool $watermark |
|||
* @param string $name |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\InvalidImageException |
|||
* @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException |
|||
*/ |
|||
public function __construct($source, $style = null, $watermark = false, $name = null) |
|||
{ |
|||
$this->source = $source; |
|||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true); |
|||
$this->setIsWatermark($watermark); |
|||
$this->setName($name); |
|||
|
|||
$this->checkImage(); |
|||
} |
|||
|
|||
/** |
|||
* Get Image style |
|||
* |
|||
* @return ImageStyle |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get image source |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getSource() |
|||
{ |
|||
return $this->source; |
|||
} |
|||
|
|||
/** |
|||
* Get image source type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getSourceType() |
|||
{ |
|||
return $this->sourceType; |
|||
} |
|||
|
|||
/** |
|||
* Sets the image name |
|||
* |
|||
* @param string $value |
|||
*/ |
|||
public function setName($value) |
|||
{ |
|||
$this->name = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get image name |
|||
* |
|||
* @return null|string |
|||
*/ |
|||
public function getName() |
|||
{ |
|||
return $this->name; |
|||
} |
|||
|
|||
/** |
|||
* Get image media ID |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getMediaId() |
|||
{ |
|||
return md5($this->source); |
|||
} |
|||
|
|||
/** |
|||
* Get is watermark |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isWatermark() |
|||
{ |
|||
return $this->watermark; |
|||
} |
|||
|
|||
/** |
|||
* Set is watermark |
|||
* |
|||
* @param bool $value |
|||
*/ |
|||
public function setIsWatermark($value) |
|||
{ |
|||
$this->watermark = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get image type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getImageType() |
|||
{ |
|||
return $this->imageType; |
|||
} |
|||
|
|||
/** |
|||
* Get image create function |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getImageCreateFunction() |
|||
{ |
|||
return $this->imageCreateFunc; |
|||
} |
|||
|
|||
/** |
|||
* Get image function |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getImageFunction() |
|||
{ |
|||
return $this->imageFunc; |
|||
} |
|||
|
|||
/** |
|||
* Get image extension |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getImageExtension() |
|||
{ |
|||
return $this->imageExtension; |
|||
} |
|||
|
|||
/** |
|||
* Get is memory image |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isMemImage() |
|||
{ |
|||
return $this->memoryImage; |
|||
} |
|||
|
|||
/** |
|||
* Get target file name |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getTarget() |
|||
{ |
|||
return $this->target; |
|||
} |
|||
|
|||
/** |
|||
* Set target file name. |
|||
* |
|||
* @param string $value |
|||
*/ |
|||
public function setTarget($value) |
|||
{ |
|||
$this->target = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get media index |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getMediaIndex() |
|||
{ |
|||
return $this->mediaIndex; |
|||
} |
|||
|
|||
/** |
|||
* Set media index. |
|||
* |
|||
* @param int $value |
|||
*/ |
|||
public function setMediaIndex($value) |
|||
{ |
|||
$this->mediaIndex = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get image string data |
|||
* |
|||
* @param bool $base64 |
|||
* @return string|null |
|||
* @since 0.11.0 |
|||
*/ |
|||
public function getImageStringData($base64 = false) |
|||
{ |
|||
$source = $this->source; |
|||
$actualSource = null; |
|||
$imageBinary = null; |
|||
$imageData = null; |
|||
$isTemp = false; |
|||
|
|||
// Get actual source from archive image or other source |
|||
// Return null if not found |
|||
if ($this->sourceType == self::SOURCE_ARCHIVE) { |
|||
$source = substr($source, 6); |
|||
list($zipFilename, $imageFilename) = explode('#', $source); |
|||
|
|||
$zip = new ZipArchive(); |
|||
if ($zip->open($zipFilename) !== false) { |
|||
if ($zip->locateName($imageFilename) !== false) { |
|||
$isTemp = true; |
|||
$zip->extractTo(Settings::getTempDir(), $imageFilename); |
|||
$actualSource = Settings::getTempDir() . DIRECTORY_SEPARATOR . $imageFilename; |
|||
} |
|||
} |
|||
$zip->close(); |
|||
} else { |
|||
$actualSource = $source; |
|||
} |
|||
|
|||
// Can't find any case where $actualSource = null hasn't captured by |
|||
// preceding exceptions. Please uncomment when you find the case and |
|||
// put the case into Element\ImageTest. |
|||
// if ($actualSource === null) { |
|||
// return null; |
|||
// } |
|||
|
|||
// Read image binary data and convert to hex/base64 string |
|||
if ($this->sourceType == self::SOURCE_GD) { |
|||
$imageResource = call_user_func($this->imageCreateFunc, $actualSource); |
|||
if ($this->imageType === 'image/png') { |
|||
// PNG images need to preserve alpha channel information |
|||
imagesavealpha($imageResource, true); |
|||
} |
|||
ob_start(); |
|||
call_user_func($this->imageFunc, $imageResource); |
|||
$imageBinary = ob_get_contents(); |
|||
ob_end_clean(); |
|||
} elseif ($this->sourceType == self::SOURCE_STRING) { |
|||
$imageBinary = $this->source; |
|||
} else { |
|||
$fileHandle = fopen($actualSource, 'rb', false); |
|||
if ($fileHandle !== false) { |
|||
$imageBinary = fread($fileHandle, filesize($actualSource)); |
|||
fclose($fileHandle); |
|||
} |
|||
} |
|||
if ($imageBinary !== null) { |
|||
if ($base64) { |
|||
$imageData = chunk_split(base64_encode($imageBinary)); |
|||
} else { |
|||
$imageData = chunk_split(bin2hex($imageBinary)); |
|||
} |
|||
} |
|||
|
|||
// Delete temporary file if necessary |
|||
if ($isTemp === true) { |
|||
@unlink($actualSource); |
|||
} |
|||
|
|||
return $imageData; |
|||
} |
|||
|
|||
/** |
|||
* Check memory image, supported type, image functions, and proportional width/height. |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\InvalidImageException |
|||
* @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException |
|||
*/ |
|||
private function checkImage() |
|||
{ |
|||
$this->setSourceType(); |
|||
|
|||
// Check image data |
|||
if ($this->sourceType == self::SOURCE_ARCHIVE) { |
|||
$imageData = $this->getArchiveImageSize($this->source); |
|||
} elseif ($this->sourceType == self::SOURCE_STRING) { |
|||
$imageData = $this->getStringImageSize($this->source); |
|||
} else { |
|||
$imageData = @getimagesize($this->source); |
|||
} |
|||
if (!is_array($imageData)) { |
|||
throw new InvalidImageException(sprintf('Invalid image: %s', $this->source)); |
|||
} |
|||
list($actualWidth, $actualHeight, $imageType) = $imageData; |
|||
|
|||
// Check image type support |
|||
$supportedTypes = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG); |
|||
if ($this->sourceType != self::SOURCE_GD && $this->sourceType != self::SOURCE_STRING) { |
|||
$supportedTypes = array_merge($supportedTypes, array(IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM)); |
|||
} |
|||
if (!in_array($imageType, $supportedTypes)) { |
|||
throw new UnsupportedImageTypeException(); |
|||
} |
|||
|
|||
// Define image functions |
|||
$this->imageType = image_type_to_mime_type($imageType); |
|||
$this->setFunctions(); |
|||
$this->setProportionalSize($actualWidth, $actualHeight); |
|||
} |
|||
|
|||
/** |
|||
* Set source type. |
|||
*/ |
|||
private function setSourceType() |
|||
{ |
|||
if (stripos(strrev($this->source), strrev('.php')) === 0) { |
|||
$this->memoryImage = true; |
|||
$this->sourceType = self::SOURCE_GD; |
|||
} elseif (strpos($this->source, 'zip://') !== false) { |
|||
$this->memoryImage = false; |
|||
$this->sourceType = self::SOURCE_ARCHIVE; |
|||
} elseif (filter_var($this->source, FILTER_VALIDATE_URL) !== false) { |
|||
$this->memoryImage = true; |
|||
if (strpos($this->source, 'https') === 0) { |
|||
$fileContent = file_get_contents($this->source); |
|||
$this->source = $fileContent; |
|||
$this->sourceType = self::SOURCE_STRING; |
|||
} else { |
|||
$this->sourceType = self::SOURCE_GD; |
|||
} |
|||
} elseif ((strpos($this->source, chr(0)) === false) && @file_exists($this->source)) { |
|||
$this->memoryImage = false; |
|||
$this->sourceType = self::SOURCE_LOCAL; |
|||
} else { |
|||
$this->memoryImage = true; |
|||
$this->sourceType = self::SOURCE_STRING; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get image size from archive |
|||
* |
|||
* @since 0.12.0 Throws CreateTemporaryFileException. |
|||
* |
|||
* @param string $source |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\CreateTemporaryFileException |
|||
* |
|||
* @return array|null |
|||
*/ |
|||
private function getArchiveImageSize($source) |
|||
{ |
|||
$imageData = null; |
|||
$source = substr($source, 6); |
|||
list($zipFilename, $imageFilename) = explode('#', $source); |
|||
|
|||
$tempFilename = tempnam(Settings::getTempDir(), 'PHPWordImage'); |
|||
if (false === $tempFilename) { |
|||
throw new CreateTemporaryFileException(); // @codeCoverageIgnore |
|||
} |
|||
|
|||
$zip = new ZipArchive(); |
|||
if ($zip->open($zipFilename) !== false) { |
|||
if ($zip->locateName($imageFilename) !== false) { |
|||
$imageContent = $zip->getFromName($imageFilename); |
|||
if ($imageContent !== false) { |
|||
file_put_contents($tempFilename, $imageContent); |
|||
$imageData = getimagesize($tempFilename); |
|||
unlink($tempFilename); |
|||
} |
|||
} |
|||
$zip->close(); |
|||
} |
|||
|
|||
return $imageData; |
|||
} |
|||
|
|||
/** |
|||
* get image size from string |
|||
* |
|||
* @param string $source |
|||
* |
|||
* @codeCoverageIgnore this method is just a replacement for getimagesizefromstring which exists only as of PHP 5.4 |
|||
*/ |
|||
private function getStringImageSize($source) |
|||
{ |
|||
$result = false; |
|||
if (!function_exists('getimagesizefromstring')) { |
|||
$uri = 'data://application/octet-stream;base64,' . base64_encode($source); |
|||
$result = @getimagesize($uri); |
|||
} else { |
|||
$result = @getimagesizefromstring($source); |
|||
} |
|||
|
|||
return $result; |
|||
} |
|||
|
|||
/** |
|||
* Set image functions and extensions. |
|||
*/ |
|||
private function setFunctions() |
|||
{ |
|||
switch ($this->imageType) { |
|||
case 'image/png': |
|||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefrompng'; |
|||
$this->imageFunc = 'imagepng'; |
|||
$this->imageExtension = 'png'; |
|||
break; |
|||
case 'image/gif': |
|||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromgif'; |
|||
$this->imageFunc = 'imagegif'; |
|||
$this->imageExtension = 'gif'; |
|||
break; |
|||
case 'image/jpeg': |
|||
case 'image/jpg': |
|||
$this->imageCreateFunc = $this->sourceType == self::SOURCE_STRING ? 'imagecreatefromstring' : 'imagecreatefromjpeg'; |
|||
$this->imageFunc = 'imagejpeg'; |
|||
$this->imageExtension = 'jpg'; |
|||
break; |
|||
case 'image/bmp': |
|||
case 'image/x-ms-bmp': |
|||
$this->imageType = 'image/bmp'; |
|||
$this->imageExtension = 'bmp'; |
|||
break; |
|||
case 'image/tiff': |
|||
$this->imageExtension = 'tif'; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Set proportional width/height if one dimension not available. |
|||
* |
|||
* @param int $actualWidth |
|||
* @param int $actualHeight |
|||
*/ |
|||
private function setProportionalSize($actualWidth, $actualHeight) |
|||
{ |
|||
$styleWidth = $this->style->getWidth(); |
|||
$styleHeight = $this->style->getHeight(); |
|||
if (!($styleWidth && $styleHeight)) { |
|||
if ($styleWidth == null && $styleHeight == null) { |
|||
$this->style->setWidth($actualWidth); |
|||
$this->style->setHeight($actualHeight); |
|||
} elseif ($styleWidth) { |
|||
$this->style->setHeight($actualHeight * ($styleWidth / $actualWidth)); |
|||
} else { |
|||
$this->style->setWidth($actualWidth * ($styleHeight / $actualHeight)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get is watermark |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getIsWatermark() |
|||
{ |
|||
return $this->isWatermark(); |
|||
} |
|||
|
|||
/** |
|||
* Get is memory image |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getIsMemImage() |
|||
{ |
|||
return $this->isMemImage(); |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Line as LineStyle; |
|||
|
|||
/** |
|||
* Line element |
|||
*/ |
|||
class Line extends AbstractElement |
|||
{ |
|||
/** |
|||
* Line style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Line |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Create new line element |
|||
* |
|||
* @param mixed $style |
|||
*/ |
|||
public function __construct($style = null) |
|||
{ |
|||
$this->style = $this->setNewStyle(new LineStyle(), $style); |
|||
} |
|||
|
|||
/** |
|||
* Get line style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Line |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
use PhpOffice\PhpWord\Style\Font; |
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
/** |
|||
* Link element |
|||
*/ |
|||
class Link extends AbstractElement |
|||
{ |
|||
/** |
|||
* Link source |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $source; |
|||
|
|||
/** |
|||
* Link text |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $text; |
|||
|
|||
/** |
|||
* Font style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
private $fontStyle; |
|||
|
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
private $paragraphStyle; |
|||
|
|||
/** |
|||
* Has media relation flag; true for Link, Image, and Object |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $mediaRelation = true; |
|||
|
|||
/** |
|||
* Has internal flag - anchor to internal bookmark |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $internal = false; |
|||
|
|||
/** |
|||
* Create a new Link Element |
|||
* |
|||
* @param string $source |
|||
* @param string $text |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
* @param bool $internal |
|||
*/ |
|||
public function __construct($source, $text = null, $fontStyle = null, $paragraphStyle = null, $internal = false) |
|||
{ |
|||
$this->source = SharedText::toUTF8($source); |
|||
$this->text = is_null($text) ? $this->source : SharedText::toUTF8($text); |
|||
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); |
|||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); |
|||
$this->internal = $internal; |
|||
} |
|||
|
|||
/** |
|||
* Get link source |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getSource() |
|||
{ |
|||
return $this->source; |
|||
} |
|||
|
|||
/** |
|||
* Get link text |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->text; |
|||
} |
|||
|
|||
/** |
|||
* Get Text style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function getFontStyle() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get link target |
|||
* |
|||
* @deprecated 0.12.0 |
|||
* |
|||
* @return string |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getTarget() |
|||
{ |
|||
return $this->source; |
|||
} |
|||
|
|||
/** |
|||
* Get Link source |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return string |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getLinkSrc() |
|||
{ |
|||
return $this->getSource(); |
|||
} |
|||
|
|||
/** |
|||
* Get Link name |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return string |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getLinkName() |
|||
{ |
|||
return $this->getText(); |
|||
} |
|||
|
|||
/** |
|||
* is internal |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function isInternal() |
|||
{ |
|||
return $this->internal; |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle; |
|||
|
|||
/** |
|||
* List item element |
|||
*/ |
|||
class ListItem extends AbstractElement |
|||
{ |
|||
/** |
|||
* Element style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\ListItem |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Text object |
|||
* |
|||
* @var \PhpOffice\PhpWord\Element\Text |
|||
*/ |
|||
private $textObject; |
|||
|
|||
/** |
|||
* Depth |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $depth; |
|||
|
|||
/** |
|||
* Create a new ListItem |
|||
* |
|||
* @param string $text |
|||
* @param int $depth |
|||
* @param mixed $fontStyle |
|||
* @param array|string|null $listStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = null, $paragraphStyle = null) |
|||
{ |
|||
$this->textObject = new Text(SharedText::toUTF8($text), $fontStyle, $paragraphStyle); |
|||
$this->depth = $depth; |
|||
|
|||
// Version >= 0.10.0 will pass numbering style name. Older version will use old method |
|||
if (!is_null($listStyle) && is_string($listStyle)) { |
|||
$this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore |
|||
} else { |
|||
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\ListItem |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get Text object |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\Text |
|||
*/ |
|||
public function getTextObject() |
|||
{ |
|||
return $this->textObject; |
|||
} |
|||
|
|||
/** |
|||
* Get depth |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getDepth() |
|||
{ |
|||
return $this->depth; |
|||
} |
|||
|
|||
/** |
|||
* Get text |
|||
* |
|||
* @return string |
|||
* @since 0.11.0 |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->textObject->getText(); |
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\ListItem as ListItemStyle; |
|||
|
|||
/** |
|||
* List item element |
|||
*/ |
|||
class ListItemRun extends TextRun |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'ListItemRun'; |
|||
|
|||
/** |
|||
* ListItem Style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\ListItem |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* ListItem Depth |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $depth; |
|||
|
|||
/** |
|||
* Create a new ListItem |
|||
* |
|||
* @param int $depth |
|||
* @param array|string|null $listStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($depth = 0, $listStyle = null, $paragraphStyle = null) |
|||
{ |
|||
$this->depth = $depth; |
|||
|
|||
// Version >= 0.10.0 will pass numbering style name. Older version will use old method |
|||
if (!is_null($listStyle) && is_string($listStyle)) { |
|||
$this->style = new ListItemStyle($listStyle); |
|||
} else { |
|||
$this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); |
|||
} |
|||
parent::__construct($paragraphStyle); |
|||
} |
|||
|
|||
/** |
|||
* Get ListItem style. |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\ListItem |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get ListItem depth. |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getDepth() |
|||
{ |
|||
return $this->depth; |
|||
} |
|||
} |
|||
@ -0,0 +1,169 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Exception\InvalidObjectException; |
|||
use PhpOffice\PhpWord\Style\Image as ImageStyle; |
|||
|
|||
/** |
|||
* OLEObject element |
|||
*/ |
|||
class OLEObject extends AbstractElement |
|||
{ |
|||
/** |
|||
* Ole-Object Src |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $source; |
|||
|
|||
/** |
|||
* Image Style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Image |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Icon |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $icon; |
|||
|
|||
/** |
|||
* Image Relation ID |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $imageRelationId; |
|||
|
|||
/** |
|||
* Has media relation flag; true for Link, Image, and Object |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $mediaRelation = true; |
|||
|
|||
/** |
|||
* Create a new Ole-Object Element |
|||
* |
|||
* @param string $source |
|||
* @param mixed $style |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\InvalidObjectException |
|||
*/ |
|||
public function __construct($source, $style = null) |
|||
{ |
|||
$supportedTypes = array('xls', 'doc', 'ppt', 'xlsx', 'docx', 'pptx'); |
|||
$pathInfo = pathinfo($source); |
|||
|
|||
if (file_exists($source) && in_array($pathInfo['extension'], $supportedTypes)) { |
|||
$ext = $pathInfo['extension']; |
|||
if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') { |
|||
$ext = substr($ext, 0, -1); |
|||
} |
|||
|
|||
$this->source = $source; |
|||
$this->style = $this->setNewStyle(new ImageStyle(), $style, true); |
|||
$this->icon = realpath(__DIR__ . "/../resources/{$ext}.png"); |
|||
|
|||
return; |
|||
} |
|||
|
|||
throw new InvalidObjectException(); |
|||
} |
|||
|
|||
/** |
|||
* Get object source |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getSource() |
|||
{ |
|||
return $this->source; |
|||
} |
|||
|
|||
/** |
|||
* Get object style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Image |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get object icon |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getIcon() |
|||
{ |
|||
return $this->icon; |
|||
} |
|||
|
|||
/** |
|||
* Get image relation ID |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getImageRelationId() |
|||
{ |
|||
return $this->imageRelationId; |
|||
} |
|||
|
|||
/** |
|||
* Set Image Relation ID. |
|||
* |
|||
* @param int $rId |
|||
*/ |
|||
public function setImageRelationId($rId) |
|||
{ |
|||
$this->imageRelationId = $rId; |
|||
} |
|||
|
|||
/** |
|||
* Get Object ID |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return int |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getObjectId() |
|||
{ |
|||
return $this->relationId + 1325353440; |
|||
} |
|||
|
|||
/** |
|||
* Set Object ID |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @param int $objId |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function setObjectId($objId) |
|||
{ |
|||
$this->relationId = $objId; |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Page break element |
|||
*/ |
|||
class PageBreak extends AbstractElement |
|||
{ |
|||
/** |
|||
* Create new page break |
|||
*/ |
|||
public function __construct() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
use PhpOffice\PhpWord\Style\Font; |
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
/** |
|||
* Preserve text/field element |
|||
*/ |
|||
class PreserveText extends AbstractElement |
|||
{ |
|||
/** |
|||
* Text content |
|||
* |
|||
* @var string|array |
|||
*/ |
|||
private $text; |
|||
|
|||
/** |
|||
* Text style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
private $fontStyle; |
|||
|
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
private $paragraphStyle; |
|||
|
|||
/** |
|||
* Create a new Preserve Text Element |
|||
* |
|||
* @param string $text |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($text = null, $fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
$this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); |
|||
$this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); |
|||
|
|||
$this->text = SharedText::toUTF8($text); |
|||
$matches = preg_split('/({.*?})/', $this->text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); |
|||
if (isset($matches[0])) { |
|||
$this->text = $matches; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get Text style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function getFontStyle() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Text content |
|||
* |
|||
* @return string|array |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->text; |
|||
} |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Row as RowStyle; |
|||
|
|||
/** |
|||
* Table row element |
|||
* |
|||
* @since 0.8.0 |
|||
*/ |
|||
class Row extends AbstractElement |
|||
{ |
|||
/** |
|||
* Row height |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $height = null; |
|||
|
|||
/** |
|||
* Row style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Row |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Row cells |
|||
* |
|||
* @var \PhpOffice\PhpWord\Element\Cell[] |
|||
*/ |
|||
private $cells = array(); |
|||
|
|||
/** |
|||
* Create a new table row |
|||
* |
|||
* @param int $height |
|||
* @param mixed $style |
|||
*/ |
|||
public function __construct($height = null, $style = null) |
|||
{ |
|||
$this->height = $height; |
|||
$this->style = $this->setNewStyle(new RowStyle(), $style, true); |
|||
} |
|||
|
|||
/** |
|||
* Add a cell |
|||
* |
|||
* @param int $width |
|||
* @param mixed $style |
|||
* @return \PhpOffice\PhpWord\Element\Cell |
|||
*/ |
|||
public function addCell($width = null, $style = null) |
|||
{ |
|||
$cell = new Cell($width, $style); |
|||
$cell->setParentContainer($this); |
|||
$this->cells[] = $cell; |
|||
|
|||
return $cell; |
|||
} |
|||
|
|||
/** |
|||
* Get all cells |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\Cell[] |
|||
*/ |
|||
public function getCells() |
|||
{ |
|||
return $this->cells; |
|||
} |
|||
|
|||
/** |
|||
* Get row style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Row |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get row height |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getHeight() |
|||
{ |
|||
return $this->height; |
|||
} |
|||
} |
|||
@ -0,0 +1,190 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* Structured document tag (SDT) element |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class SDT extends Text |
|||
{ |
|||
/** |
|||
* Form field type: comboBox|dropDownList|date |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $type; |
|||
|
|||
/** |
|||
* Value |
|||
* |
|||
* @var string|bool|int |
|||
*/ |
|||
private $value; |
|||
|
|||
/** |
|||
* CheckBox/DropDown list entries |
|||
* |
|||
* @var array |
|||
*/ |
|||
private $listItems = array(); |
|||
|
|||
/** |
|||
* Alias |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $alias; |
|||
|
|||
/** |
|||
* Tag |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $tag; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string $type |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($type, $fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
parent::__construct(null, $fontStyle, $paragraphStyle); |
|||
$this->setType($type); |
|||
} |
|||
|
|||
/** |
|||
* Get type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Set type |
|||
* |
|||
* @param string $value |
|||
* @return self |
|||
*/ |
|||
public function setType($value) |
|||
{ |
|||
$enum = array('plainText', 'comboBox', 'dropDownList', 'date'); |
|||
$this->type = $this->setEnumVal($value, $enum, 'comboBox'); |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get value |
|||
* |
|||
* @return string|bool|int |
|||
*/ |
|||
public function getValue() |
|||
{ |
|||
return $this->value; |
|||
} |
|||
|
|||
/** |
|||
* Set value |
|||
* |
|||
* @param string|bool|int $value |
|||
* @return self |
|||
*/ |
|||
public function setValue($value) |
|||
{ |
|||
$this->value = $value; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get listItems |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getListItems() |
|||
{ |
|||
return $this->listItems; |
|||
} |
|||
|
|||
/** |
|||
* Set listItems |
|||
* |
|||
* @param array $value |
|||
* @return self |
|||
*/ |
|||
public function setListItems($value) |
|||
{ |
|||
$this->listItems = $value; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get tag |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getTag() |
|||
{ |
|||
return $this->tag; |
|||
} |
|||
|
|||
/** |
|||
* Set tag |
|||
* |
|||
* @param string $tag |
|||
* @return self |
|||
*/ |
|||
public function setTag($tag) |
|||
{ |
|||
$this->tag = $tag; |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get alias |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getAlias() |
|||
{ |
|||
return $this->alias; |
|||
} |
|||
|
|||
/** |
|||
* Set alias |
|||
* |
|||
* @param string $alias |
|||
* @return self |
|||
*/ |
|||
public function setAlias($alias) |
|||
{ |
|||
$this->alias = $alias; |
|||
|
|||
return $this; |
|||
} |
|||
} |
|||
@ -0,0 +1,307 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\ComplexType\FootnoteProperties; |
|||
use PhpOffice\PhpWord\Style\Section as SectionStyle; |
|||
|
|||
class Section extends AbstractContainer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'Section'; |
|||
|
|||
/** |
|||
* Section style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Section |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Section headers, indexed from 1, not zero |
|||
* |
|||
* @var Header[] |
|||
*/ |
|||
private $headers = array(); |
|||
|
|||
/** |
|||
* Section footers, indexed from 1, not zero |
|||
* |
|||
* @var Footer[] |
|||
*/ |
|||
private $footers = array(); |
|||
|
|||
/** |
|||
* The properties for the footnote of this section |
|||
* |
|||
* @var FootnoteProperties |
|||
*/ |
|||
private $footnoteProperties; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param int $sectionCount |
|||
* @param null|array|\PhpOffice\PhpWord\Style $style |
|||
*/ |
|||
public function __construct($sectionCount, $style = null) |
|||
{ |
|||
$this->sectionId = $sectionCount; |
|||
$this->setDocPart($this->container, $this->sectionId); |
|||
if (null === $style) { |
|||
$style = new SectionStyle(); |
|||
} |
|||
$this->style = $this->setNewStyle(new SectionStyle(), $style); |
|||
} |
|||
|
|||
/** |
|||
* Set section style. |
|||
* |
|||
* @param array $style |
|||
*/ |
|||
public function setStyle($style = null) |
|||
{ |
|||
if (!is_null($style) && is_array($style)) { |
|||
$this->style->setStyleByArray($style); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get section style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Section |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Add header |
|||
* |
|||
* @since 0.10.0 |
|||
* |
|||
* @param string $type |
|||
* |
|||
* @return Header |
|||
*/ |
|||
public function addHeader($type = Header::AUTO) |
|||
{ |
|||
return $this->addHeaderFooter($type, true); |
|||
} |
|||
|
|||
/** |
|||
* Add footer |
|||
* |
|||
* @since 0.10.0 |
|||
* |
|||
* @param string $type |
|||
* |
|||
* @return Footer |
|||
*/ |
|||
public function addFooter($type = Header::AUTO) |
|||
{ |
|||
return $this->addHeaderFooter($type, false); |
|||
} |
|||
|
|||
/** |
|||
* Get header elements |
|||
* |
|||
* @return Header[] |
|||
*/ |
|||
public function getHeaders() |
|||
{ |
|||
return $this->headers; |
|||
} |
|||
|
|||
/** |
|||
* Get footer elements |
|||
* |
|||
* @return Footer[] |
|||
*/ |
|||
public function getFooters() |
|||
{ |
|||
return $this->footers; |
|||
} |
|||
|
|||
/** |
|||
* Get the footnote properties |
|||
* |
|||
* @return FootnoteProperties |
|||
*/ |
|||
public function getFootnoteProperties() |
|||
{ |
|||
return $this->footnoteProperties; |
|||
} |
|||
|
|||
/** |
|||
* Get the footnote properties |
|||
* |
|||
* @deprecated Use the `getFootnoteProperties` method instead |
|||
* |
|||
* @return FootnoteProperties |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getFootnotePropoperties() |
|||
{ |
|||
return $this->footnoteProperties; |
|||
} |
|||
|
|||
/** |
|||
* Set the footnote properties |
|||
* |
|||
* @param FootnoteProperties $footnoteProperties |
|||
*/ |
|||
public function setFootnoteProperties(FootnoteProperties $footnoteProperties = null) |
|||
{ |
|||
$this->footnoteProperties = $footnoteProperties; |
|||
} |
|||
|
|||
/** |
|||
* Is there a header for this section that is for the first page only? |
|||
* |
|||
* If any of the Header instances have a type of Header::FIRST then this method returns true. |
|||
* False otherwise. |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function hasDifferentFirstPage() |
|||
{ |
|||
foreach ($this->headers as $header) { |
|||
if ($header->getType() == Header::FIRST) { |
|||
return true; |
|||
} |
|||
} |
|||
foreach ($this->footers as $footer) { |
|||
if ($footer->getType() == Header::FIRST) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Add header/footer |
|||
* |
|||
* @since 0.10.0 |
|||
* |
|||
* @param string $type |
|||
* @param bool $header |
|||
* |
|||
* @throws \Exception |
|||
* |
|||
* @return Header|Footer |
|||
*/ |
|||
private function addHeaderFooter($type = Header::AUTO, $header = true) |
|||
{ |
|||
$containerClass = substr(get_class($this), 0, strrpos(get_class($this), '\\')) . '\\' . |
|||
($header ? 'Header' : 'Footer'); |
|||
$collectionArray = $header ? 'headers' : 'footers'; |
|||
$collection = &$this->$collectionArray; |
|||
|
|||
if (in_array($type, array(Header::AUTO, Header::FIRST, Header::EVEN))) { |
|||
$index = count($collection); |
|||
/** @var \PhpOffice\PhpWord\Element\AbstractContainer $container Type hint */ |
|||
$container = new $containerClass($this->sectionId, ++$index, $type); |
|||
$container->setPhpWord($this->phpWord); |
|||
|
|||
$collection[$index] = $container; |
|||
|
|||
return $container; |
|||
} |
|||
throw new \Exception('Invalid header/footer type.'); |
|||
} |
|||
|
|||
/** |
|||
* Set section style |
|||
* |
|||
* @deprecated 0.12.0 |
|||
* |
|||
* @param array $settings |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function setSettings($settings = null) |
|||
{ |
|||
$this->setStyle($settings); |
|||
} |
|||
|
|||
/** |
|||
* Get section style |
|||
* |
|||
* @deprecated 0.12.0 |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Section |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getSettings() |
|||
{ |
|||
return $this->getStyle(); |
|||
} |
|||
|
|||
/** |
|||
* Create header |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return Header |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function createHeader() |
|||
{ |
|||
return $this->addHeader(); |
|||
} |
|||
|
|||
/** |
|||
* Create footer |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return Footer |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function createFooter() |
|||
{ |
|||
return $this->addFooter(); |
|||
} |
|||
|
|||
/** |
|||
* Get footer |
|||
* |
|||
* @deprecated 0.10.0 |
|||
* |
|||
* @return Footer |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
public function getFooter() |
|||
{ |
|||
if (empty($this->footers)) { |
|||
return null; |
|||
} |
|||
|
|||
return $this->footers[1]; |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Shape as ShapeStyle; |
|||
|
|||
/** |
|||
* Shape element |
|||
* |
|||
* @since 0.12.0 |
|||
*/ |
|||
class Shape extends AbstractElement |
|||
{ |
|||
/** |
|||
* Shape type arc|curve|line|polyline|rect|oval |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $type; |
|||
|
|||
/** |
|||
* Shape style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Shape |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string $type |
|||
* @param mixed $style |
|||
*/ |
|||
public function __construct($type, $style = null) |
|||
{ |
|||
$this->setType($type); |
|||
$this->style = $this->setNewStyle(new ShapeStyle(), $style); |
|||
} |
|||
|
|||
/** |
|||
* Get type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getType() |
|||
{ |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Set pattern |
|||
* |
|||
* @param string $value |
|||
* @return self |
|||
*/ |
|||
public function setType($value = null) |
|||
{ |
|||
$enum = array('arc', 'curve', 'line', 'polyline', 'rect', 'oval'); |
|||
$this->type = $this->setEnumVal($value, $enum, null); |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get shape style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Shape |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
} |
|||
@ -0,0 +1,169 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\PhpWord; |
|||
use PhpOffice\PhpWord\Style\Font; |
|||
use PhpOffice\PhpWord\Style\TOC as TOCStyle; |
|||
|
|||
/** |
|||
* Table of contents |
|||
*/ |
|||
class TOC extends AbstractElement |
|||
{ |
|||
/** |
|||
* TOC style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\TOC |
|||
*/ |
|||
private $TOCStyle; |
|||
|
|||
/** |
|||
* Font style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Font|string |
|||
*/ |
|||
private $fontStyle; |
|||
|
|||
/** |
|||
* Min title depth to show |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $minDepth = 1; |
|||
|
|||
/** |
|||
* Max title depth to show |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $maxDepth = 9; |
|||
|
|||
/** |
|||
* Create a new Table-of-Contents Element |
|||
* |
|||
* @param mixed $fontStyle |
|||
* @param array $tocStyle |
|||
* @param int $minDepth |
|||
* @param int $maxDepth |
|||
*/ |
|||
public function __construct($fontStyle = null, $tocStyle = null, $minDepth = 1, $maxDepth = 9) |
|||
{ |
|||
$this->TOCStyle = new TOCStyle(); |
|||
|
|||
if (!is_null($tocStyle) && is_array($tocStyle)) { |
|||
$this->TOCStyle->setStyleByArray($tocStyle); |
|||
} |
|||
|
|||
if (!is_null($fontStyle) && is_array($fontStyle)) { |
|||
$this->fontStyle = new Font(); |
|||
$this->fontStyle->setStyleByArray($fontStyle); |
|||
} else { |
|||
$this->fontStyle = $fontStyle; |
|||
} |
|||
|
|||
$this->minDepth = $minDepth; |
|||
$this->maxDepth = $maxDepth; |
|||
} |
|||
|
|||
/** |
|||
* Get all titles |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function getTitles() |
|||
{ |
|||
if (!$this->phpWord instanceof PhpWord) { |
|||
return array(); |
|||
} |
|||
|
|||
$titles = $this->phpWord->getTitles()->getItems(); |
|||
foreach ($titles as $i => $title) { |
|||
/** @var \PhpOffice\PhpWord\Element\Title $title Type hint */ |
|||
$depth = $title->getDepth(); |
|||
if ($this->minDepth > $depth) { |
|||
unset($titles[$i]); |
|||
} |
|||
if (($this->maxDepth != 0) && ($this->maxDepth < $depth)) { |
|||
unset($titles[$i]); |
|||
} |
|||
} |
|||
|
|||
return $titles; |
|||
} |
|||
|
|||
/** |
|||
* Get TOC Style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\TOC |
|||
*/ |
|||
public function getStyleTOC() |
|||
{ |
|||
return $this->TOCStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Font Style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Font|string |
|||
*/ |
|||
public function getStyleFont() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Set max depth. |
|||
* |
|||
* @param int $value |
|||
*/ |
|||
public function setMaxDepth($value) |
|||
{ |
|||
$this->maxDepth = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get Max Depth |
|||
* |
|||
* @return int Max depth of titles |
|||
*/ |
|||
public function getMaxDepth() |
|||
{ |
|||
return $this->maxDepth; |
|||
} |
|||
|
|||
/** |
|||
* Set min depth. |
|||
* |
|||
* @param int $value |
|||
*/ |
|||
public function setMinDepth($value) |
|||
{ |
|||
$this->minDepth = $value; |
|||
} |
|||
|
|||
/** |
|||
* Get Min Depth |
|||
* |
|||
* @return int Min depth of titles |
|||
*/ |
|||
public function getMinDepth() |
|||
{ |
|||
return $this->minDepth; |
|||
} |
|||
} |
|||
@ -0,0 +1,174 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Table as TableStyle; |
|||
|
|||
/** |
|||
* Table element |
|||
*/ |
|||
class Table extends AbstractElement |
|||
{ |
|||
/** |
|||
* Table style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\Table |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Table rows |
|||
* |
|||
* @var \PhpOffice\PhpWord\Element\Row[] |
|||
*/ |
|||
private $rows = array(); |
|||
|
|||
/** |
|||
* Table width |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $width = null; |
|||
|
|||
/** |
|||
* Create a new table |
|||
* |
|||
* @param mixed $style |
|||
*/ |
|||
public function __construct($style = null) |
|||
{ |
|||
$this->style = $this->setNewStyle(new TableStyle(), $style); |
|||
} |
|||
|
|||
/** |
|||
* Add a row |
|||
* |
|||
* @param int $height |
|||
* @param mixed $style |
|||
* @return \PhpOffice\PhpWord\Element\Row |
|||
*/ |
|||
public function addRow($height = null, $style = null) |
|||
{ |
|||
$row = new Row($height, $style); |
|||
$row->setParentContainer($this); |
|||
$this->rows[] = $row; |
|||
|
|||
return $row; |
|||
} |
|||
|
|||
/** |
|||
* Add a cell |
|||
* |
|||
* @param int $width |
|||
* @param mixed $style |
|||
* @return \PhpOffice\PhpWord\Element\Cell |
|||
*/ |
|||
public function addCell($width = null, $style = null) |
|||
{ |
|||
$index = count($this->rows) - 1; |
|||
$row = $this->rows[$index]; |
|||
$cell = $row->addCell($width, $style); |
|||
|
|||
return $cell; |
|||
} |
|||
|
|||
/** |
|||
* Get all rows |
|||
* |
|||
* @return \PhpOffice\PhpWord\Element\Row[] |
|||
*/ |
|||
public function getRows() |
|||
{ |
|||
return $this->rows; |
|||
} |
|||
|
|||
/** |
|||
* Get table style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\Table |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
|
|||
/** |
|||
* Get table width |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getWidth() |
|||
{ |
|||
return $this->width; |
|||
} |
|||
|
|||
/** |
|||
* Set table width. |
|||
* |
|||
* @param int $width |
|||
*/ |
|||
public function setWidth($width) |
|||
{ |
|||
$this->width = $width; |
|||
} |
|||
|
|||
/** |
|||
* Get column count |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function countColumns() |
|||
{ |
|||
$columnCount = 0; |
|||
|
|||
$rowCount = count($this->rows); |
|||
for ($i = 0; $i < $rowCount; $i++) { |
|||
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ |
|||
$row = $this->rows[$i]; |
|||
$cellCount = count($row->getCells()); |
|||
if ($columnCount < $cellCount) { |
|||
$columnCount = $cellCount; |
|||
} |
|||
} |
|||
|
|||
return $columnCount; |
|||
} |
|||
|
|||
/** |
|||
* The first declared cell width for each column |
|||
* |
|||
* @return int[] |
|||
*/ |
|||
public function findFirstDefinedCellWidths() |
|||
{ |
|||
$cellWidths = array(); |
|||
|
|||
foreach ($this->rows as $row) { |
|||
$cells = $row->getCells(); |
|||
if (count($cells) <= count($cellWidths)) { |
|||
continue; |
|||
} |
|||
$cellWidths = array(); |
|||
foreach ($cells as $cell) { |
|||
$cellWidths[] = $cell->getWidth(); |
|||
} |
|||
} |
|||
|
|||
return $cellWidths; |
|||
} |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
use PhpOffice\PhpWord\Style\Font; |
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
/** |
|||
* Text element |
|||
*/ |
|||
class Text extends AbstractElement |
|||
{ |
|||
/** |
|||
* Text content |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $text; |
|||
|
|||
/** |
|||
* Text style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
protected $fontStyle; |
|||
|
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
protected $paragraphStyle; |
|||
|
|||
/** |
|||
* Create a new Text Element |
|||
* |
|||
* @param string $text |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($text = null, $fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
$this->setText($text); |
|||
$paragraphStyle = $this->setParagraphStyle($paragraphStyle); |
|||
$this->setFontStyle($fontStyle, $paragraphStyle); |
|||
} |
|||
|
|||
/** |
|||
* Set Text style |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Font $style |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function setFontStyle($style = null, $paragraphStyle = null) |
|||
{ |
|||
if ($style instanceof Font) { |
|||
$this->fontStyle = $style; |
|||
$this->setParagraphStyle($paragraphStyle); |
|||
} elseif (is_array($style)) { |
|||
$this->fontStyle = new Font('text', $paragraphStyle); |
|||
$this->fontStyle->setStyleByArray($style); |
|||
} elseif (null === $style) { |
|||
$this->fontStyle = new Font('text', $paragraphStyle); |
|||
} else { |
|||
$this->fontStyle = $style; |
|||
$this->setParagraphStyle($paragraphStyle); |
|||
} |
|||
|
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Text style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function getFontStyle() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Set Paragraph style |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function setParagraphStyle($style = null) |
|||
{ |
|||
if (is_array($style)) { |
|||
$this->paragraphStyle = new Paragraph(); |
|||
$this->paragraphStyle->setStyleByArray($style); |
|||
} elseif ($style instanceof Paragraph) { |
|||
$this->paragraphStyle = $style; |
|||
} elseif (null === $style) { |
|||
$this->paragraphStyle = new Paragraph(); |
|||
} else { |
|||
$this->paragraphStyle = $style; |
|||
} |
|||
|
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Set text content |
|||
* |
|||
* @param string $text |
|||
* @return self |
|||
*/ |
|||
public function setText($text) |
|||
{ |
|||
$this->text = SharedText::toUTF8($text); |
|||
|
|||
return $this; |
|||
} |
|||
|
|||
/** |
|||
* Get Text content |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->text; |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\TextBox as TextBoxStyle; |
|||
|
|||
/** |
|||
* TextBox element |
|||
* |
|||
* @since 0.11.0 |
|||
*/ |
|||
class TextBox extends AbstractContainer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'TextBox'; |
|||
|
|||
/** |
|||
* TextBox style |
|||
* |
|||
* @var \PhpOffice\PhpWord\Style\TextBox |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Create a new textbox |
|||
* |
|||
* @param mixed $style |
|||
*/ |
|||
public function __construct($style = null) |
|||
{ |
|||
$this->style = $this->setNewStyle(new TextBoxStyle(), $style); |
|||
} |
|||
|
|||
/** |
|||
* Get textbox style |
|||
* |
|||
* @return \PhpOffice\PhpWord\Style\TextBox |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Font; |
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
/** |
|||
* Text break element |
|||
*/ |
|||
class TextBreak extends AbstractElement |
|||
{ |
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
private $paragraphStyle = null; |
|||
|
|||
/** |
|||
* Text style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
private $fontStyle = null; |
|||
|
|||
/** |
|||
* Create a new TextBreak Element |
|||
* |
|||
* @param mixed $fontStyle |
|||
* @param mixed $paragraphStyle |
|||
*/ |
|||
public function __construct($fontStyle = null, $paragraphStyle = null) |
|||
{ |
|||
if (!is_null($paragraphStyle)) { |
|||
$paragraphStyle = $this->setParagraphStyle($paragraphStyle); |
|||
} |
|||
if (!is_null($fontStyle)) { |
|||
$this->setFontStyle($fontStyle, $paragraphStyle); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Set Text style |
|||
* |
|||
* @param mixed $style |
|||
* @param mixed $paragraphStyle |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function setFontStyle($style = null, $paragraphStyle = null) |
|||
{ |
|||
if ($style instanceof Font) { |
|||
$this->fontStyle = $style; |
|||
$this->setParagraphStyle($paragraphStyle); |
|||
} elseif (is_array($style)) { |
|||
$this->fontStyle = new Font('text', $paragraphStyle); |
|||
$this->fontStyle->setStyleByArray($style); |
|||
} else { |
|||
$this->fontStyle = $style; |
|||
$this->setParagraphStyle($paragraphStyle); |
|||
} |
|||
|
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Text style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Font |
|||
*/ |
|||
public function getFontStyle() |
|||
{ |
|||
return $this->fontStyle; |
|||
} |
|||
|
|||
/** |
|||
* Set Paragraph style |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function setParagraphStyle($style = null) |
|||
{ |
|||
if (is_array($style)) { |
|||
$this->paragraphStyle = new Paragraph(); |
|||
$this->paragraphStyle->setStyleByArray($style); |
|||
} elseif ($style instanceof Paragraph) { |
|||
$this->paragraphStyle = $style; |
|||
} else { |
|||
$this->paragraphStyle = $style; |
|||
} |
|||
|
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Get Paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Has font/paragraph style defined |
|||
* |
|||
* @return bool |
|||
*/ |
|||
public function hasStyle() |
|||
{ |
|||
return !is_null($this->fontStyle) || !is_null($this->paragraphStyle); |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Style\Paragraph; |
|||
|
|||
/** |
|||
* Textrun/paragraph element |
|||
*/ |
|||
class TextRun extends AbstractContainer |
|||
{ |
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'TextRun'; |
|||
|
|||
/** |
|||
* Paragraph style |
|||
* |
|||
* @var string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
protected $paragraphStyle; |
|||
|
|||
/** |
|||
* Create new instance |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $paragraphStyle |
|||
*/ |
|||
public function __construct($paragraphStyle = null) |
|||
{ |
|||
$this->paragraphStyle = $this->setParagraphStyle($paragraphStyle); |
|||
} |
|||
|
|||
/** |
|||
* Get Paragraph style |
|||
* |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function getParagraphStyle() |
|||
{ |
|||
return $this->paragraphStyle; |
|||
} |
|||
|
|||
/** |
|||
* Set Paragraph style |
|||
* |
|||
* @param string|array|\PhpOffice\PhpWord\Style\Paragraph $style |
|||
* @return string|\PhpOffice\PhpWord\Style\Paragraph |
|||
*/ |
|||
public function setParagraphStyle($style = null) |
|||
{ |
|||
if (is_array($style)) { |
|||
$this->paragraphStyle = new Paragraph(); |
|||
$this->paragraphStyle->setStyleByArray($style); |
|||
} elseif ($style instanceof Paragraph) { |
|||
$this->paragraphStyle = $style; |
|||
} elseif (null === $style) { |
|||
$this->paragraphStyle = new Paragraph(); |
|||
} else { |
|||
$this->paragraphStyle = $style; |
|||
} |
|||
|
|||
return $this->paragraphStyle; |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
use PhpOffice\PhpWord\Shared\Text as SharedText; |
|||
use PhpOffice\PhpWord\Style; |
|||
|
|||
/** |
|||
* Title element |
|||
*/ |
|||
class Title extends AbstractElement |
|||
{ |
|||
/** |
|||
* Title Text content |
|||
* |
|||
* @var string|TextRun |
|||
*/ |
|||
private $text; |
|||
|
|||
/** |
|||
* Title depth |
|||
* |
|||
* @var int |
|||
*/ |
|||
private $depth = 1; |
|||
|
|||
/** |
|||
* Name of the heading style, e.g. 'Heading1' |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $style; |
|||
|
|||
/** |
|||
* Is part of collection |
|||
* |
|||
* @var bool |
|||
*/ |
|||
protected $collectionRelation = true; |
|||
|
|||
/** |
|||
* Create a new Title Element |
|||
* |
|||
* @param string|TextRun $text |
|||
* @param int $depth |
|||
*/ |
|||
public function __construct($text, $depth = 1) |
|||
{ |
|||
if (is_string($text)) { |
|||
$this->text = SharedText::toUTF8($text); |
|||
} elseif ($text instanceof TextRun) { |
|||
$this->text = $text; |
|||
} else { |
|||
throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun'); |
|||
} |
|||
|
|||
$this->depth = $depth; |
|||
$styleName = $depth === 0 ? 'Title' : "Heading_{$this->depth}"; |
|||
if (array_key_exists($styleName, Style::getStyles())) { |
|||
$this->style = str_replace('_', '', $styleName); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get Title Text content |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getText() |
|||
{ |
|||
return $this->text; |
|||
} |
|||
|
|||
/** |
|||
* Get depth |
|||
* |
|||
* @return int |
|||
*/ |
|||
public function getDepth() |
|||
{ |
|||
return $this->depth; |
|||
} |
|||
|
|||
/** |
|||
* Get Title style |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getStyle() |
|||
{ |
|||
return $this->style; |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Element; |
|||
|
|||
/** |
|||
* TrackChange element |
|||
* @see http://datypic.com/sc/ooxml/t-w_CT_TrackChange.html |
|||
* @see http://datypic.com/sc/ooxml/t-w_CT_RunTrackChange.html |
|||
*/ |
|||
class TrackChange extends AbstractContainer |
|||
{ |
|||
const INSERTED = 'INSERTED'; |
|||
const DELETED = 'DELETED'; |
|||
|
|||
/** |
|||
* @var string Container type |
|||
*/ |
|||
protected $container = 'TrackChange'; |
|||
|
|||
/** |
|||
* The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $changeType; |
|||
|
|||
/** |
|||
* Author |
|||
* |
|||
* @var string |
|||
*/ |
|||
private $author; |
|||
|
|||
/** |
|||
* Date |
|||
* |
|||
* @var \DateTime |
|||
*/ |
|||
private $date; |
|||
|
|||
/** |
|||
* Create a new TrackChange Element |
|||
* |
|||
* @param string $changeType |
|||
* @param string $author |
|||
* @param null|int|bool|\DateTime $date |
|||
*/ |
|||
public function __construct($changeType = null, $author = null, $date = null) |
|||
{ |
|||
$this->changeType = $changeType; |
|||
$this->author = $author; |
|||
if ($date !== null && $date !== false) { |
|||
$this->date = ($date instanceof \DateTime) ? $date : new \DateTime('@' . $date); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get TrackChange Author |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getAuthor() |
|||
{ |
|||
return $this->author; |
|||
} |
|||
|
|||
/** |
|||
* Get TrackChange Date |
|||
* |
|||
* @return \DateTime |
|||
*/ |
|||
public function getDate() |
|||
{ |
|||
return $this->date; |
|||
} |
|||
|
|||
/** |
|||
* Get the Change type |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getChangeType() |
|||
{ |
|||
return $this->changeType; |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Escaper; |
|||
|
|||
/** |
|||
* @since 0.13.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
abstract class AbstractEscaper implements EscaperInterface |
|||
{ |
|||
/** |
|||
* @param string $input |
|||
* |
|||
* @return string |
|||
*/ |
|||
abstract protected function escapeSingleValue($input); |
|||
|
|||
public function escape($input) |
|||
{ |
|||
if (is_array($input)) { |
|||
foreach ($input as &$item) { |
|||
$item = $this->escapeSingleValue($item); |
|||
} |
|||
} else { |
|||
$input = $this->escapeSingleValue($input); |
|||
} |
|||
|
|||
return $input; |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Escaper; |
|||
|
|||
/** |
|||
* @since 0.13.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
interface EscaperInterface |
|||
{ |
|||
/** |
|||
* @param mixed $input |
|||
* |
|||
* @return mixed |
|||
*/ |
|||
public function escape($input); |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Escaper; |
|||
|
|||
/** |
|||
* @since 0.13.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
class RegExp extends AbstractEscaper |
|||
{ |
|||
const REG_EXP_DELIMITER = '/'; |
|||
|
|||
protected function escapeSingleValue($input) |
|||
{ |
|||
return self::REG_EXP_DELIMITER . preg_quote($input, self::REG_EXP_DELIMITER) . self::REG_EXP_DELIMITER . 'u'; |
|||
} |
|||
} |
|||
@ -0,0 +1,97 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Escaper; |
|||
|
|||
/** |
|||
* @since 0.13.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
class Rtf extends AbstractEscaper |
|||
{ |
|||
protected function escapeAsciiCharacter($code) |
|||
{ |
|||
if ($code == 9) { |
|||
return '{\\tab}'; |
|||
} |
|||
if (0x20 > $code || $code >= 0x80) { |
|||
return '{\\u' . $code . '}'; |
|||
} |
|||
if ($code == 123 || $code == 125 || $code == 92) { // open or close brace or backslash |
|||
return '\\' . chr($code); |
|||
} |
|||
|
|||
return chr($code); |
|||
} |
|||
|
|||
protected function escapeMultibyteCharacter($code) |
|||
{ |
|||
return '\\uc0{\\u' . $code . '}'; |
|||
} |
|||
|
|||
/** |
|||
* @see http://www.randomchaos.com/documents/?source=php_and_unicode |
|||
* @param string $input |
|||
*/ |
|||
protected function escapeSingleValue($input) |
|||
{ |
|||
$escapedValue = ''; |
|||
|
|||
$numberOfBytes = 1; |
|||
$bytes = array(); |
|||
for ($i = 0; $i < strlen($input); ++$i) { |
|||
$character = $input[$i]; |
|||
$asciiCode = ord($character); |
|||
|
|||
if ($asciiCode < 128) { |
|||
$escapedValue .= $this->escapeAsciiCharacter($asciiCode); |
|||
} else { |
|||
if (0 == count($bytes)) { |
|||
if ($asciiCode < 224) { |
|||
$numberOfBytes = 2; |
|||
} elseif ($asciiCode < 240) { |
|||
$numberOfBytes = 3; |
|||
} elseif ($asciiCode < 248) { |
|||
$numberOfBytes = 4; |
|||
} |
|||
} |
|||
|
|||
$bytes[] = $asciiCode; |
|||
|
|||
if ($numberOfBytes == count($bytes)) { |
|||
if (4 == $numberOfBytes) { |
|||
$multibyteCode = ($bytes[0] % 8) * 262144 + ($bytes[1] % 64) * 4096 + ($bytes[2] % 64) * 64 + ($bytes[3] % 64); |
|||
} elseif (3 == $numberOfBytes) { |
|||
$multibyteCode = ($bytes[0] % 16) * 4096 + ($bytes[1] % 64) * 64 + ($bytes[2] % 64); |
|||
} else { |
|||
$multibyteCode = ($bytes[0] % 32) * 64 + ($bytes[1] % 64); |
|||
} |
|||
|
|||
if (65279 != $multibyteCode) { |
|||
$escapedValue .= $multibyteCode < 128 ? $this->escapeAsciiCharacter($multibyteCode) : $this->escapeMultibyteCharacter($multibyteCode); |
|||
} |
|||
|
|||
$numberOfBytes = 1; |
|||
$bytes = array(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return $escapedValue; |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Escaper; |
|||
|
|||
/** |
|||
* @since 0.13.0 |
|||
* |
|||
* @codeCoverageIgnore |
|||
*/ |
|||
class Xml extends AbstractEscaper |
|||
{ |
|||
protected function escapeSingleValue($input) |
|||
{ |
|||
// todo: omit encoding parameter after migration onto PHP 5.4 |
|||
return htmlspecialchars($input, ENT_QUOTES, 'UTF-8'); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* @since 0.12.0 |
|||
*/ |
|||
final class CopyFileException extends Exception |
|||
{ |
|||
/** |
|||
* @param string $source The fully qualified source file name |
|||
* @param string $destination The fully qualified destination file name |
|||
* @param int $code The user defined exception code |
|||
* @param \Exception $previous The previous exception used for the exception chaining |
|||
*/ |
|||
final public function __construct($source, $destination, $code = 0, \Exception $previous = null) |
|||
{ |
|||
parent::__construct( |
|||
sprintf('Could not copy \'%s\' file to \'%s\'.', $source, $destination), |
|||
$code, |
|||
$previous |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* @since 0.12.0 |
|||
*/ |
|||
final class CreateTemporaryFileException extends Exception |
|||
{ |
|||
/** |
|||
* @param int $code The user defined exception code |
|||
* @param \Exception $previous The previous exception used for the exception chaining |
|||
*/ |
|||
final public function __construct($code = 0, \Exception $previous = null) |
|||
{ |
|||
parent::__construct( |
|||
'Could not create a temporary file with unique name in the specified directory.', |
|||
$code, |
|||
$previous |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* General exception |
|||
*/ |
|||
class Exception extends \Exception |
|||
{ |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* Exception used for when an image is not found |
|||
*/ |
|||
class InvalidImageException extends Exception |
|||
{ |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* Exception used for when an image is not found |
|||
*/ |
|||
class InvalidObjectException extends Exception |
|||
{ |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
use InvalidArgumentException; |
|||
|
|||
/** |
|||
* Exception used for when a style value is invalid |
|||
*/ |
|||
class InvalidStyleException extends InvalidArgumentException |
|||
{ |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord\Exception; |
|||
|
|||
/** |
|||
* Exception used for when an image type is unsupported |
|||
*/ |
|||
class UnsupportedImageTypeException extends Exception |
|||
{ |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
<?php |
|||
/** |
|||
* This file is part of PHPWord - A pure PHP library for reading and writing |
|||
* word processing documents. |
|||
* |
|||
* PHPWord is free software distributed under the terms of the GNU Lesser |
|||
* General Public License version 3 as published by the Free Software Foundation. |
|||
* |
|||
* For the full copyright and license information, please read the LICENSE |
|||
* file that was distributed with this source code. For the full list of |
|||
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors. |
|||
* |
|||
* @see https://github.com/PHPOffice/PHPWord |
|||
* @copyright 2010-2018 PHPWord contributors |
|||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
|||
*/ |
|||
|
|||
namespace PhpOffice\PhpWord; |
|||
|
|||
use PhpOffice\PhpWord\Exception\Exception; |
|||
use PhpOffice\PhpWord\Reader\ReaderInterface; |
|||
use PhpOffice\PhpWord\Writer\WriterInterface; |
|||
|
|||
abstract class IOFactory |
|||
{ |
|||
/** |
|||
* Create new writer |
|||
* |
|||
* @param PhpWord $phpWord |
|||
* @param string $name |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\Exception |
|||
* |
|||
* @return WriterInterface |
|||
*/ |
|||
public static function createWriter(PhpWord $phpWord, $name = 'Word2007') |
|||
{ |
|||
if ($name !== 'WriterInterface' && !in_array($name, array('ODText', 'RTF', 'Word2007', 'HTML', 'PDF'), true)) { |
|||
throw new Exception("\"{$name}\" is not a valid writer."); |
|||
} |
|||
|
|||
$fqName = "PhpOffice\\PhpWord\\Writer\\{$name}"; |
|||
|
|||
return new $fqName($phpWord); |
|||
} |
|||
|
|||
/** |
|||
* Create new reader |
|||
* |
|||
* @param string $name |
|||
* |
|||
* @throws Exception |
|||
* |
|||
* @return ReaderInterface |
|||
*/ |
|||
public static function createReader($name = 'Word2007') |
|||
{ |
|||
return self::createObject('Reader', $name); |
|||
} |
|||
|
|||
/** |
|||
* Create new object |
|||
* |
|||
* @param string $type |
|||
* @param string $name |
|||
* @param \PhpOffice\PhpWord\PhpWord $phpWord |
|||
* |
|||
* @throws \PhpOffice\PhpWord\Exception\Exception |
|||
* |
|||
* @return \PhpOffice\PhpWord\Writer\WriterInterface|\PhpOffice\PhpWord\Reader\ReaderInterface |
|||
*/ |
|||
private static function createObject($type, $name, $phpWord = null) |
|||
{ |
|||
$class = "PhpOffice\\PhpWord\\{$type}\\{$name}"; |
|||
if (class_exists($class) && self::isConcreteClass($class)) { |
|||
return new $class($phpWord); |
|||
} |
|||
throw new Exception("\"{$name}\" is not a valid {$type}."); |
|||
} |
|||
|
|||
/** |
|||
* Loads PhpWord from file |
|||
* |
|||
* @param string $filename The name of the file |
|||
* @param string $readerName |
|||
* @return \PhpOffice\PhpWord\PhpWord $phpWord |
|||
*/ |
|||
public static function load($filename, $readerName = 'Word2007') |
|||
{ |
|||
/** @var \PhpOffice\PhpWord\Reader\ReaderInterface $reader */ |
|||
$reader = self::createReader($readerName); |
|||
|
|||
return $reader->load($filename); |
|||
} |
|||
|
|||
/** |
|||
* Check if it's a concrete class (not abstract nor interface) |
|||
* |
|||
* @param string $class |
|||
* @return bool |
|||
*/ |
|||
private static function isConcreteClass($class) |
|||
{ |
|||
$reflection = new \ReflectionClass($class); |
|||
|
|||
return !$reflection->isAbstract() && !$reflection->isInterface(); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue