From 9857f8cdadf9bbda695a689f42e0e8cecfefab3f Mon Sep 17 00:00:00 2001
From: Liuyi <candymxq888@outlook.com>
Date: 星期四, 21 十一月 2024 17:08:07 +0800
Subject: [PATCH] 添加积分兑换

---
 pages/pointsMall/pointsGoodsDetail/index.vue    |   32 +
 unpackage/dist/dev/mp-weixin/common/vendor.js   |  401 ++++++++++++++++++++++++++------
 pages/pointsMall/index.vue                      |   71 +++--
 pages/pointsMall/pointsExchangeRecord/index.vue |  198 ++++++++++++---
 4 files changed, 540 insertions(+), 162 deletions(-)

diff --git a/pages/pointsMall/index.vue b/pages/pointsMall/index.vue
index 6bc541a..acfe229 100644
--- a/pages/pointsMall/index.vue
+++ b/pages/pointsMall/index.vue
@@ -10,13 +10,6 @@
 	
 	const typeList = ref([
 		// {value:'1',name:'全部分类',active:1},
-		// {value:'2',name:'零食',active:0},
-		// {value:'3',name:'电子设备',active:0},
-		// {value:'4',name:'洗护用品',active:0},
-		// {value:'5',name:'其他',active:0},
-		// {value:'5',name:'其他',active:0},
-		// {value:'5',name:'其他',active:0},
-		// {value:'5',name:'其他',active:0},
 	])
 	const goodsList = ref([
 		// {id:'1',imageUrl:'',name:'商品名称',price:'50.00',useIntegral:'1000',stock:102},
@@ -40,24 +33,39 @@
 	async function changeType(typeId,active,e){
 		typeList.value.forEach((item,index) =>{
 			if(index == e){
-				item.active = 1
+				item.active = true
 			}else{
-				item.active = 0
+				item.active = false
 			}
 		})
 		await getGoodsList(typeId)
 	}
 	//积分兑换
+	async function confirm(){
+		await integralConvertApi({userId:userInfo.value.id,goodsId:checkedGoodsId.value}).then(async(res) =>{
+			if(res.code == 200){
+				uni.showToast({
+					title:'兑换成功!',
+					duration:1000
+				})
+				await updateUserInfo()
+				await getGoodsList('')
+				setGoodsType()
+				setTimeout(() =>{
+					uni.navigateTo({
+						url:'/pages/pointsMall/pointsExchangeRecord/index'
+					})
+				},1000)
+			}
+		})
+	}
+	//打开确认弹窗
+	const alertDialog = ref()
+	const checkedGoodsId = ref()
 	async function integralConvert(goodsId,goodsIntegral){
 		if(goodsIntegral <= Number(userInfo.value.integral)){
-			await integralConvertApi({userId:userInfo.value.id,goodsId:goodsId}).then((res) =>{
-				if(res.code == 200){
-					uni.showToast({
-						title:'兑换成功!',
-						icon:'none'
-					})
-				}
-			})
+			checkedGoodsId.value = goodsId
+			alertDialog.value.open()
 		}else{
 			uni.showToast({
 				title:'积分余额不足!',
@@ -86,13 +94,8 @@
 			}
 		})
 	}
-	onMounted(async() =>{
-		await getGoodsTypeList()
-		await getGoodsList('')
-		console.log('onMounted')
-	})
-	onShow(async() =>{
-		await getGoodsList('')
+	//设置选中商品为全部
+	function setGoodsType(){
 		typeList.value.forEach((item,index) =>{
 			if(index == 0){
 				item.active = 1
@@ -100,6 +103,15 @@
 				item.active = 0
 			}
 		})
+	}
+	onMounted(async() =>{
+		await getGoodsTypeList()
+		await getGoodsList('')
+		console.log('onMounted')
+	})
+	onShow(async() =>{
+		await getGoodsList('')
+		setGoodsType()
 		await updateUserInfo()
 		console.log('onShow')
 	})
@@ -157,7 +169,7 @@
 					<image src="../../static/images/pointMall/nav1.svg"></image>
 				</view>
 				<view class="nav-item" @click="navTo('/pages/pointsMall/pointsExchangeRecord/index')">
-					<text>兑换记录</text>
+					<text>兑换订单</text>
 					<image src="../../static/images/pointMall/nav2.svg"></image>
 				</view>
 			</view>
@@ -172,7 +184,7 @@
 			</view>
 			<view class="goods-box">
 				<view v-for="(item,index) in goodsList" :key="index" class="goods-item">
-					<image @click="navTo(`/pages/pointsMall/pointsGoodsDetail/index?goodsId=${item.id}`)" class="goods-item-img" :src="baseUrl + '/upload' + item.imageUrl" mode="widthFix"></image>
+					<image @click="navTo(`/pages/pointsMall/pointsGoodsDetail/index?goodsId=${item.id}`)" class="goods-item-img" :src="baseUrl + '/upload' + item.imageUrl" mode="aspectFit"></image>
 					
 					<view class="goods-item-name" @click="navTo(`/pages/pointsMall/pointsGoodsDetail/index?goodsId=${item.id}`)">
 						<text>{{item.name}}</text>
@@ -199,6 +211,10 @@
 				</view>
 			</view>
 		</view>
+		<!-- 提示窗 -->
+		<uni-popup ref="alertDialog" type="dialog">
+			<uni-popup-dialog type="info" title="提示" :showClose = 'true' content="确认兑换该商品!" @confirm="confirm"></uni-popup-dialog>
+		</uni-popup>
 	</view>
 </template>
 
@@ -499,7 +515,7 @@
 			   .goods-item{
 				   display: inline-block;
 				   width:48%;
-				   max-height:800rpx;
+				   height:600rpx;
 				   background: #fff;
 				   overflow:hidden;
 				   margin-bottom:20rpx;
@@ -512,6 +528,7 @@
 					background:linear-gradient(#fff,#e8e8e8);
 				   .goods-item-img{
 					   width:80%;
+					   min-height:280rpx;
 					   margin: 0 auto;
 					   margin-bottom:50rpx;
 				   }
diff --git a/pages/pointsMall/pointsExchangeRecord/index.vue b/pages/pointsMall/pointsExchangeRecord/index.vue
index 58ca621..29d3eef 100644
--- a/pages/pointsMall/pointsExchangeRecord/index.vue
+++ b/pages/pointsMall/pointsExchangeRecord/index.vue
@@ -10,6 +10,42 @@
 			pointExchangeList.value = res.data.list
 		})
 	}
+	//兑换码相关
+	const popupCode = ref()
+	const codeValue = ref('')
+	const codeGoodsName = ref('')
+	//点击兑换
+	function showConvertCode(redeemCode,goodsName){
+		codeValue.value = redeemCode
+		popupCode.value.open()
+		codeGoodsName.value = goodsName
+	}
+	//弹窗改变事件
+	let codeInterVal
+	async function popupChange(e){
+		console.log('tanchuan',e)
+		if(e.show == true){
+			console.log('打开弹窗')
+			codeInterVal = setInterval(async() =>{
+				await searchPoints()
+				pointExchangeList.value.forEach((item) =>{
+					if(item.redeemCode == codeValue.value){
+						if(item.receiveStatus == 1){
+							clearInterval(codeInterVal)
+							popupCode.value.close()
+							uni.showToast({
+								title:'领取成功!'
+							})
+						}
+					}
+				})
+			},2000)
+		}else if(e.show == false){
+			console.log('关闭弹窗')
+			clearInterval(codeInterVal)
+			await searchPoints()
+		}
+	}
 	onMounted(async() =>{
 		await searchPoints()
 	})
@@ -17,23 +53,38 @@
 </script>
 <template>
 	<view class="container">
-		<point-navbar title='兑换记录'></point-navbar>
+		<point-navbar title='兑换订单'></point-navbar>
 		<view class="content">
 			<view class="main" v-if="pointExchangeList.length > 0">
 				<block v-for="(item,index) in pointExchangeList">
 					<view class="item">
-						<view class="item-left">
-							<text class="item-methods">兑换商品:{{item.goodsName}}</text>
-							<view class="item-status">
-								<text>领取状态:</text>
-								<text>{{item.receiveStatusView}}</text>
+						<view class="item-box">
+							<view class="item-row1">
+								<text>兑换商品:</text>
+								<text class="goods-name">{{item.goodsName}}</text>
 							</view>
-							<text class="item-time">兑换时间:{{item.exchangeDate}}</text>
-							<text v-if="item.receiveStatus == 1" class="item-time">领取时间:{{item.receiveDate}}</text>
-						</view>
-						<view class="item-right">
-							<text class="money">-{{item.integralAmount}}</text>
-							<image src="../../../static/images/pointMall/advert/money1.svg"></image>
+							<view class="item-row2">
+								<view class="status">
+									<text>领取状态:</text>
+									<text class="status-value">{{item.receiveStatusView}}</text>
+								</view>
+								<view class="advert-code" v-if="item.receiveStatus == 0" @click="showConvertCode(item.redeemCode,item.goodsName)">
+									<text>出示兑换码</text>
+								</view>
+							</view>
+							<view class="item-row3">
+								<view>积分消耗:</view>
+								<view class="points">
+									<text class="points-value">-{{item.integralAmount}}</text>
+									<image class="points-img" src="../../../static/images/pointMall/advert/money1.svg"></image>
+								</view>
+							</view>
+							<view class="item-row4">
+								<view class="time">
+									<text class="time-value">兑换时间:{{item.exchangeDate}}</text>
+									<text v-if="item.receiveStatus == 1" class="time-value">领取时间:{{item.receiveDate}}</text>
+								</view>
+							</view>
 						</view>
 					</view>
 				</block>
@@ -43,6 +94,16 @@
 				<text>暂无记录</text>
 			</view>
 		</view>
+		<uni-popup ref="popupCode" @change="popupChange" type="center" background-color="#fff" border-radius="10px">
+			<view class="convert-code"> 
+				<text class="code-title">兑换码</text>
+				<view class="code-value">
+					<!-- <l-qrcode :value="codeValue" size="260rpx" color="rgb(12, 15, 36)"></l-qrcode> -->
+					<text>{{codeValue}}</text>
+				</view>
+				<text>商品名称:{{codeGoodsName}}</text>
+			</view>
+		</uni-popup>
 	</view>
 </template>
 
@@ -72,46 +133,68 @@
 					  height:260rpx;
 					  border-bottom:1rpx solid #D8D8D8;
 					  box-sizing:border-box;
-					  padding-bottom:10rpx;
+					  padding:20rpx 0 10rpx;
 					  margin-bottom:10rpx;
-					  justify-content:space-between;
-					  align-items:flex-end;
-					  display: flex;
-					  .item-left{
+					  .item-box{
+						  width:100%;
 						  height:100%;
-						  display:flex;
-						  flex-direction:column;
-						  justify-content:flex-end;
-						  align-items: flex-start;
-						  font-weight:500;
-						  font-size: 32rpx;
-						  color: #59544e;
-						  .item-methods{
-							  margin-bottom:20rpx;
+						  display: flex;
+						  flex-direction: column;
+						  justify-content:space-around;
+						   font-weight:500;
+						   font-size: 32rpx;
+						   color: #5f5b57;
+						  .item-row1{
+							 width:100%;
+							 .goods-name{
+								 color: #4b4845;
+							 }
 						  }
-						  .item-time{
-							  font-weight: 300;
-							  font-size:26rpx;
-							  color: #909090;
+						  .item-row2{
+							width:100%;
+						  	display: flex;
+							justify-content: space-between;
+							align-items: center;
+							.status-value{
+								color: #e2ac21;
+							}
+							.advert-code{
+								width: 200rpx;
+								height:55rpx;
+								background: linear-gradient(to right,#efa339,#fbc671);
+								border-radius:30rpx;
+								display: flex;
+								justify-content: center;
+								align-items: center;
+								color: #FFF;
+								letter-spacing:1rpx;
+								font-size: 30rpx;
+							}
 						  }
-						  .item-status{
-							margin-bottom:20rpx;
+						  .item-row3{
+							 display: flex;
+							  .points{
+								  display: flex;
+								  align-items: center;
+								  .points-img{
+									  width:40rpx;
+									  height:40rpx;
+									  margin-left:5rpx;
+								  }
+								  .points-value{
+									 color: #efab22; 
+								  }
+							  }
 						  }
-					  }
-					  .item-right{
-						  height:100%;
-						  display:flex;
-						  justify-content:flex-end;
-						  align-items:flex-end;
-						  image{
-							width:40rpx;
-							height:40rpx;
-							margin-left:5rpx;
-						  }
-						  .money{
-								font-weight: 500;
-								font-size: 32rpx;
-								color: #efab22;
+						  .item-row4{
+							   width:100%;;
+							   .time{
+								     font-weight: 300;
+								     font-size:26rpx;
+								     color: #909090;
+									 display: flex;
+									 flex-direction: column;
+							   }
 						  }
 					  }
 				  }
@@ -134,5 +217,26 @@
 			}
 	   }
 	}
+	.convert-code{
+		width: 550rpx;
+		height: 550rpx;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content:space-evenly;
+		padding:10rpx 0;
+		box-sizing: border-box;
+		.code-title{
+			font-weight:600;
+		}
+		.code-value{
+			padding: 30rpx;
+			border:1rpx solid #e2e2e2;
+			box-sizing: border-box;
+			border-radius:10rpx;
+			font-weight:600;
+			letter-spacing:1rpx;
+		}
+	}
 }
 </style>
diff --git a/pages/pointsMall/pointsGoodsDetail/index.vue b/pages/pointsMall/pointsGoodsDetail/index.vue
index 5199c4a..e2c7fe7 100644
--- a/pages/pointsMall/pointsGoodsDetail/index.vue
+++ b/pages/pointsMall/pointsGoodsDetail/index.vue
@@ -15,17 +15,27 @@
 		})
 	}
 	//积分兑换
+	async function confirm(){
+		await integralConvertApi({userId:userInfo.value.id,goodsId:detailInfo.value.id}).then(async(res) =>{
+			if(res.code == 200){
+				uni.showToast({
+					title:'兑换成功!',
+					duration:1000
+				})
+				setTimeout(() =>{
+					uni.navigateTo({
+						url:'/pages/pointsMall/pointsExchangeRecord/index'
+					})
+				},1000)
+				await getGoodsDetail(goodsId)
+			}
+		})
+	}
+	//打开确认弹窗
+	const alertDialog = ref()
 	async function integralConvert(){
 		if(detailInfo.value.useIntegral <= Number(userInfo.value.integral)){
-			await integralConvertApi({userId:userInfo.value.id,goodsId:detailInfo.value.id}).then(async(res) =>{
-				if(res.code == 200){
-					uni.showToast({
-						title:'兑换成功!',
-						icon:'none'
-					})
-					await getGoodsDetail(goodsId)
-				}
-			})
+			alertDialog.value.open()
 		}else{
 			uni.showToast({
 				title:'积分余额不足!',
@@ -76,6 +86,10 @@
 				</view>
 			</view>
 		</view>
+		<!-- 提示窗 -->
+		<uni-popup ref="alertDialog" type="dialog">
+			<uni-popup-dialog type="info" title="提示" :showClose = 'true' content="确认兑换该商品!" @confirm="confirm"></uni-popup-dialog>
+		</uni-popup>
 	</view>
 </template>
 
diff --git a/unpackage/dist/dev/mp-weixin/common/vendor.js b/unpackage/dist/dev/mp-weixin/common/vendor.js
index 37418e9..9b3b668 100644
--- a/unpackage/dist/dev/mp-weixin/common/vendor.js
+++ b/unpackage/dist/dev/mp-weixin/common/vendor.js
@@ -30,17 +30,17 @@
     arr.splice(i2, 1);
   }
 };
-const hasOwnProperty$1 = Object.prototype.hasOwnProperty;
-const hasOwn = (val, key) => hasOwnProperty$1.call(val, key);
+const hasOwnProperty$2 = Object.prototype.hasOwnProperty;
+const hasOwn$1 = (val, key) => hasOwnProperty$2.call(val, key);
 const isArray = Array.isArray;
 const isMap = (val) => toTypeString(val) === "[object Map]";
 const isSet = (val) => toTypeString(val) === "[object Set]";
 const isFunction = (val) => typeof val === "function";
 const isString = (val) => typeof val === "string";
 const isSymbol = (val) => typeof val === "symbol";
-const isObject = (val) => val !== null && typeof val === "object";
+const isObject$1 = (val) => val !== null && typeof val === "object";
 const isPromise = (val) => {
-  return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);
+  return (isObject$1(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch);
 };
 const objectToString = Object.prototype.toString;
 const toTypeString = (value) => objectToString.call(value);
@@ -112,7 +112,7 @@
       }
     }
     return res;
-  } else if (isString(value) || isObject(value)) {
+  } else if (isString(value) || isObject$1(value)) {
     return value;
   }
 }
