1256 lines
44 KiB
JavaScript
1256 lines
44 KiB
JavaScript
var initial_url = "https://app.gter.net/tenement";
|
||
var app = null;
|
||
|
||
function initial(self) {
|
||
const fs = wx.getFileSystemManager();
|
||
console.log("getCurrentDate", getCurrentDate());
|
||
fs.mkdir({
|
||
dirPath: `${wx.env.USER_DATA_PATH}/${getCurrentDate()}`,
|
||
// dirPath: `${wx.env.USER_DATA_PATH}/2025-04-13`,
|
||
success(res) {
|
||
console.log("res", res);
|
||
},
|
||
fail(err) {
|
||
console.log("err", err);
|
||
},
|
||
});
|
||
fs.close();
|
||
|
||
app = self;
|
||
getUserInfo(function (code) {
|
||
sendData(code);
|
||
self.globalData.code = code;
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
function sendData(code) {
|
||
let Authorization = wx.getStorageSync("Authorization");
|
||
if (!Authorization) {
|
||
Authorization = app.randomString(32);
|
||
wx.setStorageSync("Authorization", Authorization);
|
||
wx.setStorageSync("session", Authorization);
|
||
}
|
||
wx.request({
|
||
url: initial_url,
|
||
data: {
|
||
session: wx.getStorageSync("Authorization") || "",
|
||
Authorization: wx.getStorageSync("Authorization") || "",
|
||
code: code,
|
||
options: app.globalData.options || "",
|
||
},
|
||
method: "POST", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
|
||
header: {
|
||
"content-type": "application/json",
|
||
Accept: "application/json, text/plain",
|
||
Cookie: "miucms_session=" + wx.getStorageSync("Authorization"),
|
||
Authorization: wx.getStorageSync("Authorization") || "",
|
||
},
|
||
success: function (res) {
|
||
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
|
||
bindingUser(data.user || {});
|
||
|
||
// 将配置与用户session存于本地
|
||
// if (!data.session) {
|
||
// // 这里报错.用户授权不成功
|
||
// return false;
|
||
// }
|
||
// wx.setStorageSync('session', data.user.session)
|
||
app.globalData.session = data.user.session;
|
||
// wx.setStorageSync('Authorization', data.user.session)
|
||
app.globalData.Authorization = data.user.session;
|
||
app.globalData.isUserAuthorization = data.user.session && data.user.session.length > 0 ? 2 : 1;
|
||
app.globalData.expiration_day = data.expiration_day;
|
||
app.globalData.config = data.config;
|
||
app.globalData.notice = data.notice;
|
||
app.globalData.title = data.title;
|
||
app.globalData.initialState = true;
|
||
app.globalData.user = data.user;
|
||
app.globalData.status = data.status;
|
||
app.globalData.StudentapartmentNew = data.StudentapartmentNew;
|
||
app.globalData.listTab = data.listTab;
|
||
app.globalData.wechat = data.wechat;
|
||
app.globalData.isMapFindState = data.isMapFindState;
|
||
app.globalData.isShowVideo = data.reviewmode == 1 ? false : true;
|
||
// app.globalData.isShowVideo = false
|
||
// console.log(data.popwindow);
|
||
app.globalData.popwindow = data.popwindow;
|
||
|
||
app.globalData.header = {
|
||
"content-type": "application/json",
|
||
Accept: "application/json, text/plain",
|
||
Cookie: "miucms_session=" + wx.getStorageSync("Authorization"),
|
||
Authorization: wx.getStorageSync("Authorization") || "",
|
||
};
|
||
|
||
// count()
|
||
|
||
app.globalData.offerkaipingadvertisement = data.popup || {};
|
||
const openAdTimer = wx.getStorageSync("openAdTimer");
|
||
if (openAdTimer && isToday(openAdTimer)) app.globalData.offerkaipingadvertisementState = true;
|
||
},
|
||
fail: function () {
|
||
// fail
|
||
},
|
||
complete: function () {
|
||
// complete
|
||
useSocket();
|
||
},
|
||
});
|
||
}
|
||
|
||
function isToday(timestamp) {
|
||
const date = new Date(timestamp);
|
||
const today = new Date();
|
||
|
||
return date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth() && date.getDate() === today.getDate();
|
||
}
|
||
|
||
// 发送未读消息数请求
|
||
function count() {
|
||
return new Promise((resolve, reject) => {
|
||
request(app.globalData.baseURL + "/tenement/message/count")
|
||
.then((res) => {
|
||
if (res.code == 200) {
|
||
app.globalData["unreadMessages"] = res.data.count;
|
||
app.globalData["unreadMessagesState"] = true;
|
||
} else {
|
||
wx.showModal({
|
||
title: "提示",
|
||
content: res.message,
|
||
});
|
||
}
|
||
resolve(res);
|
||
})
|
||
.catch((error) => {
|
||
reject(error);
|
||
});
|
||
});
|
||
}
|
||
|
||
// 发送验证码
|
||
function verify() {
|
||
// 得到 uniqid 和过期时间
|
||
}
|
||
|
||
// 验证验证码并注册
|
||
function register(o) {
|
||
var config = wx.getStorageSync("config");
|
||
var self = this;
|
||
wx.request({
|
||
url: config.user.register,
|
||
data: {
|
||
session: wx.getStorageSync("session"),
|
||
data: wx.getStorageSync("rawData"),
|
||
uniqid: null, //上一步获取的ID
|
||
code: null, //接收到的验证码
|
||
},
|
||
method: "POST", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
|
||
header: {
|
||
"content-type": "application/json",
|
||
Accept: "application/json, text/plain",
|
||
},
|
||
success: function (res) {
|
||
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
|
||
console.log("登录/注册成功");
|
||
initial(initial_url, app);
|
||
},
|
||
fail: function () {
|
||
// fail
|
||
},
|
||
complete: function () {
|
||
// complete
|
||
},
|
||
});
|
||
}
|
||
|
||
//用户登录
|
||
function login() {
|
||
return new Promise((resolve, reject) =>
|
||
wx.login({
|
||
success: resolve,
|
||
fail: reject,
|
||
})
|
||
);
|
||
}
|
||
|
||
//获取用户信息
|
||
function getUserInfo(o) {
|
||
login()
|
||
.then((res) => {
|
||
var code = res.code;
|
||
o(code);
|
||
})
|
||
.catch((res) => {
|
||
console.log(res);
|
||
});
|
||
}
|
||
|
||
function share(app, name) {
|
||
if (!app.globalData.config.stat || !app.globalData.config.stat.share) {
|
||
return false;
|
||
}
|
||
wx.request({
|
||
url: app.globalData.config.stat.share,
|
||
data: {
|
||
page: name,
|
||
},
|
||
method: "POST", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
|
||
header: app.globalData.header,
|
||
success: function (res) {},
|
||
fail: function (res) {},
|
||
});
|
||
}
|
||
|
||
function html2wxml(str, index, that) {
|
||
var arr = [];
|
||
if (str.indexOf("</a>") != -1) {
|
||
// 有a标签
|
||
that.data.newFunction.text[index].push({
|
||
text: str.substring(0, str.indexOf("<a")),
|
||
node: "text",
|
||
});
|
||
var rest = str.substring(str.indexOf("<a"));
|
||
// a标签后面剩下的字符串
|
||
// 第一个出现href的位置
|
||
var href1 = rest.indexOf('href="') + 6;
|
||
// 第二个“出现的位置
|
||
var href2 = rest.substring(href1).indexOf('"');
|
||
// 链接地址
|
||
var href = rest.substring(href1, href1 + href2);
|
||
rest = rest.substring(rest.indexOf(">"));
|
||
var text1 = rest.substring(1, rest.indexOf("</a>"));
|
||
that.data.newFunction.text[index].push({
|
||
text: text1,
|
||
node: "a",
|
||
href: href,
|
||
});
|
||
rest = rest.substring(rest.indexOf("</a>") + 4);
|
||
if (rest.length > 0) {
|
||
// a标签后还有字符串
|
||
if (rest.indexOf("</a>") != -1) {
|
||
// 还有A标签存在,再一次调用
|
||
that.html2wxml(rest, index);
|
||
} else {
|
||
that.data.newFunction.text[index].push({
|
||
text: rest,
|
||
node: "text",
|
||
});
|
||
}
|
||
}
|
||
} else {
|
||
that.data.newFunction.text[index] = [{
|
||
text: str,
|
||
node: "text",
|
||
}, ];
|
||
}
|
||
}
|
||
|
||
function change_data(that, newFunction) {
|
||
var arr = newFunction.split("\n");
|
||
var arr2 = [];
|
||
for (var i = 0; i < arr.length; i++) {
|
||
var str = arr[i];
|
||
that.data.newFunction.text[i] = [];
|
||
that.html2wxml(str, i);
|
||
}
|
||
that.setData({
|
||
newFunction: that.data.newFunction,
|
||
});
|
||
}
|
||
|
||
function copy(content, hintText) {
|
||
return new Promise((resolve, reject) => {
|
||
wx.setClipboardData({
|
||
data: content,
|
||
success: function (res) {
|
||
wx.showToast({
|
||
icon: "none",
|
||
title: hintText || "复制成功!",
|
||
});
|
||
resolve();
|
||
},
|
||
fail(err) {
|
||
reject(err);
|
||
},
|
||
});
|
||
});
|
||
}
|
||
|
||
//封装Request请求方法
|
||
function request(url, data = {}, ishint = true) {
|
||
return new Promise((resolve, reject) => {
|
||
// if (!app.globalData.config || !app.globalData.config.list) {
|
||
// reject()
|
||
// return false
|
||
// }
|
||
let Authorization = wx.getStorageSync("Authorization");
|
||
if (!Authorization) {
|
||
Authorization = app.randomString(32);
|
||
wx.setStorageSync("Authorization", Authorization);
|
||
wx.setStorageSync("session", Authorization);
|
||
}
|
||
|
||
let sendData = Object.assign({
|
||
session: wx.getStorageSync("session"),
|
||
},
|
||
app.globalData.options,
|
||
data
|
||
);
|
||
wx.request({
|
||
url: url,
|
||
data: sendData,
|
||
timeout: data.timeout || 60000,
|
||
header: {
|
||
"content-type": "application/json",
|
||
Accept: "application/json, text/plain",
|
||
Cookie: "miucms_session=" + Authorization,
|
||
Authorization: Authorization || "",
|
||
},
|
||
method: "POST", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
|
||
success: function (res) {
|
||
var json = res.data;
|
||
if (typeof json != "object") {
|
||
if (json != null) {
|
||
json = json.replace("\ufeff", "");
|
||
try {
|
||
var jj = JSON.parse(json);
|
||
res.data = jj;
|
||
} catch (error) {
|
||
if (ishint) {
|
||
wx.showModal({
|
||
title: "提示",
|
||
content: "请求失败",
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var data = res.data;
|
||
resolve(data);
|
||
},
|
||
fail: function (msg) {
|
||
wx.hideLoading();
|
||
if (ishint) {
|
||
wx.showToast({
|
||
title: msg,
|
||
icon: "none",
|
||
duration: 2000,
|
||
mask: true,
|
||
});
|
||
}
|
||
reject("fail");
|
||
},
|
||
});
|
||
});
|
||
}
|
||
|
||
const wxget = function (url, data = {}) {
|
||
data = Object.assign({}, app.globalData.options, data);
|
||
return new Promise((resolve, reject) => {
|
||
var authorization = wx.getStorageSync("Authorization");
|
||
if (!authorization) {
|
||
authorization = app.randomString(32);
|
||
wx.setStorageSync("Authorization", authorization);
|
||
wx.setStorageSync("session", authorization);
|
||
}
|
||
|
||
wx.request({
|
||
url: url,
|
||
data: data,
|
||
header: {
|
||
Cookie: "miucms_session=" + authorization,
|
||
Authorization: authorization,
|
||
},
|
||
method: "GET",
|
||
success: (res) => {
|
||
if (res.data.code == 200) {
|
||
resolve(res.data);
|
||
} else if (res.data.code == 401) {
|
||
// 需要授权
|
||
app.globalData.user.uid = 0;
|
||
wx.showToast({
|
||
icon: "none",
|
||
title: res.data.message,
|
||
});
|
||
reject(res);
|
||
} else {
|
||
wx.hideLoading();
|
||
wx.showModal({
|
||
title: "提示",
|
||
content: res.message || res.data.message,
|
||
});
|
||
reject(res.data);
|
||
}
|
||
},
|
||
fail(res) {
|
||
wx.showModal({
|
||
title: "提示",
|
||
content: res,
|
||
});
|
||
reject(res);
|
||
},
|
||
});
|
||
});
|
||
};
|
||
|
||
function closeAD(id) {
|
||
if (!app.globalData.config || !app.globalData.config.adv) return false;
|
||
request(app.globalData.config.adv.close, {
|
||
advid: id,
|
||
}).then((res) => {});
|
||
}
|
||
|
||
function clickAD(id) {
|
||
if (!app.globalData.config || !app.globalData.config.adv) {
|
||
return false;
|
||
}
|
||
request(app.globalData.config.adv.click, {
|
||
advid: id,
|
||
}).then((res) => {});
|
||
}
|
||
|
||
function getTopTitle(that, app) {
|
||
let topTitle = app.globalData.topTitle;
|
||
if (topTitle) {
|
||
that.setData({
|
||
topTitle: app.globalData.topTitle,
|
||
miniProgram: app.globalData.miniProgram,
|
||
});
|
||
} else {
|
||
setTimeout(() => {
|
||
that.getTopTitle();
|
||
}, 300);
|
||
}
|
||
}
|
||
|
||
function getTimeAgo(Time) {
|
||
const now = new Date();
|
||
let time = new Date(Time);
|
||
const diff = now - time;
|
||
const seconds = Math.floor(diff / 1000);
|
||
const minutes = Math.floor(seconds / 60);
|
||
const hours = Math.floor(minutes / 60);
|
||
const days = Math.floor(hours / 24);
|
||
if (seconds < 60) return `${seconds}秒前`;
|
||
else if (minutes < 60) return `${minutes}分钟前`;
|
||
else if (hours < 24) return `${hours}小时前`;
|
||
else if (days < 7) return `${days}天前`;
|
||
else return Time;
|
||
}
|
||
|
||
// 开启socket
|
||
let socketCount = 0; // 链接次数,判断失败
|
||
const useSocket = () => {
|
||
if (app.globalData.isConnected) {
|
||
console.log("已经连接,不再重复连接");
|
||
return; // 如果已经连接,则不再创建新的 socketTask
|
||
}
|
||
app.globalData.socketTask = wx.connectSocket({
|
||
url: `wss://socket.gter.net/socket?token=${wx.getStorageSync("Authorization") || ""}`,
|
||
success: function (res) {
|
||
app.globalData.isConnected = true; // 连接成功,设置为 true
|
||
},
|
||
fail: function (err) {
|
||
app.globalData.isConnected = false; // 连接成功,设置为 true
|
||
console.log(err, "err");
|
||
},
|
||
});
|
||
app.globalData.socketTask.onOpen(function () {
|
||
// 初始化发消息
|
||
if (wx.getStorageSync("Authorization")) {
|
||
let getAccountInfoSync = wx.getAccountInfoSync();
|
||
|
||
let dataToSend = {
|
||
type: "bind",
|
||
data: {
|
||
token: wx.getStorageSync("Authorization") || "",
|
||
app: getAccountInfoSync.miniProgram.appId,
|
||
// uid: user.uid || 0
|
||
},
|
||
};
|
||
app.globalData.socketTask.send({
|
||
data: JSON.stringify(dataToSend),
|
||
});
|
||
}
|
||
// 开始定时发
|
||
setTimeout(() => timedTransmission(), 50000);
|
||
});
|
||
|
||
app.globalData.socketTask.onClose(function () {
|
||
// console.log('socket关闭了', new Date())
|
||
socketCount++;
|
||
if (socketCount > 3) return;
|
||
setTimeout(() => useSocket(), 3000);
|
||
app.globalData.isConnected = false; // 连接关闭,重置为 false
|
||
});
|
||
};
|
||
|
||
// 定时发送
|
||
const timedTransmission = () => {
|
||
if (app.globalData.socketTask.readyState != 1) return;
|
||
var dataToSend = {
|
||
type: "ping",
|
||
};
|
||
app.globalData.socketTask.send({
|
||
data: JSON.stringify(dataToSend),
|
||
complete: () => setTimeout(() => timedTransmission(), 50000),
|
||
});
|
||
};
|
||
|
||
// 专门在初始化 获取筛选全局的值和传入的值
|
||
const updateProperty = (key, options, brandSelectionObj) => {
|
||
if (options[key] != undefined) return options[key];
|
||
else if (brandSelectionObj[key] != undefined) return brandSelectionObj[key];
|
||
};
|
||
|
||
// 字符串转base64
|
||
function base64_encode(str) {
|
||
var c1, c2, c3;
|
||
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||
var i = 0,
|
||
len = str.length,
|
||
string = "";
|
||
|
||
while (i < len) {
|
||
c1 = str.charCodeAt(i++) & 0xff;
|
||
if (i == len) {
|
||
string += base64EncodeChars.charAt(c1 >> 2);
|
||
string += base64EncodeChars.charAt((c1 & 0x3) << 4);
|
||
string += "==";
|
||
break;
|
||
}
|
||
c2 = str.charCodeAt(i++);
|
||
if (i == len) {
|
||
string += base64EncodeChars.charAt(c1 >> 2);
|
||
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
|
||
string += base64EncodeChars.charAt((c2 & 0xf) << 2);
|
||
string += "=";
|
||
break;
|
||
}
|
||
c3 = str.charCodeAt(i++);
|
||
string += base64EncodeChars.charAt(c1 >> 2);
|
||
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
|
||
string += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
|
||
string += base64EncodeChars.charAt(c3 & 0x3f);
|
||
}
|
||
return string;
|
||
}
|
||
|
||
// 公共跳转页面
|
||
function goPage(url) {
|
||
wx.navigateTo({
|
||
url,
|
||
fail: function (err) {
|
||
if ((err.errMsg = "navigateTo:fail webview count limit exceed")) {
|
||
wx.redirectTo({
|
||
url,
|
||
});
|
||
}
|
||
},
|
||
});
|
||
}
|
||
|
||
function getTitleName(url) {
|
||
const obj = {
|
||
"pages/index/index": "首页",
|
||
"pages/appeal/appeal": "申诉",
|
||
"pages/needHousing/needHousing": "求房源",
|
||
"pages/personList/personList": "个人房源列表",
|
||
"pages/agentList/agentList": "中介房源列表",
|
||
"pages/brandApartmentList/brandApartmentList": "公寓房源列表",
|
||
"pages/report/report": "举报",
|
||
"pages/irentPark/irentPark": "学生公寓",
|
||
"pages/user/user": "我的",
|
||
"pages/search/search": "搜索",
|
||
"pages/edit/edit": "发布",
|
||
"pages/ad/ad": "广告模板展示",
|
||
"pages/brandApartmentDetail/brandApartmentDetail": "公寓详情",
|
||
"pages/show/show": "房源详情",
|
||
"pages/share/share": "分享海报",
|
||
"pages/messageCenter/messageCenter": "系统通知",
|
||
"pages/webViewwebweb/index": "H5",
|
||
"pages/circularize/circularize": "申诉",
|
||
"pages/askHousing/askHousing": "发布求房源",
|
||
"pages/transfer/transfer": "中转页面",
|
||
"pages/video_show/video_show": "媒体展示页面",
|
||
"pagesLoginRequired/pages/setAvatarNickname/setAvatarNickname": "设置头像昵称",
|
||
"mapFind/pages/placeMap/index": "地图找房",
|
||
};
|
||
|
||
return obj[url] || "首页";
|
||
}
|
||
|
||
// 调用 统计接口
|
||
function statistics(obj) {
|
||
return;
|
||
|
||
let url = "";
|
||
let options = {};
|
||
let pages = null;
|
||
if (obj.path) {
|
||
url = obj.path;
|
||
options = obj.query || {};
|
||
} else {
|
||
pages = getCurrentPages(); // 获取当前页面栈
|
||
const currentPage = pages[pages.length - 1]; // 当前页面对象
|
||
url = currentPage.route;
|
||
options = currentPage.options;
|
||
}
|
||
|
||
// // 当页面显示时执行
|
||
// const pages = getCurrentPages(); // 获取当前页面栈
|
||
// const currentPage = pages[pages.length - 1]; // 当前页面对象
|
||
// const url = currentPage.route; // 当前页面url
|
||
// const options = currentPage.options; // 当前页面url的参数
|
||
|
||
const launchOptions = wx.getLaunchOptionsSync() || {};
|
||
|
||
// 构建带参数的URL
|
||
let urlWithArgs = url + objectToQueryString(options);
|
||
|
||
// 缓存 systemInfo
|
||
let systemInfo = wx.getStorageSync("xstatSystemInfo");
|
||
if (!systemInfo) {
|
||
const accountInfo = wx.getAccountInfoSync();
|
||
const deviceInfo = wx.getDeviceInfo();
|
||
const windowInfo = wx.getWindowInfo();
|
||
const base = wx.getAppBaseInfo();
|
||
systemInfo = {
|
||
website: accountInfo.miniProgram.appId,
|
||
hostname: accountInfo.miniProgram.appId,
|
||
screen: `${windowInfo.windowWidth}x${windowInfo.windowHeight}`,
|
||
language: base.language || "",
|
||
os: deviceInfo.system || "",
|
||
platform: deviceInfo.platform || "",
|
||
device: deviceInfo.model || "",
|
||
session: wx.getStorageSync("xstatSession") || "",
|
||
scene: launchOptions.scene || "",
|
||
};
|
||
wx.setStorageSync("xstatSystemInfo", systemInfo);
|
||
}
|
||
|
||
let payload = {
|
||
title: getTitleName(url),
|
||
url: "/" + urlWithArgs,
|
||
};
|
||
|
||
if (Object.keys(launchOptions.referrerInfo).length > 0) payload.referrer = launchOptions.referrerInfo.appId + objectToQueryString(launchOptions.referrerInfo.extraData);
|
||
|
||
if (obj.name) payload.name = obj.name;
|
||
|
||
if (obj.data && Object.keys(obj.data).length > 0) payload.data = obj.data;
|
||
|
||
try {
|
||
wx.request({
|
||
url: "https://stat.gter.net/api/send",
|
||
method: "POST",
|
||
data: {
|
||
payload,
|
||
type: obj.type || "event",
|
||
},
|
||
timeout: 5000,
|
||
header: {
|
||
"Content-Type": "application/json",
|
||
"x-stat-token": base64_encode(JSON.stringify(systemInfo)),
|
||
},
|
||
success: (res) => {
|
||
if (res.data.code == 200 && res.data.data && res.data.data.session && res.data.data.session != systemInfo.session) {
|
||
wx.setStorageSync("xstatSession", res.data.data.session);
|
||
wx.setStorageSync("xstatSystemInfo", {
|
||
...systemInfo,
|
||
session: res.data.data.session,
|
||
});
|
||
}
|
||
},
|
||
});
|
||
} catch (error) {
|
||
console.error("发送失败:", error);
|
||
}
|
||
}
|
||
|
||
// 判断是否登录 如果登录需要发送 绑定微信信息埋点
|
||
function bindingUser(user = {}) {
|
||
if (user.uid <= 0) return;
|
||
wx.xstat && wx.xstat.setUserid(user.uid); // 登录后手动设置用户id , 如果有
|
||
// setTimeout(() => {
|
||
// statistics({
|
||
// data: {
|
||
// uid: user.uid,
|
||
// uin: user.uin
|
||
// },
|
||
// type: "identify",
|
||
// });
|
||
// }, 600);
|
||
}
|
||
|
||
// 将一个JavaScript对象转换为路由参数的形式将键值对转换为key=value的形式
|
||
function objectToQueryString(obj = {}) {
|
||
const queryString = Object.keys(obj)
|
||
.map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]))
|
||
.join("&");
|
||
return queryString ? "?" + queryString : "";
|
||
}
|
||
|
||
// 返回上一页或者首页
|
||
function backOrIndex() {
|
||
wx.navigateBack({
|
||
fail: function () {
|
||
wx.redirectTo({
|
||
url: "/pages/index/index",
|
||
});
|
||
},
|
||
});
|
||
}
|
||
|
||
// 生成海报 type 1: 公寓 2:认证中介 3: 普通中介 4:个人房东 5:认证个人房源 6:招室友 7:其他
|
||
function generatePoster(target) {
|
||
return new Promise(async (resolve, reject) => {
|
||
const user = getApp().globalData.user || {};
|
||
// 修改画布创建方式
|
||
const canvas = wx.createOffscreenCanvas({
|
||
type: "2d",
|
||
width: 280 * 2, // 增加分辨率
|
||
height: 224 * 2, // 增加分辨率
|
||
});
|
||
// target.bj = "https://oss.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-p4scXnqqsgFptxhT66QUmybYLYnAVBJQe2HpJNYt7VMACPX-Rzv5EQpu30SjsUfxT00NDI5";
|
||
const ctx = canvas.getContext("2d");
|
||
ctx.scale(2, 2); // 缩放绘图上下文
|
||
const tempFilePath = await downloadPic(target.bj);
|
||
let bgImg = canvas.createImage();
|
||
bgImg.src = tempFilePath;
|
||
await new Promise((resolve) => {
|
||
bgImg.onload = resolve;
|
||
});
|
||
console.log("加载背景图片");
|
||
|
||
// 计算aspectFill模式参数
|
||
const containerRatio = 280 / 219; // 容器宽高比 (280x219)
|
||
const imageRatio = bgImg.width / bgImg.height;
|
||
let drawWidth,
|
||
drawHeight,
|
||
offsetX = 0,
|
||
offsetY = 0;
|
||
|
||
if (imageRatio > containerRatio) {
|
||
// 图片更宽,按高度缩放
|
||
drawHeight = 219;
|
||
drawWidth = drawHeight * imageRatio;
|
||
offsetX = (280 - drawWidth) / 2;
|
||
} else {
|
||
// 图片更高,按宽度缩放
|
||
drawWidth = 280;
|
||
drawHeight = drawWidth / imageRatio;
|
||
offsetY = (219 - drawHeight) / 2;
|
||
}
|
||
|
||
// 绘制圆角背景(修改drawImage参数)
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
ctx.moveTo(15, 4);
|
||
ctx.arcTo(280, 4, 280, 224, 15);
|
||
ctx.arcTo(280, 224, 0, 224, 15);
|
||
ctx.arcTo(0, 224, 0, 4, 15);
|
||
ctx.arcTo(0, 4, 280, 4, 15);
|
||
ctx.closePath();
|
||
ctx.clip();
|
||
// 计算源图片裁剪区域
|
||
let srcX = 0,
|
||
srcY = 0,
|
||
srcWidth = bgImg.width,
|
||
srcHeight = bgImg.height;
|
||
|
||
// 修正缩放逻辑
|
||
if (imageRatio > containerRatio) {
|
||
// 图片更宽时,按容器高度缩放
|
||
drawHeight = 219;
|
||
drawWidth = drawHeight * imageRatio;
|
||
offsetX = (280 - drawWidth) / 2;
|
||
|
||
// 源图片裁剪:取中间宽度区域
|
||
srcWidth = bgImg.height * containerRatio;
|
||
srcX = (bgImg.width - drawHeight) / 2;
|
||
} else {
|
||
// 图片更高时,按容器宽度缩放
|
||
drawWidth = 280;
|
||
drawHeight = drawWidth / imageRatio;
|
||
offsetY = (219 - drawHeight) / 2;
|
||
|
||
// 源图片裁剪:取中间高度区域
|
||
srcHeight = bgImg.width / containerRatio;
|
||
srcY = (bgImg.height - drawWidth) / 2;
|
||
}
|
||
|
||
console.log("srcWidth", srcWidth, "srcHeight", srcHeight, "bgImg.width", bgImg.width, "drawWidth", drawWidth, "drawHeight", drawHeight, "srcX", srcX, "srcY", srcY);
|
||
|
||
// 修改后的drawImage调用
|
||
ctx.drawImage(
|
||
bgImg,
|
||
// srcX,
|
||
// 源图像裁剪区域
|
||
imageRatio > containerRatio ? (bgImg.width - srcWidth) / 2 : srcX, // 修正水平居中计算
|
||
srcY,
|
||
srcWidth, // 改为计算后的裁剪宽度
|
||
srcHeight, // 改为计算后的裁剪高度
|
||
offsetX,
|
||
4,
|
||
drawWidth,
|
||
drawHeight
|
||
);
|
||
ctx.restore();
|
||
console.log("绘制背景图片");
|
||
|
||
// 绘制右上角标签
|
||
if (target.type == 1) {
|
||
let tagImg = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
tagImg.onload = resolve;
|
||
tagImg.src = `https://app.gter.net/image/miniApp/HKRenting/high-quality-tag.png?${Date.now()}`;
|
||
});
|
||
ctx.drawImage(tagImg, 215, 0, 65, 54);
|
||
} else if (target.type == 2 || target.type == 5) {
|
||
let tagImg = canvas.createImage();
|
||
const objSrc = {
|
||
2: "certification-intermediary-icon.png",
|
||
5: "certification-listing-icon.png",
|
||
};
|
||
await new Promise((resolve) => {
|
||
tagImg.onload = resolve;
|
||
tagImg.src = `https://app.gter.net/image/miniApp/HKRenting/${objSrc[target.type]}?${Date.now()}`;
|
||
});
|
||
ctx.drawImage(tagImg, 215, 4, 50, 58);
|
||
} else if (target.type == 3 || target.type == 4 || target.type == 6) {
|
||
// 绘制红色价格标签
|
||
ctx.save();
|
||
const tagX = target.type == 6 ? 210 : 225; // 从右侧开始计算位置
|
||
const tagY = 10;
|
||
const tagWidth = target.type == 6 ? 60 : 46;
|
||
const tagHeight = 23;
|
||
|
||
const objBJ = {
|
||
3: "#6fc16d",
|
||
4: "#8080ff",
|
||
6: "#8080ff",
|
||
};
|
||
// 绘制圆角背景
|
||
ctx.fillStyle = objBJ[target.type];
|
||
ctx.beginPath();
|
||
ctx.moveTo(tagX + 10, tagY);
|
||
ctx.arcTo(tagX + tagWidth, tagY, tagX + tagWidth, tagY + tagHeight, 10);
|
||
ctx.arcTo(tagX + tagWidth, tagY + tagHeight, tagX, tagY + tagHeight, 10);
|
||
ctx.arcTo(tagX, tagY + tagHeight, tagX, tagY, 10);
|
||
ctx.arcTo(tagX, tagY, tagX + tagWidth, tagY, 10);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
// 绘制文字(调整垂直居中)
|
||
ctx.fillStyle = "#FFFFFF";
|
||
ctx.font = "bold 15px PingFang SC";
|
||
ctx.textAlign = "center";
|
||
ctx.textBaseline = "middle"; // 确保基线设置为中间
|
||
// Y坐标计算去掉+1偏移,直接使用精确中点
|
||
const objName = {
|
||
3: "中介",
|
||
4: "房东",
|
||
6: "招室友",
|
||
};
|
||
ctx.fillText(objName[target.type], tagX + tagWidth / 2, tagY + tagHeight / 2);
|
||
ctx.restore();
|
||
}
|
||
|
||
console.log("绘制右上角标签");
|
||
|
||
let username = user.nickname || "匿名用户";
|
||
|
||
// 绘制用户信息区域
|
||
// 先测量文本长度
|
||
ctx.font = "14px PingFang SC";
|
||
ctx.fillStyle = "#000";
|
||
|
||
let displayText = username + " 为你推荐";
|
||
let textMetrics = ctx.measureText(displayText);
|
||
let textWidth = textMetrics.width;
|
||
|
||
// 添加文本截断逻辑
|
||
const MAX_TEXT_WIDTH = 165; // 最大允许文本宽度
|
||
if (textWidth > MAX_TEXT_WIDTH) {
|
||
let limit = username.length;
|
||
// 逐步减少字符直到宽度合适
|
||
while (textWidth > MAX_TEXT_WIDTH && limit > 0) {
|
||
limit--;
|
||
displayText = username.substring(0, limit) + "... 为你推荐";
|
||
textMetrics = ctx.measureText(displayText);
|
||
textWidth = textMetrics.width;
|
||
}
|
||
}
|
||
|
||
// 动态计算区域宽度(头像24 + 边距4 + 文本宽度 + 右边距10)
|
||
const infoWidth = 24 + 4 + textWidth + 10;
|
||
const startX = 0;
|
||
const startY = 24;
|
||
const radius = 16;
|
||
|
||
ctx.fillStyle = "#f2f2f2";
|
||
ctx.beginPath();
|
||
ctx.moveTo(startX, startY);
|
||
ctx.lineTo(infoWidth - radius, startY);
|
||
ctx.arcTo(infoWidth, startY, infoWidth, startY + 28, radius);
|
||
ctx.lineTo(infoWidth, startY + 28 - radius);
|
||
ctx.arcTo(infoWidth, startY + 28, startX, startY + 28, radius);
|
||
ctx.lineTo(startX, startY + 28);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
|
||
console.log("用户名好了", user.avatar);
|
||
// 绘制头像
|
||
let avatarImg = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
avatarImg.onload = resolve;
|
||
const avatarUrl = user.avatar ? `${user.avatar}?${Date.now()}` : `https://app.gter.net/image/miniApp/HKRenting/defaultAvatar.png?${Date.now()}`; // 增加时间戳避免缓存
|
||
avatarImg.src = avatarUrl;
|
||
});
|
||
|
||
console.log("加载头像");
|
||
ctx.restore(); // 确保之前的裁剪状态被清除
|
||
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
ctx.arc(14, 38, 12, 0, Math.PI * 2);
|
||
ctx.clip();
|
||
ctx.drawImage(avatarImg, 2, 26, 24, 24);
|
||
ctx.restore();
|
||
|
||
// 绘制用户名
|
||
ctx.fillStyle = "#000";
|
||
ctx.font = "14px PingFang SC";
|
||
// 修改最终文本绘制调用
|
||
ctx.fillText(displayText, 30, 43); // 使用处理后的文本
|
||
|
||
// 绘制底部信息栏
|
||
const gradient = ctx.createLinearGradient(0, 190, 0, 224);
|
||
gradient.addColorStop(0, "rgba(51, 51, 51, 0.2)");
|
||
gradient.addColorStop(1, "rgba(51, 51, 51, 0.9)");
|
||
ctx.fillStyle = gradient;
|
||
|
||
ctx.beginPath();
|
||
ctx.moveTo(0, 190);
|
||
ctx.arcTo(280, 190, 280, 224, 0);
|
||
ctx.arcTo(280, 224, 0, 224, 15);
|
||
ctx.arcTo(0, 224, 0, 190, 15);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
console.log("绘制位置图标11");
|
||
// 绘制位置图标
|
||
let positionIcon = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
positionIcon.onload = resolve;
|
||
positionIcon.src = `https://app.gter.net/image/miniApp/HKRenting/position-icon.png?${Date.now()}`;
|
||
});
|
||
ctx.drawImage(positionIcon, 9, 200, 10, 14);
|
||
console.log("绘制位置图标完成");
|
||
|
||
// 绘制位置文本
|
||
ctx.fillStyle = "#fff";
|
||
ctx.font = "15px microsoft yahei";
|
||
ctx.fillText(`香港 | ${target.title}`, 25, 212);
|
||
|
||
console.log("开始绘制箭头图标");
|
||
// 绘制箭头图标
|
||
let arrowIcon = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
arrowIcon.onload = resolve;
|
||
arrowIcon.src = `https://app.gter.net/image/miniApp/HKRenting/arrow-round-yellow.png?${Date.now()}`;
|
||
});
|
||
ctx.drawImage(arrowIcon, 255, 200, 16, 16);
|
||
console.log("绘制箭头图标完成");
|
||
|
||
// 修改最后保存图片的尺寸
|
||
const imgData = canvas.toDataURL({
|
||
width: 280,
|
||
height: 224,
|
||
destWidth: 280 * 2, // 输出双倍分辨率
|
||
destHeight: 224 * 2,
|
||
});
|
||
|
||
const filePath = `${wx.env.USER_DATA_PATH}/${getCurrentDate()}/poster_share_${Date.now()}.png`;
|
||
const fs = wx.getFileSystemManager();
|
||
console.log("开始保存");
|
||
let writeFileSum = 0; // 写入次数
|
||
const writeFile = () => {
|
||
writeFileSum++;
|
||
console.log("writeFileSum:", writeFileSum);
|
||
if (writeFileSum > 10) return;
|
||
fs.writeFile({
|
||
filePath,
|
||
data: imgData.replace(/^data:image\/\w+;base64,/, ""),
|
||
encoding: "base64",
|
||
success: (res) => {
|
||
console.log("生成成功", res);
|
||
fs.close();
|
||
resolve(filePath);
|
||
},
|
||
fail: (err) => {
|
||
console.log("err", err);
|
||
// 此处可能存在内存满了的情况
|
||
if (err?.errMsg?.indexOf("file storage limit is exceeded") != -1) {
|
||
fs.readdir({
|
||
dirPath: `${wx.env.USER_DATA_PATH}/${getCurrentDate()}`,
|
||
success: (res) => {
|
||
// 过滤并排序文件
|
||
const files = res.files
|
||
.filter((f) => f.startsWith("poster_share_") && f.endsWith(".png"))
|
||
.map((f) => ({
|
||
name: f,
|
||
timestamp: parseInt(f.match(/poster_share_(\d+)\.png/)[1]), // 提取时间戳
|
||
}))
|
||
.sort((a, b) => a.timestamp - b.timestamp); // 按时间戳升序排列
|
||
|
||
// 计算需要删除的数量(取前50%)
|
||
const deleteCount = Math.ceil(files.length / 2);
|
||
const toDelete = files.slice(0, deleteCount);
|
||
|
||
// 批量删除旧文件
|
||
toDelete.forEach((file) => {
|
||
fs.unlink({
|
||
filePath: `${wx.env.USER_DATA_PATH}/${getCurrentDate()}/${file.name}`,
|
||
success: () => console.log("已清理文件:", file.name),
|
||
fail: (e) => console.log("文件清理失败:", file.name, e),
|
||
});
|
||
});
|
||
|
||
// 重试写入
|
||
setTimeout(() => writeFile(), 1000);
|
||
},
|
||
});
|
||
}
|
||
|
||
if (err?.errMsg?.indexOf("fail no such file or directory") != -1) {
|
||
fs.mkdir({
|
||
dirPath: `${wx.env.USER_DATA_PATH}/${getCurrentDate()}`,
|
||
complete: (res) => writeFile(),
|
||
});
|
||
}
|
||
},
|
||
});
|
||
};
|
||
|
||
writeFile();
|
||
cleanupOldDateFolders();
|
||
});
|
||
}
|
||
|
||
// 生成海报 没有图片
|
||
function generatePosterNoImage(target) {
|
||
return new Promise(async (resolve, reject) => {
|
||
const user = getApp().globalData.user || {};
|
||
const canvas = wx.createOffscreenCanvas({
|
||
type: "2d",
|
||
width: 280 * 2,
|
||
height: 224 * 2,
|
||
});
|
||
const ctx = canvas.getContext("2d");
|
||
ctx.scale(2, 2);
|
||
|
||
// 绘制白色背景
|
||
ctx.fillStyle = "#FFFFFF";
|
||
ctx.fillRect(0, 0, 280, 224);
|
||
|
||
// 绘制用户信息区域
|
||
ctx.font = "14px PingFang SC";
|
||
ctx.fillStyle = "#555555";
|
||
|
||
// 绘制圆形头像
|
||
const avatarImg = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
avatarImg.onload = resolve;
|
||
const avatarUrl = user.avatar ? `${user.avatar}?${Date.now()}` : `https://app.gter.net/image/miniApp/HKRenting/defaultAvatar.png?${Date.now()}`; // 增加时间戳避免缓存
|
||
avatarImg.src = avatarUrl;
|
||
});
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
ctx.arc(12, 12, 12, 0, Math.PI * 2);
|
||
ctx.clip();
|
||
ctx.drawImage(avatarImg, 0, 0, 24, 24);
|
||
ctx.restore();
|
||
|
||
let username = user.nickname || "匿名用户";
|
||
|
||
// 绘制用户名
|
||
let displayText = username + " 为你推荐";
|
||
let textMetrics = ctx.measureText(displayText);
|
||
let textWidth = textMetrics.width;
|
||
|
||
// 添加文本截断逻辑
|
||
const MAX_TEXT_WIDTH = 240; // 最大允许文本宽度
|
||
if (textWidth > MAX_TEXT_WIDTH) {
|
||
let limit = username.length;
|
||
// 逐步减少字符直到宽度合适
|
||
while (textWidth > MAX_TEXT_WIDTH && limit > 0) {
|
||
limit--;
|
||
displayText = username.substring(0, limit) + "... 为你推荐";
|
||
textMetrics = ctx.measureText(displayText);
|
||
textWidth = textMetrics.width;
|
||
}
|
||
}
|
||
ctx.fillText(displayText, 30, 18); // 使用处理后的文本
|
||
// ctx.fillText(`${ user.nickname || "匿名用户" } 为你推荐`, 30, 18);
|
||
|
||
// 绘制背景卡片
|
||
const bgImg = canvas.createImage();
|
||
await new Promise((resolve) => {
|
||
bgImg.onload = resolve;
|
||
bgImg.src = `https://app.gter.net/image/miniApp/HKRenting/share-default-bj.png?${Date.now()}`;
|
||
});
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
console.log("ctx", ctx);
|
||
// ctx.roundRect(0, 40, 280, 184, [10]);
|
||
// 手动绘制圆角路径替代roundRect
|
||
const x = 0,
|
||
y = 40,
|
||
width = 280,
|
||
height = 184,
|
||
radius = 10;
|
||
ctx.moveTo(x + radius, y);
|
||
ctx.arcTo(x + width, y, x + width, y + height, radius);
|
||
ctx.arcTo(x + width, y + height, x, y + height, radius);
|
||
ctx.arcTo(x, y + height, x, y, radius);
|
||
ctx.arcTo(x, y, x + width, y, radius);
|
||
ctx.closePath();
|
||
ctx.clip();
|
||
ctx.drawImage(bgImg, 0, 40, 280, 184);
|
||
ctx.restore();
|
||
|
||
// 绘制文字信息
|
||
ctx.font = "16px PingFang SC";
|
||
ctx.fillStyle = "#000000";
|
||
|
||
// 位置信息
|
||
ctx.fillText(target.position, 44, 71);
|
||
|
||
// 类型信息
|
||
ctx.fillText(target.typeText, 44, 121);
|
||
|
||
// 价格信息
|
||
ctx.font = "20px PingFang SC";
|
||
ctx.fillStyle = "#FA6B11";
|
||
ctx.fillText(target.price, 44, 171);
|
||
ctx.font = "16px PingFang SC";
|
||
ctx.fillStyle = "#000000";
|
||
ctx.fillText("HK$/月", 44 + ctx.measureText(target.price).width + 12, 171);
|
||
|
||
// 导出图片
|
||
const imgData = canvas.toDataURL({
|
||
destWidth: 280 * 2,
|
||
destHeight: 224 * 2,
|
||
});
|
||
|
||
const filePath = `${wx.env.USER_DATA_PATH}/${getCurrentDate()}/poster_share_${Date.now()}.png`;
|
||
wx.getFileSystemManager().writeFile({
|
||
filePath,
|
||
data: imgData.split(",")[1],
|
||
encoding: "base64",
|
||
success: () => resolve(filePath),
|
||
fail: reject,
|
||
});
|
||
|
||
cleanupOldDateFolders();
|
||
});
|
||
}
|
||
|
||
// 下载图片
|
||
function downloadPic(src) {
|
||
return new Promise(async (resolve, reject) => {
|
||
console.log("开始下载海报");
|
||
wx.getImageInfo({
|
||
src,
|
||
success(res) {
|
||
console.log(src);
|
||
resolve(res.path);
|
||
},
|
||
fail(err) {
|
||
console.log("err", err);
|
||
},
|
||
});
|
||
});
|
||
}
|
||
|
||
function cleanupOldDateFolders() {
|
||
const fs = wx.getFileSystemManager();
|
||
const currentDate = getCurrentDate();
|
||
fs.readdir({
|
||
dirPath: wx.env.USER_DATA_PATH,
|
||
success(res) {
|
||
res.files.forEach((folder) => {
|
||
// 严格匹配YYYY-MM-DD格式的目录名(如:2023-12-31)
|
||
if (/^\d{4}-\d{2}-\d{2}$/.test(folder) && folder !== currentDate) {
|
||
const dirPath = `${wx.env.USER_DATA_PATH}/${folder}`;
|
||
fs.rmdir({
|
||
dirPath,
|
||
recursive: true,
|
||
success: () => console.log("已清理目录:", dirPath),
|
||
fail: (err) => console.log("清理失败:", dirPath, err),
|
||
});
|
||
}
|
||
});
|
||
},
|
||
});
|
||
}
|
||
|
||
function getCurrentDate() {
|
||
const date = new Date();
|
||
const year = date.getFullYear();
|
||
// getMonth() 返回值是 0(一月) 到 11(十二月) 之间的一个整数,所以要加 1
|
||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||
const day = String(date.getDate()).padStart(2, "0");
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
|
||
module.exports = {
|
||
generatePosterNoImage,
|
||
generatePoster,
|
||
initial: initial,
|
||
share: share,
|
||
change_data: change_data,
|
||
html2wxml: html2wxml,
|
||
copy,
|
||
sendData,
|
||
request,
|
||
wxget,
|
||
closeAD,
|
||
clickAD,
|
||
count,
|
||
getTopTitle,
|
||
getTimeAgo,
|
||
useSocket,
|
||
updateProperty,
|
||
goPage,
|
||
https: function (url, data, success, fail) {
|
||
wx.request({
|
||
url: url,
|
||
data: data,
|
||
method: "POST", // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
|
||
header: {
|
||
"content-type": "application/json",
|
||
Accept: "application/json, text/plain",
|
||
Cookie: "miucms_session=" + wx.getStorageSync("Authorization"),
|
||
Authorization: wx.getStorageSync("Authorization") || "",
|
||
},
|
||
success: function (res) {
|
||
typeof success == "function" && success(res);
|
||
},
|
||
fail: function () {
|
||
typeof fail == "function" && fail(res);
|
||
},
|
||
complete: function () {
|
||
typeof fail == "function" && fail(res);
|
||
},
|
||
});
|
||
},
|
||
|
||
statistics,
|
||
bindingUser,
|
||
objectToQueryString,
|
||
gtergreenonionqrcode: "https://oss.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-d_pIqcXjqqsgFptxhcq_cQnrlcvd3DQYcBq_D-81qNDQyOQ~~",
|
||
backOrIndex,
|
||
}; |