1.先看效果图,点击分享海报按钮,然后弹出分享海报
?2.前端代码
这里用的组件有vant组件库还有canvas_drawer(一个画布组件)
canvas_drawer下载地址https://github.com/kuckboy1994/mp_canvas_drawer
把 components 中的 canvasdrawer 拷贝到自己项目下,然后再app.json中引用就行了,如下
"usingComponents": {
? ? "canvasdrawer": "/static/canvasdrawer/canvasdrawer"
? }
注意!注意!注意!canvas_drawer的painting属性画布里面的图片不能用本地的,不然会显示不出来!
需要用到的数据源
data () {
return {
isschb: true,
xsxyid: 0,
painting: null,
showSharePosterPopup: false,
sharePosterImg: '',
xssptp: '', //现实的商品图片路径
nickname: ''
}
},
我这里点击的分享海报是用的一个vant组件库的图标
<view style="position: fixed;bottom: 15%;left: 86%;">
<view v-if="isschb">
<van-icon name="photo-o" size="40px" style="margin-bottom: 10px;" color="#87CEEB"
@click="generateSharePoster" />
</view>
</view>
然后弹窗也是用的vant里面的Popup弹出层
<!-- 预览海报弹窗 -->
<van-popup :show="showSharePosterPopup" :close-on-click-overlay="true" round position="bottom"
custom-style="height:80%;" @close="handleSharePosterPopupClose">
<view style="height:50px;background:#eee;">
<van-row>
<van-col span="22">
<view style="line-height:50px;" class="margin-left text-xl">保存到相册</view>
</van-col>
<van-col span="2">
<van-icon custom-class="margin-top-sm" size="25" name="cross" @click="handleSharePosterPopupClose">
</van-icon>
</van-col>
</van-row>
</view>
<img :src="sharePosterImg"
style="width:70%;height:70%;margin-left:15%;margin-top:10px;border:1px solid #ddd;" />
<view class="margin-lr margin-tb">
<van-button type="danger" block @click="savePosterImg">保存图片</van-button>
</view>
<view class="margin-bottom text-center text-gray">保存图片到手机相册后,将图片分享到您的圈子</view>
<canvasdrawer :painting="painting" @getImage="sharePosterImage" />
</van-popup>
然后是Js里面的方法
// 生成分享海报
generateSharePoster () {
let that = this
wx.downloadFile({
url: that.bzyrtx.replace('https://thirdwx.qlogo.cn', 'https://wx.qlogo.cn'),
success: (res) => {
var picurl = res.tempFilePath
wx.showLoading({
title: '海报生成中..',
mask: true
})
let url = 'api/Xys/create/xcxcode?api-version=1&xyid=' + that.xsxyid
that.$http
.get(url)
.then((res) => {
if (res) {
console.log(that.xssptp)
console.log(that.$http.config.baseURL + '/' + res.data.Result)
that.painting = {}
that.painting = {
width: 375,
height: 555,
views: [
{
type: 'image',
url: 'https://pic1.zhimg.com/v2-fd0c04a3a78a4cc98831ba147a1de101_r.jpg?source=1940ef5c',//背景图片
top: 0,
left: 0,
width: 375,
height: 555
},
{
type: 'image',
url: picurl, // 微信头像
top: 27.5,
left: 29,
width: 55,
height: 55
},
{
type: 'text',
content: '您的好友【' + that.nickname + '】',// 微信昵称
fontSize: 16,
color: '#402D16',
textAlign: 'left',
top: 33,
left: 96,
bolder: true
},
{
type: 'text',
content: '请您帮其助愿',
fontSize: 15,
color: '#563D20',
textAlign: 'left',
top: 59.5,
left: 96
},
{
type: 'image',
url: that.xssptp,// 中间显示的商品图片
top: 100,
left: 10,
width: 350,
height: 290
},
{
type: 'image',
url: that.$http.config.baseURL + '/' + res.data.Result, // 小程序码
top: 453,
left: 25,
width: 80,
height: 80
},
{
type: 'text',
content: '一份心愿,一丝情意',
fontSize: 16,
lineHeight: 21,
color: '#383549',
textAlign: 'left',
top: 406,
left: 44,
width: 287,
MaxLineNumber: 2,
breakWord: true,
bolder: true
},
{
type: 'text',
content: '小程序名称',
fontSize: 16,
color: '#000',
textAlign: 'left',
top: 470,
left: 110.5,
lineHeight: 20,
MaxLineNumber: 2,
breakWord: true,
width: 125
},
{
type: 'text',
content: '长按识别,去逛逛',
fontSize: 14,
color: '#383549',
textAlign: 'left',
top: 495,
left: 110.5,
lineHeight: 20,
MaxLineNumber: 2,
breakWord: true,
width: 125
}
]
}
that.showSharePosterPopup = true
}
})
}
})
},
// 关闭弹出层
handleSharePosterPopupClose () {
this.showSharePosterPopup = false
},
// 画布生成的图片
sharePosterImage (event) {
this.sharePosterImg = event.mp.detail.tempFilePath
wx.hideLoading()
},
// 保存图片
savePosterImg () {
let that = this
wx.saveImageToPhotosAlbum({
filePath: that.sharePosterImg,
success (res) {
wx.showToast({
title: '已保存到相册,可以去发朋友圈啦~',
icon: 'none',
duration: 2000
})
},
fail (res) {
wx.showToast({
title: '保存失败',
icon: 'none',
duration: 2000
})
}
})
}
2.后端api代码(这个是为了获取小程序码)
page是扫码进入的界面,注意小程序必须是发布了的,而且有这个界面,传的参数是扫码进入的页面要传的参数,且只能放到scene里面,了解更多请看官方文档
控制器层
/// <summary>
/// 创建小程序码
/// </summary>
/// <param name="xyid"></param>
/// <returns></returns>
[Route("api/Xys/create/xcxcode")]
[AllowAnonymous]
[HttpGet]
public Response GenerateWxxcxCode([FromUri] int xyid)
{
return xysBLL.CreateXcxCode(xyid);
}
wxAppId是小程序的appid,wxSecret是小程序的密钥,这里都要再web.config配置文件中配好
web.config文件配置
<add key="wxAppId" value="(小程序appid)" />
<add key="wxSecret" value="(小程序密钥)" />
业务逻辑层用到的类以及里面的方法
?WxHelper
public class WxHelper
{
/// <summary>
/// 获取请求凭据
/// </summary>
/// <returns></returns>
public static string GetAccessToken(string appId, string secret)
{
var token = RedisHelper.StringGet("access_token");
if (string.IsNullOrWhiteSpace(token))
{
lock (locker)
{
if (string.IsNullOrWhiteSpace(token))
{
HttpClient client = new HttpClient();
string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
url = string.Format(url, appId, secret);
var result = client.GetStringAsync(url).Result;
var rsp = JsonConvert.DeserializeObject<RspAccessToken>(result);
if (string.IsNullOrWhiteSpace(rsp.Errmsg))
{
//提前5分钟失效
DateTime expireTime = DateTime.Now.AddSeconds(rsp.Expires_in - 300);
TimeSpan expireTs = new TimeSpan(expireTime.Ticks);
TimeSpan nowTs = new TimeSpan(DateTime.Now.Ticks);
RedisHelper.StringSet("access_token", rsp.Access_token, expireTs.Subtract(nowTs));
token = rsp.Access_token;
}
else
{
throw new Exception("获取微信请求凭据失败!" + rsp.Errmsg);
}
}
}
}
return token;
}
}
?RspAccessToken
public class RspAccessToken
{
public string Access_token
{
get;
set;
}
public int Expires_in
{
get;
set;
}
public int Errcode
{
get;
set;
}
public string Errmsg
{
get;
set;
}
}
?RedisHelper
public static class RedisHelper
{
private static readonly string redisConn = ConfigurationManager.AppSettings["redis"];
private static readonly string redisHost = ConfigurationManager.AppSettings["redisHost"];
private static readonly string redisPort = ConfigurationManager.AppSettings["redisPort"];
private static readonly string redisPwd = ConfigurationManager.AppSettings["redisPwd"];
private static readonly string dbNumber = ConfigurationManager.AppSettings["redisDbNumber"];
private static readonly object locker = new object();
private static ConnectionMultiplexer connectionMultiplexer;
private static IDatabase database;
private static IDatabase GetDatabase()
{
if(database == null)
{
lock (locker)
{
if(connectionMultiplexer == null || !connectionMultiplexer.IsConnected)
{
//string connStr = "{0}:{1},allowAdmin = true,password = {2}";
//connStr = string.Format(connStr, redisHost, redisPort, redisPwd);
//connectionMultiplexer = ConnectionMultiplexer.Connect(connStr);
connectionMultiplexer = ConnectionMultiplexer.Connect(redisConn);
database = connectionMultiplexer.GetDatabase(int.Parse(dbNumber));
}
}
}
return database;
}
/// <summary>
/// 保存自增字符串
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public static long StringIncrementSet(string redisKey, long redisValue)
{
return GetDatabase().StringIncrement(redisKey, redisValue);
}
/// <summary>
/// 保存字符串
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public static bool StringSet(string redisKey, string redisValue, TimeSpan? expiry)
{
return GetDatabase().StringSet(redisKey, redisValue, expiry);
}
/// <summary>
/// 保存一个对象,该对象会被序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="exipry"></param>
/// <returns></returns>
public static bool StringSet<T>(string redisKey, T redisValue, TimeSpan? exipry)
{
string rValue = Newtonsoft.Json.JsonConvert.SerializeObject(redisValue);
return GetDatabase().StringSet(redisKey, rValue, exipry);
}
/// <summary>
/// 删除指定字符串
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public static bool KeyDelete(string redisKey)
{
return GetDatabase().KeyDelete(redisKey);
}
/// <summary>
/// 获取字符串
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public static string StringGet(string redisKey)
{
return GetDatabase().StringGet(redisKey);
}
/// <summary>
/// 获取一个对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="redisKey"></param>
/// <returns></returns>
public static T StringGet<T>(string redisKey)
{
var objct = GetDatabase().StringGet(redisKey);
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(objct);
}
}
?业务逻辑层
private static readonly string AppId = ConfigurationManager.AppSettings["wxAppId"];
private static readonly string Secret = ConfigurationManager.AppSettings["wxSecret"];
private static readonly HttpClient httpClient = new HttpClient();
private static readonly string CREATE_XCXCODE_PATH = "upload/wx/xcxcode/";
/// <summary>
/// 生成小程序码
/// </summary>
/// <returns></returns>
public Response CreateXcxCode(int xyid)
{
string token = WxHelper.GetAccessToken(AppId, Secret);
string url2 = $"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={token}";
string page = "";
page = "pages/xyjbzy/main";
var obj = new
{
page = page,
scene = xyid
};
var jsonStr = JsonConvert.SerializeObject(obj);
Logger logger = LogManager.GetCurrentClassLogger();
WebRequestHandler handler = new WebRequestHandler();
logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
logger.Info(jsonStr);
logger.Info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
HttpResponseMessage response = httpClient.PostAsJsonAsync(url2, obj).Result;
response.EnsureSuccessStatusCode();
string fileFullPath = "";
using (var stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string filePath = CREATE_XCXCODE_PATH + DateTime.Now.ToString("yyyyMMdd") + "/";
if (!Directory.Exists(basePath + filePath))
{
Directory.CreateDirectory(basePath + filePath);
}
string fileName = Guid.NewGuid().ToString("N") + ".jpeg";
fileFullPath = filePath + fileName;
using (BinaryReader binreader = new BinaryReader(stream))
{
byte[] bytes = binreader.ReadBytes(Convert.ToInt32(stream.Length));
using (var streamSub = new MemoryStream(bytes))
{
var img = Image.FromStream(stream);
img.Save(basePath + fileFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
return new Response
{
Result = fileFullPath
};
}
}
以上就是所有步骤了,可能写得不是很详细,不过我一个大老粗已经尽力了,希望对你有帮助
|