完成显示水印功能;

This commit is contained in:
2024-02-18 15:41:14 +08:00
parent a59b124e70
commit aa9ae7f30b
8 changed files with 150 additions and 32 deletions

View File

@@ -0,0 +1,75 @@
<?php
namespace app\common\tools;
use Intervention\Image\Image as ImageImage;
use Intervention\Image\ImageManagerStatic;
use SplFileInfo;
use think\facade\App;
class Image
{
public static function addWatermark(SplFileInfo $file, $watermark_str = 'phpreturn.com'):ImageImage
{
// 检查文件是否是图片
if (!in_array($file->getExtension(), ['jpg', 'jpeg', 'png', 'gif'])) {
return false;
}
ImageManagerStatic::configure(['driver' => 'imagick']);
$img = ImageManagerStatic::make($file->getPathname());
$font_size = 20;
// 字体大小为宽度的 1/20
$font_size = $img->width() / 40;
$font_size = ceil($font_size);
$x = $img->width() - $font_size;
$y = $img->height() - $font_size;
$img->text($watermark_str, $x + $font_size * 0.05, $y + $font_size * 0.05, function ($font) use ($font_size) {
$font->file(App::getRootPath() . '/source/font/SourceHanSans-Normal.otf');
$font->size($font_size);
$font->color([0, 0, 0, 0.9]);
$font->align('right');
$font->valign('bottom');
});
$img->text($watermark_str, $x, $y, function ($font) use ($font_size) {
$font->file(App::getRootPath() . '/source/font/SourceHanSans-Normal.otf');
$font->size($font_size);
$font->color([255, 255, 255, 0.9]);
$font->align('right');
$font->valign('bottom');
});
return $img;
}
public static function handelWatermarkSave($src, $watermarked_file_save_name = null)
{
$src_file = new SplFileInfo($src);
$watermark_text = get_system_config('watermark_text', 'phpreturn.com');
$src_md5 = md5($src . $watermark_text);
if (!$watermarked_file_save_name) {
$watermarked_file_save_name = '/upload/watermark/' . $src_md5 . '.' . $src_file->getExtension();
}
$watermarked_file = App::getRootPath() . '/public' . $watermarked_file_save_name;
if (file_exists($watermarked_file)) {
return $watermarked_file_save_name;
}
if (!is_dir(dirname($watermarked_file))) {
mkdir(dirname($watermarked_file), 0777, true);
}
static::addWatermark($src_file, $watermark_text)->save($watermarked_file);
return $watermarked_file_save_name;
}
}

View File

@@ -8,7 +8,6 @@ class PostShow
{ {
public static function handleCopyright($content) public static function handleCopyright($content)
{ {
// 防采集版权声明,被采集了会在其他网站显示 // 防采集版权声明,被采集了会在其他网站显示
// 可以被选中复制,可以被采集,在网页中不会显示,但是在别的网站中可以显示 // 可以被选中复制,可以被采集,在网页中不会显示,但是在别的网站中可以显示
$content_copyright = '<blockquote class="post-content-inner-copyright"> 版权声明:' . get_system_config('post_copyright') . '</blockquote>'; $content_copyright = '<blockquote class="post-content-inner-copyright"> 版权声明:' . get_system_config('post_copyright') . '</blockquote>';
@@ -27,13 +26,10 @@ class PostShow
$p_list = $dom_content->children('p'); $p_list = $dom_content->children('p');
foreach ($p_list as $index_p => $dom_p) { foreach ($p_list as $index_p => $dom_p) {
if ($index_p != 0 && $index_p % 8 == 0) { if ($index_p != 0 && $index_p % 8 == 0) {
// $dom_copyright->clone()->children()->insertAfter($dom_p); // $dom_copyright->clone()->children()->insertAfter($dom_p);
} }
if ($index_p != 0 && $index_p % 6 == 0) { if ($index_p != 0 && $index_p % 6 == 0) {
$dom_copyright_hide->clone()->children()->insertAfter($dom_p); $dom_copyright_hide->clone()->children()->insertAfter($dom_p);
} }
} }
@@ -42,4 +38,27 @@ class PostShow
return $content; return $content;
} }
public static function handleImage($content)
{
$dom_content = phpQuery::newDocumentHTML($content);
$img_list = $dom_content->find('img');
foreach ($img_list as $index_img => $dom_img) {
$dom_img = pq($dom_img);
$src = $dom_img->attr('src');
$src = get_source_link($src);
$watermarked_file_save_name = Image::handelWatermarkSave($src);
$dom_img->attr('src', $watermarked_file_save_name);
}
$content = $dom_content->html();
return $content;
}
} }

View File

