Quellcode durchsuchen

修改合同地址跳转页面代码

master
风继续吹 vor 1 Jahr
Ursprung
Commit
ed1c913794
3 geänderte Dateien mit 371 neuen und 311 gelöschten Zeilen
  1. +95
    -86
      package-lock.json
  2. +149
    -127
      src/pages/my/contact_check.vue
  3. +127
    -98
      src/pages/my/contact_check_page.vue

+ 95
- 86
package-lock.json Datei anzeigen

@@ -2963,16 +2963,6 @@
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"cacache": {
"version": "13.0.1",
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&sync_timestamp=1594428006433&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz",
@@ -2999,34 +2989,6 @@
"unique-filename": "^1.1.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"find-cache-dir": {
"version": "3.3.1",
"resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz",
@@ -3064,13 +3026,6 @@
"slash": "^2.0.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"hash-sum": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-2.0.0.tgz",
@@ -3083,25 +3038,6 @@
"integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=",
"dev": true
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz?cache=0&sync_timestamp=1597081904643&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flocate-path%2Fdownload%2Flocate-path-5.0.0.tgz",
@@ -3186,16 +3122,6 @@
"minipass": "^3.1.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"terser-webpack-plugin": {
"version": "2.3.8",
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz",
@@ -3212,18 +3138,6 @@
"terser": "^4.6.12",
"webpack-sources": "^1.4.3"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
}
}
},
@@ -15543,6 +15457,101 @@
"vue-style-loader": "^4.1.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"hash-sum": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
"dev": true,
"optional": true
},
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-style-loader": {
"version": "4.1.2",
"resolved": "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.2.tgz",


+ 149
- 127
src/pages/my/contact_check.vue Datei anzeigen

