| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238 | <?php/** * Created by PhpStorm. * User: Administrator * Date: 2019/4/17 0017 * Time: 16:27 */namespace App\Http\Controllers\Admin;use App\Exports\BasicExport;use App\Http\Controllers\Controller;use App\Http\Logics\Admin\ArticleLogic;use App\Http\Models\Article;use App\Http\Models\ArticleLinkNotice;use App\Http\Models\ArticleNote;use App\Http\Models\ArticleSiteKeep;use App\Http\Models\ArticleSocial;use App\Http\Models\Role;use App\Http\Models\Site;use App\Http\Models\SiteEnterprise;use App\Http\Models\SiteInfo;use App\Http\Models\User;use App\Http\Requests\Article\ArticleRequest;use App\Http\Requests\Article\ArticleTranslateRequest;use App\Http\Traits\HasSites;use Illuminate\Database\Eloquent\Builder;use Illuminate\Http\Request;use Illuminate\Support\Facades\Auth;use GuzzleHttp\Client;use GuzzleHttp\Pool;use GuzzleHttp\Psr7\Response;use App\Http\Requests\Article\ArticleSyncRequest;use Illuminate\Support\Facades\DB;use Illuminate\Support\Facades\Log;use Illuminate\Contracts\View\Factory;use Illuminate\Http\JsonResponse;use Illuminate\View\View;/** * 软文控制器 * Class ArticleController * @package App\Http\Controllers\Admin */class ArticleController extends Controller{    use HasSites;    protected $logic;    const STATUS = [        1 => '待翻译',        2 => '翻译中',        3 => '待审核',        4 => '审核不通过',        5 => '审核通过',    ];    public function __construct(ArticleLogic $logic)    {        $this->logic = $logic;    }    /**     * 首页     * @param Request $request     * @return Factory|JsonResponse|View     */    public function index(Request $request)    {        if (!$request->ajax()) {            return view('admin/article/index');        }		$userSite = $this->hasUserOneSite();		$idaa = $userSite->id;        $siteTitle = $request->input('site_title');        $beApplicable = $request->input('be_applicable');        if (isset($beApplicable)) {            $condition[] = ['be_applicable', '=', $beApplicable];			$condition[] = ['site_id', '=', $idaa];        }        $status = $request->input('status');        if (!empty($status) && $status != 7) {            $condition[] = ['status', '=', $status];        }        $beApplicable = $request->input('beApplicable');        if (isset($beApplicable)) {            $condition[] = ['be_applicable', '=', $beApplicable];			$condition[] = ['site_id', '=', $idaa];        }        $builder = Article::query()->scopes(['user'])->whereHas('site', function (Builder $builder) use ($siteTitle, $status) {            if ($siteTitle) {                $builder->where('cn_title', 'like', '%' . $siteTitle . '%');            }            if ($status == 7) {                $builder->where('status', $status);            }        })->with(['translator']);        if ($siteId = $request->input('siteId')) {            $condition[] = ['site_id', '=', $siteId];        }        if ($keyword = $request->input('keyword')) {            $condition[] = ['title', 'like', '%' . $keyword . '%'];        }        $articles = $builder->where($condition ?? [])->orderByDesc('id')            ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $articles->items();        array_walk($items, function ($item) {            $item->status_title = $item->status_with_css;            $item->site_title = $item->site->cn_title ?? '';            $item->translator_name = $item->translator->username ?? '';            $item->be_applicable = $item->check_status_with_css;            if (!empty($item->publish_at)) {                $item->publish_at = date('Y-m-d', strtotime($item->publish_at));            }        });        return response()->json([            'rows' => $items,            'total' => $articles->total()        ]);    }    /**     * 项目管理详情中的软文列表     * @param Request $request     * @param $id     * @return Factory|JsonResponse|View     */    public function siteArticles(Request $request, $id)    {        if (!$request->ajax()) {            $start = date('Y-m-01 00:00:00');            $end = date('Y-m-t 23:59:59');            $siteInFo = SiteInfo::query()->where('site_id', $id)->first();            $count = Article::query()->where('site_id', $id)->where('be_applicable', 1)->count();            $site = Site::query()->where('id', $id)->first();            $pendingUpgrade = Article::query()->where('site_id', $id)->where('be_applicable', 1)->whereNull('publish_at')->count() ?? 0;            $thisMonthUpgrade = Article::query()->where('site_id', $id)->whereBetween('publish_at', [$start, $end])->count() ?? 0;            return view('admin/article/site_article', [                'siteId' => $id,                'siteInFo' => $siteInFo,                'count' => $count,                'pendingUpgrade' => $pendingUpgrade,                'thisMonthUpgrade' => $thisMonthUpgrade,                'site' => $site,            ]);        }        $builder = Article::query()->with(['site', 'translator']);        $sortName = $request->input('sortName');        $sortOrder = $request->input('sortOrder');        if (!empty($sortName) && !empty($sortOrder)) {            $builder->orderBy($sortName, $sortOrder);        }        $condition[] = ['site_id', '=', $id];        $condition[] = ['be_applicable', '=', 1];        if ($status = $request->input('status')) {            $condition[] = ['status', '=', $status];        }        if ($keyword = $request->input('keyword')) {            $condition[] = ['title', 'like', '%' . $keyword . '%'];        }        $articles = $builder->where($condition ?? [])->orderByDesc('id')            ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $articles->items();        array_walk($items, function ($item) {            $item->status_title = $item->status_with_css;            $item->site_title = $item->site->cn_title ?? '';            $item->translator_name = $item->translator->username ?? '';        });        return response()->json([            'rows' => $items,            'total' => $articles->total()        ]);    }    /**     * 保存软文每月更新数     * @param Request $request     * @return JsonResponse     */    public function articlesUpdatesPerMonth(Request $request)    {        $siteId = $request->input('siteId');        $articlesUpdatesPerMonth = $request->input('articlesUpdatesPerMonth') ?? 4;        $renewalQuantity = $request->input('article_renewal_quantity') ?? 0;        Site::query()->where('id', $siteId)->update(['articles_updates_per_month' => $articlesUpdatesPerMonth, 'article_renewal_quantity' => $renewalQuantity]);        return response()->json(['message' => '操作成功']);    }    /**     * 文章详情     * @param Request $request     * @param $id     * @return Factory|View     */    public function detail(Request $request, $id)    {        $article = Article::query()->find($id);        if ($article) {            $site = Site::query()->select(['id', 'cn_title', 'en_title', 'domain'])->where(['id' => $article->site_id])->first();            $siteEnterprise = SiteEnterprise::query()->select(['brand'])->where(['site_id' => $article->site_id])->first();        }        return view('admin/article/detail', [            'data' => $article,            'referer' => $request->input('referer'),            'site' => $site ?? null,            'siteEnterprise' => $siteEnterprise ?? null        ]);    }    /**     * 文章添加保存     * @param ArticleRequest $request     * @param $id     * @return Factory|JsonResponse|View     */    public function save(ArticleRequest $request, $id)    {        if (!$request->ajax()) {            if ($id > 0) {                $article = Article::query()->where(['id' => $id])->first();            } else { //添加 [选中默认的站点]                if ($siteId = $request->input('siteId')) {                    $siteKeep = (object)['site_id' => $siteId];                } else {                    $siteKeep = ArticleSiteKeep::query()->where(['user_id' => Auth::id()])->first();                }            }            $insider = User::query()->select(['id', 'username', 'nickname'])->find(Article::INSIDER);            $translators = Role::getUsers(Role::TYPE_ARTICLE_PART);            if ($insider) {                $translators->prepend($insider);            }            return view('admin/article/save', [                'data' => $article ?? null,                'sites' => $this->userSites(),                'translators' => $translators,                'siteKeep' => $siteKeep ?? null            ]);        }        $validated = $request->validated();        if ($validated['translator_id'] != Article::INSIDER && empty($validated['content'])) {            return response()->json(['message' => '正文不能为空'], 400);        }        if (!empty($validated['translate_content'])) {            $validated['translate_content'] = del_domain_from_src($validated['translate_content']);        }        if (empty($validated['thumb'])) {            $siteInfo = SiteInfo::query()->select(['is_upload_thumb'])->where(['site_id' => $validated['site_id']])->first();            if (!empty($siteInfo->is_upload_thumb)) {                return response()->json(['message' => '缩略图站点设置必填 不能为空'], 400);            }        }        return $this->logic->save($validated, $id);    }    /**     * 文章同步     * @param ArticleSyncRequest $request     * @param $id     * @return Factory|JsonResponse|View     */    public function sync(ArticleSyncRequest $request, $id)    {        $site = Site::query()->where(['id' => $id])->first();        if (!$site) return response()->json(['message' => '站点信息不存在'], 400);        if (!$request->ajax()) {            $taskUrls = [sprintf('%scontent/getOptsByJson', $site->api_url), sprintf('%scontent/getTplsByJson', $site->api_url)];            $client = new Client([                'verify' => false,                'timeout' => 100,            ]); //并发请求链接地址            $requests = function () use ($client, $taskUrls) {                foreach ($taskUrls as $item) {                    if (empty($item))                        continue;                    yield new \GuzzleHttp\Psr7\Request('GET', $item);                }            };            $rejected = false; //  默认没有被拒绝            $result = [];            $pool = new Pool($client, $requests(), [                'concurrency' => 2, //同时并发抓取几个                'fulfilled' => function (Response $response, $index) use (&$result) {                    $temp = $response->getBody()->getContents();                    $temp = trim($temp, "\xEF\xBB\xBF");                    $result[$index] = json_decode($temp, true);                },                'rejected' => function (\Throwable $throwable, $index) use (&$rejected, &$site) {                    Log::error(var_export($throwable->getMessage(), 1));//                    Log::error(sprintf('%scontent/getOptsByJson', $site->api_url));//                    Log::error(sprintf('%scontent/getTplsByJson', $site->api_url));                    $rejected = true; //接口错误                },            ]);            $promise = $pool->promise();            $promise->wait();            if ($rejected) { //如果接口错误提示                return view('admin/errors/tips', [                    'tips' => 'api接口异常(请检查项目概况-基本信息-api地址是否填写正确',                    'closeBtn' => 1                ]);            }            return view('admin/article/sync', [//                'remoteContent' => array_values($content),                'remoteContent' => array_values($result[0]),//                'removeTemplate' => $template,                'removeTemplate' => $result[1],                'articles' => Article::query()->whereIn('id', $request->input('articleIds'))->select(['id', 'title'])->get(),                'siteId' => $id            ]);        }        $server = $site->server;        if (empty($server)) return response()->json(['message' => '站点服务器信息不存在'], 400);        return $this->logic->sync($request->validated(), $site, $server);    }    /**     * 文章认领     * @param $id     * @return JsonResponse     */    public function claim($id)    {        $article = Article::query()->where(['id' => $id])->first();        if (!$article) {            return response()->json(['message' => '文章信息不存在'], 400);        }        if ($article->translator_id) {            return response()->json(['message' => '此文章已被认领'], 400);        }        if ($article->status != 1) {            return response()->json(['message' => '此文章不属于待翻译状态'], 400);        }        if (Auth::id() != Article::IS_EXPIRED) {            if (Article::query()->where(['translator_id' => Auth::id()])                    ->whereIn('status', [Article::STATUS_TRANSLATING, Article::STATUS_FAILED])->count() >= 10) {                return response()->json(['message' => '一个用户最多只有10个翻译文章'], 400);            }        }        $article->status = Article::STATUS_TRANSLATING;        $article->translator_id = Auth::id();        $article->expired_at = date('Y-m-d H:i:s', strtotime('+1 day'));        $article->save();        return response()->json(['message' => '操作成功']);    }    /**     * 我要翻译     * @param ArticleTranslateRequest $request     * @param $id     * @return Factory|JsonResponse|View     */    public function translate(ArticleTranslateRequest $request, $id)    {        if (!$request->ajax()) {            $article = Article::query()->where(['id' => $id])->first();            return view('admin/article/hall_translate', [                'data' => $article,                'site' => Site::query()->select(['cn_title', 'en_title', 'domain'])->find($article->site_id),                'siteEnterprise' => SiteEnterprise::query()->select(['brand'])->find($article->site_id)            ]);        }        $article = Article::query()->where(['id' => $id])->first();        if (!$article) return response()->json(['message' => '文章信息不存在'], 400);        $validated = $request->validated();        if ($request->input('admin')) {            if (empty($validated['thumb'])) {                $siteInfo = SiteInfo::query()->select(['is_upload_thumb'])->where(['site_id' => $article->site_id])->first();                if (!empty($siteInfo->is_upload_thumb)) {                    return response()->json(['message' => '缩略图站点设置必填 不能为空'], 400);                }            }            if (!$validated['translate_title2']) {                $str = preg_replace("/[^a-zA-Z0-9\s]/", "", $validated['translate_title']);                $validated['translate_title2'] = strtolower(preg_replace("/\s+/", "-", $str));            }        } else {            unset($validated['translate_title2'], $validated['thumb']);        }        $validated['translate_words'] = word_count($validated['translate_title']) + word_count($validated['translate_content']);        $validated['translate_content'] = del_domain_from_src($validated['translate_content']);        $validated['translate_submit_at'] = date('Y-m-d H:i:s');        $article->update($validated);        return response()->json(['message' => '操作成功']);    }    /**     * 批量审核通过     * @param Request $request     * @return JsonResponse     */    public function batchPass(Request $request)    {        $user = Auth::user();        $passScore = $request->input('passScore') ?? 0;        $ids = $request->input('ids');        Article::query()->whereIn('id', $ids)->where(['status' => Article::STATUS_AUDITING])->update([            'status' => Article::STATUS_PASSED,            'audit_at' => date('Y-m-d H:i:s'),            'auditor_id' => $user->id,            'auditor_name' => $user->nickname,            'pass_score' => $passScore        ]);        return response()->json(['message' => '操作成功']);    }    /**     * 批量审核不通过     * @param Request $request     * @return JsonResponse     */    public function batchNoPass(Request $request)    {        $ids = $request->input('ids');        Article::query()->whereIn('id', $ids)->where(['status' => Article::STATUS_AUDITING])->update([            'status' => Article::STATUS_FAILED,            'fail_reason' => $request->input('fail_reason')        ]);        return response()->json(['message' => '操作成功']);    }    /**     * 释放任务     * @param $id     * @return JsonResponse     */    public function release($id)    {        $article = Article::query()->where(['id' => $id])->first();        if (!$article) return response()->json(['message' => '文章信息不存在'], 400);        if (!in_array($article->status, [Article::STATUS_TRANSLATING, Article::STATUS_FAILED])) {            return response()->json(['message' => '此文章不属于翻译中或审核失败状态'], 400);        }        $article->update([            'status' => 1,// 待翻译            'translator_id' => 0,            'translate_title' => $article->init_tran_title,            'translate_words' => word_count($article->init_tran_content) + word_count($article->init_tran_title),            'translate_content' => $article->init_tran_content,            'expired_at' => null        ]);        return response()->json(['message' => '操作成功']);    }    //软文注意事项    public function notice(Request $request)    {        if (!$request->ajax()) {            $data = ArticleLinkNotice::query()->where(['type' => 'article'])->first();            return view('admin/article/notice', [                'data' => $data ?? ''            ]);        }        ArticleLinkNotice::query()->where(['type' => 'article'])->update([            'content' => $request->input('content')        ]);        return response()->json(['message' => '操作成功']);    }    /**     * 任务大厅     * @param Request $request     * @return Factory|JsonResponse|View     */    public function hall(Request $request)    {        if (!$request->ajax()) {            Article::query()->whereIn('status', [Article::STATUS_TRANSLATING])                ->where([['expired_at', '<', date('Y-m-d H:i:s')]])->update([                    'translator_id' => 0,                    'expired_at' => null,                    'status' => Article::STATUS_PENDING                ]); //检测是否有翻译中且已过期的 将其释放任务//            $haveNotSettle = Article::query()->where(['translator_id' => Auth::id()])->where('status', 5)->get();//            $settleHistory = Article::query()->where(['translator_id' => Auth::id()])->where('status', 6)->get()->groupBy('audit_at');            return view('admin/article/hall', [                'notice' => ArticleLinkNotice::query()->where(['type' => 'article'])->first(),//                'settleHistory' => $settleHistory,//                'haveNotSettle'=>$haveNotSettle            ]);        }        $builder = Article::query()->where('be_applicable', 1)->with(['site', 'translator']);        if ($status = $request->input('status') ?? 1) {            $condition[] = ['status', '=', $status];        }        if ($status != Article::STATUS_PENDING) { //任务大厅可以看到未分配的文章            $condition[] = ['translator_id', '=', Auth::id()];        }        if ($keyword = $request->input('keyword')) {            $builder->where(function (Builder $query) use ($keyword) {                $query->where('title', 'like', '%' . $keyword . '%');                $query->orWhere('id', 'like', $keyword);            });        }        $articles = $builder->where($condition ?? [])->orderByDesc('id')            ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $articles->items();        array_walk($items, function ($item) {            $item->status_title = $item->status_with_css;            $item->site_title = $item->site->cn_title ?? '';            $item->translator_name = $item->translator->username ?? '';        });        return response()->json([            'rows' => $items,            'total' => $articles->total()        ]);    }    //任务大厅详情    public function hallDetail($articleId)    {        $article = Article::query()->where(['id' => $articleId])->first();        if (!$article) {            return abort(404, '数据不存在');        }        return view('admin/article/hall_detail', [            'data' => $article,            'site' => Site::query()->select(['cn_title', 'en_title', 'domain'])->find($article->site_id),            'siteEnterprise' => SiteEnterprise::query()->select(['brand'])->find($article->site_id),            'siteInfo' => SiteInfo::query()->selectRaw('article_pt_remark')->where(['site_id' => $article->site_id])->first()        ]);    }    //批量删除    public function batchDelete(Request $request)    {        $ids = $request->input('ids');        Article::destroy($ids);        return response()->json(['message' => '操作成功']);    }    //批量更新发布时间    public function batchPublished(Request $request)    {        $ids = $request->input('ids');        Article::query()->whereIn('id', $ids)->update([            'publish_at' => date('Y-m-d H:i:s')        ]);        return response()->json(['message' => '操作成功']);    }    //批量更新状态    public function batchUpdate(Request $request)    {        $ids = $request->input('ids');        Article::query()->whereIn('id', $ids)->update([            'status' => 1,        ]);        return response()->json(['message' => '操作成功']);    }    //推送消息至app    public function pushMessage(Request $request)    {        $siteId = $request->input('siteId');        DB::table('articles_notice')->insert(['site_id' => $siteId]);        return response()->json(['message' => '操作成功']);    }    /**     * 任务结算列表     * @param Request $request     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View     */    public function calc(Request $request)    {        if (!$request->ajax()) {            return view('admin/article/calc');        }        $builder = Article::query()->where(['status' => Article::STATUS_PASSED]);        if ($startAt = $request->input('start_at')) {            $builder->whereDate('created_at', '>', $startAt);        }        if ($endAt = $request->input('end_at')) {            $builder->whereDate('created_at', '<', $endAt);        }        // 注意 group_concat长度限制        $data = $builder->whereHas('translator', function (Builder $query) use ($request) {            if ($username = $request->input('username')) {                $query->where('username', 'like', '%' . $username . '%');            }        })->selectRaw('SUM(translate_words) AS totalWords,translator_id,GROUP_CONCAT(id) as article_ids,GROUP_CONCAT(id) as article_ids')            ->groupBy('translator_id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $data->items();        array_walk($items, function ($item) {            $item->article_ids = explode(',', $item->article_ids);            $scoreList = Article::query()->selectRaw('id,pass_score')->whereIn('id', $item->article_ids)                ->whereNotNull('pass_score')->get();            $totalScore = 0;            foreach ($scoreList as $score) {                $totalScore += $score->pass_score;            }            $item->avgScore = $scoreList->count() < 1 ? 0 : ($totalScore / $scoreList->count());            $item->amount = $this->logic->amountRule($item->totalWords);            $item->username = $item->translator->username ?? '';            unset($item->translator);        });        return response()->json([            'rows' => $items,            'total' => $data->total()        ]);    }    // 结算历史    public function calcHistory(Request $request)    {        if (!$request->ajax()) {            return view('/admin/article/calc_history');        }        $condition = [['status', '=', 6]];        if ($start_at = $request->input('start_at')) {            $condition[] = ['audit_at', '>=', $start_at];        }        if ($end_at = $request->input('end_at')) {            $condition[] = ['audit_at', '<=', $end_at];        }        if ($keyword = $request->input('keyword')) {            $condition[] = ['title', 'like', '%' . $keyword . '%'];        }        $data = Article::query()->with(['translator'])->where($condition)->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $data->items();        $totalAmount = 0;        array_walk($items, function ($item) use (&$totalAmount) {            $item->amount = $item->settle_amount;            $item->username = $item->translator->username ?? '';            $totalAmount = bcadd($totalAmount, $item->settle_amount, 2);        });        return response()->json([            'rows' => $items,            'total' => $data->total(),            'totalAmount' => $totalAmount        ]);    }    /***     * 有道翻译自动翻译     * @param Request $request     * @return \Illuminate\Http\JsonResponse     */    public function autoTranslate(Request $request)    {        $ids = $request->input('ids');        $articles = Article::query()->where(['status' => 1])            ->whereIn('id', $ids)->get();        return $this->logic->autoTranslate($articles);    }    /**     * 文章结算     * @param Request $request     * @return \Illuminate\Http\JsonResponse     */    public function settle(Request $request)    {        $records = Article::query()->whereIn('id', $request->input('ids'))->get();        $settleAt = date('Y-m-d H:i:s');        foreach ($records as $record) {            $record->update([                'status' => Article::STATUS_CALC, //已结算                'settle_amount' => $this->logic->amountRule($record->translate_words),                'settle_at' => $settleAt            ]);        }        return response()->json(['message' => '操作成功']);    }    //好像没用了    public function syncSocial(Request $request)    {        $article = Article::query()->whereIn('id', $request->input('ids'))->first();        $date = date('Y-m-d H:i:s');        $update = ['article_id' => $article->id];        if ($this->logic->linkedIn($article->translate_content)) {            $update['linked_sync_at'] = $date;        }        ArticleSocial::query()->updateOrCreate(['article_id' => $article->id], $update);        return response()->json(['message' => '操作成功']);    }    //项目管理中下的软文管理 保存    public function saveInfo(Request $request)    {        $article_custom_audit = $request->input('article_custom_audit') == 'true' ? 1 : 0;        $is_upload_thumb = $request->input('is_upload_thumb') == 'true' ? 1 : 0;        $article_remark = $request->input('article_remark');        $article_pt_remark = $request->input('article_pt_remark');        $article_need_num = $request->input('article_need_num');        $outside_update_platform = $request->input('outside_update_platform');        $siteId = $request->input('siteId');        if (!$siteId) {            return response()->json(['message' => '参数错误'], 400);        }        $data = [            'site_id' => $siteId,            'is_upload_thumb' => $is_upload_thumb,            'article_custom_audit' => $article_custom_audit,            'article_remark' => $article_remark,            'outside_update_platform' => $outside_update_platform,            'article_pt_remark' => $article_pt_remark,            'article_need_num' => $article_need_num,        ];        $info = SiteInfo::query()->where(['site_id' => $siteId])->first();        if ($info) {            $info->update($data);        } else {            SiteInfo::query()->create($data);        }        return response()->json(['message' => '操作成功']);    }    //软文任务审核    public function auditWord(Request $request)    {        if (!$request->ajax()) {            return view('admin/article/audit_word');        }        $builder = Article::query()->where(['status' => Article::STATUS_PASSED]);        if ($startAt = $request->input('start_at')) {            $builder->whereDate('created_at', '>', $startAt);        }        if ($endAt = $request->input('end_at')) {            $builder->whereDate('created_at', '<', $endAt);        }        // 注意 group_concat长度限制        $data = $builder->whereHas('auditor', function (Builder $query) use ($request) {            if ($username = $request->input('username')) {                $query->where('username', 'like', '%' . $username . '%');            }        })->selectRaw('SUM(translate_words) AS totalWords')            ->groupBy('auditor_id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $data->items();        return response()->json([            'rows' => $items,            'total' => $data->total()        ]);    }    //近三月趋势图    public function trend()    {        $auditData = $queryData = $xAxis = [];        for ($i = 1; $i <= 3; $i++) {            $xAxis[] = date('Y年m月', strtotime('first day of - ' . $i . 'month'));            $beginAt = date('Y-m-01 00:00:00', strtotime('first day of - ' . $i . 'month'));            $endAt = date('Y-m-t 23:59:59', strtotime('first day of - ' . $i . 'month'));            $queryData[] = Article::query()->where([['created_at', '>=', $beginAt], ['created_at', '<=', $endAt]])->count();            $auditData[] = Article::query()->where([['audit_at', '>=', $beginAt], ['audit_at', '<=', $endAt]])->count();        }        $data = [            'xAxis' => $xAxis,            'queryData' => $queryData,            'auditData' => $auditData,        ];        return view('admin.article.trend', [            'line' => $data        ]);    }    //特殊软文 有撰写人员的    public function spec(Request $request)    {        if (!$request->ajax()) {            return view('admin/article/spec');        }        $records = Site::query()->withCount('articles')->with(['users'])->where(['spec_article' => 1])            ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $result = [];        foreach ($records as $record) {            $result[] = [                'cn_title' => $record->cn_title,                'domain' => $record->domain,                'status_title' => Site::STATUS_MAP[$record->status] ?? '',                'article_goal' => $record->article_goal,                'articles_count' => $record->articles_count,                'editor' => implode(',', $record->users->where('role_id', Role::TYPE_PROPAGANDA)->pluck('nickname')->toArray())            ];        }        return response()->json([            'rows' => $result,            'total' => $records->total()        ]);    }    //软文备注    public function siteArticlesNote(Request $request, $siteId)    {        if (!$request->ajax()) {            $note = ArticleNote::query()->where(['site_id' => $siteId])->first();            return view('admin.article.note', [                'siteId' => $siteId,                'data' => $note,            ]);        }        $content = $request->input('content');        $note = ArticleNote::query()->where(['site_id' => $siteId])->first();        if ($note) {            $note->update(['content' => $content]);        } else {            ArticleNote::query()->create([                'site_id' => $siteId,                'content' => $content,            ]);        }        return response()->json(['message' => '操作成功']);    }    //软文查找    public function siteArticlesFind(Request $request, $id)    {        if (!$request->ajax()) {            $siteInFo = SiteInfo::query()->where('site_id', $id)->first();            $mobile = DB::table('site_mobile')->where('site_id', $id)->value('mobile') ?? '';            return view('admin/article/find', [                'siteId' => $id,                'siteInFo' => $siteInFo,                'mobile' => $mobile            ]);        }        $builder = Article::query()->with(['translator']);        $condition[] = ['site_id', '=', $id];        $beApplicable = $request->input('beApplicable');        if (isset($beApplicable)) {            $condition[] = ['be_applicable', '=', $beApplicable];        }        $status = $request->input('status');        if (isset($status)) {            $condition[] = ['status', '=', $status];        }        $title = $request->input('title');        if (!empty($title)) {            $condition[] = ['title', 'like', $title . '%'];        }        $userList = User::query()->where('status', 1)->pluck('nickname', 'id') ?? [];        $articles = $builder->where($condition ?? [])->orderByDesc('id')            ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $articles->items();        array_walk($items, function ($item) use ($userList) {            $item->translator_name = $item->translator->username ?? '';            $item->check = $item->check_status_with_css;            $item->status_title = $item->status_with_css;            $item->reviewer = $userList[$item->reviewer_id] ?? '';        });        return response()->json([            'rows' => $items,            'total' => $articles->total()        ]);    }    //批量适用    public function batchBeApplicable(Request $request, $siteId)    {        $ids = $request->input('ids');        $type = $request->input('type');        Article::query()->where('site_id', $siteId)            ->whereIn('id', $ids)            ->update(['be_applicable' => $type, 'reviewer_id' => Auth::id()]);        return response()->json(['message' => '操作成功']);    }    //待定    public function toBeDetermined(Request $request, $siteId)    {        $id = $request->input('id');        $type = $request->input('type');        Article::query()->where('site_id', $siteId)            ->where('id', $id)            ->update(['be_applicable' => $type, 'reviewer_id' => Auth::id()]);        return response()->json(['message' => '操作成功']);    }    public function notApplicableWherefore(Request $request, $siteId)    {        $id = $request->input('id');        $notBeApplicableInfo = $request->input('notBeApplicableInfo');        Article::query()->where('site_id', $siteId)            ->where('id', $id)            ->update(['not_be_applicable_info' => $notBeApplicableInfo, 'reviewer_id' => Auth::id()]);        return response()->json(['message' => '操作成功']);    }    //任务大厅结算历史    public function hallCalcHistory(Request $request)    {        if (!$request->ajax()) {            return view('admin/article/hall_calc_history');        }        $condition = [['translator_id', '=', Auth::id()], ['status', '=', 6]];        if ($start_at = $request->input('start_at')) {            $condition[] = ['audit_at', '>=', $start_at];        }        if ($end_at = $request->input('end_at')) {            $condition[] = ['audit_at', '<=', $end_at];        }        if ($keyword = $request->input('keyword')) {            $condition[] = ['title', 'like', '%' . $keyword . '%'];        }        $data = Article::query()->with(['translator'])->where($condition)->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);        $items = $data->items();        $totalAmount = 0;        array_walk($items, function ($item) use (&$totalAmount) {            $item->amount = $item->settle_amount;            $item->username = $item->translator->username ?? '';        });        return response()->json([            'rows' => $items,            'total' => $data->total(),            'totalAmount' => $totalAmount        ]);    }    //项目详情-软文概述    public function siteArticlesOverview(Request $request, $id)    {        if (!$request->ajax()) {            list($siteInfo, $data, $result, $scope) = $this->softArticleSummaryStatistics($id);            return view('admin/article/articles_overview', [                'data' => $data,                'siteId' => $siteInfo->id,                'result' => $result,                'scope' => $scope            ]);        }    }    //软文概况    public function articleOverview(Request $request)    {        if (!$request->ajax()) {            $userSite = $this->hasUserOneSite();            if (!$userSite) {                return view('admin/errors/tips', [                    'tips' => '站点信息不存在'                ]);            }            list($siteInfo, $data, $result, $scope) = $this->softArticleSummaryStatistics($userSite->id);            return view('admin/article/article_overview', [                'data' => $data,                'siteId' => $siteInfo->id,                'result' => $result,                'scope' => $scope            ]);        }    }    public function softArticleSummaryStatistics($siteId)    {        $siteIno = Site::query()->where('id', $siteId)->first();        $published = Article::query()->where('site_id', $siteIno->id)->whereNotNull('publish_at')->count() ?? 0;        $unpublished = Article::query()->where('site_id', $siteIno->id)->whereNull('publish_at')->count() ?? 0;        $thisMonth = Article::query()                ->whereBetween('publish_at', [date('Y-m-01 00:00:00'), date('Y-m-t 23:59:59')])                ->where('site_id', $siteIno->id)->whereNotNull('publish_at')->count() ?? 0;        $pending = Article::query()->where('site_id', $siteIno->id)                ->where('be_applicable', 0)                ->whereNull('publish_at')->count() ?? 0;        $needToPublish = $siteIno->articles_updates_per_month ?? 0 - $published;        if ($needToPublish < 0) {            $needToPublish = 0;        }        $data = [            'xAxis' => $list = [                '合同数', '实际需发布软文数', '软文扣除数', '已发布数', '未发数', '本月需发数', '本月已发数', '待审核数'            ],            'yAxis' => $list1 = [                $siteIno->article_goal, $siteIno->article_goal - $siteIno->article_difference, $siteIno->article_difference, $published, $unpublished, $needToPublish, $thisMonth, $pending            ]        ];        $info = DB::table('site_articles_info')->where('site_id', $siteIno->id)->first();        $authUser = auth()->user();        if ($authUser->is_super || in_array($authUser->role_id, [Role::TYPE_MANAGE_LEADER])) {            $scope = true;        } else {            $scope = false;        }        $result = [            'optimizeDataScopeList1' => json_decode($info->content_one ?? '', true) ?? [],            'optimizeDataScopeList2' => json_decode($info->content_two ?? '', true) ?? [],            'memo' => json_decode($info->memo ?? '', true) ?? [],        ];        return [$siteIno, $data, $result, $scope];    }    //保存软文概述    public function saveSoftArticleOverview(Request $request, $siteId)    {        $dataList1 = $request->input('dataList1') ?? [];        $dataList2 = $request->input('dataList2') ?? [];        $insertData['site_id'] = $siteId;        if (!empty($dataList1)) {            $insertData['content_one'] = \GuzzleHttp\json_encode($dataList1);        }        if (!empty($dataList2)) {            $insertData['content_two'] = \GuzzleHttp\json_encode($dataList2);        }        DB::table('site_articles_info')->where('site_id', $siteId)->delete();        DB::table('site_articles_info')->insert($insertData);        return response()->json(['message' => '操作成功']);    }    //中文文章    public function chineseArticle(Request $request)    {        $userSite = $this->hasUserOneSite();        if (!$userSite) {            return view('admin/errors/tips', [                'tips' => '站点信息不存在'            ]);        }        $id = $userSite->id;        $siteIno = Site::query()->with(['users'])->where('id', $id)->first();        if (!$request->ajax()) {            return view('admin/article/chinese_article', [                'siteId' => $siteIno->id,            ]);        }    }    //英文文章    public function englishArticle(Request $request)    {        $userSite = $this->hasUserOneSite();        if (!$userSite) {            return view('admin/errors/tips', [                'tips' => '站点信息不存在'            ]);        }        $id = $userSite->id;        $siteIno = Site::query()->with(['users'])->where('id', $id)->first();        if (!$request->ajax()) {            return view('admin/article/english_article', [                'siteId' => $siteIno->id,            ]);        }    }    //导出    public function export(Request $request, $siteId)    {        $article = Article::query();        $ids = $request->input('ids');        if ($ids) {            $id = explode(',', $ids);            $article->whereIn('id', $id);        }        $list = $article->where('site_id', $siteId)            ->orderBy('id', 'desc')            ->select('id', 'status', 'publish_at', 'title', 'content', 'translate_title', 'translate_content', 'created_at', 'be_applicable')->get();        $dataList = [];        foreach ($list as $item) {            $beApplicable = '待定';            if ($item->be_applicable == 1) {                $beApplicable = '适用';            }            if ($item->be_applicable == 2) {                $beApplicable = '不适用';            }            $data = [                'id' => $item->id,                'be_applicable' => $beApplicable,                'status' => self::STATUS[$item->status],                'created_at' => $item->created_at,                'publish_at' => $item->publish_at,                'title' => $item->title,                'content' => str_replace(' ', '', strip_tags($item->content)),                'translate_title' => $item->translate_title,                'translate_content' => str_replace(' ', '', strip_tags($item->translate_content)),            ];            $dataList[] = $data;        }        array_unshift($dataList, ['编号', '客户审核状态', '翻译状态', '创建时间', '发布时间', '中文标题', '中文内容', '英文标题', '英文内容']);        return (new BasicExport($dataList))->download(sprintf('软文列表%s.xls', date('YmdHis')));    }    public function pushMobileMessage(Request $request)    {        $mobile = $request->input('mobile');        $type = $request->input('type');        if (empty($mobile)) {            return response()->json(['message' => '请填写手机号'], 400);        }        if (!preg_match("/^1[3456789]\d{9}$/", $mobile)) {            return response()->json(['message' => '手机号输入有误'], 400);        }        $siteId = $request->input('siteId');        $info = DB::table('site_mobile')->where('site_id', $siteId)->first();        if (empty($info)) {            DB::table('site_mobile')->insert(['site_id' => $siteId, 'mobile' => $mobile]);        }        DB::table('site_mobile')->where('site_id', $siteId)->update(['mobile' => $mobile]);        //1软文审核 2月报推送        if ($type == 1) {            $tpl = 'SMS_217408472';        } else {            $tpl = 'SMS_217438615';        }        try {            $url = 'http://translate.api.yinqingli.net/openapi/Msg/Msg';            $data = [                'mobile' => $mobile,                'tpl' => $tpl,            ];            $client = new Client();            $response = $client->post($url, [                'form_params' => $data,            ]);            $result = $response->getBody()->getContents();            return response()->json(['message' => '操作成功']);        } catch (\Throwable $exception) {            return response()->json(['message' => 'error'], 400);        }    }}
 |