Files
2021-04-18 15:28:14 +08:00

1073 lines
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Vue from 'vue'
// import MpvueRouterPatch from 'mpvue-router-patch'
// Vue.use(MpvueRouterPatch)
import { wxappAuth, getUserInfo } from '@/api/user'
import store from '@/store'
import dayjs from 'dayjs'
import cookie from '@/utils/store/cookie'
import stringify from '@/utils/querystring'
import { VUE_APP_API_URL } from '@/config'
import { wechat, auth, oAuth, toAuth } from '@/libs/wechat'
export function dataFormat(time, option) {
time = +time * 1000
const d = new Date(time)
const now = new Date().getTime()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
// return parseTime(time, option);
} else {
let timeStr = d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
return timeStr
}
}
// 年月日,时分秒
// "YYYY-mm-dd HH:MM"
export function dateFormatL(fmt, date) {
let ret
const opt = {
'Y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月
'd+': date.getDate().toString(), // 日
'H+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
'S+': date.getSeconds().toString(), // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
}
for (let k in opt) {
ret = new RegExp('(' + k + ')').exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'))
}
}
return fmt
}
export function dateFormatT(time) {
time = +time * 1000
const d = new Date(time)
return d.getFullYear() + '/' + (d.getMonth() + parseInt(1)) + '/' + d.getDate()
}
export function trim(str) {
return String.prototype.trim.call(str)
}
export function isType(arg, type) {
return Object.prototype.toString.call(arg) === '[object ' + type + ']'
}
export function isWeixin() {
if (navigator && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1) {
return true
}
return false
}
export function parseQuery() {
let res = {}
// #ifdef H5
const query = (location.href.split('?')[1] || '').trim().replace(/^(\?|#|&)/, '')
if (!query) {
return res
}
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=')
const key = decodeURIComponent(parts.shift())
const val = parts.length > 0 ? decodeURIComponent(parts.join('=')) : null
if (res[key] === undefined) {
res[key] = val
} else if (Array.isArray(res[key])) {
res[key].push(val)
} else {
res[key] = [res[key], val]
}
})
// #endif
// #ifndef H5
var pages = getCurrentPages() //获取加载的页面
var currentPage = pages[pages.length - 1] //获取当前页面的对象
var url = currentPage.route //当前页面url
res = currentPage.options //如果要获取url中所带的参数可以查看options
// #endif
return res
}
/*获取当前页url*/
export function getCurrentPageUrl() {
var pages = getCurrentPages() //获取加载的页面
var currentPage = pages[pages.length - 1] //获取当前页面的对象
var url = currentPage.route //当前页面url
return url
}
/*获取当前页带参数的url*/
export function getCurrentPageUrlWithArgs() {
var pages = getCurrentPages() //获取加载的页面
var currentPage = pages[pages.length - 1] //获取当前页面的对象
var url = currentPage.route //当前页面url
var options = currentPage.options //如果要获取url中所带的参数可以查看options
//拼接url的参数
var urlWithArgs = url + '?'
for (var key in options) {
var value = options[key]
urlWithArgs += key + '=' + value + '&'
}
urlWithArgs = urlWithArgs.substring(0, urlWithArgs.length - 1)
return urlWithArgs
}
// 复制到剪切板
export const copyClipboard = data => {
uni.setClipboardData({
data: data,
success: res => {
uni.showToast({
title: '复制成功',
icon: 'success',
duration: 2000,
})
},
})
}
export const getProvider = service => {
return new Promise((resolve, reject) => {
// 获取当前环境的服务商
uni.getProvider({
service: service || 'oauth',
success: function(res) {
// 此处可以排除h5
if (res.provider) {
resolve(res.provider[0])
}
},
fail() {
reject('获取环境服务商失败')
},
})
}).catch(error => {
console.log(error)
})
}
export const authorize = authorizeStr => {
return new Promise((resolve, reject) => {
console.log('检验授权', `scope.${authorizeStr}`)
uni.getSetting({
success(res) {
console.log(res.authSetting)
if (res.authSetting[`scope.${authorizeStr}`]) {
resolve(true)
} else {
resolve(false)
}
},
fail() {
resolve(false)
},
})
})
}
export const login = loginInfo => {
return new Promise((resolve, reject) => {
if (Vue.prototype.$deviceType == 'weixin') {
// 微信授权登录
const { code } = parseQuery()
if (code) {
auth(code)
.then(() => {
let redirect = cookie.get('redirect').replace(/\ /g, '')
console.log(redirect)
if (redirect) {
redirect = redirect.split('/pages')[1]
if (!redirect) {
redirect = '/Loading/index'
}
reLaunch({
path: '/pages' + redirect,
})
cookie.remove('redirect')
} else {
reLaunch({
path: '/pages/home/index',
})
}
})
.catch(() => {
reject('当前运行环境为微信浏览器')
reLaunch({
path: '/pages/home/index',
})
})
} else {
}
return
}
if (Vue.prototype.$deviceType == 'weixinh5') {
console.log('当前运行环境为H5')
reject('当前运行环境为H5')
return
}
if (Vue.prototype.$deviceType == 'app') {
console.log('当前运行环境为app')
reject('当前运行环境为app')
return
}
console.log('————————————————————')
console.log('开始登录')
console.log('————————————————————')
console.log('获取环境商')
getProvider()
.then(provider => {
console.log('当前的环境商')
console.log(provider)
if (!provider) {
reject()
}
// 调用登录接口
console.log('调用登录接口')
uni.login({
provider: provider,
success: async function(loginRes) {
console.log(loginRes)
// 微信登录
console.log('登录接口调用成功')
console.log('开始检查用户信息授权')
let code = loginRes.code
cookie.set('wxLoginCode', loginRes.code)
let authorizeRes = await authorize('userInfo')
if (!wx.getUserProfile && !authorizeRes) {
reject('用户未授权')
return
}
if (wx.getUserProfile) {
if (loginInfo) {
wxappAuth({
encryptedData: loginInfo.encryptedData,
iv: loginInfo.iv,
code: code,
spread: cookie.get('spread'),
})
.then(({ data }) => {
console.log('登录接口调用成功')
console.log('开始处理登录信息保存,并获取用户详情')
uni.hideLoading()
store.commit('login', data.token, dayjs(data.expires_time))
store.dispatch('userInfo', true)
getUserInfo()
.then(user => {
console.log('获取用户信息成功')
uni.setStorageSync('uid', user.data.uid)
store.dispatch('setUserInfo', user.data)
resolve(user)
})
.catch(error => {
console.log('获取用户信息失败')
reject('获取用户信息失败')
})
})
.catch(error => {
console.log(error)
console.log('登录接口调用失败')
reject('登录接口调用失败')
})
} else {
reject('用户未授权')
return
}
} else {
uni.getUserInfo({
provider: provider,
success: function(user) {
console.log(user)
console.log('获取用户信息成功')
console.log('开始调用登录接口')
wxappAuth({
encryptedData: user.encryptedData,
iv: user.iv,
code: code,
spread: cookie.get('spread'),
})
.then(({ data }) => {
console.log('登录接口调用成功')
console.log('开始处理登录信息保存,并获取用户详情')
uni.hideLoading()
store.commit('login', data.token, dayjs(data.expires_time))
store.dispatch('userInfo', true)
getUserInfo()
.then(user => {
console.log('获取用户信息成功')
uni.setStorageSync('uid', user.data.uid)
store.dispatch('setUserInfo', user.data)
resolve(user)
})
.catch(error => {
console.log('获取用户信息失败')
reject('获取用户信息失败')
})
})
.catch(error => {
console.log(error)
console.log('登录接口调用失败')
reject('登录接口调用失败')
})
},
fail() {
console.log('获取用户信息失败')
reject('获取用户信息失败')
},
})
}
},
fail() {
console.log('调用登录接口失败')
reject('调用登录接口失败')
},
})
})
.catch(error => {
reject('获取环境服务商失败')
})
})
}
export const handleGetUserInfo = () => {
getUserInfo().then(res => {
console.log('获取用户信息')
store.dispatch('setUserInfo', res.data)
console.log('获取用户信息后跳转回显的页面')
let redirect = cookie.get('redirect').replace(/\ /g, '')
if (redirect) {
reLaunch({
path: redirect,
// query
})
return
}
back()
// reLaunch({
// path: '/pages/home/index',
// // query
// })
// var pages = getCurrentPages() //获取加载的页面
// var currentPage = pages[pages.length - 1] //获取当前页面的对象
// let url = "/pages/home/index"
// let query = {}
// if (currentPage) {
// const {
// redirect,
// ...querys
// } = currentPage.options
// // 获取到最后一个页面
// if (
// currentPage.route != 'pages/Loading/index' &&
// currentPage.route != 'pages/user/Login/index'
// ) {
// url = currentPage.route
// query = {
// ...querys
// }
// }
// if (currentPage.route == 'pages/authorization/index') {
// url = redirect
// query = {
// ...querys
// }
// }
// }
// console.log(url)
// if (url == '/pages/home/index' || url == '/pages/shop/GoodsClass/index' || url == '/pages/shop/ShoppingCart/index' || url == '/pages/user/User/index') {
// switchTab({
// path: `${url}`,
// query
// });
// } else {
// let redirect = cookie.get('redirect')
// if (redirect) {
// reLaunch({
// path: redirect,
// // query
// });
// return
// }
// console.log('获取用户信息后跳转回显的页面')
// // 为了防止返回上一页是授权页面,先重定向到首页,再跳转
// console.log({
// path: `/${url}`,
// query
// })
// reLaunch({
// path: '/pages/home/index',
// // query
// });
// setTimeout(() => {
// if (url.indexOf('/') == 0) {
// url = url.slice(1)
// }
// push({
// path: `/${url}`,
// query
// })
// })
// // push({
// // path: `${url}`,
// // query
// // })
// }
})
}
export function parseUrl(location) {
if (typeof location === 'string') return location
const { path, query } = location
const queryStr = stringify(query)
if (!queryStr) {
return path
}
return `${path}?${queryStr}`
}
export function parseRoute($mp) {
const _$mp = $mp || {}
const path = _$mp.page && _$mp.page.route
return {
path: `/${path}`,
params: {},
query: _$mp.query || _$mp.page.options,
hash: '',
fullPath: parseUrl({
path: `/${path}`,
query: _$mp.query || _$mp.page.options,
}),
name: path && path.replace(/\/(\w)/g, ($0, $1) => $1.toUpperCase()),
}
}
export function handleAuth() {
/**
* 如何判断权限?
* 用户如果登录了系统会留下两个东西一个是token一个是userInfo
* token存在会过期的问题如果长时间没有打开小程序会导致登录失效出现打开一个页面瞬间跳转到授权页面的问题
* 解决办法保存token的时候加上过期时间每次请求都取一下缓存里的token
* userInfo只是用来限时用户信息作用并不是很大
* ps只需要判断 token 是否存在即可
*/
if (cookie.get('login_status')) {
return true
}
return false
}
export const handleLoginStatus = (location, complete, fail, success) => {
// 不登录可访问的页面
let page = [
{
path: '/pages/Loading/index',
name: 'loading页面',
},
{
path: '/pages/home/index',
name: '首页',
},
{
path: '/pages/shop/HotNewGoods/index',
name: '热门榜单',
},
{
path: '/pages/activity/GoodsGroup/index',
name: '超值拼团',
},
{
path: '/pages/shop/Live/LiveList/index',
name: '热门直播',
},
{
path: '/pages/shop/GoodsClass/index',
name: '商品分类',
},
{
path: '/pages/user/Login/index',
name: '登录页面',
},
{
path: '/pages/authorization/index',
name: '授权页面',
},
]
// 是否可以访问
let isAuth = false
console.log('即将跳转', location, parseUrl(location))
// 从 location 中获取当前urllocation typeof string || object
let path = ''
if (typeof location === 'string') {
path = location
} else {
path = location.path
}
console.log(path)
// 判断用户是否有token
if (!handleAuth()) {
page.map(item => {
if (item.path == path) {
isAuth = true
}
})
} else {
isAuth = true
}
console.log(isAuth)
return new Promise((resolve, reject) => {
if (isAuth) {
// 有token
if (path == '/pages/home/index' || path == '/pages/shop/GoodsClass/index' || path == '/pages/shop/ShoppingCart/index' || path == '/pages/user/User/index') {
// switchTab({
// path: parseUrl(location),
// })
// return
}
resolve({
url: parseUrl(location),
complete,
fail,
success,
})
} else {
// 没有token先校验用户是否授权如果授权了进行自动登录
routerPermissions(parseUrl(location))
reject()
}
}).catch(error => {
console.log(error)
})
}
// export function checkPermissions(){
// }
export function routerPermissions(url, type) {
console.log('routerPermissions', url)
console.log('————————')
console.log(url, type, 'routerPermissions')
console.log('————————')
let path = url
if (!path) {
path = '/' + getCurrentPageUrlWithArgs()
}
console.log(Vue.prototype.$deviceType)
if (Vue.prototype.$deviceType == 'routine') {
console.log('————————')
console.log('当前是微信小程序,开始处理小程序登录方法')
console.log('————————')
// 如果是微信小程序,跳转到授权页
// 先校验用户是否授权,如果授权了,进行自动登录
console.log('————————')
console.log('开始校验权限')
console.log('————————')
authorize('userInfo')
.then(() => {
// 自动登录
console.log('————————')
console.log('自动登录')
console.log('————————')
login()
.then(res => {
// 登录成功,跳转到需要跳转的页面
console.log('————————')
console.log('登录成功,跳转页面')
console.log('————————')
store.commit('updateAuthorizationPage', false)
if (path == '/pages/shop/ShoppingCart/index' || path == '/pages/user/User/index') {
console.log('————————')
console.log('当前是购物车,或者个人中心')
console.log('————————')
return
}
if (type == 'reLaunch') {
reLaunch({
path,
})
return
}
if (type == 'replace') {
replace({
path,
})
return
}
push({
path,
})
})
.catch(error => {
console.log('————————')
console.log('自动登录失败,跳转到授权页面')
console.log('————————')
uni.showToast({
title: error,
icon: 'none',
duration: 2000,
})
reLaunch({
path: '/pages/authorization/index',
})
cookie.set('redirect', path)
})
})
.catch(error => {
// 跳转到登录页面或者授权页面
if (path == '/pages/shop/ShoppingCart/index' || path == '/pages/user/User/index') {
switchTab({
path,
})
store.commit('updateAuthorizationPage', false)
return
}
reLaunch({
path: '/pages/authorization/index',
})
cookie.set('redirect', path)
})
} else if (Vue.prototype.$deviceType == 'weixin') {
wechat().then(() => oAuth())
if (!type) {
push({
path: url,
})
}
} else {
console.log(path)
// 如果不是小程序跳转到登录页
cookie.set('redirect', path)
push({
path: '/pages/user/Login/index',
})
}
}
export function push(location, complete, fail, success) {
handleLoginStatus(location, complete, fail, success)
.then(params => {
uni.navigateTo(params)
})
.catch(error => {
// 没有权限
})
}
export function replace(location, complete, fail, success) {
handleLoginStatus(location, complete, fail, success)
.then(params => {
console.log(params)
uni.redirectTo(params)
})
.catch(error => {
// 没有权限
})
}
export function reLaunch(location, complete, fail, success) {
handleLoginStatus(location, complete, fail, success)
.then(params => {
console.log(params)
uni.reLaunch(params)
})
.catch(error => {
// 没有权限
console.log(error)
})
}
export function go(delta) {
uni.navigateBack({
delta,
})
}
export function back() {
uni.navigateBack({
delta: 1,
success: function(e) {},
fail: function(e) {},
})
}
export function switchTab(location, complete, fail, success) {
handleLoginStatus(location, complete, fail, success)
.then(params => {
uni.switchTab(params)
})
.catch(error => {
// 没有权限
})
}
export const _router = {
mode: 'history',
switchTab,
push,
replace,
go,
back,
reLaunch,
}
export function handleQrCode() {
var urlSpread = parseQuery()['q']
if (urlSpread) {
if (urlSpread.indexOf('%3F') != -1) {
// 通过海报二维码进来
urlSpread = urlSpread
.split('%3F')[1]
.replace(/%3D/g, ':')
.replace(/%26/g, ',')
.split(',')
.map((item, index) => {
item = item.split(':')
return `"${item[0]}":"${item[1]}"`
})
.join(',')
urlSpread = JSON.parse('{' + urlSpread + '}')
return urlSpread
} else {
return handleUrlParam(urlSpread)
}
}
return null
}
export function handleUrlParam(path) {
var url = path.split('?')[1] //获取url中"?"符后的字串
var theRequest = new Object()
if (path.includes('?')) {
var url = path.split('?')[1] //获取url中"?"符后的字串
let strs = url.split('&')
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
}
}
return theRequest
}
const getImageInfo = images => {
return new Promise((resolve, reject) => {
let imageAry = {}
images.map((item, index) => {
uni.getImageInfo({
src: item,
fail: function(res) {
imageAry[index] = null
if (imageAry.length == images.length) {
resolve(imageAry)
}
},
success: function(res) {
imageAry[index] = res
if (Object.keys(imageAry).length == images.length) {
resolve(imageAry)
}
},
})
})
})
}
/**
* 获取分享海报
* @param array store 海报素材
* @param string store_name 素材文字
* @param string price 价格
* @param function successFn 回调函数
*
*
*/
export const PosterCanvas = (store, successCallBack) => {
uni.showLoading({
title: '海报生成中',
mask: true,
})
getImageInfo([store.image, store.code]).then(res => {
let contentHh = 48 * 1.3
const ctx = uni.createCanvasContext('myCanvas')
ctx.clearRect(0, 0, 0, 0)
const WIDTH = 747
const HEIGHT = 1326
ctx.fillStyle = '#FFFFFF'
ctx.fillRect(0, 0, WIDTH, HEIGHT)
ctx.drawImage(res[0].path, 0, 0, WIDTH, WIDTH)
ctx.drawImage(res[1].path, 40, 1064, 200, 200)
ctx.save()
let r = 90
let d = r * 2
let cx = 40
let cy = 990
ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI)
ctx.clip()
ctx.restore()
ctx.setTextAlign('center')
ctx.setFontSize(48)
ctx.setFillStyle('#000')
ctx.fillText(store.title, WIDTH / 2, 810 + contentHh)
ctx.setTextAlign('center')
ctx.setFontSize(32)
ctx.setFillStyle('red')
ctx.fillText('¥' + store.price, WIDTH / 2, 985)
ctx.setTextAlign('center')
ctx.setFontSize(22)
ctx.setFillStyle('#333333')
ctx.fillText('长按识别二维码立即购买', WIDTH / 2, 1167)
ctx.save()
ctx.draw(true, () => {
uni.canvasToTempFilePath({
canvasId: 'myCanvas',
fileType: 'png',
destWidth: WIDTH,
destHeight: HEIGHT,
success: function(res) {
uni.hideLoading()
successCallBack && successCallBack(res.tempFilePath)
},
fail: function(error) {
console.log(error)
},
})
})
})
// uni.getImageInfo({
// src: store.image,
// fail: function (res) {
// uni.showToast({
// title: '海报生成失败',
// icon: "none",
// duration: 2000
// });
// },
// success: function (res) {
// }
// })
}
export const handleLoginFailure = () => {
console.log('————————')
console.log('退出登录,标记当前页面为授权页面,防止多次跳转')
console.log('————————')
store.commit('logout')
// 改为授权取消
store.commit('updateAuthorization', false)
let currentPageUrl = getCurrentPageUrl()
if (store.state.$deviceType == 'weixin') {
// 如果不是授权页面,
if (!store.getters.isAuthorizationPage) {
// 标识当前为授权页面
store.commit('updateAuthorizationPage', true)
toAuth()
}
return
} else {
// token 失效
// 判断当前是不是已经在登录页面或者授权页,防止二次跳转
if (store.getters.isAuthorizationPage || currentPageUrl == '/pages/user/Login/index') {
console.log(store.getters.isAuthorizationPage, currentPageUrl, '已经是登录页面或者授权页面,跳出方法')
return
}
}
console.log('————————')
console.log('当前是授权页面')
console.log(store.getters)
console.log('————————')
store.commit('updateAuthorizationPage', true)
let path = '/' + getCurrentPageUrlWithArgs()
let qrCode = handleQrCode()
if (qrCode) {
// 当前是通过海报扫描进入的
// 判断是不是拼团进来的
if (currentPageUrl == 'pages/activity/GroupRule/index') {
console.log('————————')
console.log('是拼团进来的')
console.log('————————')
if (qrCode.pinkId) {
path = parseUrl({
path: `/ ${currentPageUrl} `,
query: {
id: qrCode.pinkId,
},
})
if (qrCode.spread) {
cookie.set('spread', qrCode.spread || 0)
}
} else {
console.log('————————')
console.log('是拼团进来的,但是没有获取到参数')
console.log('————————')
handleNoParameters()
}
}
// 判断是不是扫描的砍价海报进来的
if (currentPageUrl == 'pages/activity/DargainDetails/index') {
console.log('————————')
console.log('是扫描的砍价海报进来的')
console.log('————————')
if (qrCode.bargainId) {
path = parseUrl({
path: `/ ${currentPageUrl} `,
query: {
id: qrCode.bargainId,
partake: qrCode.uid,
},
})
if (qrCode.spread) {
cookie.set('spread', qrCode.spread || 0)
}
} else {
handleNoParameters()
console.log('————————')
console.log('是扫描的砍价海报进来的,但是没有获取到参数')
console.log('————————')
}
}
if (currentPageUrl == 'pages/shop/GoodsCon/index') {
console.log('————————')
console.log('是扫描的商品详情')
console.log('————————')
if (qrCode.productId) {
path = parseUrl({
path: `/ ${currentPageUrl} `,
query: {
id: qrCode.productId,
},
})
if (qrCode.spread) {
cookie.set('spread', qrCode.spread || 0)
}
} else {
handleNoParameters()
console.log('————————')
console.log('是扫描的商品详情进来的,但是没有获取到参数')
console.log('————————')
}
}
}
console.log('————————')
console.log(path, '重定向页面地址')
console.log('————————')
routerPermissions(path, 'reLaunch')
}
const handleNoParameters = () => {
uni.showToast({
title: '未获取到必要参数,即将跳转首页',
icon: 'success',
duration: 2000,
})
setTimeout(() => {
clearTimeout()
switchTab({
path: '/pages/home/index',
})
}, 1500)
}
export function chooseImage(callback) {
uni.chooseImage({
count: 1,
sourceType: ['album'],
success: res => {
uni.getImageInfo({
src: res.tempFilePaths[0],
success: image => {
console.log(image)
uni.showLoading({ title: '图片上传中', mask: true })
uni.uploadFile({
url: `${VUE_APP_API_URL}/api/upload`,
file: image,
filePath: image.path,
header: {
Authorization: 'Bearer ' + store.getters.token,
},
name: 'file',
success: res => {
if (callback) {
callback(JSON.parse(res.data).link)
}
},
fail: err => {
uni.showToast({
title: '上传图片失败',
icon: 'none',
duration: 2000,
})
},
complete: res => {
uni.hideLoading()
},
})
},
fail: err => {
uni.showToast({
title: '获取图片信息失败',
icon: 'none',
duration: 2000,
})
},
})
},
})
}
export function handleErrorMessage(err) {
console.log(err)
uni.hideLoading()
uni.showToast({
title: err.msg || err.response.data.msg || err.response.data.message || '创建订单失败',
icon: 'none',
duration: 2000,
})
}