|
|
<?php
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
use App\Repositories\YuanheRepository;
|
|
|
|
|
|
class Company extends SoftDeletesModel
|
|
|
{
|
|
|
|
|
|
protected $casts = ['project_users' => 'json', 'partners' => 'json'];
|
|
|
protected $appends = ['is_yh_invested_text'];
|
|
|
|
|
|
public function getIsYhInvestedTextAttribute()
|
|
|
{
|
|
|
if (empty($this->is_yh_invested)) {
|
|
|
return '否';
|
|
|
}
|
|
|
return $this->is_yh_invested == 1 ? '是' : '否';
|
|
|
}
|
|
|
|
|
|
public function users()
|
|
|
{
|
|
|
return $this->hasMany(User::class, 'company_id', 'id');
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 限制只返回有关联学员且至少有一条审核通过的报名记录的公司
|
|
|
* 用于列表查询和统计查询
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
|
* @return \Illuminate\Database\Eloquent\Builder
|
|
|
*/
|
|
|
public function scopeApprovedStudents($query)
|
|
|
{
|
|
|
return $query->whereHas('users', function ($q) {
|
|
|
$q->whereHas('courseSigns', function ($signQuery) {
|
|
|
$signQuery->where('status', 1);
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 地址转经纬度
|
|
|
*/
|
|
|
public static function addressTolocation($address)
|
|
|
{
|
|
|
$map = Config::getValueByKey('map_server');
|
|
|
$map = json_decode($map, true);
|
|
|
$url = "https://restapi.amap.com/v3/geocode/geo";
|
|
|
$params = [
|
|
|
'key' => $map['key'],
|
|
|
'address' => $address,
|
|
|
];
|
|
|
try {
|
|
|
$result = httpCurl($url, 'GET', $params);
|
|
|
$result = json_decode($result, true);
|
|
|
if ($result['status'] == 1) {
|
|
|
$location = $result['geocodes'][0]['location'];
|
|
|
$location = explode(',', $location);
|
|
|
return [
|
|
|
'lng' => $location[0],
|
|
|
'lat' => $location[1],
|
|
|
];
|
|
|
}
|
|
|
return [
|
|
|
'lng' => null,
|
|
|
'lat' => null,
|
|
|
];
|
|
|
} catch (\Exception $e) {
|
|
|
return [
|
|
|
'lng' => null,
|
|
|
'lat' => null,
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 累计被投企业统计
|
|
|
* @param string|null $start_date 开始日期
|
|
|
* @param string|null $end_date 结束日期
|
|
|
* @param array|null $course_ids 课程ID(仅在自定义时间时生效)
|
|
|
* @param bool $retList 是否返回列表
|
|
|
*/
|
|
|
public static function yhInvestedTotal($end_date = null, $retList = false)
|
|
|
{
|
|
|
// 获取这些学员所在的被投企业
|
|
|
$companies = Company::approvedStudents()->where('is_yh_invested', 1)->get();
|
|
|
// 自定义时间:需要按被投时间筛选
|
|
|
// 筛选出被投时间在范围内的企业
|
|
|
$filteredCompanies = [];
|
|
|
foreach ($companies as $company) {
|
|
|
$projectUsers = $company->project_users ?? [];
|
|
|
$hasValidInvestDate = false;
|
|
|
$allInvestDatesNull = true;
|
|
|
|
|
|
foreach ($projectUsers as $item) {
|
|
|
$investDate = $item['investDate'] ?? null;
|
|
|
// 检查是否有有效的被投时间
|
|
|
if ($investDate) {
|
|
|
$allInvestDatesNull = false;
|
|
|
// 检查被投时间是否在范围内
|
|
|
if ($investDate <= $end_date) {
|
|
|
$hasValidInvestDate = true;
|
|
|
break; // 只要有一条满足就加入
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果有有效的被投时间在范围内,或者所有被投时间都是null,则加入结果
|
|
|
if ($hasValidInvestDate || $allInvestDatesNull) {
|
|
|
$filteredCompanies[] = $company;
|
|
|
}
|
|
|
}
|
|
|
$companies = collect($filteredCompanies);
|
|
|
|
|
|
// 返回结果
|
|
|
if ($retList) {
|
|
|
return $companies->values();
|
|
|
} else {
|
|
|
return $companies->count();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 今年被投企业统计(统计或列表)- 按年份范围统计
|
|
|
* @param string|null $start_date 开始日期
|
|
|
* @param string|null $end_date 结束日期
|
|
|
* @param array|null $course_ids 课程ID数组,不传则统计所有课程
|
|
|
* @param bool $retList 是否返回列表,false返回数量,true返回列表(包含学员、课程信息)
|
|
|
* @return int|array
|
|
|
*/
|
|
|
public static function companyInvestedYear($start_date = null, $end_date = null, $retList = false)
|
|
|
{
|
|
|
// 计算年份范围
|
|
|
$years = [];
|
|
|
if ($start_date && $end_date) {
|
|
|
// 从开始和结束日期中提取年份范围
|
|
|
$startYear = (int) date('Y', strtotime($start_date));
|
|
|
$endYear = (int) date('Y', strtotime($end_date));
|
|
|
// 生成所有年份的数组
|
|
|
for ($year = $startYear; $year <= $endYear; $year++) {
|
|
|
$years[] = $year;
|
|
|
}
|
|
|
} else {
|
|
|
// 如果没有提供日期,使用当前年份
|
|
|
$years[] = (int) date('Y');
|
|
|
}
|
|
|
|
|
|
// 获取这些公司中标记为被投的公司
|
|
|
$allInvestedCompanies = Company::approvedStudents()->where('is_yh_invested', 1)->get();
|
|
|
// 筛选出被投时间在年份范围内的企业
|
|
|
$companies = [];
|
|
|
foreach ($allInvestedCompanies as $company) {
|
|
|
$projectUsers = $company->project_users ?? [];
|
|
|
$hasInvestInYears = false;
|
|
|
foreach ($projectUsers as $item) {
|
|
|
$investDate = $item['investDate'] ?? null;
|
|
|
if ($investDate) {
|
|
|
$investYear = (int) date('Y', strtotime($investDate));
|
|
|
if (in_array($investYear, $years)) {
|
|
|
$hasInvestInYears = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if ($hasInvestInYears) {
|
|
|
$companies[$company->id] = $company;
|
|
|
}
|
|
|
}
|
|
|
$companies = collect($companies);
|
|
|
// 返回结果
|
|
|
if ($retList) {
|
|
|
return $companies->values();
|
|
|
} else {
|
|
|
return $companies->count();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据用户信息更新公司信息
|
|
|
* @param User $user 用户对象
|
|
|
* @return array 返回结果 ['success' => bool, 'message' => string, 'company' => Company|null]
|
|
|
*/
|
|
|
public static function updateCompanyFromUser($user)
|
|
|
{
|
|
|
if (!$user || empty($user->company_name)) {
|
|
|
return ['success' => false, 'message' => '用户或公司名称为空', 'company' => null];
|
|
|
}
|
|
|
|
|
|
// 如果已经有有效的公司关联(company_id > 0),跳过
|
|
|
// 允许处理 company_id = -1(待更新)或 null(初始状态)的情况
|
|
|
if ($user->company_id && $user->company_id > 0) {
|
|
|
return ['success' => false, 'message' => '用户已有公司关联', 'company' => null];
|
|
|
}
|
|
|
|
|
|
// 清理公司名称:去除首尾空格、换行符、制表符等异常字符
|
|
|
$cleanedCompanyName = trim($user->company_name);
|
|
|
// 去除换行符、回车符、制表符等空白字符
|
|
|
$cleanedCompanyName = preg_replace('/[\r\n\t]+/', '', $cleanedCompanyName);
|
|
|
// 将多个连续空格替换为单个空格
|
|
|
$cleanedCompanyName = preg_replace('/\s+/', ' ', $cleanedCompanyName);
|
|
|
// 再次去除首尾空格
|
|
|
$cleanedCompanyName = trim($cleanedCompanyName);
|
|
|
|
|
|
// 如果清理后为空,返回错误
|
|
|
if (empty($cleanedCompanyName)) {
|
|
|
return ['success' => false, 'message' => '公司名称无效', 'company' => null];
|
|
|
}
|
|
|
|
|
|
$YuanheRepository = new YuanheRepository();
|
|
|
|
|
|
// 获取公司详细信息,使用清理后的公司名称
|
|
|
$result = $YuanheRepository->companyInfo(['enterpriseName' => $cleanedCompanyName]);
|
|
|
|
|
|
if (!$result) {
|
|
|
// 标识一下未匹配到公司,后续可以根据这个字段筛选出未匹配到公司的用户
|
|
|
$user->company_id = 0;
|
|
|
$user->save();
|
|
|
return ['success' => false, 'message' => '公司不存在', 'company' => null];
|
|
|
}
|
|
|
|
|
|
// 如果$result['enterpriseName']存在数字,跳过
|
|
|
if (preg_match('/\d/', $result['enterpriseName'])) {
|
|
|
$user->company_id = 0;
|
|
|
$user->save();
|
|
|
return ['success' => false, 'message' => '公司名称包含数字,跳过', 'company' => null];
|
|
|
}
|
|
|
|
|
|
if ($result['status'] == '未注册') {
|
|
|
$user->company_id = 0;
|
|
|
$user->save();
|
|
|
return ['success' => false, 'message' => '公司未注册,跳过', 'company' => null];
|
|
|
}
|
|
|
|
|
|
$where = ['company_name' => $result['enterpriseName']];
|
|
|
$data = [
|
|
|
'company_address' => $result['address'],
|
|
|
'business_scope' => $result['businessScope'],
|
|
|
'company_city' => $result['city'],
|
|
|
'contact_mail' => $result['contactMail'],
|
|
|
'contact_phone' => $result['contactPhone'],
|
|
|
'company_area' => $result['country'],
|
|
|
'credit_code' => $result['creditCode'],
|
|
|
'enterprise_id' => $result['enterpriseId'],
|
|
|
'company_name' => $result['enterpriseName'],
|
|
|
'is_abroad' => $result['isAbroad'],
|
|
|
'company_market' => $result['isOnStock'],
|
|
|
'is_yh_invested' => $result['isYhInvested'],
|
|
|
'logo' => $result['logo'],
|
|
|
'company_legal_representative' => $result['operName'],
|
|
|
'company_province' => $result['province'],
|
|
|
'company_industry' => combineKeyValue($result['qccIndustry']),
|
|
|
'regist_amount' => $result['registAmount'],
|
|
|
'regist_capi_type' => $result['registCapiType'],
|
|
|
'company_date' => $result['startDate'],
|
|
|
'status' => $result['status'],
|
|
|
'stock_date' => $result['stockDate'],
|
|
|
'currency_type' => $result['currencyType'],
|
|
|
'stock_number' => $result['stockNumber'],
|
|
|
'stock_type' => $result['stockType'],
|
|
|
'company_tag' => implode(',', $result['tagList']),
|
|
|
// 更新日期
|
|
|
'update_date' => $result['updatedDate'] ?? null,
|
|
|
// 管理平台
|
|
|
'project_users' => $result['projectUsers'] ?? null,
|
|
|
// 股东信息
|
|
|
'partners' => $result['partners'] ?? null,
|
|
|
];
|
|
|
|
|
|
$company = Company::updateOrCreate($where, $data);
|
|
|
|
|
|
// 更新用户关联
|
|
|
$user->company_id = $company->id;
|
|
|
$user->save();
|
|
|
|
|
|
// 更新上市状态
|
|
|
self::updateMarketStatus($company->id);
|
|
|
|
|
|
// 更新位置
|
|
|
self::updateLocation($company->id);
|
|
|
|
|
|
return ['success' => true, 'message' => '更新成功', 'company' => $company];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 更新经纬度信息
|
|
|
* @param int $companyId 公司ID
|
|
|
* @return bool
|
|
|
*/
|
|
|
public static function updateLocation($companyId)
|
|
|
{
|
|
|
$company = Company::find($companyId);
|
|
|
if (!$company || empty($company->company_address) || $company->company_longitude) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
$local = Company::addressTolocation($company->company_address);
|
|
|
$company->company_longitude = $local['lng'];
|
|
|
$company->company_latitude = $local['lat'];
|
|
|
$company->save();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据 company_tag 更新上市状态
|
|
|
* 判断是否包含上市代码标签,如 688001.SH、000001.SZ、830001.BJ 等
|
|
|
* @param int $companyId 公司ID
|
|
|
* @return bool 是否更新成功
|
|
|
*/
|
|
|
public static function updateMarketStatus($companyId)
|
|
|
{
|
|
|
$company = Company::find($companyId);
|
|
|
if (!$company || empty($company->company_tag)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 上市代码正则:匹配全球各地上市公司股票代码后缀
|
|
|
$stockCodePattern = '/\.(SWR|SW|WR|SS|RS|SB|PK|TO|AX|WS|PR|DB|UN|RT|WT|SH|SZ|BJ|TW|HK|SG|US|DE|FR|JP|KR|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|U|V|W|X|Y|Z)(?![A-Za-z0-9])/i';
|
|
|
|
|
|
$hasStockCode = preg_match($stockCodePattern, $company->company_tag);
|
|
|
// 检查是否包含"新三板"
|
|
|
$hasXinsanban = strpos($company->company_tag, '新三板') !== false;
|
|
|
// 如果匹配到股票代码或包含"新三板",则标记为上市
|
|
|
$newMarketStatus = ($hasStockCode || $hasXinsanban) ? 1 : 0;
|
|
|
|
|
|
// 只有状态变化才更新
|
|
|
if ($company->company_market != $newMarketStatus) {
|
|
|
$company->company_market = $newMarketStatus;
|
|
|
$company->save();
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 验证公司名称是否包含特殊符号
|
|
|
* @param string $companyName 公司名称
|
|
|
* @return array 返回结果 ['valid' => bool, 'message' => string]
|
|
|
*/
|
|
|
public static function validateCompanyName($companyName)
|
|
|
{
|
|
|
if (empty($companyName)) {
|
|
|
return ['valid' => true, 'message' => ''];
|
|
|
}
|
|
|
|
|
|
// 定义不允许的特殊符号(包含中英文标点符号,键盘上能打出来的所有标点符号)
|
|
|
$forbiddenChars = [
|
|
|
// 英文标点符号
|
|
|
'/',
|
|
|
'\\',
|
|
|
'.',
|
|
|
',',
|
|
|
';',
|
|
|
':',
|
|
|
"'",
|
|
|
'"',
|
|
|
'?',
|
|
|
'!',
|
|
|
'@',
|
|
|
'#',
|
|
|
'$',
|
|
|
'%',
|
|
|
'^',
|
|
|
'&',
|
|
|
'*',
|
|
|
'(',
|
|
|
')',
|
|
|
'[',
|
|
|
']',
|
|
|
'{',
|
|
|
'}',
|
|
|
'|',
|
|
|
'`',
|
|
|
'~',
|
|
|
'-',
|
|
|
'_',
|
|
|
'+',
|
|
|
'=',
|
|
|
'<',
|
|
|
'>',
|
|
|
// 中文标点符号
|
|
|
'。',
|
|
|
',',
|
|
|
'、',
|
|
|
';',
|
|
|
':',
|
|
|
'?',
|
|
|
'!',
|
|
|
'…',
|
|
|
'—',
|
|
|
'·',
|
|
|
'~',
|
|
|
'¥',
|
|
|
'(',
|
|
|
')',
|
|
|
'【',
|
|
|
'】',
|
|
|
'《',
|
|
|
'》',
|
|
|
'〈',
|
|
|
'〉',
|
|
|
'「',
|
|
|
'」',
|
|
|
'『',
|
|
|
'』',
|
|
|
'〔',
|
|
|
'〕',
|
|
|
];
|
|
|
|
|
|
// 添加中文引号字符(使用十六进制编码避免语法错误)
|
|
|
$chineseQuotes = ["\xE2\x80\x9C", "\xE2\x80\x9D", "\xE2\x80\x98", "\xE2\x80\x99"]; // " " ' '
|
|
|
$forbiddenChars = array_merge($forbiddenChars, $chineseQuotes);
|
|
|
|
|
|
foreach ($forbiddenChars as $char) {
|
|
|
if (strpos($companyName, $char) !== false) {
|
|
|
return ['valid' => false, 'message' => '公司名称不能包含特殊符号'];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return ['valid' => true, 'message' => ''];
|
|
|
}
|
|
|
|
|
|
}
|