作者归档:admin

vue

https://github.com/thefunpower/vue

初始化

vue 3

$vue =  new Vue;
$vue->version = 3;

vue 2

$vue =  new Vue; 

index

<el-table-column type="index" label="序号" :index="indexMethod" width="80">
</el-table-column>

时间区间

$vue->search_date = [
  '今天',
  '昨天',
  '本周',
  '上周',
  '上上周',
  '本月',
  '上月',
  '上上月',
  '本年'=>'今年', 
  '上年'=>'去年',
  '上上年',
  '最近一个月',
  '最近两个月',

  '最近三个月',
  '第一季度', 
  '第二季度', 
  '第三季度', 
  '第四季度', 
];
//限制在这个时间之前的不无法选择
$vue->start_date = '2023-11-01';

$vue->add_date();

search_datekey=>value形式存在,key是显示的时间,value是显示的标题

<el-date-picker   v-model="where.date" value-format="yyyy-MM-dd" :picker-options="pickerOptions" size="medium" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>

data

$vue->data('text','welcome');

created

$vue->created(['load()']);
$vue->method('load()',"

");

mounted

$vue->mounted("a","
  alert(2);
")

其中akey

watch

$vue->watch("page(new_val,old_val)","
  console.log('watch');
  console.log(old_val);
  console.log(new_val);
")
$vue->watch("where.per_page","
  handler(new_val,old_val){
    console.log('watch');
    console.log(old_val);
    console.log(new_val);
  },  
"); 
$vue->watch("where","
  handler(new_val,old_val){
    console.log('watch');
    console.log(old_val.per_page);
    console.log(new_val.per_page);
  }, 
  deep: true
");

底部加入

<?php  
if($vue){
?>
<script type="text/javascript">
    <?=$vue->run();?>
</script>
<?php }?> 

wangeditor 富文本

body字段

在html中

<?=$vue->editor()?>

页面

<el-dialog  @opened="on_open_form"

vue代码

$vue->editor_method();
$vue->method("on_open_form()","
this.weditor();
");

添加时

setTimeout(function(){
  editorbody.setHtml('');
 },600); 

编辑时

setTimeout(function(){
     editorbody.setHtml(d.body);
 },600);   


wangeditor 5

有时需要替换原来的图片上传按钮,以下为演示,实际使用请根据情况处理。

$vue->data('is_open_editor',false);
$vue->editor_image_upload_click = "
    app.add_media('editorbody');
    app.is_open_editor = true;
"; 

压缩JS

安装

yarn add --dev javascript-obfuscator

配置

$config['vue_encodejs'] = true;
$config['vue_encodejs_ignore'] = ['/plugins/config/config.php'];

一般函数

每个季度开始、结束时间

vue_get_jidu_array($year)

某月的最后一天

vue_get_last_day($month = '2023-07')

业务处理

  • 管理员页面
<?php 
global $vue;  
admin_header();
$vue->upload_url = '/admin/media/upload';
?> 

<?php admin_footer();?> 

支付宝

.evn

show_alipay=1

沙盒

https://openhome.alipay.com/develop/sandbox/account

PC支付,将跳转显示支付宝二维码

/payment/alipay/do_pay?total_fee=0.01&method=pc&order_num=test1234560021&is_json=1

composer依赖

https://pay.yansongda.cn/docs/v3/wechat/pay.html

"yansongda/pay": "~3.5.0",
"hyperf/pimple": "~2.2.0" 

需要在

https://b.alipay.com

产品中心 签约对应的 电脑网站支付,开发设置中创建应用

https://openhome.alipay.com

网页/移动应用

微信支付

https://pay.weixin.qq.com/

查看证书序列号,cert.pem 对应证书CERT

注意:查看序列号是cert.pem,生成平台证书是app.pem(对应证书KEY)

openssl x509 -in cert.pem -noout -serial

生成平台

下载 CertificateDownloader.jar

https://github.com/wechatpay-apiv3/CertificateDownloader/releases

输出平台证书

java -jar CertificateDownloader.jar -k ${apiV3key} -m ${mchId} -f ${mchPrivateKeyFilePath} -s ${mchSerialNo} -o ${outputFilePath}

必需参数有:

  • -f <privateKeyFilePath>,商户API私钥文件路径 对应是的 证书KEY,也就是app.key
  • -k <apiV3Key>,证书解密的密钥
  • -m <merchantId>,商户号
  • -o <outputFilePath>,保存证书的路径
  • -s <merchantSerialNo>,商户API证书的序列号

系统使用

native 是生成二维码用户使用微信扫一扫

此模式需要在 https://pay.weixin.qq.com/ 产品中心开通 Native支付

此处显示未开通时,需要点击开通,按步骤开通就可以了。开通成功后显示

此时再看产品中心 Native支付显示如下

测试如:

/payment/weixin/do_pay?total_fee=0.01&method=native&order_num=test123456&is_json=1

is_json有值时返回json数组,无值返回二维码图片

小程序使用的是 jsapi 对应产品中心是 JSAPI支付

request curl

依赖 Guzzle 7.x

GET

$client = guzzle_http();
$res    = $client->request('GET', $url);
return (string)$res->getBody();  

POST

$res = $client->request('POST', $url,['body'=>$body]);
return (string)$res->getBody();  

POST JSON

$res = $client->request('POST', '/json.php', [
    'json' => ['foo' => 'bar']
]);

发送application/x-www-form-urlencoded POST请求需要你传入form_params

$res = $client->request('POST', $url, [
	'form_params' => [
	    'field_name' => 'abc',
	    'other_field' => '123',
	    'nested_field' => [
	        'nested' => 'hello'
	    ]
	]
]);

PUT

$body = file_get_contents($local_file);  
$request = new \GuzzleHttp\Psr7\Request('PUT', $upload_url, $headers=[], $body);
$response = $client->send($request, ['timeout' => 30]);
if($response->getStatusCode() == 200){
    return true;
} 

随机IP

$opt = guzzle_http_fake_option();
$opt['referer'] = '';
$opt['form_params'] = [
   'kw'  => $kw,
   'page'=> $page,
];
guzzle_http()->request('POST', $url, $opt);
$res = (string)$res->getBody();

command color

命令行颜色

代码

<?php
declare (strict_types = 1);

namespace app\admin\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\output\formatter\Style;
use think\console\Output;

class Hello extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('hello')
            ->setDescription('php think hello --ansi 演示命令行颜色');
    }

    protected function execute(Input $input, Output $output)
    {   
        $output->info("info");
        $output->error("error");
        $output->warning("warning");
        $output->highlight("highlight"); 
        $output->question("question"); 
        /*$question = $output->confirm($input, 'Continue with this action?', false); 
        if (!$question) {
            return;
        }*/

    }
}

添加至php think

add_action("console",function(&$console){
    if(!is_cli()){return;}
    // php think hello
    $console['hello'] = "app\admin\command\Hello"; 
});  

运行

php think hello --ansi

效果

uni滚动加载 mescroll-body

<template>
	<view>
		<mescroll-body top="0" :up="upOption" :down="downOption" @init="mescrollInit" @down="downCallback"
			@up="upCallback"> 
			<view class="" style="font-size: 28rpx;"> 
				  <view class="card t-center" v-for="v in list" @click="nav('/active_bm/index/detail?id='+v.id)"> 
						<image mode="aspectFit" :src="v.image_http" style="width: 100%;"></image>
						<view>{{v.title}}</view>
				  </view>
			</view>
		</mescroll-body> 

		<cl-toast ref="toast"></cl-toast>
		<cl-message ref="message"></cl-message>
		<t-login-phone @logined="logined" :visible='show_login_phone'></t-login-phone>
	</view>
</template>

<script>
	var _this
	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
	export default {
		mixins: [MescrollMixin], // 使用mixin 
		data() {
			return { 
				where: {
					page: 1,
					per_page: 10
				},
				upOption: {
					page: {
						size: 10 // 每页数据的数量,默认10
					},
					noMoreSize: 5, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
					empty: {
						tip: '暂无相关数据'
					},
					textNoMore: '-- 到底了 --'
				},
				downOption: {
					auto: false, //是否在初始化后,自动执行downCallback; 默认true 
				},
				list: [],
				is_load: false,
				vip_card: {},
				row: {},
				visible: false,
			}
		},
		onLoad() {
			_this = this
		},
		onShow() { 
		},
		methods: {
			view_detail(v) {
				this.nav('/active_bm/index/detail?id='+v.id)
			}, 
			swiper_change() {
				let index = this.active_swiper
				this.yue = this.vip_card[index].amount
			},
			logined() {
				this.reload()
			},

			/*下拉刷新的回调 */
			downCallback() {
				this.where.page = 1
				this.load() 
				this.mescroll.resetUpScroll();
			},
			upCallback(page) {
				this.where.page = page.num
				this.load()
			},
			reload() {
				this.where.page = 1
				this.load() 
			},
			load() { 
				_this.ajax(_this.config.active_bm.index, _this.where).then(res => {
					_this.is_load = true
					if(res.code != 0){
						_this.mescroll.endBySize(0, 0);
						return;
					} 
					if (res.current_page == 1) {
						_this.list = []
					}
					for (let i in res.data) {
						_this.list.push(res.data[i])
					}
					_this.mescroll.endBySize(res.total_cur, res.total);
				})
			}
		}
	};
</script>

<style lang="scss">
	.fuwu {

		.space-between {
			margin-bottom: 10rpx;
		}
	}

	page {
		background-color: #F5F7FA;
	}

	.page-community {
		/deep/.cl-tabs__bar-item {
			color: #848484;
		}

		.tabBar {
			/deep/.cl-tabs__bar {
				background-color: rgba(0, 0, 0, 0) !important;

				.cl-tabs__bar-item.is-active {
					font-size: 34rpx;
				}

				.cl-tabs__line {
					height: 6rpx;
					border-radius: 4rpx;
				}
			}
		}

		.list {
			.item {
				/deep/.cl-button.cl-button--primary {
					background-color: #F5F7FA;
					width: 136rpx;
					height: 58rpx;

					.cl-button__text {
						color: #28B5B5;
					}
				}
			}
		}
	}
</style>

用户后台

目录

app/a_user_admin 

后台地址

/a_user_admin/login

添加菜单

add_user_access('书籍.novel_book',[
    'url'=>'novel/book/index'
],1);

用户首页

add_action("user.index",function(){
    echo 1;
});

检测用户是否可以访问用户后台

do_action("user.check",$user);

登录前

do_action("user.login",$user);

发验证码前

do_action("user.phone_code",$user);

页面

<?php global $vue;user_header(); ?>

<div id="" style="padding-top:20px;">
  
</div>

<?php user_footer();?>

SSL泛解析证书

使用

首次生成证书

php think  webtool:ssl yourdomain.com issue_ca_ssl

续签证书

php think  webtool:ssl yourdomain.com renew_ca_ssl

同步证书至宝塔

php think  webtool:ssl_to_bt 0

配置.env

bt_url = http://IP:8098/
bt_key = 

依赖ZeroSSL

安装

wget -O -  https://get.acme.sh | sh -s email=yourmailaddress
或使用国内
curl https://gitcode.net/cert/cn-acme.sh/-/raw/master/install.sh?inline=false | sh -s email=yourmailaddress 

其中yourmailaddress是邮件地址

ln -s ~/.acme.sh/acme.sh

选择CA服务器

推荐zerossl

~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
~/.acme.sh/acme.sh --set-default-ca --server buypass
~/.acme.sh/acme.sh --set-default-ca --server zerossl

  • letsencrypt https://acme-v02.api.letsencrypt.org/directory
  • letsencrypt_test https://acme-staging-v02.api.letsencrypt.org/directory
  • buypass https://api.buypass.com/acme/directory
  • buypass_test https://api.test4.buypass.no/acme/directory
  • zerossl https://acme.zerossl.com/v2/DV90
  • sslcom https://acme.ssl.com/sslcom-dv-rsa, https://acme.ssl.com/sslcom-dv-ecc
  • google https://dv.acme-v02.api.pki.goog/directory
  • googletest https://dv.acme-v02.test-api.pki.goog/directory