├── assets ├── theme │ └── default │ │ ├── icon.png │ │ ├── loading-0.gif │ │ ├── loading-1.gif │ │ ├── loading-2.gif │ │ ├── layer.min.css │ │ └── layer.css ├── load.js ├── style.min.css ├── admin.scss ├── admin.css ├── base64.min.js ├── axios.min.js └── layer.js ├── admin ├── install.php ├── preload.php ├── initialize.php ├── common.php ├── setting.php ├── load.php ├── when-post.php ├── render.php └── form.php ├── class ├── log.php ├── compress.php ├── crontab.php └── local.php ├── tinymcc ├── icon │ └── local.svg └── local.js ├── nicen-localize-image.php ├── readme.txt ├── README.md ├── response └── response.php ├── config.php └── LICENSE /assets/theme/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/friend-nicen/nicen-localize-image/HEAD/assets/theme/default/icon.png -------------------------------------------------------------------------------- /assets/theme/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/friend-nicen/nicen-localize-image/HEAD/assets/theme/default/loading-0.gif -------------------------------------------------------------------------------- /assets/theme/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/friend-nicen/nicen-localize-image/HEAD/assets/theme/default/loading-1.gif -------------------------------------------------------------------------------- /assets/theme/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/friend-nicen/nicen-localize-image/HEAD/assets/theme/default/loading-2.gif -------------------------------------------------------------------------------- /admin/install.php: -------------------------------------------------------------------------------- 1 | $value ) { 14 | add_option( $key, $value ); //添加配置参数,和默认值 15 | } 16 | } 17 | 18 | nicen_make_install(); //插件自动设置 19 | 20 | /** 21 | * 关闭插件时注销任务 22 | * */ 23 | function nicen_make_end() { 24 | wp_clear_scheduled_hook( 'nicen_plugin_auto_publish' ); //清除任务 25 | } 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /admin/preload.php: -------------------------------------------------------------------------------- 1 | draft; 41 | } else { 42 | $draft_posts = 0; 43 | } 44 | 45 | $last = get_option( 'nicen_last_auto_publish' ); //上一次的运行日志 46 | 47 | return "当前草稿总数:" . $draft_posts . '篇,上一次自动发布运行时间为:' . ( empty( $last ) ? '暂未运行' : $last ); 48 | } 49 | -------------------------------------------------------------------------------- /assets/load.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author 友人a丶 3 | * @date 2022-08-12 4 | * 弹出层 5 | * */ 6 | 7 | 8 | /** 9 | * 配置antd 10 | * */ 11 | let message = antd.message; 12 | let Modal = antd.Modal; 13 | 14 | message.config({ 15 | top: `50px`, 16 | duration: 3, 17 | maxCount: 3, 18 | }); 19 | 20 | let hide = null; 21 | 22 | let load = { 23 | 24 | loading(text = '加载中...') { 25 | hide = message.loading(text, 0); 26 | }, 27 | 28 | loaded() { 29 | if (hide) { 30 | hide(); 31 | } 32 | }, 33 | success(text = '加载成功!') { 34 | message.success(text); 35 | }, 36 | error(text = '加载异常') { 37 | message.error(text); 38 | }, 39 | info(text = '加载异常') { 40 | message.info(text); 41 | }, 42 | confirm(text, callback = null, cancel = null) { 43 | Modal.confirm({ 44 | title: '提示', 45 | centered: true, 46 | content: text, 47 | maskClosable: false, 48 | onOk: (close) => { 49 | close(); //关闭 50 | if (callback) { 51 | callback() 52 | } 53 | }, onCancel: (close) => { 54 | close(); //关闭 55 | if (cancel) { 56 | cancel() 57 | } 58 | } 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /admin/initialize.php: -------------------------------------------------------------------------------- 1 | option );//初始化选项 18 | $this->logs = get_option( $this->option ); 19 | $this->record_log = get_option( 'nicen_make_plugin_record_log' ); 20 | } 21 | 22 | /** 23 | * 获取单例 24 | * */ 25 | public static function getInstance() { 26 | /*如果实例不存在*/ 27 | if ( ! self::$self ) { 28 | self::$self = new self(); 29 | } 30 | 31 | return self::$self; 32 | } 33 | 34 | /** 35 | * 新增一条日志 36 | * 37 | * @param log,操作之后的结果 38 | * 39 | * @return array 40 | */ 41 | public function add( $log ) { 42 | 43 | if ( ! $this->record_log ) { 44 | return $log; 45 | } 46 | 47 | $now = date( "Y-m-d H:i:s", time() ); 48 | 49 | /** 50 | * 判断结果 51 | * */ 52 | if ( $log['code'] ) { 53 | $this->logs .= $now . ',' . '本地化成功,' . $log['result'] . "\n"; 54 | } else { 55 | $this->logs .= $now . ',' . '本地化失败,' . $log['result'] . "\n"; 56 | } 57 | 58 | update_option( $this->option, $this->logs ); 59 | 60 | return $log; 61 | } 62 | 63 | 64 | /** 65 | * @return false|mixed|null 66 | */ 67 | public function get_logs() { 68 | return $this->logs; 69 | } 70 | 71 | /** 72 | * 清空日志 73 | * */ 74 | public function clear() { 75 | update_option( $this->option, "" ); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /tinymcc/icon/local.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 12 | 13 | 15 | -------------------------------------------------------------------------------- /admin/common.php: -------------------------------------------------------------------------------- 1 | $value ) { 15 | $nicen_make_CONFIGS[ $key ] = get_option( $key ); 16 | } 17 | 18 | /** 19 | * 返回指定配置 20 | * */ 21 | function nicen_make_config( $key = '' ) { 22 | global $nicen_make_CONFIGS; 23 | if ( empty( $key ) ) { 24 | return $nicen_make_CONFIGS; 25 | } else { 26 | return $nicen_make_CONFIGS[ $key ]; 27 | } 28 | } 29 | 30 | 31 | /** 32 | * 获取文章分类 33 | * */ 34 | function nicen_make_getCategory( $id ) { 35 | $cat = get_the_category( $id ); 36 | if ( $cat ) { 37 | return $cat[0]->name; 38 | } else { 39 | return "暂无分类"; 40 | } 41 | } 42 | 43 | 44 | /** 45 | * 获取所有标签和分类 46 | * */ 47 | function nicen_plugin_getAllCat() { 48 | 49 | $cat = []; 50 | 51 | /** 52 | * 遍历目录 53 | * */ 54 | $terms = get_terms( 'category', 'orderby=name&hide_empty=0' ); 55 | 56 | if ( count( $terms ) > 0 ) { 57 | foreach ( $terms as $term ) { 58 | $cat[] = [ 59 | 'label' => '分类:' . $term->name, 60 | 'value' => $term->term_id 61 | ]; 62 | } 63 | } 64 | 65 | return $cat; 66 | } 67 | 68 | 69 | /** 70 | * 获取图片类型 71 | * 1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM 72 | * */ 73 | function nicen_plugin_getType( $path ) { 74 | 75 | $info = getimagesize( $path ); 76 | 77 | switch ( $info[2] ) { 78 | case 1 : 79 | return 'gif'; 80 | case 2 : 81 | return 'jpeg'; 82 | case 3 : 83 | return 'png'; 84 | case 15 : 85 | return 'wbmp'; 86 | default : 87 | return 'png'; 88 | } 89 | } -------------------------------------------------------------------------------- /admin/setting.php: -------------------------------------------------------------------------------- 1 | 'sanitize_text_field') ); //主题首页副标题 36 | register_setting( "nicen_make_plugin", "nicen_make_publish_date_end", array('sanitize_callback' => 'sanitize_text_field') ); //主题首页副标题 37 | register_setting( "nicen_make_plugin", "nicen_make_publish_time_start", array('sanitize_callback' => 'sanitize_text_field') ); //主题首页副标题 38 | register_setting( "nicen_make_plugin", "nicen_make_publish_time_end", array('sanitize_callback' => 'sanitize_text_field') ); //主题首页副标题 39 | 40 | 41 | foreach ( PLUGIN_nicen_make as $item ) { 42 | /** 43 | * 如果有分节 44 | * */ 45 | if ( isset( $item['sections'] ) ) { 46 | 47 | foreach ( $item['sections'] as $section ) { 48 | 49 | /** 50 | * 循环注册分节 51 | * */ 52 | add_settings_section( 53 | $section['id'], 54 | $section['title'], 55 | function () use ( $section ) { 56 | return $section['callback'] ?? []; 57 | }, 58 | $item['id'] 59 | ); 60 | 61 | /** 62 | * 如果有字段 63 | * */ 64 | if ( isset( $section['fields'] ) ) { 65 | 66 | foreach ( $section['fields'] as $field ) { 67 | 68 | /** 69 | * 注册字段 70 | * */ 71 | register_setting( $item['id'], $field['id'] ); //主题首页副标题 72 | 73 | /** 74 | * 添加字段 75 | * */ 76 | add_settings_field( 77 | $field['id'], 78 | $field['title'], 79 | $field['callback'], 80 | $item['id'], 81 | $section['id'], 82 | $field['args'] ?? [] 83 | ); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | 92 | /** 93 | * 初始化主题设置 94 | * */ 95 | add_action( 'admin_init', 'nicen_make_config_register' ); 96 | -------------------------------------------------------------------------------- /nicen-localize-image.php: -------------------------------------------------------------------------------- 1 | manage_options 127 | 128 | 129 | v1.3.5 130 | 131 | 1. 修复插件日志无法清空的问题 132 | 2. 更新图片压缩页面加载目录时异步加载,避免文件数量太多导致卡死; 133 | 134 | v1.3.4 135 | 136 | 1. 修复不规范的img标签,不会被匹配到的问题。 137 | 138 | v1.3.3 139 | 140 | 1. 修改代码适配wordpress插件商店规范; 141 | 2. 图片压缩完成后自动刷新显示的目录; 142 | 3. 修改网络请求超时时间为120s; 143 | 144 | v1.3.1 beta 145 | 146 | 1. 新增批量本地化时,可以指定文章分类,指定文章发布时间范围; 147 | 2. 新增域名白名单,插件将忽略白名单内的域名,不会进行本地化; 148 | 3. 新增自定义图片保存类型功能 149 | 4. 新增图片批量压缩功能; 150 | 5. 接口增加随机时间戳; 151 | 6. 优化自动发布文章的定时任务 152 | 7. 修复压缩图片时图片读取失败的问题 153 | 8. 修改代码适配wordpress插件商店规范 154 | 155 | v1.2.0 beta 156 | 157 | 增加图片本地化日志收集的功能,随时了解本地化失败的原因; 158 | 新增定时发布文章的功能,可设置定时发布时是否本地化文章图片; 159 | 新增批量本地化已发布文章内外部图片的功能; 160 | 新增插件更新日志,便于用户及时响应插件更新; 161 | 新增插件BUG在线反馈的功能,便于及时修复问题; 162 | 修改接口密钥为安装插件后随机生成,防止接口被恶意利用; 163 | 新增图片本地化时是否添加网站域名的功能开关,开启后本地化后的图片链接为包含域名的完整路径; 164 | 165 | v1.1.3 166 | 167 | 本地化下载图片的方式调整为curl获取,并模拟referer绕过防盗链; 168 | 修改插件全局变量、函数的命名前缀; 169 | 修复没有判断图片下载结果导致的异常问题; -------------------------------------------------------------------------------- /assets/admin.scss: -------------------------------------------------------------------------------- 1 | [v-cloak] { 2 | display: none; 3 | } 4 | 5 | 6 | #VueApp { 7 | 8 | .ant-form-item-children { 9 | dd, li { 10 | margin-bottom: 0; 11 | } 12 | } 13 | 14 | .info { 15 | line-height: 1.8; 16 | width: 150%; 17 | word-wrap: break-word; 18 | word-spacing: normal; 19 | word-break: break-all; 20 | } 21 | 22 | .ant-input, .ant-time-picker-input { 23 | box-sizing: border-box; 24 | margin: 0; 25 | font-variant: tabular-nums; 26 | list-style: none; 27 | font-feature-settings: "tnum"; 28 | position: relative; 29 | display: inline-block; 30 | width: 100%; 31 | height: 32px; 32 | padding: 4px 11px; 33 | color: rgba(0, 0, 0, .65); 34 | font-size: 14px; 35 | line-height: 1.5; 36 | background-color: #fff; 37 | background-image: none; 38 | border: 1px solid #d9d9d9; 39 | border-radius: 4px; 40 | transition: all .3s; 41 | 42 | &:focus { 43 | outline: 0 !important; 44 | box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2) !important; 45 | } 46 | 47 | &:focus, &:hover { 48 | border-color: #40a9ff !important; 49 | border-right-width: 1px !important; 50 | } 51 | } 52 | 53 | .ant-form-item { 54 | margin-bottom: 15px; 55 | } 56 | 57 | 58 | .card-container { 59 | background: #f5f5f5; 60 | overflow: hidden; 61 | padding: 24px; 62 | 63 | 64 | & > .ant-tabs-card { 65 | 66 | & > .ant-tabs-bar { 67 | border-color: #fff; 68 | 69 | .ant-tabs-tab { 70 | border-color: transparent; 71 | background: transparent; 72 | } 73 | 74 | .ant-tabs-tab-active { 75 | border-color: #fff; 76 | background: #fff; 77 | } 78 | } 79 | 80 | & > .ant-tabs-content { 81 | 82 | min-height: 150px; 83 | margin-top: -16px; 84 | 85 | /* VIP页面说明 */ 86 | .vip { 87 | padding-bottom: 30px; 88 | 89 | .top { 90 | color: red; 91 | } 92 | 93 | .features { 94 | list-style: decimal; 95 | margin-top: 32px; 96 | 97 | .item { 98 | display: flex; 99 | justify-content: flex-start; 100 | align-items: center; 101 | 102 | &:after { 103 | background-color: black; 104 | border-radius: 50%; 105 | padding: 0 6px; 106 | margin-left: 10px; 107 | font-size: 12px; 108 | font-weight: bold; 109 | color: white; 110 | content: "×"; 111 | } 112 | } 113 | 114 | 115 | .ok { 116 | &:after { 117 | background-color: #07c160; 118 | border-radius: 50%; 119 | padding: 0 6px; 120 | margin-left: 10px; 121 | font-size: 12px; 122 | font-weight: bold; 123 | color: white; 124 | content: "√"; 125 | } 126 | } 127 | 128 | } 129 | 130 | 131 | .bottom { 132 | margin-top: 32px; 133 | } 134 | } 135 | 136 | 137 | & > .ant-tabs-tabpane { 138 | background: #fff; 139 | padding: 36px 42px 10px 42px; 140 | } 141 | 142 | .ant-form-item-label { 143 | label { 144 | display: flex; 145 | align-items: center; 146 | } 147 | } 148 | 149 | 150 | .m-colorPicker { 151 | 152 | display: inline-flex; 153 | 154 | .colorBtn { 155 | width: 25px; 156 | height: 25px; 157 | border-radius: 50%; 158 | margin-right: 15px; 159 | cursor: pointer; 160 | border: 1px solid #818181; 161 | } 162 | 163 | .box { 164 | box-shadow: 0 0 15px 10px rgba(0, 0, 0, 0.15); 165 | } 166 | } 167 | 168 | input { 169 | background-color: inherit; 170 | } 171 | 172 | 173 | } 174 | } 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /assets/admin.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | [v-cloak] { 3 | display: none; } 4 | 5 | #VueApp .ant-form-item-children dd, #VueApp .ant-form-item-children li { 6 | margin-bottom: 0; } 7 | 8 | #VueApp .info { 9 | line-height: 1.8; 10 | width: 150%; 11 | word-wrap: break-word; 12 | word-spacing: normal; 13 | word-break: break-all; } 14 | 15 | #VueApp .ant-input, #VueApp .ant-time-picker-input { 16 | box-sizing: border-box; 17 | margin: 0; 18 | font-variant: tabular-nums; 19 | list-style: none; 20 | font-feature-settings: "tnum"; 21 | position: relative; 22 | display: inline-block; 23 | width: 100%; 24 | height: 32px; 25 | padding: 4px 11px; 26 | color: rgba(0, 0, 0, 0.65); 27 | font-size: 14px; 28 | line-height: 1.5; 29 | background-color: #fff; 30 | background-image: none; 31 | border: 1px solid #d9d9d9; 32 | border-radius: 4px; 33 | transition: all .3s; } 34 | #VueApp .ant-input:focus, #VueApp .ant-time-picker-input:focus { 35 | outline: 0 !important; 36 | box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2) !important; } 37 | #VueApp .ant-input:focus, #VueApp .ant-input:hover, #VueApp .ant-time-picker-input:focus, #VueApp .ant-time-picker-input:hover { 38 | border-color: #40a9ff !important; 39 | border-right-width: 1px !important; } 40 | 41 | #VueApp .ant-form-item { 42 | margin-bottom: 15px; } 43 | 44 | #VueApp .card-container { 45 | background: #f5f5f5; 46 | overflow: hidden; 47 | padding: 24px; } 48 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-bar { 49 | border-color: #fff; } 50 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab { 51 | border-color: transparent; 52 | background: transparent; } 53 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active { 54 | border-color: #fff; 55 | background: #fff; } 56 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content { 57 | min-height: 150px; 58 | margin-top: -16px; 59 | /* VIP页面说明 */ } 60 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip { 61 | padding-bottom: 30px; } 62 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .top { 63 | color: red; } 64 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .features { 65 | list-style: decimal; 66 | margin-top: 32px; } 67 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .features .item { 68 | display: flex; 69 | justify-content: flex-start; 70 | align-items: center; } 71 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .features .item:after { 72 | background-color: black; 73 | border-radius: 50%; 74 | padding: 0 6px; 75 | margin-left: 10px; 76 | font-size: 12px; 77 | font-weight: bold; 78 | color: white; 79 | content: "×"; } 80 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .features .ok:after { 81 | background-color: #07c160; 82 | border-radius: 50%; 83 | padding: 0 6px; 84 | margin-left: 10px; 85 | font-size: 12px; 86 | font-weight: bold; 87 | color: white; 88 | content: "√"; } 89 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .vip .bottom { 90 | margin-top: 32px; } 91 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane { 92 | background: #fff; 93 | padding: 36px 42px 10px 42px; } 94 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .ant-form-item-label label { 95 | display: flex; 96 | align-items: center; } 97 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .m-colorPicker { 98 | display: inline-flex; } 99 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .m-colorPicker .colorBtn { 100 | width: 25px; 101 | height: 25px; 102 | border-radius: 50%; 103 | margin-right: 15px; 104 | cursor: pointer; 105 | border: 1px solid #818181; } 106 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content .m-colorPicker .box { 107 | box-shadow: 0 0 15px 10px rgba(0, 0, 0, 0.15); } 108 | #VueApp .card-container > .ant-tabs-card > .ant-tabs-content input { 109 | background-color: inherit; } 110 | -------------------------------------------------------------------------------- /admin/load.php: -------------------------------------------------------------------------------- 1 | jQuery(function (){alert("' . esc_js($upload) . '目录不存在,nicen_make-localize-image本地化插件无法生效!");});', 'after'; 24 | } 25 | } 26 | 27 | 28 | if (!is_writable($upload_root)) { 29 | /*输出本地化日志*/ 30 | echo '', 'after'; 31 | 32 | return; 33 | } 34 | 35 | 36 | /** 37 | * 开启了自动本地化 38 | * */ 39 | if (nicen_make_config('nicen_make_plugin_save')) { 40 | /** 41 | * 是否需要输出本地化日志 42 | * */ 43 | $info = get_option('nicen_make_plugin_save_result'); 44 | 45 | /*判断是否有本地化日志*/ 46 | if ($info) { 47 | 48 | echo preg_replace('/\s/', '', vsprintf(' 49 | 54 | ', [esc_js($info)])); 55 | 56 | update_option('nicen_make_plugin_save_result', ''); //清空日志 57 | } 58 | } 59 | 60 | 61 | } 62 | 63 | /** 64 | * 如果是文章编辑页面,则加载插件 65 | * */ 66 | if (strpos($_SERVER['SCRIPT_NAME'] ?? "", '/post')) { 67 | add_action('admin_head', 'nicen_make_detect'); //加载前台资源文件 68 | } 69 | 70 | 71 | /** 72 | * 后台主题设置页面,外部文件加载 73 | * */ 74 | function nicen_make_admin_load_source() 75 | { 76 | 77 | wp_enqueue_script('vuejs', nicen_local_image_url . 'assets/vue.min.js', ['jquery']); 78 | 79 | // 使用WordPress内置的moment.js 80 | wp_enqueue_script('moment'); 81 | wp_enqueue_script('base64', nicen_local_image_url . 'assets/base64.min.js'); 82 | 83 | wp_enqueue_script('antd', nicen_local_image_url . 'assets/antd.min.js', ['jquery', 'vuejs', 'moment']); 84 | wp_enqueue_script('Vcolorpicker', nicen_local_image_url . 'assets/colorpicker.js', array(), filemtime(nicen_local_image_path . 'assets/colorpicker.js'), true); 85 | 86 | wp_enqueue_style('antdcss', nicen_local_image_url . 'assets/antd.min.css'); 87 | 88 | wp_enqueue_style('admincss', nicen_local_image_url . 'assets/admin.css', array(), filemtime(nicen_local_image_path . 'assets/admin.css')); 89 | wp_enqueue_script('adminjs', nicen_local_image_url . 'assets/admin.js', array(), filemtime(nicen_local_image_path . 'assets/admin.js'), true); 90 | wp_enqueue_script('loadjs', nicen_local_image_url . 'assets/load.js', array(), filemtime(nicen_local_image_path . 'assets/load.js'), true); 91 | 92 | wp_enqueue_script('axios', nicen_local_image_url . 'assets/axios.min.js'); 93 | 94 | /** 95 | * 内联的js代码 96 | * */ 97 | wp_add_inline_script("adminjs", vsprintf(" 98 | const PLUGIN_CONFIG=%s; 99 | const NICEN_VERSION='%s';", [ 100 | json_encode(nicen_make_config()), 101 | esc_js(NICEN_VERSION) 102 | ]), 'before'); 103 | 104 | 105 | } 106 | 107 | 108 | /** 109 | * 加载layer弹窗插件 110 | * */ 111 | function nicen_make_load_layer() 112 | { 113 | 114 | 115 | wp_enqueue_style('layercss', nicen_local_image_url . 'assets/style.min.css', array()); 116 | wp_enqueue_script('layerjs', nicen_local_image_url . 'assets/layer.js', array('jquery')); 117 | // 使用WordPress内置的jquery-hotkeys 118 | wp_enqueue_script('jquery-hotkeys'); 119 | 120 | /** 121 | * 内联的js,输出接口密钥 122 | * */ 123 | wp_add_inline_script("layerjs", preg_replace('/\s/', '', vsprintf(' 124 | window.POST_KEY = "%s"; 125 | window.SYNC_NUMBER = %s;' 126 | 127 | , [ 128 | esc_html(nicen_make_config('nicen_make_plugin_private')), 129 | esc_html(nicen_make_config('nicen_make_sync_number')), 130 | ])), 'before'); 131 | 132 | } 133 | 134 | /** 135 | * 编辑器后台加载样式和脚本 136 | * */ 137 | if (strpos($_SERVER['SCRIPT_NAME'] ?? "", '/post') !== false && nicen_make_config('nicen_make_plugin_editor')) { 138 | add_action('admin_enqueue_scripts', 'nicen_make_load_layer'); //加载前台资源文件 139 | } 140 | 141 | /** 142 | * 后台加载样式和脚本 143 | * */ 144 | if (strpos($_SERVER['QUERY_STRING'] ?? "", 'nicen_make_plugin') !== false) { 145 | add_action('admin_enqueue_scripts', 'nicen_make_admin_load_source'); //加载前台资源文件 146 | } 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /admin/when-post.php: -------------------------------------------------------------------------------- 1 | post_content = str_replace( '>', "/>", $post->post_content ); 36 | 37 | /* 匹配所有图片 */ 38 | preg_match_all( '//', $post->post_content, $match ); 39 | 40 | 41 | /* 如果没有图片 */ 42 | if ( empty( $match[1] ) ) { 43 | /*匹配单引号规则*/ 44 | preg_match_all( "//", $post->post_content, $match ); 45 | /*如果没有图片*/ 46 | if ( empty( $match[1] ) ) { 47 | return; 48 | } 49 | } 50 | 51 | $images = array_unique( $match[1] ); //去重 52 | $site_url = site_url(); //站点url 53 | 54 | /** 55 | * 循环所有图片,判断是否需要本地化 56 | * */ 57 | 58 | $success = 0; 59 | $failed = 0; //成功和失败的数量 60 | $content = $post->post_content; 61 | 62 | foreach ( $images as $value ) { 63 | 64 | /** 65 | * 如果没有http 66 | * 代表是相对路径 67 | * */ 68 | if ( strpos( $value, 'http' ) === false ) { 69 | continue; 70 | } 71 | 72 | /** 73 | * 如果图片不包含本地域名 74 | * 如果没有重复的包含 75 | * 代表是外部图片需要进行本地化 76 | * */ 77 | if ( strpos( $value, $site_url ) === false ) { 78 | 79 | $res = ( Nicen_local::getInstance() )->localImage( $value, false );//下载图片 80 | 81 | /*判断下载结果*/ 82 | if ( $res['code'] > 0 ) { 83 | 84 | $content = str_replace( $value, $res['result'], $content ); 85 | 86 | //更新文章 87 | wp_update_post( wp_slash( [ 88 | 'ID' => $post_id, 89 | 'post_content' => $content 90 | ] ), false, false ); 91 | 92 | $success ++; //加1 93 | } else { 94 | $failed ++; //加1 95 | } 96 | } 97 | 98 | } 99 | 100 | /*记录到日志*/ 101 | if ( $success || $failed ) { 102 | $log = '上一次保存文章后,本地化图片成功' . $success . "张,失败" . $failed . '张!'; 103 | } 104 | } 105 | 106 | /** 107 | * 自动添加alt 108 | * */ 109 | if ( nicen_make_config( 'nicen_make_plugin_alt' ) ) { 110 | 111 | 112 | //获取文章对象 113 | $post = get_post( $post_id ); 114 | /*文章是否存在*/ 115 | if ( empty( $post ) ) { 116 | return; 117 | } 118 | //匹配所有图片 119 | preg_match_all( '//', $post->post_content, $match ); 120 | 121 | /*如果没有图片*/ 122 | if ( empty( $match ) ) { 123 | return; 124 | } 125 | 126 | $success = 0; //成功和失败的数量 127 | $content = $post->post_content; 128 | 129 | /* 获取要替换的内容 */ 130 | $replace = nicen_make_config( 'nicen_make_plugin_alt_type' ) == 1 ? $post->post_title : nicen_make_getCategory( $post->ID ); 131 | 132 | foreach ( $match[0] as $value ) { 133 | 134 | /** 135 | * 如果没有alt 136 | * 代表是相对路径 137 | * */ 138 | if ( strpos( $value, 'alt' ) === false ) { 139 | 140 | $content = str_replace( $value, str_replace( ' $post_id, 144 | 'post_content' => $content 145 | ] ), false, false ); 146 | 147 | $success ++; //加1 148 | } else { 149 | 150 | /** 151 | * 判断alt是否为空 152 | * */ 153 | if ( preg_match( "/(?:alt='')|(?:alt=\"\")/", $value ) ) { 154 | 155 | $content = str_replace( $value, preg_replace( "/(?:alt='')|(?:alt=\"\")/", 'alt="' . $replace . '"', $value ), $content ); 156 | 157 | //更新文章 158 | wp_update_post( wp_slash( [ 159 | 'ID' => $post_id, 160 | 'post_content' => $content 161 | ] ), false, false ); 162 | 163 | $success ++; //加1 164 | } 165 | 166 | 167 | } 168 | 169 | 170 | } 171 | 172 | 173 | /*记录到日志*/ 174 | if ( $success ) { 175 | if ( empty( $log ) ) { 176 | $log = '上一次保存文章后,自动添加alt属性' . $success . '个!'; 177 | } else { 178 | $log = $log . '自动添加alt属性' . $success . '个!'; 179 | } 180 | } 181 | 182 | } 183 | 184 | 185 | /** 186 | * 插入日志 187 | * */ 188 | if ( $flag ) { 189 | update_option( 'nicen_make_plugin_save_result', $log ); 190 | } else { 191 | return $log; 192 | } 193 | 194 | } 195 | 196 | 197 | add_action( 'edit_post', 'nicen_make_when_save_post' ); 198 | 199 | 200 | -------------------------------------------------------------------------------- /assets/base64.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using Terser v5.7.1. 3 | * Original file: /npm/js-base64@3.7.2/base64.js 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | !function(t,n){var r,e;"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(r=t.Base64,(e=n()).noConflict=function(){return t.Base64=r,e},t.Meteor&&(Base64=e),t.Base64=e)}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:this,(function(){"use strict";var t,n="3.7.2",r="function"==typeof atob,e="function"==typeof btoa,o="function"==typeof Buffer,u="function"==typeof TextDecoder?new TextDecoder:void 0,i="function"==typeof TextEncoder?new TextEncoder:void 0,f=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),c=(t={},f.forEach((function(n,r){return t[n]=r})),t),a=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,d=String.fromCharCode.bind(String),s="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):function(t,n){return void 0===n&&(n=function(t){return t}),new Uint8Array(Array.prototype.slice.call(t,0).map(n))},l=function(t){return t.replace(/=/g,"").replace(/[+\/]/g,(function(t){return"+"==t?"-":"_"}))},h=function(t){return t.replace(/[^A-Za-z0-9\+\/]/g,"")},p=function(t){for(var n,r,e,o,u="",i=t.length%3,c=0;c255||(e=t.charCodeAt(c++))>255||(o=t.charCodeAt(c++))>255)throw new TypeError("invalid character found");u+=f[(n=r<<16|e<<8|o)>>18&63]+f[n>>12&63]+f[n>>6&63]+f[63&n]}return i?u.slice(0,i-3)+"===".substring(i):u},y=e?function(t){return btoa(t)}:o?function(t){return Buffer.from(t,"binary").toString("base64")}:p,A=o?function(t){return Buffer.from(t).toString("base64")}:function(t){for(var n=[],r=0,e=t.length;r>>6)+d(128|63&n):d(224|n>>>12&15)+d(128|n>>>6&63)+d(128|63&n);var n=65536+1024*(t.charCodeAt(0)-55296)+(t.charCodeAt(1)-56320);return d(240|n>>>18&7)+d(128|n>>>12&63)+d(128|n>>>6&63)+d(128|63&n)},B=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,x=function(t){return t.replace(B,g)},C=o?function(t){return Buffer.from(t,"utf8").toString("base64")}:i?function(t){return A(i.encode(t))}:function(t){return y(x(t))},m=function(t,n){return void 0===n&&(n=!1),n?l(C(t)):C(t)},v=function(t){return m(t,!0)},U=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,F=function(t){switch(t.length){case 4:var n=((7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3))-65536;return d(55296+(n>>>10))+d(56320+(1023&n));case 3:return d((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return d((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}},w=function(t){return t.replace(U,F)},S=function(t){if(t=t.replace(/\s+/g,""),!a.test(t))throw new TypeError("malformed base64.");t+="==".slice(2-(3&t.length));for(var n,r,e,o="",u=0;u>16&255):64===e?d(n>>16&255,n>>8&255):d(n>>16&255,n>>8&255,255&n);return o},E=r?function(t){return atob(h(t))}:o?function(t){return Buffer.from(t,"base64").toString("binary")}:S,D=o?function(t){return s(Buffer.from(t,"base64"))}:function(t){return s(E(t),(function(t){return t.charCodeAt(0)}))},R=function(t){return D(T(t))},z=o?function(t){return Buffer.from(t,"base64").toString("utf8")}:u?function(t){return u.decode(D(t))}:function(t){return w(E(t))},T=function(t){return h(t.replace(/[-_]/g,(function(t){return"-"==t?"+":"/"})))},Z=function(t){return z(T(t))},j=function(t){return{value:t,enumerable:!1,writable:!0,configurable:!0}},I=function(){var t=function(t,n){return Object.defineProperty(String.prototype,t,j(n))};t("fromBase64",(function(){return Z(this)})),t("toBase64",(function(t){return m(this,t)})),t("toBase64URI",(function(){return m(this,!0)})),t("toBase64URL",(function(){return m(this,!0)})),t("toUint8Array",(function(){return R(this)}))},O=function(){var t=function(t,n){return Object.defineProperty(Uint8Array.prototype,t,j(n))};t("toBase64",(function(t){return b(this,t)})),t("toBase64URI",(function(){return b(this,!0)})),t("toBase64URL",(function(){return b(this,!0)}))},P={version:n,VERSION:"3.7.2",atob:E,atobPolyfill:S,btoa:y,btoaPolyfill:p,fromBase64:Z,toBase64:m,encode:m,encodeURI:v,encodeURL:v,utob:x,btou:w,decode:Z,isValid:function(t){if("string"!=typeof t)return!1;var n=t.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(n)||!/[^\s0-9a-zA-Z\-_]/.test(n)},fromUint8Array:b,toUint8Array:R,extendString:I,extendUint8Array:O,extendBuiltins:function(){I(),O()},Base64:{}};return Object.keys(P).forEach((function(t){return P.Base64[t]=P[t]})),P})); 8 | //# sourceMappingURL=/sm/79de78edcfa94236e4c8354f91262971e185c3633bb865b6fc17942e93a40207.map -------------------------------------------------------------------------------- /class/compress.php: -------------------------------------------------------------------------------- 1 | base64_encode( $title ), 70 | "key" => base64_encode( $key ) 71 | ]; 72 | } 73 | 74 | 75 | } else { 76 | 77 | $list[] = [ 78 | "title" => base64_encode( $file ), 79 | "key" => base64_encode( $path . '/' . $file ) 80 | ]; 81 | 82 | } 83 | 84 | } 85 | } 86 | 87 | closedir( $dir_handle ); 88 | 89 | return $list; 90 | 91 | } 92 | 93 | /** 94 | * 获取压缩后的图片 95 | * 96 | * @param string $file 97 | * */ 98 | public function getCompress( $file ) { 99 | 100 | $root = nicen_local_image_root; 101 | $abs = $root . $file; //绝度路径 102 | 103 | /** 104 | * 判断文件是否存在 105 | * */ 106 | if ( ! file_exists( $abs ) ) { 107 | return [ 108 | 'code' => 0, 109 | 'errMsg' => '文件不存在,压缩失败!' 110 | ]; 111 | } 112 | 113 | /** 114 | * 是否可写 115 | * */ 116 | if ( ! is_writable( $abs ) ) { 117 | return [ 118 | 'code' => 0, 119 | 'errMsg' => '文件不可写,压缩失败!' 120 | ]; 121 | } 122 | 123 | $res = $this->post( $abs ); 124 | $result = json_decode( $this->post( $abs ), true ); //请求压缩 125 | 126 | if ( isset( $result['dest'] ) ) { 127 | 128 | $data = $this->get( $result['dest'] ); 129 | 130 | if ( ! $data ) { 131 | return [ 132 | 'code' => 0, 133 | 'errMsg' => '文件文件读取失败,接口超时!' 134 | ]; 135 | } else { 136 | file_put_contents( $abs, $data, LOCK_EX ); //写入文件 137 | 138 | return [ 139 | 'code' => 1, 140 | 'errMsg' => '压缩成功,压缩前' . round( $result['src_size'] / 1024, 2 ) . 'kb,压缩后' . round( $result['dest_size'] / 1024, 2 ) . 'kb,压缩率' . $result['percent'] . '%!' 141 | ]; 142 | } 143 | 144 | 145 | } else { 146 | return [ 147 | 'code' => 0, 148 | 'errMsg' => $res 149 | ]; 150 | } 151 | 152 | } 153 | 154 | /** 155 | * 获取图片内容 156 | * 157 | * @param $url string,图片的链接 158 | * */ 159 | function post( $file ) { 160 | 161 | try { 162 | 163 | $post_data = [ 164 | 'files' => new \CURLFile( $file ) 165 | ]; 166 | 167 | $Http = new WP_Http_Curl(); 168 | 169 | /** 170 | * 修改请求配置 171 | * */ 172 | $args = array( 173 | 'method' => 'POST', 174 | 'sslverify' => false, 175 | 'body' => $post_data, 176 | 'timeout' => 120, 177 | 'httpversion' => '1.1' 178 | ); 179 | 180 | $res = $Http->request( 'http://api.resmush.it/ws.php', $args ); 181 | 182 | /** 183 | * 判断请求结果 184 | * */ 185 | if ( is_wp_error( $res ) ) { 186 | $errors = $res->get_error_messages(); 187 | 188 | return $errors; 189 | } 190 | 191 | return wp_remote_retrieve_body( $res ); 192 | 193 | } catch ( \Throwable $e ) { 194 | return $e->getMessage(); 195 | } 196 | } 197 | 198 | /** 199 | * 获取图片内容 200 | * 201 | * @param $url string,图片的链接 202 | * */ 203 | function get( $url ) { 204 | 205 | try { 206 | $headers = [ 207 | 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36', 208 | ]; 209 | 210 | /** 211 | * 请求数据 212 | * */ 213 | $res = wp_remote_get( $url, [ 214 | 'headers' => $headers, 215 | 'sslverify' => false, 216 | 'timeout' => 120, 217 | ] ); 218 | 219 | return wp_remote_retrieve_body( $res ); 220 | 221 | } catch ( \Throwable $e ) { 222 | return false; 223 | } 224 | } 225 | 226 | } 227 | 228 | 229 | -------------------------------------------------------------------------------- /class/crontab.php: -------------------------------------------------------------------------------- 1 | interval = get_option( 'nicen_make_plugin_interval' ); 29 | $this->type = get_option( 'nicen_make_plugin_order' ); 30 | $this->localImage = get_option( 'nicen_make_plugin_publish_local' ); 31 | $this->syncDatetime = get_option( 'nicen_make_publish_date' ); 32 | $this->number = get_option( 'nicen_make_plugin_publish_num' ); 33 | $this->status = get_option( 'nicen_make_publish_type' ); 34 | 35 | 36 | /* 定时任务是否允许 */ 37 | $this->running = get_option( 'nicen_make_plugin_auto_publish' ); 38 | 39 | 40 | /** 41 | * 开始和结束日期 42 | * */ 43 | $this->date = [ 44 | get_option( 'nicen_make_publish_date_start' ), 45 | get_option( 'nicen_make_publish_date_end' ) 46 | ]; 47 | 48 | /** 49 | * 开始和结束时间 50 | * */ 51 | $this->time = [ 52 | get_option( 'nicen_make_publish_time_start' ), 53 | get_option( 'nicen_make_publish_time_end' ) 54 | ]; 55 | 56 | } 57 | 58 | /** 59 | * 获取单例 60 | * */ 61 | public static function getInstance() { 62 | /*如果实例不存在*/ 63 | if ( ! self::$self ) { 64 | self::$self = new self(); 65 | } 66 | 67 | return self::$self; 68 | } 69 | 70 | /** 71 | * 准备任务 72 | * */ 73 | public function start() { 74 | 75 | /*初始化钩子*/ 76 | add_filter( 'cron_schedules', array( $this, 'add_schedules' ) ); //自定义间隔时间 77 | 78 | /* 并且定时任务是开着的 */ 79 | /* 钩子没有注册成功 */ 80 | if ( $this->running && ! wp_get_scheduled_event( 'nicen_plugin_auto_publish' ) ) { 81 | wp_schedule_event( time(), 'nicen_crontab', 'nicen_plugin_auto_publish' ); 82 | } 83 | 84 | 85 | add_action( 'nicen_plugin_auto_publish', array( $this, 'publish' ) );//自定义发布任务 86 | } 87 | 88 | 89 | /** 90 | * 添加一个间隔时间 91 | * */ 92 | function add_schedules( $schedules ) { 93 | 94 | $schedules['nicen_crontab'] = [ 95 | 'interval' => intval( $this->interval ), //获取设置的间隔时间 96 | 'display' => '定时发布草稿文章' 97 | ]; 98 | 99 | return $schedules; 100 | } 101 | 102 | 103 | /** 104 | * 发布文章 105 | * */ 106 | public function publish() { 107 | 108 | $time = time(); //当前秒数 109 | $date = strtotime( date( "Y-m-d", $time ) ); //当日0点 110 | $ymd = date( "Y-m-d", $time ); 111 | $now = date( "Y-m-d H:i:s", time() ); 112 | 113 | 114 | /** 115 | * 当天日期小于最小日期 116 | * */ 117 | if ( ! empty( $this->date[0] ) ) { 118 | if ( strtotime( $this->date[0] ) > $date ) { 119 | 120 | $this->log( "当前日期小于设置的最小日期,任务终止," . $now ); 121 | 122 | return; 123 | } 124 | } 125 | 126 | /** 127 | * 当天日期大于最大日期 128 | * */ 129 | if ( ! empty( $this->date[1] ) ) { 130 | if ( strtotime( $this->date[1] ) < $date ) { 131 | $this->log( "当前日期超过设置的最晚日期,任务终止," . $now ); 132 | 133 | return; 134 | } 135 | } 136 | 137 | 138 | /** 139 | * 当天时间小于最小时间 140 | * */ 141 | if ( ! empty( $this->time[0] ) ) { 142 | if ( strtotime( $ymd . " " . $this->time[0] ) > $time ) { 143 | $this->log( "当前时间小于设置的最小时间,任务终止," . $now ); 144 | 145 | return; 146 | } 147 | } 148 | 149 | /** 150 | * 当天时间大于最小时间 151 | * */ 152 | 153 | if ( ! empty( $this->time[1] ) ) { 154 | if ( strtotime( $ymd . " " . $this->time[1] ) < $time ) { 155 | $this->log( "当前时间超过设置的最大时间,任务终止," . $now ); 156 | 157 | return; 158 | } 159 | } 160 | 161 | 162 | /** 163 | * 定义文章指针 164 | * */ 165 | $log = date( "Y-m-d H:i:s", time() ) . "任务被触发,"; 166 | 167 | $query_args = [ 168 | 'posts_per_page' => $this->number, 169 | 'orderby' => $this->type, 170 | 'post_status' => [ '', 'draft', 'pending', 'future' ][ $this->status ], 171 | 'post_type' => 'post', 172 | 'order' => 'ASC' 173 | ]; 174 | 175 | $query = new \WP_Query( $query_args ); 176 | 177 | $count = 0; 178 | $title = ''; 179 | 180 | while ( $query->have_posts() ) { 181 | $query->the_post(); 182 | kses_remove_filters(); 183 | $title = get_the_title(); 184 | 185 | 186 | /** 187 | * 判断是否同步发布时间 188 | * */ 189 | if ( $this->syncDatetime ) { 190 | wp_update_post( [ 191 | 'ID' => get_the_ID(), 192 | 'post_status' => 'publish', 193 | 'post_date' => date( "Y-m-d H:i:s", time() ) 194 | ] 195 | ); 196 | } else { 197 | wp_update_post( [ 198 | 'ID' => get_the_ID(), 199 | 'post_status' => 'publish', 200 | ] 201 | ); 202 | } 203 | 204 | 205 | /** 206 | * 是否需要本地化 207 | * */ 208 | if ( $this->localImage ) { 209 | nicen_make_when_save_post( get_the_ID(), false ); 210 | } 211 | 212 | kses_init_filters(); 213 | 214 | 215 | $count ++; 216 | } 217 | 218 | wp_reset_postdata(); 219 | 220 | if ( ! $count ) { 221 | $this->log( $log . "无可以发布文章,下次运行时间:" . date( "Y-m-d H:i:s", time() + $this->interval ) ); 222 | 223 | return; 224 | } 225 | 226 | $datetime = $this->syncDatetime ? date( "Y-m-d H:i:s", time() ) : "最后一次编辑时间"; 227 | 228 | $log .= "发布文章" . $count . "篇,【{$title}】,文章发布时间为【{$datetime}】,下次运行时间:" . date( "Y-m-d H:i:s", time() + $this->interval ); 229 | $this->log( $log ); 230 | } 231 | 232 | /** 233 | * 记录运行时间,以及下一次运行时间 234 | * */ 235 | public function log( $log ) { 236 | update_option( 'nicen_last_auto_publish', $log ); 237 | } 238 | 239 | } 240 | 241 | 242 | ( Nicen_crontab::getInstance() )->start(); //开始 243 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | /** 3 | Plugin Name: nicen-localize-image 4 | Plugin URI:https://nicen.cn/2893.html 5 | Description: 用于本地化文章的外部图片的插件,支持文章发布前通过编辑器插件本地化、文章发布时自动本地化、定时发布文章时自动本地化、已发布的文章批量本地化。 6 | Version: 1.4.9 7 | Author: 友人a丶 8 | Author URI: https://nicen.cn 9 | Text Domain: nicen-localize-image 10 | License: GPLv2 or later 11 | */ 12 | ``` 13 | 14 | # 插件介绍 15 | 16 | nicen-localize-image(wordpress插件后台搜索安装),是一款用于本地化文章的外部图片的插件,支持如下功能: 17 | 18 | 1. 文章发布前通过编辑器插件本地化 19 | 2. 文章手动发布时自动本地化 20 | 3. 文章定时发布时自动本地化 21 | 4. 针对已发布的文章批量本地化。 22 | 23 | > 😁,加我微信【good7341】或机器人微信【nicen_friend】拉你进交流群! 24 | 25 | > 如您觉得插件给你带来了帮助,欢迎star!祝您早日达成自己的目标! 26 | 27 | # Pro版介绍 28 | 29 | 39.9无加密、无授权、无域名限制、持续更新,请加微信good7341,购买后会邀请您加入Pro用户群: 30 | 31 | 1. 支持图片本地化后按照年月日存放在指定的本地化图片保存目录 32 | 2. 支持编辑器内可直接复制粘贴软件截图和本地图片,并自动上传到服务器 33 | 3. 支持文章发布时自动给a标签添加target="_blank"属性 34 | 4. 支持本地化图片时可自定义referer,绕过防盗链 35 | 5. 支持本地化图片后自动添加设置的水印,自带超完备的图片水印功能 36 | 6. 支持本地化时直接上传对象存储,并替换链接为对象存储的链接 37 | 7. 支持图片水印、对象存储、定时任务等功能,共同协作 38 | 8. 支持批量本地化并发进行,可同时处理N篇文章的图片本地化 39 | 9. 支持本地化后保存为webp格式 40 | 10. 支持设置代理IP,绕过IP防火墙 41 | 11. 支持媒体库上传图片时,添加水印,转存对象存储 42 | 43 | # 仓库地址 44 | 45 | Github:[https://github.com/friend-nicen/nicen-localize-image](https://github.com/friend-nicen/nicen-localize-image) 46 | 47 | Gitee:[https://gitee.com/friend-nicen/nicen-localize-image](https://gitee.com/friend-nicen/nicen-localize-image) 48 | 49 | # 插件推荐 50 | 51 | ## Wordpress用户行为回放插件 52 | 53 | 在数字营销的世界里,了解用户行为是提升用户体验和转化率的关键。nicen-replay 54 | 插件,它能够让您轻松回放用户在网站上的每一步操作,从点击到滚动,再到表单填写,每一个细节都清晰可见。 55 | 56 | Github: 57 | 58 | Gitee: 59 | 60 | # 功能说明 61 | 62 | 插件提供两种本地化外部图片的模式,两种模式可同时开启,互不冲突; 63 | ![alt 属性文本](https://nicen.cn/wp-content/uploads/2022/08/1661002814846.png) 64 | 65 | ## 编辑器本地化插件 66 | 67 | 启用这个模式之后,会将wordpress文章编辑器切换为经典编辑器,并在编辑器上方新增一个功能图标,点击之后可以自动检测并本地化所有外部图片; 68 | 69 | ![alt 属性文本](https://nicen.cn/wp-content/uploads/2022/08/1661008460684.png) 70 | ![alt 属性文本](https://nicen.cn/wp-content/uploads/2022/08/1661008539461.png) 71 | 72 | ## 发布时自动本地化 73 | 74 | 启用这个模式之后会在文章发布时自动本地化所有外部图片; 75 | ![alt 属性文本](https://nicen.cn/wp-content/uploads/2022/08/1661008642570.png) 76 | 77 | 推荐使用【编辑器本地化插件】在发布前进行本地化,当图片数量过多或者文件太大【发布时自动本地化】可能会导致请求卡死。 78 | 79 | # 更新日志 80 | 81 | 开源版已进入维护阶段,v1.4.2以后只修复BUG不再更新新功能,新功能将发布在Pro版(Pro版) 82 | 83 | ## v2.1.9 84 | 85 | 1. 新增恢复插件默认配置的功能 86 | 87 | ## v2.1.8 88 | 89 | 1. 修复webp类型图片,图片类型检测异常的问题 90 | 91 | ## v2.1.7 92 | 93 | 1. 修复选择Cos保存到媒体库的图片,插入文章时链接格式异常的问题 94 | 95 | ## v2.1.6 96 | 97 | 1. 修复开启本地化后设置第一张图片为特色图片时,如果只有一张图片时不会设置特色图片的问题 98 | 2. 新增设置项“重新下载本地化过的链接”,开启后将忽略本地缓存,强制重新下载已经本地化过的图片链接 99 | 100 | ## v2.1.5 101 | 102 | 1. 修复本地化时,//开头的图片检测不到的问题 103 | 104 | ## v2.1.4 105 | 106 | 1. 更新引入的外部js库的cdn源 107 | 108 | ## v2.1.3 109 | 110 | 1. 修复某些特殊的图片链接会本地化失败的问题 111 | 112 | ## v2.1.2 113 | 114 | 1. 修复某些情况下本地化失败会导致替换异常的问题 115 | 116 | ## v2.1.1 117 | 118 | 1. 优化图片下载速度 119 | 120 | ## v2.1.0 121 | 122 | 1. 新增对象存储支持七牛云 123 | 2. 新增对象存储可选按年月日保存文件 124 | 3. 新增对象存储可选是否处理媒体库上传的文件 125 | 126 | ## v2.0.12 127 | 128 | 1. 新增支持绕过某些特殊的防盗链 129 | 2. 新增可设置本地化后清空IMG标签除src之外的其它属性 130 | 131 | ## v2.0.11 132 | 133 | 1. 修复webp转换导致运行异常的BUG 134 | 135 | ## v2.0.10 136 | 137 | 1. 修复开启webp转换后原图不会删除的BUG。 138 | 2. 新增特色图片可以设置使用第一张图 139 | 140 | ## v2.0.9 141 | 142 | 1. 新增开启webp转换后,可以设置指定类型的图片不进行webp转换 143 | 2. 新增开启图片水印后,可以设置指定类型的图片不添加水印 144 | 145 | ## v2.0.8 146 | 147 | 1. 修复指定百分比时透明水印变黑 148 | 2. 修复开启保存到数据库会导致水印重复添加 149 | 150 | ## v2.0.7 151 | 152 | 1. 修复水印功能使用图片水印丢失透明度的问题 153 | 154 | ## v2.0.6 155 | 156 | 1. 修复定时任务日志显示异常的问题 157 | 2. 修复某些情况下产生异常报错的情况 158 | 159 | ## v2.0.5 160 | 161 | 1. 重构定时任务,发布时将不依赖于wp的定时任务。 162 | 2. 定时任务支持设置时间范围,自动随机生成下一次发布时间。 163 | 164 | ## v2.0.4 165 | 166 | 1. 支持媒体库上传时,添加水印和上传对象存储 167 | 2. 新增媒体库可以直接选取对象存储的图片 168 | 169 | ## v2.0.3 170 | 171 | 1. 修复启用webp转换功能后,无法正常添加水印的问题。 172 | 173 | ## v2.0.3 174 | 175 | 1. 新增图片可保存为webp文件 176 | 2. 新增水印可自定义图片水印的百分比大小 177 | 178 | ## v2.0.1 179 | 180 | 1. 新增自定义网络请求代理 181 | 182 | ## v2.0.0 183 | 184 | 1. 新增本地化后,图片上传到对象存储(阿里云、腾讯云) 185 | 2. 新增定时任务可选单次定时发布的文章数量和状态 186 | 3. 新增编辑器插件本地化可以并发下载(默认同时下载5张图片) 187 | 4. 新增批量本地化并发下载,可单独设置需要同时本地化的文章数量 188 | 5. 新增本地化图片保存到数据库时,可选是否生成缩略图 189 | 6. 新增本地化图片添加域名时,可指定需要添加的域名 190 | 7. 新增批量本地化时,可选待审、定时任务等其它文章状态 191 | 8. 新增字体库列表,移除水印功能自带字体文件,在水印功能页点击下载字体自行下载 192 | 9. 新增水印功能可设置过滤规则,对于长宽小于指定值的图片不添加水印 193 | 10. 新增删除文章时可选是否自动删除文章关联的图片附件 194 | 11. 修复编辑器插件本地化时,图片数量小于并发数时,会导致本地化链接不会替换的问题 195 | 12. 修复图片水印模式下,字体文件不存在时,会导致报错的问题 196 | 13. 修复图片粘贴自动本地化上传时,特殊情形下会出现报错的问题 197 | 14. 修复存在空格时,会导致白名单功能失效的问题 198 | 199 | ## v1.4.1 200 | 201 | 1. 修复编辑器插件存在相同图片链接时,只会替换一次的问题 202 | 2. 修复复制网页图片时,触发粘贴图片上传,会导致重复上传生成两张图片的问题 203 | 3. 修复本地化图片验证图片链接状态码,没有模拟Referer导致触发防盗链,刚好链接返回异常状态码时,会本地化报错的问题。 204 | 4. 新增本地化时是否记录日志的选项,关闭后将不在记录日志。 205 | 5. 修复定时任务发布时,修改文章时间发布时间为定时任务触发时间,不生效的问题。 206 | 6. 增加文章定时发布任务有效性检测,防止被其它插件删除定时任务后,定时发布无法正常运行的问题 207 | 208 | ## v1.4.0 209 | 210 | 1. 修复分类名包含特殊字符时,批量本地化时,分类无法正常显示的问题 211 | 2. 新增系统时间校准的功能开关,定时任务页面将展示当前系统时间和默认时区,避免由时区导致定时任务无法正常运行 212 | 3. 新增图片本地化后自动关联文章 213 | 4. 新增图片本地化后按照年月日存放在指定的本地化图片保存目录 214 | 5. 更新img匹配规则,兼容一些不规则的img标签 215 | 6. 修复开启图片本地化时保存到数据库功能后,本地化报错的问题 216 | 7. 新增编辑器内可直接粘贴截图,并自动上传到服务器 217 | 8. 新增自定义referer,绕过图片防盗链 218 | 219 | ## v1.3.83 220 | 221 | 1. 修复其他主题或插件全局加载Vue时会导致插件后台无法正常加载的问题(内置js文件,插件大小会增加2M) 222 | 2. 将指定文件类型修改为图片本地化时自动检测文件类型; 223 | 3. 修复本地化保存到数据库文件显示异常的问题; 224 | 4. 新增可设置图片本地化后,自动将图片设置为文章的特色图片; 225 | 5. 新增自动给图片添加alt属性时,会将空值的alt重新设置; 226 | 6. 修复图片压缩时会重复下载两次的问题; 227 | 7. 文章发布时自动本地化后不再进行弹出提醒,处理结果会跟随wordpress默认提示进行输出; 228 | 229 | ## v1.3.82 230 | 231 | 1. 移除插件内的时区定义代码(导致某些情况下文章发布时间出现偏差); 232 | 233 | ## v1.3.81 234 | 235 | 1. 修复wordpress不使用默认表前缀安装时,批量本地化无法检测的问题; 236 | 2. 修复批量本地化时,清空时间范围后无法检测的问题; 237 | 238 | ## v1.3.8 239 | 240 | 1. 修复设置界面,日期选择时异常报错导致无法清除的问题。 241 | 242 | ## v1.3.7 243 | 244 | 1. 新增定时任务可以指定日期范围、每日的时间范围进行定时发布。 245 | 2. 新增批量本地化时可选文章状态,可指定不限、草稿、已发布等文章状态进行批量本地化。 246 | 3. 优化批量压缩图片功能。 247 | 248 | ## v1.3.6 249 | 250 | 1. 修复edit_themes权限导致部分情况下无法显示配置页面的问题:edit_themes -> manage_options 251 | 252 | ## v1.3.5 253 | 254 | 1. 修复插件日志无法清空的问题 255 | 2. 更新图片压缩页面加载目录时异步加载,避免文件数量太多导致卡死; 256 | 257 | ## v1.3.4 258 | 259 | 1. 修复不规范的img标签,不会被匹配到的问题。 260 | 261 | ## v1.3.3 262 | 263 | 1. 修改代码适配wordpress插件商店规范; 264 | 2. 图片压缩完成后自动刷新显示的目录; 265 | 3. 修改网络请求超时时间为120s; 266 | 267 | ## v1.3.1 beta 268 | 269 | 1. 新增批量本地化时,可以指定文章分类,指定文章发布时间范围; 270 | 2. 新增域名白名单,插件将忽略白名单内的域名,不会进行本地化; 271 | 3. 新增自定义图片保存类型功能 272 | 4. 新增图片批量压缩功能; 273 | 5. 接口增加随机时间戳; 274 | 6. 优化自动发布文章的定时任务 275 | 7. 修复压缩图片时图片读取失败的问题 276 | 8. 修改代码适配wordpress插件商店规范 277 | 278 | ## v1.2.0 beta 279 | 280 | 1. 增加图片本地化日志收集的功能,随时了解本地化失败的原因; 281 | 2. 新增定时发布文章的功能,可设置定时发布时是否本地化文章图片; 282 | 3. 新增批量本地化已发布文章内外部图片的功能; 283 | 4. 新增插件更新日志,便于用户及时响应插件更新; 284 | 5. 新增插件BUG在线反馈的功能,便于及时修复问题; 285 | 6. 修改接口密钥为安装插件后随机生成,防止接口被恶意利用; 286 | 7. 新增图片本地化时是否添加网站域名的功能开关,开启后本地化后的图片链接为包含域名的完整路径; 287 | 288 | ## v1.1.3 289 | 290 | 1. 本地化下载图片的方式调整为curl获取,并模拟referer绕过防盗链; 291 | 2. 修改插件全局变量、函数的命名前缀; 292 | 3. 修复没有判断图片下载结果导致的异常问题; -------------------------------------------------------------------------------- /response/response.php: -------------------------------------------------------------------------------- 1 | private = get_option( "nicen_make_plugin_private" ); 19 | } 20 | 21 | public function add_schedules( $schedules ) { 22 | $schedules['nicen_crontab'] = array( 23 | 'interval' => intval( get_option( 'nicen_make_plugin_interval' ) ), //获取设置的间隔时间 24 | 'display' => '定时发布草稿文章' 25 | ); 26 | 27 | return $schedules; 28 | } 29 | 30 | /** 31 | * 接收响应 32 | * */ 33 | public function response() { 34 | 35 | 36 | global $table_prefix; //获取数据表前缀 37 | 38 | /** 39 | * 接手响应 40 | * */ 41 | 42 | try { 43 | 44 | /** 45 | * 本地化图片的请求 46 | * */ 47 | if ( isset( $_GET['nicen_make_replace'] ) ) { 48 | $this->auth(); //权限验证 49 | ( Nicen_local::getInstance() )->localImage( sanitize_url( $_POST['img'] ) ); 50 | } 51 | 52 | /** 53 | * 清空日志 54 | * */ 55 | if ( isset( $_GET['nicen_make_clear_log'] ) ) { 56 | $this->auth(); //权限验证 57 | update_option( "nicen_plugin_error_log", "" ); //清空日志 58 | exit( json_encode( [ 59 | 'code' => 1, 60 | 'result' => "清除成功!" 61 | ] ) ); 62 | } 63 | 64 | /** 65 | * 批量本地化 66 | * */ 67 | if ( isset( $_GET['nicen_make_batch'] ) ) { 68 | 69 | 70 | $this->auth(); //权限验证 71 | global $wpdb; //数据库操作 72 | 73 | $json = json_decode( file_get_contents( 'php://input' ), true ); 74 | 75 | /** 76 | * 判断参数完整性 77 | * 有一个没填那就获取所有文章 78 | * */ 79 | 80 | $condition = [ 81 | '`post_type` = "post"' 82 | ]; 83 | 84 | 85 | /** 86 | * (排除自动草稿) 87 | * */ 88 | if ( $json['status'] === 1 ) { 89 | $condition[] = '(`post_status` = "publish" or `post_status` = "draft" or `post_status` = "pending" or `post_status` = "future")'; 90 | } elseif ( $json['status'] === 2 ) { 91 | $condition[] = '(`post_status` = "draft")'; 92 | } elseif ( $json['status'] === 3 ) { 93 | $condition[] = '(`post_status` = "publish")'; 94 | } elseif ( $json['status'] === 4 ) { 95 | $condition[] = '(`post_status` = "pending")'; 96 | } elseif ( $json['status'] === 5 ) { 97 | $condition[] = '(`post_status` = "post_status")'; 98 | } 99 | 100 | /** 101 | * ID范围 102 | * */ 103 | if ( ! empty( $json['start'] ) && ! empty( $json['end'] ) ) { 104 | $condition[] = '(`ID` >= ' . $json['start'] . ' and `ID` <= ' . $json['end'] . ')'; 105 | } 106 | 107 | 108 | /** 109 | * 时间范围 110 | * */ 111 | if ( ! empty( $json['range'] ) ) { 112 | $condition[] = '(`post_date` >= "' . $json['range'][0] . '" and `post_date` <= "' . $json['range'][1] . '")'; 113 | } 114 | 115 | /** 116 | * 分类范围 117 | * */ 118 | if ( ! empty( $json['category'] ) ) { 119 | $condition[] = '`ID` in (select DISTINCT `object_id` from `' . $table_prefix . 'term_relationships` where `term_taxonomy_id` in (' . join( ',', $json['category'] ) . '))'; 120 | } 121 | 122 | 123 | $sql = 'select `ID` from `' . $table_prefix . 'posts` where ' . join( ' and ', $condition ) . ' order by `post_date`'; 124 | 125 | 126 | $result = $wpdb->get_results( $sql ); 127 | 128 | /** 129 | * 判断本地化结果 130 | * */ 131 | if ( empty( $result ) ) { 132 | exit( json_encode( [ 133 | 'code' => 0, 134 | 'errMsg' => "没有符合条件的文章或草稿!" 135 | ] ) ); 136 | } else { 137 | exit( json_encode( [ 138 | 'code' => 1, 139 | 'errMsg' => "查询成功!", 140 | 'data' => $result 141 | ] ) ); 142 | } 143 | 144 | } 145 | 146 | 147 | /** 148 | * 开始本地化 149 | * */ 150 | if ( isset( $_GET['nicen_make_local_batch'] ) && isset( $_GET['batch_id'] ) ) { 151 | 152 | $this->auth(); //权限验证 153 | $ID = sanitize_text_field( $_GET['batch_id'] ); //文章ID 154 | $post = get_post( $ID ); //获取文章 155 | $log = nicen_make_when_save_post( $ID, false ); //开始本地化 156 | 157 | /** 158 | * 记录最后一次本地化的文章ID 159 | * */ 160 | update_option( 'nicen_last_batch', $ID ); //记录本地化 161 | /** 162 | * 返回结果 163 | * */ 164 | exit( json_encode( [ 165 | 'code' => 1, 166 | 'errMsg' => empty( $log ) ? "文章【" . $post->post_title . '】没有检测到外部图片' : "文章【" . $post->post_title . '】' . $log 167 | ] ) ); 168 | } 169 | 170 | 171 | /** 172 | * 是否修改了定时任务的执行状态 173 | * */ 174 | if ( isset( $_POST['nicen_make_plugin_auto_publish'] ) ) { 175 | 176 | /** 177 | * 对比 178 | * */ 179 | $list = [ 180 | 'nicen_make_plugin_order', 181 | 'nicen_make_plugin_auto_publish', 182 | 'nicen_make_plugin_interval', 183 | 'nicen_make_plugin_publish_local', 184 | 'nicen_make_publish_date' 185 | ]; 186 | 187 | /** 188 | * 表单值是否有了变化 189 | * */ 190 | 191 | $hasChange = false; //变化 192 | 193 | foreach ( $list as $value ) { 194 | if ( nicen_make_config( $value ) != $_POST[ $value ] ) { 195 | $hasChange = true; 196 | break; 197 | } 198 | } 199 | 200 | 201 | /** 202 | * 配置是否发生改变 203 | * */ 204 | if ( $hasChange ) { 205 | 206 | $current = sanitize_text_field( $_POST['nicen_make_plugin_auto_publish'] ); //修改的状态 207 | 208 | 209 | /** 210 | * 如果是开启 211 | * */ 212 | if ( $current ) { 213 | /*重新初始化钩子*/ 214 | add_filter( 'cron_schedules', array( $this, 'add_schedules' ) ); //自定义间隔时间 215 | wp_clear_scheduled_hook( 'nicen_plugin_auto_publish' ); //清除任务 216 | wp_schedule_event( time(), 'nicen_crontab', 'nicen_plugin_auto_publish' ); 217 | } else { 218 | update_option( 'nicen_last_auto_publish', "任务已关闭" ); 219 | wp_clear_scheduled_hook( 'nicen_plugin_auto_publish' ); //清除任务 220 | } 221 | 222 | } 223 | 224 | 225 | } 226 | 227 | 228 | /** 229 | * 图片压缩 230 | * */ 231 | if ( isset( $_GET['nicen_make_compress'] ) ) { 232 | $this->auth(); //权限验证 233 | 234 | $json = json_decode( file_get_contents( 'php://input' ), true ); 235 | 236 | if ( isset( $json['file'] ) ) { 237 | exit( json_encode( ( Nicen_comress::getInstance() )->getCompress( $json['file'] ) ) ); 238 | } 239 | } 240 | 241 | 242 | /** 243 | * 加载目录 244 | * */ 245 | if ( isset( $_GET['nicen_make_files'] ) ) { 246 | 247 | $this->auth(); //权限验证 248 | 249 | $json = json_decode( file_get_contents( "php://input" ), true ); 250 | 251 | if ( empty( $json['path'] ) ) { 252 | exit( json_encode( [ 253 | 'code' => 0, 254 | 'errMsg' => "没有指定文件目录!" 255 | ] ) ); 256 | } 257 | 258 | /** 259 | * 读取文件列表 260 | * */ 261 | $lists = ( Nicen_comress::getInstance() )->readDirs( $json['path'] ); 262 | 263 | $result = json_encode( [ 264 | 'code' => 1, 265 | 'data' => $lists, 266 | 'errMsg' => "加载成功!" 267 | ] ); 268 | 269 | exit( $result ); 270 | 271 | } 272 | 273 | 274 | } catch ( \Throwable $e ) { 275 | exit( json_encode( [ 276 | 'code' => 0, 277 | 'errMsg' => $e->getMessage() 278 | ] ) ); 279 | } 280 | 281 | } 282 | 283 | /** 284 | * 添加一个间隔时间 285 | * */ 286 | 287 | /** 288 | * 验证接口权限 289 | * */ 290 | public function auth() { 291 | 292 | if ( empty( $_GET['private'] ) && empty( $_POST['private'] ) ) { 293 | exit( json_encode( [ 294 | 'code' => 0, 295 | 'result' => "密钥为空" 296 | ] ) ); 297 | } 298 | 299 | if ( ( $_GET['private'] ?? "" ) != $this->private && ( $_POST['private'] ?? "" ) != $this->private ) { 300 | exit( json_encode( [ 301 | 'code' => 0, 302 | 'result' => "密钥有误" 303 | ] ) ); 304 | } 305 | } 306 | 307 | /** 308 | * 获取单例 309 | * */ 310 | public static function getInstance() { 311 | /*如果实例不存在*/ 312 | if ( ! self::$self ) { 313 | self::$self = new self(); 314 | } 315 | 316 | return self::$self; 317 | } 318 | 319 | 320 | } 321 | 322 | 323 | ( Nicen_response::getInstance() )->response(); //接收请求 -------------------------------------------------------------------------------- /admin/render.php: -------------------------------------------------------------------------------- 1 | get_logs() ); 16 | 17 | echo ''; 18 | echo '清空插件日志'; 19 | echo ''; 20 | 21 | echo ' 22 | 23 | 27 | '; 28 | echo ''; 29 | 30 | 31 | } 32 | 33 | 34 | /** 35 | * 插件升级 36 | */ 37 | function nicen_plugin_update() { 38 | 39 | echo ' 40 | 41 | 当前版本(' . esc_html( NICEN_VERSION ) . ')/ 最新版本({{version}}) 42 | 43 | 44 | 微信号good7341、Github提交issue、博客nicen.cn下方留言均可 45 | 46 | 47 | Github:https://github.com/friend-nicen/nicen-localize-image 48 |
49 | Gitee:https://gitee.com/friend-nicen/nicen-localize-image 50 |
51 | 博客:https://nicen.cn/2893.html 52 |
53 | 仓库内的版本永远是最新版本,如您觉得插件给你带来了帮助,欢迎star!祝您早日达成自己的目标! 54 |
55 | 56 | 57 | 58 | 61 | 62 | 63 | 微信支持 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 支付宝支持 75 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | QQ支持 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | '; 94 | 95 | } 96 | 97 | 98 | /** 99 | * 定时任务 100 | * */ 101 | function Nicen_form_timer() { 102 | 103 | echo ' 104 | 105 | 106 | 107 | '; 108 | 109 | 110 | echo ' 111 | 112 | 113 | 114 | 115 | 120 | 121 | '; 122 | 123 | 124 | } 125 | 126 | 127 | /** 128 | * 文章批量本地化 129 | */ 130 | function Nicen_form_batch() { 131 | 132 | $count = wp_count_posts();//文章总数 133 | $last = get_option( 'nicen_last_batch' ); //上次本地化的ID 134 | 135 | /** 136 | * 获取上次的ID 137 | * */ 138 | if ( ! empty( $last ) ) { 139 | $last = '上次批量本地化的文章ID为:' . esc_html( $last ) . ','; 140 | } 141 | 142 | echo ' 143 |
144 | 按照指定的文章ID范围批量进行图片本地化,点击开始后任务自动运行,运行过程中可以随时暂停,关闭网页表示强制暂停!运行过程中将会展示实时日志! 145 |

146 | ' . esc_html( $last ) . '当前共有已发布文章' . esc_html( $count->publish ) . '篇,草稿' . esc_html( $count->draft ) . '篇!不填起始ID默认批量本地化所有文章! 147 |
148 |
149 | 150 | 151 | 156 | 157 | 158 | '; 159 | 160 | 161 | /** 162 | * 新增可选项 163 | * */ 164 | $options = '[ 165 | { 166 | label:"不限", 167 | value:1 168 | }, 169 | { 170 | label:"草稿", 171 | value:2 172 | }, 173 | { 174 | label:"已发布", 175 | value:3 176 | }, 177 | { 178 | label:"待审", 179 | value:4 180 | }, 181 | { 182 | label:"定时发布", 183 | value:5 184 | } 185 | ]'; 186 | 187 | 188 | echo " 189 | 190 | 197 | 198 | "; 199 | 200 | echo ' 201 | 202 | '; 203 | 204 | 205 | echo " 206 | 207 | 215 | 216 | "; 217 | 218 | echo ''; 219 | echo ' 220 | {{batch.loading?"正在批量本地化,点击取消运行...":"开始批量本地化"}} 221 | 取消运行 222 | '; 223 | echo ''; 224 | 225 | } 226 | 227 | 228 | /** 229 | * 文章批量本地化 230 | * */ 231 | function Nicen_form_compress() { 232 | 233 | echo ' 234 | 选择指定的目录或者图片进行压缩,默认根目录为 wordpress媒体文件存放目录,压缩前请先点击加载图片目录,然后再选中目录或图片进行压缩,压缩服务由 resmush.it 提供。 235 | '; 236 | 237 | echo ''; 238 | echo ' 239 | {{tree.loading?"正在压缩第"+tree.count+"张图片,点击取消压缩...":"开始压缩"}} 240 | 取消压缩 241 | 加载图片目录 242 | '; 243 | echo ''; 244 | 245 | echo " 246 | 252 | 253 | "; 254 | 255 | 256 | } 257 | 258 | 259 | /** 260 | * 插件升级 261 | */ 262 | function nicen_plugin_vip() { 263 | ?> 264 |
265 |
开源版已进入LTS(Long-term 266 | support,长期支持,缩写:LTS)阶段,以后只修复BUG不再更新新功能,新功能将发布在Pro版: 267 |
268 | 269 |
270 | 271 |
272 | -------> 39.9元/Pro版永久+更新+售后(无使用限制,后台可下载最新版插件);如您有意请加微信good7341 273 |
274 | 275 |
276 | 277 | -1) { 23 | old = old.replace(search, re); 24 | } 25 | return old; 26 | } 27 | 28 | /** 29 | * 替换编辑器内容 30 | * */ 31 | function replaceC(content) { 32 | ed.setContent(content); 33 | } 34 | 35 | /** 36 | * 字符转义 37 | * */ 38 | function html2Escape(sHtml) { 39 | return sHtml.replace(/[<>&"]/g, function (c) { 40 | return {'<': '<', '>': '>', '&': '&', '"': '"'}[c]; 41 | }); 42 | } 43 | 44 | 45 | /** 46 | * 新增插件 47 | * */ 48 | ed.addButton('local', { 49 | title: '外部图片替换', 50 | image: url + '/icon/local.svg', 51 | onclick: function () { 52 | 53 | const confirm = layer.confirm("是否要检索文章内所有外部图片?", function () { 54 | 55 | //关闭弹出层 56 | layer.close(confirm); 57 | 58 | 59 | /** 60 | * 弹出检测窗口 61 | * */ 62 | 63 | let domain = location.host; 64 | 65 | let replace = []; //替换列表 66 | let link = []; 67 | 68 | /** 69 | * 获取所有图片 70 | * */ 71 | 72 | let count = 1; //计数 73 | 74 | /** 75 | * 遍历所有本地图片 76 | * */ 77 | $(ed.getBody()).find("img").each(function (index) { 78 | let that = $(this).attr("src"); 79 | 80 | /** 81 | * 如果没有图片 82 | * */ 83 | if (!that) { 84 | return 85 | } 86 | 87 | /** 88 | * 如果没有http 89 | * */ 90 | if (that.indexOf('http') < 0) { 91 | return 92 | } 93 | 94 | /** 95 | * 如果图片不包含本地域名 96 | * 如果没有重复的包含 97 | * */ 98 | if (that.indexOf(domain) < 0 && link.indexOf(that) < 0) { 99 | link.push(that); //记录链接 100 | replace.push(`
${count}${that}
`); 101 | count++; //加1 102 | } 103 | }); 104 | 105 | /** 106 | * 判断是否有外部图片 107 | * */ 108 | 109 | if (replace.length == 0) { 110 | layer.msg("没有找到外部图片"); 111 | return; 112 | } 113 | 114 | let content = ed.getContent(); //获取编辑器内容 115 | 116 | 117 | /** 118 | * 弹出 119 | * */ 120 | let index = layer.open({ 121 | title: "共检测到外部图片" + (count - 1) + "张", 122 | content: `
${replace.join('')}
`, 123 | area: ['30vw', '50vh'], 124 | maxmin: true, 125 | closeBtn: 1, 126 | btn: ['开始替换'], 127 | yes: async function () { 128 | 129 | let number = 1; 130 | let index = null; 131 | let flag = true; 132 | 133 | /** 134 | * 终止抓取 135 | * */ 136 | function terminate(text = false) { 137 | /** 138 | * 替换编辑器的内容 139 | * */ 140 | replaceC(content); 141 | 142 | try { 143 | flag = false; 144 | layer.close(index); 145 | if (!text) { 146 | layer.msg("成功替换" + (number - 1) + "张外部图片"); 147 | } else { 148 | layer.msg(text); 149 | } 150 | $(document).off('keydown'); 151 | } catch (e) { 152 | console.log(e); 153 | } 154 | } 155 | 156 | /** 157 | * 监听关闭事件 158 | * */ 159 | $(document).bind('keydown', 'esc', terminate); 160 | 161 | 162 | let task = []; //promise 163 | let ok = 0; //处理过的数量 164 | 165 | /** 166 | * 开始循环处理 167 | * */ 168 | for (let i of link) { 169 | 170 | /** 171 | * 如果被终止 172 | * */ 173 | if (!flag) { 174 | break; 175 | } 176 | 177 | index = layer.msg(`正在替换第${number}张,按Esc可停止替换...`, { 178 | icon: 16 179 | , shade: 0.1, 180 | time: 0 181 | }); 182 | 183 | 184 | task.push(new Promise((resolve) => { 185 | 186 | /** 187 | * 请求服务器接口 188 | * */ 189 | 190 | $.post('/?nicen_make_replace=1', { 191 | private: POST_KEY, 192 | img: i 193 | }, function (res) { 194 | 195 | if (res.code === -1) { 196 | layer.msg(res.result); 197 | resolve(0); 198 | } else if (res.code === 1) { 199 | /** 200 | * 替换变量里的内容 201 | * */ 202 | content = replaceAll(content, html2Escape(i), res.result); 203 | 204 | 205 | } else { 206 | number--; //未成功 207 | layer.msg(res.result); 208 | } 209 | 210 | resolve(1); //退出本次任务 211 | 212 | }, 'json').error(async e => { 213 | 214 | layer.msg("图片下载异常!"); 215 | 216 | let timer = setTimeout(() => { 217 | clearTimeout(timer); 218 | resolve(0); 219 | }, 1500); 220 | 221 | }) 222 | 223 | })); 224 | ok++; //计数 225 | 226 | /* 并发数 */ 227 | if (task.length === SYNC_NUMBER || ok === link.length) { 228 | let code = await Promise.all(task).catch(e => { 229 | console.log(e) 230 | return false; 231 | }); 232 | 233 | task = []; //空数组 234 | 235 | /* 计算成功数 */ 236 | for (let k of code) { 237 | if (!k) { 238 | number--; 239 | } 240 | } 241 | 242 | } 243 | 244 | 245 | number++; //数量增加 246 | } 247 | 248 | terminate("成功替换" + (number - 1) + "张外部图片,记得保存哈,可在插件设置页面查看日志!"); 249 | } 250 | }); 251 | 252 | 253 | }) 254 | 255 | } 256 | }); 257 | }, 258 | createControl: function (n, cm) { 259 | return null; 260 | }, 261 | }); 262 | 263 | tinymce.PluginManager.add('local', tinymce.plugins.local); 264 | })(); -------------------------------------------------------------------------------- /admin/form.php: -------------------------------------------------------------------------------- 1 | 29 |
30 | 31 |
32 | 36 | 41 | 42 | 43 | 51 | 52 | 56 |
57 | 58 | 62 | 63 |
64 |
65 |
66 |
67 |
68 | ', esc_html( $field['title'] ) ); 110 | echo esc_html( $field['callback']( $field['args'] ) ); 111 | echo '
'; 112 | continue; 113 | } 114 | 115 | /** 116 | * 是否需要自定义提示 117 | * */ 118 | if ( ! isset( $field['args']['tip'] ) ) { 119 | $label = 'label=%s'; 120 | } else { 121 | $label = ''; 122 | } 123 | 124 | /** 125 | * 是否具有总开关 126 | * */ 127 | if ( ! isset( $param['key'] ) ) { 128 | echo sprintf( '', esc_html( $field['title'] ) ); 129 | } else { 130 | 131 | /** 132 | * 总开关或者忽略的 133 | * */ 134 | if ( $param['key'] == $field['id'] || in_array( $field['id'], $param['ignore'] ) ) { 135 | echo sprintf( '', esc_html( $field['title'] ) ); 136 | } else { 137 | echo sprintf( '', esc_html( $field['title'] ) ); 138 | } 139 | 140 | } 141 | 142 | /** 143 | * 是否需要输出自定义tip 144 | * */ 145 | if ( isset( $field['args']['tip'] ) ) { 146 | echo sprintf( '', esc_html( $field['args']['tip'] ), esc_html( $field['title'] ) ); 155 | } 156 | 157 | /** 158 | * 调用输出函数 159 | * */ 160 | call_user_func( 161 | $field['callback'], 162 | /*合并出需要的参数*/ 163 | array_merge( 164 | $field['args'] ?? [], 165 | [ 166 | 'label_for' => $field['id'], 167 | 'title' => esc_html( $field['title'] ) 168 | ] 169 | ) ); 170 | 171 | echo ''; 172 | 173 | } 174 | } 175 | 176 | /** 177 | * 主题设置片段页面输出 178 | * */ 179 | function nicen_make_do_settings_sections_user( $page ) { 180 | global $wp_settings_sections; 181 | 182 | 183 | if ( ! isset( $wp_settings_sections[ $page ] ) ) { 184 | return; 185 | } 186 | 187 | foreach ( (array) $wp_settings_sections[ $page ] as $key => $section ) { 188 | 189 | 190 | /*输出tab头*/ 191 | echo sprintf( '', esc_html( $key ), esc_html( $section['title'] ) ); 192 | 193 | 194 | $param = [];//是否需要显示、隐藏切换 195 | 196 | /** 197 | * 是否有传递回调函数 198 | * */ 199 | if ( isset( $section['callback'] ) ) { 200 | $param = $section['callback'](); 201 | } 202 | 203 | 204 | /** 205 | * 输出输入组件 206 | * 207 | * @param $page integer "菜单页面id" 208 | * @param $section array 分节的信息 209 | * */ 210 | 211 | nicen_make_do_settings_fields_user( $page, $section['id'], $section['callback'] ?? false ); 212 | 213 | /** 214 | * 回调函数如果有自定义输出 215 | * */ 216 | if ( isset( $param['render'] ) ) { 217 | esc_html( $param['render']() ); 218 | } 219 | 220 | /*闭合*/ 221 | echo ""; 222 | 223 | 224 | } 225 | } 226 | 227 | /** 228 | * 数字输入框 229 | * */ 230 | function nicen_make_form_number( $args ) { 231 | ?> 232 | 238 | 247 | 252 | 261 | 266 | 274 | 277 | 282 | 290 | 297 | 305 |
306 | 308 | 309 | 314 |
315 | 324 | 325 |
326 | 335 | 338 | ' 340 | style="width: 100%" 341 | show-arrow 342 | v-model="data." 343 | placeholder="请选择" 344 | /> 345 | 355 | 356 | 359 | ' 361 | style="width: 100%" 362 | show-arrow 363 | mode="multiple" 364 | v-model="data." 365 | placeholder="请选择" 366 | /> 367 | "nicen_make_plugin",//主题后台设置字段 42 | "menu_title" => '图片本地化', 43 | 'page_title' => '图片本地化', 44 | 'callback' => 'nicen_make_setting_load', 45 | 'capablity' => 'manage_options', 46 | /*分节*/ 47 | "sections" => [ 48 | [ 49 | "id" => "nicen_make_plugin_section", 50 | 'title' => '基础设置', 51 | 'fields' => [ 52 | [ 53 | 'id' => 'text_info', 54 | 'title' => '功能设置说明', 55 | 'callback' => 'nicen_make_plugin_form_text', 56 | 'args' => [ 57 | 'info' => '插件提供两种本地化外部图片的功能,本地化时自动跳过重复链接的图片:
编辑器本地化插件】启用后会在文章编辑器上方显示一个小图标,点击之后可以自动检测并本地化所有外部图片;
发布时自动本地化】启用后会在文章发布时自动本地化所有外部图片;推荐使用【编辑器本地化插件】在发布前进行本地化,当图片数量过多或者文件太大【发布时自动本地化】可能会导致请求卡死。
保存到数据库】启用后会将图片信息保存到数据库,可在媒体库内看到这张图片,同时会生成多张不同大小的内容一样图片。' 58 | ] 59 | ], 60 | [ 61 | 'id' => 'nicen_make_plugin_editor', 62 | 'title' => '启用编辑器本地化图片插件', 63 | 'callback' => 'nicen_make_form_switch', 64 | ], 65 | [ 66 | 'id' => 'nicen_make_sync_number', 67 | 'title' => '编辑器插件本地化并发数', 68 | 'callback' => 'nicen_make_form_input', 69 | 'args' => [ 70 | 'tip' => '同时下载的图片数量' 71 | ] 72 | ], 73 | [ 74 | 'id' => 'nicen_make_plugin_save', 75 | 'title' => '启用文章发布时自动本地化', 76 | 'callback' => 'nicen_make_form_switch', 77 | ], 78 | [ 79 | 'id' => 'nicen_make_plugin_local', 80 | 'title' => '图片本地化时保存到数据库', 81 | 'callback' => 'nicen_make_form_switch', 82 | ], 83 | [ 84 | 'id' => 'nicen_make_save_as_thumb', 85 | 'title' => '图片本地化后设置特色图片', 86 | 'callback' => 'nicen_make_form_switch', 87 | 'args' => [ 88 | 'tip' => '打开后会自动将本地化下载的图片设置为文章特色图片,必须打开保存到数据库' 89 | ] 90 | ], 91 | [ 92 | 'id' => 'nicen_make_plugin_add_domain', 93 | 'title' => '本地化的图片链接添加域名', 94 | 'callback' => 'nicen_make_form_switch', 95 | 'args' => [ 96 | 'tip' => '不开启是默认为/wp/image.png这种格式,开启后链接变为http://domain.com/wp/image.png格式' 97 | ] 98 | ], 99 | [ 100 | 'id' => 'nicen_make_plugin_alt', 101 | 'title' => '发布时图片自动添加alt属性', 102 | 'callback' => 'nicen_make_form_switch', 103 | 'args' => [ 104 | 'tip' => '默认添加文章标题作为alt属性,只会给没有alt的标签添加' 105 | ] 106 | ], 107 | 108 | [ 109 | 'id' => 'nicen_make_plugin_alt_type', 110 | 'title' => '添加alt属性的方式', 111 | 'callback' => 'nicen_make_form_select', 112 | 'args' => [ 113 | 'options' => [ 114 | [ 115 | 'label' => '添加文章标题', 116 | 'value' => '1' 117 | ], 118 | [ 119 | 'label' => '添加文章分类', 120 | 'value' => '2' 121 | ] 122 | ] 123 | ] 124 | ], 125 | [ 126 | 'id' => 'nicen_make_plugin_referer', 127 | 'title' => '自定义Referer', 128 | 'callback' => 'nicen_make_form_input', 129 | 'args' => [ 130 | 'tip' => '不填就使用系统默认的规则' 131 | ] 132 | ], 133 | [ 134 | 'id' => 'nicen_make_plugin_path', 135 | 'title' => '本地化图片时的保存路径', 136 | 'callback' => 'nicen_make_form_input', 137 | 'args' => [ 138 | 'tip' => '以wordpress安装目录作为根目录' 139 | ] 140 | ] 141 | ] 142 | ], 143 | [ 144 | "id" => "nicen_make_plugin_crontab", 145 | 'title' => '定时发布', 146 | 'callback' => [ 147 | "render" => "Nicen_form_timer" 148 | ], 149 | 'fields' => [ 150 | [ 151 | 'id' => 'text_info', 152 | 'title' => '定时发布功能说明', 153 | 'callback' => 'nicen_make_plugin_form_text', 154 | 'args' => [ 155 | 'info' => '默认按照文章添加的顺序定时将未发布的草稿进行发布,基于wp自带的定时任务。
不选择日期和时间代表不进行限制!

Wp自带的定时任务】是在网站有用户访问时才会去执行,假设任务是16:00执行,但是这个时间段没有人访问网站,一直到17:00才有人访问,那么任务17点才会被执行,于是文章发布时间就比预定的时间晚了一小时;所以建议通过宝塔或者其他工具设置定时访问wp的任务接口,用以保证定时任务执行的准时性

您的wordpress触发定时任务接口为:' . $crontab . ',每访问一次都会重新检测定时任务是否需要执行,插件日志页面可查看运行日志

wp定时任务】:' . $nicen_crontab_tab . '
当前系统时间】:' . date( "Y-m-d H:i:s" ) . ',所在时区:' . date_default_timezone_get() . ',如果系统时间不对,请开启或关闭下方的系统时间校准!
自动发布日志】:' . nicen_getAutoInfo() 156 | ] 157 | ], 158 | [ 159 | 'id' => 'nicen_make_plugin_adjust', 160 | 'title' => '开启系统时间校准', 161 | 'callback' => 'nicen_make_form_switch', 162 | ], 163 | [ 164 | 'id' => 'nicen_make_plugin_auto_publish', 165 | 'title' => '开启自动发布文章', 166 | 'callback' => 'nicen_make_form_switch', 167 | ], 168 | [ 169 | 'id' => 'nicen_make_plugin_interval', 170 | 'title' => '每间隔多少秒发布一次', 171 | 'callback' => 'nicen_make_form_number', 172 | ], 173 | [ 174 | 'id' => 'nicen_make_plugin_publish_num', 175 | 'title' => '每次发布的文章数量', 176 | 'callback' => 'nicen_make_form_number', 177 | ], 178 | [ 179 | 'id' => 'nicen_make_publish_type', 180 | 'title' => '定时发布的文章类型', 181 | 'callback' => 'nicen_make_form_select', 182 | 'args' => [ 183 | 'options' => [ 184 | [ 185 | "label" => "草稿", 186 | "value" => "1" 187 | ], 188 | [ 189 | "label" => "待审", 190 | "value" => "2" 191 | ], 192 | [ 193 | "label" => "定时发布", 194 | "value" => "3" 195 | ] 196 | ], 197 | ] 198 | ], 199 | [ 200 | 'id' => 'nicen_make_publish_date', 201 | 'title' => '是否同步发布时间', 202 | 'callback' => 'nicen_make_form_select', 203 | 'args' => [ 204 | 'options' => [ 205 | [ 206 | 'label' => '保持默认的发布时间', 207 | 'value' => '0' 208 | ], 209 | [ 210 | 'label' => '修改为自动发布的时间', 211 | 'value' => '1' 212 | ] 213 | ], 214 | ] 215 | ], 216 | [ 217 | 'id' => 'nicen_make_plugin_order', 218 | 'title' => '选择文章发表顺序', 219 | 'callback' => 'nicen_make_form_select', 220 | 'args' => [ 221 | 'options' => [ 222 | [ 223 | 'label' => '随机发布', 224 | 'value' => 'rand' 225 | ], 226 | [ 227 | 'label' => '按创建时间', 228 | 'value' => 'ID' 229 | ] 230 | ], 231 | ] 232 | ], 233 | [ 234 | 'id' => 'nicen_make_plugin_publish_local', 235 | 'title' => '发布时是否本地化图片', 236 | 'callback' => 'nicen_make_form_select', 237 | 'args' => [ 238 | 'options' => [ 239 | [ 240 | 'label' => '不进行本地化', 241 | 'value' => '0' 242 | ], 243 | [ 244 | 'label' => '发布时本地化图片', 245 | 'value' => '1' 246 | ] 247 | ], 248 | 'tip' => '图片太多太大时,可能会本地化失败!' 249 | ] 250 | ], 251 | ] 252 | ], 253 | [ 254 | "id" => "nicen_make_plugin_batch_local", 255 | 'title' => '批量本地化', 256 | 'callback' => [ 257 | "render" => "Nicen_form_batch" 258 | ] 259 | ], 260 | [ 261 | "id" => "nicen_make_plugin_compress", 262 | 'title' => '图片压缩', 263 | 'callback' => [ 264 | "render" => "Nicen_form_compress" 265 | ] 266 | ], 267 | [ 268 | "id" => "nicen_make_plugin_white", 269 | 'title' => '域名白名单', 270 | 'fields' => [ 271 | [ 272 | 'id' => 'text_info', 273 | 'title' => '功能说明', 274 | 'callback' => 'nicen_make_plugin_form_text', 275 | 'args' => [ 276 | 'info' => '某些外链可能是有意为之,你可能并不需要进行本地化;处于白名单的域名的图片链接不会进行本地化操作【跳过白名单链接时会提示失败】;格式应当如下(一行一个): 277 |
278 | nicen.cn
279 | 1.nicen.cn
280 | 2.nicen.cn,这样这三个域名的链接都不会被本地化;' 281 | ] 282 | ], 283 | [ 284 | 'id' => 'nicen_make_publish_white', 285 | 'title' => '域名白名单', 286 | 'callback' => 'nicen_make_form_textarea', 287 | ], 288 | ] 289 | ], 290 | [ 291 | "id" => "nicen_make_plugin_local_log", 292 | 'title' => '插件日志', 293 | 'callback' => [ 294 | "render" => "nicen_plugin_local_log" 295 | ], 296 | 'fields' => [ 297 | [ 298 | 'id' => 'nicen_make_plugin_record_log', 299 | 'title' => '本地化时记录日志', 300 | 'callback' => 'nicen_make_form_switch', 301 | ], 302 | ] 303 | ], 304 | [ 305 | "id" => "nicen_make_plugin_update", 306 | 'title' => '插件升级', 307 | 'callback' => [ 308 | "render" => "nicen_plugin_update" 309 | ], 310 | ], 311 | [ 312 | "id" => "nicen_make_plugin_vip", 313 | 'title' => 'Pro版', 314 | 'callback' => [ 315 | "render" => "nicen_plugin_vip" 316 | ], 317 | ] 318 | ] 319 | ] 320 | ] ); 321 | 322 | 323 | /** 324 | * 主题所有配置 325 | * 键=>默认值 326 | * */ 327 | define( 'nicen_make_CONFIG', [ 328 | "nicen_make_plugin_local" => '1', //本地化时保存到数据库 329 | 'nicen_make_plugin_private' => md5( time() ), //初次安装时的接口密钥 330 | 'nicen_make_plugin_editor' => '1', //开启编辑器插件 331 | 'nicen_make_sync_number' => 5, //编辑器插件并发下载数量 332 | 'nicen_make_plugin_save' => '1', //保存到数据库 333 | 'nicen_make_plugin_save_result' => '', //临时保存本地化 334 | 'nicen_make_plugin_add_thumb' => '0',//是否生产缩略图 335 | 'nicen_make_plugin_alt' => '1', //自动新增alt 336 | 'nicen_make_plugin_alt_type' => '1', //alt增加的类型 337 | 'nicen_make_plugin_path' => nicen_local_image_site_root . '/uploads/replace', //资源保存的路径 338 | 'nicen_make_plugin_add_domain' => '0', //链接是否增加域名 339 | 'nicen_make_save_as_thumb' => '0', 340 | 'nicen_make_plugin_referer' => '', 341 | 342 | /*定时任务*/ 343 | 'nicen_make_plugin_order' => 'ID', //安装ID发布 344 | 'nicen_make_plugin_adjust' => '0', //校准时区 345 | 'nicen_make_plugin_auto_publish' => "0", //是否开启自动发布 346 | 'nicen_make_plugin_interval' => 300, //间隔时间 347 | 'nicen_make_plugin_publish_local' => '0', //定时发布时是否本地化 348 | 'nicen_make_publish_date' => "0", //自动发布的时间 349 | 'nicen_make_publish_date_start' => null, 350 | 'nicen_make_publish_date_end' => null, 351 | 'nicen_make_publish_time_start' => null, 352 | 'nicen_make_publish_time_end' => null, 353 | /* 定时发布的文章数量和状态 */ 354 | 'nicen_make_plugin_publish_num' => 1, 355 | 'nicen_make_publish_type' => "1", 356 | 357 | /*白名单*/ 358 | 'nicen_make_publish_white' => '', 359 | 360 | /*插件日志*/ 361 | 'nicen_make_plugin_record_log' => '1' 362 | ] ); 363 | 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /class/local.php: -------------------------------------------------------------------------------- 1 | is_sava_database = nicen_make_config( 'nicen_make_plugin_local' ); 20 | $this->site_path = nicen_make_config( 'nicen_make_plugin_path' ); //站点目录 21 | $this->is_add_domain = nicen_make_config( 'nicen_make_plugin_add_domain' ); //是否需要域名 22 | $this->root_path = nicen_local_image_root . $this->site_path; //站点目录 23 | $this->add_thumd = nicen_make_config( 'nicen_make_plugin_add_thumb' );//生成缩略图 24 | } 25 | 26 | /** 27 | * 本地化图片 28 | * 29 | * @param $flag false时return,true终止脚本直接输出 30 | * */ 31 | function localImage( $url, $flag = true ) { 32 | 33 | $upload_root = $this->root_path; //站点目录 34 | $upload = $this->site_path; //主题路径 35 | $log = Nicen_Log::getInstance(); //获取日志对象 36 | 37 | /** 38 | * 指定的图片保存目录是否存在 39 | * 不存在则创建 40 | * 创建不成功直接退出 41 | * */ 42 | if ( ! file_exists( $upload_root ) ) { 43 | if ( ! mkdir( $upload_root ) ) { 44 | 45 | if ( $flag ) { 46 | exit( json_encode( $log->add( [ 47 | 'code' => - 1, 48 | 'result' => $upload . '指定的图片保存目录创建失败!' 49 | ] ) ) ); 50 | } else { 51 | return $log->add( [ 52 | 'code' => - 1, 53 | 'result' => $upload . '指定的图片保存目录创建失败!' 54 | ] ); 55 | } 56 | 57 | } 58 | } 59 | 60 | /** 61 | * 判断目录是否可写 62 | * */ 63 | if ( ! is_writable( $upload_root ) ) { 64 | if ( $flag ) { 65 | exit( json_encode( $log->add( [ 66 | 'code' => - 1, 67 | 'result' => $upload . '指定的图片保存目录不可写,替换失败!' 68 | ] ) ) ); 69 | } else { 70 | return $log->add( [ 71 | 'code' => - 1, 72 | 'result' => $upload . '指定的图片保存目录不可写,替换失败!' 73 | ] ); 74 | } 75 | } 76 | 77 | 78 | /** 79 | * 判断是否传递图片 80 | * */ 81 | if ( empty( $url ) ) { 82 | if ( $flag ) { 83 | exit( json_encode( $log->add( [ 84 | 'code' => 0, 85 | 'result' => '图片链接为空!' 86 | ] ) ) ); 87 | } else { 88 | return $log->add( [ 89 | 'code' => 0, 90 | 'result' => '图片链接为空!' 91 | ] ); 92 | } 93 | } 94 | 95 | 96 | /** 97 | * 判断是否传递图片 98 | * */ 99 | if ( strpos( $url, 'http' ) === false ) { 100 | 101 | if ( $flag ) { 102 | exit( json_encode( $log->add( [ 103 | 'code' => 0, 104 | 'result' => '图片链接不规范!' 105 | ] ) ) ); 106 | } else { 107 | return $log->add( [ 108 | 'code' => 0, 109 | 'result' => '图片链接不规范!' 110 | ] ); 111 | } 112 | } 113 | 114 | 115 | $url = html_entity_decode( $url ); //反转义出真实链接 116 | 117 | /** 118 | * 判断是否处于白名单 119 | * */ 120 | if ( $this->is_white( $url ) ) { 121 | if ( $flag ) { 122 | exit( json_encode( $log->add( [ 123 | 'code' => 0, 124 | 'result' => "白名单链接,无需进行本地化" 125 | ] ) ) ); 126 | } else { 127 | return $log->add( [ 128 | 'code' => 0, 129 | 'result' => "白名单链接,无需进行本地化" 130 | ] ); 131 | } 132 | } 133 | 134 | /** 135 | * 获取保存的文件类型 136 | * */ 137 | $url_md5 = md5( $url ); //md5图片链接 138 | 139 | 140 | /** 141 | * 判断文件是否已经存在 142 | * 已经存在则直接返回数据 143 | * */ 144 | $file_search = glob( $upload_root . '/' . $url_md5 . '.*' ); 145 | 146 | if ( ! empty( $file_search ) ) { 147 | /** 148 | * 判断链接是否需要添加域名 149 | * */ 150 | $link = $this->getLink( $file_search[0] ); //获取链接 151 | 152 | if ( $flag ) { 153 | exit( json_encode( $log->add( [ 154 | 'code' => 1, 155 | 'result' => $link 156 | ] ) ) ); 157 | } else { 158 | return $log->add( [ 159 | 'code' => 1, 160 | 'result' => $link 161 | ] ); 162 | } 163 | 164 | } 165 | 166 | 167 | /** 168 | * 判断链接是否可以访问 169 | * */ 170 | if ( $this->getImage( $url, 1 ) != 200 ) { 171 | if ( $flag ) { 172 | exit( json_encode( ( [ 173 | 'code' => 0, 174 | 'result' => $url . '图片链接无法访问!' 175 | ] ) ) ); 176 | } else { 177 | return $log->add( [ 178 | 'code' => 0, 179 | 'result' => $url . '图片链接无法访问!' 180 | ] ); 181 | } 182 | } 183 | 184 | 185 | /** 186 | * 获取图片内容 187 | * html反转义 188 | * */ 189 | $content = @$this->getImage( $url ); 190 | 191 | /** 192 | * 如果读取成功 193 | * */ 194 | if ( $content ) { 195 | 196 | $tmp = $upload_root . '/' . $url_md5; //临时文件 197 | /** 198 | * 写入文件 199 | * */ 200 | if ( file_put_contents( $tmp, $content, LOCK_EX ) ) { 201 | 202 | 203 | $filename = $tmp . "." . nicen_plugin_getType( $tmp ); 204 | rename( $tmp, $filename ); //重命名文件 205 | $link = $this->getLink( $filename ); //获取链接 206 | 207 | /** 208 | * 是否需要保存到数据库 209 | * */ 210 | if ( $this->is_sava_database ) { 211 | $this->saveAsData( $filename ); 212 | } 213 | 214 | 215 | if ( $flag ) { 216 | exit( json_encode( $log->add( [ 217 | 'code' => 1, 218 | 'result' => $link 219 | ] ) ) ); 220 | } else { 221 | return $log->add( [ 222 | 'code' => 1, 223 | 'result' => $link 224 | ] ); 225 | } 226 | 227 | } else { 228 | 229 | if ( $flag ) { 230 | exit( json_encode( $log->add( [ 231 | 'code' => 0, 232 | 'result' => $url . '图片保存失败!' 233 | ] ) ) ); 234 | } else { 235 | return $log->add( [ 236 | 'code' => 0, 237 | 'result' => $url . '图片保存失败!' 238 | ] ); 239 | } 240 | 241 | } 242 | 243 | } else { 244 | 245 | if ( $flag ) { 246 | exit( json_encode( $log->add( [ 247 | 'code' => 0, 248 | 'result' => $url . '图片下载失败!' 249 | ] ) ) ); 250 | } else { 251 | return $log->add( [ 252 | 'code' => 0, 253 | 'result' => $url . '图片下载失败!' 254 | ] ); 255 | } 256 | } 257 | } 258 | 259 | /** 260 | * 获取单例 261 | * */ 262 | public static function getInstance() { 263 | /*如果实例不存在*/ 264 | if ( ! self::$self ) { 265 | self::$self = new self(); 266 | } 267 | 268 | return self::$self; 269 | } 270 | 271 | /** 272 | * 判断指定链接是否是白名单 273 | * 274 | * @param string $url 275 | * 276 | * @return boolean 277 | * */ 278 | public function is_white( $url ) { 279 | 280 | $white = explode( "\n", get_option( 'nicen_make_publish_white' ) ); //获取列表 281 | /*判断是否为空*/ 282 | if ( empty( $white ) ) { 283 | return false; 284 | } 285 | 286 | /* 移除左右特殊字符 */ 287 | foreach ( $white as $key => $host ) { 288 | $white[ $key ] = trim( $host ); 289 | } 290 | 291 | $link = parse_url( $url ); //解析 292 | 293 | if ( in_array( $link['host'], $white ) ) { 294 | return true; 295 | } else { 296 | return false; 297 | } 298 | } 299 | 300 | /** 301 | * @param $filename 302 | * 获取文件链接 303 | */ 304 | function getLink( $filename ) { 305 | $filename = basename( $filename ); //文件名 306 | /** 307 | * 判断链接是否需要添加域名 308 | * */ 309 | if ( $this->is_add_domain ) { 310 | $link = site_url() . $this->site_path . '/' . $filename; 311 | } else { 312 | $link = $this->site_path . '/' . $filename; 313 | } 314 | 315 | return $link; 316 | } 317 | 318 | /** 319 | * 获取图片内容 320 | * 321 | * @param $url string,图片的链接 322 | * */ 323 | function getImage( $url, $option = 0, $self_referer = null ) { 324 | 325 | $referer = nicen_make_config( 'nicen_make_plugin_referer' ); //读取自定义referer 326 | 327 | 328 | /** 329 | * 请求头模拟 330 | * */ 331 | $headers = [ 332 | "Accept-Encoding" => "gzip, deflate", 333 | 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36', 334 | 'Referer' => $self_referer ?: ( empty( $referer ) ? $this->getReferer( $url ) : $referer ) 335 | ]; 336 | 337 | 338 | /** 339 | * 请求数据 340 | * */ 341 | $args = [ 342 | 'headers' => $headers, 343 | 'sslverify' => false, 344 | 'timeout' => 120, 345 | ]; 346 | 347 | if ( $option === 1 ) { 348 | $res = wp_remote_head( $url, $args ); 349 | } else { 350 | $res = wp_remote_get( $url, $args ); 351 | } 352 | 353 | 354 | if ( ! is_array( $res ) ) { 355 | $this->error = $res->get_error_message(); 356 | } 357 | 358 | $code = wp_remote_retrieve_response_code( $res ); 359 | 360 | 361 | /** 362 | * 是否是状态码判断 363 | * */ 364 | if ( in_array( $code, [ 301, 302 ] ) ) { 365 | $newUrl = wp_remote_retrieve_header( $res, 'Location' ); 366 | 367 | return $this->getImage( $newUrl, $option, " " ); // 递归调用 368 | } else { 369 | if ( $option ) { 370 | 371 | /* 二次确认 */ 372 | if ( $option === 1 && $code !== 200 ) { 373 | $code = $this->getImage( $url, 2 ); // 递归调用 374 | } 375 | 376 | return $code; 377 | } else { 378 | return wp_remote_retrieve_body( $res ); 379 | } 380 | } 381 | 382 | 383 | } 384 | 385 | /** 386 | * @param $imageUrl 387 | * 获取默认的referer规则 388 | * 389 | * @return mixed|string 390 | */ 391 | function getReferer( $imageUrl ) { 392 | 393 | /* 定义平台的图片域名或关键词 */ 394 | $platforms = [ 395 | '163' => [ '126.net', '163.com' ], 396 | '微信公众号' => [ 'mmbiz.qpic.cn' ], 397 | 'QQ' => [ 'qpic.cn' ], 398 | '搜狐' => [ 'sohu.com' ], 399 | '今日头条' => [ 'toutiao.com' ], 400 | '微博' => [ 'weibo.com' ], 401 | '知乎' => [ 'zhihu.com' ], 402 | '抖音' => [ 'douyin.com' ], 403 | '小红书' => [ 'xiaohongshu.com' ], 404 | 'B站' => [ 'bilibili.com' ] 405 | ]; 406 | 407 | /* 检测图片属于哪个平台 */ 408 | $platform = '未知平台'; 409 | foreach ( $platforms as $plat => $keywords ) { 410 | foreach ( $keywords as $keyword ) { 411 | if ( strpos( $imageUrl, $keyword ) !== false ) { 412 | $platform = $plat; 413 | break; 414 | } 415 | } 416 | if ( $platform !== '未知平台' ) { 417 | break; 418 | } 419 | } 420 | 421 | /* 根据平台返回对应的Referer */ 422 | switch ( $platform ) { 423 | case '163': 424 | $referer = 'https://news.163.com'; // 假设网易新闻首页 425 | break; 426 | case '微信公众号': 427 | $referer = 'https://mp.weixin.qq.com'; // 微信公众号平台 428 | break; 429 | case 'QQ': 430 | $referer = 'https://qzone.qq.com'; // QQ空间 431 | break; 432 | case '搜狐': 433 | $referer = 'https://www.sohu.com'; // 搜狐首页 434 | break; 435 | case '今日头条': 436 | $referer = 'https://www.toutiao.com'; // 今日头条首页 437 | break; 438 | case '微博': 439 | $referer = 'https://weibo.com'; // 微博首页 440 | break; 441 | case '知乎': 442 | $referer = 'https://www.zhihu.com'; // 知乎首页 443 | break; 444 | case '抖音': 445 | $referer = 'https://www.douyin.com'; // 抖音首页 446 | break; 447 | case '小红书': 448 | $referer = 'https://www.xiaohongshu.com'; // 小红书首页 449 | break; 450 | case 'B站': 451 | $referer = 'https://www.bilibili.com'; // B站首页 452 | break; 453 | default: 454 | $link = parse_url( $imageUrl );//解析链接 455 | $referer = $link['scheme'] . '://' . $link['host']; 456 | break; 457 | } 458 | 459 | return $referer; 460 | } 461 | 462 | /** 463 | * 保存图片到数据库 464 | * 465 | * @param $filename string 文件名 466 | * */ 467 | function saveAsData( $filename ) { 468 | 469 | global $nicen_Post_ID; //正在操作的文章 470 | 471 | /** 472 | * 获取设置的文件保存目录 473 | * */ 474 | $link = $this->getLink( $filename ); //访问链接 475 | 476 | /** 477 | * 拼接插入的数据 478 | * */ 479 | $attachment = array( 480 | 'guid' => $link, 481 | 'post_mime_type' => wp_get_image_mime( $filename ), 482 | 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ), 483 | 'post_content' => '', 484 | 'post_status' => 'inherit' 485 | ); 486 | 487 | // Insert the attachment. 488 | if ( isset( $nicen_Post_ID ) ) { 489 | 490 | $attach_id = wp_insert_attachment( $attachment, $filename, $nicen_Post_ID ); 491 | 492 | /** 493 | * 是否作为特色图片 494 | * */ 495 | 496 | if ( nicen_make_config( 'nicen_make_save_as_thumb' ) ) { 497 | set_post_thumbnail( $nicen_Post_ID, $attach_id ); //设置特色图片 498 | } 499 | 500 | } else { 501 | $attach_id = wp_insert_attachment( $attachment, $filename ); 502 | } 503 | 504 | /** 505 | * 更新访问的URL 506 | * */ 507 | include_once ABSPATH . WPINC . '/pluggable.php'; 508 | include_once( ABSPATH . 'wp-admin/includes/image.php' ); 509 | 510 | /* 保存到数据库不生成缩略图 */ 511 | if ( empty( $this->add_thumd ) ) { 512 | /* 不生成缩略图 */ 513 | add_filter( 'intermediate_image_sizes_advanced', function ( $sizes ) { 514 | return array(); 515 | } ); 516 | } 517 | 518 | // 更新元数据 519 | $attach_data = wp_generate_attachment_metadata( $attach_id, $filename ); 520 | wp_update_attachment_metadata( $attach_id, $attach_data ); 521 | } 522 | 523 | } 524 | 525 | -------------------------------------------------------------------------------- /assets/theme/default/layer.min.css: -------------------------------------------------------------------------------- 1 | .layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%}.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #b2b2b2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;vertical-align:top}.layui-layer-move{display:none;position:fixed;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:50px;line-height:50px;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;overflow:hidden;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;top:17px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2e2d3c;cursor:pointer}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2d93ca}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:1px -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1e9fff;background-color:#1e9fff;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:300px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8d8d8d;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #d3d4d3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476a7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;text-align:right;border-top:1px solid #e9e7e7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#e9e7e7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#c9c5c5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92b8b1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:260px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:300px;padding:0 20px;text-align:center;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:51px;border-left:1px solid #eee;border-right:1px solid #eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{background:0 0;box-shadow:none}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;vertical-align:top}.layui-layer-imgnext,.layui-layer-imgprev{position:fixed;top:50%;width:27px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:30px;background-position:-5px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px}.layui-layer-imgnext{right:30px;background-position:-5px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px}.layui-layer-imgbar{position:fixed;left:0;right:0;bottom:0;width:100%;height:40px;line-height:40px;filter:Alpha(opacity=60);background-color:rgba(2,0,0,.35);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} -------------------------------------------------------------------------------- /assets/theme/default/layer.css: -------------------------------------------------------------------------------- 1 | .layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}html #layuicss-layer{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;border-radius:2px;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layer-anim{-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-00{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:50px;line-height:50px;border-bottom:1px solid #F0F0F0;font-size:14px;color:#333;overflow:hidden;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:17px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:1px -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 15px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:5px 5px 0;padding:0 15px;border:1px solid #dedede;background-color:#fff;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#1E9FFF;background-color:#1E9FFF;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:300px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:5px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#fff;border-color:#E9E7E7;color:#333}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95;border-color:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:260px;height:36px;margin:0 auto;line-height:30px;padding-left:10px;border:1px solid #e6e6e6;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px;padding:6px 10px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:300px;padding:0 20px;text-align:center;overflow:hidden;cursor:pointer}.layui-layer-tab .layui-layer-title span.layui-this{height:51px;border-left:1px solid #eee;border-right:1px solid #eee;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.layui-this{display:block}.layui-layer-photos{background:0 0;box-shadow:none}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgnext,.layui-layer-imgprev{position:fixed;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:30px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:30px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:fixed;left:0;right:0;bottom:0;width:100%;height:40px;line-height:40px;background-color:#000\9;filter:Alpha(opacity=60);background-color:rgba(2,0,0,.35);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}} -------------------------------------------------------------------------------- /assets/axios.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}([function(e,t,n){"use strict";var r=n(3),o=Object.prototype.toString;function i(e){return Array.isArray(e)}function s(e){return void 0===e}function a(e){return"[object ArrayBuffer]"===o.call(e)}function u(e){return null!==e&&"object"==typeof e}function c(e){if("[object Object]"!==o.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function f(e){return"[object Function]"===o.call(e)}function l(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),i(e))for(var n=0,r=e.length;n=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};r.forEach(["delete","get","head"],(function(e){c.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){c.headers[e]=r.merge(s)})),e.exports=c},function(e,t,n){"use strict";function r(e){this.message=e}r.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},r.prototype.__CANCEL__=!0,e.exports=r},function(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r=0)return;s[t]="set-cookie"===t?(s[t]?s[t]:[]).concat([n]):s[t]?s[t]+", "+n:n}})),s):s}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function o(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=o(window.location.href),function(t){var n=r.isString(t)?o(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},function(e,t,n){"use strict";var r=n(10).version,o={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){o[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));var i={};o.transitional=function(e,t,n){function o(e,t){return"[Axios v"+r+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return function(n,r,s){if(!1===e)throw new Error(o(r," has been removed"+(t?" in "+t:"")));return t&&!i[r]&&(i[r]=!0,console.warn(o(r," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,r,s)}},e.exports={assertOptions:function(e,t,n){if("object"!=typeof e)throw new TypeError("options must be an object");for(var r=Object.keys(e),o=r.length;o-- >0;){var i=r[o],s=t[i];if(s){var a=e[i],u=void 0===a||s(a,i,e);if(!0!==u)throw new TypeError("option "+i+" must be "+u)}else if(!0!==n)throw Error("Unknown option "+i)}},validators:o}},function(e,t,n){"use strict";var r=n(2);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;this.promise.then((function(e){if(n._listeners){var t,r=n._listeners.length;for(t=0;t 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /assets/layer.js: -------------------------------------------------------------------------------- 1 | /*! layer-v3.5.1 Web 通用弹出层组件 MIT License */ 2 | ;!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var t=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}(),i=e.LAYUI_GLOBAL||{};return i.layer_dir||t.substring(0,t.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c="creating",u=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function d(t){var n=100,a=document.getElementById(f);return++u>1e4/n?e.console&&console.error(l+".css: Invalid"):void(1989===parseInt(o.getStyle(a,"width"))?(t===c&&a.removeAttribute("lay-status"),a.getAttribute("lay-status")===c?setTimeout(d,n):i()):(a.setAttribute("lay-status",c),setTimeout(function(){d(c)},n)))}()}}},r={v:"3.5.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:260},n))}},s=function(e){var t=this,a=function(){t.creat()};t.index=++r.index,t.config.maxWidth=i(n).width()-30,t.config=i.extend({},t.config,o.config,e),document.body?a():setTimeout(function(){a()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],l.SHADE="layui-layer-shade",l.MOVE="layui-layer-move",s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,minStack:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
'+(f?r.title[0]:r.title)+"
":"";return r.zIndex=s,t([r.shade?'
':"",'
'+(e&&2!=r.type?"":u)+'
'+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
'+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
'+e+"
"}():"")+(r.resize?'':"")+"
"],u,i('
')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i("#"+l.MOVE)[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),e.shadeo=i("#"+l.SHADE+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),e.shadeo.css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():function(){e.offset(),parseInt(o.getStyle(document.getElementById(l.MOVE),"z-index"))||function(){e.layero.css("visibility","hidden"),r.ready(function(){e.offset(),e.layero.css("visibility","visible")})}()}(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&t.shadeo.on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n,t.index);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n,t.index)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n,t.index)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){t=t||{};var a=i("#"+l[0]+e),s=i("#"+l.SHADE+e),f=a.find(l[1]).outerHeight()||0,c=a.attr("minLeft")||181*o.minIndex+"px",u=a.css("position"),d={width:180,height:f,position:"fixed",overflow:"hidden"};o.record(a),o.minLeft[0]&&(c=o.minLeft[0],o.minLeft.shift()),t.minStack&&(d.left=c,d.top=n.height()-f,a.attr("minLeft")||o.minIndex++,a.attr("minLeft",c)),a.attr("position",u),r.style(e,d,!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),s.hide()},r.restore=function(e){var t=i("#"+l[0]+e),n=i("#"+l.SHADE+e),a=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(a[0]),height:parseFloat(a[1]),top:parseFloat(a[2]),left:parseFloat(a[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e),n.show()},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e,t){var n=i("#"+l[0]+e),a=n.attr("type"),s="layer-anim-close";if(n[0]){var f="layui-layer-wrap",c=function(){if(a===o.type[1]&&"object"===n.attr("conType")){n.children(":not(."+l[5]+")").remove();for(var r=n.find("."+f),s=0;s<2;s++)r.unwrap();r.css("display",r.data("display")).removeClass(f)}else{if(a===o.type[2])try{var c=i("#"+l[4]+e)[0];c.contentWindow.document.write(""),c.contentWindow.close(),n.find("."+l[5])[0].removeChild(c)}catch(u){}n[0].innerHTML="",n.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e],"function"==typeof t&&t()};n.data("isOutAnim")&&n.addClass("layer-anim "+s),i("#layui-layer-moves, #"+l.SHADE+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),n.attr("minLeft")&&(o.minIndex--,o.minLeft.push(n.attr("minLeft"))),r.ie&&r.ie<10||!n.data("isOutAnim")?c():setTimeout(function(){c()},200)}},r.closeAll=function(e,t){"function"==typeof e&&(t=e,e=null);var n=i("."+l[0]);i.each(n,function(a){var o=i(this),s=e?o.attr("type")===e:1;s&&r.close(o.attr("times"),a===n.length-1?t:null),s=null}),0===n.length&&"function"==typeof t&&t()};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(t){s=t.find(".layui-layer-input"),s.val(e.value||"").focus(),"function"==typeof f&&f(t)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
    '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
  • '+(t[0].content||"no content")+"
  • ";i'+(t[i].content||"no content")+"";return a}()+"
",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=!("string"==typeof t.photos||t.photos instanceof i),f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){h();var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0)}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev(!0)}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext(!0)}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),a&&(t.anim=-1),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||'+function(){return u.length>1?'
'+(u[d].alt||"")+""+s.imgIndex+" / "+u.length+"
":""}()+"",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){r.ready(),o.run(e.jQuery)}()}(window); --------------------------------------------------------------------------------