urlManagementDb = new UrlManagement();
        $this->urlManagementVisitDb = new UrlManagementVisit();
    }
    
    public function getTitles($oid)
    {
        $ret = $this->urlManagementDb
            ->select([
                'title',
            ]);
        // 權限判斷
        if ($oid != GeneralConst::ID_ADMIN) {
            $ret = $ret
                ->where('oid', '=', $oid);
        }
        $ret = $ret
            ->groupBy('title')
            ->orderBy('serno', 'desc')
            ->get()
            ->toArray();
        
        return $ret;
    }
    
    public function getValids()
    {
        $valids = [];
        foreach (GeneralConst::$urlMap as $k => $v) {
            $valids[] = [
                'id'   => $k,
                'text' => $v,
            ];
        }
        
        return $valids;
    }
    
    public function getUrls(
        &$cnt = 0,
        $orderColumn,
        $orderDir,
        $start,
        $length,
        $searchValue,
        $title,
        $memo,
        $createDateStart,
        $createDateFinal,
        $valid,
        $oid
    )
    {
        // 選欄位
        $validStr = '';
        foreach (GeneralConst::$urlMap as $k => $v) {
            $validStr .= ' when \'' . $k . '\' then \'' . $v . '\'';
        }
        
        $urls = $this->urlManagementDb
            ->select([
                'dataManagement_urlManagement.serno',
                'title',
                \DB::raw("concat('') as url"),
                \DB::raw("concat('') as code"),
                'memo',
                \DB::raw("ifnull(uv_count, 0) as pv"),
                \DB::raw("(case valid $validStr end) as valid"),
                \DB::raw('concat(\'\') as edit'),
                \DB::raw("concat('
') as qrcode"),
                \DB::raw("dataManagement_urlManagement.code as api_code"),
                \DB::raw("concat('" . env('APP_URL') . "/api/inner/qrcode/', dataManagement_urlManagement.code) as api_qrcode"),
            ])
            ->leftjoin(\DB::raw("(select v.code, count(*) as uv_count from dataManagement_urlManagement_visit as v where (cdate >= '" . $createDateStart . " 00:00:00' and cdate <= '" . $createDateFinal . " 23:59:59') group by v.code) as uv"), 'dataManagement_urlManagement.code', '=', 'uv.code');
        // 過濾搜尋條件
        $urls = $urls
            ->where('title', 'LIKE', '%' . $title . '%')
            ->where('memo', 'LIKE', '%' . $memo . '%');
        if ($valid != GeneralConst::URL_ALL) {
            $urls = $urls->where('valid', '=', $valid);
        }
        // 權限判斷
        if ($oid != GeneralConst::ID_ADMIN) {
            $urls = $urls->where('oid', '=', $oid);
        }
        // 取總筆數
        $cnt = $urls->count();
        // 排序
        $urls = $urls
            ->orderByRaw((int)$orderColumn . ' ' . $orderDir);
        // 彙整
        $urls = $urls
            ->groupby('dataManagement_urlManagement.code');
        // 分頁
        $urls = $urls
            ->skip($start)->take($length);
        // 實際取資料
        $urls = $urls
            ->get()
            ->toArray();
        
        // 整理返回值並返回
        return $urls;
    }
    
    public function getDateseg($oid)
    {
        // 取得所有 code
        $codes = $this->urlManagementDb->select(['code']);
        if ($oid != GeneralConst::ID_ADMIN) {
            $codes = $codes->where('oid', '=', $oid);
        }
        $codes = array_map('current', $codes->get()->toArray());
        // 取得依照時間切分的資料
        $datesegs = $this->urlManagementVisitDb->select([
            'code',
            \DB::raw("left(cdate, 10) as date"),
            \DB::raw("count(*) as cnt"),
        ]);
        if ($oid != GeneralConst::ID_ADMIN) {
            $datesegs = $datesegs->whereIn('code', $codes);
        }
        $datesegs = $datesegs
            ->groupby('code', \DB::raw("left(cdate, 10)"))
            ->orderByRaw(\DB::raw("code asc, left(cdate, 10) asc"))
            ->get()->toArray();
        
        // 整理返回值並返回
        return $datesegs;
    }
    
    public function getUrlById($id, $oid)
    {
        // 取得參數
        // 調用資料庫(或者其他業務邏輯)
        $url = $this->urlManagementDb
            ->select([
                'serno',
                'title',
                'url',
                \DB::raw("concat('" . env('ORL_URL') . "', code, '') as code"),
                'memo',
                'valid',
            ]);
        // 權限判斷
        if ($oid != GeneralConst::ID_ADMIN) {
            $url = $url
                ->where('oid', '=', $oid);
        }
        $url = $url
            ->where('serno', $id)
            ->first();
        if (is_null($url)) {
            return [];
        }
        $url = $url->toArray();
        
        // 整理返回值並返回
        return $url;
    }
    
    public function insertUrl($title, $url, $code, $memo, $valid, $oid)
    {
        // 取得參數
        // 調用資料庫(或者其他業務邏輯)
        $this->urlManagementDb
            ->insert([
                'title' => $title,
                'url'   => $url,
                'code'  => $code,
                'memo'  => $memo,
                'valid' => $valid,
                'oid'   => $oid,
            ]);
        $id = \DB::getPdo()->lastInsertId();
        
        // 整理返回值並返回
        return $id;
    }
    
    public function getCode()
    {
        // 調用資料庫(或者其他業務邏輯)
        $code = \DB::select(\DB::raw("SELECT fn_GetCodeNew('34679ACDEFGHJKLMNPQRTUVWXY', '!!!!!') as code"));
        
        // 整理返回值並返回
        return $code[0]->code;
    }
    
    public function modifyUrl($id, $title, $url, $memo, $valid)
    {
        // 取得參數
        // 調用資料庫(或者其他業務邏輯)
        $res = $this->urlManagementDb
            ->where('serno', $id)
            ->update([
                'title' => $title,
                // 'url'   => $url, // 收參數是為求程式碼一致性,但業務邏輯不需更改網址
                'memo'  => $memo,
                'valid' => $valid,
            ]);
        
        // 整理返回值並返回
        return $res;
    }
    
    public function getExportUrls($param, $oid)
    {
        // 選欄位
        $validStr = '';
        foreach (GeneralConst::$urlMap as $k => $v) {
            $validStr .= ' when \'' . $k . '\' then \'' . $v . '\'';
        }
        
        $urls = $this->urlManagementDb
            ->select([
                \DB::raw("concat(url) as url"),
                \DB::raw("concat('" . env('ORL_URL') . "', dataManagement_urlManagement.code) as code"),
                'memo',
                \DB::raw("(case valid $validStr end) as valid"),
                \DB::raw("ifnull(uv_count, 0) as pv"),
            ])
            ->leftjoin(\DB::raw("(select v.code, count(*) as uv_count from dataManagement_urlManagement_visit as v where (cdate >= '" . $param['createDateStart'] . " 00:00:00' and cdate <= '" . $param['createDateFinal'] . " 23:59:59') group by v.code) as uv"), 'dataManagement_urlManagement.code', '=', 'uv.code');
        // 過濾搜尋條件
        $urls = $urls
            ->where('title', 'LIKE', '%' . $param['title'] . '%')
            ->where('memo', 'LIKE', '%' . $param['memo'] . '%');
        if ($param['valid'] != GeneralConst::URL_ALL) {
            $urls = $urls->where('valid', '=', $param['valid']);
        }
        // 權限判斷
        if ($oid != GeneralConst::ID_ADMIN) {
            $urls = $urls->where('oid', '=', $oid);
        }
        // 彙整
        $urls = $urls
            ->groupby('dataManagement_urlManagement.code');
        // 實際取資料
        $urls = $urls
            ->get()
            ->toArray();
        
        // 整理返回值並返回
        return $urls;
    }
    
    public function downloadExcel($titles = [], $datas = [], $fileName = 'simple')
    {
        $spreadsheet = new Spreadsheet();
        ini_set('memory_limit', '1024M');
        ini_set("max_execution_time", "600");
        $spreadsheet->getActiveSheet()
            ->fromArray(
                $titles, // The data to set
                null, // Array values with this value will not be set
                'A1' // Top left coordinate of the worksheet range where we want to set these values (default is A1)
            );
        
        $spreadsheet->getActiveSheet()
            ->fromArray(
                $datas, // The data to set
                null, // Array values with this value will not be set
                'A2' // Top left coordinate of the worksheet range where we want to set these values (default is A1)
            );
        
        // Redirect output to a client’s web browser (Xlsx)
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"');
        header('Cache-Control: max-age=0');
        // If you're serving to IE 9, then the following may be needed
        header('Cache-Control: max-age=1');
        
        // If you're serving to IE over SSL, then the following may be needed
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
        header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
        header('Pragma: public'); // HTTP/1.0
        
        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
        exit;
    }
    
}