@@ -140,7 +140,7 @@
         res += normalized + " ";
       }
     }
-  } else if (isObject(value)) {
+  } else if (isObject$1(value)) {
     for (const name in value) {
       if (value[name]) {
         res += name + " ";
@@ -150,7 +150,7 @@
   return res.trim();
 }
 const toDisplayString = (val) => {
-  return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);
+  return isString(val) ? val : val == null ? "" : isArray(val) || isObject$1(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val);
 };
 const replacer = (_key, val) => {
   if (val && val.__v_isRef) {
@@ -171,7 +171,7 @@
     };
   } else if (isSymbol(val)) {
     return stringifySymbol(val);
-  } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
+  } else if (isObject$1(val) && !isArray(val) && !isPlainObject(val)) {
     return String(val);
   }
   return val;
@@ -409,11 +409,96 @@
   }
 };
 var E$1$1 = E$1;
+const isObject = (val) => val !== null && typeof val === "object";
+const defaultDelimiters = ["{", "}"];
+class BaseFormatter {
+  constructor() {
+    this._caches = /* @__PURE__ */ Object.create(null);
+  }
+  interpolate(message, values, delimiters = defaultDelimiters) {
+    if (!values) {
+      return [message];
+    }
+    let tokens = this._caches[message];
+    if (!tokens) {
+      tokens = parse(message, delimiters);
+      this._caches[message] = tokens;
+    }
+    return compile$1(tokens, values);
+  }
+}
+const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
+const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
+function parse(format, [startDelimiter, endDelimiter]) {
+  const tokens = [];
+  let position = 0;
+  let text = "";
+  while (position < format.length) {
+    let char = format[position++];
+    if (char === startDelimiter) {
+      if (text) {
+        tokens.push({ type: "text", value: text });
+      }
+      text = "";
+      let sub = "";
+      char = format[position++];
+      while (char !== void 0 && char !== endDelimiter) {
+        sub += char;
+        char = format[position++];
+      }
+      const isClosed = char === endDelimiter;
+      const type = RE_TOKEN_LIST_VALUE.test(sub) ? "list" : isClosed && RE_TOKEN_NAMED_VALUE.test(sub) ? "named" : "unknown";
+      tokens.push({ value: sub, type });
+    } else {
+      text += char;
+    }
+  }
+  text && tokens.push({ type: "text", value: text });
+  return tokens;
+}
+function compile$1(tokens, values) {
+  const compiled = [];
+  let index2 = 0;
+  const mode = Array.isArray(values) ? "list" : isObject(values) ? "named" : "unknown";
+  if (mode === "unknown") {
+    return compiled;
+  }
+  while (index2 < tokens.length) {
+    const token = tokens[index2];
+    switch (token.type) {
+      case "text":
+        compiled.push(token.value);
+        break;
+      case "list":
+        compiled.push(values[parseInt(token.value, 10)]);
+        break;
+      case "named":
+        if (mode === "named") {
+          compiled.push(values[token.value]);
+        } else {
+          {
+            console.warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);
+          }
+        }
+        break;
+      case "unknown":
+        {
+          console.warn(`Detect 'unknown' type of token!`);
+        }
+        break;
+    }
+    index2++;
+  }
+  return compiled;
+}
 const LOCALE_ZH_HANS = "zh-Hans";
 const LOCALE_ZH_HANT = "zh-Hant";
 const LOCALE_EN = "en";
 const LOCALE_FR = "fr";
 const LOCALE_ES = "es";