@@ -2,7 +2,8 @@
<view class="container">
<view class="list-box">
<view class="list-item" v-for="(item,index) in listData" :key="index">
<view class="item-info" hover-class="canclick" @click="djContract(item.contractId)" style="padding: 12rpx 0;margin-bottom: 0">
<view class="item-info" hover-class="canclick" @click="djContract(item.contractId)"
style="padding: 12rpx 0;margin-bottom: 0">
<view class="name">合同地址</view>
<view class="value u-line-1">{{item.contractAddress}}</view>
<image class="path" src="/static/path.png" mode="" />
@@ -25,8 +26,10 @@
</view>
<view class="pay-info" v-if="item.payableList.length">
<view class="subitem" v-for="(subitem,i) in item.payableList" :key="i">
<view class="label">付款日期<view class="value">{{subitem.payableDate}}</view></view>
<view class="label">付款金额<view class="value">房租{{subitem.payableMoney}}</view></view>
<view class="label">付款日期<view class="value">{{subitem.payableDate}}</view>
</view>
<view class="label">付款金额<view class="value">房租{{subitem.payableMoney}}</view>
</view>
</view>
</view>
<view class="btn-box">
@@ -35,13 +38,14 @@
</view>
</view>
</view>
<u-modal title="确认操作" @confirm="confirm" show-cancel-button confirm-color="#FF6D25" confirm-text="确定" :mask-close-able="true" v-model="showmodal" :title-style="titleStyle">
<u-modal title="确认操作" @confirm="confirm" show-cancel-button confirm-color="#FF6D25" confirm-text="确定"
:mask-close-able="true" v-model="showmodal" :title-style="titleStyle">
<view class="slot-content">
<view class="my-tip">您确认要{{pass==1?'通过':'拒绝'}}该审核吗?</view>
</view>
</u-modal>
<view class="loading" v-if="loading">
<u-loading size="40" :show="loading"/>
<u-loading size="40" :show="loading" />
正在加载中
</view>
</view>
@@ -69,7 +73,7 @@

},
onShow() {
},
created() {
this.getList()
@@ -78,62 +82,64 @@
this.getList();
},
methods: {
passFun(item){
passFun(item) {
this.pass = 1
this.showmodal = true
this.showmodal = true
this.contractId = item.contractId
},
refuseFun(item){
refuseFun(item) {
this.pass = 0
this.showmodal = true
this.showmodal = true
this.contractId = item.contractId
},
// 定金合同详情
djContract(id){
// 审批状态0未审核 1通过 2 拒绝
this.$u.api.htContract({body:{contractId:id}}).then((res)=>{
// console.log(res)
if(res.ErrNo=='0000'){
wx.navigateTo({
url: '/pages/my/contact_check_page?src='+res.result
})
}
djContract(id) {

wx.navigateTo({
url: '/pages/my/contact_check_page?id=' + id
})
},
getList(){
getList() {
if (this.loadDone) return;
this.loading = true;
let params = {
pageNo:this.pageNo,
pageSize:this.pageSize,
pageNo: this.pageNo,
pageSize: this.pageSize,
}
this.$u.api.getContractList({body:params}).then((res)=>{
this.$u.api.getContractList({
body: params
}).then((res) => {
// console.log(res)
this.loading = false;
if(res.result&&res.result.length){
if(this.pageNo==1){
if (res.result && res.result.length) {
if (this.pageNo == 1) {
this.listData = res.result
}else{
} else {
this.listData = [...this.listData, ...res.result];
}
if(res.result.length<this.pageSize){
if (res.result.length < this.pageSize) {
this.loadDone = true;
return ;
return;
}
this.pageNo += 1;
this.loadDone = false
}else{
} else {
this.loadDone = true;
if(this.pageNo==1){
if (this.pageNo == 1) {
this.listData = []
}
}
})
},
confirm(){
confirm() {
// 审核状态 0 未审核 1 已审核 2 拒绝
this.$u.api.examine({body:{contractId:this.contractId,status:this.pass==1?1:2}}).then((res)=>{
if(res.ErrNo=='0000'){
this.$u.api.examine({
body: {
contractId: this.contractId,
status: this.pass == 1 ? 1 : 2
}
}).then((res) => {
if (res.ErrNo == '0000') {
uni.showToast({
title: '操作成功',
icon: 'none'
@@ -150,112 +156,128 @@
</script>

<style lang="scss" scoped>
.container{
width: 750rpx;
min-height: 100vh;
background: #F8F8F8;
padding-top: 20rpx;
.list-box{
.list-item{
padding: 30rpx;
background: #fff;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin-bottom: 20rpx;
.item-info{
display: flex;
align-items: center;
margin-bottom: 24rpx;
.container {
width: 750rpx;
min-height: 100vh;
background: #F8F8F8;
padding-top: 20rpx;

.list-box {
.list-item {
padding: 30rpx;
background: #fff;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 40rpx;
&.canclick:hover{
background: #eee;
}
.name{
flex: 0 0 112rpx;
color: #666666;
margin-right: 58rpx;
}
.value{
flex: 1;
color: #333;
}
.path{
flex: 0 0 14rpx;
width: 14rpx;
height: 30rpx;
margin-left: 10rpx;
}
}
.pay-info{
width: 690rpx;
background: rgba(247, 248, 252, .7);
border-radius: 8rpx;
padding: 30rpx;
margin-bottom: 24rpx;
.subitem{
width: 100%;
height: 40rpx;
color: #333333;
margin-bottom: 20rpx;

.item-info {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
&:last-child{
margin-bottom: 0;
align-items: center;
margin-bottom: 24rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 40rpx;

&.canclick:hover {
background: #eee;
}
.label{
height: 40rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;

.name {
flex: 0 0 112rpx;
color: #666666;
line-height: 40rpx;
display: flex;
align-items: center;
.value{
color: #333333;
margin-left: 10rpx;
}
margin-right: 58rpx;
}

.value {
flex: 1;
color: #333;
}

.path {
flex: 0 0 14rpx;
width: 14rpx;
height: 30rpx;
margin-left: 10rpx;
}

}
}
.btn-box{
display: flex;
justify-content: flex-end;
.btn{
width: 128rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;

.pay-info {
width: 690rpx;
background: rgba(247, 248, 252, .7);
border-radius: 8rpx;
padding: 30rpx;
margin-bottom: 24rpx;

.subitem {
width: 100%;
height: 40rpx;
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;

&:last-child {
margin-bottom: 0;
}

.label {
height: 40rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 40rpx;
display: flex;
align-items: center;

.value {
color: #333333;
margin-left: 10rpx;
}
}
}

}
.pass{
background: #FF6D25;
color: #fff;
border: 1px solid #FF6D25;
margin-right: 30rpx;
}
.refuse{
background: #FFFFFF;
border: 1px solid #FF6D25;
color: #FF6D25;

.btn-box {
display: flex;
justify-content: flex-end;

.btn {
width: 128rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
border-radius: 8rpx;
}

.pass {
background: #FF6D25;
color: #fff;
border: 1px solid #FF6D25;
margin-right: 30rpx;
}

.refuse {
background: #FFFFFF;
border: 1px solid #FF6D25;
color: #FF6D25;
}
}

}
}

.my-tip {
text-align: center;
margin: 40rpx 0;
color: #666
}
}
.my-tip{
text-align: center;
margin: 40rpx 0;
color: #666
}
}
</style>

+ 127
- 98
src/pages/my/contact_check_page.vue Datei anzeigen

@@ -10,125 +10,154 @@
};
},
onLoad(options) {
uni.setStorageSync('backFlag',1)
uni.setStorageSync('backFlag_contractId',options.contractId)
uni.setStorageSync('backFlag', 1)
uni.setStorageSync('backFlag_contractId', options.contractId)

if (options.id) {
// 审批状态0未审核 1通过 2 拒绝
this.$u.api.htContract({
body: {
contractId: options.id
}
}).then((res) => {
// console.log(res)
if (res.ErrNo == '0000') {
this.src = res.result
}
})
}
},
created() {
this.src = uni.getStorageSync('src');
},
methods: {
},
methods: {},
};
</script>

<style lang="scss" scoped>
.container{
width: 750rpx;
min-height: 100vh;
background: #F8F8F8;
padding-top: 20rpx;
.list-box{
.list-item{
padding: 30rpx;
background: #fff;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
margin-bottom: 20rpx;
.item-info{
display: flex;
align-items: center;
margin-bottom: 24rpx;
.container {
width: 750rpx;
min-height: 100vh;
background: #F8F8F8;
padding-top: 20rpx;

.list-box {
.list-item {
padding: 30rpx;
background: #fff;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 40rpx;
&.canclick:hover{
background: #eee;
color: #333333;
margin-bottom: 20rpx;

}
.name{
flex: 0 0 112rpx;
color: #666666;
margin-right: 58rpx;
}
.value{
flex: 1;
color: #333;
}
.path{
flex: 0 0 14rpx;
width: 14rpx;
height: 30rpx;
margin-left: 10rpx;
}
}
.pay-info{
width: 690rpx;
background: rgba(247, 248, 252, .7);
border-radius: 8rpx;
padding: 30rpx;
margin-bottom: 24rpx;
.subitem{
width: 100%;
height: 40rpx;
.item-info {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
&:last-child{
margin-bottom: 0;
align-items: center;
margin-bottom: 24rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 40rpx;

&.canclick:hover {
background: #eee;

}
.label{
height: 40rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;

.name {
flex: 0 0 112rpx;
color: #666666;
line-height: 40rpx;
display: flex;
align-items: center;
.value{
color: #333333;
margin-left: 10rpx;
}
margin-right: 58rpx;
}

.value {
flex: 1;
color: #333;
}

.path {
flex: 0 0 14rpx;
width: 14rpx;
height: 30rpx;
margin-left: 10rpx;
}

}
}
.btn-box{
display: flex;
justify-content: flex-end;
.btn{
width: 128rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;

.pay-info {
width: 690rpx;
background: rgba(247, 248, 252, .7);
border-radius: 8rpx;
padding: 30rpx;
margin-bottom: 24rpx;

.subitem {
width: 100%;
height: 40rpx;
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;

&:last-child {
margin-bottom: 0;
}

.label {
height: 40rpx;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
line-height: 40rpx;
display: flex;
align-items: center;

.value {
color: #333333;
margin-left: 10rpx;
}
}
}

}
.pass{
background: #FF6D25;
color: #fff;
border: 1px solid #FF6D25;
margin-right: 30rpx;
}
.refuse{
background: #FFFFFF;
border: 1px solid #FF6D25;
color: #FF6D25;

.btn-box {
display: flex;
justify-content: flex-end;

.btn {
width: 128rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 26rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
border-radius: 8rpx;
}

.pass {
background: #FF6D25;
color: #fff;
border: 1px solid #FF6D25;
margin-right: 30rpx;
}

.refuse {
background: #FFFFFF;
border: 1px solid #FF6D25;
color: #FF6D25;
}
}

}
}

.my-tip {
text-align: center;
margin: 40rpx 0;
color: #666
}
}
.my-tip{
text-align: center;
margin: 40rpx 0;
color: #666
}
}
</style>

Laden…
Abbrechen
Speichern