فهرست منبع

文件添加水印

yeshihao 1 سال پیش
والد
کامیت
63d7dfaecf
44فایلهای تغییر یافته به همراه5064 افزوده شده و 816 حذف شده
  1. 4 2
      .gitignore
  2. 21 0
      dyu/.env.examp
  3. 21 0
      dyu/application/common.php
  4. 1 1
      dyu/application/common/library/storage/engine/Local.php
  5. 95 0
      dyu/application/common/model/Certificate.php
  6. 97 0
      dyu/application/common/model/CertificateApply.php
  7. 39 0
      dyu/application/common/model/CertificateCategory.php
  8. 211 63
      dyu/application/common/model/UploadFile.php
  9. 203 0
      dyu/application/common/service/watermark/WaterMarkBase.php
  10. 93 0
      dyu/application/common/service/watermark/image/Image.php
  11. 89 0
      dyu/application/common/service/watermark/pdf/Pdf.php
  12. BIN
      dyu/application/common/service/watermark/pdf/fonts/msyh.ttf
  13. 19 6
      dyu/application/store/common.php
  14. 95 67
      dyu/application/store/controller/Upload.php
  15. 105 0
      dyu/application/store/controller/content/Certificate.php
  16. 92 0
      dyu/application/store/controller/content/certificate/Category.php
  17. 163 0
      dyu/application/store/controller/content/certificate/Watermark.php
  18. 676 642
      dyu/application/store/extra/menus.php
  19. 99 0
      dyu/application/store/model/Certificate.php
  20. 124 0
      dyu/application/store/model/CertificateApply.php
  21. 82 0
      dyu/application/store/model/CertificateCategory.php
  22. 96 0
      dyu/application/store/view/content/certificate/add.php
  23. 42 0
      dyu/application/store/view/content/certificate/category/add.php
  24. 42 0
      dyu/application/store/view/content/certificate/category/edit.php
  25. 77 0
      dyu/application/store/view/content/certificate/category/index.php
  26. 103 0
      dyu/application/store/view/content/certificate/edit.php
  27. 93 0
      dyu/application/store/view/content/certificate/index.php
  28. 170 0
      dyu/application/store/view/content/certificate/watermark/add.php
  29. 167 0
      dyu/application/store/view/content/certificate/watermark/edit.php
  30. 96 0
      dyu/application/store/view/content/certificate/watermark/index.php
  31. 77 0
      dyu/application/task/controller/Test.php
  32. 2 1
      dyu/composer.json
  33. 1674 0
      dyu/composer.lock
  34. 1 1
      dyu/thinkphp/composer.json
  35. 6 0
      dyu/thinkphp/library/think/Lang.php
  36. 1 1
      dyu/thinkphp/library/think/cache/driver/Redis.php
  37. BIN
      dyu/thinkphp/library/think/console/bin/hiddeninput.exe
  38. 1 1
      dyu/thinkphp/library/think/db/Query.php
  39. 13 11
      dyu/thinkphp/library/think/log/driver/File.php
  40. 1 1
      dyu/thinkphp/library/think/process/pipes/Windows.php
  41. BIN
      dyu/thinkphp/logo.png
  42. BIN
      web/static/common/fonts/msyh.ttf
  43. 21 7
      web/static/store/js/app.js
  44. 52 12
      web/static/store/js/file.library.js

+ 4 - 2
.gitignore

@@ -1,7 +1,9 @@
-web/uploads
 dyu/vendor
 dyu/runtime
 .idea
 .vscode
 .env
-
+api.http
+docker/
+web/jpush.log
+web/uploads/*

+ 21 - 0
dyu/.env.examp

@@ -0,0 +1,21 @@
+# 应用
+[app]
+app_debug = true
+env = dev
+domain = http://localhost:8072/dyuitTools/web
+aes_key = 0EAE3F8FDB142C037DB6D8721620D144
+
+# 数据库
+[db]
+host = 10.10.1.188
+database = dyuit_tools
+username = dyuit_tools
+password = mtRSrTCPJ2zYTBf4
+port = 3306
+charset = utf8mb4
+debug = true
+
+[cache]
+type = redis
+host = 127.0.0.1
+prefix = dyuit_tools:

+ 21 - 0
dyu/application/common.php

@@ -346,3 +346,24 @@ function filter_emoji($text)
     // 如需支持emoji表情, 需将mysql的编码改为utf8mb4
     return preg_replace('/[\xf0-\xf7].{3}/', '', $text);
 }
+
+
+/**
+ * [static_file]
+ * 获取静态资源路径
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/26 15:20
+ * @param string $file
+ * @return string
+ * @throws Exception
+ */
+function static_file($file = ''): string
+{
+	$domain = \think\Env::get('app.domain');
+	if (empty($file)) {
+		return $domain . "/static/" . $file;
+	}
+	$version = get_version();
+	$version = $version['version'] ?? '1';
+	return $domain . "/static/" . $file . '?v=' . $version;
+}

+ 1 - 1
dyu/application/common/library/storage/engine/Local.php