+const hasOwnProperty$1 = Object.prototype.hasOwnProperty;
+const hasOwn = (val, key) => hasOwnProperty$1.call(val, key);
+const defaultFormatter = new BaseFormatter();
 function include(str, parts) {
   return !!parts.find((part) => str.indexOf(part) !== -1);
 }
@@ -453,6 +538,163 @@
     return lang;
   }
 }
+class I18n {
+  constructor({ locale, fallbackLocale, messages, watcher, formater: formater2 }) {
+    this.locale = LOCALE_EN;
+    this.fallbackLocale = LOCALE_EN;
+    this.message = {};
+    this.messages = {};
+    this.watchers = [];
+    if (fallbackLocale) {
+      this.fallbackLocale = fallbackLocale;
+    }
+    this.formater = formater2 || defaultFormatter;
+    this.messages = messages || {};
+    this.setLocale(locale || LOCALE_EN);
+    if (watcher) {
+      this.watchLocale(watcher);
+    }
+  }
+  setLocale(locale) {
+    const oldLocale = this.locale;
+    this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;
+    if (!this.messages[this.locale]) {
+      this.messages[this.locale] = {};
+    }
+    this.message = this.messages[this.locale];
+    if (oldLocale !== this.locale) {
+      this.watchers.forEach((watcher) => {
+        watcher(this.locale, oldLocale);
+      });
+    }
+  }
+  getLocale() {
+    return this.locale;
+  }
+  watchLocale(fn) {
+    const index2 = this.watchers.push(fn) - 1;
+    return () => {
+      this.watchers.splice(index2, 1);
+    };
+  }
+  add(locale, message, override = true) {
+    const curMessages = this.messages[locale];
+    if (curMessages) {
+      if (override) {
+        Object.assign(curMessages, message);
+      } else {
+        Object.keys(message).forEach((key) => {
+          if (!hasOwn(curMessages, key)) {
+            curMessages[key] = message[key];
+          }
+        });
+      }
+    } else {
+      this.messages[locale] = message;
+    }
+  }
+  f(message, values, delimiters) {
+    return this.formater.interpolate(message, values, delimiters).join("");
+  }
+  t(key, locale, values) {
+    let message = this.message;
+    if (typeof locale === "string") {
+      locale = normalizeLocale(locale, this.messages);
+      locale && (message = this.messages[locale]);
+    } else {
+      values = locale;
+    }
+    if (!hasOwn(message, key)) {
+      console.warn(`Cannot translate the value of keypath ${key}. Use the value of keypath as default.`);
+      return key;
+    }
+    return this.formater.interpolate(message[key], values).join("");
+  }
+}
+function watchAppLocale(appVm, i18n) {
+  if (appVm.$watchLocale) {
+    appVm.$watchLocale((newLocale) => {
+      i18n.setLocale(newLocale);
+    });
+  } else {
+    appVm.$watch(() => appVm.$locale, (newLocale) => {
+      i18n.setLocale(newLocale);
+    });
+  }
+}
+function getDefaultLocale() {
+  if (typeof index !== "undefined" && index.getLocale) {
+    return index.getLocale();
+  }
+  if (typeof global !== "undefined" && global.getLocale) {
+    return global.getLocale();
+  }
+  return LOCALE_EN;
+}
+function initVueI18n(locale, messages = {}, fallbackLocale, watcher) {
+  if (typeof locale !== "string") {
+    const options = [
+      messages,
+      locale
+    ];
+    locale = options[0];
+    messages = options[1];
+  }
+  if (typeof locale !== "string") {
+    locale = getDefaultLocale();
+  }
+  if (typeof fallbackLocale !== "string") {
+    fallbackLocale = typeof __uniConfig !== "undefined" && __uniConfig.fallbackLocale || LOCALE_EN;
+  }
+  const i18n = new I18n({
+    locale,
+    fallbackLocale,
+    messages,
+    watcher
+  });
+  let t2 = (key, values) => {
+    if (typeof getApp !== "function") {
+      t2 = function(key2, values2) {
+        return i18n.t(key2, values2);
+      };
+    } else {
+      let isWatchedAppLocale = false;
+      t2 = function(key2, values2) {
+        const appVm = getApp().$vm;
+        if (appVm) {
+          appVm.$locale;
+          if (!isWatchedAppLocale) {
+            isWatchedAppLocale = true;
+            watchAppLocale(appVm, i18n);
+          }
+        }
+        return i18n.t(key2, values2);
+      };
+    }
+    return t2(key, values);
+  };
+  return {
+    i18n,
+    f(message, values, delimiters) {
+      return i18n.f(message, values, delimiters);
+    },
+    t(key, values) {
+      return t2(key, values);
+    },
+    add(locale2, message, override = true) {
+      return i18n.add(locale2, message, override);
+    },
+    watch(fn) {
+      return i18n.watchLocale(fn);
+    },
+    getLocale() {
+      return i18n.getLocale();
+    },
+    setLocale(newLocale) {
+      return i18n.setLocale(newLocale);
+    }
+  };
+}
 function getBaseSystemInfo() {
   return wx.getSystemInfoSync();
 }
