123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- <?php
- namespace app\api\controller;
- use app\common\constant\CommonConstant;
- use app\common\constant\MaintainConstant;
- use app\common\model\Goods;
- use app\common\service\ApproveInfoService;
- use app\common\service\CommonService;
- use app\common\service\GoodsCategoryService;
- use app\common\service\UserService;
- use hg\apidoc\annotation as Apidoc;
- use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
- use PhpOffice\PhpSpreadsheet\Reader\Csv;
- use PhpOffice\PhpSpreadsheet\Reader\Xls;
- use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
- use think\db\exception\BindParamException;
- use think\Exception;
- use think\exception\PDOException;
- Use Jsyqw\PdfTable\DrawContent;
- Use Jsyqw\PdfTable\DrawContentTitle;
- Use Jsyqw\PdfTable\DrawTable;
- use Jsyqw\PdfTable\DrawTables;
- use Jsyqw\PdfTable\data\ContentData;
- Use Jsyqw\PdfTable\data\ContentTitleData;
- Use Jsyqw\PdfTable\data\TableData;
- Use Jsyqw\PdfTable\data\TableRowData;
- Use Jsyqw\PdfTable\data\TableTitleData;
- Use Jsyqw\PdfTable\models\ImageModel;
- Use Jsyqw\PdfTable\models\TextModel;
- /**
- * @Apidoc\Title("公用")
- * @Apidoc\Group("api")
- * @Apidoc\Sort("4")
- */
- class Common extends Base
- {
- // 需要登录
- protected $need_login = ['get_user_list'];
- protected $pdf;
- public function initialize()
- {
- parent::initialize();
- $this->pdf = new \TCPDF();
- }
- /**
- * 测试
- *
- * @Apidoc\Method("POST")
- * @Apidoc\Param("id", type="integer",require=true, desc="ID")
- */
- public function test()
- {
- //保存文件
- $subPath = date('Ymd');
- $savePath = './upload/pdf/' . $subPath;
- // 检查上传目录
- if (!is_dir($savePath)) {
- // 检查目录是否编码后的
- if (is_dir(base64_decode($savePath))) {
- $savePath = base64_decode($savePath);
- } else {
- // 尝试创建目录
- if (!mkdir($savePath, 0755, true)) {
- $this->error = '上传目录' . $savePath . '不存在';
- return false;
- }
- }
- } else {
- if (!is_writeable($savePath)) {
- $this->error = '上传目录' . $savePath . '不可写';
- return false;
- }
- }
- $filename = date('Ymd') . sha1(date('YmdHis', time()) . uniqid());
- $suffix = '.pdf';
- $realpath = substr($savePath, 1) . '/' . $filename . $suffix;
- self::exportPdf($_SERVER['DOCUMENT_ROOT'] . $realpath);
- // self::tablePdf('测试文件',$_SERVER['DOCUMENT_ROOT'] . $realpath);
- $this->success('测试');
- }
- // 设置PDF参数
- protected function setPdfAttr()
- {
- $this->pdf->setCreator(PDF_CREATOR);
- $this->pdf->setAuthor('Dya');
- $this->pdf->SetSubject('TCPDF Tutorial');
- $this->pdf->SetKeywords('TCPDF, PDF, example, test, guide');
- //页眉页脚
- $this->pdf->setPrintHeader(false);
- $this->pdf->setPrintFooter(true);
- // 页脚信息
- $this->pdf->setFooterData(array(0,64,0), array(0,64,128));
- $this->pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
- $this->pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
- // 自动分页 (第二个参数可以设置距离底部多少距离时分页)
- $this->pdf->setAutoPageBreak(true, 15);
- // 设置边距(左 上 右 下) 右边距默认左侧值 下边距是bool值(是否覆盖默认页边距)
- $this->pdf->setMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
- // 定义默认的单间距字体 (设置为等宽字体)
- $this->pdf->SetDefaultMonospacedFont('courier');
- // 设置图像比例因子
- $this->pdf->setImageScale(1.25);
- }
- /**
- * 绘制表格
- * @param $title
- * @param $fileName
- */
- public function tablePdf($title, $fileName)
- {
- $this->setPdfAttr();
- $this->pdf->setTitle($title);
- // 新增页面
- $this->pdf->AddPage();
- // 设置字体
- $this->pdf->SetFont('stsongstdlight', 'B', 24, '', true);
- // 参数 1:w 2:h 3:内容 4:边框 5:是否换行 6:内容居中等
- $this->pdf->Cell(0, 0, '财务收款收据', '0', 1, 'C');
- $this->pdf->SetFont('stsongstdlight', '', 18, '', true);
- $this->pdf->Cell(90, 30, 'TEL:888888', '0', 0, 'L');
- // 颜色 RGB颜色代码
- $this->pdf->setTextColor(255, 0, 0);
- $this->pdf->Cell(90, 30, 'NO.20221215', '0', 0, 'R');
- // 换行
- $this->pdf->Ln();
- // 重置颜色
- $this->pdf->setTextColor();
- $this->pdf->SetFont('stsongstdlight', '', 16, '', true);
- $this->pdf->Cell(90, 15, ' 客户名称:张三', '0', 0, 'L');
- $this->pdf->Cell(90, 15, '日期: 2022年12月15日 ', '0', 1, 'R');
- $h = 15;
- // 绘表 表头
- $this->pdf->Cell(40, $h, '规格及名称', '1', 0, 'C');
- $this->pdf->Cell(15, $h, '单位', '1', 0, 'C');
- $this->pdf->Cell(20, $h, '数量', '1', 0, 'C');
- $this->pdf->Cell(25, $h, '单价', '1', 0, 'C');
- $this->pdf->Cell(45, $h, '金额', '1', 0, 'C');
- $this->pdf->Cell(35, $h, '备注', '1', 1, 'C');
- $data = [
- ['name'=>'项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一项目一','unit'=>'件','num'=>13,'price'=>55.00,'money'=>'715.00','remark'=>''],
- ['name'=>'项目二','unit'=>'件','num'=>13,'price'=>54.00,'money'=>'702.00','remark'=>''],
- ['name'=>'项目三','unit'=>'件','num'=>19,'price'=>54.00,'money'=>'1026.00','remark'=>''],
- ['name'=>'项目四','unit'=>'件','num'=>24,'price'=>54.00,'money'=>'1296.00','remark'=>''],
- ];
- // 内容
- foreach ($data as $item) {
- $this->pdf->Cell(40, $h, $item['name'], '1', 0, 'C');
- $this->pdf->Cell(15, $h, $item['unit'], '1', 0, 'C');
- $this->pdf->Cell(20, $h, $item['num'], '1', 0, 'C');
- $this->pdf->Cell(25, $h, $item['price'], '1', 0, 'C');
- $this->pdf->Cell(45, $h, $item['money'], '1', 0, 'C');
- $this->pdf->Cell(35, $h, $item['remark'], '1', 1, 'C');
- }
- $total = sprintf('%.2F', array_sum(array_column($data, 'money')));
- $this->pdf->Cell(100, $h, '合计金额:', 'LTB', 0, 'L');
- $this->pdf->Cell(45, $h, $total, 'TBR', 0, 'R');
- $this->pdf->Cell(35, $h, '', '1', 0, 'C');
- $this->pdf->Output($fileName, 'F');
- }
- public function exportPdf($fileName)
- {
- $this->setPdfAttr();
- // $this->pdf = new \TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
- $this->pdf->SetCreator(PDF_CREATOR);
- $this->pdf->SetAuthor('RoyalsZch');
- $this->pdf->SetTitle('123');
- $this->pdf->SetSubject('123pdf');
- $this->pdf->SetKeywords('TCPDF, PDF, example, test, guide');
- // set default header data
- $this->pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE.' 001', PDF_HEADER_STRING, array(0,64,255), array(0,64,128));
- $this->pdf->setFooterData(array(0, 64, 0), array(0, 64, 128));
- // set header and footer fonts
- $this->pdf->setHeaderFont(array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
- $this->pdf->setFooterFont(array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
- // set default monospaced font
- $this->pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
- // set margins
- $this->pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
- $this->pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
- $this->pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
- // set auto page breaks
- $this->pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
- // set image scale factor
- $this->pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
- $this->pdf->SetFont('stsongstdlight', '', 14, '', true);
- // $this->pdf->Output('pdf'.'.pdf', 'D');
- // add a page
- $this->pdf->AddPage();
- // 随便写HTML
- $htmlUrl=app()->getRootPath() . 'public/upload/1.html';
- $html=file_get_contents($htmlUrl);
- // output the HTML content
- $this->pdf->writeHTML($html, true, false, true, false, '');
- // $this->pdf->Image('https://gvrboxwit.obs.cn-east-2.myhuaweicloud.com:443/web/202303/202303301615200163657.png', 15, 140, 75, 113, 'JPG', 'http://www.tcpdf.org', '', true, 150, '', false, false, 1, false, false, false);
- // reset pointer to the last page
- $this->pdf->lastPage();
- //D是下载,I是在线写入
- $this->pdf->Output($fileName, 'F');
- }
- /**
- * 类型数据
- *
- * @Apidoc\Method("POST")
- * @Apidoc\Returned("module_list", type="array", desc="模块列表")
- * @Apidoc\Returned("degree_list", type="array", desc="缓急程度列表")
- * @Apidoc\Returned("pay_type_list", type="array", desc="采购支付方式列表")
- * @Apidoc\Returned("time_list", type="array", desc="请假周期列表")
- * @Apidoc\Returned("data1", type="array", desc="采购类型列表")
- * @Apidoc\Returned("data2", type="array", desc="呈批类型列表")
- * @Apidoc\Returned("data5", type="array", desc="出差类型列表")
- * @Apidoc\Returned("data6", type="array", desc="请假类型列表")
- * @Apidoc\Returned("data8", type="array", desc="维修类型列表")
- * @Apidoc\Returned("data9", type="array", desc="合同类型列表")
- */
- public function get_type_list()
- {
- $data = CommonService::get_data();
- $this->success('类型数据', $data);
- }
- /**
- * 发起人列表
- *
- * @Apidoc\Desc("入库模块")
- * @Apidoc\Method("POST")
- * @Apidoc\Param("page", type="integer",require=true, desc="页数")
- * @Apidoc\Param("page_num", type="integer", require=true, desc="每页数量")
- * @Apidoc\Returned("userid", type="string", desc="userid")
- * @Apidoc\Returned("name", type="string", desc="姓名")
- **/
- public function get_user_list()
- {
- $offset = $this->off_set;
- $length = $this->page_num;
- $user = $this->user;
- $list = UserService::get_list(0,$offset, $length);
- $this->success('发起人列表', $list);
- }
- /**
- * 维修人员列表
- *
- * @Apidoc\Desc("维修模块")
- * @Apidoc\Method("POST")
- * @Apidoc\Param("type", type="integer", require=true, desc="类型:1=物业主管,2=信息负责人")
- **/
- public function get_maintain_user(){
- $type = $this->request->post('type');
- if (!array_key_exists($type, MaintainConstant::get_type_list())) {
- $this->success('维修人员列表.');
- }
- $list = UserService::get_maintain_user($type);
- $this->success('维修人员列表',$list);
- }
- /**
- * 获取导入模板
- *
- * @Apidoc\Desc("申购模块,入库模块,领用模块")
- * @Apidoc\Method("POST")
- * @Apidoc\Param("module", type="integer", require=true, desc="模块类型:1=申购申请,3=入库申请,4=领用申请")
- * @Apidoc\Returned("url", type="string", desc="导入模板路径")
- **/
- public function get_import_template(){
- $module = $this->request->post('module');
- if (!in_array($module, [CommonConstant::MODULE_1, CommonConstant::MODULE_3, CommonConstant::MODULE_4])) {
- $this->error('请选择正确的模块类型');
- }
- switch ($module){
- case CommonConstant::MODULE_1:
- $url = $this->request->domain().'/导入模板-采购物品.xlsx';
- break;
- case CommonConstant::MODULE_3:
- $url = $this->request->domain().'/导入模板-入库物品.xlsx';
- break;
- case CommonConstant::MODULE_4:
- $url = $this->request->domain().'/导入模板-领用物品.xlsx';
- break;
- }
- $data = compact("url");
- $this->success('导入模板',$data);
- }
- /**
- * 导入
- *
- * @Apidoc\Desc("申购模块,入库模块,领用模块")
- * @Apidoc\Method("POST")
- * @Apidoc\Param("module", type="integer", require=true, desc="模块类型:1=申购申请,3=入库申请,4=领用申请")
- * @Apidoc\Param("file", type="string", require=true, desc="上传后的文件路径")
- * @return void
- * @throws PDOException
- * @throws BindParamException
- */
- public function import()
- {
- $module = $this->request->post('module');
- $file = $this->request->post('file');
- if (!in_array($module, [CommonConstant::MODULE_1, CommonConstant::MODULE_3, CommonConstant::MODULE_4])) {
- $this->error('请选择正确的模块类型');
- }
- if (!$file) {
- $this->error('请选择文件');
- }
- $filePath = $_SERVER['DOCUMENT_ROOT'] . '/' . $file;
- if (!is_file($filePath)) {
- $this->error('文件未找到');
- }
- //实例化reader
- $ext = pathinfo($filePath, PATHINFO_EXTENSION);
- if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
- $this->error('未知的数据格式');
- }
- if ($ext === 'csv') {
- $file = fopen($filePath, 'r');
- $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
- $fp = fopen($filePath, 'w');
- $n = 0;
- while ($line = fgets($file)) {
- $line = rtrim($line, "\n\r\0");
- $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
- if ($encoding !== 'utf-8') {
- $line = mb_convert_encoding($line, 'utf-8', $encoding);
- }
- if ($n == 0 || preg_match('/^".*"$/', $line)) {
- fwrite($fp, $line . "\n");
- } else {
- fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
- }
- $n++;
- }
- fclose($file) || fclose($fp);
- $reader = new Csv();
- } elseif ($ext === 'xls') {
- $reader = new Xls();
- } else {
- $reader = new Xlsx();
- }
- //加载文件
- $insert = [];
- $data = []; // 导入的同一一级分类和二级分类和商品名称的数组
- $category_first_data = []; // 导入的分类数组
- $use_data = []; // 筛选后的领用数组
- $apply_goods_data = []; // 返回的数组
- $error_data = []; // 错误提示数组
- $flag = 2; // 默认批量导入
- try {
- if (!$PHPExcel = $reader->load($filePath)) {
- $this->error('未知的数据格式!');
- }
- $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
- $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
- $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
- $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
- if ($module == CommonConstant::MODULE_4) {
- $fields = ['goods_no', 'goods_category_first', 'goods_category_id', 'goods_name', 'goods_sku_value', 'stock'];
- } else {
- $fields = ['goods_no', 'goods_category_first', 'goods_category_id', 'goods_brand', 'goods_name', 'goods_sku_value', 'stock', 'price', 'total_price'];
- }
- for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
- $values = [];
- for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
- $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
- $values[] = is_null($val) ? '' : trim($val); // 消除空格
- }
- $values = array_filter($values); // 过滤空值
- $temp = array_combine($fields, $values); // 合并两个数组来创建一个新数组,其中的一个数组元素为键名,另一个数组元素为键值
- if ($temp) {
- $insert[] = $temp;
- if ($module == CommonConstant::MODULE_4) {
- $data[$values[1] . ',' . $values[2] . ',' . $values[3]][] = $temp;
- $category_first_data[$values[1]][$values[2]] = $values[2];
- } else {
- $data[$values[1] . ',' . $values[2] . ',' . $values[4]][] = $temp;
- }
- }
- }
- } catch (Exception $exception) {
- $this->error('出现错误:' . $exception->getMessage());
- }
- if (!$insert) {
- $this->error('记录未找到');
- }
- if ($module == CommonConstant::MODULE_4) {
- $category_first_list = GoodsCategoryService::get_list([['name', 'in', array_keys($category_first_data)]],1);
- $category_first_object = $category_first_list ? array_column($category_first_list->toArray(), null, 'name') : [];
- $msg = '导入的物品:';
- foreach ($data as $key => $value) {
- $arr = explode(',', $key);
- $goods_name = $arr[2];
- if(array_key_exists($arr[0],$category_first_object)){
- // 一级里有该商品分类
- $category_first_info = $category_first_object[$arr[0]];
- $goods_category_first_id = $category_first_info['id'];
- $category_second_object = $category_first_info['childlist'] ? array_column($category_first_info['childlist'], null, 'name') : [];
- if(array_key_exists($arr[1],$category_second_object)){
- // 二级里有该商品分类
- $category_second_info = $category_second_object[$arr[1]];
- $goods_category_id = $category_second_info['id'];
- $goods_info = Goods::field('status,is_deleted,create_at', true)
- ->where('goods_category_first', $goods_category_first_id)
- ->where('goods_category_id', $goods_category_id)
- ->where('goods_name', $goods_name)
- ->where('is_deleted', CommonConstant::IS_DELETED_0)
- ->with([
- 'goodsStock',
- ])
- ->find();
- if ($goods_info) {
- // 商品库里有该商品
- $goods_info = $goods_info->toArray();
- $goods_stock_object = array_column($goods_info['goods_stock'], null, 'name');
- foreach ($value as $kk=>$val) {
- if (array_key_exists($val['goods_sku_value'], $goods_stock_object)) {
- // 商品库里有该商品规格
- $goods_stock_info = $goods_stock_object[$val['goods_sku_value']];
- $total_stock = $goods_stock_info['stock']; // 商品库的库存
- $stock = isset($val['stock']) && $val['stock'] > 0 ? $val['stock'] : 0; // 要领用的数量
- $lack_stock = $stock - $total_stock;
- if($total_stock > 0){
- // 商品规格有库存
- $use_data[$key][] = $val;
- $use_data[$key][$kk]['goods_id'] = $goods_info['id'];
- $use_data[$key][$kk]['goods_category_first'] = $goods_category_first_id;
- $use_data[$key][$kk]['goods_category_id'] = $goods_category_id;
- $use_data[$key][$kk]['id'] = $goods_stock_info['id'];
- if($lack_stock >= 0){
- // 商品规格库存不足
- $use_data[$key][$kk]['stock'] = $total_stock; // 替换库存
- $error_data[] = [
- 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '库存不足,缺少' . $lack_stock . '件',
- ];
- }
- } else{
- $error_data[] = [
- 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '库存不足,缺少' . $lack_stock . '件',
- ];
- }
- } else {
- // 商品库里没有该商品规格
- $error_data[] = [
- 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '商品库不存在',
- ];
- }
- }
- } else {
- // 商品库里没有该商品
- $error_data[] = [
- 'msg' => $msg . $goods_name . '商品库不存在',
- ];
- }
- } else{
- // 二级里没有该商品分类
- $error_data[] = [
- 'msg' => $msg . $goods_name . '商品库不存在',
- ];
- }
- } else{
- // 一级里没有该商品分类
- $error_data[] = [
- 'msg' => $msg . $goods_name . '商品库不存在',
- ];
- }
- }
- $data = $use_data;
- $flag = 3; // 商品库选择
- }
- foreach ($data as $key => $value) {
- // 商品
- $goods_data = [];
- $goods_stock_data = [];
- $total_price = 0;
- foreach ($value as $kk => $val) {
- // 规格值
- $stock = isset($val['stock']) && $val['stock'] > 0 ? $val['stock'] : 0;
- $price = isset($val['price']) && $val['price'] > 0 ? $val['price'] : 0;
- $total_price = bcadd($total_price, $stock * $price, 2);
- $goods_stock_data[] = [
- 'id' => isset($val['id']) ? $val['id'] : 0,
- 'name' => $val['goods_sku_value'],
- 'stock' => $stock,
- 'price' => $price,
- ];
- $goods_data = [
- 'goods_id' => isset($val['goods_id']) ? $val['goods_id'] : 0,
- 'goods_category_first' => $val['goods_category_first'],
- 'goods_category_id' => $val['goods_category_id'],
- 'goods_no' => $val['goods_no'],
- 'goods_name' => $val['goods_name'],
- 'goods_brand' => isset($val['goods_brand']) ? $val['goods_brand'] : '',
- ];
- }
- $goods_data['flag'] = $flag;
- $goods_data['total_price'] = $total_price;
- $goods_data['goods_stock'] = $goods_stock_data;
- $apply_goods_data[] = $goods_data;
- }
- $data = compact("apply_goods_data", "error_data");
- $error_data ? $this->success('领用物品提示', $data) : $this->success('导入成功', $data);
- }
- }
|