@@ -44,7 +44,7 @@ class Local extends Server
         // 验证文件并上传
         $info = $this->file->validate([
             'size' => 4 * 1024 * 1024,
-            'ext' => 'jpg,jpeg,png,gif'
+            'ext' => 'jpg,jpeg,png,gif,pdf'
         ])->move($uplodDir, $this->fileName);
         if (empty($info)) {
             $this->error = $this->file->getError();

+ 95 - 0
dyu/application/common/model/Certificate.php

@@ -0,0 +1,95 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\common\model;
+
+use think\Cache;
+
+/**
+ * Class Certificate
+ *
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/26 13:37
+ * @package app\common\model
+ */
+class Certificate extends BaseModel
+{
+	protected $name = 'certificate';
+
+
+	/**
+	 * 文章详情
+	 * @param $id
+	 * @return null|static
+	 * @throws \think\exception\DbException
+	 */
+	public static function detail($id)
+	{
+		return self::get($id, ['file', 'category']);
+	}
+
+	/**
+	 * 软删除
+	 *
+	 * @return false|int
+	 */
+	public function setDelete()
+	{
+		return $this->save(['is_delete' => 1]);
+	}
+
+	/**
+	 * [category]
+	 * 关联分类
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:38
+	 * @return \think\model\relation\BelongsTo
+	 */
+	public function category()
+	{
+		return $this->belongsTo(CertificateCategory::class, 'certificate_category_id', 'id');
+	}
+
+	/**
+	 * [file]
+	 * 关联文件
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:48
+	 * @return \think\model\relation\BelongsTo
+	 */
+	public function file()
+	{
+		return $this->belongsTo('UploadFile', 'file_id', 'file_id')
+			->bind(['file_path', 'file_name', 'file_url']);
+	}
+
+	/**
+	 * [getCertificateList]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 10:43
+	 * @param array  $where
+	 * @param string $field
+	 * @return bool|\PDOStatement|string|\think\Collection
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public static function getCertificateList($where = [], $field = '*')
+	{
+		$model = new static;
+		!empty($where) && $model->where($where);
+		return $model->field($field)->where('is_delete', '=', 0)->select();
+	}
+
+
+}

+ 97 - 0
dyu/application/common/model/CertificateApply.php

@@ -0,0 +1,97 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\common\model;
+
+use app\common\model\store\User;
+
+/**
+ * Class CertificateApply
+ *
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/26 13:38
+ * @package app\common\model
+ */
+class CertificateApply extends BaseModel
+{
+	protected $name = 'certificate_apply';
+
+
+	protected $type = [
+		'certificate_ids' => 'array',
+		'result_data'     => 'array',
+		'category_ids'    => 'array',
+	];
+
+	/**
+	 * [getStatusTextAttr]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 10:06
+	 * @param $value
+	 * @param $data
+	 * @return string
+	 */
+	public function getStatusTextAttr($value, $data)
+	{
+		$arr = [10 => '待审核', 20 => '审核通过', 30 => '审核失败'];
+		return $arr[$data['status']] ?? '';
+	}
+
+
+	/**
+	 * [store]
+	 * 提交人
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 18:33
+	 * @return \think\model\relation\BelongsTo
+	 */
+	public function storeUser()
+	{
+		return $this->belongsTo(User::class, 'store_user_id', 'store_user_id');
+	}
+
+	/**
+	 * [apply]
+	 * 申请人
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 18:33
+	 * @return \think\model\relation\BelongsTo
+	 */
+	public function applyUser()
+	{
+		return $this->belongsTo(User::class, 'apply_user_id', 'store_user_id');
+	}
+
+
+	/**
+	 * 文章详情
+	 *
+	 * @param $id
+	 * @return null|static
+	 * @throws \think\exception\DbException
+	 */
+	public static function detail($id)
+	{
+		return self::get($id);
+	}
+
+	/**
+	 * 软删除
+	 *
+	 * @return false|int
+	 */
+	public function setDelete()
+	{
+		return $this->save(['is_delete' => 1]);
+	}
+}

+ 39 - 0
dyu/application/common/model/CertificateCategory.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\common\model;
+
+use think\Cache;
+
+/**
+ * 拼团商品分类模型
+ * Class Category
+ *
+ * @package app\common\model
+ */
+class CertificateCategory extends BaseModel
+{
+	protected $name = 'certificate_category';
+
+
+	/**
+	 * [detail]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:25
+	 * @param $id
+	 * @return CertificateCategory|null
+	 * @throws \think\exception\DbException
+	 */
+	public static function detail($id)
+	{
+		return static::get($id);
+	}
+}

+ 211 - 63
dyu/application/common/model/UploadFile.php

@@ -10,82 +10,230 @@
 
 namespace app\common\model;
 
+use app\common\library\storage\Driver as StorageDriver;
 
 /**
  * 文件库模型
  * Class UploadFile
+ *
  * @package app\common\model
  */
 class UploadFile extends BaseModel
 {
-    protected $name = 'upload_file';
-    protected $updateTime = false;
-    protected $deleteTime = false;
-    protected $append = ['file_path'];
+	protected $name = 'upload_file';
+	protected $updateTime = false;
+	protected $deleteTime = false;
+	protected $append = ['file_path', 'cover_file_path'];
+
+	/**
+	 * 关联文件库分组表
+	 *
+	 * @return \think\model\relation\BelongsTo
+	 */
+	public function uploadGroup()
+	{
+		return $this->belongsTo('UploadGroup', 'group_id');
+	}
+
+	/**
+	 * 获取图片完整路径
+	 *
+	 * @param $value
+	 * @param $data
+	 * @return string
+	 */
+	public function getFilePathAttr($value, $data)
+	{
+		if ($data['storage'] === 'local') {
+			return self::$base_url . 'uploads/' . $data['file_name'];
+		}
+		if ($data['storage'] === 'third_party') {
+			return $data['file_name'];
+		}
+		$domain = str_replace('http://dy-dxf.oss-cn-hangzhou.aliyuncs.com', 'https://dy-dxf.oss-cn-hangzhou.aliyuncs.com', $data['file_url']);
+		return $domain . '/' . $data['file_name'];
+	}
+
+	/**
+	 * [getCoverFilePathAttr]
+	 * 获取封面图片
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/6/14 15:23
+	 * @param $value
+	 * @param $data
+	 * @return array|bool|float|int|mixed|object|\stdClass|string|null
+	 */
+	public function getCoverFilePathAttr($value, $data)
+	{
+		if (empty($data['file_type'])) {
+			return $this->file_path ?? '';
+		}
+		if ($data['file_type'] == 'video') {
+			return static_file('store/img/video.png');
+		}
+		if ($data['file_type'] == 'file') {
+			return  static_file('store/img/file.png');
+		}
+		if ($data['file_type'] == 'pdf') {
+			return  static_file('store/img/pdf.png');
+		}
+		return $this->file_path;
+	}
+
+	/**
+	 * 通过mime获取文件类型
+	 *
+	 * @param string $mime
+	 * @return string
+	 * @Author Mark
+	 * @DateTime 2024-08-07
+	 */
+	public static function mime2fileType(string $mime): string
+	{
+		$map = [
+			//图片
+			'image/jpeg'      => 'image',
+			'image/jpg'       => 'image',
+			'image/png'       => 'image',
+			'image/gif'       => 'image',
+			'image/bmp'       => 'image',
+			'image/webp'      => 'image',
+			//视频
+			'video/mp4'       => 'video',
+			//pdf
+			'application/pdf' => 'pdf',
+		];
+		return $map[$mime] ?? '';
+	}
 
-    /**
-     * 关联文件库分组表
-     * @return \think\model\relation\BelongsTo
-     */
-    public function uploadGroup()
-    {
-        return $this->belongsTo('UploadGroup', 'group_id');
-    }
+	/**
+	 * 文件详情
+	 *
+	 * @param $file_id
+	 * @return null|static
+	 * @throws \think\exception\DbException
+	 */
+	public static function detail($file_id)
+	{
+		return self::get($file_id);
+	}
 
-    /**
-     * 获取图片完整路径
-     * @param $value
-     * @param $data
-     * @return string
-     */
-    public function getFilePathAttr($value, $data)
-    {
-        if ($data['storage'] === 'local') {
-            return self::$base_url . 'uploads/' . $data['file_name'];
-        }
-        return $data['file_url'] . '/' . $data['file_name'];
-    }
+	/**
+	 * 根据文件名查询文件id
+	 *
+	 * @param $fileName
+	 * @return mixed
+	 */
+	public static function getFildIdByName($fileName)
+	{
+		return (new static)->where(['file_name' => $fileName])->value('file_id');
+	}
 
-    /**
-     * 文件详情
-     * @param $file_id
-     * @return null|static
-     * @throws \think\exception\DbException
-     */
-    public static function detail($file_id)
-    {
-        return self::get($file_id);
-    }
+	/**
+	 * 查询文件id
+	 *
+	 * @param $fileId
+	 * @return mixed
+	 */
+	public static function getFileName($fileId)
+	{
+		return (new static)->where(['file_id' => $fileId])->value('file_name');
+	}
 
-    /**
-     * 根据文件名查询文件id
-     * @param $fileName
-     * @return mixed
-     */
-    public static function getFildIdByName($fileName)
-    {
-        return (new static)->where(['file_name' => $fileName])->value('file_id');
-    }
+	/**
+	 * 添加新记录
+	 *
+	 * @param $data
+	 * @return false|int
+	 */
+	public function add($data)
+	{
+		$data['wxapp_id'] = $data['wxapp_id'] ?? (self::$wxapp_id ?: 0);
+		return $this->save($data);
+	}
 
-    /**
-     * 查询文件id
-     * @param $fileId
-     * @return mixed
-     */
-    public static function getFileName($fileId)
-    {
-        return (new static)->where(['file_id' => $fileId])->value('file_name');
-    }
+	/**
+	 * [imageArr]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2023/6/16 20:47
+	 */
+	public static function id2url($id)
+	{
+		$file = self::cache(3600)->find($id);
+		return $file->file_path ?? '';
+	}
 
-    /**
-     * 添加新记录
-     * @param $data
-     * @return false|int
-     */
-    public function add($data)
-    {
-        $data['wxapp_id'] = self::$wxapp_id;
-        return $this->save($data);
-    }
+	/**
+	 * 文件上传
+	 *
+	 * @param integer $wxappId
+	 * @param integer $group_id
+	 * @param string $fileField
+	 * @return static
+	 * @Author Mark
+	 * @DateTime 2024-08-22
+	 */
+	public function uploadFile($wxappId, $group_id = -1, $fileField = 'iFile', $comapnyId = 0)
+	{
+		$config = Setting::getItem('storage', $wxappId);
+		// 实例化存储驱动
+		$StorageDriver = new StorageDriver($config);
+		// 设置上传文件的信息
+		$StorageDriver->setUploadFile($fileField);
+		//判断上传类型
+		$fileInfo = $StorageDriver->getFileInfo();
+		if (!UploadFile::mime2fileType($fileInfo['type'])) {
+			$this->error = '图片上传失败:mime类型错误';
+			return false;
+		}
+		// 上传图片
+		if (!$StorageDriver->upload()) {
+			$this->error = '图片上传失败:' . $StorageDriver->getError();
+			return false;
+		}
+		// 图片上传路径
+		$fileName = $StorageDriver->getFileName();
+		// 图片信息
+		$fileInfo = $StorageDriver->getFileInfo();
+		$uploadFile = self::addUploadFile($group_id, $fileName, $fileInfo, $config, $comapnyId);
+		// 图片上传成功
+		return $uploadFile;
+	}
 
+	/**
+	 * 写入数据库
+	 *
+	 * @param int $group_id
+	 * @param string $fileName
+	 * @param array $fileInfo
+	 * @param array $config
+	 * @return static
+	 * @Author Mark
+	 * @DateTime 2024-08-22
+	 */
+	private function addUploadFile($group_id, $fileName, $fileInfo, $config, $companyId)
+	{
+		// 存储引擎
+		$storage = $config['default'];
+		// 存储域名
+		$fileUrl = isset($config['engine'][$storage]['domain'])
+			? $config['engine'][$storage]['domain'] : '';
+		// 添加文件库记录
+		$model = new self;
+		$model->add([
+			'group_id'    => $group_id > 0 ? (int)$group_id : 0,
+			'storage'     => $storage,
+			'file_url'    => $fileUrl,
+			'file_name'   => $fileName,
+			'file_size'   => $fileInfo['size'],
+			'file_type' => self::mime2fileType($fileInfo['type']),
+			'extension'   => pathinfo($fileInfo['name'], PATHINFO_EXTENSION),
+			'origin_name' => $fileInfo['name'],
+			'mime' => $fileInfo['type'],
+			'company_id' => $companyId,
+		]);
+		return $model;
+	}
 }

+ 203 - 0
dyu/application/common/service/watermark/WaterMarkBase.php

@@ -0,0 +1,203 @@
+<?php
+
+namespace app\common\service\watermark;
+
+use app\common\service\watermark\image\Image;
+use app\common\service\watermark\pdf\Pdf;
+
+/**
+ * Class WaterMarkBase
+ * 生成水印
+ *
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/27 14:03
+ * @package app\common\service\watermark
+ */
+class WaterMarkBase
+{
+
+	/**
+	 * @var string
+	 */
+	public $error = '';
+
+	/**
+	 * @var
+	 */
+	public $url;
+
+	public $water;
+
+	public $wxapp_id;
+
+	public $type;
+
+	public $tempDownloadFileName;
+
+	/**
+	 * WaterMarkBase constructor.
+	 *
+	 * @param $url //图片路径
+	 * @param $water //水印内容
+	 * @param $wxapp_id //wxappid
+	 */
+	public function __construct($url, $water, $wxapp_id, $type = 'image')
+	{
+		$this->url      = $url;
+		$this->water    = $water;
+		$this->wxapp_id = $wxapp_id;
+		$this->type     = $type;
+	}
+
+	/**
+	 * [waterMark]
+	 * 添加水印
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 14:03
+	 * @return string
+	 */
+	public function waterMark()
+	{
+		//获取文件路径查看是否存在本地
+		$filePath = $this->saveTempImage($this->wxapp_id, $this->url);
+		//根据类型调用水印方法
+		switch ($this->type) {
+			case 'image':
+				$image = new Image();
+				$image->waterMark($filePath, $this->water, 1);
+				break;
+			case 'pdf':
+				$pdf = new Pdf();
+				$pdf->waterMark($filePath, $this->water);
+				break;
+		}
+
+		return $filePath;
+	}
+
+
+	/**
+	 * [saveTempImage]
+	 * 保存临时文件
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/25 14:28
+	 * @param        $wxapp_id
+	 * @param        $url
+	 * @param string $mark
+	 * @return string
+	 */
+	private
+	function saveTempImage($wxapp_id, $url, $mark = 'temp')
+	{
+		$savePath = $this->getTempSavePath($wxapp_id, $url, $mark);
+		if (file_exists($savePath)) {
+			return $savePath;
+		}
+		$ch = curl_init($url);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+		curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
+		$img = curl_exec($ch);
+		curl_close($ch);
+		$fp = fopen($savePath, 'w');
+		fwrite($fp, $img);
+		fclose($fp);
+		return $savePath;
+	}
+
+
+	/**
+	 * 获取保存路径
+	 *
+	 * @param int    $wxapp_id
+	 * @param string $url
+	 * @param string $mark
+	 * @return string
+	 * @Author Mark
+	 * @DateTime 2024-08-14
+	 */
+	private function getTempSavePath($wxapp_id, $url, $mark = 'temp'): string
+	{
+		$dirPath = WEB_PATH.'temp/image'.'/'.$wxapp_id;
+		!is_dir($dirPath) && mkdir($dirPath, 0755, true);
+		if ($this->type == 'pdf') {
+			$fileName = $mark.'_'.date('YmdHis').'_'.md5($url).'.pdf';
+		} else {
+			$fileName = $mark.'_'.date('YmdHis').'_'.md5($url).'.png';
+		}
+
+		$savePath                   = $dirPath.'/'.$fileName;
+		$this->tempDownloadFileName = $fileName;
+		return $savePath;
+	}
+
+
+	/**
+	 * gif转png
+	 *
+	 * @param string $path
+	 * @return void
+	 * @Author Mark
+	 * @DateTime 2024-06-12
+	 */
+	private function git2png($path)
+	{
+		$image = imagecreatefromgif($path);
+		if ($image === false) {
+			return true;
+		}
+		// 设置PNG的背景颜色(透明度)
+		$background = imagecolorallocatealpha($image, 0, 0, 0, 127);
+		// 创建一个全新的真彩色图像
+		$png_image = imagecreatetruecolor(imagesx($image), imagesy($image));
+		// 设置透明度,以便将GIF的透明区域变成半透明的黑色
+		imagefill($png_image, 0, 0, $background);
+		// 如果GIF有透明区域,将其合并到新图片中
+		if (imagecolortransparent($image) >= 0) {
+			// 获取GIF图片的透明颜色索引
+			$transparent_index = imagecolortransparent($image);
+			// 获取透明颜色
+			$transparent_color = imagecolorsforindex($image, $transparent_index);
+			// 设置新图片的透明颜色
+			$background = imagecolorallocatealpha($png_image, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue'], $transparent_color['alpha']);
+			// 设置新图片的透明区域
+			imagefill($png_image, 0, 0, $background);
+			imagecolortransparent($png_image, $background);
+		}
+		// 将原始图片拷贝到新图片上
+		imagecopy($png_image, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
+		imagepng($png_image, $path);
+
+		// 释放内存
+		imagedestroy($image);
+		imagedestroy($png_image);
+	}
+
+	/**
+	 * 设置错误信息
+	 *
+	 * @param string $msg
+	 * @return false
+	 * @Author Mark
+	 * @DateTime 2024-08-23
+	 */
+	public function setError(string $msg): bool
+	{
+		$this->error = $msg;
+		return false;
+	}
+
+	/**
+	 * 获取错误信息
+	 *
+	 * @return string
+	 * @Author Mark
+	 * @DateTime 2024-08-23
+	 */
+	public function getError(): string
+	{
+		return $this->error;
+	}
+}

+ 93 - 0
dyu/application/common/service/watermark/image/Image.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace app\common\service\watermark\image;
+
+use Grafika\Color;
+use Grafika\Grafika;
+use Grafika\ImageType;
+
+class Image
+{
+
+	/**
+	 * [waterMark]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2023/11/14 14:45
+	 * @param     $filePath //文件路径
+	 * @param     $waterText //水印文字
+	 * @param int $type 0不倾斜 1倾斜
+	 * @return bool
+	 * @throws
+	 */
+	public function waterMark($filePath, $waterText, $type = 0)
+	{
+		// 1 打开海报背景图
+		$editor = Grafika::createEditor(['Gd']);
+		$editor->open($backdropImage, $filePath);
+		// 获取背景图宽高
+		$size = getimagesize($filePath);
+		//获取文字类型路劲
+		$fontPath = Grafika::fontsDir().DS.'st-heiti-light.ttc';
+		//获取文字数量
+		$fontNum = mb_strlen($waterText);
+		// 3.创建文字图片
+		//判断是否需要添加水印
+		if ($type) {
+			//获取斜边长度
+			$hypo = hypot($size[0], $size[1]);
+			// 判断文字图片开始的位置
+			$fontSize = intval($hypo) / $fontNum * 0.5;
+			// 获取文字大小宽高
+			$fontSizeArr = $this->get_text_box($waterText, $fontSize, $fontPath);
+			$fontX       = intval(($size[0] * (($hypo - $fontSizeArr[0]) / 2)) / $hypo);
+			$fontY       = intval(($size[1] * (($hypo - $fontSizeArr[0]) / 2)) / $hypo);
+			//计算倾斜角度
+			$angle = intval(atan($size[1] / $size[0]) * 180 / pi());
+			$image = imagecreatetruecolor($size[0], $size[1]);
+		} else {
+			// 判断文字图片开始的位置
+			$fontSize = $size[0] / $fontNum * 0.7;
+			// 获取文字大小宽高
+			$fontSizeArr = $this->get_text_box($waterText, $fontSize, $fontPath);
+			$fontX       = 0;
+			$fontY       = 0;
+			$angle       = 0;
+			$image       = imagecreatetruecolor($fontSizeArr[0], $fontSizeArr[1]);
+		}
+		imagesavealpha($image, true);
+		// 设置透明度
+		$frontImageSource = imagecolorallocatealpha($image, 0, 0, 0, 127);
+		imagefill($image, 0, 0, $frontImageSource);
+		//生成文字透明背景板
+		$fontImage = new \Grafika\Gd\Image($image, '', imagesx($image), imagesy($image), ImageType::PNG);
+
+		//设置文字颜色
+		$Color = new Color('#C0C0C0');
+		$editor->text($fontImage, $waterText, $fontSize, $fontX, $fontY, $Color, $fontPath, -$angle);
+		//合并图片
+		$editor->blend($backdropImage, $fontImage, 'overlay', 1, 'center');
+		// 保存图片
+		$editor->save($backdropImage, $filePath);
+		return true;
+	}
+
+	/**
+	 * [get_text_box]
+	 * 根据文字获取宽高
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2023/11/14 10:04
+	 * @param $text
+	 * @param $size
+	 * @param $font
+	 * @return array
+	 */
+	private function get_text_box($text, $size, $font)
+	{
+		$point  = imagettfbbox($size, 0, $font, $text);
+		$width  = $point[4] - $point[6];
+		$height = $point[1] - $point[7];
+		return [$width, $height];
+	}
+}

+ 89 - 0
dyu/application/common/service/watermark/pdf/Pdf.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace app\common\service\watermark\pdf;
+
+use Mpdf\Mpdf;
+use Mpdf\Config\ConfigVariables;
+use Mpdf\Config\FontVariables;
+
+/**
+ * Class Pdf
+ *
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/28 11:17
+ * @package app\common\service\watermark\pdf
+ */
+class Pdf
+{
+
+
+//	public function waterMark($filePath, $waterText, $type = 0)
+//	{
+//		$pdf = new Fpdi();
+//		$pdf->AddFont('msyh', '', 'msyh.ttf', true); //简体中文可正常显示
+//		$pdf->SetFont('msyh', '', 40);
+//
+//		$pageCount = $pdf->setSourceFile($filePath);
+//
+//		for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
+//			$templateId = $pdf->importPage($pageNo);
+//			$pdf->AddPage();
+//			$pdf->useTemplate($templateId, ['adjustPageSize' => true]);
+//			$size     = $pdf->getTemplateSize($templateId);
+//			$center_x = $size['width'] / 2;
+//			$center_y = $size['height'] / 2;
+//			$pdf->SetXY($center_x, $center_y);
+//			//文字水印
+//			$pdf->SetTextColor(200, 200, 200);
+//			$pdf->Write(0, $waterText);
+//		}
+//
+//		$pdf->Output('F', $filePath); //下载修改后的PDF
+//	}
+
+
+	/**
+	 * [waterMark]
+	 * 打印水印
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 13:39
+	 * @param     $filePath
+	 * @param     $waterText
+	 * @param int $type
+	 * @return bool
+	 * @throws \Mpdf\MpdfException
+	 * @throws \setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException
+	 * @throws \setasign\Fpdi\PdfParser\PdfParserException
+	 * @throws \setasign\Fpdi\PdfParser\Type\PdfTypeException
+	 */
+	public function waterMark($filePath, $waterText, $type = 0)
+	{
+		$defaultConfig          = (new ConfigVariables())->getDefaults();
+		$fontDirs               = $defaultConfig['fontDir'];
+		$defaultFontConfig      = (new FontVariables())->getDefaults();
+		$fontData               = $defaultFontConfig['fontdata'];
+		$mpdf                   = new Mpdf(['mode'         => '+aCJK',
+		                                    'fontDir'      => array_merge($fontDirs,[__DIR__.'/fonts']),
+		                                    'fontdata'     => $fontData + ['msyh' => ['R' => 'msyh.ttf',],],
+		                                    'default_font' => 'msyh'
+		]);
+		$mpdf->autoScriptToLang = true;
+		$mpdf->autoLangToFont   = true;
+
+		$text = $waterText;
+		//文字水印
+		$watermarkText = new \Mpdf\WatermarkText($text, 30, 30, '#cccccc', 0.4);
+		$mpdf->SetWatermarkText($watermarkText, 0.3);
+		$mpdf->showWatermarkText = true;
+		$mpdf->watermarkAngle    = '-45';
+		$pageCount               = $mpdf->SetSourceFile($filePath); //读取原始文件页数
+		for ($i = 1; $i <= $pageCount; $i++) {
+			$import_page = $mpdf->ImportPage($i);
+			$mpdf->UseTemplate($import_page);
+			if ($i < $pageCount)
+				$mpdf->AddPage();
+		}
+		$mpdf->Output($filePath, 'F');// 下载修改后的PDF
+		return true;
+	}
+}

BIN
dyu/application/common/service/watermark/pdf/fonts/msyh.ttf


+ 19 - 6
dyu/application/store/common.php

@@ -3,18 +3,31 @@
 // 应用公共函数库文件
 
 use app\store\service\Auth;
+use think\Session;
 
 /**
  * 验证指定url是否有访问权限
+ *
  * @param string|array $url
- * @param bool $strict 严格模式
+ * @param bool         $strict 严格模式
  * @return bool
  */
 function checkPrivilege($url, $strict = true)
 {
-    try {
-        return Auth::getInstance()->checkPrivilege($url, $strict);
-    } catch (\Exception $e) {
-        return false;
-    }
+	try {
+		return Auth::getInstance()->checkPrivilege($url, $strict);
+	} catch (\Exception $e) {
+		return false;
+	}
 }
+
+/**
+ * 获取当前商户用户id
+ *
+ * @return int
+ */
+function getStoreUserId()
+{
+	$store = Session::get('dyu_store');
+	return $store['user']['store_user_id'] ?? 0;
+}

+ 95 - 67
dyu/application/store/controller/Upload.php

@@ -21,76 +21,104 @@ use app\store\model\Setting as SettingModel;
  */
 class Upload extends Controller
 {
-    private $config;
+	private $config;
 
-    /**
-     * 构造方法
-     * @throws \app\common\exception\BaseException
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\ModelNotFoundException
-     * @throws \think\exception\DbException
-     */
-    public function _initialize()
-    {
-        parent::_initialize();
-        // 存储配置信息
-        $this->config = SettingModel::getItem('storage');
-    }
+	/**
+	 * 构造方法
+	 * @throws \app\common\exception\BaseException
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public function _initialize()
+	{
+		parent::_initialize();
+		// 存储配置信息
+		$this->config = SettingModel::getItem('storage');
+	}
 
-    /**
-     * 图片上传接口
-     * @param int $group_id
-     * @return array
-     * @throws \think\Exception
-     */
-    public function image($group_id = -1)
-    {
-        // 实例化存储驱动
-        $StorageDriver = new StorageDriver($this->config);
-        // 设置上传文件的信息
-        $StorageDriver->setUploadFile('iFile');
-        // 上传图片
-        if (!$StorageDriver->upload()) {
-            return json(['code' => 0, 'msg' => '图片上传失败' . $StorageDriver->getError()]);
-        }
+	/**
+	 * 图片上传接口
+	 * @param int $group_id
+	 * @return array
+	 * @throws \think\Exception
+	 */
+	public function image($group_id = -1)
+	{
+		// 实例化存储驱动
+		$StorageDriver = new StorageDriver($this->config);
+		// 设置上传文件的信息
+		$StorageDriver->setUploadFile('iFile');
+		//判断上传类型
+		$fileInfo = $StorageDriver->getFileInfo();
+		if (!UploadFile::mime2fileType($fileInfo['type'])) {
+			return json(['code' => 0, 'msg' => '图片上传失败:mime类型错误']);
+		}
+		// 上传图片
+		if (!$StorageDriver->upload()) {
+			return json(['code' => 0, 'msg' => '图片上传失败' . $StorageDriver->getError()]);
+		}
+		// 图片上传路径
+		$fileName = $StorageDriver->getFileName();
+		// 图片信息
+		$fileInfo = $StorageDriver->getFileInfo();
+		$uploadFile = $this->addUploadFile($group_id, $fileName, $fileInfo);
+		// 图片上传成功
+		return json(['code' => 1, 'msg' => '图片上传成功', 'data' => $uploadFile]);
+	}
 
-        // 图片上传路径
-        $fileName = $StorageDriver->getFileName();
-        // 图片信息
-        $fileInfo = $StorageDriver->getFileInfo();
-        // 添加文件库记录
-        $uploadFile = $this->addUploadFile($group_id, $fileName, $fileInfo, 'image');
-        // 图片上传成功
-        return json(['code' => 1, 'msg' => '图片上传成功', 'data' => $uploadFile]);
-    }
 
-    /**
-     * 添加文件库上传记录
-     * @param $group_id
-     * @param $fileName
-     * @param $fileInfo
-     * @param $fileType
-     * @return UploadFile
-     */
-    private function addUploadFile($group_id, $fileName, $fileInfo, $fileType)
-    {
-        // 存储引擎
-        $storage = $this->config['default'];
-        // 存储域名
-        $fileUrl = isset($this->config['engine'][$storage]['domain'])
-            ? $this->config['engine'][$storage]['domain'] : '';
-        // 添加文件库记录
-        $model = new UploadFile;
-        $model->add([
-            'group_id' => $group_id > 0 ? (int)$group_id : 0,
-            'storage' => $storage,
-            'file_url' => $fileUrl,
-            'file_name' => $fileName,
-            'file_size' => $fileInfo['size'],
-            'file_type' => $fileType,
-            'extension' => pathinfo($fileInfo['name'], PATHINFO_EXTENSION),
-        ]);
-        return $model;
-    }
+	public function file($group_id = -1)
+	{
+		// 实例化存储驱动
+		$StorageDriver = new StorageDriver($this->config);
+		// 设置上传文件的信息
+		$StorageDriver->setUploadFile('iFile');
+		//判断上传类型
+		$fileInfo = $StorageDriver->getFileInfo();
+		if (!UploadFile::mime2fileType($fileInfo['type'])) {
+			return json(['code' => 0, 'msg' => '图片上传失败:mime类型错误']);
+		}
+		// 上传图片
+		if (!$StorageDriver->upload()) {
+			return json(['code' => 0, 'msg' => '文件上传失败' . $StorageDriver->getError()]);
+		}
 
+		// 图片上传路径
+		$fileName = $StorageDriver->getFileName();
+		// 图片信息
+		$fileInfo = $StorageDriver->getFileInfo();
+		// 添加文件库记录
+		$uploadFile = $this->addUploadFile($group_id, $fileName, $fileInfo);
+		// 图片上传成功
+		return json(['code' => 1, 'msg' => '文件上传成功', 'data' => $uploadFile]);
+	}
+	/**
+	 * 添加文件库上传记录
+	 * @param $group_id
+	 * @param $fileName
+	 * @param $fileInfo
+	 * @param $fileType
+	 * @return UploadFile
+	 */
+	private function addUploadFile($group_id, $fileName, $fileInfo)
+	{
+		// 存储引擎
+		$storage = $this->config['default'];
+		// 存储域名
+		$fileUrl = isset($this->config['engine'][$storage]['domain'])
+			? $this->config['engine'][$storage]['domain'] : '';
+		// 添加文件库记录
+		$model = new UploadFile;
+		$model->add([
+			'group_id'    => $group_id > 0 ? (int)$group_id : 0,
+			'storage'     => $storage,
+			'file_url'    => $fileUrl,
+			'file_name'   => $fileName,
+			'file_size'   => $fileInfo['size'],
+			'file_type' => UploadFile::mime2fileType($fileInfo['type']),
+			'extension'   => pathinfo($fileInfo['name'], PATHINFO_EXTENSION),
+		]);
+		return $model;
+	}
 }

+ 105 - 0
dyu/application/store/controller/content/Certificate.php

@@ -0,0 +1,105 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\controller\content;
+
+use app\store\controller\Controller;
+use app\store\model\Article as ArticleModel;
+use app\store\model\Certificate as CertificateModel;
+use app\store\model\article\Category as CategoryModel;
+use app\store\model\CertificateCategory as CertificateCategoryModel;
+
+/**
+ * 文章管理控制器
+ * Class article
+ *
+ * @package app\store\controller\content
+ */
+class Certificate extends Controller
+{
+	/**
+	 * 文章列表
+	 *
+	 * @return mixed
+	 * @throws \think\exception\DbException
+	 */
+	public function index()
+	{
+		$model = new CertificateModel;
+		$list  = $model->getList();
+		return $this->fetch('index', compact('list'));
+	}
+
+	/**
+	 * [add]
+	 * 添加资质
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:56
+	 * @return array|bool|mixed
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public function add()
+	{
+		$model = new CertificateModel;
+		if (!$this->request->isAjax()) {
+			$category = CertificateCategoryModel::getAll();
+			return $this->fetch('add', compact('category'));
+		}
+		// 新增记录
+		if ($model->add($this->postData())) {
+			return $this->renderSuccess('添加成功', url('content.certificate/index'));
+		}
+		return $this->renderError($model->getError() ?: '添加失败');
+	}
+
+	/**
+	 * 更新文章
+	 *
+	 * @param $article_id
+	 * @return array|mixed
+	 * @throws \think\exception\DbException
+	 */
+	public function edit($id)
+	{
+		// 文章详情
+		$model = CertificateModel::detail($id);
+		if (!$this->request->isAjax()) {
+			$category = CertificateCategoryModel::getAll();
+			return $this->fetch('edit', compact('model', 'category'));
+		}
+		// 更新记录
+		if ($model->edit($this->postData())) {
+			return $this->renderSuccess('更新成功', url('content.certificate/index'));
+		}
+		return $this->renderError($model->getError() ?: '更新失败');
+	}
+
+	/**
+	 * [delete]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 10:08
+	 * @param $id
+	 * @return array|bool
+	 * @throws \think\exception\DbException
+	 */
+	public function delete($id)
+	{
+		// 文章详情
+		$model = CertificateModel::detail($id);
+		if (!$model->setDelete()) {
+			return $this->renderError($model->getError() ?: '删除失败');
+		}
+		return $this->renderSuccess('删除成功');
+	}
+
+}

+ 92 - 0
dyu/application/store/controller/content/certificate/Category.php

@@ -0,0 +1,92 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\controller\content\certificate;
+
+use app\store\controller\Controller;
+use app\store\model\article\Category as CategoryModel;
+use app\store\model\CertificateCategory as CertificateCategoryModel;
+
+/**
+ * 文章分类
+ * Class Category
+ *
+ * @package app\store\controller\content
+ */
+class Category extends Controller
+{
+	/**
+	 * 文章分类列表
+	 *
+	 * @return mixed
+	 */
+	public function index()
+	{
+		$model = new CertificateCategoryModel;
+		$list  = $model->getAll();
+		return $this->fetch('index', compact('list'));
+	}
+
+	/**
+	 * 添加文章分类
+	 *
+	 * @return array|mixed
+	 */
+	public function add()
+	{
+		$model = new CertificateCategoryModel;
+		if (!$this->request->isAjax()) {
+			return $this->fetch('add');
+		}
+		// 新增记录
+		if ($model->add($this->postData('category'))) {
+			return $this->renderSuccess('添加成功', url('content.certificate.category/index'));
+		}
+		return $this->renderError($model->getError() ?: '添加失败');
+	}
+
+	/**
+	 * 编辑文章分类
+	 *
+	 * @param $id
+	 * @return array|mixed
+	 * @throws \think\exception\DbException
+	 */
+	public function edit($id)
+	{
+		// 分类详情
+		$model = CertificateCategoryModel::detail($id);
+		if (!$this->request->isAjax()) {
+			return $this->fetch('edit', compact('model'));
+		}
+		// 更新记录
+		if ($model->edit($this->postData('category'))) {
+			return $this->renderSuccess('更新成功', url('content.certificate.category/index'));
+		}
+		return $this->renderError($model->getError() ?: '更新失败');
+	}
+
+	/**
+	 * 删除文章分类
+	 *
+	 * @param $category_id
+	 * @return array
+	 * @throws \think\exception\DbException
+	 */
+	public function delete($id)
+	{
+		$model = CertificateCategoryModel::detail($id);
+		if (!$model->remove($id)) {
+			return $this->renderError($model->getError() ?: '删除失败');
+		}
+		return $this->renderSuccess('删除成功');
+	}
+
+}

+ 163 - 0
dyu/application/store/controller/content/certificate/Watermark.php

@@ -0,0 +1,163 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\controller\content\certificate;
+
+use app\store\controller\Controller;
+use app\store\model\CertificateCategory as CertificateCategoryModel;
+use app\store\model\Certificate as CertificateModel;
+use app\store\model\CertificateApply as CertificateApplyModel;
+use ZipArchive;
+
+/**
+ * 文章分类
+ * Class Category
+ *
+ * @package app\store\controller\content
+ */
+class Watermark extends Controller
+{
+	/**
+	 * 文章分类列表
+	 *
+	 * @return mixed
+	 */
+	public function index()
+	{
+		$model = new CertificateApplyModel;
+		$list  = $model->getList();
+		return $this->fetch('index', compact('list'));
+	}
+
+	/**
+	 * 添加文章分类
+	 *
+	 * @return array|mixed
+	 */
+	public function add()
+	{
+		$model = new CertificateApplyModel;
+		if (!$this->request->isAjax()) {
+			$category = CertificateCategoryModel::getAll();
+			return $this->fetch('add', compact('category'));
+		}
+		// 新增记录
+		if ($model->add($this->postData())) {
+			return $this->renderSuccess('添加成功', url('content.certificate.watermark/index'));
+		}
+		return $this->renderError($model->getError() ?: '添加失败');
+	}
+
+	/**
+	 * 编辑文章分类
+	 *
+	 * @param $id
+	 * @return array|mixed
+	 * @throws \think\exception\DbException
+	 */
+	public function edit($id)
+	{
+		// 分类详情
+		$model = CertificateApplyModel::detail($id);
+		if (!$this->request->isAjax()) {
+			$category        = CertificateCategoryModel::getAll();
+			$certificateList = CertificateModel::getCertificateList(['certificate_category_id' => ['in', $model['category_ids']]], ['id', 'name']);
+			return $this->fetch('edit', compact('model', 'category', 'certificateList'));
+		}
+		// 更新记录
+		if ($model->edit($this->postData())) {
+			return $this->renderSuccess('审核成功', url('content.certificate.watermark/index'));
+		}
+		return $this->renderError($model->getError() ?: '审核失败');
+	}
+
+	/**
+	 * [delete]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 10:09
+	 * @param $id
+	 * @return array|bool
+	 */
+	public function delete($id)
+	{
+		$model = CertificateApplyModel::detail($id);
+		if (!$model->setDelete()) {
+			return $this->renderError($model->getError() ?: '取消失败');
+		}
+		return $this->renderSuccess('取消成功');
+	}
+
+	/**
+	 * [getCertificateList]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 10:51
+	 * @param array $category_ids
+	 * @return array|bool
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public function getCertificateList($category_ids = [])
+	{
+		$model = new CertificateModel;
+		if (!$list = $model->getCertificateList(['certificate_category_id' => ['in', $category_ids]], ['id', 'name'])) {
+			return $this->renderError($model->getError() ?: '请求失败');
+		}
+		return $this->renderSuccess('请求成功', '', $list);
+	}
+
+
+	/**
+	 * [zipDownload]
+	 * 下载zip
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 11:15
+	 * @param $id
+	 * @throws \think\exception\DbException
+	 */
+	public function zipDownload($id)
+	{
+		$model = CertificateApplyModel::detail($id);
+		if (empty($model) || empty($model['result_data'])) {
+			return $this->renderError('查无文件');
+		}
+
+		//TP自带的类
+		$zip = new \ZipArchive();
+
+		//压缩文件名
+		$filename    = Date('Ymd').$model['project'].'.zip';
+		$zipFilePath = RUNTIME_PATH."/temp/".$filename;
+		if (file_exists($zipFilePath)) {
+			unlink($zipFilePath);
+		}
+		//新建zip压缩包
+		$zip->open($zipFilePath, \ZIPARCHIVE::OVERWRITE | \ZIPARCHIVE::CREATE);
+
+		//循环压缩文件
+		foreach ($model['result_data'] as $value) {
+			$substr = mb_substr($value['file_path'], mb_strpos($value['file_path'], "."));
+			//查询文件名称(若之前保存文件为源文件名保存可跳过该步骤)
+			$zip->addFile($value['file_path'], basename($value['name'].$substr));
+		}
+		//打包zip
+		$zip->close();
+		header("Cache-Control:public");
+		header("Content-Description: File Transfer");
+		header("Content-disposition: attachment; filename=".basename($filename));//文件名
+		header("Content-Type:application/zip"); //格式为zip
+		header("Content-Transfer-Encoding:binary"); //这是二进制文件
+		header("Content-Length:".filesize($zipFilePath)); //文件大小
+		@readfile($zipFilePath);
+	}
+
+}

+ 676 - 642
dyu/application/store/extra/menus.php

@@ -1,4 +1,5 @@
 <?php
+
 /**
  * 后台菜单配置
  *    'home' => [
@@ -8,654 +9,687 @@
  *     ],
  */
 return [
-    'index' => [
-        'name' => '首页',
-        'icon' => 'icon-home',
-        'index' => 'index/index',
-    ],
-    'store' => [
-        'name' => '管理员',
-        'icon' => 'icon-guanliyuan',
-        'index' => 'store.user/index',
-        'submenu' => [
-            [
-                'name' => '管理员列表',
-                'index' => 'store.user/index',
-                'uris' => [
-                    'store.user/index',
-                    'store.user/add',
-                    'store.user/edit',
-                    'store.user/delete',
-                ],
-            ],
-            [
-                'name' => '角色管理',
-                'index' => 'store.role/index',
-                'uris' => [
-                    'store.role/index',
-                    'store.role/add',
-                    'store.role/edit',
-                    'store.role/delete',
-                ],
-            ],
-        ]
-    ],
-    'goods' => [
-        'name' => '商品管理',
-        'icon' => 'icon-goods',
-        'index' => 'goods/index',
-        'submenu' => [
-            [
-                'name' => '商品列表',
-                'index' => 'goods/index',
-                'uris' => [
-                    'goods/index',
-                    'goods/add',
-                    'goods/edit',
-                    'goods/copy'
-                ],
-            ],
-            [
-                'name' => '商品分类',
-                'index' => 'goods.category/index',
-                'uris' => [
-                    'goods.category/index',
-                    'goods.category/add',
-                    'goods.category/edit',
-                ],
-            ],
-            [
-                'name' => '商品评价',
-                'index' => 'goods.comment/index',
-                'uris' => [
-                    'goods.comment/index',
-                    'goods.comment/detail',
-                ],
-            ]
-        ],
-    ],
-    'order' => [
-        'name' => '订单管理',
-        'icon' => 'icon-order',
-        'index' => 'order/all_list',
-        'submenu' => [
-            [
-                'name' => '全部订单',
-                'index' => 'order/all_list',
-            ],
-            [
-                'name' => '待发货',
-                'index' => 'order/delivery_list',
-            ],
-            [
-                'name' => '待收货',
-                'index' => 'order/receipt_list',
-            ],
-            [
-                'name' => '待付款',
-                'index' => 'order/pay_list',
-            ],
-            [
-                'name' => '已完成',
-                'index' => 'order/complete_list',
+	'index'      => [
+		'name'  => '首页',
+		'icon'  => 'icon-home',
+		'index' => 'index/index',
+	],
+	'store'      => [
+		'name'    => '管理员',
+		'icon'    => 'icon-guanliyuan',
+		'index'   => 'store.user/index',
+		'submenu' => [
+			[
+				'name'  => '管理员列表',
+				'index' => 'store.user/index',
+				'uris'  => [
+					'store.user/index',
+					'store.user/add',
+					'store.user/edit',
+					'store.user/delete',
+				],
+			],
+			[
+				'name'  => '角色管理',
+				'index' => 'store.role/index',
+				'uris'  => [
+					'store.role/index',
+					'store.role/add',
+					'store.role/edit',
+					'store.role/delete',
+				],
+			],
+		]
+	],
+	'goods'      => [
+		'name'    => '商品管理',
+		'icon'    => 'icon-goods',
+		'index'   => 'goods/index',
+		'submenu' => [
+			[
+				'name'  => '商品列表',
+				'index' => 'goods/index',
+				'uris'  => [
+					'goods/index',
+					'goods/add',
+					'goods/edit',
+					'goods/copy'
+				],
+			],
+			[
+				'name'  => '商品分类',
+				'index' => 'goods.category/index',
+				'uris'  => [
+					'goods.category/index',
+					'goods.category/add',
+					'goods.category/edit',
+				],
+			],
+			[
+				'name'  => '商品评价',
+				'index' => 'goods.comment/index',
+				'uris'  => [
+					'goods.comment/index',
+					'goods.comment/detail',
+				],
+			]
+		],
+	],
+	'order'      => [
+		'name'    => '订单管理',
+		'icon'    => 'icon-order',
+		'index'   => 'order/all_list',
+		'submenu' => [
+			[
+				'name'  => '全部订单',
+				'index' => 'order/all_list',
+			],
+			[
+				'name'  => '待发货',
+				'index' => 'order/delivery_list',
+			],
+			[
+				'name'  => '待收货',
+				'index' => 'order/receipt_list',
+			],
+			[
+				'name'  => '待付款',
+				'index' => 'order/pay_list',
+			],
+			[
+				'name'  => '已完成',
+				'index' => 'order/complete_list',
 
-            ],
-            [
-                'name' => '已取消',
-                'index' => 'order/cancel_list',
-            ],
-            [
-                'name' => '售后管理',
-                'index' => 'order.refund/index',
-                'uris' => [
-                    'order.refund/index',
-                    'order.refund/detail',
-                ]
-            ],
-        ]
-    ],
-    'user' => [
-        'name' => '用户管理',
-        'icon' => 'icon-user',
-        'index' => 'user/index',
-        'submenu' => [
-            [
-                'name' => '用户列表',
-                'index' => 'user/index',
-            ],
-            [
-                'name' => '会员等级',
-                'active' => true,
-                'submenu' => [
-                    [
-                        'name' => '等级管理',
-                        'index' => 'user.grade/index',
-                        'uris' => [
-                            'user.grade/index',
-                            'user.grade/add',
-                            'user.grade/edit',
-                            'user.grade/delete',
-                        ]
-                    ],
-                ]
-            ],
-            [
-                'name' => '余额记录',
-                'active' => true,
-                'submenu' => [
-                    [
-                        'name' => '充值记录',
-                        'index' => 'user.recharge/order',
-                    ],
-                    [
-                        'name' => '余额明细',
-                        'index' => 'user.balance/log',
-                    ],
-                ]
-            ],
-        ]
-    ],
-    'shop' => [
-        'name' => '门店管理',
-        'icon' => 'icon-shop',
-        'index' => 'shop/index',
-        'submenu' => [
-            [
-                'name' => '门店管理',
-                'active' => true,
-                'index' => 'shop/index',
-                'submenu' => [
-                    [
-                        'name' => '门店列表',
-                        'index' => 'shop/index',
-                        'uris' => [
-                            'shop/index',
-                            'shop/add',
-                            'shop/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '店员管理',
-                        'index' => 'shop.clerk/index',
-                        'uris' => [
-                            'shop.clerk/index',
-                            'shop.clerk/add',
-                            'shop.clerk/edit',
-                        ]
-                    ],
-                ]
-            ],
-            [
-                'name' => '订单核销记录',
-                'index' => 'shop.order/index',
-            ]
-        ]
-    ],
-    'content' => [
-        'name' => '内容管理',
-        'icon' => 'icon-wenzhang',
-        'index' => 'content.article/index',
-        'submenu' => [
-            [
-                'name' => '文章管理',
-                'active' => true,
-                'submenu' => [
-                    [
-                        'name' => '文章列表',
-                        'index' => 'content.article/index',
-                        'uris' => [
-                            'content.article/index',
-                            'content.article/add',
-                            'content.article/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '文章分类',
-                        'index' => 'content.article.category/index',
-                        'uris' => [
-                            'content.article.category/index',
-                            'content.article.category/add',
-                            'content.article.category/edit',
-                        ]
-                    ],
-                ]
-            ],
-            [
-                'name' => '文件库管理',
-                'submenu' => [
-                    [
-                        'name' => '文件分组',
-                        'index' => 'content.files.group/index',
-                        'uris' => [
-                            'content.files.group/index',
-                            'content.files.group/add',
-                            'content.files.group/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '文件列表',
-                        'index' => 'content.files/index'
-                    ],
-                    [
-                        'name' => '回收站',
-                        'index' => 'content.files/recycle',
-                    ],
-                ]
-            ],
-        ]
-    ],
-    'market' => [
-        'name' => '营销管理',
-        'icon' => 'icon-marketing',
-        'index' => 'market.coupon/index',
-        'submenu' => [
-            [
-                'name' => '优惠券',
+			],
+			[
+				'name'  => '已取消',
+				'index' => 'order/cancel_list',
+			],
+			[
+				'name'  => '售后管理',
+				'index' => 'order.refund/index',
+				'uris'  => [
+					'order.refund/index',
+					'order.refund/detail',
+				]
+			],
+		]
+	],
+	'user'       => [
+		'name'    => '用户管理',
+		'icon'    => 'icon-user',
+		'index'   => 'user/index',
+		'submenu' => [
+			[
+				'name'  => '用户列表',
+				'index' => 'user/index',
+			],
+			[
+				'name'    => '会员等级',
+				'active'  => true,
+				'submenu' => [
+					[
+						'name'  => '等级管理',
+						'index' => 'user.grade/index',
+						'uris'  => [
+							'user.grade/index',
+							'user.grade/add',
+							'user.grade/edit',
+							'user.grade/delete',
+						]
+					],
+				]
+			],
+			[
+				'name'    => '余额记录',
+				'active'  => true,
+				'submenu' => [
+					[
+						'name'  => '充值记录',
+						'index' => 'user.recharge/order',
+					],
+					[
+						'name'  => '余额明细',
+						'index' => 'user.balance/log',
+					],
+				]
+			],
+		]
+	],
+	'shop'       => [
+		'name'    => '门店管理',
+		'icon'    => 'icon-shop',
+		'index'   => 'shop/index',
+		'submenu' => [
+			[
+				'name'    => '门店管理',
+				'active'  => true,
+				'index'   => 'shop/index',
+				'submenu' => [
+					[
+						'name'  => '门店列表',
+						'index' => 'shop/index',
+						'uris'  => [
+							'shop/index',
+							'shop/add',
+							'shop/edit',
+						]
+					],
+					[
+						'name'  => '店员管理',
+						'index' => 'shop.clerk/index',
+						'uris'  => [
+							'shop.clerk/index',
+							'shop.clerk/add',
+							'shop.clerk/edit',
+						]
+					],
+				]
+			],
+			[
+				'name'  => '订单核销记录',
+				'index' => 'shop.order/index',
+			]
+		]
+	],
+	'content'    => [
+		'name'    => '内容管理',
+		'icon'    => 'icon-wenzhang',
+		'index'   => 'content.article/index',
+		'submenu' => [
+			[
+				'name'    => '文章管理',
+				'active'  => true,
+				'submenu' => [
+					[
+						'name'  => '文章列表',
+						'index' => 'content.article/index',
+						'uris'  => [
+							'content.article/index',
+							'content.article/add',
+							'content.article/edit',
+						]
+					],
+					[
+						'name'  => '文章分类',
+						'index' => 'content.article.category/index',
+						'uris'  => [
+							'content.article.category/index',
+							'content.article.category/add',
+							'content.article.category/edit',
+						]
+					],
+				]
+			],
+			[
+				'name'    => '文件库管理',
+				'submenu' => [
+					[
+						'name'  => '文件分组',
+						'index' => 'content.files.group/index',
+						'uris'  => [
+							'content.files.group/index',
+							'content.files.group/add',
+							'content.files.group/edit',
+						]
+					],
+					[
+						'name'  => '文件列表',
+						'index' => 'content.files/index'
+					],
+					[
+						'name'  => '回收站',
+						'index' => 'content.files/recycle',
+					],
+				]
+			],
+			[
+				'name'    => '资质管理',
+				'active'  => true,
+				'submenu' => [
+					[
+						'name'  => '资质列表',
+						'index' => 'content.certificate/index',
+						'uris'  => [
+							'content.certificate/index',
+							'content.certificate/add',
+							'content.certificate/edit',
+						]
+					],
+					[
+						'name'  => '资质分类',
+						'index' => 'content.certificate.category/index',
+						'uris'  => [
+							'content.certificate.category/index',
+							'content.certificate.category/add',
+							'content.certificate.category/edit',
+						]
+					],
+					[
+						'name'  => '资质申请',
+						'index' => 'content.certificate.watermark/index',
+						'uris'  => [
+							'content.certificate.watermark/index',
+							'content.certificate.watermark/add',
+							'content.certificate.watermark/edit',
+						]
+					],
+				]
+			],
+		]
+	],
+	'market'     => [
+		'name'    => '营销管理',
+		'icon'    => 'icon-marketing',
+		'index'   => 'market.coupon/index',
+		'submenu' => [
+			[
+				'name'    => '优惠券',
 //                'active' => true,
-                'submenu' => [
-                    [
-                        'name' => '优惠券列表',
-                        'index' => 'market.coupon/index',
-                        'uris' => [
-                            'market.coupon/index',
-                            'market.coupon/add',
-                            'market.coupon/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '领取记录',
-                        'index' => 'market.coupon/receive'
-                    ],
-                ]
-            ],
-            [
-                'name' => '用户充值',
-                'submenu' => [
-                    [
-                        'name' => '充值套餐',
-                        'index' => 'market.recharge.plan/index',
-                        'uris' => [
-                            'market.recharge.plan/index',
-                            'market.recharge.plan/add',
-                            'market.recharge.plan/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '充值设置',
-                        'index' => 'market.recharge/setting'
-                    ],
-                ]
-            ],
-            [
-                'name' => '积分管理',
-                'submenu' => [
-                    [
-                        'name' => '积分设置',
-                        'index' => 'market.points/setting'
-                    ],
-                    [
-                        'name' => '积分明细',
-                        'index' => 'market.points/log'
-                    ],
-                ]
-            ],
-            [
-                'name' => '消息推送',
-                'submenu' => [
-                    [
-                        'name' => '发送消息',
-                        'index' => 'market.push/send',
-                    ],
-                    [
-                        'name' => '活跃用户',
-                        'index' => 'market.push/user',
-                    ],
+				'submenu' => [
+					[
+						'name'  => '优惠券列表',
+						'index' => 'market.coupon/index',
+						'uris'  => [
+							'market.coupon/index',
+							'market.coupon/add',
+							'market.coupon/edit',
+						]
+					],
+					[
+						'name'  => '领取记录',
+						'index' => 'market.coupon/receive'
+					],
+				]
+			],
+			[
+				'name'    => '用户充值',
+				'submenu' => [
+					[
+						'name'  => '充值套餐',
+						'index' => 'market.recharge.plan/index',
+						'uris'  => [
+							'market.recharge.plan/index',
+							'market.recharge.plan/add',
+							'market.recharge.plan/edit',
+						]
+					],
+					[
+						'name'  => '充值设置',
+						'index' => 'market.recharge/setting'
+					],
+				]
+			],
+			[
+				'name'    => '积分管理',
+				'submenu' => [
+					[
+						'name'  => '积分设置',
+						'index' => 'market.points/setting'
+					],
+					[
+						'name'  => '积分明细',
+						'index' => 'market.points/log'
+					],
+				]
+			],
+			[
+				'name'    => '消息推送',
+				'submenu' => [
+					[
+						'name'  => '发送消息',
+						'index' => 'market.push/send',
+					],
+					[
+						'name'  => '活跃用户',
+						'index' => 'market.push/user',
+					],
 //                    [
 //                        'name' => '发送日志',
 //                        'index' => 'market.push/log',
 //                    ],
-                ]
-            ],
-            [
-                'name' => '满额包邮',
-                'index' => 'market.basic/full_free',
-            ],
-        ],
-    ],
-    'statistics' => [
-        'name' => '数据统计',
-        'icon' => 'icon-qushitu',
-        'index' => 'statistics.data/index',
-    ],
-    'wxapp' => [
-        'name' => '小程序',
-        'icon' => 'icon-wxapp',
-        'color' => '#36b313',
-        'index' => 'wxapp/setting',
-        'submenu' => [
-            [
-                'name' => '小程序设置',
-                'index' => 'wxapp/setting',
-            ],
-            [
-                'name' => '页面管理',
-                'active' => true,
-                'submenu' => [
-                    [
-                        'name' => '页面设计',
-                        'index' => 'wxapp.page/index',
-                        'uris' => [
-                            'wxapp.page/index',
-                            'wxapp.page/add',
-                            'wxapp.page/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '分类模板',
-                        'index' => 'wxapp.page/category'
-                    ],
-                    [
-                        'name' => '页面链接',
-                        'index' => 'wxapp.page/links'
-                    ]
-                ]
-            ],
-            [
-                'name' => '帮助中心',
-                'index' => 'wxapp.help/index',
-                'uris' => [
-                    'wxapp.help/index',
-                    'wxapp.help/add',
-                    'wxapp.help/edit'
-                ]
-            ],
-        ],
-    ],
-    'apps' => [
-        'name' => '应用中心',
-        'icon' => 'icon-application',
-        'is_svg' => true,   // 多色图标
-        'index' => 'apps.dealer.apply/index',
-        'submenu' => [
-            [
-                'name' => '分销中心',
-                'submenu' => [
-                    [
-                        'name' => '入驻申请',
-                        'index' => 'apps.dealer.apply/index',
-                    ],
-                    [
-                        'name' => '分销商用户',
-                        'index' => 'apps.dealer.user/index',
-                        'uris' => [
-                            'apps.dealer.user/index',
-                            'apps.dealer.user/edit',
-                            'apps.dealer.user/fans',
-                        ]
-                    ],
-                    [
-                        'name' => '分销订单',
-                        'index' => 'apps.dealer.order/index',
-                    ],
-                    [
-                        'name' => '提现申请',
-                        'index' => 'apps.dealer.withdraw/index',
-                    ],
-                    [
-                        'name' => '分销设置',
-                        'index' => 'apps.dealer.setting/index',
-                    ],
-                    [
-                        'name' => '分销海报',
-                        'index' => 'apps.dealer.setting/qrcode',
-                    ],
-                ]
-            ],
-            [
-                'name' => '拼团管理',
-                'submenu' => [
-                    [
-                        'name' => '商品分类',
-                        'index' => 'apps.sharing.category/index',
-                        'uris' => [
-                            'apps.sharing.category/index',
-                            'apps.sharing.category/add',
-                            'apps.sharing.category/edit',
-                        ]
-                    ],
-                    [
-                        'name' => '商品列表',
-                        'index' => 'apps.sharing.goods/index',
-                        'uris' => [
-                            'apps.sharing.goods/index',
-                            'apps.sharing.goods/add',
-                            'apps.sharing.goods/edit',
-                            'apps.sharing.goods/copy',
-                            'apps.sharing.goods/copy_master',
-                        ]
-                    ],
-                    [
-                        'name' => '拼单管理',
-                        'index' => 'apps.sharing.active/index',
-                        'uris' => [
-                            'apps.sharing.active/index',
-                            'apps.sharing.active/users',
-                        ]
-                    ],
-                    [
-                        'name' => '订单管理',
-                        'index' => 'apps.sharing.order/index',
-                        'uris' => [
-                            'apps.sharing.order/index',
-                            'apps.sharing.order/detail',
-                            'apps.sharing.order.operate/batchdelivery'
-                        ]
-                    ],
-                    [
-                        'name' => '售后管理',
-                        'index' => 'apps.sharing.order.refund/index',
-                        'uris' => [
-                            'apps.sharing.order.refund/index',
-                            'apps.sharing.order.refund/detail',
-                        ]
-                    ],
-                    [
-                        'name' => '商品评价',
-                        'index' => 'apps.sharing.comment/index',
-                        'uris' => [
-                            'apps.sharing.comment/index',
-                            'apps.sharing.comment/detail',
-                        ],
-                    ],
-                    [
-                        'name' => '拼团设置',
-                        'index' => 'apps.sharing.setting/index'
-                    ]
-                ]
-            ],
-            [
-                'name' => '砍价活动',
-                'index' => 'apps.bargain.active/index',
-                'submenu' => [
-                    [
-                        'name' => '活动列表',
-                        'index' => 'apps.bargain.active/index',
-                        'uris' => [
-                            'apps.bargain.active/index',
-                            'apps.bargain.active/add',
-                            'apps.bargain.active/edit',
-                            'apps.bargain.active/delete',
-                        ],
-                    ],
-                    [
-                        'name' => '砍价记录',
-                        'index' => 'apps.bargain.task/index',
-                        'uris' => [
-                            'apps.bargain.task/index',
-                            'apps.bargain.task/add',
-                            'apps.bargain.task/edit',
-                            'apps.bargain.task/delete',
-                            'apps.bargain.task/help',
-                        ],
-                    ],
-                    [
-                        'name' => '砍价设置',
-                        'index' => 'apps.bargain.setting/index',
-                    ]
-                ]
-            ],
-            [
-                'name' => '整点秒杀',
-                'index' => 'apps.sharp.goods/index',
-                'submenu' => [
-                    [
-                        'name' => '秒杀商品',
-                        'index' => 'apps.sharp.goods/index',
-                        'uris' => [
-                            'apps.sharp.goods/index',
-                            'apps.sharp.goods/add',
-                            'apps.sharp.goods/select',
-                            'apps.sharp.goods/edit',
-                            'apps.sharp.goods/delete',
-                        ],
-                    ],
-                    [
-                        'name' => '活动会场',
-                        'index' => 'apps.sharp.active/index',
-                        'uris' => [
-                            'apps.sharp.active/index',
-                            'apps.sharp.active/add',
-                            'apps.sharp.active/edit',
-                            'apps.sharp.active/state',
-                            'apps.sharp.active/delete',
+				]
+			],
+			[
+				'name'  => '满额包邮',
+				'index' => 'market.basic/full_free',
+			],
+		],
+	],
+	'statistics' => [
+		'name'  => '数据统计',
+		'icon'  => 'icon-qushitu',
+		'index' => 'statistics.data/index',
+	],
+	'wxapp'      => [
+		'name'    => '小程序',
+		'icon'    => 'icon-wxapp',
+		'color'   => '#36b313',
+		'index'   => 'wxapp/setting',
+		'submenu' => [
+			[
+				'name'  => '小程序设置',
+				'index' => 'wxapp/setting',
+			],
+			[
+				'name'    => '页面管理',
+				'active'  => true,
+				'submenu' => [
+					[
+						'name'  => '页面设计',
+						'index' => 'wxapp.page/index',
+						'uris'  => [
+							'wxapp.page/index',
+							'wxapp.page/add',
+							'wxapp.page/edit',
+						]
+					],
+					[
+						'name'  => '分类模板',
+						'index' => 'wxapp.page/category'
+					],
+					[
+						'name'  => '页面链接',
+						'index' => 'wxapp.page/links'
+					]
+				]
+			],
+			[
+				'name'  => '帮助中心',
+				'index' => 'wxapp.help/index',
+				'uris'  => [
+					'wxapp.help/index',
+					'wxapp.help/add',
+					'wxapp.help/edit'
+				]
+			],
+		],
+	],
+	'apps'       => [
+		'name'    => '应用中心',
+		'icon'    => 'icon-application',
+		'is_svg'  => true,   // 多色图标
+		'index'   => 'apps.dealer.apply/index',
+		'submenu' => [
+			[
+				'name'    => '分销中心',
+				'submenu' => [
+					[
+						'name'  => '入驻申请',
+						'index' => 'apps.dealer.apply/index',
+					],
+					[
+						'name'  => '分销商用户',
+						'index' => 'apps.dealer.user/index',
+						'uris'  => [
+							'apps.dealer.user/index',
+							'apps.dealer.user/edit',
+							'apps.dealer.user/fans',
+						]
+					],
+					[
+						'name'  => '分销订单',
+						'index' => 'apps.dealer.order/index',
+					],
+					[
+						'name'  => '提现申请',
+						'index' => 'apps.dealer.withdraw/index',
+					],
+					[
+						'name'  => '分销设置',
+						'index' => 'apps.dealer.setting/index',
+					],
+					[
+						'name'  => '分销海报',
+						'index' => 'apps.dealer.setting/qrcode',
+					],
+				]
+			],
+			[
+				'name'    => '拼团管理',
+				'submenu' => [
+					[
+						'name'  => '商品分类',
+						'index' => 'apps.sharing.category/index',
+						'uris'  => [
+							'apps.sharing.category/index',
+							'apps.sharing.category/add',
+							'apps.sharing.category/edit',
+						]
+					],
+					[
+						'name'  => '商品列表',
+						'index' => 'apps.sharing.goods/index',
+						'uris'  => [
+							'apps.sharing.goods/index',
+							'apps.sharing.goods/add',
+							'apps.sharing.goods/edit',
+							'apps.sharing.goods/copy',
+							'apps.sharing.goods/copy_master',
+						]
+					],
+					[
+						'name'  => '拼单管理',
+						'index' => 'apps.sharing.active/index',
+						'uris'  => [
+							'apps.sharing.active/index',
+							'apps.sharing.active/users',
+						]
+					],
+					[
+						'name'  => '订单管理',
+						'index' => 'apps.sharing.order/index',
+						'uris'  => [
+							'apps.sharing.order/index',
+							'apps.sharing.order/detail',
+							'apps.sharing.order.operate/batchdelivery'
+						]
+					],
+					[
+						'name'  => '售后管理',
+						'index' => 'apps.sharing.order.refund/index',
+						'uris'  => [
+							'apps.sharing.order.refund/index',
+							'apps.sharing.order.refund/detail',
+						]
+					],
+					[
+						'name'  => '商品评价',
+						'index' => 'apps.sharing.comment/index',
+						'uris'  => [
+							'apps.sharing.comment/index',
+							'apps.sharing.comment/detail',
+						],
+					],
+					[
+						'name'  => '拼团设置',
+						'index' => 'apps.sharing.setting/index'
+					]
+				]
+			],
+			[
+				'name'    => '砍价活动',
+				'index'   => 'apps.bargain.active/index',
+				'submenu' => [
+					[
+						'name'  => '活动列表',
+						'index' => 'apps.bargain.active/index',
+						'uris'  => [
+							'apps.bargain.active/index',
+							'apps.bargain.active/add',
+							'apps.bargain.active/edit',
+							'apps.bargain.active/delete',
+						],
+					],
+					[
+						'name'  => '砍价记录',
+						'index' => 'apps.bargain.task/index',
+						'uris'  => [
+							'apps.bargain.task/index',
+							'apps.bargain.task/add',
+							'apps.bargain.task/edit',
+							'apps.bargain.task/delete',
+							'apps.bargain.task/help',
+						],
+					],
+					[
+						'name'  => '砍价设置',
+						'index' => 'apps.bargain.setting/index',
+					]
+				]
+			],
+			[
+				'name'    => '整点秒杀',
+				'index'   => 'apps.sharp.goods/index',
+				'submenu' => [
+					[
+						'name'  => '秒杀商品',
+						'index' => 'apps.sharp.goods/index',
+						'uris'  => [
+							'apps.sharp.goods/index',
+							'apps.sharp.goods/add',
+							'apps.sharp.goods/select',
+							'apps.sharp.goods/edit',
+							'apps.sharp.goods/delete',
+						],
+					],
+					[
+						'name'  => '活动会场',
+						'index' => 'apps.sharp.active/index',
+						'uris'  => [
+							'apps.sharp.active/index',
+							'apps.sharp.active/add',
+							'apps.sharp.active/edit',
+							'apps.sharp.active/state',
+							'apps.sharp.active/delete',
 
-                            'apps.sharp.active_time/index',
-                            'apps.sharp.active_time/add',
-                            'apps.sharp.active_time/edit',
-                            'apps.sharp.active_time/state',
-                            'apps.sharp.active_time/delete',
-                        ],
-                    ],
-                    [
-                        'name' => '基础设置',
-                        'index' => 'apps.sharp.setting/index',
-                    ]
-                ]
-            ],
-            [
-                'name' => '好物圈',
-                'index' => 'apps.wow.shoping/index',
-                'submenu' => [
-                    [
-                        'name' => '商品收藏',
-                        'index' => 'apps.wow.shoping/index',
-                    ],
-                    [
-                        'name' => '订单信息',
-                        'index' => 'apps.wow.order/index',
-                    ],
-                    [
-                        'name' => '基础设置',
-                        'index' => 'apps.wow.setting/index',
-                    ]
-                ]
-            ],
-            // [
-            //     'name' => '小程序直播',
-            //     'index' => 'apps.live.room/index',
-            //     'submenu' => [
-            //         [
-            //             'name' => '直播间管理',
-            //             'index' => 'apps.live.room/index',
-            //         ],
-            //     ]
-            // ],
-        ]
-    ],
-    'setting' => [
-        'name' => '设置',
-        'icon' => 'icon-setting',
-        'index' => 'setting/store',
-        'submenu' => [
-            [
-                'name' => '商城设置',
-                'index' => 'setting/store',
-            ],
-            [
-                'name' => '交易设置',
-                'index' => 'setting/trade',
-            ],
-            [
-                'name' => '运费模板',
-                'index' => 'setting.delivery/index',
-                'uris' => [
-                    'setting.delivery/index',
-                    'setting.delivery/add',
-                    'setting.delivery/edit',
-                ],
-            ],
-            [
-                'name' => '物流公司',
-                'index' => 'setting.express/index',
-                'uris' => [
-                    'setting.express/index',
-                    'setting.express/add',
-                    'setting.express/edit',
-                ],
-            ],
-            [
-                'name' => '短信通知',
-                'index' => 'setting/sms'
-            ],
-            [
-                'name' => '模板消息',
-                'index' => 'setting/tplmsg',
-                'uris' => [
-                    'setting/tplmsg',
-                    'setting.help/tplmsg'
+							'apps.sharp.active_time/index',
+							'apps.sharp.active_time/add',
+							'apps.sharp.active_time/edit',
+							'apps.sharp.active_time/state',
+							'apps.sharp.active_time/delete',
+						],
+					],
+					[
+						'name'  => '基础设置',
+						'index' => 'apps.sharp.setting/index',
+					]
+				]
+			],
+			[
+				'name'    => '好物圈',
+				'index'   => 'apps.wow.shoping/index',
+				'submenu' => [
+					[
+						'name'  => '商品收藏',
+						'index' => 'apps.wow.shoping/index',
+					],
+					[
+						'name'  => '订单信息',
+						'index' => 'apps.wow.order/index',
+					],
+					[
+						'name'  => '基础设置',
+						'index' => 'apps.wow.setting/index',
+					]
+				]
+			],
+			// [
+			//     'name' => '小程序直播',
+			//     'index' => 'apps.live.room/index',
+			//     'submenu' => [
+			//         [
+			//             'name' => '直播间管理',
+			//             'index' => 'apps.live.room/index',
+			//         ],
+			//     ]
+			// ],
+		]
+	],
+	'setting'    => [
+		'name'    => '设置',
+		'icon'    => 'icon-setting',
+		'index'   => 'setting/store',
+		'submenu' => [
+			[
+				'name'  => '商城设置',
+				'index' => 'setting/store',
+			],
+			[
+				'name'  => '交易设置',
+				'index' => 'setting/trade',
+			],
+			[
+				'name'  => '运费模板',
+				'index' => 'setting.delivery/index',
+				'uris'  => [
+					'setting.delivery/index',
+					'setting.delivery/add',
+					'setting.delivery/edit',
+				],
+			],
+			[
+				'name'  => '物流公司',
+				'index' => 'setting.express/index',
+				'uris'  => [
+					'setting.express/index',
+					'setting.express/add',
+					'setting.express/edit',
+				],
+			],
+			[
+				'name'  => '短信通知',
+				'index' => 'setting/sms'
+			],
+			[
+				'name'  => '模板消息',
+				'index' => 'setting/tplmsg',
+				'uris'  => [
+					'setting/tplmsg',
+					'setting.help/tplmsg'
 
-                ],
-            ],
-            [
-                'name' => '退货地址',
-                'index' => 'setting.address/index',
-                'uris' => [
-                    'setting.address/index',
-                    'setting.address/add',
-                    'setting.address/edit',
-                ],
-            ],
-            [
-                'name' => '上传设置',
-                'index' => 'setting/storage',
-            ],
-            [
-                'name' => '小票打印机',
-                'submenu' => [
-                    [
-                        'name' => '打印机管理',
-                        'index' => 'setting.printer/index',
-                        'uris' => [
-                            'setting.printer/index',
-                            'setting.printer/add',
-                            'setting.printer/edit'
-                        ]
-                    ],
-                    [
-                        'name' => '打印设置',
-                        'index' => 'setting/printer'
-                    ]
-                ]
-            ],
-            [
-                'name' => '其他',
-                'submenu' => [
-                    [
-                        'name' => '清理缓存',
-                        'index' => 'setting.cache/clear'
-                    ]
-                ]
-            ]
-        ],
-    ],
+				],
+			],
+			[
+				'name'  => '退货地址',
+				'index' => 'setting.address/index',
+				'uris'  => [
+					'setting.address/index',
+					'setting.address/add',
+					'setting.address/edit',
+				],
+			],
+			[
+				'name'  => '上传设置',
+				'index' => 'setting/storage',
+			],
+			[
+				'name'    => '小票打印机',
+				'submenu' => [
+					[
+						'name'  => '打印机管理',
+						'index' => 'setting.printer/index',
+						'uris'  => [
+							'setting.printer/index',
+							'setting.printer/add',
+							'setting.printer/edit'
+						]
+					],
+					[
+						'name'  => '打印设置',
+						'index' => 'setting/printer'
+					]
+				]
+			],
+			[
+				'name'    => '其他',
+				'submenu' => [
+					[
+						'name'  => '清理缓存',
+						'index' => 'setting.cache/clear'
+					]
+				]
+			]
+		],
+	],
 ];

+ 99 - 0
dyu/application/store/model/Certificate.php

@@ -0,0 +1,99 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\model;
+
+use app\common\model\Certificate as CertificateModel;
+
+/**
+ * Class Certificate
+ * 资质管理
+ *
+ * @Author: Yeshihao
+ * @DateTime: 2024/11/26 14:01
+ * @package app\store\model
+ */
+class Certificate extends CertificateModel
+{
+	public function getList()
+	{
+		return $this->with(['file', 'category'])
+			->where('is_delete', '=', 0)
+			->order(['create_time' => 'desc'])
+			->paginate(15, false, [
+				'query' => request()->request()
+			]);
+	}
+
+	/**
+	 * [add]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:55
+	 * @param $data
+	 * @return false|int
+	 */
+	public function add($data)
+	{
+		if (empty($data['file_id'])) {
+			$this->error = '请上传资质文件';
+			return false;
+		}
+		if (empty($data['name'])) {
+			$this->error = '请输入资质名称';
+			return false;
+		}
+		//获取文件类型
+		$file              = UploadFile::detail($data['file_id']);
+		$data['file_type'] = $file['file_type'];
+		$data['wxapp_id']  = self::$wxapp_id;
+		return $this->allowField(true)->save($data);
+	}
+
+	/**
+	 * 更新记录
+	 *
+	 * @param $data
+	 * @return bool|int
+	 */
+	public function edit($data)
+	{
+		if (empty($data['file_id'])) {
+			$this->error = '请上传资质文件';
+			return false;
+		}
+		if (empty($data['name'])) {
+			$this->error = '请输入资质名称';
+			return false;
+		}
+		return $this->allowField(true)->save($data) !== false;
+	}
+
+
+
+	/**
+	 * [getCertificateTotal]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:31
+	 * @param array $where
+	 * @return int|string
+	 * @throws \think\Exception
+	 */
+	public static function getCertificateTotal($where = [])
+	{
+		$model = new static;
+		!empty($where) && $model->where($where);
+		return $model->where('is_delete', '=', 0)->count();
+	}
+
+
+
+}

+ 124 - 0
dyu/application/store/model/CertificateApply.php

@@ -0,0 +1,124 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\model;
+
+use app\common\model\CertificateApply as CertificateApplyModel;
+use app\common\service\watermark\WaterMarkBase;
+
+/**
+ * 拼团商品分类模型
+ * Class Category
+ *
+ * @package app\common\model
+ */
+class CertificateApply extends CertificateApplyModel
+{
+
+	/**
+	 * [getList]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 11:12
+	 * @return \think\Paginator
+	 * @throws \think\exception\DbException
+	 */
+	public function getList()
+	{
+		return $this->with(['applyUser'])
+			->where('is_delete', '=', 0)
+			->order(['create_time' => 'desc'])
+			->paginate(15, false, [
+				'query' => request()->request()
+			]);
+	}
+
+
+	/**
+	 * [add]
+	 * 新增申请
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/27 18:05
+	 * @param $data
+	 * @return false|int
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public function add($data)
+	{
+		//判断是否有资质文件
+		if (!isset($data['certificate_ids']) || empty($data['certificate_ids'])) {
+			$this->error = '请选择资质文件';
+			return false;
+		}
+		//获取资质文件信息
+		$certificateList = Certificate::getCertificateList(['id' => ['in', $data['certificate_ids']]]);
+		if ($certificateList->isEmpty()) {
+			$this->error = '查无相关资质文件';
+			return false;
+		}
+//		$result_data = [];
+//		foreach ($certificateList as $certificate) {
+//			$service = new WaterMarkBase($certificate['file']['file_path'], $data['watermark'], self::$wxapp_id, $certificate['file_type']);
+//			$result  = $service->waterMark();
+//		}
+		//获取文件类型
+		$data['wxapp_id']      = self::$wxapp_id;
+		$data['store_user_id'] = getStoreUserId();
+		return $this->allowField(true)->save($data);
+	}
+
+
+	/**
+	 * [edit]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/28 10:56
+	 * @param $data
+	 * @return false|int
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public function edit($data)
+	{
+		//申请拒绝
+		if ($data['status'] == 30) {
+			if (!isset($data['refuse_reason']) || empty($data['refuse_reason'])) {
+				$this->error = '请填写拒绝原因';
+				return false;
+			}
+		}
+		if ($data['status'] == 20) {
+			$result_data = [];
+			//获取资质文件信息
+			$certificateList = Certificate::getCertificateList(['id' => ['in', $this['certificate_ids']]]);
+			if ($certificateList->isEmpty()) {
+				$this->error = '查无相关资质文件';
+				return false;
+			}
+			foreach ($certificateList as $certificate) {
+				$service       = new WaterMarkBase($certificate['file']['file_path'], $this['watermark'], self::$wxapp_id, $certificate['file_type']);
+				$filePath      = $service->waterMark();
+				$result_data[] = [
+					'name'      => $certificate['name'],
+					'file_path' => $filePath,
+				];
+			}
+			$data['result_data'] = $result_data;
+		}
+
+		//获取文件类型
+		$data['apply_user_id'] = getStoreUserId();
+		return $this->allowField(true)->save($data);
+	}
+}

+ 82 - 0
dyu/application/store/model/CertificateCategory.php

@@ -0,0 +1,82 @@
+<?php
+
+/**
+ *
+ * @copyright ©2020 点小铺
+ * @author  hanj
+ * @link: https://dyuit.com
+ * Created by VSCode
+ */
+
+namespace app\store\model;
+
+use app\common\model\CertificateCategory as CertificateCategoryModel;
+use app\store\model\Certificate as CertificateModel;
+
+
+class CertificateCategory extends CertificateCategoryModel
+{
+
+
+	/**
+	 * [getALL]
+	 * 获取全部资质分类
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:19
+	 * @return array
+	 * @throws \think\db\exception\DataNotFoundException
+	 * @throws \think\db\exception\ModelNotFoundException
+	 * @throws \think\exception\DbException
+	 */
+	public static function getALL()
+	{
+		$model = new static;
+		return $model->order(['create_time' => 'asc'])->select()->toArray();
+	}
+
+	/**
+	 * [add]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:22
+	 * @param $data
+	 * @return false|int
+	 */
+	public function add($data)
+	{
+		$data['wxapp_id'] = self::$wxapp_id;
+		return $this->allowField(true)->save($data);
+	}
+
+	/**
+	 * [edit]
+	 *
+	 * @Author: Yeshihao
+	 * @DateTime: 2024/11/26 14:27
+	 * @param $data
+	 * @return false|int
+	 */
+	public function edit($data)
+	{
+		return $this->allowField(true)->save($data);
+	}
+
+
+	/**
+	 * 删除商品分类
+	 *
+	 * @param $category_id
+	 * @return bool|int
+	 */
+	public function remove($category_id)
+	{
+		// 判断是否存在文章
+		$count = CertificateModel::getCertificateTotal(['certificate_category_id' => $category_id]);
+		if ($count > 0) {
+			$this->error = '该分类下存在'.$count.'个文章,不允许删除';
+			return false;
+		}
+		return $this->delete();
+	}
+}

+ 96 - 0
dyu/application/store/view/content/certificate/add.php

@@ -0,0 +1,96 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">添加资质</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="name"
+                                           value="" placeholder="请输入标题" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质分类 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select name="certificate_category_id"
+                                            data-am-selected="{searchBox: 1, btnSize: 'sm',
+                                             placeholder:'请选择', maxHeight: 400}">
+                                        <option value=""></option>
+										<?php if (isset($category)): foreach ($category as $item): ?>
+                                            <option value="<?= $item['id'] ?>"><?= $item['name'] ?></option>
+										<?php endforeach; endif; ?>
+                                    </select>
+                                    <small class="am-margin-left-xs">
+                                        <a href="<?= url('content.certificate.category/add') ?>">去添加</a>
+                                    </small>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">文件上传 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <div class="am-form-file">
+                                        <div class="am-form-file">
+                                            <button type="button"
+                                                    class="upload-file am-btn am-btn-secondary am-radius">
+                                                <i class="am-icon-cloud-upload"></i> 选择文件
+                                            </button>
+                                            <div class="uploader-list am-cf">
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 图片文件列表模板 -->
+<script id="tpl-file-item" type="text/template">
+    {{ each list }}
+    <div class="file-item">
+        <a href="{{ $value.file_path }}" title="点击查看大图" target="_blank">
+            <img src="{{ $value.file_path }}">
+        </a>
+        <input type="hidden" name="{{ name }}" value="{{ $value.file_id }}">
+        <i class="iconfont icon-shanchu file-item-delete"></i>
+    </div>
+    {{ /each }}
+</script>
+
+<!-- 文件库弹窗 -->
+{{include file="layouts/_template/file_library" /}}
+
+<script>
+    $(function () {
+
+        // 选择图片
+        $('.upload-file').selectImages({
+            name: 'file_id',
+            type: ['image', 'pdf'],
+        });
+
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 42 - 0
dyu/application/store/view/content/certificate/category/add.php

@@ -0,0 +1,42 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">添加资质分类</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">分类名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="category[name]"
+                                           value="" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 42 - 0
dyu/application/store/view/content/certificate/category/edit.php

@@ -0,0 +1,42 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">编辑资质分类</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">分类名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="category[name]"
+                                           value="<?= $model['name'] ?>" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $(function () {
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 77 - 0
dyu/application/store/view/content/certificate/category/index.php

@@ -0,0 +1,77 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <div class="widget-head am-cf">
+                    <div class="widget-title am-cf">资质分类</div>
+                </div>
+                <div class="widget-body am-fr">
+                    <div class="am-u-sm-12 am-u-md-6 am-u-lg-6">
+                        <div class="am-form-group">
+                            <div class="am-btn-toolbar">
+								<?php if (checkPrivilege('content.certificate.category/add')): ?>
+                                    <div class="am-btn-group am-btn-group-xs">
+                                        <a class="am-btn am-btn-default am-btn-success am-radius"
+                                           href="<?= url('content.certificate.category/add') ?>">
+                                            <span class="am-icon-plus"></span> 新增
+                                        </a>
+                                    </div>
+								<?php endif; ?>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="am-u-sm-12">
+                        <table width="100%" class="am-table am-table-compact am-table-striped tpl-table-black">
+                            <thead>
+                            <tr>
+                                <th>分类ID</th>
+                                <th>分类名称</th>
+                                <th>添加时间</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+							<?php if (!empty($list)): foreach ($list as $first): ?>
+                                <tr>
+                                    <td class="am-text-middle"><?= $first['id'] ?></td>
+                                    <td class="am-text-middle"><?= $first['name'] ?></td>
+                                    <td class="am-text-middle"><?= $first['create_time'] ?></td>
+                                    <td class="am-text-middle">
+                                        <div class="tpl-table-black-operation">
+											<?php if (checkPrivilege('content.certificate.category/edit')): ?>
+                                                <a href="<?= url('content.certificate.category/edit',
+													['id' => $first['id']]) ?>">
+                                                    <i class="am-icon-pencil"></i> 编辑
+                                                </a>
+											<?php endif; ?>
+											<?php if (checkPrivilege('content.certificate.category/delete')): ?>
+                                                <a href="javascript:;" class="item-delete tpl-table-black-operation-del"
+                                                   data-id="<?= $first['id'] ?>">
+                                                    <i class="am-icon-trash"></i> 删除
+                                                </a>
+											<?php endif; ?>
+                                        </div>
+                                    </td>
+                                </tr>
+							<?php endforeach; else: ?>
+                                <tr>
+                                    <td colspan="5" class="am-text-center">暂无记录</td>
+                                </tr>
+							<?php endif; ?>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+        // 删除元素
+        var url = "<?= url('content.certificate.category/delete') ?>";
+        $('.item-delete').delete('id', url);
+
+    });
+</script>
+

+ 103 - 0
dyu/application/store/view/content/certificate/edit.php

@@ -0,0 +1,103 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">编辑资质</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质名称</label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="name"
+                                           value="<?= $model['name'] ?>" placeholder="请输入资质名称" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质分类 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select name="category_id"
+                                            data-am-selected="{searchBox: 1, btnSize: 'sm',
+                                             placeholder:'请选择', maxHeight: 400}">
+                                        <option value=""></option>
+										<?php if (isset($category)): foreach ($category as $item): ?>
+                                            <option value="<?= $item['id'] ?>"
+												<?= $model['certificate_category_id'] == $item['id'] ? 'selected' : '' ?>><?= $item['name'] ?></option>
+										<?php endforeach; endif; ?>
+                                    </select>
+                                    <small class="am-margin-left-xs">
+                                        <a href="<?= url('content.certificate.category/add') ?>">去添加</a>
+                                    </small>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">文件上传 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <div class="am-form-file">
+                                        <div class="am-form-file">
+                                            <button type="button"
+                                                    class="upload-file am-btn am-btn-secondary am-radius">
+                                                <i class="am-icon-cloud-upload"></i> 选择图片
+                                            </button>
+                                            <div class="uploader-list am-cf">
+                                                <div class="file-item">
+                                                    <a href="<?= $model['file']['file_path'] ?>" title="点击查看大图"
+                                                       target="_blank"><?= $model['file']['file_name'] ?>
+                                                    </a>
+                                                    <input type="hidden" name="file_id"
+                                                           value="<?= $model['file_id'] ?>">
+                                                    <i class="iconfont icon-shanchu file-item-delete"></i>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 图片文件列表模板 -->
+<script id="tpl-file-item" type="text/template">
+    {{ each list }}
+    <div class="file-item">
+        <a href="{{ $value.file_path }}" title="点击查看大图" target="_blank">
+            <img src="{{ $value.file_path }}">
+        </a>
+        <input type="hidden" name="{{ name }}" value="{{ $value.file_id }}">
+        <i class="iconfont icon-shanchu file-item-delete"></i>
+    </div>
+    {{ /each }}
+</script>
+
+<!-- 文件库弹窗 -->
+{{include file="layouts/_template/file_library" /}}
+<script>
+    $(function () {
+
+        // 选择图片
+        $('.upload-file').selectImages({
+            name: 'file_id',
+            type: ['image', 'pdf'],
+        });
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+    });
+</script>

+ 93 - 0
dyu/application/store/view/content/certificate/index.php

@@ -0,0 +1,93 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <div class="widget-head am-cf">
+                    <div class="widget-title am-cf">资质列表</div>
+                </div>
+                <div class="widget-body am-fr">
+                    <div class="am-u-sm-12 am-u-md-6 am-u-lg-6">
+                        <div class="am-form-group">
+                            <div class="am-btn-toolbar">
+								<?php if (checkPrivilege('content.certificate/add')): ?>
+                                    <div class="am-btn-group am-btn-group-xs">
+                                        <a class="am-btn am-btn-default am-btn-success am-radius"
+                                           href="<?= url('content.certificate/add') ?>">
+                                            <span class="am-icon-plus"></span> 新增
+                                        </a>
+                                    </div>
+								<?php endif; ?>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="am-scrollable-horizontal am-u-sm-12">
+                        <table width="100%" class="am-table am-table-compact am-table-striped
+                         tpl-table-black am-text-nowrap">
+                            <thead>
+                            <tr>
+                                <th>资质ID</th>
+                                <th>资质名称</th>
+                                <th>文件类型</th>
+                                <th>添加时间</th>
+                                <th>申请时间</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+							<?php if (!$list->isEmpty()): foreach ($list as $item): ?>
+                                <tr>
+                                    <td class="am-text-middle"><?= $item['id'] ?></td>
+                                    <td class="am-text-middle">
+                                        <p class="item-title"
+                                           style="max-width: 400px;"><?= $item['name'] ?></p>
+                                    </td>
+                                    <td class="am-text-middle"><?= $item['file_type'] ?></td>
+                                    <td class="am-text-middle"><?= $item['category']['name'] ?></td>
+                                    <td class="am-text-middle"><?= $item['create_time'] ?></td>
+                                    <td class="am-text-middle">
+                                        <div class="tpl-table-black-operation">
+											<?php if (checkPrivilege('content.certificate/edit')): ?>
+                                                <a href="<?= url('content.certificate/edit',
+													['id' => $item['id']]) ?>">
+                                                    <i class="am-icon-pencil"></i> 编辑
+                                                </a>
+											<?php endif; ?>
+											<?php if (checkPrivilege('content.certificate/delete')): ?>
+                                                <a href="javascript:void(0);"
+                                                   class="item-delete tpl-table-black-operation-del"
+                                                   data-id="<?= $item['id'] ?>">
+                                                    <i class="am-icon-trash"></i> 删除
+                                                </a>
+											<?php endif; ?>
+                                        </div>
+                                    </td>
+                                </tr>
+							<?php endforeach; else: ?>
+                                <tr>
+                                    <td colspan="10" class="am-text-center">暂无记录</td>
+                                </tr>
+							<?php endif; ?>
+                            </tbody>
+                        </table>
+                    </div>
+                    <div class="am-u-lg-12 am-cf">
+                        <div class="am-fr"><?= $list->render() ?> </div>
+                        <div class="am-fr pagination-total am-margin-right">
+                            <div class="am-vertical-align-middle">总记录:<?= $list->total() ?></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        // 删除元素
+        var url = "<?= url('content.certificate/delete') ?>";
+        $('.item-delete').delete('id', url);
+
+    });
+</script>
+

+ 170 - 0
dyu/application/store/view/content/certificate/watermark/add.php

@@ -0,0 +1,170 @@
+<style>
+    .am-selected {
+        width: 100%;
+    }
+</style>
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">资质申请</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">申请人 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="username"
+                                           value="" placeholder="请输入申请人" required>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">项目名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="project"
+                                           value="" placeholder="请输入项目名称" required>
+                                    <div class="help-block">
+                                        <small>填写资质申请的关联项目名称或者公司名称</small>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">申请用途 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="reason"
+                                           value="" placeholder="请输入项目名称" required>
+                                    <div class="help-block">
+                                        <small>填写申请资质材料的用途,如“招标”,“注册”,“采购入库”等</small>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">水印 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="watermark"
+                                           value="" placeholder="请输入水印" required>
+                                    <div class="help-block">
+                                        <small>如:“比亚迪供应商入库专用,他用无效”</small>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 活动时间 </label>
+                                <div class="am-u-sm-9 am-u-md-6 am-u-lg-5 am-u-end">
+                                    <!-- 会员等级列表-->
+                                    <div class="am-input-group">
+                                        <input type="text" class="j-laydate-start am-form-field"
+                                               name="indate"
+                                               placeholder="有效期"
+                                               value="">
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label ">申请备注 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                     <textarea rows="3" name="remark" placeholder="请输入申请用途"
+                                               class="am-field-valid"></textarea>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质分类 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select id="category_select" name="category_ids[]" data-am-selected="{searchBox: 1, btnSize: 'sm',
+                                             placeholder:'请选择', maxHeight: 400}" multiple required style="width: 100%">
+                                        <option value=""></option>
+										<?php if (isset($category)): foreach ($category as $item): ?>
+                                            <option value="<?= $item['id'] ?>"><?= $item['name'] ?></option>
+										<?php endforeach; endif; ?>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质资料 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <div id="checkboxContainer">
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                    <button type="submit" class="j-submit am-btn am-btn-secondary">提交
+                                    </button>
+                                </div>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+<script src="static/common/plugins/laydate/laydate.js"></script>
+
+<script>
+    $(function () {
+        // 时间选择器
+        laydate.render({
+            elem: '.j-laydate-start'
+            , type: 'date'
+        });
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+
+
+        // $('#addCheckbox').click(function() {
+        //     // 创建复选框的 HTML 代码
+        //     const checkboxHtml = ` <input type="checkbox" name="options" lay-skin="primary" title="新复选框"> `;
+        //     // 将复选框添加到页面中
+        //     $('#checkboxContainer').append(checkboxHtml);
+        //     // 使用 Layui 的 form 模块来渲染刚添加的复选框
+        //     layui.use('form', function() {
+        //         const form = layui.form;
+        //         form.render(); // 重新渲染
+        //     });
+        // });
+        var $selected = $('#category_select');
+        $selected.on('change', function () {
+            var url = "<?= url('content.certificate.watermark/getCertificateList') ?>";
+            var load = layer.load();
+            var category_ids = $(this).val();
+            console.log(category_ids);
+            $.post(url, {'category_ids': category_ids}, function (result) {
+                if (result.code === 1) {
+                    var data = result.data;
+                    $('#checkboxContainer').html('');
+                    $.each(data, function (index, item) {
+                        const checkboxHtml = '<label class="am-checkbox-inline"> <input required type="checkbox" name="certificate_ids[]" value="' + item.id + '"> ' + item.name + '</label>';
+                        $('#checkboxContainer').append(checkboxHtml);
+                    });
+                    // // 使用 Layui 的 form 模块来渲染刚添加的复选框
+                    // layui.use('form', function () {
+                    //     const form = layui.form;
+                    //     form.render(); // 重新渲染
+                    // });
+
+                }
+                layer.close(load);
+            });
+            console.log($(this).val());
+            // 创建复选框的 HTML 代码
+            // const checkboxHtml = ` <input type="checkbox" name="options" lay-skin="primary" title="新复选框"> `;
+            // // 将复选框添加到页面中
+            // $('#checkboxContainer').append(checkboxHtml);
+            // // 使用 Layui 的 form 模块来渲染刚添加的复选框
+            // layui.use('form', function() {
+            //     const form = layui.form;
+            //     form.render(); // 重新渲染
+            // });
+        });
+
+    });
+</script>

+ 167 - 0
dyu/application/store/view/content/certificate/watermark/edit.php

@@ -0,0 +1,167 @@
+<style>
+    .am-selected {
+        width: 100%;
+    }
+</style>
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <form id="my-form" class="am-form tpl-form-line-form" method="post">
+                    <div class="widget-body">
+                        <fieldset>
+                            <div class="widget-head am-cf">
+                                <div class="widget-title am-fl">资质审核</div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">申请人 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="username"
+                                           value="<?= $model['username'] ?>" placeholder="请输入申请人" disabled>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">项目名称 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="project"
+                                           value="<?= $model['project'] ?>" placeholder="请输入项目名称" disabled>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">申请用途 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="reason"
+                                           value="<?= $model['reason'] ?>" placeholder="请输入项目名称" disabled>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">水印 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <input type="text" class="tpl-form-input" name="watermark"
+                                           value="<?= $model['watermark'] ?>" placeholder="请输入水印" disabled>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 活动时间 </label>
+                                <div class="am-u-sm-9 am-u-md-6 am-u-lg-5 am-u-end">
+                                    <!-- 会员等级列表-->
+                                    <div class="am-input-group">
+                                        <input type="text" class="j-laydate-start am-form-field"
+                                               name="indate"
+                                               placeholder="有效期"
+                                               value="<?= $model['indate'] ?>" disabled>
+                                    </div>
+                                    <div class="help-block">
+                                        <small>砍价活动的开始时间与截止时间</small>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label ">申请备注 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                     <textarea rows="3" name="remark" placeholder="请输入申请用途"
+                                               class="am-field-valid" disabled><?= $model['remark'] ?></textarea>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质分类 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <select id="category_select" data-am-selected="{searchBox: 1, btnSize: 'sm',
+                                             placeholder:'请选择', maxHeight: 400}" multiple disabled style="width: 100%">
+                                        <option value=""></option>
+										<?php if (isset($category)): foreach ($category as $item): ?>
+                                            <option <?= in_array($item['id'], $model['category_ids']) ? 'selected' : '' ?>
+                                                    value="<?= $item['id'] ?>"><?= $item['name'] ?></option>
+										<?php endforeach; endif; ?>
+                                    </select>
+                                </div>
+                            </div>
+							<?php if ($model['status'] == 20): ?>
+                                <div class="am-form-group">
+                                    <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">水印下载 </label>
+                                    <div class="am-u-sm-9 am-u-end">
+                                        <a href="<?= url('content.certificate.watermark/zipDownload', ['id' => $model['id']]) ?>">zip打包下载</a>
+                                    </div>
+                                </div>
+							<?php endif; ?>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">资质资料 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <div id="checkboxContainer">
+										<?php if (isset($certificateList)): foreach ($certificateList as $certificate): ?>
+                                            <label class="am-checkbox-inline">
+                                                <input type="checkbox"
+                                                       disabled <?= in_array($certificate['id'], $model['certificate_ids']) ? 'checked' : '' ?> > <?= $certificate['name'] ?>
+                                            </label>
+										<?php endforeach; endif; ?>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="am-form-group">
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require">审批状态 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <label class="am-radio-inline">
+                                        <input type="radio" name="status" value="20" data-am-ucheck
+											<?= in_array($model['status'], [20]) ? 'checked' : '' ?> <?= ($model['status'] != 10) ? 'disabled' : '' ?>
+                                               required>
+                                        通过
+                                    </label>
+                                    <label class="am-radio-inline">
+                                        <input type="radio" name="status" value="30" data-am-ucheck
+											<?= $model['status'] == 30 ? 'checked' : '' ?> <?= $model['status'] != 10 ? 'disabled' : '' ?>
+                                               required>
+                                        拒绝
+                                    </label>
+                                </div>
+                            </div>
+                            <div id="reason_div" class="am-form-group" <?= $model['status'] != 30 ? 'hidden' : '' ?>>
+                                <label class="am-u-sm-3 am-u-lg-2 am-form-label form-require"> 审核拒绝原因 </label>
+                                <div class="am-u-sm-9 am-u-end">
+                                    <textarea rows="2" name="refuse_reason" id="reason_textarea" placeholder="请输入拒绝原因"
+                                              class="am-field-valid" <?= $model['status'] != 10 ? 'disabled' : '' ?> required><?= $model['refuse_reason'] ?></textarea>
+                                </div>
+                            </div>
+							<?php if ($model['status'] == 10): ?>
+                                <div class="am-form-group">
+                                    <div class="am-u-sm-9 am-u-sm-push-3 am-margin-top-lg">
+                                        <button type="submit" class="j-submit am-btn am-btn-secondary">审批
+                                        </button>
+                                    </div>
+                                </div>
+							<?php endif; ?>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+<script src="static/common/plugins/laydate/laydate.js"></script>
+
+<script>
+    $(function () {
+        // 时间选择器
+        laydate.render({
+            elem: '.j-laydate-start'
+            , type: 'date'
+        });
+
+        /**
+         * 表单验证提交
+         * @type {*}
+         */
+        $('#my-form').superForm();
+        $("input[name='status']").change(function () {
+            var num = $('input:radio[name="status"]:checked').val();
+            if (num == 20) {
+                $("#reason_div").hide();
+                $("#reason_textarea").val('');
+            } else {
+                $("#reason_div").show();
+            }
+        });
+
+    });
+</script>

+ 96 - 0
dyu/application/store/view/content/certificate/watermark/index.php

@@ -0,0 +1,96 @@
+<div class="row-content am-cf">
+    <div class="row">
+        <div class="am-u-sm-12 am-u-md-12 am-u-lg-12">
+            <div class="widget am-cf">
+                <div class="widget-head am-cf">
+                    <div class="widget-title am-cf">资质列表</div>
+                </div>
+                <div class="widget-body am-fr">
+                    <div class="am-u-sm-12 am-u-md-6 am-u-lg-6">
+                        <div class="am-form-group">
+                            <div class="am-btn-toolbar">
+								<?php if (checkPrivilege('content.certificate.watermark/add')): ?>
+                                    <div class="am-btn-group am-btn-group-xs">
+                                        <a class="am-btn am-btn-default am-btn-success am-radius"
+                                           href="<?= url('content.certificate.watermark/add') ?>">
+                                            <span class="am-icon-plus"></span> 新增
+                                        </a>
+                                    </div>
+								<?php endif; ?>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="am-scrollable-horizontal am-u-sm-12">
+                        <table width="100%" class="am-table am-table-compact am-table-striped
+                         tpl-table-black am-text-nowrap">
+                            <thead>
+                            <tr>
+                                <th>申请人</th>
+                                <th>申请时间</th>
+                                <th>项目名称</th>
+                                <th>申请用途</th>
+                                <th>申请结果</th>
+                                <th>审核人</th>
+                                <th>有效期</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+							<?php if (!$list->isEmpty()): foreach ($list as $item): ?>
+                                <tr>
+                                    <td class="am-text-middle"><?= $item['username'] ?></td>
+                                    <td class="am-text-middle"><?= $item['create_time'] ?></td>
+                                    <td class="am-text-middle"><?= $item['project'] ?></td>
+                                    <td class="am-text-middle"><?= $item['reason'] ?></td>
+                                    <td class="am-text-middle"><?= $item['status_text'] ?></td>
+                                    <td class="am-text-middle"><?= $item['applyUser']['real_name'] ?? '' ?></td>
+                                    <td class="am-text-middle"><?= $item['indate'] ?></td>
+                                    <td class="am-text-middle">
+                                        <div class="tpl-table-black-operation">
+											<?php if (checkPrivilege('content.certificate.watermark/edit')): ?>
+                                                <a href="<?= url('content.certificate.watermark/edit',
+													['id' => $item['id']]) ?>">
+                                                    <i class="am-icon-pencil"></i> <?= $item['status'] == 10 ? '审核' : '查看' ?>
+                                                </a>
+											<?php endif; ?>
+											<?php if (checkPrivilege('content.certificate.watermark/delete')): ?>
+												<?php if ($item['status'] == 10): ?>
+                                                    <a href="javascript:void(0);"
+                                                       class="item-delete tpl-table-black-operation-del"
+                                                       data-id="<?= $item['id'] ?>">
+                                                        <i class="am-icon-trash"></i> 取消申请
+                                                    </a>
+												<?php endif; ?>
+											<?php endif; ?>
+                                        </div>
+                                    </td>
+                                </tr>
+							<?php endforeach; else: ?>
+                                <tr>
+                                    <td colspan="10" class="am-text-center">暂无记录</td>
+                                </tr>
+							<?php endif; ?>
+                            </tbody>
+                        </table>
+                    </div>
+                    <div class="am-u-lg-12 am-cf">
+                        <div class="am-fr"><?= $list->render() ?> </div>
+                        <div class="am-fr pagination-total am-margin-right">
+                            <div class="am-vertical-align-middle">总记录:<?= $list->total() ?></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $(function () {
+
+        // 删除元素
+        var url = "<?= url('content.certificate.watermark/delete') ?>";
+        $('.item-delete').delete('id', url,'确认要取消申请吗');
+
+    });
+</script>
+

+ 77 - 0
dyu/application/task/controller/Test.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace app\task\controller;
+
+use TCPDF;
+
+class Test
+{
+
+	public function createPdf()
+	{
+		// 创建新的PDF文档
+		$pdf = new TCPDF();
+
+		// 设置文档信息
+		$pdf->SetCreator(PDF_CREATOR);
+		$pdf->SetAuthor('Your Name');
+		$pdf->SetTitle('PDF with Watermark');
+		$pdf->SetSubject('TCPDF Tutorial');
+		$pdf->SetKeywords('TCPDF, PDF, example, test, guide');
+
+		// 设置默认的头信息, 传入空字符串禁用
+		$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE.' 001', PDF_HEADER_STRING);
+
+		// 设置头部和底部字体
+		$pdf->setHeaderFont([PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN]);
+		$pdf->setFooterFont([PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA]);
+
+		// 移除默认的页脚
+		$pdf->setPrintFooter(false);
+
+		// 设置默认的单元格边距
+		$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
+
+		// 设置间距
+		$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
+		$pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM);
+
+		// 设置图像比例因子
+		$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
+
+		// 设置默认的字体,这里设置为DejaVuSans
+//		$pdf->SetFont('dejavusans', '', 14);
+
+		// 添加页面内容
+		$pdf->AddPage();
+		$pdf->Write(0, "I'm a simple text to test the watermark.\n");
+
+		// 设置水印文字
+		$watermarkText = "水印水印水印水印水印";
+		$pdf->SetFont('msyh', '', 50);
+
+		// 计算斜着文字的起始坐标
+		$x = $pdf->getX();
+		$y = $pdf->getY();
+
+// 设置斜着文字的角度
+		$angle = 45;
+
+// 使用Rotate()函数插入斜着的文字水印
+		$pdf->StartTransform();
+		$pdf->Rotate($angle, $x, $y);
+		$pdf->SetTextColor(200, 200, 200);
+		$pdf->Text($x, $y, $watermarkText);
+		$pdf->StopTransform();
+
+//		$pdf->SetTextColor(200, 200, 200);
+//		$pdf->SetXY(20, 50);
+//		$pdf->Write(0, 'Watermark');
+//		$pdf->SetXY(100, 50);
+//		$pdf->Write(0, '水印'); //中文乱码
+
+		$pdf->Output(WEB_PATH.'temp'.'/'.'AA.pdf', 'F'); //生成PDF文件到某地
+		// 输出PDF
+		$pdf->Output('AA.pdf', 'I');
+	}
+}

+ 2 - 1
dyu/composer.json

@@ -31,7 +31,8 @@
     "qcloud/cos-sdk-v5": "^1.2",
     "kosinix/grafika": "dev-master",
     "myclabs/php-enum": "^1.6",
-    "lvht/geohash": "^1.1"
+    "lvht/geohash": "^1.1",
+    "mpdf/mpdf": "^8.2"
   },
   "autoload": {
     "psr-4": {

+ 1674 - 0
dyu/composer.lock

@@ -0,0 +1,1674 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "e3fffe0e94dac722e5b111e088d2a333",
+    "packages": [
+        {
+            "name": "aliyuncs/oss-sdk-php",
+            "version": "v2.7.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/aliyun/aliyun-oss-php-sdk.git",
+                "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/aliyun/aliyun-oss-php-sdk/zipball/483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+                "reference": "483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "*",
+                "phpunit/phpunit": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "OSS\\": "src/OSS"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Aliyuncs",
+                    "homepage": "http://www.aliyun.com"
+                }
+            ],
+            "description": "Aliyun OSS SDK for PHP",
+            "homepage": "http://www.aliyun.com/product/oss/",
+            "support": {
+                "issues": "https://github.com/aliyun/aliyun-oss-php-sdk/issues",
+                "source": "https://github.com/aliyun/aliyun-oss-php-sdk/tree/v2.7.2"
+            },
+            "time": "2024-10-28T10:41:12+00:00"
+        },
+        {
+            "name": "guzzlehttp/command",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/command.git",
+                "reference": "2aaa2521a8f8269d6f5dfc13fe2af12c76921034"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/command/zipball/2aaa2521a8f8269d6f5dfc13fe2af12c76921034",
+                "reference": "2aaa2521a8f8269d6f5dfc13fe2af12c76921034",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "guzzlehttp/guzzle": "^6.2",
+                "guzzlehttp/promises": "~1.3",
+                "guzzlehttp/psr7": "~1.0",
+                "php": ">=5.5.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0|~5.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Command\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Jeremy Lindblom",
+                    "email": "jeremeamia@gmail.com",
+                    "homepage": "https://github.com/jeremeamia"
+                }
+            ],
+            "description": "Provides the foundation for building command-based web service clients",
+            "support": {
+                "issues": "https://github.com/guzzle/command/issues",
+                "source": "https://github.com/guzzle/command/tree/1.0.0"
+            },
+            "time": "2016-11-24T13:34:15+00:00"
+        },
+        {
+            "name": "guzzlehttp/guzzle",
+            "version": "6.5.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/guzzle.git",
+                "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981",
+                "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "guzzlehttp/promises": "^1.0",
+                "guzzlehttp/psr7": "^1.9",
+                "php": ">=5.5",
+                "symfony/polyfill-intl-idn": "^1.17"
+            },
+            "require-dev": {
+                "ext-curl": "*",
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+                "psr/log": "^1.1"
+            },
+            "suggest": {
+                "psr/log": "Required for using the Log middleware"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "6.5-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "GuzzleHttp\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Jeremy Lindblom",
+                    "email": "jeremeamia@gmail.com",
+                    "homepage": "https://github.com/jeremeamia"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                }
+            ],
+            "description": "Guzzle is a PHP HTTP client library",
+            "homepage": "http://guzzlephp.org/",
+            "keywords": [
+                "client",
+                "curl",
+                "framework",
+                "http",
+                "http client",
+                "rest",
+                "web service"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/guzzle/issues",
+                "source": "https://github.com/guzzle/guzzle/tree/6.5.8"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-06-20T22:16:07+00:00"
+        },
+        {
+            "name": "guzzlehttp/guzzle-services",
+            "version": "1.1.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/guzzle-services.git",
+                "reference": "9e3abf20161cbf662d616cbb995f2811771759f7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/guzzle-services/zipball/9e3abf20161cbf662d616cbb995f2811771759f7",
+                "reference": "9e3abf20161cbf662d616cbb995f2811771759f7",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "guzzlehttp/command": "~1.0",
+                "guzzlehttp/guzzle": "^6.2",
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "suggest": {
+                "gimler/guzzle-description-loader": "^0.0.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GuzzleHttp\\Command\\Guzzle\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Jeremy Lindblom",
+                    "email": "jeremeamia@gmail.com",
+                    "homepage": "https://github.com/jeremeamia"
+                },
+                {
+                    "name": "Stefano Kowalke",
+                    "email": "blueduck@mail.org",
+                    "homepage": "https://github.com/konafets"
+                }
+            ],
+            "description": "Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.",
+            "support": {
+                "issues": "https://github.com/guzzle/guzzle-services/issues",
+                "source": "https://github.com/guzzle/guzzle-services/tree/1.1.3"
+            },
+            "time": "2017-10-06T14:32:02+00:00"
+        },
+        {
+            "name": "guzzlehttp/promises",
+            "version": "1.5.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/promises.git",
+                "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e",
+                "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "symfony/phpunit-bridge": "^4.4 || ^5.1"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "GuzzleHttp\\Promise\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                }
+            ],
+            "description": "Guzzle promises library",
+            "keywords": [
+                "promise"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/promises/issues",
+                "source": "https://github.com/guzzle/promises/tree/1.5.3"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-05-21T12:31:43+00:00"
+        },
+        {
+            "name": "guzzlehttp/psr7",
+            "version": "1.9.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/guzzle/psr7.git",
+                "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/e4490cabc77465aaee90b20cfc9a770f8c04be6b",
+                "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.4.0",
+                "psr/http-message": "~1.0",
+                "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+            },
+            "provide": {
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "ext-zlib": "*",
+                "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
+            },
+            "suggest": {
+                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions_include.php"
+                ],
+                "psr-4": {
+                    "GuzzleHttp\\Psr7\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Michael Dowling",
+                    "email": "mtdowling@gmail.com",
+                    "homepage": "https://github.com/mtdowling"
+                },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
+                {
+                    "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
+                    "homepage": "https://github.com/Tobion"
+                }
+            ],
+            "description": "PSR-7 message implementation that also provides common utility methods",
+            "keywords": [
+                "http",
+                "message",
+                "psr-7",
+                "request",
+                "response",
+                "stream",
+                "uri",
+                "url"
+            ],
+            "support": {
+                "issues": "https://github.com/guzzle/psr7/issues",
+                "source": "https://github.com/guzzle/psr7/tree/1.9.1"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-04-17T16:00:37+00:00"
+        },
+        {
+            "name": "kosinix/grafika",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kosinix/grafika.git",
+                "reference": "211f61fc334b8b36616b23e8af7c5727971d96ee"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/kosinix/grafika/zipball/211f61fc334b8b36616b23e8af7c5727971d96ee",
+                "reference": "211f61fc334b8b36616b23e8af7c5727971d96ee",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "default-branch": true,
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Grafika\\": "src/Grafika"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT",
+                "GPL-2.0+"
+            ],
+            "authors": [
+                {
+                    "name": "Nico Amarilla",
+                    "homepage": "https://www.kosinix.com"
+                }
+            ],
+            "description": "An image manipulation library for PHP.",
+            "homepage": "http://kosinix.github.io/grafika",
+            "keywords": [
+                "grafika"
+            ],
+            "support": {
+                "issues": "https://github.com/kosinix/grafika/issues",
+                "source": "https://github.com/kosinix/grafika/tree/2.0.8"
+            },
+            "time": "2017-06-20T03:13:49+00:00"
+        },
+        {
+            "name": "lvht/geohash",
+            "version": "v1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/lvht/geohash.git",
+                "reference": "bbba3e1b487f0ec2e5e666c1bc9d1d4277990a29"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/lvht/geohash/zipball/bbba3e1b487f0ec2e5e666c1bc9d1d4277990a29",
+                "reference": "bbba3e1b487f0ec2e5e666c1bc9d1d4277990a29",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Lvht\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "吕海涛",
+                    "email": "git@lvht.net",
+                    "homepage": "https://github.com/lvht"
+                }
+            ],
+            "description": "geohash like python-geohash",
+            "homepage": "http://github.com/lvht/geohash",
+            "keywords": [
+                "geohash"
+            ],
+            "support": {
+                "issues": "https://github.com/lvht/geohash/issues",
+                "source": "https://github.com/lvht/geohash/tree/master"
+            },
+            "time": "2017-08-24T11:05:30+00:00"
+        },
+        {
+            "name": "mpdf/mpdf",
+            "version": "v8.2.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/mpdf/mpdf.git",
+                "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/mpdf/mpdf/zipball/e175b05e3e00977b85feb96a8cccb174ac63621f",
+                "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-gd": "*",
+                "ext-mbstring": "*",
+                "mpdf/psr-http-message-shim": "^1.0 || ^2.0",
+                "mpdf/psr-log-aware-trait": "^2.0 || ^3.0",
+                "myclabs/deep-copy": "^1.7",
+                "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
+                "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
+                "psr/http-message": "^1.0 || ^2.0",
+                "psr/log": "^1.0 || ^2.0 || ^3.0",
+                "setasign/fpdi": "^2.1"
+            },
+            "require-dev": {
+                "mockery/mockery": "^1.3.0",
+                "mpdf/qrcode": "^1.1.0",
+                "squizlabs/php_codesniffer": "^3.5.0",
+                "tracy/tracy": "~2.5",
+                "yoast/phpunit-polyfills": "^1.0"
+            },
+            "suggest": {
+                "ext-bcmath": "Needed for generation of some types of barcodes",
+                "ext-xml": "Needed mainly for SVG manipulation",
+                "ext-zlib": "Needed for compression of embedded resources, such as fonts"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/functions.php"
+                ],
+                "psr-4": {
+                    "Mpdf\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0-only"
+            ],
+            "authors": [
+                {
+                    "name": "Matěj Humpál",
+                    "role": "Developer, maintainer"
+                },
+                {
+                    "name": "Ian Back",
+                    "role": "Developer (retired)"
+                }
+            ],
+            "description": "PHP library generating PDF files from UTF-8 encoded HTML",
+            "homepage": "https://mpdf.github.io",
+            "keywords": [
+                "pdf",
+                "php",
+                "utf-8"
+            ],
+            "support": {
+                "docs": "https://mpdf.github.io",
+                "issues": "https://github.com/mpdf/mpdf/issues",
+                "source": "https://github.com/mpdf/mpdf"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/mpdf",
+                    "type": "custom"
+                }
+            ],
+            "time": "2024-11-18T15:30:42+00:00"
+        },
+        {
+            "name": "mpdf/psr-http-message-shim",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/mpdf/psr-http-message-shim.git",
+                "reference": "3206e6b80b6d2479e148ee497e9f2bebadc919db"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/3206e6b80b6d2479e148ee497e9f2bebadc919db",
+                "reference": "3206e6b80b6d2479e148ee497e9f2bebadc919db",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "psr/http-message": "^1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Mpdf\\PsrHttpMessageShim\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Dorison",
+                    "email": "mark@chromatichq.com"
+                },
+                {
+                    "name": "Kristofer Widholm",
+                    "email": "kristofer@chromatichq.com"
+                },
+                {
+                    "name": "Nigel Cunningham",
+                    "email": "nigel.cunningham@technocrat.com.au"
+                }
+            ],
+            "description": "Shim to allow support of different psr/message versions.",
+            "support": {
+                "issues": "https://github.com/mpdf/psr-http-message-shim/issues",
+                "source": "https://github.com/mpdf/psr-http-message-shim/tree/1.0.0"
+            },
+            "time": "2023-09-01T05:59:47+00:00"
+        },
+        {
+            "name": "mpdf/psr-log-aware-trait",
+            "version": "v2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/mpdf/psr-log-aware-trait.git",
+                "reference": "7a077416e8f39eb626dee4246e0af99dd9ace275"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/mpdf/psr-log-aware-trait/zipball/7a077416e8f39eb626dee4246e0af99dd9ace275",
+                "reference": "7a077416e8f39eb626dee4246e0af99dd9ace275",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "psr/log": "^1.0 || ^2.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Mpdf\\PsrLogAwareTrait\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Dorison",
+                    "email": "mark@chromatichq.com"
+                },
+                {
+                    "name": "Kristofer Widholm",
+                    "email": "kristofer@chromatichq.com"
+                }
+            ],
+            "description": "Trait to allow support of different psr/log versions.",
+            "support": {
+                "issues": "https://github.com/mpdf/psr-log-aware-trait/issues",
+                "source": "https://github.com/mpdf/psr-log-aware-trait/tree/v2.0.0"
+            },
+            "time": "2023-05-03T06:18:28+00:00"
+        },
+        {
+            "name": "myclabs/deep-copy",
+            "version": "1.11.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/DeepCopy.git",
+                "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+                "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": "^7.1 || ^8.0"
+            },
+            "conflict": {
+                "doctrine/collections": "<1.6.8",
+                "doctrine/common": "<2.13.3 || >=3,<3.2.2"
+            },
+            "require-dev": {
+                "doctrine/collections": "^1.6.8",
+                "doctrine/common": "^2.13.3 || ^3.2.2",
+                "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/DeepCopy/deep_copy.php"
+                ],
+                "psr-4": {
+                    "DeepCopy\\": "src/DeepCopy/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Create deep copies (clones) of your objects",
+            "keywords": [
+                "clone",
+                "copy",
+                "duplicate",
+                "object",
+                "object graph"
+            ],
+            "support": {
+                "issues": "https://github.com/myclabs/DeepCopy/issues",
+                "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
+            },
+            "funding": [
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-03-08T13:26:56+00:00"
+        },
+        {
+            "name": "myclabs/php-enum",
+            "version": "1.8.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/php-enum.git",
+                "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483",
+                "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "php": "^7.3 || ^8.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5",
+                "squizlabs/php_codesniffer": "1.*",
+                "vimeo/psalm": "^4.6.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "MyCLabs\\Enum\\": "src/"
+                },
+                "classmap": [
+                    "stubs/Stringable.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP Enum contributors",
+                    "homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
+                }
+            ],
+            "description": "PHP Enum implementation",
+            "homepage": "http://github.com/myclabs/php-enum",
+            "keywords": [
+                "enum"
+            ],
+            "support": {
+                "issues": "https://github.com/myclabs/php-enum/issues",
+                "source": "https://github.com/myclabs/php-enum/tree/1.8.4"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/mnapoli",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-08-04T09:53:51+00:00"
+        },
+        {
+            "name": "paragonie/random_compat",
+            "version": "v9.99.100",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/paragonie/random_compat.git",
+                "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
+                "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">= 7"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*|5.*",
+                "vimeo/psalm": "^1"
+            },
+            "suggest": {
+                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+            },
+            "type": "library",
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paragon Initiative Enterprises",
+                    "email": "security@paragonie.com",
+                    "homepage": "https://paragonie.com"
+                }
+            ],
+            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+            "keywords": [
+                "csprng",
+                "polyfill",
+                "pseudorandom",
+                "random"
+            ],
+            "support": {
+                "email": "info@paragonie.com",
+                "issues": "https://github.com/paragonie/random_compat/issues",
+                "source": "https://github.com/paragonie/random_compat"
+            },
+            "time": "2020-10-15T08:29:30+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-message.git",
+                "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+                "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/http-message/tree/1.1"
+            },
+            "time": "2023-04-04T09:50:52+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.1.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+                "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "Psr/Log/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "support": {
+                "source": "https://github.com/php-fig/log/tree/1.1.4"
+            },
+            "time": "2021-05-03T11:20:27+00:00"
+        },
+        {
+            "name": "qcloud/cos-sdk-v5",
+            "version": "v1.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/tencentyun/cos-php-sdk-v5.git",
+                "reference": "e67ad8143695192ee206bcbcafc78c08da92c621"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/tencentyun/cos-php-sdk-v5/zipball/e67ad8143695192ee206bcbcafc78c08da92c621",
+                "reference": "e67ad8143695192ee206bcbcafc78c08da92c621",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "guzzlehttp/guzzle": "~6.3",
+                "guzzlehttp/guzzle-services": "~1.1",
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/Qcloud/Cos/Common.php"
+                ],
+                "psr-4": {
+                    "Qcloud\\Cos\\": "src/Qcloud/Cos/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "yaozongyou",
+                    "email": "yaozongyou@vip.qq.com"
+                },
+                {
+                    "name": "lewzylu",
+                    "email": "327874225@qq.com"
+                }
+            ],
+            "description": "PHP SDK for QCloud COS",
+            "keywords": [
+                "cos",
+                "php",
+                "qcloud"
+            ],
+            "support": {
+                "issues": "https://github.com/tencentyun/cos-php-sdk-v5/issues",
+                "source": "https://github.com/tencentyun/cos-php-sdk-v5/tree/v2.2.0"
+            },
+            "time": "2021-05-18T12:47:31+00:00"
+        },
+        {
+            "name": "qiniu/php-sdk",
+            "version": "v7.14.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/qiniu/php-sdk.git",
+                "reference": "ee752ffa7263ce99fca0bd7340cf13c486a3516c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/qiniu/php-sdk/zipball/ee752ffa7263ce99fca0bd7340cf13c486a3516c",
+                "reference": "ee752ffa7263ce99fca0bd7340cf13c486a3516c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-curl": "*",
+                "ext-xml": "*",
+                "myclabs/php-enum": "~1.5.2 || ~1.6.6 || ~1.7.7 || ~1.8.4",
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "paragonie/random_compat": ">=2",
+                "phpunit/phpunit": "^4.8 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4",
+                "squizlabs/php_codesniffer": "^2.3 || ~3.6"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/Qiniu/functions.php",
+                    "src/Qiniu/Http/Middleware/Middleware.php"
+                ],
+                "psr-4": {
+                    "Qiniu\\": "src/Qiniu"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Qiniu",
+                    "email": "sdk@qiniu.com",
+                    "homepage": "http://www.qiniu.com"
+                }
+            ],
+            "description": "Qiniu Resource (Cloud) Storage SDK for PHP",
+            "homepage": "http://developer.qiniu.com/",
+            "keywords": [
+                "cloud",
+                "qiniu",
+                "sdk",
+                "storage"
+            ],
+            "support": {
+                "issues": "https://github.com/qiniu/php-sdk/issues",
+                "source": "https://github.com/qiniu/php-sdk/tree/v7.14.0"
+            },
+            "time": "2024-10-25T08:39:01+00:00"
+        },
+        {
+            "name": "ralouphie/getallheaders",
+            "version": "3.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ralouphie/getallheaders.git",
+                "reference": "120b605dfeb996808c31b6477290a714d356e822"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+                "reference": "120b605dfeb996808c31b6477290a714d356e822",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "require-dev": {
+                "php-coveralls/php-coveralls": "^2.1",
+                "phpunit/phpunit": "^5 || ^6.5"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/getallheaders.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ralph Khattar",
+                    "email": "ralph.khattar@gmail.com"
+                }
+            ],
+            "description": "A polyfill for getallheaders.",
+            "support": {
+                "issues": "https://github.com/ralouphie/getallheaders/issues",
+                "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+            },
+            "time": "2019-03-08T08:55:37+00:00"
+        },
+        {
+            "name": "setasign/fpdi",
+            "version": "v2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Setasign/FPDI.git",
+                "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6db878129ec6c7e141316ee71872923e7f1b7ad",
+                "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-zlib": "*",
+                "php": "^5.6 || ^7.0 || ^8.0"
+            },
+            "conflict": {
+                "setasign/tfpdf": "<1.31"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~5.7",
+                "setasign/fpdf": "~1.8.6",
+                "setasign/tfpdf": "~1.33",
+                "squizlabs/php_codesniffer": "^3.5",
+                "tecnickcom/tcpdf": "~6.2"
+            },
+            "suggest": {
+                "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured."
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "setasign\\Fpdi\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jan Slabon",
+                    "email": "jan.slabon@setasign.com",
+                    "homepage": "https://www.setasign.com"
+                },
+                {
+                    "name": "Maximilian Kresse",
+                    "email": "maximilian.kresse@setasign.com",
+                    "homepage": "https://www.setasign.com"
+                }
+            ],
+            "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.",
+            "homepage": "https://www.setasign.com/fpdi",
+            "keywords": [
+                "fpdf",
+                "fpdi",
+                "pdf"
+            ],
+            "support": {
+                "issues": "https://github.com/Setasign/FPDI/issues",
+                "source": "https://github.com/Setasign/FPDI/tree/v2.6.0"
+            },
+            "funding": [
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-12-11T16:03:32+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-idn",
+            "version": "v1.31.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-idn.git",
+                "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
+                "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2",
+                "symfony/polyfill-intl-normalizer": "^1.10"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Idn\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Laurent Bassin",
+                    "email": "laurent@bassin.info"
+                },
+                {
+                    "name": "Trevor Rowbotham",
+                    "email": "trevor.rowbotham@pm.me"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "idn",
+                "intl",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "symfony/polyfill-intl-normalizer",
+            "version": "v1.31.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+                "reference": "3833d7255cc303546435cb650316bff708a1c75c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+                "reference": "3833d7255cc303546435cb650316bff708a1c75c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "suggest": {
+                "ext-intl": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for intl's Normalizer class and related functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "intl",
+                "normalizer",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-09T11:45:10+00:00"
+        },
+        {
+            "name": "topthink/framework",
+            "version": "v5.0.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/framework.git",
+                "reference": "643c58ed1bd22a2823ce5e95b3b68a5075f9087c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/framework/zipball/643c58ed1bd22a2823ce5e95b3b68a5075f9087c",
+                "reference": "643c58ed1bd22a2823ce5e95b3b68a5075f9087c",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.4.0",
+                "topthink/think-installer": "~1.0"
+            },
+            "require-dev": {
+                "johnkary/phpunit-speedtrap": "^1.0",
+                "mikey179/vfsstream": "~1.6",
+                "phpdocumentor/reflection-docblock": "^2.0",
+                "phploc/phploc": "2.*",
+                "phpunit/phpunit": "4.8.*",
+                "sebastian/phpcpd": "2.*"
+            },
+            "type": "think-framework",
+            "autoload": {
+                "psr-4": {
+                    "think\\": "library/think"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "the new thinkphp framework",
+            "homepage": "http://thinkphp.cn/",
+            "keywords": [
+                "framework",
+                "orm",
+                "thinkphp"
+            ],
+            "support": {
+                "issues": "https://github.com/top-think/framework/issues",
+                "source": "https://github.com/top-think/framework/tree/v5.0.25"
+            },
+            "time": "2022-10-25T14:59:38+00:00"
+        },
+        {
+            "name": "topthink/think-installer",
+            "version": "v1.0.14",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/top-think/think-installer.git",
+                "reference": "eae1740ac264a55c06134b6685dfb9f837d004d1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/top-think/think-installer/zipball/eae1740ac264a55c06134b6685dfb9f837d004d1",
+                "reference": "eae1740ac264a55c06134b6685dfb9f837d004d1",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "composer-plugin-api": "^1.0||^2.0"
+            },
+            "require-dev": {
+                "composer/composer": "^1.0||^2.0"
+            },
+            "type": "composer-plugin",
+            "extra": {
+                "class": "think\\composer\\Plugin"
+            },
+            "autoload": {
+                "psr-4": {
+                    "think\\composer\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "support": {
+                "issues": "https://github.com/top-think/think-installer/issues",
+                "source": "https://github.com/top-think/think-installer/tree/v1.0.14"
+            },
+            "time": "2021-03-25T08:34:02+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "kosinix/grafika": 20
+    },
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=5.4.0",
+        "ext-pdo": "*",
+        "ext-curl": "*",
+        "ext-json": "*",
+        "ext-bcmath": "*",
+        "ext-gd": "*",
+        "ext-openssl": "*",
+        "ext-libxml": "*",
+        "ext-simplexml": "*",
+        "ext-zlib": "*"
+    },
+    "platform-dev": [],
+    "plugin-api-version": "2.0.0"
+}

