From 30cdf6966f4410e719887e682bf55b46af722db1 Mon Sep 17 00:00:00 2001 From: itgaojian163 Date: Fri, 21 Mar 2025 09:02:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 47 ++++++++++++ app.json | 20 +++++ app.wxss | 40 ++++++++++ components/ad-popup/ad-popup.js | 25 +++++++ components/ad-popup/ad-popup.json | 3 + components/ad-popup/ad-popup.wxml | 6 ++ components/ad-popup/ad-popup.wxss | 40 ++++++++++ net/api/commonApi.js | 19 +++++ net/api/domainApi.js | 42 +++++++++++ net/api/indexApi.js | 50 +++++++++++++ net/api/policyApi.js | 19 +++++ net/api/testapi.js | 44 +++++++++++ net/http.js | 67 +++++++++++++++++ pages/index/index.js | 26 +++++++ pages/index/index.json | 4 + pages/index/index.wxml | 7 ++ pages/index/index.wxss | 62 ++++++++++++++++ pages/login/login.js | 63 ++++++++++++++++ pages/login/login.json | 3 + pages/login/login.wxml | 19 +++++ pages/login/login.wxss | 66 +++++++++++++++++ pages/treaty/privacy/privacy.js | 66 +++++++++++++++++ pages/treaty/privacy/privacy.json | 3 + pages/treaty/privacy/privacy.wxml | 1 + pages/treaty/privacy/privacy.wxss | 1 + pages/treaty/service/service.js | 66 +++++++++++++++++ pages/treaty/service/service.json | 3 + pages/treaty/service/service.wxml | 1 + pages/treaty/service/service.wxss | 1 + project.config.json | 28 +++++++ project.private.config.json | 9 +++ sitemap.json | 7 ++ utils/cache.js | 53 ++++++++++++++ utils/format.js | 57 +++++++++++++++ utils/http.js | 67 +++++++++++++++++ utils/storage.js | 75 +++++++++++++++++++ utils/util.js | 118 ++++++++++++++++++++++++++++++ utils/validator.js | 43 +++++++++++ 38 files changed, 1271 insertions(+) create mode 100644 app.js create mode 100644 app.json create mode 100644 app.wxss create mode 100644 components/ad-popup/ad-popup.js create mode 100644 components/ad-popup/ad-popup.json create mode 100644 components/ad-popup/ad-popup.wxml create mode 100644 components/ad-popup/ad-popup.wxss create mode 100644 net/api/commonApi.js create mode 100644 net/api/domainApi.js create mode 100644 net/api/indexApi.js create mode 100644 net/api/policyApi.js create mode 100644 net/api/testapi.js create mode 100644 net/http.js create mode 100644 pages/index/index.js create mode 100644 pages/index/index.json create mode 100644 pages/index/index.wxml create mode 100644 pages/index/index.wxss create mode 100644 pages/login/login.js create mode 100644 pages/login/login.json create mode 100644 pages/login/login.wxml create mode 100644 pages/login/login.wxss create mode 100644 pages/treaty/privacy/privacy.js create mode 100644 pages/treaty/privacy/privacy.json create mode 100644 pages/treaty/privacy/privacy.wxml create mode 100644 pages/treaty/privacy/privacy.wxss create mode 100644 pages/treaty/service/service.js create mode 100644 pages/treaty/service/service.json create mode 100644 pages/treaty/service/service.wxml create mode 100644 pages/treaty/service/service.wxss create mode 100644 project.config.json create mode 100644 project.private.config.json create mode 100644 sitemap.json create mode 100644 utils/cache.js create mode 100644 utils/format.js create mode 100644 utils/http.js create mode 100644 utils/storage.js create mode 100644 utils/util.js create mode 100644 utils/validator.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..a9780cc --- /dev/null +++ b/app.js @@ -0,0 +1,47 @@ +// app.js +App({ + globalData: { + userInfo: null, + isAdPopupVisible: false + }, + onLaunch() { + // 展示本地存储能力 + const logs = wx.getStorageSync('logs') || [] + logs.unshift(Date.now()) + wx.setStorageSync('logs', logs) + + // 登录 + wx.login({ + success: res => { + // 发送 res.code 到后台换取 openId, sessionKey, unionId + } + }) + }, + // 显示广告弹窗 + showAdPopup(imageUrl) { + this.globalData.isAdPopupVisible = true; + this.globalData.adImageUrl = imageUrl; + // 通知所有页面更新弹窗状态 + this.updateAdPopup(); + }, + + // 关闭广告弹窗 + hideAdPopup() { + this.globalData.isAdPopupVisible = false; + this.updateAdPopup(); + }, + + // 更新所有页面的弹窗状态 + updateAdPopup() { + console.log("显示广告") + const pages = getCurrentPages(); + pages.forEach(page => { + if (page.setData) { + page.setData({ + isAdPopupVisible: this.globalData.isAdPopupVisible, + adImageUrl: this.globalData.adImageUrl + }); + } + }); + } +}) \ No newline at end of file diff --git a/app.json b/app.json new file mode 100644 index 0000000..eca1053 --- /dev/null +++ b/app.json @@ -0,0 +1,20 @@ +{ + "pages": [ + "pages/login/login", + "pages/index/index", + "pages/treaty/privacy/privacy", + "pages/treaty/service/service" + ], + "window": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "AI喵著", + "navigationBarBackgroundColor": "#ffffff" + }, + "style": "v2", + "componentFramework": "glass-easel", + "sitemapLocation": "sitemap.json", + "lazyCodeLoading": "requiredComponents", + "usingComponents": { + "ad-popup": "./components/ad-popup/ad-popup" + } +} \ No newline at end of file diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..db6116d --- /dev/null +++ b/app.wxss @@ -0,0 +1,40 @@ +/**app.wxss**/ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} + + +/**自定义CheckBox**/ +wx-checkbox .wx-checkbox-input.wx-checkbox-input-checked { + color: #fff !important; + background-color: #3F72FF; + border: 2rpx solid #3F72FF +} + +wx-checkbox .wx-checkbox-input { + /*margin-right: 10rpx;*/ + -webkit-appearance: none; + appearance: none; + outline: 0; + text-indent: 0; + border-radius: 50%; + width: 40rpx; + height: 40rpx; + background-color: transparent; + position: relative; + border: 1rpx solid rgb(85, 85, 85); + box-sizing: border-box; +} + +/*钩大小*/ +wx-checkbox .wx-checkbox-input.wx-checkbox-input-checked:before { + font-size: 36rpx; +} + +/***End***/ \ No newline at end of file diff --git a/components/ad-popup/ad-popup.js b/components/ad-popup/ad-popup.js new file mode 100644 index 0000000..ea6e1c4 --- /dev/null +++ b/components/ad-popup/ad-popup.js @@ -0,0 +1,25 @@ +// component/ad-dialog/ad-dialog.js +Component({ + properties: { + // 广告图片 URL + imageUrl: { + type: String, + value: '' + }, + // 是否显示弹窗 + visible: { + type: Boolean, + value: false + } + }, + + methods: { + // 关闭弹窗 + onClose() { + this.setData({ + visible: false + }); + this.triggerEvent('close'); // 触发关闭事件 + } + } +}) \ No newline at end of file diff --git a/components/ad-popup/ad-popup.json b/components/ad-popup/ad-popup.json new file mode 100644 index 0000000..fba482a --- /dev/null +++ b/components/ad-popup/ad-popup.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/ad-popup/ad-popup.wxml b/components/ad-popup/ad-popup.wxml new file mode 100644 index 0000000..ec93774 --- /dev/null +++ b/components/ad-popup/ad-popup.wxml @@ -0,0 +1,6 @@ + + + + × + + \ No newline at end of file diff --git a/components/ad-popup/ad-popup.wxss b/components/ad-popup/ad-popup.wxss new file mode 100644 index 0000000..ea2bdab --- /dev/null +++ b/components/ad-popup/ad-popup.wxss @@ -0,0 +1,40 @@ +.ad-popup { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; +} + +.ad-content { + position: relative; + width: 80%; + background: #fff; + border-radius: 10px; + overflow: hidden; +} + +.ad-content image { + width: 100%; + height: 300rpx; +} + +.close-btn { + position: absolute; + top: 10rpx; + right: 10rpx; + width: 40rpx; + height: 40rpx; + background: #ccc; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + font-size: 30rpx; + color: #fff; +} \ No newline at end of file diff --git a/net/api/commonApi.js b/net/api/commonApi.js new file mode 100644 index 0000000..f506b45 --- /dev/null +++ b/net/api/commonApi.js @@ -0,0 +1,19 @@ +import { + request +} from "../http"; + +// 管理地址 +const apiPath = { + investDetail: "/news-content/listpage?rows=1&page=1", //投资优势 + servicePrivacy: "app/agreementportal/getrelease/93679af4-e264-4d1c-bd49-538028daa95d" +} +class CommonService { + static doGetInvestDetail(data) { + return request(apiPath.investDetail, "GET", data) + } + static doGetServicePrivacy() { + return request(apiPath.servicePrivacy, "GET", null) + } +} + +export default CommonService; \ No newline at end of file diff --git a/net/api/domainApi.js b/net/api/domainApi.js new file mode 100644 index 0000000..03726c9 --- /dev/null +++ b/net/api/domainApi.js @@ -0,0 +1,42 @@ +import { + request +} from "../http"; + +// 管理地址 +const apiPath = { + domainCategory: "/news-directories/list?directoriesParentId=b04b4dc3-020a-4a9f-a567-464d27f70b19", //特色产业 + keyEnterprise: "/query/sql/q2984a0f", //重点企业 + domainInfo: "/news-content/listpage?newsDirectoriesId=2c76e2a0-37b2-4144-9d92-64376e5a22c3", //产业基础 + industryArea: "/news-content/listpage?newsDirectoriesId=df975b5b-74bf-4c5d-a4bc-10acb6f32e81", //产业园区 + plates: "/news-content/listpage?newsDirectoriesId=40d9b2e3-a609-4f45-9833-acbfdb16ce56", //产业图谱 + newDetail: "/news-content/listpage", //详情 + detail: "/news-content/get/" +} +class DomainService { + static doGetDomainCategory() { + return request(apiPath.domainCategory, "GET") + } + static doGetKeyEnterprise() { + return request(apiPath.keyEnterprise, "GET") + } + static doGetKeyEnterprise(data) { + return request(apiPath.keyEnterprise, "GET", data) + } + static doGetDomainInfo() { + return request(apiPath.domainInfo, "GET") + } + static doGetIndustryArea() { + return request(apiPath.industryArea, "GET") + } + static doGetPlates() { + return request(apiPath.plates, "GET") + } + static doGetDetail(data) { + return request(apiPath.newDetail, "GET", data) + } + static doDetail(url) { + return request(apiPath.detail + url, "GET") + } +} + +export default DomainService; \ No newline at end of file diff --git a/net/api/indexApi.js b/net/api/indexApi.js new file mode 100644 index 0000000..ac5d300 --- /dev/null +++ b/net/api/indexApi.js @@ -0,0 +1,50 @@ +import { + request +} from "../http"; + +// 管理地址 +const apiPath = { + descVideo: "/news-content/listpage?newsDirectoriesId=9532d411-15c5-4c9c-8d73-e9f68a482702", + descInfo: "/news-content/listpage?newsDirectoriesId=91a98b33-1133-4935-8c4c-9b37cc5fe63b&rows=1&page=1", + statistics: "/query/sql/q9ce6963", + invest: "/query/sql/q428ea76", + investAreaInfo: "/news-content/listpage?rows=1&page=1", //地区概况 //资源条件 //气候条件 //基础设施 + categoryList: "/news-directories/list", //投资优势 投资环境 + superiosityDetail: "/news-content/listpage?rows=1&page=1", //投资优势详情 + investDetail: "", //投资机会详情 +} +class IndexService { + static doGetDescVideo() { + return request(apiPath.descVideo, "GET") + } + static doGetDescInfo() { + return request(apiPath.descInfo, "GET") + } + static doGetStatistics(data) { + return request(apiPath.statistics, "GET", data) + } + static doGetInvest() { + return request(apiPath.invest, "GET") + } + static doGetInvestDetail(data) { + return request(apiPath.invest, "GET", data) + } + static doGetInvestArea(data) { + return request(apiPath.investAreaInfo, "GET", data) + } + static doGetSuperiorityList() { + return request(apiPath.categoryList, "GET", { + directoriesParentId: 'c7fa126e-1fa7-4cdb-b13a-2afb2f7b48e9' + }) + } + static doGetInvestAreaCategory() { + return request(apiPath.categoryList, "GET", { + directoriesParentId: 'd3ba3ff5-6d9e-4aed-9331-73e50b5ac598' + }) + } + static doGetSuperiorityDetail(data) { + return request(apiPath.superiosityDetail, "GET", data) + } +} + +export default IndexService; \ No newline at end of file diff --git a/net/api/policyApi.js b/net/api/policyApi.js new file mode 100644 index 0000000..f884829 --- /dev/null +++ b/net/api/policyApi.js @@ -0,0 +1,19 @@ +import { + request +} from "../http"; + +// 管理地址 +const apiPath = { + policyList: "/news-content/listpage", //政策列表 + policyDetail: "/news-content/get/", //政策详情 +} +class PolicyService { + static doGetPolicyList(data) { + return request(apiPath.policyList, "GET", data) + } + static doGetDetail(id) { + return request(apiPath.policyDetail + id, "GET") + } +} + +export default PolicyService; \ No newline at end of file diff --git a/net/api/testapi.js b/net/api/testapi.js new file mode 100644 index 0000000..7b70902 --- /dev/null +++ b/net/api/testapi.js @@ -0,0 +1,44 @@ +import { + request +} from "../http"; + +// 管理地址,个人习惯,喜欢的下载request参数中也行 +const apiPath = { + login: "/api/v1/login" +} +class AuthService { + static login(data) { + // 按住ctrl点击wx.request进入ts声明看options的类型,method是均大写的,对应即可 + return request(apiPath.login, "GET", data) + + // 由于request的参数顺序第四个才是查询参数,所以如果需要传递,第三个传输传空对象即可 + // return request(apiPath.login, "GET", {}, data) + } +} + +export default AuthService; + + +// import AuthService from "../../service/AuthService"; +// // 导入封装好的服务层 + +// // 其他代码省略 +// page({ +// // Promise语法 +// submitForm(){ +// AuthService.login({username:"a",password:"2"}).then(res=>{ +// // 干点别的 +// },err=>{ +// // 出错了干点啥 +// }) +// }, +// // async-await语法糖 +// async asycsubmitForm(){ +// try{ +// const res = await AuthService.login({username:"abc",password:"123"}); +// // 干点别的 +// }catch(err){ +// // 错了干点啥? +// } +// } +// }) \ No newline at end of file diff --git a/net/http.js b/net/http.js new file mode 100644 index 0000000..f521858 --- /dev/null +++ b/net/http.js @@ -0,0 +1,67 @@ +// 定义api服务地址 +const baseUrl = 'https://www.xzszwhy.cn/daqi/app'; +// const baseUrl = 'http://106.74.34.136:8084/daqi/app'; +/** + * 传入请求参数,返回Promise支持链试调用 + * @param url 请求地址 + * @param method 请求方法类型,不传入默认是"GET" + * @param data 请求体数据 + * @param params 请求参数 + */ +function request(url, method = "GET", data = {}, params = {}) { + const header = { + "content-type": "application/json" + // 有其他content-type需求加点逻辑判断处理即可 + } + //TODO 获取token,有就丢进请求头 + // const tokenString = wx.getStorageSync("access_token"); + // if (tokenString) { + // header.Authorization = `Bearer ${tokenString}`; + // } + return new Promise(function (resolve, reject) { + // 判断是否传递了query参数,有则进行地址拼接 + // if (params) { + // url += "?" + urlEncode(params) + // } + // wx.showLoading({ + // title: '加载中...', + // mask: true //显示蒙层 + // }) + wx.request({ + url: baseUrl + url, + timeout: 8000, + method, + data, + dataType: "json", // 微信官方文档中介绍会对数据进行一次JSON.parse + header, + success(res) { + // wx.hideLoading(); + // HTTP状态码为200才视为成功 + if (res.statusCode === 200) { + // 真正的数据响应体中还有一层success字段判断业务状态,按实际情况处理 + resolve(res.data) + // if (res.data.success) { + // resolve(res.data.result) + // } else { + // // 业务判断错误 + // reject(res) + // } + } else { + // wx.request的特性,只要有响应就会走success回调,所以在这里判断状态,非200的均视为请求失败 + reject(res) + } + }, + fail(err) { + // wx.hideLoading(); + // 断网、服务器挂了都会fail回调,直接reject即可 + reject(err) + } + }) + }) +} + +// 导出请求和服务地址 +export { + request, + baseUrl +} \ No newline at end of file diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..33faa1a --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,26 @@ +// index.js +import format from "../../utils/format" +const app = getApp() +Page({ + data: { + motto: 'Hello World', + userInfo: { + avatarUrl: '', + nickName: '', + }, + isAdPopupVisible: false, + adImageUrl: '' + }, + onLoad(e) { + console.log(app) + this.setData({ + adImageUrl: app.globalData.adImageUrl, + isAdPopupVisible: app.globalData.isAdPopupVisible + }) + }, + printInfo() { + app.showAdPopup("https://ts1.tc.mm.bing.net/th/id/R-C.d88442788ee5a458d50e40f0a8cb1e05?rik=EoPp8GhejYeQfw&riu=http%3a%2f%2fimg.pconline.com.cn%2fimages%2fupload%2fupc%2ftx%2fwallpaper%2f1307%2f10%2fc2%2f23151595_1373424485102.jpg&ehk=J7xq%2f50bCmdD4jUXfnTlau2s5WiVsBxQArAjvJzqIo4%3d&risl=&pid=ImgRaw&r=0") + // const num = format.formatQuantity(19952) + // console.log(num) + }, +}) \ No newline at end of file diff --git a/pages/index/index.json b/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..26bb97b --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pages/index/index.wxss b/pages/index/index.wxss new file mode 100644 index 0000000..1ebed4b --- /dev/null +++ b/pages/index/index.wxss @@ -0,0 +1,62 @@ +/**index.wxss**/ +page { + height: 100vh; + display: flex; + flex-direction: column; +} +.scrollarea { + flex: 1; + overflow-y: hidden; +} + +.userinfo { + display: flex; + flex-direction: column; + align-items: center; + color: #aaa; + width: 80%; +} + +.userinfo-avatar { + overflow: hidden; + width: 128rpx; + height: 128rpx; + margin: 20rpx; + border-radius: 50%; +} + +.usermotto { + margin-top: 200px; +} + +.avatar-wrapper { + padding: 0; + width: 56px !important; + border-radius: 8px; + margin-top: 40px; + margin-bottom: 40px; +} + +.avatar { + display: block; + width: 56px; + height: 56px; +} + +.nickname-wrapper { + display: flex; + width: 100%; + padding: 16px; + box-sizing: border-box; + border-top: .5px solid rgba(0, 0, 0, 0.1); + border-bottom: .5px solid rgba(0, 0, 0, 0.1); + color: black; +} + +.nickname-label { + width: 105px; +} + +.nickname-input { + flex: 1; +} diff --git a/pages/login/login.js b/pages/login/login.js new file mode 100644 index 0000000..bc79b5e --- /dev/null +++ b/pages/login/login.js @@ -0,0 +1,63 @@ +// pages/login/login.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + isChecked: false, + hintText: "获取电话号码", + code: '', + msg: '', + errno: '' + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + //用户服务协议 + showServiceDeal() { + wx.navigateTo({ + url: '/pages/treaty/service/service', + }) + }, + //隐私条款 + showPrivacyDeal() { + wx.navigateTo({ + url: '/pages/treaty/privacy/privacy', + }) + }, + onChange(e) { + console.log(e) + this.setData({ + isChecked: e.detail.value === '1' + }); + }, + doGetPhoneNumber(e) { + if (e.detail.errMsg === 'getPhoneNumber:ok') { + // 用户同意授权 + const { + encryptedData, + iv + } = e.detail; + console.log('encryptedData:', encryptedData); + console.log('iv:', iv); + //通过后台获取手机号 + //弹窗获取授权用户昵称 + } else { + // 用户拒绝授权 + console.log('用户拒绝授权'); + } + }, + doGetUserInfo() { + wx.getUserProfile({ + desc: '获取昵称用于展示', + success: (res) => { + + } + }) + } +}) \ No newline at end of file diff --git a/pages/login/login.json b/pages/login/login.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/login/login.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/login/login.wxml b/pages/login/login.wxml new file mode 100644 index 0000000..711e155 --- /dev/null +++ b/pages/login/login.wxml @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/pages/login/login.wxss b/pages/login/login.wxss new file mode 100644 index 0000000..f553763 --- /dev/null +++ b/pages/login/login.wxss @@ -0,0 +1,66 @@ +/* pages/login/login.wxss */ +.login { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + position: relative; +} + +.login-container { + background-image: url('https://file.moyublog.com/d/file/2023-11-23/b8721515c6161e26a742b241aa05e0f9.jpg'); + width: 100vw; + height: 100vh; +} + +.btn-content { + position: absolute; + bottom: 0; + left: 50%; + transform: translate(-50%, -50%); + background-color: white; + width: 80vw; + height: 250rpx; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 20rpx; +} + +.deal { + color: blue; +} + +.deal-box { + font-size: 24rpx; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; +} + +.btn { + background-color: green; + color: white; + animation: clickScale 1.2s; + animation-iteration-count: infinite; + animation-timing-function: ease-in-out; + border-radius: 50rpx; + margin-top: 30rpx; + font-size: 24rpx; +} + +@keyframes clickScale { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(1.05); + } + + 100% { + transform: scale(1); + } +} \ No newline at end of file diff --git a/pages/treaty/privacy/privacy.js b/pages/treaty/privacy/privacy.js new file mode 100644 index 0000000..1da32d0 --- /dev/null +++ b/pages/treaty/privacy/privacy.js @@ -0,0 +1,66 @@ +// pages/treaty/privacy/privacy.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) \ No newline at end of file diff --git a/pages/treaty/privacy/privacy.json b/pages/treaty/privacy/privacy.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/treaty/privacy/privacy.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/treaty/privacy/privacy.wxml b/pages/treaty/privacy/privacy.wxml new file mode 100644 index 0000000..2104826 --- /dev/null +++ b/pages/treaty/privacy/privacy.wxml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pages/treaty/privacy/privacy.wxss b/pages/treaty/privacy/privacy.wxss new file mode 100644 index 0000000..ecd4d97 --- /dev/null +++ b/pages/treaty/privacy/privacy.wxss @@ -0,0 +1 @@ +/* pages/treaty/privacy/privacy.wxss */ \ No newline at end of file diff --git a/pages/treaty/service/service.js b/pages/treaty/service/service.js new file mode 100644 index 0000000..08d269d --- /dev/null +++ b/pages/treaty/service/service.js @@ -0,0 +1,66 @@ +// pages/treaty/service/service.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) \ No newline at end of file diff --git a/pages/treaty/service/service.json b/pages/treaty/service/service.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/treaty/service/service.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/treaty/service/service.wxml b/pages/treaty/service/service.wxml new file mode 100644 index 0000000..bcf2d75 --- /dev/null +++ b/pages/treaty/service/service.wxml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pages/treaty/service/service.wxss b/pages/treaty/service/service.wxss new file mode 100644 index 0000000..a0af57d --- /dev/null +++ b/pages/treaty/service/service.wxss @@ -0,0 +1 @@ +/* pages/treaty/service/service.wxss */ \ No newline at end of file diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..55325de --- /dev/null +++ b/project.config.json @@ -0,0 +1,28 @@ +{ + "compileType": "miniprogram", + "libVersion": "trial", + "packOptions": { + "ignore": [], + "include": [] + }, + "setting": { + "coverView": true, + "es6": true, + "postcss": true, + "minified": true, + "enhance": true, + "showShadowRootInWxmlPanel": true, + "packNpmRelationList": [], + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + } + }, + "condition": {}, + "editorSetting": { + "tabIndent": "auto", + "tabSize": 2 + }, + "appid": "wx501e9ce64f25c418" +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..9309aeb --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,9 @@ +{ + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "projectname": "ts_mz", + "setting": { + "compileHotReLoad": true, + "urlCheck": false + }, + "libVersion": "3.7.10" +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/utils/cache.js b/utils/cache.js new file mode 100644 index 0000000..4e0d2a7 --- /dev/null +++ b/utils/cache.js @@ -0,0 +1,53 @@ +// 缓存工具类 +const CACHE_PREFIX = 'ts_mz_'; +const DEFAULT_CACHE_TIME = 5 * 60 * 1000; // 默认缓存5分钟 + +class Cache { + /** + * 设置缓存 + * @param {string} key 缓存键 + * @param {any} value 缓存值 + * @param {number} expire 过期时间(毫秒) + */ + static set(key, value, expire = DEFAULT_CACHE_TIME) { + const data = { + value, + expire: expire ? new Date().getTime() + expire : null + }; + wx.setStorageSync(CACHE_PREFIX + key, JSON.stringify(data)); + } + + /** + * 获取缓存 + * @param {string} key 缓存键 + * @returns {any} 缓存值 + */ + static get(key) { + const data = wx.getStorageSync(CACHE_PREFIX + key); + if (!data) return null; + + const cache = JSON.parse(data); + if (cache.expire && cache.expire < new Date().getTime()) { + wx.removeStorageSync(CACHE_PREFIX + key); + return null; + } + return cache.value; + } + + /** + * 删除缓存 + * @param {string} key 缓存键 + */ + static remove(key) { + wx.removeStorageSync(CACHE_PREFIX + key); + } + + /** + * 清空所有缓存 + */ + static clear() { + wx.clearStorageSync(); + } +} + +module.exports = Cache; \ No newline at end of file diff --git a/utils/format.js b/utils/format.js new file mode 100644 index 0000000..b34a624 --- /dev/null +++ b/utils/format.js @@ -0,0 +1,57 @@ +// 格式化金额 +const formatAmount = (amount, decimals = 2) => { + if (!amount && amount !== 0) return '--'; + return Number(amount).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ','); +}; + +// 格式化数量(支持万、亿单位) +const formatQuantity = (num) => { + if (!num && num !== 0) return '--'; + if (num >= 100000000) { + return (num / 100000000).toFixed(2) + '亿'; + } + if (num >= 10000) { + return (num / 10000).toFixed(2) + '万'; + } + return num.toFixed(2) + '元'; +}; + +// 格式化文件大小 +const formatFileSize = (bytes) => { + if (!bytes && bytes !== 0) return '--'; + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let num = bytes; + let index = 0; + while (num >= 1024 && index < units.length - 1) { + num /= 1024; + index++; + } + return num.toFixed(2) + units[index]; +}; + +// 格式化手机号 +const formatPhone = (phone) => { + if (!phone) return ''; + return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'); +}; + +// 格式化身份证号 +const formatIdCard = (idCard) => { + if (!idCard) return ''; + return idCard.replace(/(\d{4})\d{10}(\d{4})/, '$1**********$2'); +}; + +// 格式化银行卡号 +const formatBankCard = (cardNo) => { + if (!cardNo) return ''; + return cardNo.replace(/(\d{4})\d+(\d{4})/, '$1 **** **** $2'); +}; + +module.exports = { + formatAmount, + formatQuantity, + formatFileSize, + formatPhone, + formatIdCard, + formatBankCard +}; \ No newline at end of file diff --git a/utils/http.js b/utils/http.js new file mode 100644 index 0000000..f521858 --- /dev/null +++ b/utils/http.js @@ -0,0 +1,67 @@ +// 定义api服务地址 +const baseUrl = 'https://www.xzszwhy.cn/daqi/app'; +// const baseUrl = 'http://106.74.34.136:8084/daqi/app'; +/** + * 传入请求参数,返回Promise支持链试调用 + * @param url 请求地址 + * @param method 请求方法类型,不传入默认是"GET" + * @param data 请求体数据 + * @param params 请求参数 + */ +function request(url, method = "GET", data = {}, params = {}) { + const header = { + "content-type": "application/json" + // 有其他content-type需求加点逻辑判断处理即可 + } + //TODO 获取token,有就丢进请求头 + // const tokenString = wx.getStorageSync("access_token"); + // if (tokenString) { + // header.Authorization = `Bearer ${tokenString}`; + // } + return new Promise(function (resolve, reject) { + // 判断是否传递了query参数,有则进行地址拼接 + // if (params) { + // url += "?" + urlEncode(params) + // } + // wx.showLoading({ + // title: '加载中...', + // mask: true //显示蒙层 + // }) + wx.request({ + url: baseUrl + url, + timeout: 8000, + method, + data, + dataType: "json", // 微信官方文档中介绍会对数据进行一次JSON.parse + header, + success(res) { + // wx.hideLoading(); + // HTTP状态码为200才视为成功 + if (res.statusCode === 200) { + // 真正的数据响应体中还有一层success字段判断业务状态,按实际情况处理 + resolve(res.data) + // if (res.data.success) { + // resolve(res.data.result) + // } else { + // // 业务判断错误 + // reject(res) + // } + } else { + // wx.request的特性,只要有响应就会走success回调,所以在这里判断状态,非200的均视为请求失败 + reject(res) + } + }, + fail(err) { + // wx.hideLoading(); + // 断网、服务器挂了都会fail回调,直接reject即可 + reject(err) + } + }) + }) +} + +// 导出请求和服务地址 +export { + request, + baseUrl +} \ No newline at end of file diff --git a/utils/storage.js b/utils/storage.js new file mode 100644 index 0000000..faed3c7 --- /dev/null +++ b/utils/storage.js @@ -0,0 +1,75 @@ +/** + * 存储管理工具 + */ + +const STORAGE_PREFIX = 'aimz_'; + +// 获取完整的存储键名 +const getFullKey = (key) => { + return `${STORAGE_PREFIX}${key}`; +}; + +// 设置存储 +const set = (key, data) => { + try { + const fullKey = getFullKey(key); + wx.setStorageSync(fullKey, data); + return true; + } catch (error) { + console.error('Storage set error:', error); + return false; + } +}; + +// 获取存储 +const get = (key, defaultValue = null) => { + try { + const fullKey = getFullKey(key); + const value = wx.getStorageSync(fullKey); + return value || defaultValue; + } catch (error) { + console.error('Storage get error:', error); + return defaultValue; + } +}; + +// 移除存储 +const remove = (key) => { + try { + const fullKey = getFullKey(key); + wx.removeStorageSync(fullKey); + return true; + } catch (error) { + console.error('Storage remove error:', error); + return false; + } +}; + +// 清除所有存储 +const clear = () => { + try { + wx.clearStorageSync(); + return true; + } catch (error) { + console.error('Storage clear error:', error); + return false; + } +}; + +// 获取存储信息 +const info = () => { + try { + return wx.getStorageInfoSync(); + } catch (error) { + console.error('Storage info error:', error); + return null; + } +}; + +module.exports = { + set, + get, + remove, + clear, + info +}; \ No newline at end of file diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..0db9dc1 --- /dev/null +++ b/utils/util.js @@ -0,0 +1,118 @@ +const formatTime = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') +} + +/** + * + * @param {*} date + */ +const formatDate = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + + return [year, month, day].map(formatNumber).join('-') +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : '0' + n +} + +//随机生成暖色系 +const randomLightColor = () => { + // 暖色系的范围通常是红色和黄色较多,所以红色分量范围从 128 到 255 + let red = Math.floor(Math.random() * 128) + 128; + // 绿色分量范围从 64 到 255 + let green = Math.floor(Math.random() * 192) + 64; + // 蓝色分量范围从 0 到 128 + let blue = Math.floor(Math.random() * 128); + + // 将十进制的 RGB 分量转换为十六进制,并确保长度为 2 位 + let redHex = red.toString(16).padStart(2, '0'); + let greenHex = green.toString(16).padStart(2, '0'); + let blueHex = blue.toString(16).padStart(2, '0'); + + // 组合成十六进制颜色代码 + return '#' + redHex + greenHex + blueHex; +} +//随机生成冷色系 +const randomDarkColor = () => { + // 冷色系通常蓝色和绿色较多,所以蓝色分量范围从 128 到 255 + let blue = Math.floor(Math.random() * 128) + 128; + // 绿色分量范围从 128 到 255 + let green = Math.floor(Math.random() * 128) + 128; + // 红色分量范围从 0 到 128 + let red = Math.floor(Math.random() * 128); + + // 将十进制的 RGB 分量转换为十六进制,并确保长度为 2 位 + let redHex = red.toString(16).padStart(2, '0'); + let greenHex = green.toString(16).padStart(2, '0'); + let blueHex = blue.toString(16).padStart(2, '0'); + + // 组合成十六进制颜色代码 + return '#' + redHex + greenHex + blueHex; +} + +const randomRgbColor = () => { // 随机生成RGB颜色 + var r = Math.floor(Math.random() * 256); // 随机生成256以内r值 + var g = Math.floor(Math.random() * 256); // 随机生成256以内g值 + var b = Math.floor(Math.random() * 256); // 随机生成256以内b值 + return `rgb(${r},${g},${b})`; // 返回rgb(r,g,b)格式颜色 +} +const randomRgbaColor = () => { // 随机生成RGBA颜色 + var r = Math.floor(Math.random() * 256); // 随机生成256以内r值 + var g = Math.floor(Math.random() * 256); // 随机生成256以内g值 + var b = Math.floor(Math.random() * 256); // 随机生成256以内b值 + var alpha = Math.random(); // 随机生成1以内a值 + return `rgba(${r},${g},${b},${alpha})`; // 返回rgba(r,g,b,a)格式颜色 +} + +const formatRichText = (html) => { + let newContent = html.replace(/)*>/gi, function (match, capture) { + match = match.replace(/style="(^")+"/gi, '').replace(/style='(^')+'/gi, ''); + match = match.replace(/width="(^")+"/gi, '').replace(/width='(^')+'/gi, ''); + match = match.replace(/height="(^")+"/gi, '').replace(/height='(^')+'/gi, ''); + return match; + }); + newContent = newContent.replace(/style="(^")+"/gi, function (match, capture) { + match = match.replace(/width:(^;)+;/gi, 'max-width:100%;').replace(/width:(^;)+;/gi, 'max-width:100%;'); + return match; + }); + newContent = newContent.replace(/)*\/>/gi, ''); + newContent = newContent.replace(/\ { + // 匹配 标签 + let imgTags = richText.match(/]*>/g); + if (imgTags) { + imgTags.forEach((imgTag) => { + // 去除 style 属性 + let newImgTag = imgTag.replace(/ style="[^"]*"/g, ''); + richText = richText.replace(imgTag, newImgTag); + }); + } + return richText; +} +module.exports = { + formatTime: formatTime, + formatDate: formatDate, + randomRgb: randomRgbColor, + randomRgba: randomRgbaColor, + randomDark: randomDarkColor, + randomLight: randomLightColor, + formatHtml: formatRichText, + removeImgStyle: removeImgStyleFromRichText +} \ No newline at end of file diff --git a/utils/validator.js b/utils/validator.js new file mode 100644 index 0000000..b3adf66 --- /dev/null +++ b/utils/validator.js @@ -0,0 +1,43 @@ +// 手机号验证 +const isValidPhone = (phone) => { + return /^1[3-9]\d{9}$/.test(phone); +}; + +// 邮箱验证 +const isValidEmail = (email) => { + return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email); +}; + +// URL验证 +const isValidUrl = (url) => { + try { + new URL(url); + return true; + } catch { + return false; + } +}; + +// 身份证号验证 +const isValidIdCard = (idCard) => { + return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idCard); +}; + +// 企业统一社会信用代码验证 +const isValidCreditCode = (creditCode) => { + return /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/.test(creditCode); +}; + +// 密码强度验证(至少包含数字和字母,长度8-20位) +const isValidPassword = (password) => { + return /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,20}$/.test(password); +}; + +module.exports = { + isValidPhone, + isValidEmail, + isValidUrl, + isValidIdCard, + isValidCreditCode, + isValidPassword +}; \ No newline at end of file