init
|
@ -0,0 +1,63 @@
|
|||
<script>
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
import appUpdate from '@/components/appUpdate/appUpdate.js'
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
//console.log('App Launch')
|
||||
// #ifdef APP-PLUS
|
||||
let systemInfo = uni.getSystemInfoSync()
|
||||
const data={
|
||||
appid: systemInfo.appId,
|
||||
version: systemInfo.appVersion
|
||||
}
|
||||
console.log(data)
|
||||
//把appid和版本发送请求服务器,看服务器上是否有更新
|
||||
this.$api.checkVersion(data).then(res => {
|
||||
console.log(res)
|
||||
if(res.code==0){
|
||||
//如果返回0则表示有更新
|
||||
appUpdate(res)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
onShow: function() {
|
||||
// #ifdef MP-WEIXIN
|
||||
|
||||
// 当向小程序后台请求完新版本信息,会进行回调。res: {hasUpdate: true, version: 1.0.0}
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
if (res.hasUpdate) { // 有更新
|
||||
uni.showLoading({title:'更新中...'}); // 开始下载前,显示Loading
|
||||
}
|
||||
});
|
||||
// 当新版本下载完成,会进行回调
|
||||
updateManager.onUpdateReady(function () {
|
||||
uni.hideLoading(); // 关闭 Loading
|
||||
uni.showModal({ // 弹确认框(强制更新)
|
||||
title:'更新提示',
|
||||
content:'更新完毕,是否重启?',
|
||||
success:function (res) {
|
||||
if (res.confirm) {
|
||||
updateManager.applyUpdate(); // 强制小程序重启并使用新版本。
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
// 当新版本下载失败,会进行回调
|
||||
updateManager.onUpdateFailed(function () {
|
||||
uni.hideLoading(); // 关闭 Loading
|
||||
uni.showToast({ title:'更新失败,稍后再试...', icon:"error" });
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
onHide: function() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@/uni_modules/uview-ui/index.scss";
|
||||
</style>
|
|
@ -0,0 +1,37 @@
|
|||
import request from '@/utils/request'
|
||||
//使用说明
|
||||
// export const getList = data => request.get('/api/list', data, false)
|
||||
// 页面调用名 请求参数 请求类型 接口地址 loading是否显示
|
||||
/*页面中调用方法:(若无请求参数则留空,例:this.$api.getList())
|
||||
this.$api.getList(params).then(res => {
|
||||
|
||||
})
|
||||
*/
|
||||
//列表
|
||||
export const getList = data => request.get('/api/list', data)
|
||||
//登陆
|
||||
export const login = data => request.post('/api/login', data)
|
||||
//注册
|
||||
export const register = data => request.post('/api/register', data)
|
||||
//忘记密码
|
||||
export const forgetPassWord = data => request.post('/api/forgetPassWord', data)
|
||||
//登陆用户信息
|
||||
export const baseInfo = data => request.get('/api/baseinfo', data)
|
||||
//检测版本升级
|
||||
export const checkVersion = data => request.post('/api/checkVersion2', data,false)
|
||||
//文章详情
|
||||
export const detail = data => request.get('/api/detail', data,false)
|
||||
//获取单页内容
|
||||
export const page = data => request.get('/api/page', data)
|
||||
//提交实名认证资料
|
||||
export const auth = data => request.post('/api/auth', data)
|
||||
//修改密码
|
||||
export const password = data => request.post('/api/password', data)
|
||||
//注销帐号
|
||||
export const logout_account = data => request.post('/api/logout_account', data)
|
||||
//修改手机号
|
||||
export const phoneBind = data => request.get('/api/phoneBind', data)
|
||||
//修改邮箱
|
||||
export const emailBind = data => request.get('/api/emailBind', data)
|
||||
//提交反馈
|
||||
export const feedback = data => request.post('/api/feedback', data)
|
|
@ -0,0 +1,11 @@
|
|||
let BASE_URL
|
||||
//开发环境中
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// 开发环境
|
||||
BASE_URL = 'https://mock.apifox.cn/m1/3553664-0-default' //开发环境请求地址
|
||||
} else {
|
||||
// 生产环境
|
||||
BASE_URL = 'https://mock.apifox.cn/m1/3553664-0-default' //生成环境请求地址
|
||||
}
|
||||
|
||||
export default BASE_URL
|
|
@ -0,0 +1,790 @@
|
|||
export default function(updateInfo) {
|
||||
updateInfo.platform = updateInfo.platform ? updateInfo.platform : 'android'
|
||||
updateInfo.mainColor = updateInfo.mainColor ? updateInfo.mainColor : 'FF5B78'
|
||||
if (updateInfo.platform == 'android' || updateInfo.platform == 'ios') {
|
||||
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
let maskLayer = new plus.nativeObj.View('maskLayer', {
|
||||
top: '0px',
|
||||
left: '0px',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)'
|
||||
})
|
||||
let screenWidth = plus.screen.resolutionWidth
|
||||
let screenHeight = plus.screen.resolutionHeight
|
||||
const popupViewWidth = screenWidth * 0.7
|
||||
const viewContentPadding = 20
|
||||
const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2))
|
||||
const descriptionList = drawtext((updateInfo.updateContent || '发现新版本'), viewContentWidth)
|
||||
let popupViewHeight = 80 + 20 + 20 + 90 + 50
|
||||
let popupViewContentList = [{
|
||||
src: '/static/images/update.png',
|
||||
id: "logo",
|
||||
tag: "img",
|
||||
position: {
|
||||
top: "0px",
|
||||
left: (popupViewWidth - 124) / 2 + "px",
|
||||
width: "124px",
|
||||
height: "80px",
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'title',
|
||||
text: "发现新版本 " + (updateInfo.version || ''),
|
||||
textStyles: {
|
||||
size: '18px',
|
||||
color: "#333",
|
||||
weight: "bold",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: '90px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "30px",
|
||||
}
|
||||
}
|
||||
]
|
||||
const textHeight = 18
|
||||
let contentTop = 130
|
||||
descriptionList.forEach((item, index) => {
|
||||
if (index > 0) {
|
||||
popupViewHeight += textHeight;
|
||||
contentTop += textHeight;
|
||||
}
|
||||
popupViewContentList.push({
|
||||
tag: 'font',
|
||||
id: 'content' + index + 1,
|
||||
text: item.content,
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: "#666",
|
||||
lineSpacing: "50%",
|
||||
align: "left"
|
||||
},
|
||||
position: {
|
||||
top: contentTop + "px",
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: textHeight + "px",
|
||||
}
|
||||
});
|
||||
if (item.type == "break") {
|
||||
contentTop += 10;
|
||||
popupViewHeight += 10;
|
||||
}
|
||||
})
|
||||
if (updateInfo.force) {
|
||||
popupViewContentList.push({
|
||||
tag: 'rect', //绘制底边按钮
|
||||
rectStyles: {
|
||||
radius: "6px",
|
||||
color: updateInfo.mainColor
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "40px"
|
||||
}
|
||||
})
|
||||
popupViewContentList.push({
|
||||
tag: 'font',
|
||||
id: 'confirmText',
|
||||
text: "立即升级",
|
||||
textStyles: {
|
||||
size: '16px',
|
||||
color: "#FFF",
|
||||
lineSpacing: "0%",
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "40px"
|
||||
}
|
||||
})
|
||||
} else {
|
||||
popupViewContentList.push({
|
||||
tag: 'rect',
|
||||
id: 'cancelBox',
|
||||
rectStyles: {
|
||||
radius: "3px",
|
||||
borderColor: "#f1f1f1",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
})
|
||||
popupViewContentList.push({
|
||||
tag: 'rect',
|
||||
id: 'confirmBox',
|
||||
rectStyles: {
|
||||
radius: "3px",
|
||||
color: updateInfo.mainColor,
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
})
|
||||
popupViewContentList.push({
|
||||
tag: 'font',
|
||||
id: 'cancelText',
|
||||
text: "暂不升级",
|
||||
textStyles: {
|
||||
size: '16px',
|
||||
color: "#666",
|
||||
lineSpacing: "0%",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
})
|
||||
popupViewContentList.push({
|
||||
tag: 'font',
|
||||
id: 'confirmText',
|
||||
text: "立即升级",
|
||||
textStyles: {
|
||||
size: '16px',
|
||||
color: "#FFF",
|
||||
lineSpacing: "0%",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
})
|
||||
}
|
||||
let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
|
||||
tag: "rect",
|
||||
top: (screenHeight - popupViewHeight) / 2 + "px",
|
||||
left: '15%',
|
||||
height: popupViewHeight + "px",
|
||||
width: "70%"
|
||||
})
|
||||
popupView.drawRect({
|
||||
color: "#FFFFFF",
|
||||
radius: "8px"
|
||||
}, {
|
||||
top: "40px",
|
||||
height: popupViewHeight - 40 + "px",
|
||||
})
|
||||
popupView.draw(popupViewContentList)
|
||||
popupView.addEventListener("click", e => {
|
||||
let maxTop = popupViewHeight - viewContentPadding
|
||||
let maxLeft = popupViewWidth - viewContentPadding
|
||||
let buttonWidth = (viewContentWidth - viewContentPadding) / 2
|
||||
if (e.clientY > maxTop - 30 && e.clientY < maxTop) {
|
||||
if (updateInfo.force) {
|
||||
if (e.clientX > viewContentPadding && e.clientX < maxLeft) {
|
||||
maskLayer.hide()
|
||||
popupView.hide()
|
||||
let platform = updateInfo.platform || 'android'
|
||||
let downUrl = updateInfo.downUrl || ''
|
||||
download(updateInfo)
|
||||
}
|
||||
} else {
|
||||
let maxTop = popupViewHeight - viewContentPadding;
|
||||
let maxLeft = popupViewWidth - viewContentPadding;
|
||||
let buttonWidth = (viewContentWidth - viewContentPadding) / 2;
|
||||
if (e.clientY > maxTop - 30 && e.clientY < maxTop) {
|
||||
// 暂不升级
|
||||
if (e.clientX > viewContentPadding && e.clientX < maxLeft - buttonWidth -
|
||||
viewContentPadding) {
|
||||
maskLayer.hide()
|
||||
popupView.hide()
|
||||
}
|
||||
if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
|
||||
// 立即升级
|
||||
maskLayer.hide()
|
||||
popupView.hide()
|
||||
let platform = updateInfo.platform || 'android'
|
||||
let downUrl = updateInfo.downUrl || ''
|
||||
download(updateInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
// 点击遮罩层
|
||||
maskLayer.addEventListener("click", function() { //处理遮罩层点击
|
||||
// maskLayer.hide();
|
||||
// popupView.hide();
|
||||
})
|
||||
// 显示弹窗
|
||||
maskLayer.show()
|
||||
popupView.show()
|
||||
}
|
||||
|
||||
// 下载流程
|
||||
function download(updateInfo) {
|
||||
let platform = updateInfo.platform || 'android'
|
||||
if (updateInfo.downUrl) {
|
||||
if (platform == 'ios') {
|
||||
plus.runtime.openURL(updateInfo.downUrl)
|
||||
}
|
||||
if (platform == 'android') {
|
||||
getDownload(updateInfo)
|
||||
}
|
||||
} else {
|
||||
plus.nativeUI.alert('下载地址无效')
|
||||
}
|
||||
}
|
||||
|
||||
// 从服务器下载应用资源包(wgt文件)
|
||||
const getDownload = function(data) {
|
||||
let dtask
|
||||
let popupData = {
|
||||
progress: true,
|
||||
buttonNum: 2
|
||||
};
|
||||
if(data.force){
|
||||
popupData.buttonNum = 0
|
||||
}
|
||||
|
||||
let lastProgressValue = 0
|
||||
let popupObj = downloadPopup(popupData, data.mainColor)
|
||||
|
||||
dtask = plus.downloader.createDownload(data.downUrl, {
|
||||
filename: "_doc/update/"
|
||||
}, function(download, status) {
|
||||
if (status == 200) {
|
||||
popupObj.change({
|
||||
progressValue: 100,
|
||||
progressTip:"正在安装文件...",
|
||||
progress: true,
|
||||
buttonNum: 0
|
||||
})
|
||||
plus.runtime.install(download.filename, {}, function() {
|
||||
popupObj.change({
|
||||
contentText: "应用资源更新完成!",
|
||||
buttonNum: 1,
|
||||
progress: false
|
||||
});
|
||||
}, function(e) {
|
||||
popupObj.cancel()
|
||||
plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message);
|
||||
});
|
||||
} else {
|
||||
popupObj.change({
|
||||
contentText: "文件下载失败...",
|
||||
buttonNum: 1,
|
||||
progress: false
|
||||
});
|
||||
}
|
||||
});
|
||||
dtask.start()
|
||||
dtask.addEventListener("statechanged", function(task, status) {
|
||||
switch (task.state) {
|
||||
case 1: // 开始
|
||||
popupObj.change({
|
||||
progressValue:0,
|
||||
progressTip:"准备下载...",
|
||||
progress: true
|
||||
});
|
||||
break;
|
||||
case 2: // 已连接到服务器
|
||||
popupObj.change({
|
||||
progressValue:0,
|
||||
progressTip:"开始下载...",
|
||||
progress: true
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
const progress = parseInt(task.downloadedSize / task.totalSize * 100);
|
||||
if(progress - lastProgressValue >= 2){
|
||||
lastProgressValue = progress;
|
||||
popupObj.change({
|
||||
progressValue:progress,
|
||||
progressTip: "已下载" + progress + "%",
|
||||
progress: true
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
// 取消下载
|
||||
popupObj.cancelDownload = function(){
|
||||
dtask && dtask.abort()
|
||||
uni.showToast({
|
||||
title: "已取消下载",
|
||||
icon:"none"
|
||||
});
|
||||
}
|
||||
// 重启APP
|
||||
popupObj.reboot = function(){
|
||||
plus.runtime.restart()
|
||||
}
|
||||
}
|
||||
|
||||
// 文件下载的弹窗绘图
|
||||
function downloadPopupDrawing(data, mainColor){
|
||||
// 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
|
||||
const screenWidth = plus.screen.resolutionWidth;
|
||||
const screenHeight = plus.screen.resolutionHeight;
|
||||
//弹窗容器宽度
|
||||
const popupViewWidth = screenWidth * 0.7;
|
||||
|
||||
// 弹窗容器的Padding
|
||||
const viewContentPadding = 20;
|
||||
// 弹窗容器的宽度
|
||||
const viewContentWidth = popupViewWidth - (viewContentPadding * 2);
|
||||
// 弹窗容器高度
|
||||
let popupViewHeight = viewContentPadding * 3 + 60;
|
||||
let progressTip = data.progressTip || "准备下载...";
|
||||
let contentText = data.contentText || "正在为您更新,请耐心等待";
|
||||
|
||||
let elementList = [
|
||||
{
|
||||
tag: 'rect', //背景色
|
||||
color: '#FFFFFF',
|
||||
rectStyles:{
|
||||
radius: "8px"
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'title',
|
||||
text: "升级APP",
|
||||
textStyles: {
|
||||
size: '16px',
|
||||
color: "#333",
|
||||
weight: "bold",
|
||||
verticalAlign: "middle",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: viewContentPadding + 'px',
|
||||
height: "30px",
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'content',
|
||||
text: contentText,
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: "#333",
|
||||
verticalAlign: "middle",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: viewContentPadding * 2 + 30 + 'px',
|
||||
height: "20px",
|
||||
}
|
||||
}
|
||||
];
|
||||
// 是否有进度条
|
||||
|
||||
if(data.progress){
|
||||
popupViewHeight += viewContentPadding + 40
|
||||
elementList = elementList.concat([
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'progressValue',
|
||||
text: progressTip,
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: mainColor,
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: viewContentPadding * 4 + 20 + 'px',
|
||||
height: "30px"
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'rect', //绘制进度条背景
|
||||
id: 'progressBg',
|
||||
rectStyles:{
|
||||
radius: "4px",
|
||||
borderColor: "#f1f1f1",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
position:{
|
||||
top: viewContentPadding * 4 + 60 + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "8px"
|
||||
}
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
if (data.buttonNum == 2) {
|
||||
popupViewHeight += viewContentPadding + 30;
|
||||
elementList = elementList.concat([
|
||||
{
|
||||
tag: 'rect', //绘制底边按钮
|
||||
rectStyles:{
|
||||
radius: "3px",
|
||||
borderColor: "#f1f1f1",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
position:{
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px"
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'rect', //绘制底边按钮
|
||||
rectStyles:{
|
||||
radius: "3px",
|
||||
color: mainColor
|
||||
},
|
||||
position:{
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px"
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'cancelText',
|
||||
text: "取消下载",
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: "#666",
|
||||
lineSpacing: "0%",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'confirmText',
|
||||
text: "后台下载",
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: "#FFF",
|
||||
lineSpacing: "0%",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
|
||||
width: (viewContentWidth - viewContentPadding) / 2 + "px",
|
||||
height: "40px",
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
if (data.buttonNum == 1) {
|
||||
popupViewHeight += viewContentPadding + 40;
|
||||
elementList = elementList.concat([
|
||||
{
|
||||
tag: 'rect', //绘制底边按钮
|
||||
rectStyles:{
|
||||
radius: "6px",
|
||||
color: $mainColor
|
||||
},
|
||||
position:{
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "40px"
|
||||
}
|
||||
},
|
||||
{
|
||||
tag: 'font',
|
||||
id: 'confirmText',
|
||||
text: "关闭",
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: "#FFF",
|
||||
lineSpacing: "0%",
|
||||
},
|
||||
position: {
|
||||
bottom: viewContentPadding + 'px',
|
||||
left: viewContentPadding + "px",
|
||||
width: viewContentWidth + "px",
|
||||
height: "40px"
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
return {
|
||||
popupViewHeight:popupViewHeight,
|
||||
popupViewWidth:popupViewWidth,
|
||||
screenHeight:screenHeight,
|
||||
viewContentWidth:viewContentWidth,
|
||||
viewContentPadding:viewContentPadding,
|
||||
elementList: elementList
|
||||
};
|
||||
}
|
||||
// 文件下载的弹窗
|
||||
function downloadPopup(data, mainColor) {
|
||||
|
||||
// 弹窗遮罩层
|
||||
let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
|
||||
top: '0px',
|
||||
left: '0px',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)'
|
||||
});
|
||||
|
||||
let popupViewData = downloadPopupDrawing(data, mainColor);
|
||||
|
||||
// 弹窗内容
|
||||
let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
|
||||
tag: "rect",
|
||||
top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
|
||||
left: '15%',
|
||||
height: popupViewData.popupViewHeight + "px",
|
||||
width: "70%",
|
||||
});
|
||||
let progressValue = 0;
|
||||
let progressTip = 0;
|
||||
let contentText = 0;
|
||||
let buttonNum = 2;
|
||||
if(data.buttonNum >= 0){
|
||||
buttonNum = data.buttonNum;
|
||||
}
|
||||
popupView.draw(popupViewData.elementList);
|
||||
let callbackData = {
|
||||
change: function(res) {
|
||||
let progressElement = [];
|
||||
if(res.progressValue){
|
||||
progressValue = res.progressValue;
|
||||
// 绘制进度条
|
||||
progressElement.push({
|
||||
tag: 'rect', //绘制进度条背景
|
||||
id: 'progressValueBg',
|
||||
rectStyles:{
|
||||
radius: "4px",
|
||||
color: mainColor
|
||||
},
|
||||
position:{
|
||||
top: popupViewData.viewContentPadding * 4 + 60 + 'px',
|
||||
left: popupViewData.viewContentPadding + "px",
|
||||
width: popupViewData.viewContentWidth * (res.progressValue / 100) + "px",
|
||||
height: "8px"
|
||||
}
|
||||
});
|
||||
}
|
||||
if(res.progressTip){
|
||||
progressTip = res.progressTip;
|
||||
progressElement.push({
|
||||
tag: 'font',
|
||||
id: 'progressValue',
|
||||
text: res.progressTip,
|
||||
textStyles: {
|
||||
size: '14px',
|
||||
color: mainColor,
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: popupViewData.viewContentPadding * 4 + 20 + 'px',
|
||||
height: "30px"
|
||||
}
|
||||
});
|
||||
}
|
||||
if(res.contentText){
|
||||
contentText = res.contentText;
|
||||
progressElement.push({
|
||||
tag: 'font',
|
||||
id: 'content',
|
||||
text: res.contentText,
|
||||
textStyles: {
|
||||
size: '16px',
|
||||
color: "#333",
|
||||
whiteSpace: "normal"
|
||||
},
|
||||
position: {
|
||||
top: popupViewData.viewContentPadding * 2 + 30 + 'px',
|
||||
height: "30px",
|
||||
}
|
||||
});
|
||||
}
|
||||
if(res.buttonNum >= 0 && buttonNum != res.buttonNum){
|
||||
buttonNum = res.buttonNum;
|
||||
popupView.reset();
|
||||
popupViewData = downloadPopupDrawing(Object.assign({
|
||||
progressValue:progressValue,
|
||||
progressTip:progressTip,
|
||||
contentText:contentText,
|
||||
},res));
|
||||
let newElement = [];
|
||||
popupViewData.elementList.map((item,index) => {
|
||||
let have = false;
|
||||
progressElement.forEach((childItem,childIndex) => {
|
||||
if(item.id == childItem.id){
|
||||
have = true;
|
||||
}
|
||||
});
|
||||
if(!have){
|
||||
newElement.push(item);
|
||||
}
|
||||
});
|
||||
progressElement = newElement.concat(progressElement);
|
||||
popupView.setStyle({
|
||||
tag: "rect",
|
||||
top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
|
||||
left: '15%',
|
||||
height: popupViewData.popupViewHeight + "px",
|
||||
width: "70%",
|
||||
});
|
||||
popupView.draw(progressElement);
|
||||
}else{
|
||||
popupView.draw(progressElement);
|
||||
}
|
||||
},
|
||||
cancel: function() {
|
||||
maskLayer.hide();
|
||||
popupView.hide();
|
||||
}
|
||||
}
|
||||
popupView.addEventListener("click", function(e) {
|
||||
let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding;
|
||||
let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding;
|
||||
if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
|
||||
if(buttonNum == 1){
|
||||
// 单按钮
|
||||
if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft) {
|
||||
maskLayer.hide();
|
||||
popupView.hide();
|
||||
callbackData.reboot();
|
||||
}
|
||||
}else if(buttonNum == 2){
|
||||
// 双按钮
|
||||
let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2;
|
||||
if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft - buttonWidth - popupViewData.viewContentPadding) {
|
||||
maskLayer.hide();
|
||||
popupView.hide();
|
||||
callbackData.cancelDownload();
|
||||
} else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
|
||||
maskLayer.hide();
|
||||
popupView.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 显示弹窗
|
||||
maskLayer.show();
|
||||
popupView.show();
|
||||
// 改变进度条
|
||||
return callbackData
|
||||
}
|
||||
|
||||
// 文字换行
|
||||
function drawtext(text, maxWidth) {
|
||||
let textArr = text.split("");
|
||||
let len = textArr.length;
|
||||
// 上个节点
|
||||
let previousNode = 0;
|
||||
// 记录节点宽度
|
||||
let nodeWidth = 0;
|
||||
// 文本换行数组
|
||||
let rowText = [];
|
||||
// 如果是字母,侧保存长度
|
||||
let letterWidth = 0;
|
||||
// 汉字宽度
|
||||
let chineseWidth = 14;
|
||||
// otherFont宽度
|
||||
let otherWidth = 7;
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(textArr[i])) {
|
||||
if (letterWidth > 0) {
|
||||
if (nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth) {
|
||||
rowText.push({
|
||||
type: "text",
|
||||
content: text.substring(previousNode, i)
|
||||
});
|
||||
previousNode = i
|
||||
nodeWidth = chineseWidth
|
||||
letterWidth = 0
|
||||
} else {
|
||||
nodeWidth += chineseWidth + letterWidth * otherWidth
|
||||
letterWidth = 0
|
||||
}
|
||||
} else {
|
||||
if (nodeWidth + chineseWidth > maxWidth) {
|
||||
rowText.push({
|
||||
type: "text",
|
||||
content: text.substring(previousNode, i)
|
||||
})
|
||||
previousNode = i
|
||||
nodeWidth = chineseWidth
|
||||
} else {
|
||||
nodeWidth += chineseWidth
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (/\n/g.test(textArr[i])) {
|
||||
rowText.push({
|
||||
type: "break",
|
||||
content: text.substring(previousNode, i)
|
||||
})
|
||||
previousNode = i + 1
|
||||
nodeWidth = 0
|
||||
letterWidth = 0
|
||||
} else if (textArr[i] == "\\" && textArr[i + 1] == "n") {
|
||||
rowText.push({
|
||||
type: "break",
|
||||
content: text.substring(previousNode, i)
|
||||
})
|
||||
previousNode = i + 2
|
||||
nodeWidth = 0
|
||||
letterWidth = 0
|
||||
} else if (/[a-zA-Z0-9]/g.test(textArr[i])) {
|
||||
letterWidth += 1;
|
||||
if (nodeWidth + letterWidth * otherWidth > maxWidth) {
|
||||
rowText.push({
|
||||
type: "text",
|
||||
content: text.substring(previousNode, i + 1 - letterWidth)
|
||||
})
|
||||
previousNode = i + 1 - letterWidth
|
||||
nodeWidth = letterWidth * otherWidth
|
||||
letterWidth = 0
|
||||
}
|
||||
} else {
|
||||
if (nodeWidth + otherWidth > maxWidth) {
|
||||
rowText.push({
|
||||
type: "text",
|
||||
content: text.substring(previousNode, i)
|
||||
});
|
||||
previousNode = i
|
||||
nodeWidth = otherWidth
|
||||
} else {
|
||||
nodeWidth += otherWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (previousNode < len) {
|
||||
rowText.push({
|
||||
type: "text",
|
||||
content: text.substring(previousNode, len)
|
||||
})
|
||||
}
|
||||
return rowText
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<template>
|
||||
<view>
|
||||
<view class="box">
|
||||
<view class="title">{{ currentYear }}年 {{ currentMonth }}月</view>
|
||||
<scroll-view scroll-x="true">
|
||||
<block v-for="(item, index) in dayList" :key="index">
|
||||
<view
|
||||
class="dayTitle"
|
||||
:class="current == index ? 'select' : ''"
|
||||
@click="timeSelectd(index)"
|
||||
>
|
||||
<view
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
"
|
||||
>
|
||||
<view class="day">{{ item.day }}</view>
|
||||
<view v-if="index == 0" style="font-size: 25rpx">今天</view>
|
||||
<view v-else style="font-size: 25rpx">周{{ item.week }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import common from "@/utils/common.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentYear: new Date().getFullYear(), // 当前年份
|
||||
currentMonth: new Date().getMonth() + 1, // 当前月份(0-11需+1)
|
||||
isShow: false,
|
||||
current: 0,
|
||||
dayList: [],
|
||||
xzTime: common.GetNowTime(new Date()),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.dayList = common.weekDate().dayList;
|
||||
const firstDay = this.dayList[0];
|
||||
this.currentYear = firstDay.year;
|
||||
this.currentMonth = firstDay.month; // 假设 dayList 中的月份已处理补零
|
||||
},
|
||||
methods: {
|
||||
// 日期选择
|
||||
timeSelectd(index) {
|
||||
this.current = index;
|
||||
let date =
|
||||
this.dayList[index].year +
|
||||
"-" +
|
||||
this.dayList[index].month +
|
||||
"-" +
|
||||
this.dayList[index].day;
|
||||
date = common.GetNowTime(new Date(date));
|
||||
this.xzTime = date;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.box {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
scroll-view {
|
||||
padding: 20rpx 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.title {
|
||||
font-weight: 800;
|
||||
font-size: 70rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.dayTitle {
|
||||
margin-left: 20rpx;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
width: 124rpx;
|
||||
height: 124rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 25rpx;
|
||||
border: 1rpx solid #4689fe;
|
||||
|
||||
.day {
|
||||
font-weight: normal;
|
||||
font-size: 34rpx;
|
||||
color: #4473fe;
|
||||
}
|
||||
}
|
||||
|
||||
.dayTitle:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.select {
|
||||
font-weight: bold;
|
||||
font-size: 34rpx;
|
||||
color: #ffffff;
|
||||
background: #4473fe;
|
||||
border-radius: 25rpx;
|
||||
border: 1rpx solid #4473fe;
|
||||
.day {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
let config = {
|
||||
//不拦截页面路径
|
||||
whiteList: [
|
||||
'/pages/public/login',
|
||||
'/pages/public/forget_password',
|
||||
'/pages/public/register',
|
||||
'/pages/index/index',
|
||||
'/pages/index/list',
|
||||
'/pages/subPack/index/detail',
|
||||
//一行一个
|
||||
],
|
||||
token : 'token', //本地存储token的变量名
|
||||
login_page : '/pages/public/login', //拦截后跳转的登陆页路径
|
||||
vconsole_status: 0, //是否启用调试工具,1为启用,0不启用
|
||||
}
|
||||
export default config
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
import App from './App'
|
||||
import '@/utils/interceptor.js';//引入拦截
|
||||
|
||||
import Vue from 'vue'
|
||||
import uView from '@/uni_modules/uview-ui'
|
||||
Vue.use(uView)
|
||||
|
||||
import store from './store'
|
||||
|
||||
// 注册请求方法
|
||||
import * as api from '@/api/api.js'
|
||||
Vue.prototype.$api = api
|
||||
|
||||
|
||||
import BASE_URL from '@/api/env.js' //引入接口共用地址
|
||||
Vue.prototype.$API_BASE_URL= BASE_URL
|
||||
|
||||
import config from '@/config/config.js';
|
||||
Vue.prototype.$systemConfig = config
|
||||
|
||||
let vuexStore = require("@/store/$u.mixin.js");
|
||||
Vue.mixin(vuexStore);
|
||||
|
||||
//是否启用调试工具
|
||||
if(config.vconsole_status){
|
||||
const vconsole = require('vconsole')
|
||||
Vue.prototype.$vconsole = new vconsole() // 使用vconsole
|
||||
}
|
||||
|
||||
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
store,
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
|
||||
// #ifdef VUE3
|
||||
import { createSSRApp } from 'vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"name" : "巡检保洁",
|
||||
"appid" : "",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"Camera" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PRIVILEGED\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"geolocation" : {
|
||||
"system" : {
|
||||
"__platform__" : [ "ios" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"splashscreen" : {
|
||||
"androidStyle" : "default"
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"postcss" : true,
|
||||
"minified" : true
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
}
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "2"
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"id": "liuyan814-unitempate",
|
||||
"name": "巡检保洁",
|
||||
"displayName": "巡检保洁",
|
||||
"version": "1.0.6",
|
||||
"description": "快速搭建uni-app项目,封装request,带页面拦截器,请求锁,带请求loading,集成uview,集成在线更新组件、集成调试工具vconsole,分包。",
|
||||
"keywords": [
|
||||
"封装request",
|
||||
"页面拦截器",
|
||||
"uview",
|
||||
"图鸟UI",
|
||||
"在线更新"
|
||||
],
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"uni-app前端模板",
|
||||
"前端页面模板"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
// 如果您是通过uni_modules形式引入uView,可以忽略此配置
|
||||
"easycom": {
|
||||
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "保洁点位"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/cleanDetails",
|
||||
"style": {
|
||||
"navigationStyle": "custom" ,
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "保洁详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/cleanPlan",
|
||||
"style": {
|
||||
"navigationStyle": "custom" ,
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "保洁计划"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/planList",
|
||||
"style": {
|
||||
"navigationStyle": "custom" ,
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "计划列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationBarBackgroundColor": "#4790FF",
|
||||
"navigationBarTextStyle": "white",
|
||||
"enablePullDownRefresh": true
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/public/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/profile",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "个人信息",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/setting",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "设置",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/password",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "修改密码",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/index",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "帐号&安全",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/about/index",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "关于我们",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/phone",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "手机号绑定",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/email",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "邮箱绑定",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/account/logout_account",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "注销帐号",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/auth",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "实名认证",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/public/page",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/about/feedback",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "意见反馈",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/public/register",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "注册",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/public/forget_password",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "忘记密码",
|
||||
"enablePullDownRefresh" : false
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
//分包加载配置,此配置为小程序的分包加载机制。
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages/subPack", //子包的根目录
|
||||
"pages": [
|
||||
{
|
||||
"path": "index/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "详情"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "#211D2F",
|
||||
"navigationBarTitleText": "uni-app",
|
||||
"navigationBarBackgroundColor": "white",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#2D2D2D",
|
||||
"selectedColor": "#4183F8",
|
||||
"borderStyle": "white",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/tab/home.png",
|
||||
"selectedIconPath": "static/tab/home_cur.png",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/index/list",
|
||||
"iconPath": "static/tab/list.png",
|
||||
"selectedIconPath": "static/tab/list_cur.png",
|
||||
"text": "计划"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/my/index",
|
||||
"iconPath": "static/tab/my.png",
|
||||
"selectedIconPath": "static/tab/my_cur.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// 分包预载配置
|
||||
"preloadRule": {
|
||||
// 当我们进入了pages/index/index页面以后就会预下载pages/subPack分包
|
||||
"pages/index/index": {
|
||||
"network": "all", //在指定网络下预下载,可选值为:all(不限网络)、wifi(仅wifi下预下载)
|
||||
"packages": ["pages/subPack"] //进入页面后预下载分包
|
||||
}
|
||||
},
|
||||
"uniIdRouter": {}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="custom-card">
|
||||
<view class="card-header">
|
||||
<view class="header-left">
|
||||
<u-tag :text="item.goods_type" type="success" shape="circleRight"/>
|
||||
<view class="header-title"></view>
|
||||
</view>
|
||||
<view class="header-right">
|
||||
<u-tag text="待服务" shape="circleLeft" type="primary" v-if="item.type==1"/>
|
||||
<u-tag text="服务中" shape="circleLeft" type="info" v-if="item.type==2"/>
|
||||
<u-tag text="待验收" shape="circleLeft" type="warning" v-if="item.type==3"/>
|
||||
<u-tag text="问题单" shape="circleLeft" type="error" v-if="item.type==4"/>
|
||||
<u-tag text="已完成" shape="circleLeft" type="success" v-if="item.type==5"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-body" @click="detail(item.id)">
|
||||
<u-alert-tips type="warning" :description="item.remark" v-if="item.remark"></u-alert-tips>
|
||||
|
||||
<view class="tags">
|
||||
<u-tag text="加急" type="error" mode="dark" v-if="item.urgent==1"/>
|
||||
<u-tag text="设备在家" type="primary" mode="light" v-if="item.have_device==1"/>
|
||||
<u-tag text="设备不在家" type="primary" mode="light" v-if="item.have_device==0"/>
|
||||
<u-tag text="收费" type="warning" mode="light" v-if="item.charge==1"/>
|
||||
<u-tag text="不收费" type="warning" mode="light" v-if="item.charge==0"/>
|
||||
<u-tag text="签约单" type="success" mode="light" v-if="item.sign_order==1"/>
|
||||
</view>
|
||||
|
||||
<view class="section-title">基本信息:</view>
|
||||
<view class="card-body-item">
|
||||
<view class="item-title">订单编号:</view>
|
||||
<view class="item-content">{{item.order_sn}}</view>
|
||||
</view>
|
||||
|
||||
<view class="section-title">派单信息:</view>
|
||||
|
||||
<view class="card-body-item">
|
||||
<view class="item-title">派单时间:</view>
|
||||
<view class="item-content">{{item.dispatch_time}}</view>
|
||||
</view>
|
||||
|
||||
<view class="card-body-item">
|
||||
<view class="item-title">安装师傅:</view>
|
||||
<view class="item-content">{{item.master_name}}</view>
|
||||
</view>
|
||||
|
||||
<view class="card-body-item">
|
||||
<view class="item-title">师傅电话:</view>
|
||||
<view class="item-content">{{item.master_tel}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
item : []
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
this.id = op.id
|
||||
this.getDetail()
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
getDetail(){
|
||||
const data = {
|
||||
advance_id : this.id
|
||||
}
|
||||
this.$api.advanceDetail(data).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.item = res.data
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
page{background: #f2f2f2;}
|
||||
.content{padding: 20rpx;}
|
||||
.custom-card {
|
||||
background-color: #fff;
|
||||
border: 1px solid #f2f2f2;
|
||||
border-radius: 4px;
|
||||
padding: 8px 0;
|
||||
margin-top: 15rpx;
|
||||
.card-header {
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
padding-bottom: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.header-left{
|
||||
display: flex;
|
||||
.header-title{
|
||||
color:#333;
|
||||
font-weight: bold;
|
||||
margin-top: 3rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
.header-right{
|
||||
.date{font-size: 26rpx;color:#999;font-weight: normal;margin-right: 15rpx;margin-top: 5rpx;}
|
||||
}
|
||||
}
|
||||
.card-body{
|
||||
padding: 20rpx;
|
||||
.section-title{font-weight: bold; margin-top: 20rpx;}
|
||||
.card-body-item{
|
||||
display: flex;
|
||||
line-height: 80rpx;
|
||||
border-bottom: 1px solid #efefef;
|
||||
.item-title{color:#A9A9A9}
|
||||
.item-content{
|
||||
flex:1;
|
||||
color:#666;
|
||||
.goods_list{display: flex;line-height: 60rpx;
|
||||
.install{width: 60%;}
|
||||
.price{width: 20%;}
|
||||
.master_money{width: 20%;}
|
||||
}
|
||||
.photo_list{ display: flex;}
|
||||
.photo_list image{width:80rpx;height:100rpx; margin-top: 10rpx; margin-left: 10rpx;}
|
||||
}
|
||||
.item-right{margin-right: 8rpx;}
|
||||
}
|
||||
.tags{
|
||||
margin-top: 10rpx;
|
||||
line-height:60rpx;
|
||||
.u-tag{margin-right: 15rpx;}
|
||||
}
|
||||
.fee{
|
||||
background: #F9F9F9;
|
||||
padding:20rpx;
|
||||
display: flex;
|
||||
.fee-item{width: 50%;text-align: center;
|
||||
.fee-item-title{
|
||||
color: #A9A9A9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-footer {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,205 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm">
|
||||
<u-form-item label="标识号:" prop="login_code" label-width="170">
|
||||
<u-input placeholder="请输入标识号,若不知,请联系所属公司" v-model="form.login_code" />
|
||||
</u-form-item>
|
||||
<u-form-item label="真实姓名:" label-width="170" prop="name">
|
||||
<u-input placeholder="请输入真实姓名" v-model="form.name" />
|
||||
</u-form-item>
|
||||
<u-form-item label="手机号:" label-width="170" prop="phone">
|
||||
<u-input placeholder="请输入输入手机号码" v-model="form.phone" />
|
||||
</u-form-item>
|
||||
<u-form-item label="登陆密码:" label-width="170" prop="password">
|
||||
<u-input placeholder="请输入登陆密码" v-model="form.password" />
|
||||
</u-form-item>
|
||||
<u-form-item label="身份证号:" label-width="170" prop="cardno">
|
||||
<u-input placeholder="请输入身份证号码" v-model="form.cardno" />
|
||||
</u-form-item>
|
||||
<u-form-item label="身份证正反面:" label-width="190">
|
||||
<u-upload upload-text="选择或拍照" width="180" height="180" ref="uUpload" :action="action" :fileList="fileList" :form-data="form_data" ></u-upload>
|
||||
</u-form-item>
|
||||
|
||||
<view class="agreement">
|
||||
<u-checkbox size="40rpx" v-model="check" @change="checkboxChange"></u-checkbox>
|
||||
<view class="agreement-text">
|
||||
我已知晓并同意 <text @click="showPopup(4)" style="color:cornflowerblue">《用户服务协议》</text>及<text @click="showPopup(5)" style="color:cornflowerblue">《隐私政策》</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="submit_con">
|
||||
<u-button type="primary" @click="submit">提交注册</u-button>
|
||||
</view>
|
||||
</u-form>
|
||||
|
||||
<u-popup v-model="popupVisible" mode="bottom" length="60%">
|
||||
<view class="popup-content">
|
||||
<rich-text :nodes="protocolsContent" style="line-height: 50rpx;"></rich-text>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
|
||||
<u-button class="close_pop" size="medium" type="primary" @click="hidePopup">关闭</u-button>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync,getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
action: this.$api_url + '/api/index/upload_cos',
|
||||
fileList:[],
|
||||
popupVisible: false,
|
||||
protocolsContent: "",
|
||||
check: false,
|
||||
agreement: false,
|
||||
form: {
|
||||
login_code: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
cardno: '',
|
||||
photo:'',
|
||||
password:''
|
||||
},
|
||||
form_data : {
|
||||
floder : 'photo'
|
||||
},
|
||||
rules: {
|
||||
login_code: [
|
||||
{
|
||||
required: true,
|
||||
type:"number",
|
||||
message: '请输入标识号',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入真实姓名',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{
|
||||
required: true,
|
||||
type:"number",
|
||||
message: '请输入登陆手机号',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
cardno: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入身份证号码',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
onReady(){
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkboxChange(e) {
|
||||
this.agreement = e.value;
|
||||
},
|
||||
showPopup(id) {
|
||||
this.popupVisible = true;
|
||||
const params ={id:id}
|
||||
this.$api.page(params).then(res => {
|
||||
this.protocolsContent = res.data.content
|
||||
})
|
||||
},
|
||||
hidePopup() {
|
||||
this.popupVisible = false;
|
||||
},
|
||||
submit() {
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
if(!this.agreement) return toast('请查看并同意相关协议');
|
||||
//获取上传列表
|
||||
let _uploadPhoto_data = {}
|
||||
var _list = this.$refs.uUpload.lists
|
||||
|
||||
for (let i = 0; i < _list.length; i++) {
|
||||
_uploadPhoto_data[i] = {
|
||||
url: _list[i].response.data.file
|
||||
}
|
||||
}
|
||||
|
||||
if(Object.keys(_uploadPhoto_data).length ==0 ){
|
||||
toast('必须上传身份证正反面')
|
||||
return
|
||||
}
|
||||
|
||||
this.form.photo = JSON.stringify(_uploadPhoto_data)
|
||||
this.$api.register(this.form).then(res => {
|
||||
if(res.code==0){
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},1500)
|
||||
|
||||
console.log(res);
|
||||
}else{
|
||||
toast(res.msg)
|
||||
console.log(res);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.popup-content {
|
||||
padding: 40rpx;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.content{padding:30rpx}
|
||||
.agreement {
|
||||
display: flex;
|
||||
margin: 40rpx 0 0 10rpx;
|
||||
|
||||
.agreement-text {
|
||||
padding-left: 0rpx;
|
||||
color: $u-tips-color;
|
||||
}
|
||||
}
|
||||
.submit_con{margin-top: 20rpx;}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-navbar title="保洁详情"></u-navbar>
|
||||
<view class="area-info">
|
||||
<view class="name">保洁区域名称</view>
|
||||
<view class="position">所在区域:学校操场</view>
|
||||
</view>
|
||||
<view class="area-details">
|
||||
<view class="title">区域详情</view>
|
||||
<view class="details">
|
||||
<view class="block">
|
||||
<view class="value">室内/室外</view>
|
||||
<view class="label">区域类型</view>
|
||||
</view>
|
||||
<view class="block">
|
||||
<view class="value">保洁员1号</view>
|
||||
<view class="label">保洁人员</view>
|
||||
</view>
|
||||
<view class="block">
|
||||
<view class="value">2024/1/27 9:53:35</view>
|
||||
<view class="label">清扫时间</view>
|
||||
</view>
|
||||
<view class="block">
|
||||
<view class="value">清扫完成</view>
|
||||
<view class="label">备注</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="title">保洁区域图片</view>
|
||||
<view class="images">
|
||||
<u-image
|
||||
class="image"
|
||||
v-for="(v, i) in 7"
|
||||
:key="i"
|
||||
width="212rpx"
|
||||
height="212rpx"
|
||||
src="https://cdn.uviewui.com/uview/example/fade.jpg"
|
||||
></u-image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: 100vh;
|
||||
background: linear-gradient(#fff 0%, #e0ebf9 20%);
|
||||
.title {
|
||||
line-height: 1;
|
||||
border-left: 10rpx solid #5a7ee9;
|
||||
padding-left: 16rpx;
|
||||
font-weight: bold;
|
||||
font-size: 36rpx;
|
||||
color: #000000;
|
||||
}
|
||||
.area-info {
|
||||
padding: 44rpx;
|
||||
margin-top: 30rpx;
|
||||
height: 290rpx;
|
||||
background: url("@/static/images/area-bg.png") no-repeat 100% 100%;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.name {
|
||||
font-weight: bold;
|
||||
font-size: 56rpx;
|
||||
color: #211d2f;
|
||||
}
|
||||
.position {
|
||||
margin-top: 44rpx;
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #717b94;
|
||||
}
|
||||
}
|
||||
.area-details {
|
||||
padding: 50rpx 32rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 36rpx 36rpx 0 0;
|
||||
min-height: calc(100vh - 400rpx);
|
||||
.details {
|
||||
margin-top: 42rpx;
|
||||
margin-bottom: 70rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
.block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 48.5%;
|
||||
height: 160rpx;
|
||||
background: #f1f7fe;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.block:nth-child(n + 3) {
|
||||
margin-top: 14rpx;
|
||||
}
|
||||
}
|
||||
.images {
|
||||
margin-top: 46rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 212rpx);
|
||||
gap: 20rpx; // 图片间距
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,224 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
title=""
|
||||
:background="{ backgroundColor: '#DFEEFD' }"
|
||||
:border-bottom="false"
|
||||
>
|
||||
<view class="slot-wrap">
|
||||
<u-dropdown :title-size="42" active-color="#211D2F">
|
||||
<u-dropdown-item
|
||||
v-model="dropdownValue"
|
||||
title="保洁计划"
|
||||
:options="dropdownOptions"
|
||||
></u-dropdown-item>
|
||||
</u-dropdown>
|
||||
</view>
|
||||
</u-navbar>
|
||||
<view class="area-info">
|
||||
<view class="name">2024年11月21号</view>
|
||||
<view class="position"> 08:30~11:30</view>
|
||||
<view class="tabs">
|
||||
<view
|
||||
@click="changeTab(i)"
|
||||
class="tab-item"
|
||||
v-for="(v, i) in selectTabs"
|
||||
:key="i"
|
||||
:class="{ select: selectIdx === i }"
|
||||
>
|
||||
{{ v.name }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="arealist">
|
||||
<view class="block-info">
|
||||
<view class="schedule">待保洁</view>
|
||||
<view class="name">
|
||||
<u-icon size="40" :name="posIcon"></u-icon>
|
||||
<view class="text">东大门北侧_门2</view>
|
||||
</view>
|
||||
<view class="type">
|
||||
<view class="value">区域类型</view>
|
||||
<u-tag
|
||||
text="室外"
|
||||
class="tag"
|
||||
border-color="transparent"
|
||||
type="success"
|
||||
/>
|
||||
<u-tag text="特殊" border-color="transparent" type="warning" />
|
||||
</view>
|
||||
<view class="illustrate">
|
||||
{{ "需要清理整个户外通道/保持跑道整洁花坛边落叶清扫" }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
posIcon: require("@/static/images/pos-icon.png"),
|
||||
selectIdx: 0,
|
||||
dropdownValue: 1,
|
||||
dropdownOptions: [
|
||||
{
|
||||
label: "保洁计划1",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "保洁计划2",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: "保洁计划3",
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: "保洁计划4",
|
||||
value: 4,
|
||||
},
|
||||
],
|
||||
selectTabs: [
|
||||
{
|
||||
name: "全部",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: "待保洁",
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
changeTab(i) {
|
||||
console.log(i);
|
||||
this.selectIdx = i;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: 100vh;
|
||||
background: #f7f8fc;
|
||||
.slot-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
/deep/ .u-dropdown-item__options {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
line-height: 1;
|
||||
border-left: 10rpx solid #5a7ee9;
|
||||
padding-left: 16rpx;
|
||||
font-weight: bold;
|
||||
font-size: 36rpx;
|
||||
color: #000000;
|
||||
}
|
||||
.area-info {
|
||||
padding: 24rpx 32rpx;
|
||||
padding-top: 72rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: url("@/static/images/plan-icon-bg.png") no-repeat 90% 60%;
|
||||
background-size: 40%;
|
||||
background-color: #dfeefd;
|
||||
.name {
|
||||
font-weight: 800;
|
||||
font-size: 48rpx;
|
||||
color: #1d1d1d;
|
||||
}
|
||||
.position {
|
||||
margin-top: 40rpx;
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #465161;
|
||||
}
|
||||
.tabs {
|
||||
margin-top: 38rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.tab-item {
|
||||
z-index: 99;
|
||||
pointer-events: auto; /* 确保可点击 */
|
||||
background: #ffffff;
|
||||
border-radius: 30rpx;
|
||||
padding: 18rpx 0;
|
||||
width: 48%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #383535;
|
||||
}
|
||||
.select {
|
||||
color: #ffffff;
|
||||
background: #4278f4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.arealist {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 32rpx;
|
||||
.block-info {
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
border-radius: 18rpx;
|
||||
padding: 65rpx 46rpx;
|
||||
.schedule {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #FEEDED; /* 背景颜色 */
|
||||
color: white;
|
||||
width: 160rpx;
|
||||
height: 45rpx;
|
||||
font-size: 30rpx;
|
||||
color: #DB3636;
|
||||
border-bottom-left-radius: 500rpx; /* 切角 */
|
||||
}
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.text {
|
||||
margin-left: 20rpx;
|
||||
font-size: 38rpx;
|
||||
color: #32353b;
|
||||
}
|
||||
}
|
||||
.type {
|
||||
display: flex;
|
||||
margin: 38rpx 0;
|
||||
.value {
|
||||
margin-right: 10rpx;
|
||||
font-size: 32rpx;
|
||||
color: #8896b4;
|
||||
}
|
||||
.tag {
|
||||
margin: 0 16rpx;
|
||||
}
|
||||
}
|
||||
.illustrate {
|
||||
padding: 46rpx;
|
||||
background: #f3f6f7;
|
||||
border-radius: 21rpx;
|
||||
font-size: 32rpx;
|
||||
color: #353535;
|
||||
line-height: 57rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,173 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<daySelect />
|
||||
<view class="task-info">
|
||||
<view class="title">今日任务</view>
|
||||
<view class="task-list">
|
||||
<view class="task-item">
|
||||
<view class="name-state">
|
||||
<view class="name">足球场休息室</view>
|
||||
<u-tag text="已完成" type="success" border-color="transparent" />
|
||||
</view>
|
||||
<view class="time">
|
||||
<u-tag text="9:00~12:00" type="info" border-color="transparent" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="area-schedule">
|
||||
<view class="finish">
|
||||
<view class="point"></view>
|
||||
<view class="title">已保洁区域</view>
|
||||
<view class="count-rate">26 <view class="total">/50</view> </view>
|
||||
<u-line-progress
|
||||
height="10"
|
||||
class="schedule-line"
|
||||
:show-percent="false"
|
||||
active-color="#2979ff"
|
||||
:percent="70"
|
||||
></u-line-progress>
|
||||
</view>
|
||||
<view class="unfinish">
|
||||
<view class="point"></view>
|
||||
<view class="title">已保洁区域</view>
|
||||
<view class="count-rate">26 <view class="total">/50</view> </view>
|
||||
<u-line-progress
|
||||
height="10"
|
||||
class="schedule-line"
|
||||
:show-percent="false"
|
||||
active-color="#FC873D"
|
||||
:percent="70"
|
||||
></u-line-progress>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cleaning-plan">
|
||||
<view class="title">今日保洁计划名称</view>
|
||||
<view class="time">
|
||||
<view class="top">00:00:00</view>
|
||||
<view class="bottom">23:59:00</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import daySelect from "@/components/daySelect/index.vue";
|
||||
export default {
|
||||
components: {
|
||||
daySelect,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: 100vh; // 确保容器有明确高度
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.task-info {
|
||||
margin: 0 32rpx;
|
||||
padding: 18rpx;
|
||||
background: #f5f6fa;
|
||||
border-radius: 24rpx;
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 34rpx;
|
||||
color: #282828;
|
||||
}
|
||||
.task-list {
|
||||
margin-top: 36rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.task-item {
|
||||
padding: 44rpx 30rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
.name-state {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.name {
|
||||
position: relative;
|
||||
}
|
||||
.name::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: -6%;
|
||||
display: inline-block;
|
||||
width: 5rpx;
|
||||
height: 30rpx;
|
||||
background: #3d6af0;
|
||||
}
|
||||
}
|
||||
.time {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.area-schedule {
|
||||
margin: 0 32rpx;
|
||||
margin-top: 26rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> view {
|
||||
padding: 22rpx;
|
||||
width: 48%;
|
||||
background: #f5f6fa;
|
||||
border-radius: 10rpx;
|
||||
.point {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #4473fe;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 28rpx;
|
||||
font-size: 32rpx;
|
||||
color: #292929;
|
||||
}
|
||||
.count-rate {
|
||||
margin-left: 12rpx;
|
||||
margin-top: 40rpx;
|
||||
display: flex;
|
||||
font-size: 50rpx;
|
||||
color: #4473fe;
|
||||
.total {
|
||||
font-size: 50rpx;
|
||||
color: #dbdee9;
|
||||
}
|
||||
}
|
||||
.schedule-line {
|
||||
margin-top: 32rpx;
|
||||
}
|
||||
}
|
||||
.unfinish .point {
|
||||
background: #fc873d;
|
||||
}
|
||||
.unfinish .count-rate {
|
||||
color: #fc873d;
|
||||
}
|
||||
}
|
||||
|
||||
.cleaning-plan {
|
||||
margin: 0 32rpx;
|
||||
margin-top: 36rpx;
|
||||
padding: 42rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: url("@/static/images/plan-bg.png") no-repeat 100% 100%;
|
||||
background-size: 100% 100%;
|
||||
.title {
|
||||
font-weight: 500;
|
||||
font-size: 36rpx;
|
||||
color: #334a65;
|
||||
}
|
||||
.time{
|
||||
font-weight: 500;
|
||||
font-size: 36rpx;
|
||||
color: #334A65;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,170 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="top">
|
||||
<u-cell-group>
|
||||
<u-cell-item :arrow="false" title="保洁人员" value="小饼"></u-cell-item>
|
||||
<u-cell-item
|
||||
:arrow="false"
|
||||
title="上报时间"
|
||||
value="2025.4.1"
|
||||
></u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
|
||||
<view class="title">保洁区域</view>
|
||||
|
||||
<view class="bottom">
|
||||
<u-form :model="form" :rules="rules" ref="uForm" label-width="200">
|
||||
<!-- 区域选择(多选) -->
|
||||
<u-form-item label="东大门操场" prop="areas" required>
|
||||
<u-input v-model="form.cleaner" placeholder="请输入故障" />
|
||||
</u-form-item>
|
||||
|
||||
<!-- 备注(文本域) -->
|
||||
<u-form-item label="备注" prop="notes" label-position="top">
|
||||
<u-input
|
||||
v-model="form.notes"
|
||||
placeholder="请输入备注信息"
|
||||
autoHeight
|
||||
maxlength="200"
|
||||
count
|
||||
type="textarea"
|
||||
></u-input>
|
||||
</u-form-item>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<u-form-item
|
||||
label="现场照片"
|
||||
prop="images"
|
||||
required
|
||||
label-position="top"
|
||||
>
|
||||
<u-upload
|
||||
v-model="form.images"
|
||||
:max-count="3"
|
||||
:previewFullImage="true"
|
||||
:multiple="true"
|
||||
@afterRead="handleImageUpload"
|
||||
@delete="handleImageDelete"
|
||||
></u-upload>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<u-button @click="submitForm" customStyle="margin-top: 40rpx" type="primary"
|
||||
>保存</u-button
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
cleaner: "", // 保洁人员
|
||||
reportTime: "", // 上报时间
|
||||
areas: [], // 清洁区域
|
||||
notes: "", // 备注
|
||||
images: [], // 图片列表
|
||||
},
|
||||
areaOptions: [
|
||||
{ label: "东大门操场", value: "east_gate" },
|
||||
{ label: "西区教学楼", value: "west_building" },
|
||||
{ label: "中心花园", value: "central_garden" },
|
||||
],
|
||||
rules: {
|
||||
cleaner: [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写保洁人员",
|
||||
trigger: ["blur", "change"],
|
||||
},
|
||||
],
|
||||
reportTime: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择上报时间",
|
||||
trigger: ["change"],
|
||||
},
|
||||
],
|
||||
areas: [
|
||||
{
|
||||
type: "array",
|
||||
required: true,
|
||||
message: "请至少选择一个清洁区域",
|
||||
trigger: ["change"],
|
||||
},
|
||||
],
|
||||
images: [
|
||||
{
|
||||
type: "array",
|
||||
min: 1,
|
||||
required: true,
|
||||
message: "请至少上传一张现场照片",
|
||||
trigger: ["change"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 图片上传处理
|
||||
handleImageUpload(event) {
|
||||
const files = event.file;
|
||||
// 这里添加实际的上传逻辑
|
||||
this.form.images.push(...files.map((file) => ({ url: file.url })));
|
||||
},
|
||||
|
||||
// 图片删除处理
|
||||
handleImageDelete(index) {
|
||||
this.form.images.splice(index, 1);
|
||||
},
|
||||
|
||||
// 表单提交
|
||||
submitForm() {
|
||||
this.$refs.uForm.validate().then((valid) => {
|
||||
if (valid) {
|
||||
uni.showToast({
|
||||
title: "提交成功",
|
||||
icon: "success",
|
||||
});
|
||||
// 这里添加实际提交逻辑
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: auto;
|
||||
min-height: 100vh;
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #f3f5fa;
|
||||
|
||||
.bottom,
|
||||
.top {
|
||||
background: #ffffff;
|
||||
border-radius: 22rpx;
|
||||
padding: 0rpx 32rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 38rpx;
|
||||
color: #1a1a1b;
|
||||
margin: 42rpx 0 32rpx 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
// 调整复选框布局
|
||||
.u-checkbox-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 30rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
title="计划列表"
|
||||
:background="{ backgroundColor: '#F7F8FC' }"
|
||||
:border-bottom="false"
|
||||
>
|
||||
<view slot="right"> 424242 </view>
|
||||
</u-navbar>
|
||||
|
||||
<view class="selectTab">
|
||||
<view class="tab-item">
|
||||
<view class="label">已完成计划</view>
|
||||
<view class="count">12</view>
|
||||
</view>
|
||||
<view class="tab-item">
|
||||
<view class="label">未完成计划</view>
|
||||
<view class="count">5</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="planList">
|
||||
<view class="plan-item">
|
||||
<view class="time">
|
||||
<u-icon
|
||||
label="uView"
|
||||
size="40"
|
||||
name="https://cdn.uviewui.com/uview/example/button.png"
|
||||
></u-icon>
|
||||
<view class="date">05-21</view>
|
||||
</view>
|
||||
<view class="place-time">
|
||||
<view class="place">校门A区教学楼</view>
|
||||
<u-tag text="9:00~12:00" type="info" border-color="transparent" />
|
||||
</view>
|
||||
<view class="illustrate">
|
||||
北大门右侧操场跑道/南广场升旗台/A区第二食堂3楼
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: 100vh;
|
||||
background: #f7f8fc;
|
||||
.selectTab{
|
||||
padding: 42rpx 90rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
// background: ;
|
||||
.tab-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50%;
|
||||
background: #fff;
|
||||
.label{
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
.count{
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.planList {
|
||||
padding: 0 32rpx;
|
||||
.plan-item {
|
||||
margin-top: 32rpx;
|
||||
padding: 32rpx;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form ref="uForm">
|
||||
<u-form-item label="反馈内容:" label-width="150" >
|
||||
<u-input v-model="content" type="textarea"/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="上传图片:" label-width="150" >
|
||||
<u-upload upload-text="选择或拍照" width="180" height="180" ref="uUpload" :action="action" :fileList="fileList" :form-data="form_data" ></u-upload>
|
||||
</u-form-item>
|
||||
|
||||
<u-button type="primary" @click="submit">确定</u-button>
|
||||
</u-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
action: '/api/index/upload_cos',
|
||||
content : '',
|
||||
fileList:[],
|
||||
form_data : {
|
||||
floder : 'photo'
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
},
|
||||
onReady(){
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
|
||||
let _uploadPhoto_data = {}
|
||||
var _list = this.$refs.uUpload.lists
|
||||
|
||||
for (let i = 0; i < _list.length; i++) {
|
||||
_uploadPhoto_data[i] = {
|
||||
url: _list[i].response.data.file
|
||||
}
|
||||
}
|
||||
|
||||
const param={
|
||||
photo :JSON.stringify(_uploadPhoto_data),
|
||||
content: this.content
|
||||
}
|
||||
this.$api.feedback(param).then(res => {
|
||||
if(res.code==0){
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
console.log('提交成功');
|
||||
}else{
|
||||
toast(res.msg)
|
||||
console.log('提交失败');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page{background: #f2f2f2;}
|
||||
.content{margin: 10rpx;background: #fff;padding:20rpx}
|
||||
</style>
|
|
@ -0,0 +1,69 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="logo">
|
||||
<u-image src="@/static/logo.png" width="150rpx" height="150rpx" mode="aspectFill"></u-image>
|
||||
</view>
|
||||
|
||||
<u-cell-item icon="info-circle-fill" bg-color="#fff" title="当前版本" hover-class="none" :value="version" :arrow="false"></u-cell-item>
|
||||
|
||||
<u-cell-group title="其他:">
|
||||
<u-cell-item icon="home-fill" title="公司简介" @click="about"></u-cell-item>
|
||||
<u-cell-item icon="integral-fill" title="公司资质" @click="Qualification"></u-cell-item>
|
||||
<u-cell-item icon="file-text-fill" title="服务协议" @click="serviceAgreement" ></u-cell-item>
|
||||
<u-cell-item icon="file-text-fill" title="隐私政策" @click="privacyPolicy"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
<u-cell-group title="联系:">
|
||||
<u-cell-item icon="server-fill" title="联系我们" @click="contactUs"></u-cell-item>
|
||||
<u-cell-item icon="chat-fill" title="意见反馈" @click="feedback"></u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, Jump,getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
version:"",
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
const that = this
|
||||
uni.getSystemInfo({
|
||||
success: function (res) {
|
||||
console.log("res", res)
|
||||
that.version = res.appVersion
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
about(){
|
||||
Jump('/pages/public/page?id=1')
|
||||
},
|
||||
Qualification(){
|
||||
Jump('/pages/public/page?id=2')
|
||||
},
|
||||
serviceAgreement(){
|
||||
Jump('/pages/public/page?id=3')
|
||||
},
|
||||
privacyPolicy(){
|
||||
Jump('/pages/public/page?id=4')
|
||||
},
|
||||
contactUs(){
|
||||
Jump('/pages/public/page?id=5')
|
||||
},
|
||||
feedback(){
|
||||
useRouter('/pages/my/about/feedback',{} ,'navigateTo')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
page{background:#f2f2f2}
|
||||
.logo{width: 150rpx;height: 150rpx; margin:0 auto;margin-top: 30rpx; margin-bottom: 30rpx;}
|
||||
</style>
|
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
<u-form-item label="原邮箱:" labelWidth="160">{{baseInfo.email}}</u-form-item>
|
||||
|
||||
<u-form-item label="新邮箱:" labelWidth="160" prop="new_email">
|
||||
<u-input placeholder="请输入新邮箱" v-model="form.new_email" />
|
||||
</u-form-item>
|
||||
|
||||
|
||||
<u-form-item label="验证码:" labelWidth="160" prop="code">
|
||||
<u-input placeholder="请输入验证码" v-model="form.code" />
|
||||
<u-verification-code :seconds="seconds" ref="uCode"
|
||||
@change="codeChange"></u-verification-code>
|
||||
<u-button slot="right" type="primary" size="mini" @click="getCode">{{tips}}</u-button>
|
||||
</u-form-item>
|
||||
<u-button type="primary" @click="submit">确定</u-button>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {toast, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseInfo: {
|
||||
email : '',
|
||||
},
|
||||
form: {
|
||||
new_email: '',
|
||||
code: ''
|
||||
},
|
||||
rules: {
|
||||
new_email: [
|
||||
{
|
||||
required: true,
|
||||
type: 'email',
|
||||
message: '邮箱格式错误',
|
||||
trigger: 'blur,change'
|
||||
}
|
||||
],
|
||||
code: [
|
||||
{
|
||||
required: true,
|
||||
min: 4,
|
||||
type: 'number',
|
||||
message: '验证码格式错误',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
seconds: 60,
|
||||
refCode: null,
|
||||
tips:'获取验证码'
|
||||
};
|
||||
},
|
||||
onLoad(){
|
||||
this.getUserInfo()
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
methods: {
|
||||
getUserInfo() {
|
||||
this.$api.baseInfo().then(res => {
|
||||
this.baseInfo = res.data
|
||||
})
|
||||
},
|
||||
|
||||
submit(){
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
//验证通过,执行TODO
|
||||
this.$api.emailBind(this.form).then(res => {
|
||||
if (res.code == 0) {
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
} else {
|
||||
toast(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
},
|
||||
codeChange(text) {
|
||||
this.tips = text;
|
||||
},
|
||||
getCode() {
|
||||
if(this.$refs.uCode.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被this.start()方法中的提示覆盖
|
||||
this.$u.toast('验证码已发送');
|
||||
// 通知验证码组件内部开始倒计时
|
||||
this.$refs.uCode.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
this.$u.toast('倒计时结束后再发送');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{padding:35rpx}
|
||||
</style>
|
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-cell-group title="帐号绑定:">
|
||||
<u-cell-item icon="account-fill" title="手机绑定" :value="baseInfo.phone" @click="phone"></u-cell-item>
|
||||
<u-cell-item icon="email-fill" title="邮箱绑定" :value="baseInfo.email" @click="email"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
<u-cell-group title="密码:">
|
||||
<u-cell-item icon="lock-fill" title="登陆密码" value="修改" @click="modifypassword"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
<u-cell-group title="帐号:">
|
||||
<u-cell-item icon="minus-people-fill" title="注销帐号" value="" @click="logout_account"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
<u-button @click="showModal=true" type="primary" style="margin-top: 20rpx;width:98%">
|
||||
退出登陆
|
||||
</u-button>
|
||||
|
||||
|
||||
<u-modal v-model="showModal" showCancelButton title="退出登录" content='确定要退出吗?' @cancel="showModal=false" @confirm="confirmExit"></u-modal>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseInfo: {
|
||||
name:'',
|
||||
phone:'',
|
||||
avatar:'',
|
||||
email : '',
|
||||
company_name:'',
|
||||
registerDate:'',
|
||||
login_code:'',
|
||||
auth: 0,
|
||||
},
|
||||
version:"",
|
||||
showModal: false,
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
this.getUserInfo()
|
||||
const that = this
|
||||
uni.getSystemInfo({
|
||||
success: function (res) {
|
||||
console.log("res", res)
|
||||
that.version = res.appVersion
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getUserInfo() {
|
||||
this.$api.baseInfo().then(res => {
|
||||
this.baseInfo = res.data
|
||||
})
|
||||
},
|
||||
confirmExit() {
|
||||
uni.removeStorageSync('token')
|
||||
this.showModal =false
|
||||
useRouter('/pages/public/login',{} ,'reLaunch')
|
||||
},
|
||||
|
||||
modifypassword(){
|
||||
useRouter('/pages/my/account/password',{} ,'navigateTo')
|
||||
},
|
||||
email(){
|
||||
useRouter('/pages/my/account/email',{} ,'navigateTo')
|
||||
},
|
||||
phone(){
|
||||
useRouter('/pages/my/account/phone',{} ,'navigateTo')
|
||||
},
|
||||
logout_account(){
|
||||
useRouter('/pages/my/account/logout_account',{} ,'navigateTo')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
page{background:#f2f2f2}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="u-content">
|
||||
<u-parse :html="content"></u-parse>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="tipsArea">
|
||||
<view class="operation">
|
||||
<u-checkbox v-model="agree">我同意<<注销协议>>,提交后帐号将不再恢复</u-checkbox>
|
||||
</view>
|
||||
<view class="btn">
|
||||
<u-button type="primary" style="width: 98%;margin-bottom: 15rpx;" @click="confirme">注销帐号</u-button>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-modal v-model="showModal" showCancelButton title="注销" content='确定要注销帐号吗?' @cancel="closeShowModal" @confirm="confirmOperation"></u-modal>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
content: '',
|
||||
show:true,
|
||||
agree : false,
|
||||
showModal: false
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
this.getPage()
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
|
||||
getPage(){
|
||||
const param={
|
||||
id:6
|
||||
}
|
||||
this.$api.page(param).then(res => {
|
||||
if (res.code ==1 ) {
|
||||
this.content = res.data.content
|
||||
}
|
||||
})
|
||||
},
|
||||
confirme(){
|
||||
if(!this.agree) return toast('请查看并同意相关协议');
|
||||
this.showModal = true
|
||||
},
|
||||
confirmOperation() {
|
||||
this.$api.logout_account().then(res => {
|
||||
if (res.code ==0 ) {
|
||||
toast(res.msg);
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
closeShowModal(){
|
||||
this.showModal = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.u-content{
|
||||
padding: 20rpx;
|
||||
color: $u-content-color;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.8;
|
||||
padding-bottom: 250rpx;
|
||||
}
|
||||
.tipsArea{position: fixed; bottom: 0;background: #fdf6ec;width: 100%;}
|
||||
.operation{padding:20rpx;padding-top: 20rpx;
|
||||
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
<u-form-item label="原密码:" labelWidth="120" prop="password">
|
||||
<u-input placeholder="请输入原密码" v-model="form.password" />
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="新密码:" labelWidth="120" prop="news_password">
|
||||
<u-input placeholder="请输入要修改的新密码" v-model="form.news_password" />
|
||||
</u-form-item>
|
||||
<u-button type="primary" @click="submit">确定</u-button>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {toast, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
password: '',
|
||||
new_password :''
|
||||
},
|
||||
rules: {
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入原密码',
|
||||
trigger: 'blur,change'
|
||||
}
|
||||
],
|
||||
news_password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新密码',
|
||||
trigger: 'blur,change'
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
//验证通过,执行TODO
|
||||
this.$api.password(this.form).then(res => {
|
||||
if (res.code == 0) {
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
} else {
|
||||
toast(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{padding:35rpx}
|
||||
</style>
|
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
<u-form-item label="原手机号:" labelWidth="160">{{baseInfo.phone}}</u-form-item>
|
||||
|
||||
<u-form-item label="新手机号:" labelWidth="160" prop="new_phone">
|
||||
<u-input placeholder="请输入手机号" v-model="form.new_phone" />
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="验证码:" labelWidth="160" prop="code">
|
||||
<u-input placeholder="请输入验证码" v-model="form.code" />
|
||||
<u-verification-code :seconds="seconds" ref="uCode"
|
||||
@change="codeChange"></u-verification-code>
|
||||
<u-button slot="right" type="primary" size="mini" @click="getCode">{{tips}}</u-button>
|
||||
</u-form-item>
|
||||
<u-button type="primary" @click="submit">确定</u-button>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {toast, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseInfo: {
|
||||
phone : '',
|
||||
},
|
||||
form: {
|
||||
new_phone: '',
|
||||
code: ''
|
||||
},
|
||||
rules: {
|
||||
new_phone: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号',
|
||||
trigger: 'blur,change'
|
||||
},
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
return this.$u.test.mobile(value);
|
||||
},
|
||||
message: '手机号码不正确',
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
code: [
|
||||
{
|
||||
required: true,
|
||||
min: 4,
|
||||
type: 'number',
|
||||
message: '验证码格式错误',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
seconds: 60,
|
||||
refCode: null,
|
||||
tips:'获取验证码'
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
onLoad(){
|
||||
this.getUserInfo()
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
//验证通过,执行TODO
|
||||
this.$api.phoneBind(this.form).then(res => {
|
||||
if (res.code == 0) {
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
} else {
|
||||
toast(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
},
|
||||
getUserInfo() {
|
||||
this.$api.baseInfo().then(res => {
|
||||
this.baseInfo = res.data
|
||||
})
|
||||
},
|
||||
codeChange(text) {
|
||||
this.tips = text;
|
||||
},
|
||||
getCode() {
|
||||
if(this.$refs.uCode.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被this.start()方法中的提示覆盖
|
||||
this.$u.toast('验证码已发送');
|
||||
// 通知验证码组件内部开始倒计时
|
||||
this.$refs.uCode.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
this.$u.toast('倒计时结束后再发送');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{padding:35rpx}
|
||||
</style>
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="">
|
||||
<u-cell-group>
|
||||
<u-cell-item title="通知" :arrow="false">
|
||||
<u-switch v-model="costs_display" @change="costs_display_change"></u-switch>
|
||||
</u-cell-item>
|
||||
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
costs_display: false,
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
this.costs_display = getStorageSync("costs_display") || false
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
costs_display_change(status){
|
||||
setStorageSync("costs_display",status)
|
||||
console.log('status' ,getStorageSync("costs_display"))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content{padding: 30rpx;}
|
||||
</style>
|
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
<u-form-item label="姓名:" label-width="170" prop="cardno">
|
||||
<u-input v-model="form.name" placeholder="请输入姓名"/>
|
||||
</u-form-item>
|
||||
<u-form-item label="身份证号:" label-width="170" prop="cardno">
|
||||
<u-input v-model="form.cardno" placeholder="请输入身份证号"/>
|
||||
</u-form-item>
|
||||
<u-form-item label="身份证正反面:" label-width="200">
|
||||
<u-upload upload-text="选择或拍照" width="180" height="180" ref="uUpload" :action="action" :fileList="fileList" :form-data="form_data" ></u-upload>
|
||||
</u-form-item>
|
||||
|
||||
<view class="submit_con">
|
||||
<u-button type="primary" @click="submit">提交</u-button>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync,getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
action: this.$api_url + '/api/index/upload_cos',
|
||||
fileList:[],
|
||||
form: {
|
||||
cardno: '',
|
||||
photo:'',
|
||||
name:''
|
||||
},
|
||||
|
||||
form_data : {
|
||||
floder : 'photo'
|
||||
},
|
||||
rules: {
|
||||
cardno: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入姓名',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
cardno: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入身份证号码',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
onReady(){
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
|
||||
methods: {
|
||||
submit() {
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
|
||||
//获取上传列表
|
||||
let _uploadPhoto_data = {}
|
||||
var _list = this.$refs.uUpload.lists
|
||||
|
||||
for (let i = 0; i < _list.length; i++) {
|
||||
_uploadPhoto_data[i] = {
|
||||
url: _list[i].response.data.file
|
||||
}
|
||||
}
|
||||
|
||||
this.form.photo = JSON.stringify(_uploadPhoto_data),
|
||||
this.$api.auth(this.form).then(res => {
|
||||
if(res.code==0){
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.$emit('refresh', {}) //添加事件
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
|
||||
console.log(res);
|
||||
}else{
|
||||
toast(res.msg)
|
||||
console.log(res);
|
||||
}
|
||||
})
|
||||
|
||||
console.log(this.form)
|
||||
} else {
|
||||
|
||||
console.log('验证失败');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.content{padding:30rpx}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="head">
|
||||
<u-avatar :src="baseInfo.avatar" size="140" mode="circle" class="avatar" :show-level="true" level-icon ="camera" @click="upload_avatar"></u-avatar>
|
||||
<view class="personInfo">
|
||||
<view>{{baseInfo.name}}</view>
|
||||
<view class="account">帐号:{{baseInfo.phone}}</view>
|
||||
|
||||
</view>
|
||||
<view class="auth">
|
||||
<u-tag text="已实名" shape="circleLeft" type="success" v-if="baseInfo.auth==1"/>
|
||||
<u-tag text="未实名" shape="circleLeft" type="error" v-if="baseInfo.auth==0"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-cell-group>
|
||||
<u-cell-item icon="account-fill" title="个人信息" @click="profile"></u-cell-item>
|
||||
<u-cell-item icon="lock-fill" title="帐号&安全" @click="account"></u-cell-item>
|
||||
|
||||
<u-cell-item icon="setting-fill" title="设置" @click="setting"></u-cell-item>
|
||||
<u-cell-item icon="server-fill" title="服务中心" @click="service_center"></u-cell-item>
|
||||
|
||||
<u-cell-item icon="info-circle" title="关于我们" @click="about"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
|
||||
baseInfo: {
|
||||
name:'',
|
||||
phone:'',
|
||||
avatar:'',
|
||||
company_name:'',
|
||||
registerDate:'',
|
||||
login_code:'',
|
||||
auth: 0,
|
||||
},
|
||||
version:"",
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
this.getUserInfo()
|
||||
const that = this
|
||||
uni.getSystemInfo({
|
||||
success: function (res) {
|
||||
console.log("res", res)
|
||||
that.version = res.appVersion
|
||||
}
|
||||
})
|
||||
},
|
||||
onShow() {
|
||||
uni.$on('refresh', e => {
|
||||
this.getUserInfo()
|
||||
uni.$off('refresh')
|
||||
})
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
//console.log('refresh');
|
||||
this.getUserInfo()
|
||||
uni.stopPullDownRefresh();//停止刷新
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
upload_avatar(){
|
||||
const _this=this
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album','camera'], //从相册选择
|
||||
success: function (res) {
|
||||
|
||||
uni.uploadFile({
|
||||
url: _this.$api_url + '/api/index/upload_cos',
|
||||
filePath: res.tempFilePaths[0],
|
||||
name: 'file',
|
||||
formData: {
|
||||
floder: 'avatar'
|
||||
},
|
||||
success: (uploadFileRes) => {
|
||||
//let retData = JSON.parse(uploadFileRes)
|
||||
|
||||
let retData = JSON.parse(uploadFileRes.data)
|
||||
console.log('up:',retData)
|
||||
const _data ={
|
||||
avatar: retData.data.file
|
||||
}
|
||||
_this.$api.baseInfoSave(_data).then(ret => {
|
||||
if (ret.code == 1) {
|
||||
_this.baseInfo.avatar = retData.data.file
|
||||
} else {
|
||||
toast(res.msg)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
getUserInfo() {
|
||||
this.$api.baseInfo().then(res => {
|
||||
//console.log(res)
|
||||
this.baseInfo = res.data
|
||||
this.avatar_src= res.data.avatar
|
||||
})
|
||||
},
|
||||
|
||||
service_center(){
|
||||
toast('未设置跳转,请自行定义')
|
||||
},
|
||||
|
||||
profile(){
|
||||
useRouter('/pages/my/profile',{} ,'navigateTo')
|
||||
},
|
||||
account(){
|
||||
useRouter('/pages/my/account/index',{} ,'navigateTo')
|
||||
},
|
||||
setting(){
|
||||
useRouter('/pages/my/account/setting',{} ,'navigateTo')
|
||||
},
|
||||
about(){
|
||||
useRouter('/pages/my/about/index',{} ,'navigateTo')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{
|
||||
|
||||
.head{
|
||||
background-color:rgb(71, 144, 255);
|
||||
display: flex;
|
||||
|
||||
min-height: 300rpx;
|
||||
padding-top: 60rpx;
|
||||
.avatar{
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
.personInfo{
|
||||
color:#fff;
|
||||
margin-top: 25rpx;
|
||||
font-size: 30rpx;
|
||||
margin-left: 30rpx;
|
||||
line-height: 50rpx;
|
||||
.account{font-size: 26rpx;}
|
||||
}
|
||||
.auth{flex: 1;text-align: right;margin-top: 40rpx;}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-cell-group title="个人信息:">
|
||||
<u-cell-item icon="account-fill" title="姓名" hover-class="none" :value="baseInfo.name" :arrow="false"></u-cell-item>
|
||||
<u-cell-item icon="phone-fill" title="手机" hover-class="none" :value="baseInfo.phone" :arrow="false"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
<u-cell-group title="实名:">
|
||||
<u-cell-item icon="integral-fill" title="实名认证" :value="auth_txt" @click="auth"></u-cell-item>
|
||||
</u-cell-group>
|
||||
|
||||
|
||||
<u-cell-group title="其他信息:">
|
||||
<u-cell-item icon="home-fill" title="所属公司" hover-class="none" :value="baseInfo.company_name" :arrow="false"></u-cell-item>
|
||||
<u-cell-item icon="coupon-fill" title="标识号" hover-class="none" :value="baseInfo.login_code" :arrow="false"></u-cell-item>
|
||||
<u-cell-item icon="calendar-fill" title="注册时间" hover-class="none" :value="baseInfo.registerDate" :arrow="false"></u-cell-item>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseInfo: {
|
||||
name:'',
|
||||
phone:'',
|
||||
avatar:'',
|
||||
company_name:'',
|
||||
registerDate:'',
|
||||
login_code:'',
|
||||
auth: 0,
|
||||
|
||||
},
|
||||
auth_txt: '未实名'
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
this.getUserInfo()
|
||||
},
|
||||
methods: {
|
||||
getUserInfo() {
|
||||
this.$api.baseInfo().then(res => {
|
||||
this.baseInfo = res.data
|
||||
if(this.baseInfo.auth==1){
|
||||
this.auth_txt ="已实名"
|
||||
}
|
||||
})
|
||||
},
|
||||
auth(){
|
||||
if(!this.baseInfo.auth){
|
||||
useRouter('/pages/my/auth',{} ,'navigateTo')
|
||||
}else{
|
||||
toast('已实名认证')
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
page{background:#f2f2f2}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
|
||||
|
||||
<u-form-item label="手机号:" labelWidth="160" prop="phone">
|
||||
<u-input placeholder="请输入手机号" v-model="form.phone" />
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="验证码:" labelWidth="160" prop="code">
|
||||
<u-input placeholder="请输入验证码" v-model="form.code" />
|
||||
<u-verification-code :seconds="seconds" ref="uCode"
|
||||
@change="codeChange"></u-verification-code>
|
||||
<u-button slot="right" type="primary" size="mini" @click="getCode">{{tips}}</u-button>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="密码:" labelWidth="160" prop="password">
|
||||
<u-input placeholder="请输入要重置的密码" v-model="form.password" />
|
||||
</u-form-item>
|
||||
|
||||
|
||||
<u-button type="primary" @click="submit">确定</u-button>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import {toast, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
baseInfo: {
|
||||
phone : '',
|
||||
},
|
||||
form: {
|
||||
phone: '',
|
||||
code: '',
|
||||
password:''
|
||||
},
|
||||
rules: {
|
||||
phone: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号',
|
||||
trigger: 'blur,change'
|
||||
},
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
return this.$u.test.mobile(value);
|
||||
},
|
||||
message: '手机号码不正确',
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
code: [
|
||||
{
|
||||
required: true,
|
||||
min: 4,
|
||||
type: 'number',
|
||||
message: '验证码格式错误',
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
min: 6,
|
||||
message: '请输入密码',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
seconds: 60,
|
||||
refCode: null,
|
||||
tips:'获取验证码'
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
onLoad(){
|
||||
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
//验证通过,执行TODO
|
||||
this.$api.forgetPassWord(this.form).then(res => {
|
||||
if (res.code == 0) {
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},500)
|
||||
} else {
|
||||
toast(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
},
|
||||
codeChange(text) {
|
||||
this.tips = text;
|
||||
},
|
||||
getCode() {
|
||||
if(this.$refs.uCode.canGetCode) {
|
||||
// 模拟向后端请求验证码
|
||||
uni.showLoading({
|
||||
title: '正在获取验证码'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
// 这里此提示会被this.start()方法中的提示覆盖
|
||||
this.$u.toast('验证码已发送');
|
||||
// 通知验证码组件内部开始倒计时
|
||||
this.$refs.uCode.start();
|
||||
}, 2000);
|
||||
} else {
|
||||
this.$u.toast('倒计时结束后再发送');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{padding:35rpx}
|
||||
</style>
|
|
@ -0,0 +1,120 @@
|
|||
<template>
|
||||
|
||||
<view class="content">
|
||||
<view class="logo">
|
||||
<image style="width: 150rpx; height: 150rpx; " src="/static/images/logo.png" alt="" /></image>
|
||||
</view>
|
||||
<view class="login">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
|
||||
<u-form-item label="帐号:" prop="phone">
|
||||
<u-input v-model="form.phone" placeholder="请输入登陆账号" />
|
||||
</u-form-item>
|
||||
<u-form-item label="密码:" prop="password">
|
||||
<u-input type="password" v-model="form.password" placeholder="请输入密码"/>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
<u-button @click="submit" style="margin-top: 30rpx;" type="primary">登录</u-button>
|
||||
<view class="forgetPassword" @click="forgetPassWord">忘记密码</view>
|
||||
<view class="reg" @click="register">没有帐号?注册</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
phone: '',
|
||||
password: '',
|
||||
},
|
||||
rules: {
|
||||
|
||||
phone: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入帐号',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
const data = {
|
||||
login_code: this.form.login_code,
|
||||
phone: this.form.phone,
|
||||
password: this.form.password,
|
||||
}
|
||||
|
||||
this.$api.login(data).then(res => {
|
||||
console.log(res)
|
||||
if (res.code !== 0) {
|
||||
toast(res.msg)
|
||||
} else {
|
||||
toast('登录成功')
|
||||
setStorageSync('token' ,res.data.token )
|
||||
useRouter('/pages/index/index',{} ,'switchTab')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
},
|
||||
register(){
|
||||
useRouter('/pages/public/register')
|
||||
},
|
||||
forgetPassWord(){
|
||||
useRouter('/pages/public/forget_password')
|
||||
}
|
||||
},
|
||||
// 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
|
||||
onReady() {
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding: 0 10rpx;
|
||||
width:100%;
|
||||
background-image: url('/static/images/login_bg.png') ;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left top;
|
||||
}
|
||||
.logo{
|
||||
width:150rpx;
|
||||
margin:0 auto;
|
||||
padding-top:140rpx;
|
||||
}
|
||||
.login{
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
margin-top: 260rpx;
|
||||
}
|
||||
.title {
|
||||
text-align: center;
|
||||
margin: 80rpx 0 0 0;
|
||||
}
|
||||
.reg{float: right;padding:30rpx 0 30rpx 0;color:#2979ff;}
|
||||
|
||||
.forgetPassword{float: left;padding:30rpx 0 30rpx 0;color:#2979ff;}
|
||||
</style>
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<mp-html :content="html" :tag-style="tag_style"/>
|
||||
<!-- <rich-text :nodes="html"></rich-text> -->
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
html: '',
|
||||
tag_style:{
|
||||
p: 'line-height:45rpx; margin-top: 30rpx;',
|
||||
img : 'width:100%',
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
this.id = op.id
|
||||
this.getPage()
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
getPage(){
|
||||
const param = {
|
||||
id : this.id
|
||||
}
|
||||
this.$api.page(param).then(res => {
|
||||
if (res.code ==1 ) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: res.data.title
|
||||
})
|
||||
this.html = res.data.content
|
||||
//解析HTML用到了插件mp-html,更多文档见:https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.content{
|
||||
padding: 20rpx;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<u-form :model="form" ref="uForm" :error-type="['toast']">
|
||||
<u-form-item label="登陆帐号:" prop="username" label-width="170"><u-input placeholder="请输入登陆帐号" v-model="form.username" /></u-form-item>
|
||||
<u-form-item label="真实姓名:" label-width="170" prop="name"><u-input placeholder="请输入真实姓名" v-model="form.name" /></u-form-item>
|
||||
<u-form-item label="手机号:" label-width="170" prop="phone"><u-input placeholder="请输入输入手机号码" v-model="form.phone" /></u-form-item>
|
||||
<u-form-item label="登陆密码:" label-width="170" prop="password"><u-input type="password" placeholder="请输入登陆密码" v-model="form.password" /></u-form-item>
|
||||
|
||||
<view class="agreement">
|
||||
<u-checkbox size="40rpx" v-model="check" @change="checkboxChange"></u-checkbox>
|
||||
<view class="agreement-text">
|
||||
我已知晓并同意 <text @click="showPopup(4)" style="color:cornflowerblue">《用户服务协议》</text>及<text @click="showPopup(5)" style="color:cornflowerblue">《隐私政策》</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="submit_con">
|
||||
<u-button type="primary" @click="submit">提交注册</u-button>
|
||||
</view>
|
||||
</u-form>
|
||||
|
||||
|
||||
<u-popup v-model="popupVisible" mode="bottom" length="60%" :closeable="true">
|
||||
<view class="popup-content">
|
||||
<rich-text :nodes="protocolsContent" style="line-height: 50rpx;"></rich-text>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
|
||||
<u-button class="close_pop" size="medium" type="primary" @click="hidePopup">关闭</u-button>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync,getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
action: this.$api_url + '/api/index/upload_cos',
|
||||
fileList:[],
|
||||
popupVisible: false,
|
||||
protocolsContent: "",
|
||||
check: false,
|
||||
agreement: false,
|
||||
form: {
|
||||
username: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
cardno: '',
|
||||
photo:'',
|
||||
password:''
|
||||
},
|
||||
form_data : {
|
||||
floder : 'photo'
|
||||
},
|
||||
rules: {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入登陆帐号',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入真实姓名',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{
|
||||
required: true,
|
||||
type:"number",
|
||||
message: '请输入登陆手机号',
|
||||
// 可以单个或者同时写两个触发验证方式
|
||||
trigger: ['change','blur'],
|
||||
}
|
||||
],
|
||||
}
|
||||
};
|
||||
},
|
||||
onReady(){
|
||||
this.$refs.uForm.setRules(this.rules);
|
||||
},
|
||||
|
||||
methods: {
|
||||
checkboxChange(e) {
|
||||
this.agreement = e.value;
|
||||
},
|
||||
showPopup(id) {
|
||||
this.popupVisible = true;
|
||||
|
||||
const params ={id:id}
|
||||
this.$api.page(params).then(res => {
|
||||
//console.log('list', res.data);
|
||||
this.protocolsContent = res.data.content
|
||||
})
|
||||
|
||||
},
|
||||
hidePopup() {
|
||||
this.popupVisible = false;
|
||||
},
|
||||
|
||||
submit() {
|
||||
this.$refs.uForm.validate(valid => {
|
||||
if (valid) {
|
||||
if(!this.agreement) return toast('请查看并同意相关协议');
|
||||
this.$api.register(this.form).then(res => {
|
||||
if(res.code==0){
|
||||
toast(res.msg)
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},1500)
|
||||
|
||||
console.log(res);
|
||||
}else{
|
||||
toast(res.msg)
|
||||
console.log(res);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
console.log(this.form)
|
||||
} else {
|
||||
|
||||
console.log('验证失败');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.popup-content {
|
||||
padding: 40rpx;
|
||||
padding-bottom: 120rpx;
|
||||
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.content{padding:30rpx}
|
||||
.agreement {
|
||||
display: flex;
|
||||
margin: 40rpx 0 0 10rpx;
|
||||
|
||||
.agreement-text {
|
||||
padding-left: 0rpx;
|
||||
color: $u-tips-color;
|
||||
}
|
||||
}
|
||||
.submit_con{margin-top: 20rpx;}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="banner" auto-focus>
|
||||
<image class="banner-img" :src="detail.thumb"></image>
|
||||
<view class="title-area">
|
||||
<text class="title-text">{{detail.title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="article-meta">
|
||||
<text class="article-meta-text article-author">{{detail.source}}</text>
|
||||
<text class="article-meta-text article-text">发表于</text>
|
||||
<text class="article-meta-text article-time">{{detail.addtime}}</text>
|
||||
</view>
|
||||
<view class="article-content">
|
||||
|
||||
|
||||
<view v-html="html"></view>
|
||||
|
||||
|
||||
</view>
|
||||
<view class="comment-wrap"></view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
detail: [],
|
||||
html: ''
|
||||
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
this.id = op.id
|
||||
this.getInfo()
|
||||
|
||||
},
|
||||
onReady() {
|
||||
|
||||
|
||||
},
|
||||
methods: {
|
||||
getInfo(){
|
||||
const params = {
|
||||
id : this.id
|
||||
}
|
||||
this.$api.detail(params).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.detail = res.data
|
||||
this.html = res.data.content
|
||||
console.log( this.html)
|
||||
}else{
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
page {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.banner {
|
||||
height: 380rpx;
|
||||
position: relative;
|
||||
background-color: #ccc;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.banner-img {
|
||||
width:100%
|
||||
}
|
||||
|
||||
.title-area {
|
||||
position: absolute;
|
||||
left: 15rpx;
|
||||
right: 15rpx;
|
||||
bottom: 15rpx;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 40rpx;
|
||||
font-weight: 400;
|
||||
line-height: 20rpx;
|
||||
lines: 2;
|
||||
color: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.article-meta {
|
||||
padding: 10rpx 15rpx;
|
||||
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.article-meta-text {
|
||||
color: gray;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.article-text {
|
||||
font-size: 32rpx;
|
||||
line-height: 25rpx;
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
|
||||
.article-author {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.article-time {
|
||||
font-size:30rpx;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-size: 36rpx;
|
||||
padding: 0 35rpx;
|
||||
margin-bottom: 35rpx;
|
||||
overflow: hidden;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.article-content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.article-content p{line-height:40rpx; margin-top: 40rpx;}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<z-paging ref="paging" v-model="dataList" @query="queryList">
|
||||
<template #top>
|
||||
<z-tabs :list="tabList" @change="tabChange" />
|
||||
</template>
|
||||
|
||||
|
||||
<!-- 如果希望其他view跟着页面滚动,可以放在z-paging标签内 -->
|
||||
<view class="" v-for="(item,index) in dataList" :key="index" @click="itemClick(item)">
|
||||
<u-card :title="item.store_name" :sub-title="item.status" >
|
||||
<view class="" slot="body">
|
||||
<view class="content"><strong>申请:</strong>{{item.master_id}}</view>
|
||||
<view class="content"><strong>时间:</strong>{{item.addtime}}</view>
|
||||
<view class="content"><strong>数量:</strong>{{item.total_nums}}</view>
|
||||
</view>
|
||||
</u-card>
|
||||
</view>
|
||||
|
||||
</z-paging>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dataList: [],
|
||||
tabList: ['全部','已审核','待审核'],
|
||||
tabIndex: 0,
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
tabChange(index) {
|
||||
this.tabIndex = index;
|
||||
this.$refs.paging.reload(true);
|
||||
},
|
||||
|
||||
queryList(pageNo, pageSize) {
|
||||
const params = {
|
||||
page: pageNo,
|
||||
limit: pageSize,
|
||||
type: this.tabIndex + 1
|
||||
}
|
||||
this.$api.outList(params).then(res => {
|
||||
if (res.code == 1) {
|
||||
//将请求的结果数组传递给z-paging
|
||||
this.$refs.paging.complete(res.data);
|
||||
}else{
|
||||
this.$refs.paging.complete(false);
|
||||
}
|
||||
})
|
||||
},
|
||||
itemClick(item) {
|
||||
//console.log(item)
|
||||
uni.navigateTo({
|
||||
url:'./detail?id='+item.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
page{background:#f2f2f2}
|
||||
.content{padding: 20rpx;}
|
||||
</style>
|
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {toast, clearStorageSync, setStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
id: 0
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
//this.id = op.id
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
onReady() {
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
page{background:#f2f2f2}
|
||||
.content{padding: 20rpx;}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
可把模板放在 \HBuilder X\templates\file\vue-page目录下面,这样可以在新建页面中,快速创建。
|
|
@ -0,0 +1,131 @@
|
|||
## 项目说明
|
||||
|
||||
本项目可以快速搭建uni-app项目,封装request,集成z-paging(下拉刷新,上拉加载),带页面拦截器,请求锁,请求loading,集成uview,集成在线更新组件,集成本地调试工具vconsole、分包。
|
||||
|
||||
## 接口开发
|
||||
|
||||
接口服务器地址文件:**api/env.js**,修改服务器地址:
|
||||
|
||||
```json
|
||||
let BASE_URL
|
||||
//开发环境中
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// 开发环境
|
||||
BASE_URL = 'https://mock.apifox.com/m1/3553664-0-default' //开发环境请求地址
|
||||
} else {
|
||||
// 生产环境
|
||||
BASE_URL = 'https://mock.apifox.com/m1/3553664-0-default' //生成环境请求地址
|
||||
}
|
||||
|
||||
export default BASE_URL
|
||||
```
|
||||
|
||||
接口文件:**api/api.js**,在里面定义相关接口地址即可。
|
||||
|
||||
```json
|
||||
//列表,GET方式请求
|
||||
export const getList = data => request.get('/api/list', data)
|
||||
//登陆,POST方式请求
|
||||
export const login = data => request.post('/api/login', data)
|
||||
//检测版本升级,POST方式请求,第三个参数(false)不显示loading加载
|
||||
export const checkVersion = data => request.post('/api/checkVersion', data,false)
|
||||
```
|
||||
|
||||
页面中调用的方法:
|
||||
|
||||
GET或POST调用如下:(无须导入接口方法,已在全局文件main.js中引入)
|
||||
|
||||
```json
|
||||
//请求参数
|
||||
const params = {
|
||||
page: pageNo,
|
||||
limit: pageSize
|
||||
}
|
||||
//getList即对应api.js中的接口
|
||||
this.$api.getList(params).then(res => {
|
||||
//todo....
|
||||
})
|
||||
```
|
||||
|
||||
## 页面拦截器
|
||||
|
||||
本项目集成了页面拦截器,页面拦截器即表示在白名单的页面URL不拦截,其他页面则拦截。
|
||||
|
||||
场景:办公OA APP,只有登陆页面不需要拦截,其他页面则需要拦截。
|
||||
|
||||
拦截器与token搭配使用,若是本地无TOKE,APP启动时打开首页,则自动会跳转到登陆页。若本地存在TOKEN,则打开首页时不会再要求登陆。
|
||||
|
||||
页面拦截器配置文件在**config/config.js**
|
||||
|
||||
以OA为例,登陆页不需要拦截则设置如下,还可添加其他不需要拦截的页面。
|
||||
|
||||
```json
|
||||
let config = {
|
||||
//不拦截页面路径
|
||||
whiteList: [
|
||||
'/pages/public/login'
|
||||
],
|
||||
token : 'token', //本地存储token的变量名
|
||||
login_page : '/pages/public/login' //拦截后跳转的登陆页路径
|
||||
}
|
||||
```
|
||||
|
||||
注:封装请求文件(/utils/request.js)中,若服务器返回错误码大于400,则也跳转登陆页。
|
||||
|
||||
```
|
||||
if(res.code > 400){
|
||||
clearStorageSync('token')
|
||||
useRouter(systemConfig.login_page, 'reLaunch')
|
||||
}else{
|
||||
reslove(res)
|
||||
}
|
||||
```
|
||||
|
||||
## 在线升级
|
||||
|
||||
本项目集成了在线升级组件(仅支持APP),文件在:**components/appUpdate**,是否更新需要服务器返回如下JSON信息:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"platform": "android",
|
||||
"version": "1.3.0",
|
||||
"downUrl": "下载地址",
|
||||
"updateContent": "修复BUG",
|
||||
"force" : 0
|
||||
}
|
||||
```
|
||||
|
||||
> code为0时会提示更新,1则不弹出更新窗口。
|
||||
>
|
||||
> 测试更新弹出窗口,可修改api.js中的检测更新接口地址为:/api/checkVersion2
|
||||
|
||||
## 本地调试工具vconsole
|
||||
|
||||
本项目集成了本地调试工具vconsole,主要用于在生成APP或小程序后方便调试检查错误。
|
||||
|
||||
若不需要开启,可以修改配置文件config/config.js是否开启:
|
||||
|
||||
`vconsole_status: 1, //是否启用调试工具,1为启用,0不启用`
|
||||
|
||||
## 分包
|
||||
|
||||
增加分包功能,分包功能主要针对微信小程序,分包配置在pages.json中subPackages段内。如果不需要分包可以删除,并修改manifest.json 中"mp-weixin“段中 ` "subPackages" : true` 删除。
|
||||
|
||||
## 集成UI
|
||||
|
||||
本项目含集成了uview,z-paging,具体使用方法见官方文档。
|
||||
|
||||
uview官方文档:[介绍 | uView - 多平台快速开发的UI框架 - uni-app UI框架](https://v1.uviewui.com/components/intro.html)
|
||||
|
||||
z-paging官方文档:[介绍 | z-paging文档](https://z-paging.zxlee.cn/start/intro.html)(非常方便的实现上拉加载、下拉刷新等功能)
|
||||
|
||||
## 其他说明
|
||||
|
||||
**下载说明:建议单独下载文件后并解压,并在HB中打开目录进行演示,不要覆盖现在项目。**
|
||||
|
||||
注:本项目中接口服务器和数据为mock数据,运行即可看到数据。
|
||||
|
||||
登陆: 随机输入用户名和密码都可以登陆成功。
|
||||
|
||||
如果在使用过程中遇到问题,可以在评论区反馈也可加微信liuyan814。
|
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 403 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 466 B |
After Width: | Height: | Size: 477 B |
|
@ -0,0 +1,27 @@
|
|||
import { mapState } from 'vuex'
|
||||
import store from "@/store"
|
||||
|
||||
// 尝试将用户在根目录中的store/index.js的vuex的state变量,全部加载到全局变量中
|
||||
let $uStoreKey = [];
|
||||
try{
|
||||
$uStoreKey = store.state ? Object.keys(store.state) : [];
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
created() {
|
||||
// 将vuex方法挂在到$u中
|
||||
// 使用方法为:如果要修改vuex的state中的user.name变量为"史诗" => this.$u.vuex('user.name', '史诗')
|
||||
// 如果要修改vuex的state的version变量为1.0.1 => this.$u.vuex('version', '1.0.1')
|
||||
this.$u.vuex = (name, value) => {
|
||||
this.$store.commit('$uStore', {
|
||||
name,value
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 将vuex的state中的所有变量,解构到全局混入的mixin中
|
||||
...mapState($uStoreKey)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
Vue.use(Vuex)
|
||||
|
||||
let lifeData = {};
|
||||
|
||||
try{
|
||||
// 尝试获取本地是否存在lifeData变量,第一次启动APP时是不存在的
|
||||
lifeData = uni.getStorageSync('lifeData');
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
|
||||
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
||||
let saveStateKeys = ['vuex_user', 'vuex_token'];
|
||||
|
||||
// 保存变量到本地存储中
|
||||
const saveLifeData = function(key, value){
|
||||
// 判断变量名是否在需要存储的数组中
|
||||
if(saveStateKeys.indexOf(key) != -1) {
|
||||
// 获取本地存储的lifeData对象,将变量添加到对象中
|
||||
let tmp = uni.getStorageSync('lifeData');
|
||||
// 第一次打开APP,不存在lifeData变量,故放一个{}空对象
|
||||
tmp = tmp ? tmp : {};
|
||||
tmp[key] = value;
|
||||
// 执行这一步后,所有需要存储的变量,都挂载在本地的lifeData对象中
|
||||
uni.setStorageSync('lifeData', tmp);
|
||||
}
|
||||
}
|
||||
const store = new Vuex.Store({
|
||||
// 下面这些值仅为示例,使用过程中请删除
|
||||
state: {
|
||||
// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
|
||||
// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
|
||||
vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {name: '明月'},
|
||||
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
|
||||
// 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式
|
||||
vuex_version: '1.0.1',
|
||||
},
|
||||
mutations: {
|
||||
$uStore(state, payload) {
|
||||
// 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
|
||||
let nameArr = payload.name.split('.');
|
||||
let saveKey = '';
|
||||
let len = nameArr.length;
|
||||
if(nameArr.length >= 2) {
|
||||
let obj = state[nameArr[0]];
|
||||
for(let i = 1; i < len - 1; i ++) {
|
||||
obj = obj[nameArr[i]];
|
||||
}
|
||||
obj[nameArr[len - 1]] = payload.value;
|
||||
saveKey = nameArr[0];
|
||||
} else {
|
||||
// 单层级变量,在state就是一个普通变量的情况
|
||||
state[payload.name] = payload.value;
|
||||
saveKey = payload.name;
|
||||
}
|
||||
// 保存变量到本地,见顶部函数定义
|
||||
saveLifeData(saveKey, state[saveKey])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default store
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
@import '@/uni_modules/uview-ui/theme.scss';
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color:#333;//基本色
|
||||
$uni-text-color-inverse:#fff;//反色
|
||||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable:#c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color:#ffffff;
|
||||
$uni-bg-color-grey:#f8f8f8;
|
||||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color:#c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm:12px;
|
||||
$uni-font-size-base:14px;
|
||||
$uni-font-size-lg:16;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm:20px;
|
||||
$uni-img-size-base:26px;
|
||||
$uni-img-size-lg:40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2C405A; // 文章标题颜色
|
||||
$uni-font-size-title:20px;
|
||||
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||
$uni-font-size-subtitle:26px;
|
||||
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||
$uni-font-size-paragraph:15px;
|
|
@ -0,0 +1,88 @@
|
|||
//获取当前时间,格式YYYY-MM-DD HH:MM:SS
|
||||
const GetNowTime = time => {
|
||||
var date = time,
|
||||
year = date.getFullYear(),
|
||||
month = date.getMonth() + 1,
|
||||
day = date.getDate(),
|
||||
hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(),
|
||||
minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(),
|
||||
second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
|
||||
month >= 1 && month <= 9 ? (month = "0" + month) : "";
|
||||
day >= 0 && day <= 9 ? (day = "0" + day) : "";
|
||||
// var timer = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
|
||||
var timer = year + '-' + month + '-' + day;
|
||||
return timer;
|
||||
}
|
||||
|
||||
// 格式化电话号码
|
||||
const GetPhone = phone => {
|
||||
let tel = phone.slice(0, 3) + '****' + phone.slice(7, 11);
|
||||
return tel;
|
||||
}
|
||||
//返回日期和周几数组
|
||||
function weekDate() {
|
||||
const myDate = new Date();
|
||||
const padZero = num => String(num).padStart(2, '0'); // 补零工具函数
|
||||
|
||||
const dayList = [];
|
||||
|
||||
// 生成当天数据(补零)
|
||||
dayList.push({
|
||||
day: padZero(myDate.getDate()),
|
||||
month: padZero(myDate.getMonth() + 1),
|
||||
week: toWeekDay(myDate.getDay()),
|
||||
year: myDate.getFullYear()
|
||||
});
|
||||
|
||||
// 生成后续10天数据
|
||||
for (let i = 0; i < 10; i++) {
|
||||
myDate.setDate(myDate.getDate() + 1);
|
||||
dayList.push({
|
||||
day: padZero(myDate.getDate()),
|
||||
month: padZero(myDate.getMonth() + 1),
|
||||
week: toWeekDay(myDate.getDay()),
|
||||
year: myDate.getFullYear()
|
||||
});
|
||||
}
|
||||
|
||||
// 返回标准化日期格式
|
||||
return {
|
||||
dayList,
|
||||
StartDate: `${dayList[0].year}-${dayList[0].month}-${dayList[0].day}`,
|
||||
EndDate: `${dayList[dayList.length - 1].year}-${dayList[dayList.length - 1].month}-${dayList[dayList.length - 1].day}`
|
||||
};
|
||||
}
|
||||
|
||||
function toWeekDay(weekDay) { // 传入数据 讲一周的某一天返回成中文状态下的字符
|
||||
switch (weekDay) {
|
||||
case 1:
|
||||
return '一';
|
||||
break;
|
||||
case 2:
|
||||
return '二';
|
||||
break;
|
||||
case 3:
|
||||
return '三';
|
||||
break;
|
||||
case 4:
|
||||
return '四';
|
||||
break;
|
||||
case 5:
|
||||
return '五';
|
||||
break;
|
||||
case 6:
|
||||
return '六';
|
||||
break;
|
||||
case 0:
|
||||
return '日';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return '传入未知参数';
|
||||
}
|
||||
module.exports = {
|
||||
GetNowTime,
|
||||
GetPhone,
|
||||
weekDate
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
import systemConfig from '@/config/config.js';
|
||||
// 页面白名单,不受拦截
|
||||
const whiteList = systemConfig.whiteList
|
||||
function hasPermission (url) {
|
||||
let islogin = uni.getStorageSync(systemConfig.token );//isLogin是登录成功后在本地存储登录标识,存储一个能够判断用户登录的唯一标识就行
|
||||
// 在白名单中或有登录判断条件可以直接跳转
|
||||
if(whiteList.indexOf(url) !== -1 || islogin) {
|
||||
//console.log('通过')
|
||||
return true
|
||||
}
|
||||
//console.log('失败')
|
||||
return false
|
||||
}
|
||||
uni.addInterceptor('navigateTo', {
|
||||
// 页面跳转前进行拦截, invoke根据返回值进行判断是否继续执行跳转
|
||||
invoke (e) {
|
||||
const url = e.url.split('?')[0]
|
||||
if(!hasPermission(url)){
|
||||
uni.reLaunch({
|
||||
url:systemConfig.login_page
|
||||
})
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
success (e) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
uni.addInterceptor('switchTab', {
|
||||
// tabbar页面跳转前进行拦截
|
||||
invoke (e) {
|
||||
|
||||
const url = e.url.split('?')[0]
|
||||
if(!hasPermission(url)){
|
||||
uni.reLaunch({
|
||||
url: systemConfig.login_page
|
||||
})
|
||||
//console.log('不在白名单内')
|
||||
return false
|
||||
}
|
||||
//console.log('在白名单内')
|
||||
return true
|
||||
},
|
||||
success (e) {
|
||||
|
||||
}
|
||||
})
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
|
||||
import BASE_URL from '@/api/env.js' //引入接口共用地址
|
||||
import RequestManager from '@/utils/requestManager.js'
|
||||
import {toast, clearStorageSync, getStorageSync, useRouter} from '@/utils/utils.js'
|
||||
import systemConfig from '@/config/config.js';
|
||||
const manager = new RequestManager()
|
||||
|
||||
const baseRequest = async (url, method, data = {}, loading = true) =>{
|
||||
let requestId = manager.generateId(method, url, data)
|
||||
if(!requestId) {
|
||||
console.log('重复请求')
|
||||
}
|
||||
if(!requestId)return false;
|
||||
|
||||
const header = {}
|
||||
header.Authorization = getStorageSync(systemConfig.token) || ''
|
||||
return new Promise((reslove, reject) => {
|
||||
loading && uni.showLoading({title: 'loading'})
|
||||
uni.request({
|
||||
url: BASE_URL + url,
|
||||
method: method || 'GET',
|
||||
header: header,
|
||||
timeout: 10000,
|
||||
data: data || {},
|
||||
complete: ()=>{
|
||||
uni.hideLoading()
|
||||
manager.deleteById(requestId)
|
||||
},
|
||||
success: (successData) => {
|
||||
//console.log(successData)
|
||||
const res = successData.data
|
||||
if(successData.statusCode == 200){
|
||||
// 业务逻辑,自行修改,401是服务器上返回该token过期,过期后跳转到登陆页面
|
||||
if(res.code > 400){
|
||||
clearStorageSync('token')
|
||||
useRouter(systemConfig.login_page, 'reLaunch')
|
||||
}else{
|
||||
reslove(res)
|
||||
}
|
||||
}else{
|
||||
console.log('网络连接失败,请稍后重试' ,url)
|
||||
toast('网络连接失败,请稍后重试')
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: (msg) => {
|
||||
console.log("请求:"+BASE_URL + url +',发生错误:', err)
|
||||
toast('网络连接失败,请稍后重试')
|
||||
reject(msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const request = {};
|
||||
|
||||
['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
|
||||
request[method] = (api, data, loading) => baseRequest(api, method, data, loading)
|
||||
})
|
||||
|
||||
export default request
|
|
@ -0,0 +1,66 @@
|
|||
class RequestManager {
|
||||
constructor() {
|
||||
this.idMap = new Map()
|
||||
}
|
||||
/**
|
||||
* 生成唯一ID,并将ID和请求信息存储到map对象中
|
||||
* @param {string} method - 请求方法
|
||||
* @param {string} url - 请求URL
|
||||
* @param {object} params - 请求参数
|
||||
* @returns {string|boolean} - 生成的唯一ID,如果存在相同请求则返回false
|
||||
*/
|
||||
generateId(method, url, params) {
|
||||
const id = this.generateUniqueId(method, url, params)
|
||||
if (this.idMap.has(id)) {
|
||||
return false
|
||||
}
|
||||
this.idMap.set(id, { method, url, params })
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID删除map对象中的请求信息
|
||||
* @param {string} id - 要删除的唯一ID
|
||||
*/
|
||||
deleteById(id) {
|
||||
this.idMap.delete(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一ID的方法
|
||||
* @param {string} method - 请求方法
|
||||
* @param {string} url - 请求URL
|
||||
* @param {object} params - 请求参数
|
||||
* @returns {string} - 生成的唯一ID
|
||||
*/
|
||||
generateUniqueId(method, url, params) {
|
||||
const idString = `${method}-${url}-${this.serializeObject(params)}`
|
||||
let id = 0;
|
||||
for (let i = 0; i < idString.length; i++) {
|
||||
id = ((id << 5) - id) + idString.charCodeAt(i)
|
||||
id |= 0;
|
||||
}
|
||||
return id.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象为字符串
|
||||
* @param {object} obj - 要序列化的对象
|
||||
* @returns {string} - 序列化后的字符串
|
||||
*/
|
||||
serializeObject(obj) {
|
||||
const keys = Object.keys(obj).sort()
|
||||
const serializedObj = {}
|
||||
for (let key of keys) {
|
||||
const value = obj[key]
|
||||
if (value !== null && typeof value === 'object') {
|
||||
serializedObj[key] = this.serializeObject(value)
|
||||
} else {
|
||||
serializedObj[key] = value
|
||||
}
|
||||
}
|
||||
return JSON.stringify(serializedObj)
|
||||
}
|
||||
}
|
||||
|
||||
export default RequestManager
|
|
@ -0,0 +1,475 @@
|
|||
/**
|
||||
* 提示方法
|
||||
* @param {String} title 提示文字
|
||||
* @param {String} icon icon图片
|
||||
* @param {Number} duration 提示时间
|
||||
*/
|
||||
export function toast(title, icon = 'none', duration = 1500) {
|
||||
if(title) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon,
|
||||
duration
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} url
|
||||
* @return {function}
|
||||
* @description navigateTo跳转
|
||||
*/
|
||||
export function Jump(url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 提示信息
|
||||
* **/
|
||||
export function showModal(title, msg, showCancel) {
|
||||
uni.showModal({
|
||||
title: title,
|
||||
content: msg,
|
||||
showCancel: showCancel,
|
||||
success: function(res) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function showLoading(content) {
|
||||
uni.showLoading({
|
||||
title: content
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 隐藏loading
|
||||
* **/
|
||||
export function hideLoading() {
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
/***
|
||||
* 获取时间戳
|
||||
*/
|
||||
export function getTimStamp() {
|
||||
var timestamp = Date.parse(new Date());
|
||||
timestamp = timestamp / 1000;
|
||||
return timestamp;
|
||||
}
|
||||
/***
|
||||
* 生成随机数
|
||||
*/
|
||||
export function getNonce() {
|
||||
var t = '';
|
||||
for (var i = 0; i < 12; i++) {
|
||||
t += Math.floor(Math.random() * 10);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
/**
|
||||
* 获取32位随机数
|
||||
* ***/
|
||||
export function getnoncestr() {
|
||||
let len = len || 32;
|
||||
var $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var maxPos = $chars.length;
|
||||
var pwd = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return pwd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析url中的参数
|
||||
*/
|
||||
export function UrlParamHash(url) {
|
||||
var params = {},
|
||||
h;
|
||||
var hash = url.slice(url.indexOf("?") + 1).split("&");
|
||||
for (var i = 0; i < hash.length; i++) {
|
||||
h = hash[i].split("=");
|
||||
if (h.length > 1) {
|
||||
params[h[0]] = h[1];
|
||||
} else {
|
||||
params[h[0]] = "";
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一键复制 uni.setClipboardData
|
||||
* 用法:
|
||||
* 1. import {setClipboardData} from '该文件的地址'
|
||||
* 2. 利用async await
|
||||
* 3. await setClipboardData(需要复制的文本)
|
||||
*/
|
||||
const setClipboardData = (text) =>{
|
||||
return new Promise((resolve,reject)=>{
|
||||
uni.setClipboardData({
|
||||
data: text,
|
||||
success: (res) => {
|
||||
resolve(res)
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统剪贴板内容 uni.getClipboardData
|
||||
* 用法:
|
||||
* 1. import {getClipboardData} from '该文件的地址'
|
||||
* 2. 利用async await来接收获取到的数据
|
||||
* 3. await getClipboardData()
|
||||
*/
|
||||
const getClipboardData = () =>{
|
||||
return new Promise((resolve,reject)=>{
|
||||
uni.getClipboardData({
|
||||
success: (res) => {
|
||||
resolve(res)
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拨打电话 uni.makePhoneCall()
|
||||
* 用法:
|
||||
* 1. import {getBatteryInfo} from '该文件的地址'
|
||||
* 2. 直接makePhoneCall(拨打的电话号码)
|
||||
*/
|
||||
const makePhoneCall = (phone) =>{
|
||||
uni.makePhoneCall({
|
||||
phoneNumber:phone
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
* @param {String} key 键名
|
||||
* @param {String} data 值
|
||||
*/
|
||||
export function setStorageSync(key, data) {
|
||||
uni.setStorageSync(key, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
* @param {String} key 键名
|
||||
*/
|
||||
export function getStorageSync(key) {
|
||||
return uni.getStorageSync(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @param {String} key 键名
|
||||
*/
|
||||
export function removeStorageSync(key) {
|
||||
return uni.removeStorageSync(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
* @param {String} key 键名
|
||||
*/
|
||||
export function clearStorageSync() {
|
||||
return uni.clearStorageSync()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 页面跳转
|
||||
* @param {'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab' | 'navigateBack' | number } url 转跳路径
|
||||
* @param {String} params 跳转时携带的参数
|
||||
* @param {String} type 转跳方式
|
||||
**/
|
||||
export function useRouter(url, params = {}, type = 'navigateTo') {
|
||||
try {
|
||||
if (Object.keys(params).length) url = `${url}?data=${encodeURIComponent(JSON.stringify(params))}`
|
||||
if (type === 'navigateBack') {
|
||||
uni[type]({ delta: url })
|
||||
} else {
|
||||
uni[type]({ url })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览图片
|
||||
* @param {Array} urls 图片链接
|
||||
*/
|
||||
export function previewImage(urls, itemList = ['发送给朋友', '保存图片', '收藏']) {
|
||||
uni.previewImage({
|
||||
urls,
|
||||
longPressActions: {
|
||||
itemList,
|
||||
fail: function (error) {
|
||||
console.error(error,'===previewImage')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存图片到本地
|
||||
* @param {String} filePath 图片临时路径
|
||||
**/
|
||||
export function saveImage(filePath) {
|
||||
if (!filePath) return false
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath,
|
||||
success: (res) => {
|
||||
toast('图片保存成功', 'success')
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err.errMsg === 'saveImageToPhotosAlbum:fail:auth denied' || err.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '需要您授权保存相册',
|
||||
showCancel: false,
|
||||
success: (modalSuccess) => {
|
||||
uni.openSetting({
|
||||
success(settingdata) {
|
||||
if (settingdata.authSetting['scope.writePhotosAlbum']) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '获取权限成功,再次点击图片即可保存',
|
||||
showCancel: false
|
||||
})
|
||||
} else {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '获取权限失败,将无法保存到相册哦~',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
},
|
||||
fail(failData) {
|
||||
console.log('failData', failData)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝
|
||||
* @param {Object} data
|
||||
**/
|
||||
export const clone = (data) => JSON.parse(JSON.stringify(data))
|
||||
/**
|
||||
* 获取平台名称
|
||||
* @return {string} 平台名称
|
||||
*/
|
||||
export function getPlatform() {
|
||||
let platform;
|
||||
switch (process.env.VUE_APP_PLATFORM) {
|
||||
case 'app':
|
||||
case 'app-plus':
|
||||
let n = uni.getSystemInfoSync().platform.toLowerCase();
|
||||
if (n === 'ios') {
|
||||
platform = 'ios';
|
||||
} else if (n === 'android') {
|
||||
platform = 'android';
|
||||
} else {
|
||||
platform = 'app';
|
||||
}
|
||||
break;
|
||||
case 'mp-weixin':
|
||||
platform = 'wx';
|
||||
break;
|
||||
case 'mp-alipay':
|
||||
platform = 'alipay';
|
||||
break;
|
||||
case 'mp-baidu':
|
||||
platform = 'baidu';
|
||||
break;
|
||||
case 'mp-qq':
|
||||
platform = 'qq';
|
||||
break;
|
||||
case 'mp-toutiao':
|
||||
platform = 'toutiao';
|
||||
break;
|
||||
case 'quickapp-webview':
|
||||
platform = 'kuai';
|
||||
break;
|
||||
}
|
||||
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组去重
|
||||
* @param {Array} array 数值
|
||||
* @retrun {Array} 数值
|
||||
*/
|
||||
export function arrayShuffle(array) {
|
||||
let i = array.length, t, j;
|
||||
while (i) {
|
||||
j = Math.floor(Math.random() * i--);
|
||||
t = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = t;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
* @param {Date} date 日期
|
||||
* @param {string} format 返回的日期格式
|
||||
* @retrun {string} 日期
|
||||
*/
|
||||
export function dateFormat(date, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
const config = {
|
||||
YYYY: date.getFullYear(),
|
||||
MM: date.getMonth()+1,
|
||||
DD: date.getDate(),
|
||||
HH: date.getHours(),
|
||||
mm: date.getMinutes(),
|
||||
ss: date.getSeconds(),
|
||||
}
|
||||
for(const key in config){
|
||||
let value = config[key];
|
||||
if (value < 10) {
|
||||
value = '0' + value;
|
||||
}
|
||||
format = format.replace(key, value)
|
||||
}
|
||||
return format
|
||||
}
|
||||
|
||||
/**
|
||||
* base64转文件
|
||||
* @param {string} base64data base64
|
||||
* @param {Function} cb 回调
|
||||
*/
|
||||
export function base64ToSrc(base64data, cb) {
|
||||
const FILE_BASE_NAME = 'tmp_base64src';
|
||||
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
|
||||
if (!format) {
|
||||
return (new Error('格式错误'));
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
let filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
|
||||
// #endif
|
||||
// #ifdef MP-QQ
|
||||
let filePath = `${qq.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
|
||||
// #endif
|
||||
|
||||
const buffer = uni.base64ToArrayBuffer(bodyData);
|
||||
uni.getFileSystemManager().writeFile({
|
||||
filePath,
|
||||
data: buffer,
|
||||
encoding: 'binary',
|
||||
success() {
|
||||
cb && cb(filePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
* @param {string} str str
|
||||
* @param {string}
|
||||
*/
|
||||
export function encodeBase64(str) {
|
||||
return new Buffer.from(str).toString('base64');
|
||||
}
|
||||
|
||||
/**
|
||||
* base64解码
|
||||
* @param {string} str str
|
||||
* @param {string}
|
||||
*/
|
||||
export function decodeBase64(str) {
|
||||
const commonContent = str.replace(/\s/g, '+');
|
||||
return new Buffer.from(commonContent, 'base64').toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放声音
|
||||
* @param {string} src 声音文件地址
|
||||
* @param {Boolean} loop 是否循环
|
||||
*/
|
||||
export function playSound(src, loop = false) {
|
||||
const innerAudioContext = uni.createInnerAudioContext();
|
||||
innerAudioContext.autoplay = true;
|
||||
innerAudioContext.loop = loop;
|
||||
innerAudioContext.src = src;
|
||||
innerAudioContext.onPlay(() => {});
|
||||
innerAudioContext.onError((res) => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单ID
|
||||
* @param {string} prefix 订单前缀
|
||||
* @param {string} 订单ID
|
||||
*/
|
||||
export function createOrderSn(prefix = '') {
|
||||
return `${prefix}${this.randomString(10).toUpperCase()}${+new Date()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片转base64
|
||||
* @param {string} src 图片地址
|
||||
* @return {Promise} base64
|
||||
*/
|
||||
export function imageToBase64(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getImageInfo({
|
||||
src,
|
||||
success: image => {
|
||||
console.log(image);
|
||||
uni.getFileSystemManager().readFile({
|
||||
filePath: image.path,
|
||||
encoding: 'base64',
|
||||
success: e => {
|
||||
return resolve(`data:image/jpeg;base64,${e.data}`);
|
||||
},
|
||||
fail: e => {
|
||||
return reject(null);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 随机范围内的数字
|
||||
* @param {number} start 起始数字
|
||||
* @param {number} end 起始数字
|
||||
* @return {number || null} 随机数
|
||||
*/
|
||||
export function randomByRange(start, end){
|
||||
if (typeof start === 'number' && typeof end === 'number') {
|
||||
return start + Math.floor(Math.random() * (end - start));
|
||||
} else {
|
||||
console.error('参数必须为数字');
|
||||
return null;
|
||||
}
|
||||
}
|