+ 1 - 1
dyu/thinkphp/composer.json

@@ -22,7 +22,7 @@
     "require-dev": {
         "phpunit/phpunit": "4.8.*",
         "johnkary/phpunit-speedtrap": "^1.0",
-        "mikey179/vfsStream": "~1.6",
+        "mikey179/vfsstream": "~1.6",
         "phploc/phploc": "2.*",
         "sebastian/phpcpd": "2.*",
         "phpdocumentor/reflection-docblock": "^2.0"

+ 6 - 0
dyu/thinkphp/library/think/Lang.php

@@ -211,6 +211,12 @@ class Lang
             }
         }
 
+        if (preg_match('/^([a-z\d\-]+)/i', $langSet, $matches)) {
+            $langSet = strtolower($matches[1]);
+        } else {
+            $langSet = self::$range;
+        }
+
         // 合法的语言
         if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) {
             self::$range = $langSet ?: self::$range;

+ 1 - 1
dyu/thinkphp/library/think/cache/driver/Redis.php

@@ -70,7 +70,7 @@ class Redis extends Driver
      */
     public function has($name)
     {
-        return $this->handler->exists($this->getCacheKey($name));
+        return (bool) $this->handler->exists($this->getCacheKey($name));
     }
 
     /**

BIN
dyu/thinkphp/library/think/console/bin/hiddeninput.exe


+ 1 - 1
dyu/thinkphp/library/think/db/Query.php

@@ -1952,7 +1952,7 @@ class Query
         if (!empty($this->pk)) {
             $pk = $this->pk;
         } else {
-            $pk = $this->getTableInfo(is_array($options) ? $options['table'] : $options, 'pk');
+            $pk = $this->getTableInfo(is_array($options) && isset($options['table']) ? $options['table'] : $options, 'pk');
         }
         return $pk;
     }

+ 13 - 11
dyu/thinkphp/library/think/log/driver/File.php

@@ -85,13 +85,11 @@ class File
      */
     protected function getMasterLogFile()
     {
+        $cli = PHP_SAPI == 'cli' ? '_cli' : '';
         if ($this->config['single']) {
-            $name = is_string($this->config['single']) ? $this->config['single'] : 'single';
-
-            $destination = $this->config['path'] . $name . '.log';
+            $name        = is_string($this->config['single']) ? $this->config['single'] : 'single';
+            $destination = $this->config['path'] . $name . $cli . '.log';
         } else {
-            $cli = PHP_SAPI == 'cli' ? '_cli' : '';
-
             if ($this->config['max_files']) {
                 $filename = date('Ymd') . $cli . '.log';
                 $files    = glob($this->config['path'] . '*.log');
@@ -125,15 +123,13 @@ class File
 
         if ($this->config['single']) {
             $name = is_string($this->config['single']) ? $this->config['single'] : 'single';
-
-            $name .= '_' . $type;
         } elseif ($this->config['max_files']) {
-            $name = date('Ymd') . '_' . $type . $cli;
+            $name = date('Ymd');
         } else {
-            $name = date('d') . '_' . $type . $cli;
+            $name = date('d');
         }
 
-        return $path . DIRECTORY_SEPARATOR . $name . '.log';
+        return $path . DIRECTORY_SEPARATOR . $name . '_' . $type . $cli . '.log';
     }
 
     /**
@@ -154,7 +150,13 @@ class File
         $info['timestamp'] = date($this->config['time_format']);
 
         foreach ($message as $type => $msg) {
-            $info[$type] = is_array($msg) ? implode("\r\n", $msg) : $msg;
+            $msg = is_array($msg) ? implode("\r\n", $msg) : $msg;
+            if (PHP_SAPI == 'cli') {
+                $info['msg']  = $msg;
+                $info['type'] = $type;
+            } else {
+                $info[$type] = $msg;
+            }
         }
 
         if (PHP_SAPI == 'cli') {

+ 1 - 1
dyu/thinkphp/library/think/process/pipes/Windows.php

@@ -196,7 +196,7 @@ class Windows extends Pipes
             return;
         }
 
-        if (null !== $w && 0 < count($r)) {
+        if (null !== $r && 0 < count($r)) {
             $data = '';
             while ($dataread = fread($r['input'], self::CHUNK_SIZE)) {
                 $data .= $dataread;

BIN
dyu/thinkphp/logo.png


BIN
web/static/common/fonts/msyh.ttf


+ 21 - 7
web/static/store/js/app.js

@@ -38,7 +38,14 @@
                     }
                 },
                 submit: function () {
-                    if (this.isFormValid() === true) {
+                    // console.log($form);
+                    // return false;
+                    var _this=this;
+                    // layer.confirm('是否确认提交?', {
+                    //     icon: 1,        //会出现正确的图片
+                    //     btn: ['确定', '取消']     //按钮
+                    // }, function (index) {
+                    if (_this.isFormValid() === true) {
                         // 自定义验证
                         if (options.validation.call(true) === false) {
                             return false;
@@ -61,6 +68,7 @@
                             }
                         });
                     }
+                    // });
                     return false;
                 }
             });
@@ -75,9 +83,11 @@
                 param[index] = $(this).attr('data-id');
                 layer.confirm(msg ? msg : '确定要删除吗?', {title: '友情提示'}
                     , function (index) {
+                        var load=layer.load();
                         $.post(url, param, function (result) {
                             result.code === 1 ? $.show_success(result.msg, result.url)
                                 : $.show_error(result.msg);
+                            layer.close(load);
                         });
                         layer.close(index);
                     }
@@ -96,15 +106,18 @@
                     name: 'iFile'            // input name
                     , imagesList: '.uploader-list'    // 图片列表容器
                     , imagesItem: '.file-item'       // 图片元素容器
+                    , imagesTpl: 'tpl-file-item'     // 图片元素模板
                     , imageDelete: '.file-item-delete'  // 删除按钮元素
                     , multiple: false    // 是否多选
                     , limit: null        // 图片数量 (如果存在done回调函数则无效)
                     , done: null  // 选择完成后的回调函数
+                    ,maxSize:5*1024
+                    , type: []
                 }
                 , options = $.extend({}, defaults, option);
             // 显示文件库 选择文件
             $this.fileLibrary({
-                type: 'image'
+                type: options.type
                 , done: function (data, $touch) {
                     // 判断回调参数是否存在, 否则执行默认
                     if (typeof options.done === 'function') {
@@ -112,7 +125,7 @@
                     }
                     // 新增图片列表
                     var list = options.multiple ? data : [data[0]];
-                    var $html = $(template('tpl-file-item', {list: list, name: options.name}))
+                    var $html = $(template(options.imagesTpl, {list: list, name: options.name}))
                         , $imagesList = $this.next(options.imagesList);
                     if (
                         options.limit > 0
@@ -123,11 +136,12 @@
                     }
                     // 注册删除事件
                     $html.find(options.imageDelete).click(function () {
-                        $(this).parent().remove();
+                        $(this).parents(options.imagesItem).remove();
                     });
                     // 渲染html
                     options.multiple ? $imagesList.append($html) : $imagesList.html($html);
                 }
+                ,maxSize:options.maxSize
             });
         },
 
@@ -172,7 +186,7 @@
                 if (data.hasOwnProperty(key)) value = data[key];
                 if (value.constructor === Array) {
                     value.forEach(function (_value) {
-                        _result.push(key + "=" + _value);
+                        _result.push(key + "[]=" + _value);
                     });
                 } else {
                     _result.push(key + '=' + value);
@@ -356,7 +370,7 @@
                 , title: options.title
                 , closeBtn: options.closeBtn
                 , area: options.area
-                , offset: 'auto'
+                , offset: options.offset
                 , anim: 1
                 , shade: 0.3
                 , btn: options.btn
@@ -459,7 +473,7 @@ $(function () {
         layer.confirm('您确定要删除该' + (name ? name : '图片') + '吗?', {
             title: '友情提示'
         }, function (index) {
-            $this.parent().remove();
+            $this.parents(".file-item").remove();
             layer.close(index);
         });
     });

+ 52 - 12
web/static/store/js/file.library.js

@@ -9,9 +9,14 @@
     function FileLibrary(trigger, options) {
         // 配置项
         var defaults = {
-            type: 'image',
+            type: [],
             layerId: 'file-library'
             , layerSkin: 'file-library'
+            , accept: {
+                title: 'Images',
+                extensions: 'gif,jpg,jpeg,bmp,png',
+                mimeTypes: 'image/*'
+            },
         };
         this.options = $.extend({}, defaults, options);
         // 触发对象
@@ -59,13 +64,13 @@
          */
         showLibraryModal: function () {
             var _this = this;
-            _this.getJsonData({group_id: -1}, function (data) {
+            _this.getJsonData({group_id: -1, type_arr: _this.options.type}, function (data) {
                 data.is_default = true;
                 // 捕获页
                 layer.open({
                     type: 1
                     , id: _this.options.layerId
-                    , title: '图片库'
+                    , title: '文件库'
                     , skin: _this.options.layerSkin
                     , area: '840px'
                     , offset: 'auto'
@@ -107,6 +112,8 @@
             _this.editGroupEvent();
             // 删除分组事件
             _this.deleteGroupEvent();
+            //注意上传类型
+            _this.uploadFileType();
             // 注册文件上传事件
             _this.uploadImagesEvent();
             // 注册文件删除事件
@@ -135,6 +142,41 @@
             });
         },
 
+        /**
+         *  注册上传文件类型
+         */
+        uploadFileType: function () {
+            var _this = this;
+            var type = _this.options.type;
+            //判断传入的值是否是数组
+            // if (type instanceof Array == false) {
+            //     return;
+            // }
+            if (!Array.isArray(type)) {
+                return;
+            }
+            var extensions = '';
+            var mimeTypes = '';
+            $.each(type, function (index, item) {
+                if (item == 'image') {
+                    extensions += 'gif,jpg,jpeg,bmp,png,';
+                    mimeTypes += 'image/*,';
+                }
+                if (item == 'pdf') {
+                    extensions += 'pdf,';
+                    mimeTypes += 'application/pdf,';
+                }
+                if (item == 'video') {
+                    extensions += 'mp4,';
+                    mimeTypes += 'video/mp4,';
+                }
+            })
+            _this.options.accept = {
+                extensions: extensions,
+                mimeTypes: mimeTypes,
+            };
+        },
+
         /**
          * 文件移动事件
          */
@@ -200,7 +242,7 @@
             var _this = this;
             var loadIndex = null;
             // 文件大小
-            var maxSize = 2;
+            var maxSize = this.options.maxSize;
             // 初始化Web Uploader
             var uploader = WebUploader.create({
                 // 选完文件后,是否自动上传。
@@ -222,13 +264,9 @@
                 // 文件总数量
                 // fileNumLimit: 10,
                 // 文件大小2m => 2097152
-                fileSingleSizeLimit: maxSize * 1024 * 1024,
+                fileSingleSizeLimit: maxSize * 1024,
                 // 只允许选择图片文件。
-                accept: {
-                    title: 'Images',
-                    extensions: 'gif,jpg,jpeg,bmp,png',
-                    mimeTypes: 'image/*'
-                },
+                accept: this.options.accept,
                 // 文件上传header扩展
                 headers: {
                     'Accept': 'application/json, text/javascript, */*; q=0.01',
@@ -240,7 +278,7 @@
                 if (type === 'F_DUPLICATE') {
                     console.log('请不要重复选择文件!');
                 } else if (type === 'F_EXCEED_SIZE') {
-                    alert('文件大小不可超过' + maxSize + 'm 哦!换个小点的文件吧!');
+                    alert('文件大小不可超过' + maxSize/1024 + 'm 哦!换个小点的文件吧!');
                 }
             });
             // 文件上传前触发,添加附带参数
@@ -371,6 +409,8 @@
                     , data = {
                     file_id: $this.data('file-id')
                     , file_path: $this.data('file-path')
+                    , cover_file_path: $this.data('cover-file-path')
+                    , origin_name: $this.data('origin-name')
                 }
                     , selectedList = _this.data.selectedList
                     , index = $.arrayFilterMultiple(selectedList, 'file_id', data.file_id);
@@ -429,7 +469,7 @@
             var _this = this
                 , groupId = this.getCurrentGroupId();
             // 重新渲染文件列表
-            _this.getJsonData({group_id: groupId, page: page || 1}, function (data) {
+            _this.getJsonData({group_id: groupId, page: page || 1,type_arr: _this.options.type}, function (data) {
                 _this.$element.find('#file-list-body').html(template('tpl-file-list', data['file_list']));
             });
             // 清空选中的文件