@@ -464,7 +706,7 @@
     onFail = validateProtocolFail;
   }
   for (const key in protocol) {
-    const errMsg = validateProp$1(key, data[key], protocol[key], !hasOwn(data, key));
+    const errMsg = validateProp$1(key, data[key], protocol[key], !hasOwn$1(data, key));
     if (isString(errMsg)) {
       onFail(name, errMsg);
     }
@@ -527,7 +769,7 @@
       valid = value instanceof type;
     }
   } else if (expectedType === "Object") {
-    valid = isObject(value);
+    valid = isObject$1(value);
   } else if (expectedType === "Array") {
     valid = isArray(value);
   } else {
@@ -783,7 +1025,7 @@
         return errMsg;
       }
     } else {
-      if (!hasOwn(params, name)) {
+      if (!hasOwn$1(params, name)) {
         params[name] = formatterOrDefaultValue;
       }
     }
@@ -1157,7 +1399,7 @@
         argsOption = argsOption(fromArgs, toArgs) || {};
       }
       for (const key in fromArgs) {
-        if (hasOwn(argsOption, key)) {
+        if (hasOwn$1(argsOption, key)) {
           let keyOption = argsOption[key];
           if (isFunction(keyOption)) {
             keyOption = keyOption(fromArgs[key], fromArgs, toArgs);
@@ -1175,7 +1417,7 @@
             toArgs[key] = processCallback(methodName, callback, returnValue);
           }
         } else {
-          if (!keepFromArgs && !hasOwn(toArgs, key)) {
+          if (!keepFromArgs && !hasOwn$1(toArgs, key)) {
             toArgs[key] = fromArgs[key];
           }
         }
@@ -1193,7 +1435,7 @@
     return processArgs(methodName, res, returnValue, {}, keepReturnValue);
   }
   return function wrapper(methodName, method) {
-    if (!hasOwn(protocols2, methodName)) {
+    if (!hasOwn$1(protocols2, methodName)) {
       return method;
     }
     const protocol = protocols2[methodName];
@@ -1487,13 +1729,13 @@
   const wrapper = initWrapper(protocols2);
   const UniProxyHandlers = {
     get(target, key) {
-      if (hasOwn(target, key)) {
+      if (hasOwn$1(target, key)) {
         return target[key];
       }
-      if (hasOwn(api, key)) {
+      if (hasOwn$1(api, key)) {
         return promisify(key, api[key]);
       }
-      if (hasOwn(baseApis, key)) {
+      if (hasOwn$1(baseApis, key)) {
         return promisify(key, baseApis[key]);
       }
       return promisify(key, wrapper(key, platform[key]));
@@ -2505,7 +2747,7 @@
     }
     const targetIsArray = isArray(target);
     if (!isReadonly2) {
-      if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
+      if (targetIsArray && hasOwn$1(arrayInstrumentations, key)) {
         return Reflect.get(arrayInstrumentations, key, receiver);
       }
       if (key === "hasOwnProperty") {
@@ -2525,7 +2767,7 @@
     if (isRef(res)) {
       return targetIsArray && isIntegerKey(key) ? res : res.value;
     }
-    if (isObject(res)) {
+    if (isObject$1(res)) {
       return isReadonly2 ? readonly(res) : reactive(res);
     }
     return res;
@@ -2552,7 +2794,7 @@
         }
       }
     }
-    const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key);
+    const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn$1(target, key);
     const result = Reflect.set(target, key, value, receiver);
     if (target === toRaw(receiver)) {
       if (!hadKey) {
@@ -2564,7 +2806,7 @@
     return result;
   }
   deleteProperty(target, key) {
-    const hadKey = hasOwn(target, key);
+    const hadKey = hasOwn$1(target, key);
     const oldValue = target[key];
     const result = Reflect.deleteProperty(target, key);
     if (result && hadKey) {
@@ -2869,7 +3111,7 @@
       return target;
     }
     return Reflect.get(
-      hasOwn(instrumentations, key) && key in target ? instrumentations : target,
+      hasOwn$1(instrumentations, key) && key in target ? instrumentations : target,
       key,
       receiver
     );
@@ -2957,7 +3199,7 @@
   );
 }
 function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) {
-  if (!isObject(target)) {
+  if (!isObject$1(target)) {
     {
       warn$2(`value cannot be made reactive: ${String(target)}`);
     }
@@ -3006,8 +3248,8 @@
   }
   return value;
 }
-const toReactive = (value) => isObject(value) ? reactive(value) : value;
-const toReadonly = (value) => isObject(value) ? readonly(value) : value;
+const toReactive = (value) => isObject$1(value) ? reactive(value) : value;
+const toReadonly = (value) => isObject$1(value) ? readonly(value) : value;
 const COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided.  Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`;
 class ComputedRefImpl {
   constructor(getter, _setter, isReadonly2, isSSR) {
@@ -3761,7 +4003,7 @@
     }
   }
   if (!raw && !hasExtends) {
-    if (isObject(comp)) {
+    if (isObject$1(comp)) {
       cache.set(comp, null);
     }
     return null;
@@ -3771,7 +4013,7 @@
   } else {
     extend(normalized, raw);
   }
-  if (isObject(comp)) {
+  if (isObject$1(comp)) {
     cache.set(comp, normalized);
   }
   return normalized;
@@ -3781,7 +4023,7 @@
     return false;
   }
   key = key.slice(2).replace(/Once$/, "");
-  return hasOwn(options, key[0].toLowerCase() + key.slice(1)) || hasOwn(options, hyphenate(key)) || hasOwn(options, key);
+  return hasOwn$1(options, key[0].toLowerCase() + key.slice(1)) || hasOwn$1(options, hyphenate(key)) || hasOwn$1(options, key);
 }
 let currentRenderingInstance = null;
 function setCurrentRenderingInstance(instance) {
@@ -4032,7 +4274,7 @@
   };
 }
 function traverse(value, depth, currentDepth = 0, seen) {
-  if (!isObject(value) || value["__v_skip"]) {
+  if (!isObject$1(value) || value["__v_skip"]) {
     return value;
   }
   if (depth && depth > 0) {
@@ -4095,7 +4337,7 @@
     if (!isFunction(rootComponent)) {
       rootComponent = extend({}, rootComponent);
     }
-    if (rootProps != null && !isObject(rootProps)) {
+    if (rootProps != null && !isObject$1(rootProps)) {
       warn$1(`root props passed to app.mount() must be an object.`);
       rootProps = null;
     }
@@ -4369,7 +4611,7 @@
   })
 );
 const isReservedPrefix = (key) => key === "_" || key === "$";
-const hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key);
+const hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn$1(state, key);
 const PublicInstanceProxyHandlers = {
   get({ _: instance }, key) {
     const { ctx, setupState, data, props, accessCache, type, appContext } = instance;
@@ -4393,17 +4635,17 @@
       } else if (hasSetupBinding(setupState, key)) {
         accessCache[key] = 1;
         return setupState[key];
-      } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
+      } else if (data !== EMPTY_OBJ && hasOwn$1(data, key)) {
         accessCache[key] = 2;
         return data[key];
       } else if (
         // only cache other properties when instance has declared (thus stable)
         // props
-        (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key)
+        (normalizedProps = instance.propsOptions[0]) && hasOwn$1(normalizedProps, key)
       ) {
         accessCache[key] = 3;
         return props[key];
-      } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {
+      } else if (ctx !== EMPTY_OBJ && hasOwn$1(ctx, key)) {
         accessCache[key] = 4;
         return ctx[key];
       } else if (shouldCacheAccess) {
@@ -4424,12 +4666,12 @@
       (cssModule = type.__cssModules) && (cssModule = cssModule[key])
     ) {
       return cssModule;
-    } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {
+    } else if (ctx !== EMPTY_OBJ && hasOwn$1(ctx, key)) {
       accessCache[key] = 4;
       return ctx[key];
     } else if (
       // global properties
-      globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key)
+      globalProperties = appContext.config.globalProperties, hasOwn$1(globalProperties, key)
     ) {
       {
         return globalProperties[key];
@@ -4437,7 +4679,7 @@
     } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading
     // to infinite warning loop
     key.indexOf("__v") !== 0)) {
-      if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) {
+      if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn$1(data, key)) {
         warn$1(
           `Property ${JSON.stringify(
             key
@@ -4455,13 +4697,13 @@
     if (hasSetupBinding(setupState, key)) {
       setupState[key] = value;
       return true;
-    } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) {
+    } else if (setupState.__isScriptSetup && hasOwn$1(setupState, key)) {
       warn$1(`Cannot mutate <script setup> binding "${key}" from Options API.`);
       return false;
-    } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
+    } else if (data !== EMPTY_OBJ && hasOwn$1(data, key)) {
       data[key] = value;
       return true;
-    } else if (hasOwn(instance.props, key)) {
+    } else if (hasOwn$1(instance.props, key)) {
       warn$1(`Attempting to mutate prop "${key}". Props are readonly.`);
       return false;
     }
@@ -4487,12 +4729,12 @@
     _: { data, setupState, accessCache, ctx, appContext, propsOptions }
   }, key) {
     let normalizedProps;
-    return !!accessCache[key] || data !== EMPTY_OBJ && hasOwn(data, key) || hasSetupBinding(setupState, key) || (normalizedProps = propsOptions[0]) && hasOwn(normalizedProps, key) || hasOwn(ctx, key) || hasOwn(publicPropertiesMap, key) || hasOwn(appContext.config.globalProperties, key);
+    return !!accessCache[key] || data !== EMPTY_OBJ && hasOwn$1(data, key) || hasSetupBinding(setupState, key) || (normalizedProps = propsOptions[0]) && hasOwn$1(normalizedProps, key) || hasOwn$1(ctx, key) || hasOwn$1(publicPropertiesMap, key) || hasOwn$1(appContext.config.globalProperties, key);
   },
   defineProperty(target, key, descriptor) {
     if (descriptor.get != null) {
       target._.accessCache[key] = 0;
-    } else if (hasOwn(descriptor, "value")) {
+    } else if (hasOwn$1(descriptor, "value")) {
       this.set(target, key, descriptor.value, null);
     }
     return Reflect.defineProperty(target, key, descriptor);
@@ -4666,7 +4908,7 @@
         `data() returned a Promise - note data() cannot be async; If you intend to perform data fetching before component renders, use async setup() + <Suspense>.`
       );
     }
-    if (!isObject(data)) {
+    if (!isObject$1(data)) {
       warn$1(`data() should return an object.`);
     } else {
       instance.data = reactive(data);
@@ -4784,7 +5026,7 @@
   for (const key in injectOptions) {
     const opt = injectOptions[key];
     let injected;
-    if (isObject(opt)) {
+    if (isObject$1(opt)) {
       if ("default" in opt) {
         injected = inject(
           opt.from || key,
@@ -4830,7 +5072,7 @@
     }
   } else if (isFunction(raw)) {
     watch(getter, raw.bind(publicThis));
-  } else if (isObject(raw)) {
+  } else if (isObject$1(raw)) {
     if (isArray(raw)) {
       raw.forEach((r2) => createWatcher(r2, ctx, publicThis, key));
     } else {
@@ -4870,7 +5112,7 @@
     }
     mergeOptions(resolved, base, optionMergeStrategies);
   }
-  if (isObject(base)) {
+  if (isObject$1(base)) {
     cache.set(base, resolved);
   }
   return resolved;
@@ -5041,7 +5283,7 @@
         }
         const value = rawProps[key];
         if (options) {
-          if (hasOwn(attrs, key)) {
+          if (hasOwn$1(attrs, key)) {
             if (value !== attrs[key]) {
               attrs[key] = value;
               hasAttrsChanged = true;
@@ -5072,9 +5314,9 @@
     let kebabKey;
     for (const key in rawCurrentProps) {
       if (!rawProps || // for camelCase
-      !hasOwn(rawProps, key) && // it's possible the original props was passed in as kebab-case
+      !hasOwn$1(rawProps, key) && // it's possible the original props was passed in as kebab-case
       // and converted to camelCase (#955)
-      ((kebabKey = hyphenate(key)) === key || !hasOwn(rawProps, kebabKey))) {
+      ((kebabKey = hyphenate(key)) === key || !hasOwn$1(rawProps, kebabKey))) {
         if (options) {
           if (rawPrevProps && // for camelCase
           (rawPrevProps[key] !== void 0 || // for kebab-case
@@ -5095,7 +5337,7 @@
     }
     if (attrs !== rawCurrentProps) {
       for (const key in attrs) {
-        if (!rawProps || !hasOwn(rawProps, key) && true) {
+        if (!rawProps || !hasOwn$1(rawProps, key) && true) {
           delete attrs[key];
           hasAttrsChanged = true;
         }
@@ -5120,7 +5362,7 @@
       }
       const value = rawProps[key];
       let camelKey;
-      if (options && hasOwn(options, camelKey = camelize(key))) {
+      if (options && hasOwn$1(options, camelKey = camelize(key))) {
         if (!needCastKeys || !needCastKeys.includes(camelKey)) {
           props[camelKey] = value;
         } else {
@@ -5145,7 +5387,7 @@
         key,
         castValues[key],
         instance,
-        !hasOwn(castValues, key)
+        !hasOwn$1(castValues, key)
       );
     }
   }
@@ -5154,7 +5396,7 @@
 function resolvePropValue(options, props, key, value, instance, isAbsent) {
   const opt = options[key];
   if (opt != null) {
-    const hasDefault = hasOwn(opt, "default");
+    const hasDefault = hasOwn$1(opt, "default");
     if (hasDefault && value === void 0) {
       const defaultValue = opt.default;
       if (opt.type !== Function && !opt.skipFactory && isFunction(defaultValue)) {
@@ -5218,7 +5460,7 @@
     }
   }
   if (!raw && !hasExtends) {
-    if (isObject(comp)) {
+    if (isObject$1(comp)) {
       cache.set(comp, EMPTY_ARR);
     }
     return EMPTY_ARR;
@@ -5234,7 +5476,7 @@
       }
     }
   } else if (raw) {
-    if (!isObject(raw)) {
+    if (!isObject$1(raw)) {
       warn$1(`invalid props options`, raw);
     }
     for (const key in raw) {
@@ -5253,7 +5495,7 @@
             1
             /* shouldCastTrue */
           ] = stringIndex < 0 || booleanIndex < stringIndex;
-          if (booleanIndex > -1 || hasOwn(prop, "default")) {
+          if (booleanIndex > -1 || hasOwn$1(prop, "default")) {
             needCastKeys.push(normalizedKey);
           }
         }
@@ -5261,7 +5503,7 @@
     }
   }
   const res = [normalized, needCastKeys];
-  if (isObject(comp)) {
+  if (isObject$1(comp)) {
     cache.set(comp, res);
   }
   return res;
@@ -5309,7 +5551,7 @@
       resolvedValues[key],
       opt,
       shallowReadonly(resolvedValues),
-      !hasOwn(rawProps, key) && !hasOwn(rawProps, hyphenate(key))
+      !hasOwn$1(rawProps, key) && !hasOwn$1(rawProps, hyphenate(key))
     );
   }
 }
@@ -5353,7 +5595,7 @@
       valid = value instanceof type;
     }
   } else if (expectedType === "Object") {
-    valid = isObject(value);
+    valid = isObject$1(value);
   } else if (expectedType === "Array") {
     valid = isArray(value);
   } else if (expectedType === "null") {
@@ -5657,7 +5899,7 @@
     {
       instance.render = setupResult;
     }
-  } else if (isObject(setupResult)) {
+  } else if (isObject$1(setupResult)) {
     if (isVNode(setupResult)) {
       warn$1(
         `setup() should not return VNodes directly - return a render function instead.`
@@ -6002,7 +6244,7 @@
       copy = {};
       seen.set(src, copy);
       for (const name in src) {
-        if (hasOwn(src, name)) {
+        if (hasOwn$1(src, name)) {
           copy[name] = clone(src[name], seen);
         }
       }
@@ -6122,7 +6364,7 @@
   }
 }
 function toSkip(value) {
-  if (isObject(value)) {
+  if (isObject$1(value)) {
     markRaw(value);
   }
   return value;
@@ -6163,7 +6405,7 @@
           onBeforeUnmount(() => remove(existing, refValue), refValue.$);
         }
       } else if (_isString) {
-        if (hasOwn(setupState, r2)) {
+        if (hasOwn$1(setupState, r2)) {
           setupState[r2] = refValue;
         }
       } else if (isRef(r2)) {
@@ -6744,14 +6986,14 @@
     event.preventDefault = NOOP;
     event.stopPropagation = NOOP;
     event.stopImmediatePropagation = NOOP;
-    if (!hasOwn(event, "detail")) {
+    if (!hasOwn$1(event, "detail")) {
       event.detail = {};
     }
-    if (hasOwn(event, "markerId")) {
+    if (hasOwn$1(event, "markerId")) {
       event.detail = typeof event.detail === "object" ? event.detail : {};
       event.detail.markerId = event.markerId;
     }
-    if (isPlainObject(event.detail) && hasOwn(event.detail, "checked") && !hasOwn(event.detail, "value")) {
+    if (isPlainObject(event.detail) && hasOwn$1(event.detail, "checked") && !hasOwn$1(event.detail, "value")) {
       event.detail.value = event.detail.checked;
     }
     if (isPlainObject(event.detail)) {
@@ -6787,7 +7029,7 @@
     for (let i2 = 0; i2 < source; i2++) {
       ret[i2] = renderItem(i2 + 1, i2, i2);
     }
-  } else if (isObject(source)) {
+  } else if (isObject$1(source)) {
     if (source[Symbol.iterator]) {
       ret = Array.from(source, (item, i2) => renderItem(item, i2, i2));
     } else {
@@ -6897,7 +7139,7 @@
 function initMocks(instance, mpInstance, mocks2) {
   const ctx = instance.ctx;
   mocks2.forEach((mock) => {
-    if (hasOwn(mpInstance, mock)) {
+    if (hasOwn$1(mpInstance, mock)) {
       instance[mock] = ctx[mock] = mpInstance[mock];
     }
   });
@@ -6953,7 +7195,7 @@
   return hooks;
 }
 function initHook(mpOptions, hook, excludes) {
-  if (excludes.indexOf(hook) === -1 && !hasOwn(mpOptions, hook)) {
+  if (excludes.indexOf(hook) === -1 && !hasOwn$1(mpOptions, hook)) {
     mpOptions[hook] = function(args) {
       return this.$vm && this.$vm.$callHook(hook, args);
     };
@@ -6986,7 +7228,7 @@
       const hooks = Object.keys(MINI_PROGRAM_PAGE_RUNTIME_HOOKS);
       mixins.forEach((mixin) => {
         hooks.forEach((hook) => {
-          if (hasOwn(mixin, hook) && !runtimeHooks.includes(hook)) {
+          if (hasOwn$1(mixin, hook) && !runtimeHooks.includes(hook)) {
             runtimeHooks.push(hook);
           }
         });
@@ -7063,13 +7305,13 @@
     const globalData = app.globalData;
     if (globalData) {
       Object.keys(appOptions.globalData).forEach((name) => {
-        if (!hasOwn(globalData, name)) {
+        if (!hasOwn$1(globalData, name)) {
           globalData[name] = appOptions.globalData[name];
         }
       });
     }
     Object.keys(appOptions).forEach((name) => {
-      if (!hasOwn(app, name)) {
+      if (!hasOwn$1(app, name)) {
         app[name] = appOptions[name];
       }
     });
@@ -7119,7 +7361,7 @@
 const EXTRAS = ["externalClasses"];
 function initExtraOptions(miniProgramComponentOptions, vueOptions) {
   EXTRAS.forEach((name) => {
-    if (hasOwn(vueOptions, name)) {
+    if (hasOwn$1(vueOptions, name)) {
       miniProgramComponentOptions[name] = vueOptions[name];
     }
   });
@@ -7426,7 +7668,7 @@
   componentOptions.data = initData();
   componentOptions.behaviors = initBehaviors(vueOptions);
 }
-function parseComponent(vueOptions, { parse, mocks: mocks2, isPage: isPage2, initRelation: initRelation2, handleLink: handleLink2, initLifetimes: initLifetimes2 }) {
+function parseComponent(vueOptions, { parse: parse2, mocks: mocks2, isPage: isPage2, initRelation: initRelation2, handleLink: handleLink2, initLifetimes: initLifetimes2 }) {
   vueOptions = vueOptions.default || vueOptions;
   const options = {
     multipleSlots: true,
@@ -7436,7 +7678,7 @@
   };
   if (isArray(vueOptions.mixins)) {
     vueOptions.mixins.forEach((item) => {
-      if (isObject(item.options)) {
+      if (isObject$1(item.options)) {
         extend(options, item.options);
       }
     });
@@ -7472,8 +7714,8 @@
   {
     initWorkletMethods(mpComponentOptions.methods, vueOptions.methods);
   }
-  if (parse) {
-    parse(mpComponentOptions, { handleLink: handleLink2 });
+  if (parse2) {
+    parse2(mpComponentOptions, { handleLink: handleLink2 });
   }
   return mpComponentOptions;
 }
@@ -7501,7 +7743,7 @@
   return $destroyComponentFn(instance);
 }
 function parsePage(vueOptions, parseOptions2) {
-  const { parse, mocks: mocks2, isPage: isPage2, initRelation: initRelation2, handleLink: handleLink2, initLifetimes: initLifetimes2 } = parseOptions2;
+  const { parse: parse2, mocks: mocks2, isPage: isPage2, initRelation: initRelation2, handleLink: handleLink2, initLifetimes: initLifetimes2 } = parseOptions2;
   const miniProgramPageOptions = parseComponent(vueOptions, {
     mocks: mocks2,
     isPage: isPage2,
@@ -7524,7 +7766,7 @@
   }
   initRuntimeHooks(methods, vueOptions.__runtimeHooks);
   initMixinRuntimeHooks(methods);
-  parse && parse(miniProgramPageOptions, { handleLink: handleLink2 });
+  parse2 && parse2(miniProgramPageOptions, { handleLink: handleLink2 });
   return miniProgramPageOptions;
 }
 function initCreatePage(parseOptions2) {
@@ -10626,6 +10868,7 @@
 exports.f = f$1;
 exports.getCurrentInstance = getCurrentInstance;
 exports.index = index;
+exports.initVueI18n = initVueI18n;
 exports.n = n$1;
 exports.o = o$1;
 exports.onHide = onHide;

--
Gitblit v1.9.3