Browse Source

海报插件和方正字体

lizhen_gitee 1 year ago
parent
commit
a18ce472a9

+ 1 - 0
addons/poster/.addonrc

@@ -0,0 +1 @@
+{"files":["application\\admin\\controller\\Poster.php","application\\admin\\lang\\zh-cn\\poster.php","application\\admin\\model\\Poster.php","application\\admin\\model\\PosterLog.php","application\\admin\\validate\\Poster.php","application\\admin\\view\\poster\\add.html","application\\admin\\view\\poster\\edit.html","application\\admin\\view\\poster\\index.html","application\\admin\\view\\poster\\posterrecord.html","application\\index\\controller\\Poster.php","application\\index\\view\\poster\\index.html","public\\assets\\js\\backend\\poster.js","public\\assets\\js\\frontend\\poster.js","public\\assets\\addons\\poster\\images\\colorful.png","public\\assets\\addons\\poster\\images\\default.png","public\\assets\\addons\\poster\\images\\head.jpg","public\\assets\\addons\\poster\\images\\img.jpg","public\\assets\\addons\\poster\\images\\qr.jpg","public\\assets\\addons\\poster\\js\\designer.js","public\\assets\\addons\\poster\\js\\jquery.colorpicker.min.js","public\\assets\\addons\\poster\\js\\jquery.contextMenu.js"],"license":"regular","licenseto":"19079","licensekey":"giB6XFp8O4eV02Ya CAQ3gsw12y462HR8CufcRQ==","domains":["zhongyi.com"],"licensecodes":[],"validations":["1bdbbcf301965bd6a1f749e1db7676cf"],"menus":["poster","poster\/index","poster\/add","poster\/edit","poster\/del","poster\/multi","poster\/posterrecord","poster\/clear"]}

+ 83 - 0
addons/poster/Poster.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace addons\poster;
+
+use app\common\library\Menu;
+use think\Addons;
+use think\Request;
+
+/**
+ * 超级海报管理插件
+ */
+class Poster extends Addons
+{
+    /**
+     * 插件安装方法
+     * @return bool
+     */
+    public function install()
+    {
+        $menu = [
+            [
+                'name'    => 'poster',
+                'title'   => '超级海报',
+                'icon'    => 'fa fa-qrcode',
+                'remark'  => '设计生成海报,支持会员昵称、头像、自定义图片、自定义二维码。',
+                'sublist' => [
+                    ['name' => 'poster/index', 'title' => '查看'],
+                    ['name' => 'poster/add', 'title' => '添加'],
+                    ['name' => 'poster/edit', 'title' => '修改'],
+                    ['name' => 'poster/del', 'title' => '删除'],
+                    ['name' => 'poster/multi', 'title' => '批量更新'],
+                    ['name' => 'poster/posterrecord', 'title' => '查看记录'],
+                    ['name' => 'poster/clear', 'title' => '清除海报'],
+                ]
+            ]
+        ];
+        Menu::create($menu);
+        return true;
+    }
+
+    /**
+     * 插件卸载方法
+     * @return bool
+     */
+    public function uninstall()
+    {
+        Menu::delete('poster');
+        return true;
+    }
+    
+    /**
+     * 插件启用方法
+     */
+    public function enable()
+    {
+        Menu::enable('poster');
+    }
+
+    /**
+     * 插件禁用方法
+     */
+    public function disable()
+    {
+        Menu::disable('poster');
+    }
+
+    /**
+     * 会员中心边栏后
+     * @return mixed
+     * @throws \Exception
+     */
+    public function userSidenavAfter()
+    {
+        $request = Request::instance();
+        $controllername = strtolower($request->controller());
+        $actionname = strtolower($request->action());
+        $data = [
+            'actionname'     => $actionname,
+            'controllername' => $controllername
+        ];
+        return $this->fetch('view/hook/user_sidenav_after', $data);
+    }
+}

+ 34 - 0
addons/poster/README.md