@@ -5,36 +5,45 @@ declare(strict_types=1);
namespace app\model; namespace app\model;
use app\common\model\Base; use app\common\model\Base;
use app\common\tools\Image;
/** /**
* @mixin think\Model * @mixin think\Model
*/ */
class Nav extends Base class Nav extends Base
{ {
public static $autoClearCache = [ public static $autoClearCache = [
[ [
'type' => 'key', 'type' => 'key',
'name' => 'type_list', 'name' => 'type_list',
'field' => 'type' 'field' => 'type',
], ],
[ [
'type' => 'tag', 'type' => 'tag',
'name' => 'page_cache' 'name' => 'page_cache',
], ],
]; ];
public static $statusName = [ public static $statusName = [
0 => '不显示', 0 => '不显示',
1 => '显示' 1 => '显示',
]; ];
// //
public function getImgAttr($value) public function getImgAttr($value)
{ {
return get_source_link($value); return get_source_link($value);
} }
public function getImgShowAttr()
{
$src = $this->getData('img');
$watermarked_file_save_name = Image::handelWatermarkSave($src);
return $watermarked_file_save_name;
}
public function getStatusNameAttr() public function getStatusNameAttr()
{ {
return self::$statusName[$this->getData('status')]; return self::$statusName[$this->getData('status')];

View File

@@ -5,15 +5,14 @@ declare(strict_types=1);
namespace app\model; namespace app\model;
use app\common\model\Base; use app\common\model\Base;
use app\common\tools\Image;
use app\common\tools\PostBlock; use app\common\tools\PostBlock;
use app\common\tools\PostShow; use app\common\tools\PostShow;
use League\HTMLToMarkdown\Converter\TableConverter; use League\HTMLToMarkdown\Converter\TableConverter;
use League\HTMLToMarkdown\HtmlConverter; use League\HTMLToMarkdown\HtmlConverter;
use think\facade\Cache; use think\facade\Cache;
use think\facade\Request; use think\facade\Request;
use think\Model;
use think\model\concern\SoftDelete; use think\model\concern\SoftDelete;
use think\Paginator;
/** /**
* @mixin think\Model * @mixin think\Model
@@ -23,7 +22,6 @@ class Post extends Base
use SoftDelete; use SoftDelete;
// //
public const CACHE_KEY_HITS = 'cache_hits_'; public const CACHE_KEY_HITS = 'cache_hits_';
public static $autoClearCache = [ public static $autoClearCache = [
@@ -32,7 +30,7 @@ class Post extends Base
public static $stausNameList = [ public static $stausNameList = [
0 => '不发布', 0 => '不发布',
1 => '发布' 1 => '发布',
]; ];
protected $defaultSoftDelete = 0; protected $defaultSoftDelete = 0;
@@ -52,7 +50,6 @@ class Post extends Base
return $this->hasMany(PostComment::class, 'post_id'); return $this->hasMany(PostComment::class, 'post_id');
} }
public function getCommentCountAttr() public function getCommentCountAttr()
{ {
return PostComment::getPostCommentsCount($this->getData('id')); return PostComment::getPostCommentsCount($this->getData('id'));
@@ -62,16 +59,18 @@ class Post extends Base
{ {
return strtotime($value); return strtotime($value);
} }
public function getPublishTimeTextAttr() public function getPublishTimeTextAttr()
{ {
$value = $this->getData('publish_time'); $value = $this->getData('publish_time');
return date('Y-m-d', $value); return date('Y-m-d', $value);
} }
public function getPublishTimeDatetimeAttr() public function getPublishTimeDatetimeAttr()
{ {
$value = $this->getData('publish_time'); $value = $this->getData('publish_time');
return date('Y-m-d H:i:s', $value); return date('Y-m-d H:i:s', $value);
} }
@@ -97,8 +96,7 @@ class Post extends Base
public function getDescAttr($value) public function getDescAttr($value)
{ {
if(empty($value)) { if (empty($value)) {
} }
return $value; return $value;
@@ -157,11 +155,9 @@ class Post extends Base
{ {
$content_html = $this->getAttr('content_html'); $content_html = $this->getAttr('content_html');
$content_html .= PostBlock::copyright($this); $content_html .= PostBlock::copyright($this);
$converter = new HtmlConverter(['strip_tags' => true]);
$converter = new HtmlConverter(array('strip_tags' => true));
$converter->getEnvironment()->addConverter(new TableConverter()); $converter->getEnvironment()->addConverter(new TableConverter());
@@ -172,9 +168,10 @@ class Post extends Base
public function getContentHtmlShowAttr() public function getContentHtmlShowAttr()
{ {
$content = $this->getAttr('content_html'); $content = $this->getAttr('content_html');
$content = PostShow::handleImage($content);
return PostShow::handleCopyright($content); return PostShow::handleCopyright($content);
} }
@@ -187,6 +184,15 @@ class Post extends Base
return get_source_link($value); return get_source_link($value);
} }
public function getPosterShowAttr()
{
$poster = $this->getAttr('poster');
$watermarked_file_save_name = Image::handelWatermarkSave($poster);
return $watermarked_file_save_name;
}
public function getReadUrlAttr() public function getReadUrlAttr()
{ {
$path = '/index/a' . $this->getData('uid') . '.html'; $path = '/index/a' . $this->getData('uid') . '.html';
@@ -211,7 +217,7 @@ class Post extends Base
$list_post_category_id = $this->getAttr('categorys')->column('category_id'); $list_post_category_id = $this->getAttr('categorys')->column('category_id');
$list_start_post = Post::where('category_id', 'in', $list_post_category_id)->where('type', 'category-start')->cacheAlways(600)->where('status', 1)->select(); $list_start_post = self::where('category_id', 'in', $list_post_category_id)->where('type', 'category-start')->cacheAlways(600)->where('status', 1)->select();
foreach ($list_start_post as $k_start_post => $v_start_post) { foreach ($list_start_post as $k_start_post => $v_start_post) {
$start_content .= $v_start_post->content_html; $start_content .= $v_start_post->content_html;
@@ -224,20 +230,21 @@ class Post extends Base
{ {
$end_content = ''; $end_content = '';
$list_post_category_id = $this->getAttr('categorys')->column('category_id'); $list_post_category_id = $this->getAttr('categorys')->column('category_id');
$list_end_post = Post::where('category_id', 'in', $list_post_category_id)->where('type', 'category-end')->cacheAlways(600)->where('status', 1)->select(); $list_end_post = self::where('category_id', 'in', $list_post_category_id)->where('type', 'category-end')->cacheAlways(600)->where('status', 1)->select();
foreach ($list_end_post as $k_end_post => $v_end_post) { foreach ($list_end_post as $k_end_post => $v_end_post) {
$end_content.= $v_end_post->content_html; $end_content .= $v_end_post->content_html;
} }
return $end_content; return $end_content;
} }
public function getHitsTitleAttr() public function getHitsTitleAttr()
{ {
$cache_key = static::CACHE_KEY_HITS.$this->getAttr('id'); $cache_key = static::CACHE_KEY_HITS . $this->getAttr('id');
$value = Cache::get($cache_key); $value = Cache::get($cache_key);
if(!is_null($value)) { if (!is_null($value)) {
return $value; return $value;
} }
@@ -250,7 +257,7 @@ class Post extends Base
public function setHitsAttr($value) public function setHitsAttr($value)
{ {
$cache_key = static::CACHE_KEY_HITS.$this->getAttr('id'); $cache_key = static::CACHE_KEY_HITS . $this->getAttr('id');
$this->getAttr('hits_title'); $this->getAttr('hits_title');
Cache::inc($cache_key); Cache::inc($cache_key);

View File

@@ -32,7 +32,8 @@
"league/html-to-markdown": "^5.1", "league/html-to-markdown": "^5.1",
"topthink/think-filesystem": "^2.0", "topthink/think-filesystem": "^2.0",
"mibe/feedwriter": "^1.1", "mibe/feedwriter": "^1.1",
"matomo/device-detector": "^6.1" "matomo/device-detector": "^6.1",
"intervention/image": "^2.7"
}, },
"require-dev": { "require-dev": {
"symfony/var-dumper": "^4.2" "symfony/var-dumper": "^4.2"

Binary file not shown.

View File

@@ -174,6 +174,13 @@
<input type="text" name="resource_domain" value="{:get_system_config('resource_domain')}" class="layui-input"> <input type="text" name="resource_domain" value="{:get_system_config('resource_domain')}" class="layui-input">
</div> </div>
</div> </div>
<!-- 水印内容 -->
<div class="layui-form-item">
<div class="layui-form-label">水印内容</div>
<div class="layui-input-block">
<input type="text" name="watermark_text" value="{:get_system_config('watermark_text')}" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text"> <div class="layui-form-item layui-form-text">
<div class="layui-form-label">统计代码</div> <div class="layui-form-label">统计代码</div>
<div class="layui-input-block"> <div class="layui-input-block">

View File

@@ -26,7 +26,7 @@
{volist name='list_nav_slide' id='nav'} {volist name='list_nav_slide' id='nav'}
<a href="{$nav.value|default='javascript:;'}" target="{$nav.target}"> <a href="{$nav.value|default='javascript:;'}" target="{$nav.target}">
<div class="index-poster" style="background-image: url({$nav.img});"> <div class="index-poster" style="background-image: url({$nav.img_show});">
</div> </div>
<div class="panel"> <div class="panel">
@@ -78,7 +78,7 @@
</div> </div>
</div> </div>
<div class="post-event-body"> <div class="post-event-body">
{$post->content_html|raw} {$post->content_html_show|raw}
</div> </div>
</div> </div>
{/case} {/case}
@@ -86,7 +86,7 @@
<a href="{:url('Post/read',['uid'=>$post.uid])}" class="post-item" onmouseover="$(this).find('.poster').addClass('layui-anim-scale')" onmouseout="$(this).find('.poster').removeClass('layui-anim-scale')"> <a href="{:url('Post/read',['uid'=>$post.uid])}" class="post-item" onmouseover="$(this).find('.poster').addClass('layui-anim-scale')" onmouseout="$(this).find('.poster').removeClass('layui-anim-scale')">
{notempty name='$post->getData("poster")'} {notempty name='$post->getData("poster")'}
<div class="poster layui-anim" style="background-image: url('{$post.poster}');"></div> <div class="poster layui-anim" style="background-image: url('{$post.poster_show}');"></div>
{/notempty} {/notempty}
<div class="info"> <div class="info">