初始化

This commit is contained in:
2023-12-29 00:08:10 +08:00
commit 5ed0fc646f
512 changed files with 54378 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
node_modules
unpackage/cache
unpackage/dist
unpackage/release
.hbuilderx
.idea
.vscode

52
App.vue Normal file
View File

@@ -0,0 +1,52 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
@import "uview-ui/index.scss";
html,
body {
overflow: hidden;
height: 100vh;
}
@font-face {
font-family: caisemenghuanjingyu;
src: url(@/static/caisemenghuanjingyu.ttf);
}
body {
background-image: linear-gradient(to bottom right, #fdebe6, #f7f7f7);
}
uni-page-body {
// padding: 44px 0 0 0;
overflow: hidden;
height: 100%;
}
.uni-page {
// #ifdef MP-WEIXIN
// padding-top: 180rpx;
// #endif
height: 100%;
overflow: auto;
padding-left: 20rpx;
padding-right: 20rpx;
width: calc(100% - 40rpx);
// padding: 44px 20rpx 50px 20rpx;
}
</style>

56
README.md Normal file
View File

@@ -0,0 +1,56 @@
# 项目资源
## 后端接口文档
https://jx.xiaolinghou.com/api.html
## 微信配置
**公众号appid:** wx877c9b57a770f86e
**小程序appid:** wxd3ef894000268f39
**公众号appsecret:** 08981c42f32bf9433dd6217cac6ffc81
**令牌(Token):** i6x66atmwq5db2786357hxtrwg4nkpue
**消息加解密(AESKey):** qa6h5y6qbx85gv8ceda42nn9buyfdje5r7ui94sstny
## 短信平台配置
[阿里云短信平台](https://www.aliyun.com/product/sms)
**AccessKey ID** LTAI5tFM2EoRya9TB32GwQGf
**Secret** wF7opAyy2MNh9aPszWPFXPBKxuzhkp
**TemplateParam短信模板变量对应的实际值** {"code":"1234"}
## 所用UI
https://lanhuapp.com/link/#/invite?sid=lxr2dzba
分享人: 519838418
团队名称: 智能寄信的团队
相关项目: 智能寄信
链接有效期: 20230712~20230726
## 所用插件
Icon: https://iconpark.oceanengine.com/official
UI: https://www.uviewui.com/components/intro.html
路由: https://www.hhyang.cn/v2/start/quickstart.html
请求: https://www.quanzhan.co/luch-request/guide/3.x/
## 以下页面许自行设计
![在这里插入图片描述](https://git.yoyij.com/WangMing/mapDepot/raw/branch/main/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20230712221507.jpg)

49
components/Copy/Copy.vue Normal file
View File

@@ -0,0 +1,49 @@
<template>
<view class="copy" @click="onCopy">
<svg :width="size" :height="size" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 12.4316V7.8125C13 6.2592 14.2592 5 15.8125 5H40.1875C41.7408 5 43 6.2592 43 7.8125V32.1875C43 33.7408 41.7408 35 40.1875 35H35.5163" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M32.1875 13H7.8125C6.2592 13 5 14.2592 5 15.8125V40.1875C5 41.7408 6.2592 43 7.8125 43H32.1875C33.7408 43 35 41.7408 35 40.1875V15.8125C35 14.2592 33.7408 13 32.1875 13Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/></svg>
</view>
</template>
<script>
export default {
name:"Copy",
props: {
size: {
default: 14,
type: Number | String
},
text: {
default: '',
type: String
},
successText: {
default: '已复制',
type: String
}
},
data() {
return {
};
},
methods: {
onCopy() {
uni.setClipboardData({
data: this.text,
success: ()=> {
uni.showToast({
title: this.successText,
icon: 'success'
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.copy {
}
</style>

View File

@@ -0,0 +1,46 @@
<template>
<text>
{{ loadText }}
</text>
</template>
<script>
export default {
name:"LoadMessage",
props: {
text: {
type: String,
default: ''
}
},
data() {
return {
loadText: ''
}
},
watch: {
text: {
immediate: true,
handler(newVal) {
let strList = this.text.split('');
let newList = [];
let index = 0;
let timer = setInterval(()=> {
if(index < strList.length) {
newList.push(strList[index]);
index++;
this.loadText = newList.join('');
} else {
clearInterval(timer);
}
}, 50)
}
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,87 @@
<template>
<view class="pay-pattern">
<u-radio-group :value="value" placement="column" @change="groupChange">
<view class="patter-item" v-for="pattern in payPatternList" :key="pattern.id" @click="change(pattern)">
<view class="patter-icon" style="width: 50rpx;height: 50rpx;">
<image :src="pattern.iconUrl" mode="" style="width: 100%;height: 100%"></image>
</view>
<view class="patter-name">
{{pattern.title}}
</view>
<view class="patter-chenck-box">
<u-radio :name="pattern.id" activeColor="#E39B46"></u-radio>
</view>
</view>
</u-radio-group>
</view>
</template>
<script>
export default {
name: "Pay-patter",
props: {
value: {
default: 1
},
payPatternList: {
type: Array,
default: () => [{
title: '微信支付',
iconUrl: '/static/12微信支付@2x.png',
// #ifdef H5
id: 0,
// #endif
// #ifdef MP-WEIXIN
id: 2,
// #endif
}, {
title: '余额支付',
iconUrl: '/static/12余额支付@2x.png',
id: 1,
}]
}
},
data() {
return {
radioValue: 1
};
},
onReady() {
this.radioValue = this.value
},
methods: {
change(pattern) {
this.$emit('change', pattern.id)
this.$emit('input', pattern.id)
},
groupChange(id) {
this.$emit('change', id)
this.$emit('input', id)
},
}
}
</script>
<style scoped lang="scss">
.pay-pattern {
display: flex;
flex-direction: column;
}
.patter-item {
display: flex;
align-items: center;
// padding: ;
margin: 20rpx 0;
}
.patter-name {
flex: 1;
}
.patter-icon {
// height: 100%;
margin-right: 30rpx;
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<view class="pay-pattern">
<u-radio-group :value="value" placement="column" @change="groupChange">
<view class="patter-item" v-for="pattern in payPatternList" :key="pattern.id" @click="change(pattern)">
<view class="patter-icon" style="width: 50rpx;height: 50rpx;">
<image :src="pattern.iconUrl" mode="" style="width: 100%;height: 100%"></image>
</view>
<view class="patter-name">
{{pattern.title}}
</view>
<view class="patter-chenck-box">
<u-radio :name="pattern.id" activeColor="#E39B46"></u-radio>
</view>
</view>
</u-radio-group>
</view>
</template>
<script>
export default {
name: "PayType",
props: {
value: {
default: 1
},
payPatternList: {
type: Array,
default: () => [{
title: '微信支付',
iconUrl: '/static/12微信支付@2x.png',
// #ifdef H5
id: 'wechat',
// #endif
// #ifdef MP-WEIXIN
id: 'routine',
// #endif
}, {
title: '余额支付',
iconUrl: '/static/12余额支付@2x.png',
id: 1,
}]
}
},
data() {
return {
radioValue: 1
};
},
onReady() {
this.radioValue = this.value
},
methods: {
change(pattern) {
this.$emit('change', pattern.id)
this.$emit('input', pattern.id)
},
groupChange(id) {
this.$emit('change', id)
this.$emit('input', id)
},
}
}
</script>
<style scoped lang="scss">
.pay-pattern {
display: flex;
flex-direction: column;
}
.patter-item {
display: flex;
align-items: center;
// padding: ;
margin: 20rpx 0;
}
.patter-name {
flex: 1;
}
.patter-icon {
// height: 100%;
margin-right: 30rpx;
}
</style>

View File

@@ -0,0 +1,93 @@
<template>
<u-popup
style="position: absolute"
:show="isViewLetter"
@close="close"
:closeable="true"
mode="center"
customStyle="border-radius: 40rpx;"
>
<view class="content-main">
<view class="content-title"> 请选择制作方式 </view>
<view
class="content-item"
v-for="(item ,index) in productionType"
:key="item.id"
>
<view class="content-item-button" @click="$emit('selectPlan', item)">
{{ item.title }}
</view>
<view class="content-item-explain">
{{ item.explain }}
<text style="color: #ce7a2c" v-if="item.price">{{ item.price }}</text
>{{ item.price ? "元/次" : "" }}
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name: "SelectProductionMethod",
created() {
this.productionType = this.$store.productionType;
console.log(this.productionType, "111111111111111");
},
data() {
return {
isViewLetter: true,
productionType: false,
};
},
methods: {
close() {
this.$emit("close");
},
},
};
</script>
<style lang="scss">
.content-main {
width: 600rpx;
height: 654rpx;
box-sizing: border-box;
padding: 30rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.content-title {
width: 238rpx;
height: 45rpx;
font-size: 34rpx;
font-weight: bold;
margin-bottom: 30rpx;
}
.content-item-button {
margin-top: 40rpx;
flex: 1;
background: linear-gradient(to bottom right, #e8b648, #e08745);
height: 80rpx;
width: 500rpx;
font-size: 34rpx;
border-radius: 20rpx;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
.content-item-explain {
width: 100%;
font-size: 26rpx;
font-family: OPPOSans Regular-Regular, OPPOSans Regular;
font-weight: 400;
color: #111111;
text-align: center;
margin-top: 10rpx;
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<view class="event-notice" @click="$emit('click')">
<view class="notice-left-icon">
<slot name="leftIcon"></slot>
</view>
<view class="notice-content">
{{content}}
</view>
<view class="notice-right-icon">
<slot name="rightIcon"></slot>
</view>
</view>
</template>
<script>
export default {
name: "event-notice",
props: {
content: {
type: String,
default: ''
},
},
data() {
return {
};
}
}
</script>
<style lang="scss" scoped>
.event-notice {
display: flex;
background-color: #FFF7F2;
border-radius: 20rpx;
height: 90rpx;
align-items: center;
padding: 10rpx 20rpx;
.notice-left-icon,.notice-right-icon{
width: 66rpx;
height: 66rpx;
line-height: 66rpx;
display: flex;
align-items: center;
justify-content: center; }
.notice-left-icon{
margin-right: 20rpx;
}
.notice-content{
flex: 1;
color: #CE7A2C;
font-weight: bold;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
font-size: 32rpx;
}
}
</style>

View File

@@ -0,0 +1,93 @@
<template>
<scroll-view class="waybill-info" style="height:200rpx;" :scroll-y="true">
<template v-if="WaybillInfo">
<view class="waybill-info-item" v-for="item in [...WaybillInfo.kuaidi.data].reverse()">
<view class="time-line">
</view>
<view class="item-icon">
<image src="../../static/11快递@2x.png" style="width: 50rpx;height: 50rpx;" mode=""></image>
</view>
<view class="item-info">
<view class="item-status">
{{getTitle(item.context)}}
</view>
<view class="item-time">
{{item.time}}
</view>
<view class="item-status-address">
{{item.context}}
</view>
</view>
</view>
</template>
</scroll-view>
</template>
<script>
export default {
props: {
WaybillInfo: {
type: Object,
default: () => {}
}
},
name: "waybill-info",
data() {
return {
getTitle(text) {
const regex = /【(.*?)】/;
const matches = regex.exec(text);
if (matches && matches.length > 1) {
const extractedText = matches[1]; // 提取括号中的字
return extractedText
}
},
};
}
}
</script>
<style scoped lang="scss">
.waybill-info {
flex: 1;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 40rpx;
min-height: 300rpx;
padding: 38rpx;
position: relative;
}
.time-line {
position: absolute;
height: calc(100% - 72rpx);
border-left: 1rpx dashed #ccc;
left: 26rpx;
top: 38rpx;
}
.waybill-info-item {
display: flex;
margin-bottom: 60rpx;
.item-icon {
margin-right: 20rpx;
}
.item-status {
font-size: 30rpx;
font-weight: bold;
margin-bottom: 10rpx;
}
.item-time,
.item-status-address {
font-size: 24rpx;
color: #999999;
}
}
</style>

View File

@@ -0,0 +1,111 @@
<template>
<view class="waybill" @click="$emit('click',WaybillInfo)" v-if="WaybillInfo">
<view class="waybill-number">
运单号 {{WaybillInfo.kuaidi.nu}}
</view>
<view class="waybill-address">
<view class="waybill-address-form waybill-address-info">
<view class="address-user-name">
{{WaybillInfo.send_address[2]}}
</view>
<view class="address-name">
{{formatDate(WaybillInfo.create_time)}}
</view>
</view>
<view class="waybill-address-status">
{{'运输中'}}
<image src="../../static/10箭头@2x.png" mode="" style="width: 100%;height: 12rpx;"></image>
</view>
<view class="waybill-address-to waybill-address-info">
<view class="address-user-name">
{{WaybillInfo.take_address[2]}}
</view>
<view class="address-name">
{{formatDate(WaybillInfo.kuaidi.data[WaybillInfo.kuaidi.data.length-1].time)}}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
WaybillInfo: {
type: Object,
default: () => {}
}
},
name: "waybill",
data() {
return {
};
},
methods: {
formatDate(date) {
console.log(date);
let dateArr = date.split('-')
dateArr.splice(0, 1)
return dateArr.join('-')
}
},
}
</script>
<style scoped lang="scss">
.waybill {
height: 260rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 40rpx 40rpx;
padding: 38rpx 49rpx;
box-sizing: border-box;
margin: 30rpx 0;
.waybill-number {
font-size: 30rpx;
color: #999999;
margin-bottom: 36rpx;
}
}
.waybill-address {
display: flex;
.waybill-address-info {
// padding: 0 20rpx;
display: flex;
flex-direction: column;
align-items: center;
width: 180rpx;
overflow: hidden;
.address-user-name {
width: 100%;
font-weight: bold;
font-size: 34rpx;
white-space: nowrap;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
}
.address-name {
width: 100%;
font-size: 12rpx;
color: #999999;
white-space: nowrap;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
}
}
.waybill-address-status {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
}
</style>

20
index.html Normal file
View File

@@ -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>

41
main.js Normal file
View File

@@ -0,0 +1,41 @@
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor';
// 引入UI框架
import uView from "uview-ui";
Vue.use(uView);
import '@icon-park/vue/styles/index.css'
import './store/index.js'
import './store/mine.js'
// 引入 uni-simple-router
import './utils/index.js'
import './utils/directive.js'
import {
router,
RouterMount
} from './router/index.js'; //路径换成自己的
Vue.use(router);
Vue.config.productionTip = false;
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount();
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif

114
manifest.json Normal file
View File

@@ -0,0 +1,114 @@
{
"name" : "iSendLetter",
"appid" : "__UNI__EEA218E",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"publicPath" : "https://jx.xiaolinghou.com/webtest/",
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {
"OAuth" : {},
"Payment" : {}
},
/* */
"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.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.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<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.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {
"oauth" : {
"weixin" : {
"appid" : "wx877c9b57a770f86e",
"UniversalLinks" : ""
}
},
"payment" : {
"weixin" : {
"__platform__" : [ "ios", "android" ],
"appid" : "wx877c9b57a770f86e",
"UniversalLinks" : ""
}
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxd3ef894000268f39",
"setting" : {
"urlCheck" : false,
"es6" : true,
"minified" : true,
"postcss" : true
},
"usingComponents" : true,
"permission" : {}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2",
"h5" : {
"router" : {
"base" : "./"
}
}
}
// "devServer": {
// "proxy": {
// "/api": {
// "target": "https://jx.xiaolinghou.com",
// "changeOrigin": true,
// "secure": true, // 设置支持https协议的代理
// "pathRewrite": {
// "^/api": "/api"
// },
// "logLevel": "debug"
// }
// }
// }

164
package-lock.json generated Normal file
View File

@@ -0,0 +1,164 @@
{
"name": "iSendetter",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "iSendetter",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@icon-park/vue": "^1.4.2",
"luch-request": "^3.1.0",
"uni-read-pages": "^1.0.5",
"uni-simple-router": "^2.0.8-beta.4",
"uview-ui": "^2.0.36"
}
},
"node_modules/@babel/parser": {
"version": "7.22.7",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.22.7.tgz",
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
"peer": true,
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@dcloudio/types": {
"version": "2.6.12",
"resolved": "https://registry.npmmirror.com/@dcloudio/types/-/types-2.6.12.tgz",
"integrity": "sha512-mrCMwcINy1IFjU9VUqLeWBkj404yWs5paLDttBcA+eqUjanuUQbBcTVPqlrGgkyzLXDcV2oDDZRSNxNpXi4kMQ=="
},
"node_modules/@icon-park/vue": {
"version": "1.4.2",
"resolved": "https://registry.npmmirror.com/@icon-park/vue/-/vue-1.4.2.tgz",
"integrity": "sha512-YXXC53R0hjM76B2M4ANRI0m2bQB1cifUW+YXxQfGofITP6gr+pSMafBz/vzECYSkW3zZklm2mVuqQj4RAZGR2Q==",
"dependencies": {
"@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
"csstype": "^3.0.3"
},
"engines": {
"node": ">= 8.0.0",
"npm": ">= 5.0.0"
},
"peerDependencies": {
"vue": "2.x"
}
},
"node_modules/@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
"integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA=="
},
"node_modules/@vue/compiler-sfc": {
"version": "2.7.14",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-2.7.14.tgz",
"integrity": "sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==",
"peer": true,
"dependencies": {
"@babel/parser": "^7.18.4",
"postcss": "^8.4.14",
"source-map": "^0.6.1"
}
},
"node_modules/csstype": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"node_modules/luch-request": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/luch-request/-/luch-request-3.1.0.tgz",
"integrity": "sha512-v3mAoH5TArn+l0wRBOGcHYrchfIkD90PP7IuiQFkxURQzepd5TvMDrG2P1PLw0AU31ZYMTZzUd8XpDgKHo3Vdw==",
"dependencies": {
"@dcloudio/types": "^2.0.16"
},
"engines": {
"node": "16"
}
},
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"peer": true
},
"node_modules/postcss": {
"version": "8.4.25",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.25.tgz",
"integrity": "sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==",
"peer": true,
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/uni-read-pages": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/uni-read-pages/-/uni-read-pages-1.0.5.tgz",
"integrity": "sha512-GkrrZ0LX0vn9R5k6RKEi0Ez3Q3e2vUpjXQ8Z6/K/d28KudI9ajqgt8WEjQFlG5EPm1K6uTArN8LlqmZTEixDUA==",
"hasInstallScript": true
},
"node_modules/uni-simple-router": {
"version": "2.0.8-beta.4",
"resolved": "https://registry.npmmirror.com/uni-simple-router/-/uni-simple-router-2.0.8-beta.4.tgz",
"integrity": "sha512-ipTHhOaRvjV8qrt3HosX5pNMhwFYBnFOuKyV5joH0evfXubjrGI5tjdwpmwzfW5h3VBth3iAqScv+pW/QmIJXw=="
},
"node_modules/uview-ui": {
"version": "2.0.36",
"resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.36.tgz",
"integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA==",
"engines": {
"HBuilderX": "^3.1.0"
}
},
"node_modules/vue": {
"version": "2.7.14",
"resolved": "https://registry.npmmirror.com/vue/-/vue-2.7.14.tgz",
"integrity": "sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==",
"peer": true,
"dependencies": {
"@vue/compiler-sfc": "2.7.14",
"csstype": "^3.1.0"
}
}
}
}

23
package.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "iSendetter",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {
"uview-ui": "^2.0.36",
"@icon-park/vue": "^1.4.2",
"luch-request": "^3.1.0",
"uni-read-pages": "^1.0.5",
"uni-simple-router": "^2.0.8-beta.4"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://git.yoyij.com/Yyf/iSendLetter.git"
},
"keywords": [],
"author": "",
"license": "ISC"
}

253
pages.json Normal file
View File

@@ -0,0 +1,253 @@
{
"pages": [ //pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
},
{
"path": "pages/consult/consult",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
},
{
"path": "pages/login/login",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/aiChat/aiChat",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
},
{
"path": "pages/editor-letter/editor-letter",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
},
{
"path": "pages/letter-view/letter-view",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
},
{
"path": "pages/confirmOrder/confirmOrder",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/editor-letter-manual/editor-letter-manual",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/agentBusiness/agentBusiness",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/replyLetterQuery/replyLetterQuery",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/waybill-info/waybill-info",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/register/register",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/mine/mine",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/mine/mineOrder",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/mine/openMember",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/address/address",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/addAddr/addAddr",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/coupon/coupon",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/queryAddr/queryAddr",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/preview/preview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/payPage/payPage",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"titleNView": false //禁用原生导航栏APP和H5可用
}
}
}, {
"path": "pages/addrDetails/addrDetails",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}, {
"path": "pages/setting/setting",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
// "borderStyle": "#fff7f3",
"borderStyle": "white",
"backgroundColor": "#fff7f3",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/01tab首页1.png",
"selectedIconPath": "static/01tab首页1.png",
"text": "首页"
}, {
"pagePath": "pages/queryAddr/queryAddr",
"iconPath": "static/tab地址1@2x.png",
"selectedIconPath": "static/tab地址1@2x.png",
"text": "地址"
},
{
"pagePath": "pages/consult/consult",
"iconPath": "static/03客服1@2x.png",
"selectedIconPath": "static/03客服1@2x.png",
"text": "咨询"
}, {
"pagePath": "pages/mine/mine",
"iconPath": "static/04我的4@2x.png",
"selectedIconPath": "static/04我的4@2x.png",
"text": "我的"
}
]
}
}

220
pages/addAddr/addAddr.vue Normal file
View File

@@ -0,0 +1,220 @@
<template>
<view class="add-address">
<u-navbar :title="type === 'add' ? '新增地址' : '修改地址'" autoBack bg-color="#fff0e7" placeholder></u-navbar>
<view class="add-content">
<scroll-view :scroll-y="true" style="height: 100%;">
<u--form labelPosition="left" errorType="toast" labelWidth="auto" :model="formData" :rules="rules" ref="uForm">
<view class="v-card">
<view class="v-card-title">
<view class="v-radio">
<u-radio-group v-model="formData.type" placement="row" inactiveColor="#E39B46" activeColor="#E39B46">
<u-radio shape="circle" label="收件地址" :name="0"></u-radio>
<u-radio shape="circle" label="寄件地址" :name="1"></u-radio>
</u-radio-group>
</view>
<view class="v-card-title-right" @click="$Router.push('/pages/queryAddr/queryAddr')"
v-if="formData.type === 0">
看守所/监狱地址查询 <u-icon style="margin-left: 10rpx;" name="arrow-right" color="#E39B46" size="20rpx"></u-icon>
</view>
</view>
<template v-if="formData.type === 0">
<u-form-item label="收件人姓名" prop="name">
<u--input v-model="formData.name" border="none" placeholder="请输入收件人姓名" inputAlign="right"></u--input>
</u-form-item>
<u-form-item label="收件人电话" prop="phone">
<u--input v-model="formData.phone" border="none" placeholder="请输入收件人电话" inputAlign="right"></u--input>
</u-form-item>
<u-form-item label="详细地址" prop="address">
<u--input v-model="formData.address" border="none" placeholder="请输入收邮件人详细地址"
inputAlign="right"></u--input>
</u-form-item>
</template>
<template v-else>
<u-form-item label="寄件人姓名" prop="name">
<u--input v-model="formData.name" border="none" placeholder="请输入寄件人姓名" inputAlign="right"></u--input>
</u-form-item>
<u-form-item label="寄件人电话" prop="phone">
<u--input v-model="formData.phone" border="none" placeholder="请输入寄件人电话" inputAlign="right"></u--input>
</u-form-item>
<u-form-item label="详细地址" prop="address">
<u--input v-model="formData.address" border="none" placeholder="请输入寄邮件人详细地址"
inputAlign="right"></u--input>
</u-form-item>
</template>
</view>
</u--form>
</scroll-view>
</view>
<view class="address-footer">
<u-button class="u-button" :plain="false" @click="saveAddress">保存</u-button>
</view>
</view>
</template>
<script>
import {
addAddress,
editAddress
} from '@/request/yyf.js';
export default {
data() {
return {
checkboxValue: [],
formData: {
type: 0,
phone: '',
name: '',
address: '',
id: ''
},
type: 'add', // add edit
}
},
computed: {
rules() {
let { type } = this.formData;
return {
phone: {
required: true,
pattern: /^1[3-9]\d{9}$/,
message: type === 0 ? '请输入正确的收件人电话' : '请输入正确的寄件人电话',
trigger: ['blur', 'change']
},
name: {
required: true,
message: type === 0 ? '请输入收件人姓名' : '请输入寄件人姓名',
trigger: ['blur', 'change']
},
address: {
required: true,
message: type === 0 ? '请输入收邮件人详细地址' : '请输入寄邮件人详细地址',
trigger: ['blur', 'change']
},
}
}
},
onLoad() {
// console.log(this.$Route.query);
let query = this.$Route.query;
if (query.id) {
this.type = 'edit';
Object.keys(this.formData).forEach(key => {
this.formData[key] = query[key];
});
}
uni.$on('addAddress', (data)=> {
this.formData.address = data;
})
},
methods: {
saveAddress() {
this.$refs['uForm'].validate().then(res => {
console.log('校验通过');
if(this.type === 'add') {
this.submitAddAddress();
} else {
this.submitEditAddress();
}
}).catch(errors => {
console.log(errors);
// uni.$u.toast('校验失败');
})
},
async submitAddAddress() {
const {
data
} = await addAddress(this.formData);
if (data.code === 1) {
uni.$u.toast('添加成功');
uni.$emit('refresh');
this.$Router.back();
}
},
async submitEditAddress() {
const {
data
} = await editAddress(this.formData);
if (data.code === 1) {
uni.$u.toast('修改成功');
uni.$emit('refresh');
this.$Router.back();
}
}
},
onReady() {
//如果需要兼容微信小程序并且校验规则中含有方法等只能通过setRules方法设置规则。
this.$refs.uForm.setRules(this.rules);
},
}
</script>
<style lang="scss" scoped>
::v-deep .u-radio {
margin-right: 20rpx;
}
.add-address {
box-sizing: border-box;
height: 100vh;
display: flex;
flex-direction: column;
padding: 30rpx 30rpx 40rpx;
.add-content {
flex: 1;
overflow: hidden;
.v-card {
margin-bottom: 20rpx;
padding: 30rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 40rpx 40rpx;
.v-card-title {
padding-bottom: 50rpx;
font-size: 34rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #333333;
.v-card-title-right {
margin-top: 30rpx;
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 30rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #E39B46;
}
}
.checkbox {
padding-top: 50rpx;
display: flex;
justify-content: flex-end;
}
}
}
.address-footer {
padding-top: 30rpx;
.u-button {
height: 98rpx;
border: 3rpx solid #FFE3D6;
background: linear-gradient(178deg, #E8B648 0%, #E08745 100%);
border-radius: 12rpx;
font-size: 30rpx;
line-height: 30rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #fff;
}
}
}
</style>

1268
pages/addAddr/address.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
<template>
<view class="addrDetails uni-page">
<u-navbar title="地址详情" autoBack bg-color="#fff0e7" placeholder></u-navbar>
<view class="v-card">
<view class="v-card-item title">
{{ detailsInfo.title }}
</view>
<view class="v-card-item address">
<text>地址:</text>
<text style="padding: 0 40rpx;"> {{ address }}</text>
<Copy :text="address"></Copy>
</view>
<view class="v-card-item">
<text>电话:</text>
<text class="phone" style="padding: 0 40rpx;">
<view v-if="phone[0]">
<text style="padding-right: 40rpx;">{{ phone[0] }}</text>
<u-icon disabled name="phone-fill" color="#14F269" size="60rpx" @click="callPhone(phone[0])"></u-icon>
</view>
<view v-if="phone[1]">
<text style="padding-right: 40rpx;">{{ phone[1] }}</text>
<u-icon name="phone-fill" color="#14F269" size="60rpx" @click="callPhone(phone[1])"></u-icon>
</view>
</text>
<!-- <Copy :text="detailsInfo.province + ''+ detailsInfo.address"></Copy> -->
</view>
<view class="v-card-item">
<text class="label">地址是否经过核实:</text>
<view class="v-type" style="padding: 0 40rpx;">
<u-checkbox :checked="detailsInfo.is_check === 1" activeColor="#E08745" label="已核实" shape="circle"></u-checkbox>
</view>
</view>
<view class="v-card-item">
<text class="label">能否通信:</text>
<view class="v-type" style="padding: 0 40rpx;">
<u-checkbox disabled :checked="detailsInfo.is_phone === 1" activeColor="#E08745" label="已核实" shape="circle"></u-checkbox>
</view>
</view>
<view class="v-card-item">
<text class="label">支持的邮寄类型:</text>
<view class="v-type" style="padding: 0 40rpx;" v-if="loading">
<u-checkbox v-if="detailsInfo.mail_type[0]" disabled activeColor="#E08745" label="明信片" shape="circle" ></u-checkbox>
<u-checkbox v-if="detailsInfo.mail_type[1]" disabled activeColor="#E08745" label="普通信封" shape="circle"></u-checkbox>
</view>
</view>
<view class="v-card-item">
<text class="label">支持的邮寄方式:</text>
<view class="v-type" style="padding: 0 40rpx;" v-if="loading">
<u-checkbox v-if="detailsInfo.mail_action[0]" disabled activeColor="#E08745" label="平信" shape="circle"></u-checkbox>
<u-checkbox v-if="detailsInfo.mail_action[1]" disabled activeColor="#E08745" label="挂号信" shape="circle"></u-checkbox>
</view>
</view>
</view>
</view>
</template>
<script>
import { getAddrDetails } from '@/request/yyf.js';
import Copy from '@/components/Copy/Copy.vue';
export default {
components: {
Copy
},
data() {
return {
params: {
id: ''
},
detailsInfo: {},
phone: '',
address: '',
loading: false
}
},
onLoad() {
let { id } = this.$Route.query;
this.params.id = id;
this.getDetails();
},
methods: {
async getDetails() {
const { data } = await getAddrDetails(this.params);
if(data.code === 1) {
this.loading = true;
this.detailsInfo = data.data;
this.address = this.detailsInfo.province + ' ' + this.detailsInfo.address;
if(data.data.phone[0]) {
this.phone = data.data.phone[0].split('');
}
}
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
}
}
}
</script>
<style lang="scss" scoped>
.v-card {
padding: 40rpx;
background-color: #fff;
border-radius: 40rpx;
.v-card-item {
padding: 10rpx 0;
display: flex;
align-items: center;
.label {
width: 200rpx;
}
}
.title {
font-size: 32rpx;
font-weight: bold;
}
.phone {
flex: 1;
display: flex;
align-items: center;
view {
display: flex;
align-items: center;
}
}
.v-type {
display: flex;
}
::v-deep .u-checkbox {
white-space: nowrap;
min-width: 160rpx;
text {
color: #606266 !important;
}
.u-checkbox__icon-wrap {
background: #E08745 !important;
border-color: #E08745 !important;
.u-icon__icon, .uicon-checkbox-mark {
color: #fff !important;
}
}
}
}
</style>

303
pages/address/address.vue Normal file
View File

@@ -0,0 +1,303 @@
<template>
<view class="address">
<u-navbar title="地址簿" autoBack bg-color="#fff0e7" placeholder></u-navbar>
<view class="tabs-wrap">
<u-tabs
:list="tabList"
:current="currentType"
lineColor="#E39B46"
lineHeight="12rpx"
:activeStyle="{
color: '#333333',
fontSize: '26rpx',
fontWeight: 'bold'
}"
:inactiveStyle="{
color: '#333333',
fontSize: '26rpx',
}"
@click="changeTab"
>
</u-tabs>
</view>
<view class="address-list">
<scroll-view :scroll-y="true" style="height: 100%;" @scrolltolower="loadMoreData">
<view class="address-item"
@click="selectAddres(item)"
v-for="item in currentAddrList"
:key="item.id">
<!-- <view class="item-title">
{{ item.type === 0 ? '收件地址' : '寄件地址' }}
</view> -->
<view class="address-item-name">
<view class="name">{{ item.name }}</view>
<view class="nation"></view>
<view class="time">{{ item.phone }}</view>
</view>
<view class="address-item-text">
{{ item.address }}
</view>
<view class="address-item-ft">
<view></view>
<view class="address-item-ft-right">
<view class="address-item-ft-right-item" @click.stop="editAddress(item)">
<svg width="16" height="16" viewBox="0 0 48 48" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M42 26V40C42 41.1046 41.1046 42 40 42H8C6.89543 42 6 41.1046 6 40V8C6 6.89543 6.89543 6 8 6L22 6"
stroke="#ababab" stroke-width="4" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M16 26.7199V34H21.3172L42 13.3081L34.6951 6L14 26.7199Z" fill="none"
stroke="#ababab" stroke-width="4" stroke-linejoin="round" />
</svg>
<text>编辑地址</text>
</view>
<view class="address-item-ft-right-item" @click.stop="confirmDelete(item)">
<svg width="16" height="16" viewBox="0 0 48 48" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M9 10V44H39V10H9Z" fill="none" stroke="#ababab" stroke-width="4"
stroke-linejoin="round" />
<path d="M20 20V33" stroke="#ababab" stroke-width="4" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M28 20V33" stroke="#ababab" stroke-width="4" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M4 10H44" stroke="#ababab" stroke-width="4" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M16 10L19.289 4H28.7771L32 10H16Z" fill="none" stroke="#ababab"
stroke-width="4" stroke-linejoin="round" />
</svg>
<text>删除地址</text>
</view>
</view>
</view>
</view>
</scroll-view>
<u-modal
showCancelButton
:show="show"
:title="title"
:content="content"
:cancelText="cancelText"
:confirmText="confirmText"
confirmColor="#E08745"
@cancel="show = false"
@confirm="deleteAddr"
>
</u-modal>
</view>
<view class="address-footer">
<u-button class="u-button" :plain="false" icon="plus-circle" @click="addAddress">添加地址</u-button>
</view>
</view>
</template>
<script>
import { getAddressList, delAddress } from '@/request/yyf.js';
export default {
data() {
return {
tabList: [
{ name: '收件地址', type: 0 },
{ name: '寄件地址', type: 1 },
],
checkboxValue: [],
show: false,
title: "警告",
content: "确认删除该地址吗?",
confirmText: "确认",
cancelText: "取消",
delId: '',
addrList: {
0: [],
1: [],
},
params: {
0: { page: 1 },
1: { page: 1 },
},
total: {
0: { total: 0 },
1: { total: 0 },
},
currentType: 0
}
},
computed: {
currentAddrList() {
return this.addrList[this.currentType]
}
},
onLoad() {
this.queryData();
uni.$on('refresh', ()=> {
this.refreshData();
})
},
methods: {
leftClick() {
this.$router.replace('/pages/mine/mine');
},
addAddress() {
this.$Router.push('/pages/addAddr/addAddr');
},
editAddress(item) {
this.$Router.push({
path: '/pages/addAddr/addAddr',
query: {
...item
}
});
},
selectAddres(data) {
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit('selectAddres', {
data
});
uni.navigateBack()
},
confirmDelete({ id }) {
this.delId = id;
this.show = true;
},
async deleteAddr() {
try{
const { data } = await delAddress({
id: this.delId
})
if(data.code === 1) {
this.show = false;
uni.$u.toast('删除成功');
this.refreshData();
} else {
throw data.msg;
}
}catch(e){
//TODO handle the exception
uni.$u.toast(e);
}
},
changeTab({ index, type }) {
if(type === this.currentType) {
return
}
this.currentType = index;
this.orderType = type;
if(this.addrList[this.currentType].length <= 0) {
this.queryData();
}
},
// 刷新
refreshData() {
this.addrList[this.currentType] = [];
this.params[this.currentType].page = 1;
this.queryData();
},
async queryData() {
const { data } = await getAddressList({
...this.params[this.currentType],
type: this.currentType,
order: 'desc'
})
if(data.code === 1) {
this.total[this.currentType].total = data.data.total;
this.addrList[this.currentType].push(...data.data.data);
}
},
loadMoreData() {
if(this.total[this.currentType].total > this.addrList[this.currentType].length) {
this.params[this.currentType].page += 1;
this.queryData();
}
}
}
}
</script>
<style lang="scss" scoped>
.address {
box-sizing: border-box;
height: 100vh;
display: flex;
flex-direction: column;
padding: 0 30rpx 40rpx;
.address-list {
flex: 1;
overflow: hidden;
background: linear-gradient(to bottom right, #fdebe6, #f7f7f7);
.address-item {
margin: 15rpx 0;
padding: 50rpx 40rpx;
background-color: #fff;
border-radius: 40rpx;
.item-title {
padding-bottom: 40rpx;
font-size: 36rpx;
font-weight: bold;
}
.address-item-name {
display: flex;
font-size: 32rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #333333;
.nation {
padding: 0 10rpx;
}
}
.address-item-text {
padding: 10rpx 0 50rpx;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #ababab;
}
.address-item-ft {
display: flex;
align-items: center;
justify-content: space-between;
.address-item-ft-right {
display: flex;
&-item {
padding-left: 40rpx;
display: flex;
align-items: center;
text {
padding-left: 5rpx;
color: #ababab;
}
}
}
}
}
}
.address-footer {
padding-top: 30rpx;
.u-button {
height: 98rpx;
border: 3rpx solid #FFE3D6;
background: transparent;
border-radius: 12rpx;
font-size: 30rpx;
line-height: 30rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #222222;
}
}
}
</style>

View File

@@ -0,0 +1,251 @@
<template>
<view class="uni-page">
<u-navbar placeholder :autoBack="true" bgColor="#fff0e7" title="代收信件" />
<view class="content-main">
<view class="info-box">
<view class="explain">
我们对不方便收信的家属提供信件免费代收服务
</view>
<view class="address-info content">
<view class="address-info-left">
<view class="address-title">
<text>{{addressInfo.name}} </text> <text>{{addressInfo.phone}}</text>
</view>
<view class="address-content">
{{addressInfo.address}}
</view>
</view>
<view class="copy-button">
<u-button type="primary" @click="copy" shape="circle" text="复制" color="#e39b46"></u-button>
</view>
</view>
<view class="upload-explain">
<view class="upload-explain-item" v-for="(item,index) in explainList" :key="index">
<view class="dot"> </view>
<text class="explain-text">{{item}}</text>
</view>
</view>
</view>
<view class="info-box">
<view class="explain">
请填写您的联系方式
</view>
<view class="content">
<view style="margin-bottom: 20rpx;" v-for="(item,index) in phoneNumbers" :key="index">
<u--input placeholder="请输入您的手机号码" type="number" border="surround" v-model="item.number">
<template slot="suffix">
<view class="" style="display: flex;">
<u-button v-if="index" @tap="deleteNumber(index)" color="red"
size="mini">删除</u-button>
</view>
</template>
</u--input>
</view>
<view class="" style="display: flex;">
<u-button type="primary" text="添加手机号" @click="addPhoneNumber"></u-button>
<u-button :customStyle="{
'margin-left':'20rpx',
width:'200rpx'
}" type="success" @click="submitNumber()">保存</u-button>
</view>
<!-- <u-button type="primary" text="添加手机号" @click="addPhoneNumber"></u-button> -->
</view>
<view class="upload-explain">
<view class="upload-explain-item">
<view class="dot"> </view>
<text class="explain-text">填写的电话务必能联系到您本人以免信件丢失</text>
</view>
</view>
</view>
</view>
<view class="floor-bottom">
</view>
</view>
</template>
<script>
import {
getAgentBusinessInfoApi,
setAgentBusinessInfoApi
} from '@/request/wm.js'
export default {
data() {
return {
explainList: ['请复制上方地址,并把我们的地址附在信件里面',
'信件由我们收到后,第一时间会电话通知您',
'信件可以拍照或邮寄,邮费需自己承担',
'代收服务完全免费,不收取任何费用]',
],
phoneNumbers: [{
number: ''
}],
addressInfo: '',
};
},
onLoad() {
this.getAgentBusinessInfo()
},
methods: {
addPhoneNumber() {
this.phoneNumbers.push({
number: null
})
},
deleteNumber(index) {
this.phoneNumbers.splice(index, 1)
},
async getAgentBusinessInfo() {
let {
data
} = await getAgentBusinessInfoApi()
this.addressInfo = data.data
if (data.data.links.length) {
this.phoneNumbers = data.data.links.map((item) => {
return {
number: item
}
})
}
console.log(this.phoneNumbers);
},
async submitNumber(phoneNumber, index) {
let canSub = null
this.phoneNumbers.forEach(item => {
if (!/^1[3456789]\d{9}$/.test(item.number)) {
canSub = item.number
}
})
if (canSub) {
uni.showModal({
title: '提示',
content: `手机号 ${canSub} 不合法,请重新输入!`,
showCancel: false,
})
} else {
let phone = this.phoneNumbers.map(item => item.number)
phone = {
phone: phone.join(',')
}
console.log(phone);
let {
data
} = await setAgentBusinessInfoApi(phone)
console.log(data);
}
},
copy() {
uni.setClipboardData({
data: `${this.addressInfo.name} ${this.addressInfo.phone} ${this.addressInfo.address}`,
success: function() {
uni.showToast({
title: '复制成功',
icon: 'success'
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.content-main {
flex: 1;
overflow: auto;
// height: 100%;
}
.info-box {
margin-top: 30rpx;
background-color: white;
min-height: 100rpx;
border-radius: 40rpx;
height: fit-content;
padding: 30rpx 30rpx;
display: flex;
flex-direction: column;
.info-title {
font-size: 34rpx;
font-weight: bold;
}
}
.explain {
font-size: 30rpx;
}
.content {
margin: 34rpx 0;
}
.address-info {
border-radius: 40rpx;
height: 174rpx;
background: #FFF7F2;
display: flex;
padding: 0 30rpx;
align-items: center;
justify-content: space-between;
.address-info-left {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 30rpx;
}
.address-title {
width: 100%;
font-weight: bold;
overflow: hidden;
font-size: 34rpx;
white-space: nowrap;
text-overflow: ellipsis;
text {
text-overflow: ellipsis;
}
// font-size: 34rpx;
}
.address-content {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 26rpx;
}
}
.upload-explain {
padding-left: 30rpx;
.upload-explain-item {
display: flex;
align-items: center;
margin-bottom: 10rpx;
.dot {
width: 12rpx;
height: 12rpx;
background-color: #999796;
margin-right: 14rpx;
border-radius: 50%;
}
.explain-text {
flex: 1;
font-size: 26rpx;
opacity: 0.5;
}
}
}
</style>

402
pages/aiChat/aiChat.vue Normal file
View File

@@ -0,0 +1,402 @@
<template>
<view class="uni-page ai-chat">
<u-navbar :autoBack="true" bgColor="#fff0e7" placeholder title="寄信助手" right-icon=""
@rightClick="clearMessageList">
<template slot="right">
<image @click="clearMessageList" class="img-icon" src="/static/icons/清除_clear.svg" alt=""
style="height: 47rpx; width: 47rpx;">
</image>
</template>
</u-navbar>
<view class="ai-chat-hint" v-if="!messageList.length">
<view class="message-item-chat message-item">
<view class="message-item-avatar">
<image src="/static/03头像@2x.png" alt="" style="width: 100%;height: 100%;">
</view>
<view class="message-item-content">
<view class="message-hint-temp-title">
Hi,我是你的寄信助手小艾
</view>
<view class="message-hint-temp-explain">
有什么问题可以直接问我...
</view>
</view>
</view>
<view class="hint-message-box">
<view @click="sendMessage(item)" class="hint-message-item" v-for="item in hintMessage" :key="item">
{{item}}
</view>
</view>
</view>
<scroll-view :scroll-into-view="scrollView" class="chat-messageList" id="chat-messageList" v-else
:scroll-y="true">
<template v-for="(mess,index) in messageList">
<view v-if="mess.role==='user'" :key="index" class="message-item-user message-item">
<view class="message-item-content" style="margin:0 10rpx 0 100rpx;word-wrap: break-word;">
{{mess.message}}
</view>
<view class="message-item-avatar">
<image style="width: 100%;height: 100%;" :src="userInfo.avatar" alt="">
</view>
</view>
<view class="message-item-chat message-item" v-if="mess.role==='assistant'">
<view class="message-item-avatar">
<image style="width: 100%;height: 100%;" src="/static/03头像@2x.png" alt="">
</view>
<view class="message-item-content" style="margin:0 100rpx 0 10rpx ;">
<u-loading-icon v-if="!mess.message"></u-loading-icon>
<text :id="!mess.message?'loading-message':''">{{mess.message}}</text>
<view v-if="mess.message" class="message-item-content-toolbar">
<view class="message-toolbar-left">
<!-- <view>
确定内容
</view> -->
<view @click="toWrite(mess.message)">
去编辑
</view>
</view>
<view class="message-toolbar-right">
<view @click="copy(mess.message)">
复制
</view>
</view>
</view>
</view>
</view>
</template>
<view :id="'scroll_base'+messageList.length">
</view>
</scroll-view>
<view class="chat-floor">
<!-- <view class="floor-toolbar">
<view class="floor-toolbar-item">
发送照片
</view>
<view class="floor-toolbar-item">
发送订单
</view>
</view> -->
<view class="textarea-box">
<u--textarea :disabled="isSnedMsg" :autoHeight="true" :maxlength="99999" :placeholder="placeholder"
v-model="mesText">
</u--textarea>
<view class="button-box" @click="sendMessage(mesText)">
<image :class="{img:true,
'button-disable':isSnedMsg}" src="/static/25发送@2x.png" alt="发送"></image>
</view>
</view>
<view class="limit-of-times">
<!-- 智能寄信 套餐剩余次数 <text style="color: #fe9262;margin: 0 10rpx;">
2
</text> -->
</view>
</view>
</view>
</template>
<script>
import '@/utils/EncoderDecoderTogether.min.js'
import {
getMessageList,
sendMessageApi
} from '@/request/wm.js'
export default {
data() {
return {
placeholder: '输入您的问题...',
messageList: [],
hintMessage: ['我要给狱中的朋友寄一封信...', '帮我给好朋友写封信...', '帮我写封信...', '我想给狱中的朋友写封信,有什么注意事项...'],
mesText: '',
userInfo: {},
scrollView: 'scroll_base',
isSnedMsg: false
}
},
components: {},
onReady() {
this.userInfo = this.$store.userInfo
console.log(this.$store.userInfo, '11111111111111');
let isNewChat = uni.getStorageSync('NEW_CHAT')
if (isNewChat) return
this.initData()
console.log(this.userInfo);
},
mounted() {},
methods: {
async sendMessage(mes) {
if (this.isSnedMsg) return
this.isSnedMsg = true
let isNewchat = uni.getStorageSync('NEW_CHAT')
this.messageList.push({
role: 'user',
message: mes
})
this.messageList.push({
role: 'assistant',
message: ''
})
this.mesText = ''
this.$nextTick(() => {
this.scrollView = 'loading-message'
})
await sendMessageApi({
message: mes,
new: +isNewchat || 0
}, this)
console.log(this.messageList[this.messageList.length - 1],'aaa');
// this.messageList[this.messageList.length - 1] = {
// role: 'assistant',
// message: data.msg
// }
uni.setStorageSync('NEW_CHAT', '')
this.$nextTick(() => {
setTimeout(() => {
this.scrollView = 'scroll_base' + this.messageList.length
})
})
// this.isSnedMsg = false
},
async initData() {
let {
data
} = await getMessageList()
this.messageList = data.data.data
this.$nextTick(() => {
this.scrollView = 'scroll_base' + data.data?.data.length || ''
})
},
clearMessageList() {
this.messageList = []
this.isSnedMsg= false
uni.setStorageSync('NEW_CHAT', JSON.stringify(1))
},
copy(text) {
uni.setClipboardData({
data: text,
success: function() {
uni.showToast({
title: '复制成功',
icon: 'success'
})
}
})
},
toWrite(text) {
this.$mutations.setLetterInfo({
message: text.replace(/\\n/g , '\n')
})
console.log(this.$store.letterInfo);
uni.navigateTo({
url: 'pages/editor-letter/editor-letter'
})
}
}
}
</script>
<style scoped lang="scss">
.uni-page {
display: flex;
flex-direction: column;
background: radial-gradient(circle, #ffe3d6, #ffe8dd, #fff3ee);
.chat-messageList {
width: 100%;
flex: 1;
overflow: auto;
}
.ai-chat-hint {
flex: 1;
}
.img-icon {
// #ifdef MP-WEIXIN
position: absolute;
right: 200rpx;
top: 50%;
transform: translateY(-50%);
// #endif
}
}
::v-deep .u-textarea--disabled {
background-color: rgba(245, 247, 250, 0.3) !important;
}
.button-disable {
opacity: 0.3;
}
.ai-chat-hint {
.message-item {
height: fit-content;
.message-item-content {
padding: 12rpx;
background-color: transparent;
}
}
}
.ai-chat {
.message-item {
padding: 20rpx 0;
display: flex;
width: 100%;
overflow: hidden;
.message-item-content {
flex: 1;
font-size: 30rpx;
color: #222222;
}
}
.message-item-avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
// border-radius: 50%;
}
}
.hint-message-box {
display: flex;
flex-wrap: wrap;
.hint-message-item {
color: #333333;
width: fit-content;
border-radius: 40rpx;
margin-right: 30rpx;
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.5);
padding: 22rpx 35rpx;
font-size: 32rpx;
}
}
.message-item-content {
padding: 35rpx;
background-color: rgba(255, 255, 255, 0.5);
;
border-radius: 40rpx;
overflow: auto;
.message-hint-temp-title {
font-size: 32rpx;
// width: 387rpx;
// height: 42rpx;
color: #333333;
}
.message-hint-temp-explain {
// width: 340rpx;
// height: 40rpx;
color: #E08745;
font-size: 30rpx;
}
}
.message-item-content-toolbar {
display: flex;
margin-top: 20rpx;
color: #CE7A2C;
justify-content: space-between;
.message-toolbar-left {
view {
margin-right: 20rpx;
}
display: flex;
}
}
.chat-floor {
padding: 20rpx 0;
.floor-toolbar {
display: flex;
font-size: 26rpx;
flex-wrap: wrap;
margin-bottom: 20rpx;
}
.floor-toolbar-item {
display: flex;
align-items: center;
justify-content: center;
width: 123rpx;
height: 52rpx;
background-color: #fed2b8;
color: #FE9161;
margin-right: 30rpx;
}
.textarea-box {
height: 270rpx;
border-radius: 20rpx;
border: 3rpx solid #FE9161 !important;
display: flex;
overflow-y: auto;
}
::v-deep .u-textarea {
flex: 1;
border: unset;
padding: 0;
background: transparent;
.u-textarea__field {}
textarea {
padding: 20rpx;
}
}
::v-deep .button-box {
position: absolute;
right: 20rpx;
bottom: 60rpx;
display: flex;
align-items: flex-end;
border: unset;
padding: 20rpx;
.img {
width: 120rpx;
height: 76rpx;
object-fit: contain;
}
}
.limit-of-times {
margin-top: 10rpx;
text-align: center;
font-size: 26rpx;
}
}
}
</style>

View File

@@ -0,0 +1,418 @@
<template>
<view class="uni-page">
<u-navbar placeholder :autoBack="true" bgColor="#fff0e7" title="订单信息"></u-navbar>
<view class="content-main">
<view class="info-box">
<view class="info-title">
地址信息
</view>
<view class="info-content">
<view class="step-line">
</view>
<view class="step-item">
<view class="step-icon">
</view>
<view class="address-box">
<view class="address-info">
张大大 17638755181
</view>
<view class="address-detail">
西安市雁塔区中天国际公寓A座2605
</view>
</view>
<view class="addres-book-button">
地址簿<img src="~@/static/01跳转@2x.png" alt="" style="width: 14rpx;height: 25rpx;">
</view>
</view>
<view class="step-item">
<view class="step-icon step-icon-last">
</view>
<view class="address-box">
<view class="address-info">
王大大 17638755181
</view>
<view class="address-detail">
新疆乌鲁木齐大三巴公路铁硫唑1楼209
</view>
</view>
<view class="addres-book-button">
地址簿<img src="~@/static/01跳转@2x.png" alt="" style="width: 14rpx;height: 25rpx;">
</view>
</view>
</view>
</view>
<view class="info-box">
<view class="info-title">
邮寄方式
</view>
<view class="info-content">
<view class=" info-content-flex">
<view :class="{'post-pattern-item':true,
'post-pattern-item-active':pattern.id === orderInfo.postPattern
}" v-for="pattern in postPattern" :key="pattern.id" @click="()=>{
orderInfo.postPattern = pattern.id
priceInfo.postage.value = pattern.price
}">
<view class="patter-price">
{{pattern.price}}<text style="font-size: 24rpx;"></text>
</view>
<view class="patter-explain">
{{pattern.explain}}
</view>
</view>
</view>
</view>
<EventNotice content="最新活动开通会员0元寄信">
<template #leftIcon>
<image src="/static/12活动@2x.png" style="width: 100%;height: 100%" alt=""></image>
</template>
<template #rightIcon>
<u-icon name="arrow-right" color="#CE7A2C" size="16"></u-icon>
</template>
</EventNotice>
</view>
<view class="info-box">
<PayPattern v-model="orderInfo.payPattern" @change="test"></PayPattern>
</view>
<view class="info-box">
<u-cell-group :border="false">
<u-cell :border="false" title="我的会员" isLink>
<template #value>
<view class="">
暂无会员
</view>
</template>
</u-cell>
<u-cell :border="false" title="我的优惠券" isLink></u-cell>
<u-cell :border="false" title="我的备注" isLink>
<template #value>
<view style="width:300rpx;">
{{orderInfo.note}}
</view>
</template>
</u-cell>
</u-cell-group>
</view>
</view>
<view class="floor-button">
<u-popup closeable :border="false" :show="showPrice" mode="bottom" :round="40" @close="closePricePanel">
<view class="price-panel-box">
<u-cell-group :border="false">
<u-cell :border="false" v-for="item in priceInfo" :key="item.id">
<template #title>
<view class="price-info-title">{{item.name}}</view>
</template>
<template #value>
<view :class="{
'price-info-value':true,
'price-info-value-black':item.value<=0,
}">¥ {{+item.value.toFixed(2)}}</view>
</template>
</u-cell>
<view class="" style="display: flex;margin-top: 50rpx;">
<view class="to-view-button" @click="toView">
费用合计 <text style="margin-left: 20rpx;color: #CE7A2C;">¥<text
style="font-size: 42rpx;margin-left: 10rpx;">{{totalPrice}}</text></text>
</view>
<view class="nextstep-button" @click="tpPay">
立即支付
</view>
</view>
</u-cell-group>
</view>
</u-popup>
<view class="nextstep-button" @click="confirm">
确认
</view>
</view>
</view>
</template>
<script>
import EventNotice from '@/components/event-notice/event-notice.vue'
import PayPattern from '@/components/Pay-patter/Pay-patter.vue'
export default {
components: {
EventNotice,
PayPattern
},
data() {
return {
orderInfo: {
plan: '',
postPattern: 1,
payPattern: 1,
note: '奥克兰大理石是镂空雕刻,圾的卢卡斯离开的萨科拉上来,打死了 '
},
postPattern: [{
id: 1,
price: 5.2,
explain: '平信(无物流)'
},
{
id: 2,
price: 10.0,
explain: '挂号信'
},
{
id: 3,
price: 30.0,
explain: 'EMS'
},
{
id: 4,
price: 30.0,
explain: '顺丰'
}
],
priceInfo: {
print: {
id: 1,
name: '信件费用-普通打印',
key: 'print',
value: 1
},
picture: {
id: 2,
name: '照片费用2',
key: 'picture',
value: 100
},
postage: {
id: 3,
name: '邮寄费用',
key: 'postage',
value: 135
},
discounts: {
id: 4,
name: '我的优惠券',
key: 'discounts',
value: 22
}
},
showPrice: false,
};
},
onLoad(option) {
this.orderInfo.plan = option.plan
this.priceInfo.postage.value = this.postPattern[0].price
console.log(option);
},
methods: {
test(e) {
console.log(e, this.orderInfo);
},
confirm() {
this.showPrice = true
},
closePricePanel() {
this.showPrice = false
},
tpPay() {
}
},
computed: {
totalPrice() {
return Object.values(this.priceInfo).reduce((total, next) => {
return total + next.value
}, 0)
}
}
}
</script>
<style lang="scss" scoped>
.uni-page {
display: flex;
flex-direction: column;
}
.content-main {
flex: 1;
overflow: auto;
// height: 100%;
}
.info-box {
margin-top: 30rpx;
background-color: white;
min-height: 100rpx;
border-radius: 40rpx;
height: fit-content;
padding: 30rpx 30rpx;
.info-title {
font-size: 34rpx;
font-weight: bold;
}
.info-content {
position: relative;
padding: 30rpx 0;
.step-line {
position: absolute;
height: calc(60%);
width: 0;
// background-color: black;
border-left: 1rpx black dashed;
left: 28rpx;
top: 20%;
}
.step-item {
display: flex;
margin-bottom: 50rpx;
align-items: center;
position: relative;
height: 100%;
}
.step-item:last-child {
margin-bottom: 0;
}
.address-box {
flex: 1;
// padding-top: 20rpx;
}
.address-info,
.addres-book-button {
font-size: 32rpx;
color: black;
}
.step-icon-box {
height: 100%;
}
}
.address-detail {
font-size: 24rpx;
}
.step-icon {
position: relative;
z-index: 1;
margin-right: 10rpx;
width: 56rpx;
height: 56rpx;
background-color: #E39B46;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
// font-family: OPPOSans-bold, OPPOSans;
color: white;
font-size: 34rpx;
font-weight: bold;
// bottom: 0;
}
.addres-book-button {
width: fit-content;
margin-right: 10rpx;
height: 100%;
display: flex;
align-items: center;
img {
margin-left: 10rpx;
}
}
}
.info-content-flex {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150rpx;
gap: 30rpx;
height: 100%;
width: 100%;
.post-pattern-item {
width: 196rpx;
height: 134rpx;
background: #FFF7F2;
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.patter-price {
font-size: 42rpx;
font-weight: bold;
color: black;
}
.patter-explain {
margin-top: 10rpx;
font-size: 24rpx;
// opacity: 50%;
}
}
.post-pattern-item-active {
background: #E39B46;
.patter-price {
color: white;
}
.patter-explain {
color: white;
opacity: 1;
}
}
}
.to-view-button {
width: 459rpx;
min-height: 98rpx;
background-color: #ffe4d9;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30rpx;
}
.nextstep-button {
flex: 1;
background: linear-gradient(to bottom right, #e8b648, #e08745);
min-height: 98rpx;
border-radius: 20rpx;
color: white;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
.price-panel-box {
box-sizing: border-box;
height: 690rpx;
padding: 37rpx;
padding-top: 171rpx;
.price-info-title {
font-size: 30rpx;
}
.price-info-value {
color: #CE7A2C;
}
}
</style>

View File

@@ -0,0 +1,595 @@
<template>
<view class="uni-page">
<u-navbar placeholder :autoBack="true" bgColor="#fff0e7" title="订单信息"></u-navbar>
<view class="content-main">
<view class="info-box">
<view class="info-title"> 地址信息 </view>
<view class="info-content">
<view class="step-line"> </view>
<view class="step-item">
<view class="step-icon"> </view>
<view class="address-box" v-if="sendAddre">
<view class="address-info">
{{ sendAddre.name }} {{ sendAddre.phone }}
</view>
<view class="address-detail">
{{ sendAddre.address }}
</view>
</view>
<view class="address-box" v-else>
<view class="address-info">请选择寄件地址 </view>
</view>
<view class="addres-book-button" @click="toSelectAddress('sendAddre')">
地址簿<img src="~@/static/01跳转@2x.png" alt="" style="width: 14rpx; height: 25rpx" />
</view>
</view>
<view class="step-item">
<view class="step-icon step-icon-last"> </view>
<view class="address-box" v-if="takeAddre">
<view class="address-info">
{{ takeAddre.name }} {{ takeAddre.phone }}
</view>
<view class="address-info"> </view>
<view class="address-detail">
{{ takeAddre.address }}
</view>
</view>
<view class="address-box" v-else>
<view class="address-info">请选择收件地址 </view>
</view>
<view class="addres-book-button" @click="toSelectAddress('takeAddre')">
地址簿<img src="~@/static/01跳转@2x.png" alt="" style="width: 14rpx; height: 25rpx" />
</view>
</view>
</view>
</view>
<view class="info-box">
<view class="info-title"> 邮寄方式 </view>
<view class="info-content">
<view class="info-content-flex">
<view :class="{
'post-pattern-item': true,
'post-pattern-item-active':
pattern.id === orderInfo.postPattern,
}" v-for="pattern in postPattern" :key="pattern.id" @click="
() => {
orderInfo.postPattern = pattern.id;
priceInfo.postage.value = pattern.balance;
}
">
<view class="patter-price">
{{ pattern.balance }}<text style="font-size: 24rpx">元</text>
</view>
<view class="patter-explain">
{{ pattern.title }}
</view>
</view>
</view>
</view>
<!-- <EventNotice content="最新活动开通会员0元寄信">
<template #leftIcon>
<image src="/static/12活动@2x.png" style="width: 100%; height: 100%" alt=""></image>
</template>
<template #rightIcon>
<u-icon name="arrow-right" color="#CE7A2C" size="16"></u-icon>
</template>
</EventNotice> -->
</view>
<view class="info-box">
<PayPattern v-model="orderInfo.payPattern"></PayPattern>
</view>
<view class="info-box">
<u-cell-group :border="false">
<!-- <u-cell :border="false" title="我的会员" isLink>
<template #value>
<view class=""> 暂无会员 </view>
</template>
</u-cell> -->
<u-cell :border="false" title="我的优惠券" isLink @click="toSelectDiscounts">
<template #value>
<view style="width: 300rpx; text-align: right">
{{ discounts ? discounts.title : "" }}
</view>
</template>
</u-cell>
<u-cell :border="false" title="我的备注" isLink @click="
() => {
showExplainInput = true;
}
">
<template #value>
<view style="width: 300rpx">
{{ orderInfo.note }}
</view>
</template>
</u-cell>
</u-cell-group>
</view>
</view>
<view class="floor-button">
<u-popup closeable :border="false" :show="showPrice" mode="bottom" :round="40" @close="closePricePanel">
<view class="price-panel-box">
<u-cell-group :border="false">
<u-cell :border="false" v-for="item in priceInfo" :key="item.id">
<template #title>
<view class="price-info-title">{{ item.name }}</view>
</template>
<template #value>
<view :class="{
'price-info-value': true,
'price-info-value-black': item.value <= 0,
}">¥ {{ item.value.toFixed(2)}}</view>
</template>
</u-cell>
<view class="" style="display: flex; margin-top: 50rpx">
<view class="to-view-button">
费用合计
<text style="margin-left: 20rpx; color: #ce7a2c">¥<text
style="font-size: 42rpx; margin-left: 10rpx">{{
totalPrice
}}</text></text>
</view>
<view class="nextstep-button" @click="tpPay"> 立即支付 </view>
</view>
</u-cell-group>
</view>
</u-popup>
<u-popup :show="showExplainInput" @close="
() => {
showExplainInput = false;
}
">
<view>
<u--textarea v-model="orderInfo.note" placeholder="请输入备注信息"></u--textarea>
</view>
</u-popup>
<view class="nextstep-button" @click="confirm"> 确认 </view>
</view>
<u-loading-page :loading="isPayOver"></u-loading-page>
</view>
</template>
<script>
import {
toPay,
getPostList
} from "../../request/wm.js";
import EventNotice from "@/components/event-notice/event-notice.vue";
import PayPattern from "@/components/Pay-patter/Pay-patter.vue";
export default {
components: {
EventNotice,
PayPattern,
},
data() {
return {
orderInfo: {
plan: "",
postPattern: 1,
payPattern: 1,
note: "",
},
isPayOver: false,
postPattern: [{
id: 1,
price: 5.2,
explain: "平信(无物流)",
},
{
id: 2,
price: 10.0,
explain: "挂号信",
},
{
id: 3,
price: 30.0,
explain: "EMS",
},
{
id: 4,
price: 30.0,
explain: "顺丰",
},
],
priceInfo: {
print: {
id: 1,
name: "信件费用-普通打印",
key: "print",
value: 0,
},
picture: {
id: 2,
name: "照片费用",
key: "picture",
value: 0,
},
postage: {
id: 3,
name: "邮寄费用",
key: "postage",
value: 0,
},
discounts: {
id: 4,
name: "我的优惠券",
key: "discounts",
value: 0,
},
},
showPrice: false,
sendAddre: null,
takeAddre: null,
discounts: null,
showExplainInput: false,
postList: [],
};
},
async onLoad() {
if (!this.$store.letterInfo) {
uni.navigateTo({
url: "/pages/index/index",
});
}
let {
data
} = await getPostList();
this.postPattern = data.data.data;
this.priceInfo.postage.value = this.postPattern[0].balance;
},
methods: {
test(e) {
console.log(e, this.orderInfo);
},
confirm() {
if (!this.sendAddre || !this.takeAddre) {
uni.showToast({
icon: "error",
title: "请选择收货地址",
});
return;
}
// console.log(this.orderInfo);
if (!this.$store.letterInfo.coupon) {
this.$store.letterInfo.coupon = 0;
}
this.$store.letterInfo.send_type = this.orderInfo.postPattern;
this.$store.letterInfo.remark = this.orderInfo.note;
console.log(this.$store.letterInfo);
this.showPrice = true;
},
closePricePanel() {
this.showPrice = false;
},
toSelectDiscounts() {
uni.navigateTo({
url: "/pages/coupon/coupon",
events: {
select: ({
data
}) => {
let baseValue = +this.totalPrice + (this.discounts?.balance || 0)
console.log(baseValue, data.start);
console.log(baseValue < data.start);
if (baseValue < data.start) {
console.log(uni.$u);
setTimeout(() => {
uni.$u.toast('不满足优惠券最低使用额度');
}, 100)
return
}
if (data) {
this.discounts = data;
this.priceInfo.discounts.value = 0 - data.balance
// this.priceInfo.discounts.value = 0 - 5;
this.$store.letterInfo.coupon = data.id;
} else {
// this.priceInfo.discounts.value = 0 - data.balance
this.priceInfo.discounts.value = 0;
this.$store.letterInfo.coupon = 0;
}
console.log(data);
},
},
});
},
toSelectAddress(type) {
uni.navigateTo({
url: "/pages/address/address",
events: {
selectAddres: ({
data
}) => {
switch (type) {
case "sendAddre":
this.sendAddre = data;
this.$store.letterInfo.send_address =
`${data.name} ${data.phone} ${data.address}`;
console.log(this.sendAddre);
break;
case "takeAddre":
this.takeAddre = data;
this.$store.letterInfo.take_address =
`${data.name} ${data.phone} ${data.address}`;
console.log(this.takeAddre);
break;
default:
break;
}
},
},
});
},
async tpPay() {
this.isPayOver = true;
try {
this.$store.letterInfo.pay_payment = this.orderInfo.payPattern;
let payData = {
...this.$store.letterInfo,
isMmanual: undefined,
};
let {
data
} = await toPay(this.$store.letterInfo);
if (data.code === 1) {
this.isPayOver = false;
// #ifdef H5
if (this.orderInfo.payPattern === 1) {
uni.showToast({
title: data.msg,
});
setTimeout(() => {
uni.navigateTo({
url: "/pages/mine/mine",
});
}, 1000);
} else {
location.href = data.data.pay.url;
// window.lo
}
// #endif
// #ifdef MP-WEIXIN
uni.showToast({
title: "小程序支付暂未配置",
icon: "error",
});
// #endif
} else {
uni.showToast({
title: data.msg,
icon: "error",
});
this.isPayOver = false;
}
} catch (e) {
this.isPayOver = false;
//TODO handle the exception
}
console.log(data);
},
},
computed: {
totalPrice() {
console.log(this.$store.letterInfo);
this.$store.productionType.forEach((item) => {
console.log(item.id, this.$store.letterInfo.mail_type);
if (item.id === this.$store.letterInfo.mail_type) {
this.priceInfo.print.name = "信件费用-" + item.title;
this.priceInfo.print.value = +item.price;
}
});
let photoPrices = null;
if (this.$store.letterInfo.isMmanual) {
photoPrices = this.$store.photoPrice?.photo_write;
} else {
photoPrices = this.$store.photoPrice?.photo_artificial;
}
this.$store.letterInfo.thumb?.forEach((file, index) => {
if (!index) return;
if (photoPrices && photoPrices[index] !== undefined) {
this.priceInfo.picture.value += +photoPrices[index];
} else {
this.priceInfo.picture.value += +photoPrices[photoPrices.length - 1];
}
});
let value = Object.values(this.priceInfo).reduce((total, next) => {
console.log(total + next.value);
return (+total + +next.value).toFixed(2);
}, 0);
return value < 0 ? 0 : value
},
},
};
</script>
<style lang="scss" scoped>
.uni-page {
display: flex;
flex-direction: column;
}
.content-main {
flex: 1;
overflow: auto;
// height: 100%;
}
.info-box {
margin-top: 30rpx;
background-color: white;
min-height: 100rpx;
border-radius: 40rpx;
height: fit-content;
padding: 30rpx 30rpx;
.info-title {
font-size: 34rpx;
font-weight: bold;
}
.info-content {
position: relative;
padding: 30rpx 0;
.step-line {
position: absolute;
height: calc(60%);
width: 0;
// background-color: black;
border-left: 1rpx black dashed;
left: 28rpx;
top: 20%;
}
.step-item {
display: flex;
margin-bottom: 50rpx;
align-items: center;
position: relative;
height: 100%;
}
.step-item:last-child {
margin-bottom: 0;
}
.address-box {
flex: 1;
// padding-top: 20rpx;
}
.address-info,
.addres-book-button {
font-size: 32rpx;
color: black;
}
.step-icon-box {
height: 100%;
}
}
.address-detail {
font-size: 24rpx;
}
.step-icon {
position: relative;
z-index: 1;
margin-right: 10rpx;
width: 56rpx;
height: 56rpx;
background-color: #e39b46;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
// font-family: OPPOSans-bold, OPPOSans;
color: white;
font-size: 34rpx;
font-weight: bold;
// bottom: 0;
}
.addres-book-button {
width: fit-content;
margin-right: 10rpx;
height: 100%;
display: flex;
align-items: center;
img {
margin-left: 10rpx;
}
}
}
.info-content-flex {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150rpx;
gap: 30rpx;
height: 100%;
width: 100%;
.post-pattern-item {
width: 196rpx;
height: 134rpx;
background: #fff7f2;
border-radius: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.patter-price {
font-size: 42rpx;
font-weight: bold;
color: black;
}
.patter-explain {
margin-top: 10rpx;
font-size: 24rpx;
// opacity: 50%;
}
}
.post-pattern-item-active {
background: #e39b46;
.patter-price {
color: white;
}
.patter-explain {
color: white;
opacity: 1;
}
}
}
.to-view-button {
width: 459rpx;
min-height: 98rpx;
background-color: #ffe4d9;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30rpx;
}
.nextstep-button {
flex: 1;
background: linear-gradient(to bottom right, #e8b648, #e08745);
min-height: 98rpx;
border-radius: 20rpx;
color: white;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
.price-panel-box {
box-sizing: border-box;
height: 690rpx;
padding: 37rpx;
padding-top: 171rpx;
.price-info-title {
font-size: 30rpx;
}
.price-info-value {
color: #ce7a2c;
}
}
</style>

282
pages/consult/consult.vue Normal file
View File

@@ -0,0 +1,282 @@
<template>
<view class="uni-page ai-chat">
<u-navbar :left-icon="null" placeholder :autoBack="true" bgColor="#fff0e7" title="寄信助手"></u-navbar>
<view class="ai-chat-hint">
<view class="message-item-chat message-item">
<view class="message-item-avatar">
<image src="/static/03头像@2x.png" alt="" style="width: 100%;height: 100%;">>
</view>
<view class="message-item-content">
<view class="message-hint-temp-title">
Hi,我是你的寄信助手小艾
</view>
<view class="message-hint-temp-explain">
有什么问题可以直接问我...
</view>
</view>
</view>
</view>
<scroll-view class="chat-messageList" :scroll-into-view="scrollView" :scroll-y="true">
<template v-for="(mess,index) in messageList">
<view v-if="mess.type==='user'" :id="'message-'+(index+1)" :key="index"
class="message-item-user message-item">
<view class="message-item-content" style="margin:0 10rpx 0 100rpx;">
{{mess.message}}
</view>
<view class="message-item-avatar">
<image :src="userInfo.avatar" alt="" style="width: 100%;height: 100%;">>
</view>
</view>
<view v-if="mess.type==='rebot'" :id="'message-'+(index+1)" :key="index"
class="message-item-chat message-item">
<view class="message-item-avatar">
<image src="/static/03头像@2x.png" alt="" style="width: 100%;height: 100%;">>
</view>
<view class="message-item-content" style="margin:0 100rpx 0 10rpx ;">
{{mess.message}}
</view>
</view>
<view v-if="mess.type==='rebootremplate'" :id="'message-'+(index+1)" :key="index"
class="message-item-chat-template message-item">
<view class="message-item-avatar">
<image src="/static/03头像@2x.png" alt="" style="width: 100%;height: 100%;">
</view>
<view class="message-item-content" style="margin:0 100rpx 0 10rpx ;">
<view class="template-title">
{{mess.title}}
</view>
<view class="template-item" v-for="(item,index) in baseRobotMessage.data" :key="index"
@click="sendQuestion(item)">
{{item.title}}
</view>
</view>
</view>
</template>
</scroll-view>
<!-- <view class="chat-floor">
<view class="floor-toolbar">
<view class="floor-toolbar-item">
发送照片
</view>
<view class="floor-toolbar-item">
发送订单
</view>
</view>
<u-input class="u-input" placeholder="输入您的问题..." v-model="mesText">
<view slot="suffix">
<u-button color="null" class="self-button" :customStyle="{height:'66rpx',border:'unset'}"
@tap="sendMessage(mesText)" type="success" size="mini">
<img style="width: 110rpx;height: 65rpx;" src="/static/25发送@2x.png" alt="发送">
</u-button>
</view>
</u-input>
</view> -->
</view>
</template>
<script>
import {
getQuestionApi
} from '@/request/wm.js'
export default {
data() {
return {
baseRobotMessage: {
type: 'rebootremplate',
title: '您是否要咨询以下问题?',
data: ['我要如何寄信?', '不知道地址怎么寄信??', '我要如何寄信??', '我要如何寄信?', '不知道地址怎么寄信?', '我要如何寄信?']
},
messageList: [],
hintMessage: ['我要给狱中的朋友寄一封信...', '帮我给好朋友写封信...', '帮我写封信...', '我想给狱中的朋友写封信,有什么注意事项...'],
mesText: '',
userInfo: {},
scrollView: null
}
},
async onLoad() {
this.userInfo = this.$store.userInfo
let {
data
} = await getQuestionApi()
this.baseRobotMessage = data
console.log(data.data);
this.messageList.push({
data: this.baseRobotMessage,
type: 'rebootremplate',
title: '您是否要咨询以下问题?',
})
console.log(this.userInfo);
},
methods: {
sendQuestion(item) {
this.messageList.push({
type: 'user',
message: item.title
})
this.messageList.push({
type: 'rebot',
message: item.answer
})
this.$nextTick(() => {
setTimeout(()=>{
this.scrollView = 'message-' + this.messageList.length
})
})
}
}
}
</script>
<style scoped lang="scss">
.uni-page {
display: flex;
flex-direction: column;
background: radial-gradient(circle, #ffe3d6, #ffe8dd, #fff3ee);
.chat-messageList {
width: 100%;
min-height: 300rpx;
display: flex;
flex-direction: column;
flex: 1;
}
}
.ai-chat-hint {
.message-item {
.message-item-content {
padding: 12rpx;
background-color: transparent;
}
}
}
.ai-chat {
.message-item {
padding: 20rpx 0;
display: flex;
width: 100%;
overflow: hidden;
.message-item-content {
flex: 1;
font-size: 30rpx;
color: #222222;
}
}
.message-item-avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
// border-radius: 50%;
}
}
.hint-message-box {
display: flex;
flex-wrap: wrap;
.hint-message-item {
color: #333333;
width: fit-content;
border-radius: 40rpx;
margin-right: 30rpx;
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.5);
padding: 22rpx 35rpx;
font-size: 32rpx;
}
}
.message-item-content {
padding: 35rpx;
background-color: rgba(255, 255, 255, 0.5);
;
border-radius: 40rpx;
.message-hint-temp-title {
font-size: 32rpx;
// width: 387rpx;
// height: 42rpx;
color: #333333;
}
.message-hint-temp-explain {
// width: 340rpx;
// height: 40rpx;
color: #E08745;
font-size: 30rpx;
}
}
.message-item-chat-template {
.message-item-content {
background-color: #FFFFFF;
}
}
.chat-floor {
padding-bottom: 20rpx;
.floor-toolbar {
display: flex;
font-size: 26rpx;
flex-wrap: wrap;
margin-bottom: 20rpx;
}
.floor-toolbar-item {
display: flex;
align-items: center;
justify-content: center;
width: 123rpx;
height: 52rpx;
background: #FFE7D9;
color: #FE9161;
margin-right: 30rpx;
}
::v-deep .u-input {
height: 102rpx;
border-radius: 20rpx !important;
padding: 0 0rpx 0 20rpx !important;
border: 3rpx solid #FE9161 !important;
}
}
}
.template-title {
font-size: 30rpx;
margin-bottom: 23rpx;
}
.template-item {
font-size: 26rpx;
padding: 23rpx 0;
font-weight: 700;
border-bottom: 1rpx solid #E2E2E2;
}
.self-button {
background-color: unset;
border: unset;
width: 120rpx;
height: 76rpx;
img {
width: 100%;
height: 100%;
}
}
</style>

261
pages/consult/index.vue Normal file
View File

@@ -0,0 +1,261 @@
<template>
<view class="uni-page ai-chat">
<u-navbar :left-icon="null" placeholder :autoBack="true" bgColor="#fff0e7" title="寄信助手"></u-navbar>
<view class="ai-chat-hint">
<view class="message-item-chat message-item">
<view class="message-item-avatar">
<img src="/static/03头像@2x.png" alt="">
</view>
<view class="message-item-content">
<view class="message-hint-temp-title">
Hi,我是你的寄信助手小艾
</view>
<view class="message-hint-temp-explain">
有什么问题可以直接问我...
</view>
</view>
</view>
</view>
<view class="chat-messageList">
<template v-for="(mess,index) in messageList">
<view v-if="mess.type==='user'" :key="index" class="message-item-user message-item">
<view class="message-item-content" style="margin:0 10rpx 0 100rpx;">
我也不周到爱思阿斯加德记录基拉s./萨达好看阿是点开链接啊时间阿圣诞节啊克
</view>
<view class="message-item-avatar">
<img :src="userInfo.avatar" alt="">
</view>
</view>
<view v-if="mess.type==='rebot'" :key="index" class="message-item-chat message-item">
<view class="message-item-avatar">
<img :src="userInfo.avatar" alt="">
</view>
<view class="message-item-content" style="margin:0 100rpx 0 10rpx ;">
我也不周到爱思阿斯加德记录基拉s./萨达好看阿是点开链接啊时间阿圣诞节啊克
</view>
</view>
<view v-if="mess.type==='rebootremplate'" :key="index" class="message-item-chat-template message-item">
<view class="message-item-avatar">
<img src="/static/03头像@2x.png" alt="">
</view>
<view class="message-item-content" style="margin:0 100rpx 0 10rpx ;">
<view class="template-title">
{{baseRobotMessage.title}}
</view>
<view class="template-item" v-for="(item,index) in baseRobotMessage.data" :key="index">
{{item}}
</view>
</view>
</view>
</template>
</view>
<view class="chat-floor">
<view class="floor-toolbar">
<view class="floor-toolbar-item">
发送照片
</view>
<view class="floor-toolbar-item">
发送订单
</view>
</view>
<u-input class="u-input" :placeholder="placeholder" v-module="mesText">
<view slot="suffix">
<u-button color="null" class="self-button" :customStyle="{height:'66rpx',border:'unset'}"
@tap="sendMessage(mesText)" type="success" size="mini">
<img style="width: 110rpx;height: 65rpx;" src="/static/25发送@2x.png" alt="发送">
</u-button>
</view>
</u-input>
</view>
</view>
</template>
<script>
import {
getQuestionApi
} from '@/request/wm.js'
export default {
data() {
return {
placeholder: '输入您的问题...',
baseRobotMessage: {
type: 'rebootremplate',
title: '您是否要咨询以下问题?',
data: ['我要如何寄信?', '不知道地址怎么寄信??', '我要如何寄信??', '我要如何寄信?', '不知道地址怎么寄信?', '我要如何寄信?']
},
messageList: [],
hintMessage: ['我要给狱中的朋友寄一封信...', '帮我给好朋友写封信...', '帮我写封信...', '我想给狱中的朋友写封信,有什么注意事项...'],
mesText: '',
userInfo: {},
}
},
async onLoad() {
this.userInfo = this.$store.userInf
let res = await getQuestionApi()
console.log(res);
this.messageList.push(this.baseRobotMessage)
console.log(this.userInfo);
},
methods: {
sendMessage(mes) {
console.log(mes);
this.messageList.push({
mes: 'mes'
})
}
}
}
</script>
<style scoped lang="scss">
.uni-page {
display: flex;
flex-direction: column;
background: radial-gradient(circle, #ffe3d6, #ffe8dd, #fff3ee);
.chat-messageList {
width: 100%;
display: flex;
flex-direction: column;
flex: 1;
}
}
.ai-chat-hint {
.message-item {
.message-item-content {
padding: 12rpx;
background-color: transparent;
}
}
}
.ai-chat {
.message-item {
padding: 20rpx 0;
display: flex;
width: 100%;
overflow: hidden;
.message-item-content {
flex: 1;
font-size: 30rpx;
color: #222222;
}
}
.message-item-avatar {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
// border-radius: 50%;
}
}
.hint-message-box {
display: flex;
flex-wrap: wrap;
.hint-message-item {
color: #333333;
width: fit-content;
border-radius: 40rpx;
margin-right: 30rpx;
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.5);
padding: 22rpx 35rpx;
font-size: 32rpx;
}
}
.message-item-content {
padding: 35rpx;
background-color: rgba(255, 255, 255, 0.5);
;
border-radius: 40rpx;
.message-hint-temp-title {
font-size: 32rpx;
// width: 387rpx;
// height: 42rpx;
color: #333333;
}
.message-hint-temp-explain {
// width: 340rpx;
// height: 40rpx;
color: #E08745;
font-size: 30rpx;
}
}
.message-item-chat-template {
.message-item-content {
background-color: #FFFFFF;
}
}
.chat-floor {
padding-bottom: 20rpx;
.floor-toolbar {
display: flex;
font-size: 26rpx;
flex-wrap: wrap;
margin-bottom: 20rpx;
}
.floor-toolbar-item {
display: flex;
align-items: center;
justify-content: center;
width: 123rpx;
height: 52rpx;
background: #FFE7D9;
color: #FE9161;
margin-right: 30rpx;
}
::v-deep .u-input {
height: 102rpx;
border-radius: 20rpx !important;
padding: 0 0rpx 0 20rpx !important;
border: 3rpx solid #FE9161 !important;
}
}
}
.template-title {
font-size: 30rpx;
margin-bottom: 23rpx;
}
.template-item {
font-size: 26rpx;
padding: 23rpx 0;
font-weight: 700;
border-bottom: 1rpx solid #E2E2E2;
}
.self-button {
background-color: unset;
border: unset;
width: 120rpx;
height: 76rpx;
img {
width: 100%;
height: 100%;
}
}
</style>

178
pages/coupon/coupon.vue Normal file
View File

@@ -0,0 +1,178 @@
<template>
<view class="cuopon">
<u-navbar title="优惠券" autoBack bg-color="#fff0e7" placeholder></u-navbar>
<view class="cuopon-list">
<scroll-view :scroll-y="true" style="height: 100%;">
<view class="cuopon-item" v-for="item in couponList" :key="item.id">
<view class="amount-wrap">
<view class="amount-sign">
¥
</view>
<view class="amount">
{{ item.balance }}
</view>
</view>
<view class="v-info">
<view class="title">
{{ item.title }}
</view>
<view class="time">
有效期 {{ item.end_time }}
</view>
<view class="v-desc-wrap">
<view class="v-desc">
{{ item.start }}可用
</view>
<view class="v-desc">
自动抵扣
</view>
</view>
</view>
<view class="v-ft">
<u-button class="v-btn" :disabled="!!amount&&item.start >= amount" @click="seleteDiscounts(item)">使用</u-button>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import { getCouponList } from '@/request/yyf.js';
export default {
data() {
return {
checkboxValue: [],
couponList: [],
amount: 0
}
},
onLoad() {
this.getData();
let amount = this.$Route.query.amount;
if( amount ) {
this.amount = Number(amount);
}
},
methods: {
leftClick() {
this.$router.replace('/pages/mine/mine');
},
seleteDiscounts(data){
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit('select', {
data
});
uni.$emit('selectCoupon', data);
uni.navigateBack();
},
async getData() {
const { data } = await getCouponList({
status: 1
});
if(data.code === 1) {
this.couponList = data.data.data;
}
}
}
}
</script>
<style lang="scss" scoped>
.cuopon {
box-sizing: border-box;
height: 100vh;
display: flex;
flex-direction: column;
padding: 30rpx 30rpx 40rpx;
.cuopon-list {
flex: 1;
overflow: hidden;
// background: rgba(255, 255, 255, .4);
.cuopon-item {
display: flex;
margin-bottom: 30rpx;
padding: 25rpx 45rpx;
background-color: #fff;
background: #FFFFFF;
border-radius: 20rpx 20rpx 20rpx 20rpx;
.amount-wrap {
display: flex;
.amount-sign {
font-size: 25rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #FF3838;
line-height: 40rpx;
}
.amount {
width: 120rpx;
margin-left: 5rpx;
font-size: 80rpx;
font-weight: 800;
line-height: 1;
color: #FF3838;
}
}
.v-info {
flex: 1;
padding: 0 35rpx;
.title {
font-size: 32rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #111111;
}
.time {
padding: 14rpx 0;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #8C8C8C;
}
.v-desc-wrap {
display: flex;
flex-wrap: wrap;
.v-desc {
margin-right: 12rpx;
padding: 7rpx 10rpx;
background: #FFE4D9;
font-size: 23rpx;
font-family: OPPOSans Regular-Regular, OPPOSans Regular;
font-weight: 400;
color: #FF3838;
border-radius: 3rpx;
}
}
}
.v-ft {
display: flex;
align-items: flex-end;
.v-btn {
height: 50rpx;
background: #E39B46;
border-radius: 40rpx 40rpx 40rpx 40rpx;
font-size: 23rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #FFFFFF;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,269 @@
<template>
<view class="uni-page">
<u-navbar placeholder :autoBack="true" bgColor="#fff0e7" title="XX书信-手写版"></u-navbar>
<view class="content-main">
<view class="no-picture-chunk" v-if="fileList.length<1" @click="uploadImg">
<view class="picture-chunk-center">
<u-icon name="plus-circle" color="#E49458" size="40"></u-icon>
<text style="color: #e49458; font-size: 30rpx">添加照片</text>
</view>
</view>
<u-grid v-else :border="false" class="picture-chunk" :col="2">
<u-grid-item v-for="(file,index) in fileList" :key="index">
<view class="" style="padding: 20rpx 20rpx;">
<image @click="$showImg(fileList.map(item=>item.url),index)"
style="object-fit: cover; width: 335rpx;height: 278rpx; border-radius: 40rpx;overflow: hidden;"
:src="file.url" alt="">
</view>
</u-grid-item>
<u-grid-item>
<view class="picture-chunk-center"
style="object-fit: cover; width: 335rpx;height: 278rpx; border-radius: 40rpx;overflow: hidden;"
@click="uploadImg">
<u-icon name="plus-circle" color="#E49458" size="40"></u-icon>
<text style="color: #e49458; font-size: 30rpx">添加照片</text>
</view>
</u-grid-item>
</u-grid>
<view class="upload-explain">
<view class="upload-explain-item">
<view class="dot"> </view>
<text class="explain-text">请务必将信纸铺平无褶皱</text>
</view>
<view class="upload-explain-item">
<view class="dot"> </view>
<text class="explain-text">
请在光线充足的条件下拍照避免阴影及画面清晰</text>
</view>
<view class="upload-explain-item">
<view class="dot"> </view>
<text class="explain-text"> 请尽量正面90°角度拍照不要倾斜</text>
</view>
</view>
</view>
<view class="floor-explain">
说明照片会相纸打印随信一起寄出首张照片免费多出部分每张费用按以下顺序改变
{{$store.photoPrice?$store.photoPrice.photo_write.join('元>'):''}}
超出的按最后一个价格延续
</view>
<SelectProductionMethod @selectPlan="selectPlan" @close="isShowNextBox=false" v-if="isShowNextBox">
</SelectProductionMethod>
<view class="floor-button" v-if="fileList.length>0&&canShowToolbar">
<view class="to-view-button" @click="toView">
<u-icon name="eye" color="#222222" size="28" style="margin-right: 10px"></u-icon>书信预览
</view>
<view class="nextstep-button" @click="toNextStep"> 下一步 </view>
</view>
</view>
</template>
<script>
import SelectProductionMethod from "@/components/SelectProductionMethod/SelectProductionMethod.vue";
import {
uploadFile
} from "@/request/api.js";
import {
getPhotoPriceApi
} from "@/request/wm.js";
export default {
components: {
SelectProductionMethod,
},
data() {
return {
fileList: [],
isShowNextBox: false,
canShowToolbar: false,
};
},
onLoad() {
this.getPhotoPrice();
},
methods: {
async uploadImg() {
uni.chooseImage({
count: 1, // 最多可选择的图片数量
success: async (res) => {
let lists = res.tempFilePaths;
let fileListLen = this.fileList.length;
lists.map((item) => {
this.fileList.push({
...item,
status: "uploading",
message: "上传中",
});
});
let {
data
} = await uploadFile(lists[0]);
if (data.code === 1) {
let item = this.fileList[fileListLen];
this.fileList.splice(
fileListLen,
1,
Object.assign(item, {
status: "success",
message: "",
url: data.data.fullurl,
})
);
this.canShowToolbar = true
}
},
fail: (err) => {
console.log("选择照片失败", err);
},
});
},
toView() {
// 这里要发送请求获取预览的拦截
// this.$store.letterViewInfo.message = this.letterData;
// this.$store.letterViewInfo.letterAthor = this.letterAthor;
// this.$store.letterViewInfo.currentTime = this.currentTime;
this.$store.letterViewInfo.fileList = this.fileList.map(item => item.url);
uni.navigateTo({
url: "pages/letter-view/letter-view",
});
// this.isViewLetter = true
},
toNextStep() {
this.isShowNextBox = true;
},
async getPhotoPrice() {
let {
data
} = await getPhotoPriceApi();
// this.$mutations.setPhotoPrice(data.data)
this.$set(this.$store, "photoPrice", data.data);
// console.log(this.$store.photoPrice,'111');
// console.log(data);
},
selectPlan(item) {
let data = {
message: "",
thumb: this.fileList.map((item) => item.url),
send_address: "",
take_address: "",
affix: "",
remark: "",
mail_type: item.id,
isMmanual: true,
};
this.$set(this.$store, "letterInfo", data);
uni.navigateTo({
url: "pages/confirmOrder/confirmOrder",
});
},
},
};
</script>
<style lang="scss">
.uni-page {
display: flex;
flex-direction: column;
.content-main {
flex: 1;
overflow: auto;
// height: 100%;
}
}
.no-picture-chunk {
margin: 30rpx 0;
height: 496rpx;
box-sizing: border-box;
background-color: rgba(255, 255, 255, 0.5);
padding: 43rpx;
border-radius: 40rpx;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.picture-chunk-center {
margin-bottom: 20rpx;
background-color: rgba(255, 255, 255, 0.5);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.picture-chunk {
.picture-chunk-center {
width: 335rpx;
height: 278rpx;
border-radius: 40rpx;
background-color: rgba(255, 255, 255, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
.upload-explain {
padding-left: 30rpx;
.upload-explain-item {
display: flex;
align-items: center;
margin-bottom: 10rpx;
.dot {
width: 12rpx;
height: 12rpx;
background-color: #999796;
margin-right: 14rpx;
border-radius: 50%;
}
.explain-text {
flex: 1;
font-size: 26rpx;
opacity: 0.5;
}
}
}
.floor-explain {
font-size: 26rpx;
font-weight: 400;
color: #222222;
text-align: center;
margin-bottom: 20rpx;
opacity: 0.7;
}
.floor-button {
display: flex;
.to-view-button {
width: 459rpx;
min-height: 98rpx;
background-color: #ffe4d9;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30rpx;
}
.nextstep-button {
flex: 1;
background: linear-gradient(to bottom right, #e8b648, #e08745);
min-height: 98rpx;
border-radius: 20rpx;
color: white;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>

View File

@@ -0,0 +1,285 @@
<template>
<view class="uni-page">
<u-navbar placeholder :autoBack="true" bgColor="#fff0e7" title="编辑书信" />
<view class="letter-content">
<textarea input-mode="multiline" :maxlength="-1" v-model="letterData" :autoHeight="true" placeholder="请输入内容"
border="bottom"></textarea>
</view>
<view class="signature-time">
<view class="signature">
<!-- <u--textarea :maxlength="10" class="signature-input" v-model="letterAthor" placeholder="请输入署名"
border="bottom"></u--textarea> -->
<u--input style="white-space: pre-wrap;" inputAlign="center" placeholder="请输入署名" v-model="letterAthor"
border="bottom" :customStyle="{
width:'200rpx'
}">
</u--input>
</view>
<view class="time">
<!-- {{typeof new Date}} -->
{{ currentTime }}
</view>
</view>
<view class="img-list-box">
<u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" multiple :maxCount="10"
:previewFullImage="true">
<view class="upload-box">
<view class="plus-circle">
<u-icon name="plus-circle" color="#e49458" size="35"></u-icon>
<view style="margin-top:10rpx;">
添加照片
</view>
</view>
</view>
</u-upload>
</view>
<view class="photo-explain">
<SelectProductionMethod @selectPlan="selectPlan" @close="isShowNextBox=false" v-if="isShowNextBox">
</SelectProductionMethod>
说明照片会相纸打印随信一起寄出首张照片免费多出部分每张费用按以下顺序改变
{{$store.photoPrice?$store.photoPrice.photo_artificial:''}}
超出的按最后一个价格延续
</view>
<view class="bottom-button">
<view class="to-view-button" @click="toView">
<u-icon name="eye" color="#222222" size="28" style="margin-right:10px;"></u-icon>书信预览
</view>
<view class="nextstep-button" @click="toNextStep">
下一步
</view>
</view>
</view>
</template>
<script>
import {
uploadFile
} from '@/request/api.js'
import {
getPhotoPriceApi
} from '@/request/wm.js'
import SelectProductionMethod from '@/components/SelectProductionMethod/SelectProductionMethod.vue'
export default {
components: {
SelectProductionMethod
},
data() {
return {
letterData: '',
letterAthor: '',
fileList: [],
isShowNextBox: false,
currentTime: (new Date).$formatDate()
}
},
onLoad(opt) {
if (opt.clear) {
this.$set(this.$store, 'letterInfo', {})
}
this.getPhotoPrice()
this.letterData = this.$store.letterInfo.message
console.log(this.letterData);
},
methods: {
deletePic(event) {
this.fileList.splice(event.index, 1)
},
async afterRead(event) {
console.log(event);
let lists = [].concat(event.file)
let fileListLen = this.fileList.length;
lists.map((item) => {
this.fileList.push({
...item,
status: 'uploading',
message: '上传中'
})
})
let res = await uploadFile(event.file[0].url);
console.log(res);
if (res.data.code === 1) {
let item = this.fileList[fileListLen];
this.fileList.splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: res.data.data.fullurl
}))
}
},
toView() {
// 这里要发送请求获取预览的拦截
// uni.showLoading({
// title: '加载中'
// });
this.$store.letterViewInfo.message = this.letterData;
this.$store.letterViewInfo.letterAthor = this.letterAthor;
this.$store.letterViewInfo.currentTime = this.currentTime;
this.$store.letterViewInfo.fileList = this.fileList;
console.log(this.$store.letterViewInfo);
uni.navigateTo({
url: "pages/letter-view/letter-view",
})
// this.isViewLetter = true
},
toNextStep() {
this.isShowNextBox = true
},
async getPhotoPrice() {
let {
data
} = await getPhotoPriceApi()
this.$set(this.$store, 'photoPrice', data.data)
this.$store.productionType.forEach(item => {
console.log(data.data[item.key],'111111111111111');
let price = data.data[item.key]?.find(price => {
if (+price > 0) {
return true
}
})
item.price = price || 0
})
console.log(this.$store.productionType, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
},
selectPlan(item) {
this.$store.letterInfo.message = this.letterData;
this.$store.letterInfo.mail_type = item.id
this.$store.letterInfo.thumb = this.fileList.map(item => {
return item.url
})
this.$store.letterInfo.affix = this.letterAthor
uni.navigateTo({
url: 'pages/confirmOrder/confirmOrder?plan=' + item.id,
})
}
},
}
</script>
<style scoped lang="scss">
.uni-page {
display: flex;
flex-direction: column;
position: relative;
}
.letter-content {
padding: 30rpx;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 20rpx;
height: fit-content;
flex: 1;
margin-top: 20rpx;
textarea {
// min-height: 300rpx;
width: 100%;
background-color: transparent;
}
}
::v-deep.signature-input {
max-width: 300rpx;
width: 300rpx;
text-align: center;
height: 30rpx;
border-bottom: unset;
// text-align: center;
background-color: transparent;
textarea {
height: 30rpx;
}
}
.signature-time {
margin-top: 10rpx;
display: flex;
flex-direction: column;
justify-content: end;
text-align: center;
align-items: flex-end;
;
.time,
.signature {
width: 300rpx;
text-align: center;
display: flex;
justify-content: center;
}
>view {
width: fit-content;
// width: 250px;
text-align: center;
}
}
.upload-box {
width: 150rpx;
height: 150rpx;
border-radius: 20rpx;
background-color: #fffdfc;
color: #CE7A2C;
font-size: 25rpx;
font-weight: 500;
}
.plus-circle {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.photo-explain {
height: 100rpx;
margin-top: 20rpx;
font-size: 26rpx;
font-weight: 400;
color: #9f9a97;
margin-bottom: 150rpx;
}
.bottom-button {
position: fixed;
bottom: 10rpx;
width: calc(100% - 40rpx);
display: flex;
z-index: 11;
}
.to-view-button {
width: 459rpx;
min-height: 98rpx;
background-color: #ffe4d9;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 30rpx;
}
.nextstep-button {
flex: 1;
background: linear-gradient(to bottom right, #e8b648, #e08745);
min-height: 98rpx;
border-radius: 20rpx;
color: white;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
.nextstep-button:hover {
background-color: black;
}
</style>

262
pages/index/index.vue Normal file
View File

@@ -0,0 +1,262 @@
<template>
<view class="uni-page">
<u-navbar :leftIcon="null" placeholder bgColor="#fff0e7" title="首页"></u-navbar>
<view class="index-item ai-helper-welcome" @click="navigateTo('/pages/aiChat/aiChat')">
<image src="~@/static/01banner@2x.png" alt="" style="width: 100%;height: 100%;">
</view>
<view class="index-item ai-to-write" @click="navigateTo('/pages/aiChat/aiChat')">
<view class="index-item-img">
</view>
<view class="index-item-content">
<view class="index-item-title">
用AI寄信助手写信
</view>
<view class="index-item-explain">
简单几步智能寄信..
</view>
</view>
<view class="index-item-right-icon">
<image src="/static/01跳转@2x.png" alt="" style="width: 12.58rpx;height: 21.72rpx;">
</view>
</view>
<view class="index-item user-to-write" @click="navigateTo('pages/editor-letter/editor-letter?clear=1')">
<view class="index-item-img">
</view>
<view class="index-item-content">
<view class="index-item-title">
在线填写或手写拍照
</view>
<view class="index-item-explain">
自己写信问候远方的朋友...
</view>
</view>
<view class="index-item-right-icon">
<image src="/static/01跳转@2x.png" alt="" style="width: 12.58rpx;height: 21.72rpx;">
</view>
</view>
<view class="write-explain">
请选择对应的寄信方式AI寄信更便捷哦
</view>
<view class="grid-box">
<view class="grid-item" v-for="(item,index) in bottomOption" :key="item.name" @click="()=>{
navigateTo(item.target)
}">
<view class="grid-item-img">
<image :src="item.img" alt="" style="width: 100%;height: 100%;">
</view>
<view class="grid-item-content">
<view class="grid-item-title">
{{item.title}}
</view>
<view class="grid-item-explain">
{{item.explain}}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {
bottomOption: [
// {
// title: '写信须知',
// explain: '写信注意事项',
// img: '/static/01-1写信@2x.png',
// // target: 'pages/agentBusiness/agentBusiness'
// }, {
// title: '寄信样稿',
// explain: '寄信模板参考',
// img: '/static/01-2寄信@2x.png',
// // target: 'pages/agentBusiness/agentBusiness'
// },
{
title: '代收信件',
explain: '查看历史草稿',
img: 'https://jx.xiaolinghou.com/webtest/static/01-3代收@2x.png',
target: 'pages/agentBusiness/agentBusiness'
}, {
title: '地址查询',
explain: '看守所/监狱',
img: '/static/01-4回信@2x.png',
target: 'pages/queryAddr/queryAddr'
}
]
}
},
onLoad() {
uni.showTabBar()
// this.checkIsLogin()
},
methods: {
navigateTo(url) {
console.log(url);
uni.navigateTo({
url
})
},
// checkIsLogin() {
// if (this.$isWechat()) {
// uni.getStorage({
// key: 'token',
// success: (res) => {
// },
// fail: (res) => {
// uni.navigateTo({
// url: '/pages/login/login'
// })
// }
// });
// }
// },
toAiWrite() {
}
}
}
</script>
<style scoped lang="scss">
.index-item {
margin: 30rpx auto;
width: 690rpx;
height: 261rpx;
border-radius: 20rpx 20rpx 20rpx 20rpx;
background-size: 100%;
padding: 10px;
box-sizing: border-box;
display: flex;
align-items: center;
background: #FFD0B1;
}
.index-item.ai-helper-welcome {
padding: 0;
background-size: 100%;
}
.ai-helper-welcome {
// background-image: url(~@/static/01banner@2x.png);
}
.index-item-img {
width: 166rpx;
height: 166rpx;
background-size: 100%;
}
.ai-to-write {
.index-item-img {
background-image: url(~@/static/01AI@2x.png);
}
}
.user-to-write {
background-color: #FFDEAC;
.index-item-img {
background-image: url(~@/static/01填写.png);
}
}
.index-item-title {
font-size: 34rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #111111;
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
}
.index-item-content {
// padding: 0 15px;
padding-left: 20px;
width: 334rpx;
}
.index-item-explain {
font-size: 26rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #333333;
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
}
.index-item-right-icon {
width: 10%;
height: 40%;
text-align: right;
}
.write-explain {
width: 100%;
text-align: center;
height: 37rpx;
font-size: 28rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
margin-bottom: 50rpx;
color: #86807e;
}
.grid-box {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 10rpx;
.grid-item {
margin-bottom: 20px;
width: 335rpx;
height: 136rpx;
background: #FFFFFF;
border-radius: 20rpx;
}
}
.grid-item {
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
padding-left: 50rpx
}
.grid-item-img {
width: 70rpx;
height: 70rpx;
padding-right: 14rpx;
img {
width: 100%;
height: 100%;
}
}
.grid-item-content {
.grid-item-title {
width: 120rpx;
font-size: 30rpx;
font-weight: bold;
}
.grid-item-explain {
color: #c4c4c4;
font-size: 24rpx;
}
}
</style>

View File

@@ -0,0 +1,77 @@
<template>
<view class="preview">
<u-navbar title="书信预览" autoBack bg-color="transparent" placeholder></u-navbar>
<view class="preview-content">
<view class="preview-content-inner" style="background: url(../../static/mine/preview_bg.png) center/100% 100% no-repeat;">
<view style="white-space: pre-wrap; line-height: 40rpx;">
{{ letterInfo.message||'' }}
</view>
<view class="preview-ft" v-if="loading">
<view class="name">
{{ letterInfo.letterAthor||'' }}
</view>
<view class="time">
{{ letterInfo.currentTime||'' }}
</view>
</view>
<view class="preview-image" v-if="letterInfo.fileList.length > 0">
<image v-for="(item, index) in letterInfo.fileList" :key="index" :src="item.url" style="width: 100%;"></image>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
viewImgSrc: '',
loading: true
}
},
computed: {
letterInfo() {
console.log(this.$store.letterViewInfo);
return this.$store.letterViewInfo
}
},
onLoad(option) {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.preview {
box-sizing: border-box;
height: 100vh;
padding: 30rpx 0 0 0;
display: flex;
flex-direction: column;
.preview-content {
flex: 1;
overflow: auto;
.preview-content-inner {
box-sizing: border-box;
padding: 240rpx 80rpx 140rpx;
overflow-y: auto;
font-family: caisemenghuanjingyu;
}
.preview-ft {
// padding-top: 40rpx;
view {
display: flex;
justify-content: flex-end;
}
}
}
}
</style>

431
pages/login/login.vue Normal file
View File

@@ -0,0 +1,431 @@
<template>
<view class="page">
<!-- <u-navbar :autoBack="true" bgColor="#fff0e7" title="登录"></u-navbar> -->
<view class="top-background-raduis">智能寄信</view>
<view class="login-box">
<view class="login-card-title">
<view class="login-card-title-content">{{
titleData[loginPattern]
}} </view>
</view>
<view class="login-card-input login-card-input-account" v-if="loginPattern==='userLogin'">
<!-- 输入框头部图标 -->
<u--input class="hj-input" v-model="userInfo.account" focus maxlength="30" :trim="true"
@focus="UserNamePassWrodFocusBorderStyle" :styles="inputColorConfigToUserName"
@blur="UserNamePassWrodBlurBorderStyle" placeholder="请输入账号"></u--input>
<!-- 输入框头部图标 -->
<u--input class="hj-input" v-model="userInfo.password" type="password" @focus="PassWordFocusBorderStyle"
@blur="PassWordBlurBorderStyle" :styles="inputColorConfigToPassWord" placeholder="请输入密码"></u--input>
</view>
<view class="login-card-input login-card-input-account"
v-if="loginPattern==='forgotPassword'||loginPattern==='captchaLogin'">
<!-- 输入框头部图标 -->
<u--input class="hj-input" v-model="captchaInfo.mobile" focus maxlength="30" :trim="true"
@focus="UserNamePassWrodFocusBorderStyle" :styles="inputColorConfigToUserName"
@blur="UserNamePassWrodBlurBorderStyle" placeholder="请输入手机号"></u--input>
<view class="hj-input" style="display: flex;justify-content: center;"
v-if="$isPhoneNumber(captchaInfo.mobile)">
<u-code-input :disabledKeyboard="!$isPhoneNumber(captchaInfo.mobile)" :maxlength="4"
v-model="captchaInfo.captcha"></u-code-input>
<view style="margin-left: 10rpx;">
<u-toast ref="uToast"></u-toast>
<u-code :seconds="seconds" @end="end" @start="start" ref="uCode" @change="codeChange"></u-code>
<u-button @tap="getCode">{{captchaButtonText}}</u-button>
</view>
</view>
<u--input class="hj-input" v-if="loginPattern==='forgotPassword'&&$isPhoneNumber(captchaInfo.mobile)"
v-model="forgotPasswordInfo.newpassword" type="password" @focus="PassWordFocusBorderStyle"
@blur="PassWordBlurBorderStyle" :styles="inputColorConfigToPassWord" placeholder="请输入密码"></u--input>
<!-- 输入框头部图标 -->
<!-- <u--input class="hj-input" v-model="userInfo.password" type="password" @focus="PassWordFocusBorderStyle"
@blur="PassWordBlurBorderStyle" :styles="inputColorConfigToPassWord" placeholder="请输入密码"></u--input> -->
</view>
<view class="login-card-loginIn" @click="submitLoginData"
v-if="loginPattern==='userLogin'||$isPhoneNumber(captchaInfo.mobile)&&captchaInfo.captcha.length===4">
<view class="login-card-loginIn-btn">
{{loginPattern==='forgotPassword'?'找回密码':'登 录'}}
</view>
</view>
<view class="login-bottom-info">
<view class="info-item" v-if="loginPattern!=='captchaLogin'" @click="loginPattern ='captchaLogin'">
手机号登录
</view>
<view class="info-item" v-if="loginPattern !=='userLogin'" @click="loginPattern ='userLogin'">
账号密码登录
</view>
<view class="info-item" @click="loginPattern ='forgotPassword'" v-if="loginPattern !=='forgotPassword'">
忘记密码
</view>
<!-- <view class="info-item" @click="toRegister" v-if="loginPattern !=='forgotPassword'">
立刻注册
</view> -->
</view>
</view>
<view class="bottom-message">
登录/注册 代表你已同意用户使用协议
</view>
<view class="top-background-raduis-bootom"></view>
</view>
</template>
<script>
import {
userLogin,
phonenumberLogin,
sendVerifyCode,
retrievePassword
} from '@/request/api.js'
import {
onLoad
} from 'uview-ui/libs/mixin/mixin';
export default {
data() {
return {
// 输入框边框颜色默认值
colorDefault: '#b4b4b4',
// 输入框边框聚焦值
colorFocusColor: '#3cb79a',
// 输入框颜色配置
inputColorConfigToUserName: {
color: "#000000",
disableColor: "#eee",
borderColor: "#b4b4b4",
},
// 输入框颜色配置
inputColorConfigToPassWord: {
color: "#000000",
disableColor: "#eee",
borderColor: "#b4b4b4",
},
value: "",
userInfo: {
account: '',
password: ''
},
titleData: {
captchaLogin: '验证码登录',
forgotPassword: '找回密码',
userLogin: '账号密码登录'
},
captchaInfo: {
mobile: '',
captcha: '',
},
forgotPasswordInfo: {
mobile: '',
captcha: '',
newpassword: ''
},
// registerInfo: {
// }
showCaptchInput: false,
seconds: 60,
captchaButtonText: '获取验证码',
loginPattern: 'captchaLogin', //userLogin captchaLogin forgotPassword
};
},
onLoad() {},
//监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object用于页面传参触发时机早于 onLoad
onInit() {},
//监听页面加载,其参数为上个页面传递的数据,参数类型为 Object用于页面传参
//监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
async onLoad() {
// #ifdef H5
if (await this.$isWechat()) {
console.log('当前登录环境微信H5');
if (this.$getUrlParams('code')) {
this.$wechatloginAfter(this.$getUrlParams('code'))
return
} else if (uni.getStorageSync('token')) {
uni.navigateTo({
url: '/'
})
return
} else {
this.$login()
}
} else {
console.log('当前登录环境普通H5');
}
// #endif
//
// #ifdef MP-WEIXIN
console.log('当前登录环境:微信')
this.$login()
// #endif
},
//监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
beforeDestroy() {},
//页面滚动到底部的事件不是scroll-view滚到底常用于下拉下一页数据。
onReachBottom() {},
onShareAppMessage() {},
created() {},
methods: {
async getCode() {
try {
if (this.$refs.uCode.canGetCode) {
uni.showLoading({
title: '正在获取验证码'
})
let event = ''
switch (this.loginPattern) {
case "captchaLogin":
event = 'mobilelogin'
break;
default:
event = 'savepwd'
break;
}
let {
data
} = await sendVerifyCode({
mobile: this.captchaInfo.mobile,
event
})
console.log(data);
this.$refs.uCode.start();
} else {
uni.$u.toast('倒计时结束后再发送');
}
} catch (e) {
console.log(e);
}
},
toRegister() {
uni.navigateTo({
url: 'pages/register/register'
})
},
async submitLoginData() {
// loginPattern: 'userLogin', // captchaLogin forgotPassword
try {
let res
if (this.loginPattern === "userLogin") {
let {
data
} = await userLogin(this.userInfo)
console.log(data);
res = data.data
if (!data.code) throw (data.msg)
} else if (this.loginPattern === "captchaLogin") {
let {
data
} = await phonenumberLogin({
...this.captchaInfo,
event: 'mobilelogin'
})
console.log(data);
if (!data.code) throw (data.msg)
res = data.data
} else {
this.forgotPasswordInfo = {
...this.forgotPasswordInfo,
...this.captchaInfo,
}
let {
data
} = await retrievePassword(this.forgotPasswordInfo)
console.log(data);
if (!data.code) throw (data.msg)
res = data.data
this.loginPattern = 'userLogin'
uni.$u.toast('密码重置成功');
return
}
uni.setStorageSync('userInfo', res.userinfo)
uni.setStorageSync('token', res.userinfo.token)
this.$mutations.setUserInfo(res.userinfo)
this.$set(this.$store, 'userInfo', res.userinfo)
console.log(this.$store.userInfo);
uni.redirectTo({
url: '/pages/index/index'
})
} catch (e) {
uni.$u.toast(e);
console.log(e);
}
// console.log(data);
},
codeChange(text) {
this.captchaButtonText = text
},
end() {
// uni.$u.toast('倒计时结束');
},
start() {
uni.$u.toast('验证码发送成功');
},
// 输入框聚焦变换边框样式
UserNamePassWrodFocusBorderStyle() {
this.inputColorConfigToUserName.borderColor = this.colorFocusColor;
},
PassWordFocusBorderStyle() {
this.inputColorConfigToPassWord.borderColor = this.colorFocusColor;
},
// 输入框失去焦点变换边框样式
UserNamePassWrodBlurBorderStyle() {
this.inputColorConfigToUserName.borderColor = this.colorDefault;
},
PassWordBlurBorderStyle() {
this.inputColorConfigToPassWord.borderColor = this.colorDefault;
},
},
};
</script>
<style lang="scss" scoped>
* {
box-sizing: border-box;
}
uni-page-body {
padding: 0 0 0 0 !important;
}
.page {
position: relative;
height: 100vh;
}
.top-background-raduis {
height: 30%;
background-color: #3cb79a;
padding-top: 100rpx;
display: flex;
align-items: flex-start;
color: white;
font-weight: bold;
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
font-size: 50rpx;
// background-image: url(/static/01banner.png);
background-size: 100% cover;
justify-content: center;
// background-color: #ffd0b1;
// border-bottom-left-radius: 50%;
// border-bottom-right-radius: 50%;
border-radius: 0 0 0 100%;
}
.top-background-raduis-bootom {
height: 500rpx;
border-radius: 0 100% 0 0;
width: 100%;
// border-top-left-radius: 50%;
// border-top-right-radius: 50%;
background-color: #3cb79a;
position: fixed;
bottom: 0;
}
/deep/ .is-input-border {
border-radius: 7px !important;
}
/deep/ .uni-easyinput__content {
min-height: 39px !important;
}
.hj-input {
margin-bottom: 20rpx;
margin-top: 15rpx;
}
.hj-input:nth-child(2) {
margin-top: 35rpx;
}
.login-box {
top: 20%;
position: absolute;
width: 80%;
left: 50%;
transform: translateX(-50%);
right: 10%;
max-height: 650rpx;
padding: 30rpx;
background-color: white;
border-radius: 40rpx;
box-shadow: 9rpx 9rpx 6rpx rgba(0, 0, 0, 0.3);
z-index: 1;
.login-card-input {
// background-color: violet;
// height: 50%;
padding: 5rpx;
::v-deep .u-input {
margin-bottom: 20rpx;
}
}
.login-card-title {
height: 20%;
// background-color: black;
padding: 10rpx;
display: flex;
justify-content: center;
.login-card-title-content {
font-size: 1.2em;
color: #3cb79a;
border-bottom: 3px solid #3cb79a;
}
}
.login-card-loginIn {
height: 110rpx;
display: flex;
justify-content: center;
padding: 10rpx;
align-items: center;
.login-card-loginIn-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #3cb79a;
width: 100%;
font-size: 1.2em;
height: 70rpx;
border-radius: 40rpx;
color: white;
}
}
.login-bottom-info {
height: 50rpx;
display: flex;
font-size: 20rpx;
color: #3cb79a;
justify-content: center;
align-items: center;
}
.info-item {
margin-top: 20rpx;
margin-left: 30rpx;
font-size: 30rpx;
}
}
.bottom-message {
position: absolute;
height: 70rpx;
display: flex;
z-index: 99;
width: 100%;
justify-content: center;
align-items: center;
font-size: 20rpx;
overflow: hidden;
color: white;
bottom: 80rpx;
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<!-- 用户信息组件 -->
<view class="mine-hd">
<view class="mine-info">
<view class="mine-avatar">
<image :src="userInfo.avatar" mode="aspectFit"></image>
</view>
<view class="mine-info-text">
<view class="name">
<view class="name-text">{{ userInfo.nickname }}</view>
<!-- <view class="member-sign">
<image src="../../../static/mine/m_gorden_member.png" mode="aspectFit" v-if="memberStatus"></image>
<image src="../../../static/mine/m_normal_member.png" mode="aspectFit" v-else></image>
</view> -->
</view>
<!-- <view class="member-text">
<text v-if="memberStatus">会员到期时间: 2023-05-28 24:00:00</text>
<text v-else>暂未开通会员</text>
</view> -->
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
memberStatus: false,
orderList: []
}
},
computed: {
userInfo() {
return this.$storeMine.userInfo;
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.mine-hd {
padding: 0 0 30rpx;
.mine-info {
display: flex;
align-items: center;
.mine-avatar {
image {
width: 109rpx;
height: 109rpx;
border-radius: 9999rpx;
}
}
.mine-info-text {
padding-left: 25rpx;
.name {
display: flex;
align-items: center;
.name-text {
line-height: 40rpx;
font-size: 38rpx;
font-weight: 600;
}
.member-sign {
padding-left: 10rpx;
image {
width: 150rpx;
height: 40rpx;
}
}
}
.member-text {
padding-top: 10rpx;
font-size: 24rpx;
}
}
}
}
</style>

369
pages/mine/mine.vue Normal file
View File

@@ -0,0 +1,369 @@
<template>
<view class="uni-page mine">
<u-navbar title="个人中心" leftIconSize="0" bg-color="transparent" placeholder></u-navbar>
<MineHeader></MineHeader>
<view class="mine-inner">
<!-- 开通会员 -->
<view class="open-member">
<view class="open-member-hd">
<template v-if="userInfo.vip_end">
<view class="open-member-hd-left">
<image class="open-member-hd-left-vip" src="../../static/mine/m_member_vip.png" mode="">
</image>
<text>会员到期时间</text>
</view>
<view class="open-member-hd-right" @click="jumpPage('/pages/mine/openMember')">
<text>有效期至{{ userInfo.vip_end }}</text>
</view>
</template>
<template v-else>
<view class="open-member-hd-left">
<image class="open-member-hd-left-vip" src="../../static/mine/m_member_vip.png" mode="">
</image>
<text>开通会员功能</text>
</view>
<view class="open-member-hd-right" @click="jumpPage('/pages/mine/openMember')">
<text>享受更多特权</text>
<u-icon name="arrow-right" size="14" color="#6D3B00"></u-icon>
</view>
</template>
</view>
<!-- 钱包 -->
<view class="open-member-bd">
<view class="open-member-bd-left">
我的钱包
</view>
<view class="open-member-bd-right">
{{ userInfo.money }}
<!-- <text>我的钱包</text>
<u-icon name="arrow-right" size="14" color="#ababab"></u-icon> -->
</view>
</view>
</view>
<!-- 订单 -->
<view class="order-entrance">
<view class="order-entrance-title">
我的订单
</view>
<view class="order-entrance-list">
<view class="order-entrance-list-item" v-for="item in order" :key="item.label"
@click="jumpPage(item.path)">
<view class="order-entrance-list-item-value">
<text class="number">{{ orderNum[item.type] || 0 }}</text>
<text class="unit"></text>
</view>
<view class="order-entrance-list-item-label">
{{ item.label }}
</view>
</view>
</view>
</view>
<!-- 菜单 -->
<view class="menu">
<view class="menu-item" v-for="item in menuList" :key="item.label" @click="jumpPage(item.path)">
<view class="menu-item-inner">
<view class="menu-item-icon">
<!-- <component :is="item.icon" size="20"></component> -->
<u-icon :name="item.icon" size="20"></u-icon>
</view>
<view class="menu-item-text">
<view class="label">
{{ item.label }}
</view>
<view class="desc">
{{ item.desc }}
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import MineHeader from './components/MineHeader.vue';
import {
getOrderList,
getUserInfo
} from '@/request/yyf.js';
export default {
components: {
MineHeader,
},
data() {
return {
order: [{
label: '待付款',
type: '0',
path: '/pages/mine/mineOrder?type=0'
},
{
label: '待寄出',
type: '1',
path: '/pages/mine/mineOrder?type=1'
},
{
label: '已寄出',
type: '2',
path: '/pages/mine/mineOrder?type=2'
},
{
label: '被退回',
type: '3',
path: '/pages/mine/mineOrder?type=3'
},
{
label: '已取消',
type: '4',
path: '/pages/mine/mineOrder?type=4'
},
],
menuList: [
// { label: '邀请有礼', path: '', icon: 'share-square', desc: '邀请好友获取收益' },
{
label: '地址管理',
path: '/pages/address/address',
icon: 'map',
desc: '添加收件地址'
},
{
label: '我的优惠券',
path: '/pages/coupon/coupon',
icon: 'coupon',
desc: '查看我的优惠券'
},
// { label: '咨询客服', path: '', icon: 'server-fill', desc: '在线咨询客服' },
{
label: '系统设置',
path: '/pages/setting/setting',
icon: 'setting',
desc: '基本资料设置'
},
// { label: '关于我们', path: '', icon: 'error-circle', desc: '公司基本介绍' },
]
}
},
computed: {
userInfo() {
return this.$storeMine.userInfo;
},
orderList() {
return this.$storeMine.orderList;
},
orderNum() {
return this.$storeMine.orderNum;
},
prevTime() {
let {
prevtime
} = this.userInfo;
const date = new Date(prevtime * 1000);
const year = date.getFullYear(); // 获取年份
const month = date.getMonth() + 1 > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1); // 获取月份需要加1
const day = date.getDate() > 10 ? date.getDate() : '0' + date.getDate(); // 获取日期
const hour = date.getHours() > 10 ? date.getHours() : '0' + date.getHours(); // 获取小时
const minute = date.getMinutes() > 10 ? date.getMinutes() : '0' + date.getMinutes(); // 获取分钟
const second = date.getSeconds() > 10 ? date.getSeconds() : '0' + date.getSeconds(); // 获取秒数
const formattedDate = `${year}-${month}-${day}`; // 拼接成格式化后的日期字符串
return formattedDate
}
},
onShow() {
this.$actionsMine.onGetuserInfo();
this.$actionsMine.onGetOrderNum();
},
methods: {
jumpPage(path) {
// console.log(path);
path && this.$Router.push(path);
},
},
}
</script>
<style lang="scss" scoped>
/deep/.u-icon {
display: inline-block;
}
.mine-inner {
.open-member {
height: 210rpx;
background: url(../../static/mine/m_member_bg.png) center/100% no-repeat;
.open-member-hd {
padding: 17rpx 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.open-member-hd-left {
display: flex;
align-items: center;
&-vip {
width: 46rpx;
height: 40rpx;
}
text {
padding-left: 27rpx;
line-height: 1;
font-family: PingFang SC-Bold, PingFang SC;
font-size: 26rpx;
font-weight: 600;
color: #6D3B00;
}
}
.open-member-hd-right {
cursor: pointer;
display: flex;
align-items: center;
text {
padding-right: 10rpx;
line-height: 1;
font-family: PingFang SC-Bold, PingFang SC;
font-size: 24rpx;
color: #6D3B00;
}
}
}
.open-member-bd {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
padding: 0 30rpx;
height: 130rpx;
background-color: #fff;
border-radius: 40rpx;
&-left {
font-size: 34rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #111111;
}
&-right {
display: flex;
align-items: center;
text {
padding-right: 10rpx;
}
cursor: pointer;
font-size: 24rpx;
font-family: PingFang SC-Bold,
PingFang SC;
color: #ababab;
}
}
}
.order-entrance {
box-sizing: border-box;
margin-top: 26rpx;
height: 260rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 40rpx 40rpx;
padding: 30rpx 40rpx;
.order-entrance-title {
padding-bottom: 45rpx;
font-size: 34rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #333333;
}
.order-entrance-list {
cursor: pointer;
display: flex;
.order-entrance-list-item {
flex: 1;
text-align: center;
&-label {
padding-top: 18rpx;
font-size: 26rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #333333;
}
&-value {
.number {
font-size: 34rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #CE7A2C;
}
.unit {
padding-left: 5rpx;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #CE7A2C;
}
}
}
}
}
.menu {
display: flex;
flex-wrap: wrap;
margin: 0 -10rpx;
.menu-item {
margin-top: 10px;
box-sizing: border-box;
padding: 0 10rpx;
width: 50%;
.menu-item-inner {
cursor: pointer;
box-sizing: border-box;
padding: 37rpx 39rpx;
background-color: #fff;
border-radius: 40rpx;
display: flex;
.menu-item-icon {
padding-right: 12rpx;
}
.menu-item-text {
.label {
font-size: 26rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #111111;
line-height: 1;
}
.desc {
padding-top: 10rpx;
font-size: 20rpx;
color: #ababab;
line-height: 1;
}
}
}
}
}
}
</style>

443
pages/mine/mineOrder.vue Normal file
View File

@@ -0,0 +1,443 @@
<template>
<view class="order">
<u-navbar title="我的订单" @leftClick="leftClick" placeholder bg-color="#fff0e7"></u-navbar>
<view class="tabs-wrap">
<u-tabs
:list="tabList"
:current="currentType"
lineColor="#E39B46"
lineHeight="12rpx"
:activeStyle="{
color: '#333333',
fontSize: '26rpx',
fontWeight: 'bold'
}"
:inactiveStyle="{
color: '#333333',
fontSize: '26rpx',
}"
@click="changeTab"
>
</u-tabs>
</view>
<view class="order-inner">
<scroll-view style="height: 100%;"
scroll-y="true"
refresher-enabled
:refresher-triggered="refreshState"
@refresherrefresh="onScrollRefresh"
@scrolltolower="loadMoreData"
>
<template v-if="currentOrder.length > 0">
<view class="order-item" v-for="item in currentOrder" :key="item.id" >
<view class="order-hd">
<view class="order-id">订单号 {{ item.id }}</view>
<view class="order-time">{{ item.create_time }}</view>
</view>
<view class="order-address">
<view class="name">
<view style="min-width: 55%; display: flex;">
<view class="name-left">
{{ item.send_address[0] }}
</view>
<view class="name-icon">
<image src="../../static/mine/m_order_arrow.png" mode=""></image>
</view>
</view>
<view class="name-right" style="flex: 1;">
{{ item.take_address[0] }}
</view>
</view>
<view class="address-text">
<view class="address-text-inner" >
{{ item.send_address[2] }}
</view>
<view class="address-text-inner">
{{ item.take_address[2] }}
</view>
</view>
</view>
<view class="order-opera">
<template v-if="currentType === 0">
<u-button text="取消付款" plain shape="circle" @click="confirmCancel(item)"></u-button>
<u-button text="去付款" type="warning" plain shape="circle" @click="selectPayMent(item)"></u-button>
</template>
<!-- <template v-else-if="currentType === 1"> -->
<u-button text="查看预览" type="warning" plain shape="circle" @click="jumpPage(item)"></u-button>
<u-button @click="toViewLogistics(item)" v-if="currentType==2||currentType==3" text="物流详情" type="warning" plain shape="circle" ></u-button>
<!-- </template> -->
</view>
</view>
</template>
<view class="no-data" v-if="currentOrder.length <= 0">
暂无订单
</view>
<u-modal
showCancelButton
:show="show"
:title="title"
:content="content"
:cancelText="cancelText"
:confirmText="confirmText"
confirmColor="#E08745"
@cancel="show = false"
@confirm="cancelOrder"
>
</u-modal>
<u-popup :show="showPopup" closeOnClickOverlay @close="showPopup = false">
<view class="popup-content">
<PayPatter v-model="pay_payment"></PayPatter>
<view class="popup-footer">
<u-button class="v-default" shape="circle" @click="showPopup = false">取消</u-button>
<u-button class="v-primary" shape="circle" type="primary" @click="onRePayment(currentPayInfo)">确认</u-button>
</view>
</view>
</u-popup>
</scroll-view>
</view>
</view>
</template>
<script>
import { rePayment, cancelPayment, getOrderList } from '@/request/yyf.js';
import PayPatter from '@/components/Pay-patter/Pay-patter.vue';
export default {
components: {
PayPatter
},
data() {
return {
currentType: 0,
orderType: '0',
show: false, // 弹窗状态
title: "警告",
content: "确认取消订单吗?",
confirmText: "确认",
cancelText: "取消",
currentId: '',
orderList: {
'0': [],
'1': [],
'2': [],
'3': [],
'4': [],
},
params: {
'0': { page: 1 },
'1': { page: 1 },
'2': { page: 1 },
'3': { page: 1 },
'4': { page: 1 },
},
total: {
'0': { total: 0 },
'1': { total: 0 },
'2': { total: 0 },
'3': { total: 0 },
'4': { total: 0 },
},
showPopup: false,
pay_payment: '',
currentPayInfo: {},
refreshState: false
}
},
computed: {
tabList() {
return [
{ name: '待付款', type: '0', badge: { value: this.orderNum['0'] || 0 } },
{ name: '待寄出', type: '1', badge: { value: this.orderNum['1'] || 0 } },
{ name: '已寄出', type: '2', badge: { value: this.orderNum['2'] || 0 } },
{ name: '被退回', type: '3', badge: { value: this.orderNum['3'] || 0 } },
{ name: '已取消', type: '4', badge: { value: this.orderNum['4'] || 0 } },
]
},
currentOrder() {
return this.orderList[this.currentType]
},
orderNum() {
return this.$storeMine.orderNum;
},
},
watch: {
'$Route'(newVal) {
console.log(newVal);
}
},
methods: {
jumpPage(item) {
this.$Router.push({
path: '/pages/preview/preview',
query: {
...item
}
})
},
toViewLogistics(data){
uni.navigateTo({
url:'pages/waybill-info/waybill-info?id='+data.id,
})
// console.log(data);
},
leftClick() {
this.$Router.replace('/pages/mine/mine');
},
changeTab({ index, type }) {
if(type === this.currentType) {
return
}
this.currentType = index;
this.orderType = type;
if(this.orderList[this.currentType].length <= 0) {
this.queryData();
}
},
confirmCancel({ id }) {
this.currentId = id;
this.show = true;
},
async cancelOrder() {
const { data } = await cancelPayment({
id: this.currentId
});
if(data.code === 1) {
uni.$u.toast('订单已取消');
this.show = false;
this.refreshData();
this.$actionsMine.onGetOrderNum();
} else {
uni.$u.toast(data.msg);
}
},
selectPayMent(item) {
this.currentPayInfo = { ...item };
console.log(item);
this.showPopup = true;
},
// 重新支付
async onRePayment(item) {
let { message, affix, thumb, mail_type, coupon, send_type, pay_payment, send_address, take_address, id } = item;
// this.$store.letterInfo = {};
// this.$store.letterInfo.message = message;
// this.$store.letterInfo.mail_type = mail_type;
// this.$store.letterInfo.thumb = thumb;
// this.$store.letterInfo.affix = affix;
// this.$store.letterInfo.coupon = coupon;
// this.$store.letterInfo.send_type = send_type;
// this.$store.letterInfo.pay_payment = pay_payment;
// this.$store.letterInfo.send_address = send_address.reduce((total, item)=> total + ' ' + item);
// this.$store.letterInfo.take_address = take_address.reduce((total, item)=> total + ' ' + item);
// // console.log(this.$store.letterInfo);
// this.$Router.push({
// path: '/pages/confirmOrder/confirmOrder',
// query: {
// ...item
// }
// })
const { data } = await rePayment({
id,
pay_payment: this.pay_payment
})
if (data.code === 1) {
if(this.pay_payment === 1) {
uni.showToast({
title: data.msg,
});
this.refreshData();
} else {
// #ifdef H5
location.href = data.data.pay.url;
// #endif
// #ifdef MP-WEIXIN
uni.showToast({
title: "小程序支付暂未配置",
icon: "error",
});
// #endif
}
} else {
uni.showToast({
title: data.msg,
icon: 'error'
})
}
},
// 刷新
refreshData() {
this.orderList[this.currentType] = [];
this.params[this.currentType].page = 1;
this.queryData();
},
onScrollRefresh() {
this.refreshState = true;
this.refreshData()
},
async queryData() {
const { data } = await getOrderList({
...this.params[this.currentType],
status: this.currentType,
order: 'desc'
})
if(data.code === 1) {
this.total[this.currentType].total = data.data.total;
this.orderList[this.currentType].push(...data.data.data);
}
setTimeout(()=>{
this.refreshState = false;
}, 1000)
},
loadMoreData() {
if(this.total[this.currentType].total > this.orderList[this.currentType].length) {
this.params[this.currentType].page += 1;
this.queryData();
}
}
},
onLoad() {
let { type } = this.$Route.query;
this.currentType = parseInt(type);
this.orderType = type;
this.$actionsMine.onGetOrderNum();
this.queryData();
}
}
</script>
<style lang="scss" scoped>
/deep/.u-tabs__wrapper__nav__line {
bottom: 0;
}
/deep/.u-tabs__wrapper__nav__item {
box-sizing: border-box;
min-width: 20%;
}
/deep/.u-badge--error {
margin-left: 0 !important;
background-color: transparent;
color: #000;
font-size: 24rpx;
}
.order {
height: 100vh;
display: flex;
flex-direction: column;
.tabs-wrap {
}
.order-inner {
flex: 1;
overflow: auto;
background-color: rgba(255, 255, 255, .33);
padding: 35rpx 30rpx;
.order-item {
box-sizing: border-box;
padding: 42rpx 40rpx;
background-color: #fff;
border-radius: 40rpx;
margin-bottom: 40rpx;
.order-hd {
display: flex;
justify-content: space-between;
color: #333;
font-size: 26rpx;
font-family: OPPOSans-Medium, OPPOSans;
}
.order-address {
padding-top: 33rpx;
.name {
display: flex;
align-items: center;
font-size: 34rpx;
font-weight: bold;
&-icon {
padding: 0 28rpx;
image {
width: 190rpx;
height: 12rpx;
}
}
}
.address-text {
padding-top: 10rpx;
display: flex;
.address-text-inner {
width: 50%;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #ababab;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-right: 5%;
&:last-child {
flex: 1;
}
}
}
}
.order-opera {
margin-top: 46rpx;
display: flex;
justify-content: flex-end;
/deep/.u-button {
margin: 0 0 0 20rpx;
padding: 12rpx 22rpx;
height: auto;
background-color: transparent;
border-width: 2rpx;
width: auto;
}
/deep/.u-button--warning {
color: #f9ae3d;
}
}
}
}
.no-data {
padding: 100rpx 0;
text-align: center;
color: #ababab;
}
}
.popup-content {
padding: 40rpx;
.popup-footer {
padding-top: 40rpx;
display: flex;
.v-default {
margin-right: 20rpx;
}
.v-primary {
background-color: #E39B46;
border-color: #E39B46;;
}
}
}
</style>

536
pages/mine/openMember.vue Normal file
View File

@@ -0,0 +1,536 @@
<template>
<view class="open">
<u-navbar
title="会员中心"
placeholder
autoBack
bg-color="transparent"
></u-navbar>
<view class="open-header">
<MineHeader></MineHeader>
</view>
<view class="open-inner">
<view class="open-title">
开通会员即可享受包月或按次服务最高可省88.8
</view>
<view class="open-content">
<!-- tab -->
<u-tabs
:list="tabList"
lineColor="#E39B46"
lineHeight="12rpx"
:activeStyle="{
color: '#333333',
fontSize: '26rpx',
fontWeight: 'bold',
}"
@click="changeTab"
>
</u-tabs>
<view class="open-content-inner">
<!-- 付款信息 -->
<view class="open-content-inner-bd">
<!-- 月份 -->
<view class="open-month" v-if="currentType === 'date'">
<!-- <u-scroll-list :indicator="false" style="overflow-x: auto;"> -->
<view
class="v-item"
:class="selectMeal === item.id ? 'select' : ''"
v-for="(item, index) in list['date']"
:key="index"
@click="switchMeal(item.id)"
>
<image
class="bg-img"
v-show="selectMeal === item.id"
src="@/static/mine/m_open_select.png"
mode=""
></image>
<image
class="bg-img"
v-show="selectMeal !== item.id"
src="@/static/mine/m_open_not_select.png"
mode=""
></image>
<view class="v-item-inner">
<view class="v-item-title">
{{ item.title }}
</view>
<view class="v-item-dec">
{{ item.content }}
</view>
<view class="v-item-amount">
<view class="v-item-amount-label"> 金额 </view>
<view class="v-item-amount-value">
{{ item.balance }}
</view>
</view>
</view>
</view>
<!-- </u-scroll-list> -->
</view>
<!-- 次数 -->
<view class="open-month" v-else>
<view
class="v-item"
:class="selectMeal === item.id ? 'select' : ''"
v-for="(item, index) in list['count']"
:key="index"
@click="switchMeal(item.id)"
>
<image
class="bg-img"
v-show="selectMeal === item.id"
src="@/static/mine/m_open_select.png"
mode=""
></image>
<image
class="bg-img"
v-show="selectMeal !== item.id"
src="@/static/mine/m_open_not_select.png"
mode=""
></image>
<view class="v-item-inner">
<view class="v-item-title">
{{ item.title }}
</view>
<view class="v-item-dec">
{{ item.content }}
</view>
<view class="v-item-amount">
<view class="v-item-amount-label"> 金额 </view>
<view class="v-item-amount-value">
{{ item.balance }}
</view>
</view>
</view>
</view>
</view>
<view class="open-info">
<view class="open-info-title">
<text class="main"> 专属权益 </text>
<text class="in"> 开通会员后将享受超多专属权益 </text>
</view>
<view class="open-info-content">
<view
class="open-info-content-item"
v-for="(item, index) in infoList"
:key="index"
>
<image :src="item.img" mode=""></image>
<view>{{ item.label }}</view>
</view>
</view>
</view>
</view>
<!-- 底部支付 -->
<view class="open-content-inner-ft">
<view class="terms">
<u-checkbox-group v-model="checkboxValue">
<u-checkbox
shape="circle"
label="我已阅读并同意《会员使用协议》《隐私协议》"
inactiveColor="#E39B46"
labelColor="#111111"
activeColor="#E39B46"
>
</u-checkbox>
</u-checkbox-group>
</view>
<view class="opera">
<view class="amount">
<text class="amount-price">{{ currentAmount }}</text>
<!-- <text class="amount-text">开通立省</text>
<text class="save-text">88</text> -->
</view>
<u-button
:disabled="checkboxValue.length === 0 || !formData.id"
@click="showPopup = true"
>立即支付</u-button
>
</view>
</view>
</view>
</view>
</view>
<u-popup
:show="showPopup"
mode="bottom"
closeOnClickOverlay
@close="showPopup = false"
style="position: absolute"
>
<view class="popup-content">
<PayType v-model="formData.platform"></PayType>
<u-cell-group style="margin-top: 60rpx">
<u-cell
title="我的优惠券"
isLink
@click="
$Router.push('/pages/coupon/coupon?amount=' + currentAmount)
"
>
<template #value>
<view style="width: 300rpx; text-align: right">
{{ couponInfo ? couponInfo.title : "" }}
</view>
</template>
</u-cell>
</u-cell-group>
<view class="popup-footer">
<u-button class="v-default" shape="circle" @click="showPopup = false"
>取消</u-button
>
<u-button
class="v-primary"
shape="circle"
type="primary"
@click="onPayment"
>确认</u-button
>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import MineHeader from "./components/MineHeader.vue";
import PayType from "@/components/PayType/PayType.vue";
import { getPayList, onPayment, checkPayStatus } from "@/request/yyf.js";
export default {
components: {
MineHeader,
PayType,
},
data() {
return {
tabList: [
{ name: "包月套餐", type: "date" },
{ name: "按次套餐", type: "count" },
],
currentType: "date",
checkboxValue: [],
selectMeal: 0,
list: {
date: [],
count: [],
},
infoList: [
{ label: "免费寄信", img: require("../../static/mine/m_member_1.png") },
{ label: "人工代写", img: require("../../static/mine/m_member_2.png") },
{ label: "专属客服", img: require("../../static/mine/m_member_3.png") },
{
label: "尊贵身份标识",
img: require("../../static/mine/m_member_4.png"),
},
],
formData: {
platform: "",
coupon: "",
id: "",
},
couponInfo: null,
showPopup: false,
};
},
computed: {
currentAmount() {
let { id } = this.formData;
if (id) {
let obj = this.list[this.currentType].find((item) => item.id === id);
return obj.balance.toFixed(2);
}
},
},
onLoad() {
this.onGetPay();
uni.$on("selectCoupon", (data) => {
console.log("selectCoupon", data);
this.couponInfo = data;
this.formData.coupon = data.id;
});
},
methods: {
changeTab({ type }) {
this.currentType = type;
if (this.list[type][0]) {
let id = this.list[type][0].id;
this.formData.id = id;
this.selectMeal = id;
}
},
switchMeal(id) {
console.log(id);
this.selectMeal = id;
this.formData.id = id;
},
async onGetPay() {
const { data } = await getPayList({});
// console.log(data);
if (data.code === 1) {
data.data.forEach((item) => {
this.list[item.key] = item.list;
});
this.formData.id = this.list["date"][0].id;
this.selectMeal = this.list["date"][0].id;
// console.log(this.formData.id);
}
},
async onPayment() {
let { platform } = this.formData;
const { data } = await onPayment({
...this.formData,
coupon: this.formData.coupon || undefined,
});
// console.log(data);
this.showPopup = false;
if (data.code === 1) {
if (platform === 1) {
uni.showToast({
title: "支付成功",
});
this.$actionsMine.onGetuserInfo();
setTimeout(() => {
uni.navigateTo({
url: "/pages/mine/mine",
});
}, 1000);
} else {
// #ifdef H5
location.href = data.data.url;
// #endif
// #ifdef MP-WEIXIN
uni.showToast({
title: "小程序支付暂未配置",
icon: "error",
});
// #endif
}
} else {
uni.showToast({
title: data.msg,
icon: "error",
});
}
},
async onCheckPayStatus() {
// const { data } = await checkPayStatus({
// order_id: ''
// });
},
},
};
</script>
<style lang="scss" scoped>
/deep/.u-tabs__wrapper__nav__line {
bottom: 0;
}
.open {
height: 100vh;
display: flex;
flex-direction: column;
.open-header {
padding: 0 20rpx;
}
.open-inner {
flex: 1;
border-radius: 40rpx 40rpx 0 0;
background-color: #ffdbac;
.open-title {
padding: 15rpx 0;
border-radius: 40rpx 40rpx 0 0;
text-align: center;
font-size: 28rpx;
line-height: 1;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #de640a;
}
.open-content {
box-sizing: border-box;
padding-top: 20rpx;
height: calc(100% - 58rpx);
background-color: #fff;
border-radius: 40rpx 40rpx 0 0;
.open-content-inner {
margin-top: 40rpx;
height: calc(100% - 140rpx);
padding: 0 20rpx;
display: flex;
flex-direction: column;
&-bd {
flex: 1;
overflow-y: auto;
.open-month {
overflow-x: auto;
white-space: nowrap;
.v-item {
display: inline-block;
box-sizing: border-box;
width: 250rpx;
height: 330rpx;
// background: url(../../static/mine/m_open_not_select.png) center/100% no-repeat;
margin-right: 20rpx;
position: relative;
.v-item-inner {
position: relative;
z-index: 1;
padding-top: 65rpx;
padding-left: 30rpx;
}
.bg-img {
position: absolute;
left: 0;
right: 0;
width: 100%;
height: 100%;
z-index: 0;
}
&.select {
width: 330rpx;
}
.v-item-title {
font-size: 36rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #011111;
}
.v-item-dec {
padding-top: 10rpx;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
color: #ababab;
}
.v-item-amount {
&-label {
padding: 27rpx 0 11rpx;
font-size: 18rpx;
color: #666;
}
&-value {
color: #ce7a2c;
font-size: 47rpx;
font-weight: bold;
}
}
}
}
.open-info {
.open-info-title {
padding: 55rpx 0 45rpx;
.main {
font-size: 30rpx;
font-family: OPPOSans-bold, OPPOSans;
font-weight: bold;
color: #111111;
}
.in {
padding-left: 15rpx;
font-size: 23rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #ababab;
}
}
.open-info-content {
display: flex;
&-item {
padding: 0 10rpx;
width: 25%;
text-align: center;
image {
width: 124rpx;
height: 124rpx;
}
view {
padding-top: 20rpx;
font-size: 26rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #111111;
}
}
}
}
}
&-ft {
.opera {
margin-top: 48rpx;
display: flex;
.amount {
box-sizing: border-box;
padding: 0 36rpx;
width: 459rpx;
height: 98rpx;
line-height: 98rpx;
background: #ffe4d9;
border-radius: 20px 20px 20px 20px;
color: #ce7a2c;
.amount-price {
font-size: 42rpx;
}
.amount-text {
padding: 0 10rpx;
color: #111;
}
}
/deep/.u-button {
width: 214rpx;
height: 98rpx;
background: linear-gradient(178deg, #e8b648 0%, #e08745 100%);
border-radius: 20rpx 20rpx 20rpx 20rpx;
color: #fff;
font-size: 30rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
}
}
}
}
}
}
}
.popup-content {
padding: 40rpx;
.popup-footer {
padding-top: 40rpx;
display: flex;
.v-default {
margin-right: 20rpx;
}
.v-primary {
background-color: #e39b46;
border-color: #e39b46;
}
}
}
</style>

23
pages/payPage/payPage.vue Normal file
View File

@@ -0,0 +1,23 @@
<template>
<view>
{{payurl}}
<web-view :src="payurl"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
payurl:''
};
},
onLoad(option) {
this.payurl = option.url
}
}
</script>
<style lang="scss">
</style>

85
pages/preview/preview.vue Normal file
View File

@@ -0,0 +1,85 @@
<template>
<view class="preview">
<u-navbar title="书信预览" autoBack bg-color="transparent" placeholder></u-navbar>
<view class="preview-content">
<view class="preview-content-inner" style="background: url(../../static/mine/preview_bg.png) center/100% 100% no-repeat;">
<view style="white-space: pre-wrap; line-height: 40rpx;">
{{ detailsInfo.message }}
</view>
<view class="preview-image" v-if="loading && detailsInfo.thumb.length > 0">
<image v-for="(item, index) in detailsInfo.thumb" :key="index" :src="item" style="width: 100%; min-height: 100rpx;"></image>
</view>
<view class="preview-ft" v-if="loading">
<view class="name">
{{ detailsInfo.send_address[0] }}
</view>
<view class="time">
{{ detailsInfo.create_time }}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { getOrderDetails } from '@/request/yyf.js';
export default {
data() {
return {
content: {},
detailsInfo: {},
loading: false
}
},
onLoad() {
this.content = this.$Route.query;
console.log(this.content);
this.onGetDetails();
},
methods: {
async onGetDetails() {
const { data } = await getOrderDetails({
id: this.content.id
})
console.log(data);
if(data.code === 1) {
this.detailsInfo = data.data;
this.loading = true;
}
}
}
}
</script>
<style lang="scss" scoped>
.preview {
box-sizing: border-box;
height: 100vh;
padding: 30rpx 0 0 0;
display: flex;
flex-direction: column;
.preview-content {
flex: 1;
overflow: auto;
.preview-content-inner {
box-sizing: border-box;
padding: 240rpx 80rpx 140rpx;
overflow-y: auto;
font-family: caisemenghuanjingyu;
}
.preview-ft {
// padding-top: 40rpx;
view {
display: flex;
justify-content: flex-end;
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,270 @@
<template>
<view class="queryAddr">
<u-navbar title="地址查询" autoBack bg-color="#fff0e7" placeholder></u-navbar>
<view class="queryAddr-list">
<scroll-view :scroll-y="true" style="height: 100%;">
<view class="v-card">
<view class="v-address-title">
<view class="label">
选择地区
</view>
<view class="v-select" @click="showPicker">
<text>{{columns[0][value[0]]}}</text> <u-icon name="arrow-down-fill"></u-icon>
</view>
<view class="v-select" @click="showPicker">
<text>{{columns[1][value[1]]}}</text> <u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
<view class="v-address-title">
<view class="label">
选择类型
</view>
<view class="v-select">
<text>看守所</text> <u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
</view>
<view class="address-details">
<u-row gutter="20rpx" style="width: 100%;">
<u-col :span="6" v-for="item in jailList" :key="item.id">
<view class="address-details-item" @click="viewDetails(item)">
<view class="add" @click.stop="selectAddr(item)">
<svg width="28" height="28" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 16V32" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 24L32 24" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
</view>
<view class="address-title">
<text>{{item.title}}</text>
</view>
<view class="address-text" style="padding-top: 20rpx;">
<text>{{item.address}}</text>
<view class="" @click.stop>
<Copy :text="getAddress(item)" successText="地址已复制" @click.stop></Copy>
</view>
</view>
<view class="phone" style="height: 40rpx; padding-top: 20rpx;">
<text>{{item.phone[0]}}</text>
<view class="" @click.stop>
<Copy :text="item.phone[0]" ></Copy>
</view>
</view>
</view>
</u-col>
</u-row>
</view>
</scroll-view>
</view>
<u-picker :show="show" ref="uPicker" @change="changeHandler" :columns="columns" @confirm="confirm"
@cancel="cancel"></u-picker>
</view>
</template>
<script>
import {
getJailListApi
} from '@/request/yyf.js'
import AllAddress from './addresData.js'
import Copy from '@/components/Copy/Copy.vue';
export default {
components: {
Copy
},
data() {
return {
checkboxValue: [],
state: '',
value: [0, 0],
city: '',
type: '',
jailList: [],
show: false,
columns: [
['中国', '美国'],
['深圳', '厦门', '上海', '拉萨']
],
}
},
onLoad() {
let data = [AllAddress.map(item => item.name)]
data[1] = ['所有']
data[1].push(...AllAddress[0].city.map(item => item.name))
this.columns = data
this.getJailList()
console.log(data);
},
methods: {
addAddress() {
this.$Router.push('/pages/addAddr/addAddr');
},
async changeHandler(e) {
if (e.columnIndex) {
} else {
this.columns.splice(1, 1, AllAddress[e.index].city.map(item => item.name))
}
this.value.splice(e.columnIndex, 1, e.index)
this.getJailList()
},
editAddress() {
},
async getJailList() {
let queryData
if (this.value[1]) {
queryData = {
province: this.columns[1][this.value[1]]
}
} else {
queryData = {
province: this.columns[0][this.value[0]]
}
}
let {
data
} = await getJailListApi(queryData)
this.jailList = data.data.data
console.log(data.data.data);
},
showPicker() {
this.show = true;
},
confirm(e) {
this.show = false;
},
cancel() {
this.show = false;
},
getAddress({ address }) {
let res = '';
let addr1 = this.columns[0][this.value[0]];
let addr2 = this.columns[1][this.value[1]];
if(addr2 != '所有') {
res = addr1 + addr2 + address;
} else {
res = addr1 + address;
}
return res;
},
viewDetails({ id }) {
this.$Router.push({
path: '/pages/addrDetails/addrDetails',
query: {
id
}
})
},
selectAddr({ address }) {
console.log(address);
let res = '';
let addr1 = this.columns[0][this.value[0]];
let addr2 = this.columns[1][this.value[1]];
if(addr2 != '所有') {
res = addr1 + addr2 + address;
} else {
res = addr1 + address;
}
uni.$emit('addAddress', res);
this.$Router.back();
}
}
}
</script>
<style lang="scss" scoped>
.queryAddr {
box-sizing: border-box;
height: 100vh;
display: flex;
flex-direction: column;
padding: 30rpx 30rpx 40rpx;
.queryAddr-list {
flex: 1;
overflow: hidden;
.v-card {
padding: 20rpx 40rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 40rpx 40rpx;
.v-address-title {
padding: 10rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
.v-select {
margin-left: 10rpx;
width: 234rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 14rpx 0;
background: #FFEFE7;
border-radius: 20rpx 20rpx 20rpx 20rpx;
text {
padding-right: 40rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #333333;
}
}
}
}
.address-details {
.address-details-item {
position: relative;
margin-top: 20rpx;
box-sizing: border-box;
// width: 335rpx;
padding: 31rpx 40rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 40rpx 40rpx;
.address-title {
padding-bottom: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.address-text {
display: flex;
justify-content: space-between;
padding: 13rpx 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 24rpx;
font-family: OPPOSans-Medium, OPPOSans;
font-weight: 500;
color: #ababab;
line-height: 28rpx;
}
.phone {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.add {
position: absolute;
right: 20rpx;
top: 20rpx;
}
}
}
}
}
</style>

355
pages/register/register.vue Normal file
View File

@@ -0,0 +1,355 @@
<template>
<view class="page">
<!-- <u-navbar :autoBack="true" bgColor="#fff0e7" title="登录"></u-navbar> -->
<view class="top-background-raduis">智能寄信</view>
<view class="login-box">
<view class="login-card-title">
<view class="login-card-title-content">
手机号注册
</view>
</view>
<view class="login-card-input login-card-input-account"
v-if="loginPattern==='forgotPassword'||loginPattern==='captchaLogin'">
<!-- 输入框头部图标 -->
<u--input class="hj-input" v-model="captchaInfo.mobile" focus maxlength="30" :trim="true"
@focus="UserNamePassWrodFocusBorderStyle" :styles="inputColorConfigToUserName"
@blur="UserNamePassWrodBlurBorderStyle" placeholder="请输入手机号"></u--input>
<view class="hj-input" style="display: flex;justify-content: center;"
v-if="$isPhoneNumber(captchaInfo.mobile)">
<u-code-input :disabledKeyboard="!$isPhoneNumber(captchaInfo.mobile)" :maxlength="4"
v-model="captchaInfo.captcha"></u-code-input>
<view style="margin-left: 10rpx;">
<u-toast ref="uToast"></u-toast>
<u-code :seconds="seconds" @end="end" @start="start" ref="uCode" @change="codeChange"></u-code>
<u-button @tap="getCode">{{captchaButtonText}}</u-button>
</view>
</view>
</view>
<view class="login-card-loginIn" @click="submitLoginData"
v-if="$isPhoneNumber(captchaInfo.mobile)&&captchaInfo.captcha.length===4">
<view class="login-card-loginIn-btn">
注册
</view>
</view>
<view class="login-bottom-info">
<view class="info-item" @click="toLogin" >
返回登陆
</view>
</view>
</view>
<view class="bottom-message">
登录/注册 代表你已同意用户使用协议
</view>
<view class="top-background-raduis-bootom"></view>
</view>
</template>
<script>
import {
userLogin,
phonenumberLogin,
sendVerifyCode,
retrievePassword
} from '@/request/api.js'
export default {
data() {
return {
// 输入框边框颜色默认值
colorDefault: '#b4b4b4',
// 输入框边框聚焦值
colorFocusColor: '#3cb79a',
// 输入框颜色配置
inputColorConfigToUserName: {
color: "#000000",
disableColor: "#eee",
borderColor: "#b4b4b4",
},
// 输入框颜色配置
inputColorConfigToPassWord: {
color: "#000000",
disableColor: "#eee",
borderColor: "#b4b4b4",
},
value: "",
userInfo: {
account: '',
password: ''
},
captchaInfo: {
mobile: '',
captcha: '',
},
forgotPasswordInfo: {
mobile: '',
captcha: '',
newpassword: ''
},
// registerInfo: {
// }
showCaptchInput: false,
seconds: 60,
captchaButtonText: '获取验证码',
loginPattern: 'captchaLogin', //userLogin captchaLogin forgotPassword
};
},
onLoad() {},
//监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object用于页面传参触发时机早于 onLoad
onInit() {},
//监听页面加载,其参数为上个页面传递的数据,参数类型为 Object用于页面传参
//监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发
async onReady() {
// #ifdef H5
if (await this.$isWechat()) {
console.log('当前登录环境微信H5');
if (this.$getUrlParams('code')) {
this.$wechatloginAfter(this.$getUrlParams('code'))
return
} else if (uni.getStorageSync('token')) {
uni.navigateTo({
url: '/'
})
return
} else {
this.$login()
}
} else {
console.log('当前登录环境普通H5');
}
// #endif
//
// #ifdef MP-WEIXIN
console.log('当前登录环境:微信')
this.$login()
// #endif
},
//监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
beforeDestroy() {},
//页面滚动到底部的事件不是scroll-view滚到底常用于下拉下一页数据。
onReachBottom() {},
onShareAppMessage() {},
created() {},
methods: {
toLogin(){
uni.navigateTo({
url:'/pages/login/login'
})
},
async getCode() {
try {
if (this.$refs.uCode.canGetCode) {
uni.showLoading({
title: '正在获取验证码'
})
let {
data
} = await sendVerifyCode({
mobile: this.captchaInfo.mobile,
event:'register'
})
this.$refs.uCode.start();
} else {
uni.$u.toast('倒计时结束后再发送');
}
} catch (e) {
console.log(e);
}
},
toRegister() {
uni.navigateTo({
url: 'pages/register/register'
})
},
async submitLoginData() {
// loginPattern: 'userLogin', // captchaLogin forgotPassword
try {
let {
data
} = await phonenumberLogin(this.captchaInfo)
if (!data.code) throw (data.msg)
res = data.data
uni.setStorageSync('userInfo', res.userinfo)
uni.setStorageSync('token', res.userinfo.token)
uni.redirectTo({
url: '/pages/index/index'
})
} catch (e) {
uni.$u.toast(e);
console.log(e);
}
// console.log(data);
},
codeChange(text) {
this.captchaButtonText = text
},
end() {
// uni.$u.toast('倒计时结束');
},
start() {
uni.$u.toast('验证码发送成功');
},
// 输入框聚焦变换边框样式
UserNamePassWrodFocusBorderStyle() {
this.inputColorConfigToUserName.borderColor = this.colorFocusColor;
},
PassWordFocusBorderStyle() {
this.inputColorConfigToPassWord.borderColor = this.colorFocusColor;
},
// 输入框失去焦点变换边框样式
UserNamePassWrodBlurBorderStyle() {
this.inputColorConfigToUserName.borderColor = this.colorDefault;
},
PassWordBlurBorderStyle() {
this.inputColorConfigToPassWord.borderColor = this.colorDefault;
},
},
};
</script>
<style lang="scss" scoped>
* {
box-sizing: border-box;
}
uni-page-body {
padding: 0 0 0 0 !important;
}
.page {
position: relative;
height: 100vh;
}
.top-background-raduis {
height: 30%;
background-color: #3cb79a;
padding-top: 100rpx;
display: flex;
align-items: flex-start;
color: white;
font-weight: bold;
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
font-size: 50rpx;
// background-image: url(/static/01banner.png);
background-size: 100% cover;
justify-content: center;
// background-color: #ffd0b1;
// border-bottom-left-radius: 50%;
// border-bottom-right-radius: 50%;
border-radius: 0 0 0 100%;
}
.top-background-raduis-bootom {
height: 500rpx;
border-radius: 0 100% 0 0;
width: 100%;
// border-top-left-radius: 50%;
// border-top-right-radius: 50%;
background-color: #3cb79a;
position: fixed;
bottom: 0;
}
/deep/ .is-input-border {
border-radius: 7px !important;
}
/deep/ .uni-easyinput__content {
min-height: 39px !important;
}
.hj-input {
margin-bottom: 20rpx;
margin-top: 15rpx;
}
.hj-input:nth-child(2) {
margin-top: 35rpx;
}
.login-box {
top: 20%;
position: absolute;
width: 80%;
left: 10%;
right: 10%;
max-height: 650rpx;
padding: 30rpx;
background-color: white;
border-radius: 40rpx;
box-shadow: 9px 9px 6px #e3e3e3;
z-index: 1;
.login-card-input {
// background-color: violet;
// height: 50%;
padding: 5rpx;
}
.login-card-title {
height: 20%;
// background-color: black;
padding: 10rpx;
display: flex;
justify-content: center;
.login-card-title-content {
font-size: 1.2em;
color: #3cb79a;
border-bottom: 3px solid #3cb79a;
}
}
.login-card-loginIn {
height: 110rpx;
display: flex;
justify-content: center;
padding: 10rpx;
align-items: center;
.login-card-loginIn-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #3cb79a;
width: 100%;
font-size: 1.2em;
height: 70rpx;
border-radius: 40rpx;
color: white;
}
}
.login-bottom-info {
height: 50rpx;
display: flex;
font-size: 20rpx;
color: #3cb79a;
justify-content: center;
align-items: center;
}
.info-item {
margin-left: 30rpx;
}
}
.bottom-message {
position: absolute;
height: 70rpx;
display: flex;
z-index: 99;
width: 100%;
justify-content: center;
align-items: center;
font-size: 20rpx;
overflow: hidden;
color: white;
bottom: 80rpx;
}
</style>

View File

@@ -0,0 +1,42 @@
<template>
<view class="uni-page">
<u-navbar :auto-back="true" placeholder bgColor="#fff0e7" title="回信查询"></u-navbar>
<view class="content-main">
<Waybill :WaybillInfo="{}" @click="toViewInfo"></Waybill>
</view>
</view>
</template>
<script>
import Waybill from '@/components/waybill/waybill.vue'
export default {
components: {
Waybill
},
data() {
return {
};
},
methods: {
toViewInfo(waybill) {
uni.navigateTo({
url:'pages/waybill-info/waybill-info'
})
}
}
}
</script>
<style lang="scss">
.uni-page {
display: flex;
flex-direction: column;
.content-main {
flex: 1;
overflow: auto;
// height: 100%;
}
}
</style>

52
pages/setting/setting.vue Normal file
View File

@@ -0,0 +1,52 @@
<template>
<view class="uni-page">
<u-navbar title="设置" autoBack placeholder bg-color="#fff0e7"></u-navbar>
<u-button class="v-btn" type="warning" plain shape="circle" @click="logout">退出登录</u-button>
<u-modal
showCancelButton
:show="show"
:title="title"
:content="content"
:cancelText="cancelText"
:confirmText="confirmText"
confirmColor="#E08745"
@cancel="show = false"
@confirm="confirmLogout"
>
</u-modal>
</view>
</template>
<script>
import { onLogout } from '@/request/yyf.js';
export default {
data() {
return {
show: false, // 弹窗状态
title: "警告",
content: "确认退出登录吗?",
confirmText: "确认",
cancelText: "取消",
}
},
methods: {
logout() {
this.show = true;
},
async confirmLogout() {
await onLogout();
uni.clearStorageSync();
this.$Router.replace('/pages/index/index');
}
}
}
</script>
<style lang="scss" scoped>
.v-btn {
margin-top: 200rpx;
background-color: transparent;
color: #000 !important;
}
</style>

View File

@@ -0,0 +1,63 @@
<template>
<view class="uni-page">
<u-navbar :auto-back="true" placeholder bgColor="#fff0e7" title="运单详情"></u-navbar>
<view class="content-main">
<Waybill :WaybillInfo="waybill"></Waybill>
<WaybillInfo :WaybillInfo="waybill"></WaybillInfo>
</view>
</view>
</template>
<script>
import Waybill from '@/components/waybill/waybill.vue'
import WaybillInfo from '@/components/waybill-info/waybill-info.vue'
import {
getOrderInfo
} from '@/request/wm.js'
export default {
components: {
Waybill,
WaybillInfo
},
data() {
return {
waybill: null
};
},
async onLoad(option) {
let {
data
} = await getOrderInfo({
id: +option.id
})
this.waybill = data.data
console.log(this.waybill);
},
onShow(option) {
console.log(option);
},
methods: {
toViewInfo(waybill) {
uni.navigateTo({
url: ''
})
}
}
}
</script>
<style lang="scss">
.uni-page {
display: flex;
flex-direction: column;
.content-main {
flex: 1;
display: flex;
flex-direction: column;
overflow: auto;
padding-bottom: 20rpx;
// height: 100%;
}
}
</style>

85
request/api.js Normal file
View File

@@ -0,0 +1,85 @@
// 存放接口处
import http from './request.js';
/**
* 账号密码登录
* @param{account:string ,password: string} params
*/
export const userLogin = (data) => http.request({
method: "POST",
url: '/user/login',
data
});
/**
* 微信code登录
* @param{platform:string ,code: 微信code} data
*/
export const thirdLogin = (data) => http.request({
method: "POST",
url: '/user/third',
data
})
/**
* 手机验证码登录
* @param{mobile:string ,captcha: 验证码} data
*/
export const phonenumberLogin = (data) => http.request({
method: "POST",
url: '/user/mobilelogin',
data
})
/**
* 重置密码
* @param{mobile:string ,captcha: 验证码,newpassword:string} data
*/
export const retrievePassword = (data) => http.request({
method: "POST",
url: '/user/resetpwd',
data
})
/**
* 发送验证码
* @param{mobile:手机号码 ,event: [register:'注册',login:'登录',bind:'绑定手机号',修改:'savepwd']} data
*/
export const sendVerifyCode = (data) => http.request({
method: "POST",
url: '/sms/send',
data
})
// /**
// * 上传文件
// * @param{file} file
// */
// export const uploadFile = (files) => {
// uni.uploadFile({
// url: 'https://jx.xiaolinghou.com/api/common/upload', //仅为示例,非真实的接口地址
// header: {
// token: uni.getStorageSync('token'),
// },
// files,
// name: 'file',
// success: (res) => {
// console.log(res);
// },
// fail: (err) => {
// console.log(err);
// }
// });
// }
/**
* 上传
*/
export const uploadFile = (filePath) => http.upload('/common/upload', {
filePath,
name: 'file'
})

1
request/baseUrl.js Normal file
View File

@@ -0,0 +1 @@
export const baseUrl = 'https://jx.xiaolinghou.com/api';

52
request/request.js Normal file
View File

@@ -0,0 +1,52 @@
import Request from 'luch-request' // https://www.quanzhan.co/luch-request/guide/3.x/#npm
import {
baseUrl
} from './baseUrl.js';
const http = new Request();
http.setConfig((config) => {
console.log(12313123123);
/* config 为默认全局配置*/
config.baseURL = baseUrl; /* 根域名 */
config.timeout = 100000;
// config.header['Access-Control-Allow-Origin'] = "*"
// config.header['Origin']='*'
return config
})
// 在请求之前拦截
http.interceptors.request.use((config) => {
console.log(config);
config.header = {
token:uni.getStorageSync('token'),
...config.header,
}
return config
}, config => { // 可使用async await 做异步操作
console.log(config);
return Promise.reject(config)
})
// 在请求之后拦截
http.interceptors.response.use((response) => {
/* 对响应成功做点什么 可使用async await 做异步操作*/
return response
}, (response) => {
console.log(response,'1111111111');
if(response.data?.code===401){
uni.navigateTo({
url:'pages/login/login'
})
}
uni.showToast({
title:'请求错误',
icon:'error'
})
// uni.showToast({title:response.data?.message||response.errMsg})
/* 对响应错误做点什么*/
// console.log(response)
return Promise.reject(response)
})
export default http;

200
request/wm.js Normal file
View File

@@ -0,0 +1,200 @@
// 存放接口处
import http from './request.js';
// #ifdef MP-WEIXIN
import {
TextDecoder
} from '@/utils/text-encoding-0.6.3/index.js'
// #endif
// 获取聊天记录
export const getMessageList = (data) => http.request({
method: "GET",
url: '/chat/history'
});
/**
* 微信code登录
* @param{platform:string ,code: 微信code} data
*/
export const thirdLogin = (data) => http.request({
method: "POST",
url: '/user/third',
data
})
// 发送消息
// export const sendMessageApi = (data) => http.request({
// method: "POST",
// url: '/chat/random',
// data
// })
// 发送消息
// export const sendMessageApi = (data) => {
// const requestTask = uni.request({
// url: "https://jx.xiaolinghou.com/api/chat/random",
// timeout: 150000,
// responseType: "text",
// method: "POST",
// header: {
// token: 'ccef1fb8-c85c-4144-9e69-00a4f279f9ab'
// },
// enableChunked: true, //配置这里
// data,
// success: response => {
// console.log(response)
// },
// fail: error => {}
// })
// requestTask.onChunkReceived(function(res) {
// const uint8Array = new Uint8Array(res.data);
// // 尝试使用多个字符编码进行解码
// const encodings = ['utf-8', 'gbk', 'big5']; // 按照你的需求添加更多的编码方式
// let text = '';
// for (const encoding of encodings) {
// try {
// const textDecoder = new TextDecoder(encoding);
// text = textDecoder.decode(uint8Array);
// break;
// } catch (error) {
// console.log(`Decoding failed with ${encoding}: ${error}`);
// }
// }
// console.log(text);
// })
// }
// 发送消息
export const sendMessageApi = async (data, that) => {
let token = uni.getStorageSync('token')
if (!token) {
uni.navigateTo({
url: '/pages/login/login'
})
return
}
// #ifdef H5
const response = await fetch('https://jx.xiaolinghou.com/api/chat/random', {
method: "POST",
headers: {
"Content-Type": "application/json",
token,
},
body: JSON.stringify(data)
}, );
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let read = () => {
return reader.read().then(({
done,
value
}) => {
if (done) {
that.isSnedMsg = false
return;
}
// 将已下载部分的内容展示出来
let text = decoder.decode(value, {
stream: true
});
const match = text.match(/"(.*?)"/);
if (match) {
text = match[1];
}
console.log(text);
that.messageList[that.messageList.length - 1].message += text
// 继续读取下一部分
return read();
});
}
read()
// #endif
// #ifdef MP-WEIXIN
const requestTask = uni.request({
url: "https://jx.xiaolinghou.com/api/chat/random",
timeout: 150000,
responseType: "text",
method: "POST",
header: {
token
},
enableChunked: true, //配置这里
data,
success: response => {
console.log(response)
},
fail: error => {}
})
const decoder = new TextDecoder("utf8");
requestTask.onChunkReceived(function(response) {
const uint8Array = new Uint8Array(response.data);
let text = String.fromCharCode.apply(null, uint8Array);
text = decodeURIComponent(escape(text));
const match = text.match(/"(.*?)"/);
if (match) {
text = match[1]
}
console.log(text);
that.messageList[that.messageList.length - 1].message += text
})
// #endif
}
// 获取问题列表
export const getQuestionApi = () => http.request({
method: "GET",
url: '/index/article'
})
// 获取价格区间
export const getPhotoPriceApi = () => http.request({
method: "GET",
url: '/index/photo'
})
// 支付
export const toPay = (data) => http.request({
method: "POST",
url: '/order/pay',
data
})
// 快递方式列表
export const getPostList = () => http.request({
method: "GET",
url: '/order/express'
})
// 代收信件信息
export const getAgentBusinessInfoApi = () => http.request({
method: "GET",
url: '/user/write_back'
})
// 保存代收信息
export const setAgentBusinessInfoApi = (data) => http.request({
method: "POST",
url: '/user/set_back',
data
})
// 查询订单详情
export const getOrderInfo = (params) => http.request({
method: "GET",
url: '/order/info',
params
})

121
request/yyf.js Normal file
View File

@@ -0,0 +1,121 @@
// 存放接口处
import http from './request.js';
// 获取用户信息
export const getUserInfo = () => http.request({
method: "GET",
url: '/user/get_info',
});
// 删除地址
export const delAddress = (data) => http.request({
method: "POST",
url: '/user/address_del',
data
});
// 修改地址
export const editAddress = (data) => http.request({
method: "POST",
url: '/user/address_edit',
data
});
// 添加地址
export const addAddress = (data) => http.request({
method: "POST",
url: '/user/address_add',
data
});
// 收货地址列表
export const getAddressList = (data) => http.request({
method: "GET",
url: '/user/address_list',
data
});
// 下单记录
export const getOrderList = (data) => http.request({
method: "GET",
url: '/order/list',
data
})
// 订单详情
export const getOrderDetails = (data) => http.request({
method: "GET",
url: '/order/info',
data
})
// 订单数量
export const getOrderNum = (data) => http.request({
method: "GET",
url: '/order/count',
data
})
// 查询优惠券
export const getCouponList = (data) => http.request({
method: "GET",
url: '/coupon/list',
data
})
// 重新支付
export const cancelPayment = (data) => http.request({
method: "GET",
url: '/order/close',
data
})
// 重新支付
export const rePayment = (data) => http.request({
method: "GET",
url: '/order/pays',
data
})
// 看守所列表
export const getJailListApi = (params) => http.request({
method: "GET",
url: '/index/city',
params,
})
// 看守所详情
export const getAddrDetails = (params) => http.request({
method: "GET",
url: '/index/city_info',
params,
})
// 看守所详情
export const onLogout = (params) => http.request({
method: "POST",
url: '/user/logout',
params,
})
// 充值列表
export const getPayList = (params) => http.request({
method: "POST",
url: '/pay/list',
params,
})
// 检查是否支付成功
export const checkPayStatus = (params) => http.request({
method: "GET",
url: '/pay/check',
params,
})
// 下单
export const onPayment = (params) => http.request({
method: "POST",
url: '/pay/pay',
params,
})

41
router/index.js Normal file
View File

@@ -0,0 +1,41 @@
// router.js
// https://www.hhyang.cn/v2/start/cross/codeRoute.html
import {
RouterMount,
createRouter
} from 'uni-simple-router';
const router = createRouter({
platform: process.env.VUE_APP_PLATFORM,
routes: [...ROUTES]
});
let baseRoute = ['/pages/index/index', '/pages/login/login','/pages/register/register']
//全局路由前置守卫
router.beforeEach((to, from, next) => {
console.log(to.path);
if (baseRoute.includes(to.path)) {
next()
return
}
uni.getStorage({
key: 'token',
success: (res) => {
next();
},
fail: (res) => {
next('/pages/login/login');
}
});
});
// 全局路由后置守卫
router.afterEach((to, from) => {
console.log('跳转结束')
})
export {
router,
RouterMount
}

BIN
static/01-1写信.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
static/01-1写信@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
static/01-1写信@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
static/01-2寄信.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/01-2寄信@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
static/01-2寄信@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
static/01-3代收.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
static/01-3代收@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
static/01-3代收@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/01-4回信.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
static/01-4回信@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/01-4回信@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
static/01AI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
static/01AI@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
static/01AI@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
static/01banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
static/01banner@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
static/01banner@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
static/01tab首页1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
static/01tab首页1@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
static/01tab首页1@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
static/01填写.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
static/01填写@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
static/01填写@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
static/01跳转.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

BIN
static/01跳转@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

BIN
static/01跳转@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

BIN
static/01首页.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

BIN
static/03tab客服.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

BIN
static/03tab客服@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
static/03tab客服@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/03头像.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
static/03头像@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
static/03客服1@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
static/04tab我的.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

BIN
static/04tab我的@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
static/04tab我的@3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/04我的4@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
static/10箭头@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
static/11快递@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/12活动@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
static/24bac@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
static/25发送.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
static/25发送@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M20 5.91406H28V13.9141H43V21.9141H5V13.9141H20V5.91406Z" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 40H40V22H8V40Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M16 39.8976V33.9141" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M24 39.8977V33.8977" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M32 39.8976V33.9141" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 40H36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>

After

Width:  |  Height:  |  Size: 846 B

BIN
static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Some files were not shown because too many files have changed in this diff Show More