@@ -0,0 +1,34 @@
+# 超级海报
+
+#### 介绍
+1.支持生成和管理和生成多个海报
+2.可查看会员海报缓存和一键清除海报缓存数据和文件
+3.海报支持,会员头像,昵称,图片,自定义二维码
+4.可拖放移动位置,可拖拉放大缩小
+5.昵称支持颜色设置和字体大小设置
+
+#### 注意事项
+为了兼容更多系统,二维码采用了自定义表字段的形式生成,图片地址远程地址和本地均支持。
+二维码表: 你的二维码所在表
+二维码字段:二维码字段(本地文件或远程地址)
+二维码关联字段:(与会员关联的字段)
+
+#### 软件架构
+基于fastadmin开发的应用插件
+
+
+#### 安装教程
+
+1. 安装FastAdmin已经安装的请忽略,未安装的可以参考[FastAdmin框架安装文档](https://doc.fastadmin.net/doc/install.html)
+
+2. 如果你是直接从官网插件市场购买下载的,那么你下载的压缩包只是插件的核心文件,你需要先安装FastAdmin,然后在后台管理->插件管理->在线/离线安装即可。
+
+
+#### 码云特技
+
+1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
+2.  码云官方博客 [blog.gitee.com](https://blog.gitee.com)
+3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
+4.  [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
+5.  码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
+6.  码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 7 - 0
addons/poster/bootstrap.js

@@ -0,0 +1,7 @@
+require.config({
+    paths: {
+        'designer': '../addons/poster/js/designer',
+        'jquery.contextMenu': '../addons/poster/js/jquery.contextMenu',
+        'jquery-colorpicker': '../addons/poster/js/jquery.colorpicker.min',
+    }
+});

+ 5 - 0
addons/poster/config.php

@@ -0,0 +1,5 @@
+<?php
+
+return [
+    
+];

+ 13 - 0
addons/poster/controller/Index.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace addons\poster\controller;
+
+use think\addons\Controller;
+
+class Index extends Controller
+{
+    public function index()
+    {
+        $this->error("当前插件暂无前台页面");
+    }
+}

+ 10 - 0
addons/poster/info.ini

@@ -0,0 +1,10 @@
+name = poster
+title = 超级海报
+intro = 设计生成海报,支持会员昵称、头像、自定义图片、自定义二维码。
+author = Xing6
+website = http://www.fastadmin.net
+version = 1.0.4
+state = 1
+url = /addons/poster
+license = regular
+licenseto = 19079

+ 31 - 0
addons/poster/install.sql

@@ -0,0 +1,31 @@
+-- ----------------------------
+-- Table structure for __PREFIX__poster
+-- ----------------------------
+CREATE TABLE `__PREFIX__poster` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+  `title` varchar(255) DEFAULT '' COMMENT '海报名称',
+  `waittext` varchar(255) DEFAULT '' COMMENT '生成等待文字',
+  `bg_image` varchar(255) DEFAULT '' COMMENT '背景图片',
+  `data` text COMMENT '数据',
+  `status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态',
+  `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
+  `createtime` int(10) DEFAULT NULL COMMENT '创建时间',
+  `updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  KEY `idx_createtime` (`createtime`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='超级海报表';
+
+-- ----------------------------
+-- Table structure for __PREFIX__poster_log
+-- ----------------------------
+CREATE TABLE `__PREFIX__poster_log` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录ID',
+  `poster_id` int(11) DEFAULT '0' COMMENT '海报ID',
+  `user_id` int(11) DEFAULT '0' COMMENT '会员ID',
+  `image` varchar(255) DEFAULT '' COMMENT '海报图片',
+  `createtime` int(10) DEFAULT NULL COMMENT '创建时间',
+  `updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  KEY `idx_poster_id` (`poster_id`),
+  KEY `idx_user_id` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='海报记录表';

+ 190 - 0
addons/poster/library/Image.php

@@ -0,0 +1,190 @@
+<?php
+
+namespace addons\poster\library;
+
+use think\Db;
+
+class Image
+{
+    protected $target;      //图像资源
+    protected $poster_url;  //海报url
+    protected $model;       //海报模型
+
+    public function __construct()
+    {
+        $this->model = new \app\admin\model\Poster;
+    }
+
+
+    /**
+     * 创建海报
+     * @author Created by Xing <464401240@qq.com>
+     */
+    public function createPosterImage($poster, $member)
+    {
+        $path = $this->model->getDirs($poster['id']);
+        if (!is_dir($path)) {
+            $this->mkdirs($path);
+        }
+        $md5 = md5(json_encode(array(
+            'user_id'   => $member['id'],
+            'bg'        => $poster['bg_image'],
+            'data'      => $poster['data'],
+            'poster_id' => $poster['id']
+        )));
+        $file = $md5 . '.png';
+        $this->poster_url = $path . $file;
+        if (is_file($this->poster_url)) {
+            return $this->poster_url; //文件存在则直接返回
+        }
+
+        set_time_limit(0);
+        @ini_set('memory_limit', '256M');
+        $this->target = imagecreatetruecolor(640, 750);
+
+        $white = imagecolorallocate($this->target, 255, 255, 255);
+        imagefill($this->target, 0, 0, $white);
+        $bg = $this->createImage($poster['bg_image']);
+        if (!empty($bg)) {
+            $bgWidth = imagesx($bg);
+            $bgHeight = imagesy($bg);
+            $ratio = 640 / $bgWidth;
+            $newWidth = imagesx($bg) * $ratio;
+            $newHeight = imagesy($bg) * $ratio;
+
+            $bgClone = imagecreatetruecolor($newWidth, $newHeight);
+            imagecopyresampled($bgClone, $bg, 0, 0, 0, 0, $newWidth, $newHeight, $bgWidth, $bgHeight);
+
+            imagecopy($this->target, $bgClone, 0, 0, 0, 0, $newWidth, $newHeight);
+
+            imagedestroy($bg);
+            imagedestroy($bgClone);
+        }
+        $data = json_decode(str_replace('&quot;', '\'', $poster['data']), true);
+
+        foreach ($data as $d) {
+            $d = $this->getRealData($d);
+            if ($d['type'] == 'head') {
+                $avatar = preg_replace('/\\/0$/i', '/96', $member['avatar']);
+                $this->mergeImage($d, $avatar);
+            } elseif ($d['type'] == 'img' && isset($d['src'])) {
+                $this->mergeImage($d, $d['src']);
+            } elseif ($d['type'] == 'qr' && isset($d['qr_table']) && isset($d['qr_relation']) && isset($d['qr_field'])) {
+                $exist = Db::query('show tables like "' . $d['qr_table'] . '"');
+                if ($exist) {
+                    $fields = Db::getConnection()->getFields($d['qr_table']); //传入数据表名称 $tablename
+                    if (isset($fields[$d['qr_relation']])) {
+                        $qrimg = Db::table($d['qr_table'])->where([$d['qr_relation'] => $member['id']])->value($d['qr_field']);
+                        $this->mergeImage($d, $qrimg);
+                    }
+                }
+            } elseif ($d['type'] == 'nickname') {
+//                $this->mergeText($d, $member['nickname']);
+                $this->mergeText($d, $d['content']);
+            }
+        }
+
+        header("Content-Type:image/png");
+        imagepng($this->target, $path . $file);
+        imagedestroy($this->target);
+
+        $params['poster_id'] = $poster['id'];
+        $params['user_id'] = $member['id'];
+        $params['image'] = $this->poster_url;
+        //$posterLog = new \app\admin\model\PosterLog();
+        //$posterLog->save($params);
+        return $this->poster_url;
+    }
+
+    public function mergeImage($data, $imgurl)
+    {
+        $img = $this->createImage($imgurl);
+        if (!$img) {
+            return false;
+        }
+        $w = imagesx($img);
+        $h = imagesy($img);
+        imagecopyresized($this->target, $img, $data['left'], $data['top'], 0, 0, $data['width'], $data['height'], $w, $h);
+        imagedestroy($img);
+    }
+
+    public function mergeText($data, $text)
+    {
+//        $font = ROOT_PATH . 'public/assets/fonts/SourceHanSansK-Regular.ttf';
+        $font = ROOT_PATH . '/public/assets/fonts/fangzheng.ttf';
+
+        if (!isset($data['color'])) {
+            $data['color'] = '#000';
+        }
+
+//        $text = mb_convert_encoding($text, "GB2312", "UTF-8");
+//        $text = iconv('gb2312','utf-8',$text);//解决乱码问题
+        $colors = $this->hex2rgb($data['color']);
+        $color = imagecolorallocate($this->target, $colors['red'], $colors['green'], $colors['blue']);
+        imagettftext($this->target, $data['size'], 0, $data['left'], $data['top'] + $data['size'], $color, $font, $text);
+    }
+
+    public function createImage($imgurl)
+    {
+        if (strpos($imgurl, 'data:image') !== false) {
+            $imgurl = '/assets/addons/poster/images/head.jpg';
+        }
+        if (strpos($imgurl, '://') === false) {
+            $imgurl = ROOT_PATH . '/public' . $imgurl;
+            if (!is_file($imgurl)) {
+                return '';
+            }
+        }
+        @$content = file_get_contents($imgurl);
+        if ($content) {
+            return imagecreatefromstring($content);
+        }
+        return '';
+    }
+
+    private function getRealData($data)
+    {
+        $data['left'] = isset($data['left']) ? intval(str_replace('px', '', $data['left'])) * 2 : 0;
+        $data['top'] = isset($data['top']) ? intval(str_replace('px', '', $data['top'])) * 2 : 0;
+        $data['width'] = isset($data['width']) ? intval(str_replace('px', '', $data['width'])) * 2 : 0;
+        $data['height'] = isset($data['height']) ? intval(str_replace('px', '', $data['height'])) * 2 : 0;
+        $data['size'] = isset($data['size']) ? intval(str_replace('px', '', $data['size'])) * 2 : 0;
+        return $data;
+    }
+
+    /**
+     * 递归创建文件夹
+     * @author Created by Xing <464401240@qq.com>
+     */
+    private function mkdirs($path)
+    {
+        if (!is_dir($path)) {
+            $this->mkdirs(dirname($path));
+            mkdir($path);
+        }
+        return is_dir($path);
+    }
+
+    /**
+     * hex转rgb
+     * @param $colour
+     * @return array|bool
+     */
+    private function hex2rgb($colour)
+    {
+        if ($colour[0] == '#') {
+            $colour = substr($colour, 1);
+        }
+        if (strlen($colour) == 6) {
+            list($r, $g, $b) = array($colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5]);
+        } elseif (strlen($colour) == 3) {
+            list($r, $g, $b) = array($colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2]);
+        } else {
+            return false;
+        }
+        $r = hexdec($r);
+        $g = hexdec($g);
+        $b = hexdec($b);
+        return array('red' => $r, 'green' => $g, 'blue' => $b);
+    }
+}

+ 3 - 0
addons/poster/view/hook/user_sidenav_after.html

@@ -0,0 +1,3 @@
+<ul class="list-group">
+    <li class="list-group-item {:$controllername =='poster'?'active':''}"><a href="{:url('index/poster/index')}"><i class="fa fa-qrcode"></i> {:__('我的海报')}</a></li>
+</ul>

BIN
public/assets/fonts/fangzheng.ttf